4028 lines
108 KiB
C
4028 lines
108 KiB
C
#include "./include/sip_pub.h"
|
|
#include "./include/sip.h"
|
|
#include "./include/sip_const.h"
|
|
#include "./include/sip_struct.h"
|
|
#include "./include/sip_ext.h"
|
|
#include "./include/sip_msg.h"
|
|
#include "./include/sip_debug.h"
|
|
|
|
// Utility code start
|
|
|
|
char *sip_strncpy(char *dest, const char *src, WORD length)
|
|
{
|
|
if ((dest == NULL) || (src == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_strncpy: dest or src is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return NULL;
|
|
}
|
|
|
|
strncpy(dest, src, length);
|
|
dest[length] = '\0';
|
|
return dest;
|
|
}
|
|
|
|
// remove SPACE before and after the content
|
|
int sip_clrspace(char *word)
|
|
{
|
|
char *pbeg;
|
|
char *pend;
|
|
WORD len;
|
|
|
|
if (word == NULL)
|
|
return -1;
|
|
if (*word == '\0')
|
|
return 0;
|
|
len = strlen (word);
|
|
|
|
pbeg = word;
|
|
while ((' ' == *pbeg) || ('\r' == *pbeg) || ('\n' == *pbeg) || ('\t' == *pbeg))
|
|
pbeg++;
|
|
|
|
pend = word + len - 1;
|
|
while ((' ' == *pend) || ('\r' == *pend) || ('\n' == *pend) || ('\t' == *pend))
|
|
{
|
|
pend--;
|
|
if (pend < pbeg)
|
|
{
|
|
*word = '\0';
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Add terminating NULL only if we've cleared room for it
|
|
if (pend + 1 <= word + (len - 1))
|
|
pend[1] = '\0';
|
|
|
|
if (pbeg != word)
|
|
memcpy(word, pbeg, pend - pbeg + 2);
|
|
|
|
return 0;
|
|
}
|
|
|
|
char *sip_clrncpy(char *dst, char *src, WORD len)
|
|
{
|
|
char *pbeg;
|
|
char *pend;
|
|
char *p;
|
|
WORD spaceless_length;
|
|
|
|
if ((dst == NULL) || (src == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_clrncpy: dst or src is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return NULL;
|
|
}
|
|
|
|
// find the start of relevant text
|
|
pbeg = src;
|
|
while ((' ' == *pbeg) || ('\r' == *pbeg) || ('\n' == *pbeg) || ('\t' == *pbeg))
|
|
pbeg++;
|
|
|
|
// find the end of relevant text
|
|
pend = src + len - 1;
|
|
while ((' ' == *pend) || ('\r' == *pend) || ('\n' == *pend) || ('\t' == *pend))
|
|
{
|
|
pend--;
|
|
if (pend < pbeg)
|
|
{
|
|
*dst = '\0';
|
|
return dst;
|
|
}
|
|
}
|
|
|
|
// if pend == pbeg there is only one char to copy
|
|
spaceless_length = pend - pbeg + 1; // excluding any '\0'
|
|
memcpy(dst, pbeg, spaceless_length);
|
|
p = dst + spaceless_length;
|
|
|
|
// terminate the string and pad dest with zeros until len
|
|
do
|
|
{
|
|
*p = '\0';
|
|
p++;
|
|
spaceless_length++;
|
|
}
|
|
while (spaceless_length < len);
|
|
|
|
return dst;
|
|
}
|
|
|
|
int sip_set_next_token(char *dest, char *buf, int endSeparator, char **next)
|
|
{
|
|
char *sep; // separator
|
|
|
|
if ((dest == NULL) || (buf == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_set_next_token: dest or buf is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
*next = NULL;
|
|
|
|
sep = buf;
|
|
while ((*sep != endSeparator) && (*sep != '\0') && (*sep != '\r')
|
|
&& (*sep != '\n'))
|
|
sep++;
|
|
if ((*sep == '\r') || (*sep == '\n'))
|
|
{ // we should continue normally only if this is the separator asked!
|
|
if (*sep != endSeparator)
|
|
return -1;
|
|
}
|
|
if (*sep == '\0')
|
|
return -1; // value must not end with this separator!
|
|
if (sep == buf)
|
|
return -1; // empty value (or several space!)
|
|
|
|
sip_strncpy(dest, buf, sep - buf);
|
|
|
|
*next = sep + 1; // return the position right after the separator
|
|
|
|
return 0;
|
|
}
|
|
|
|
void sip_util_replace_all_lws(char *msg)
|
|
{
|
|
char *tmp;
|
|
|
|
if (msg == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_util_replace_all_lws: msg is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return;
|
|
}
|
|
|
|
tmp = msg;
|
|
|
|
for (; tmp[0] != '\0'; tmp++)
|
|
{
|
|
if (('\0' == tmp[0]) || ('\0' == tmp[1]) ||
|
|
('\0' == tmp[2]) || ('\0' == tmp[3]))
|
|
return;
|
|
|
|
if ((('\r' == tmp[0]) && ('\n' == tmp[1]) &&
|
|
('\r' == tmp[2]) && ('\n' == tmp[3])) ||
|
|
(('\r' == tmp[0]) && ('\r' == tmp[1])) ||
|
|
(('\n' == tmp[0]) && ('\n' == tmp[1])))
|
|
return;
|
|
|
|
if ((('\r' == tmp[0]) && ('\n' == tmp[1]) &&
|
|
((' ' == tmp[2]) || ('\t' == tmp[2]))) ||
|
|
(('\r' == tmp[0]) &&
|
|
((' ' == tmp[1]) || ('\t' == tmp[1]))) ||
|
|
(('\n' == tmp[0]) &&
|
|
((' ' == tmp[1]) || ('\t' == tmp[1]))))
|
|
{
|
|
// Replace line end and TAB symbols by SP
|
|
tmp[0] = ' ';
|
|
tmp[1] = ' ';
|
|
tmp = tmp + 2;
|
|
// Replace all following TAB symbols
|
|
for (; ('\t' == tmp[0] || ' ' == tmp[0]); )
|
|
{
|
|
tmp[0] = ' ';
|
|
tmp++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// this method search for the separator and
|
|
// return it only if it is located before the
|
|
// second separator
|
|
char *sip_next_separator(char *ch, int separatorToFind, int beforeSeparator)
|
|
{
|
|
char *ind;
|
|
char *tmp;
|
|
|
|
if (ch == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_next_separator: ch is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return NULL;
|
|
}
|
|
|
|
ind = strchr (ch, separatorToFind);
|
|
if (ind == NULL)
|
|
return NULL;
|
|
|
|
tmp = NULL;
|
|
if (beforeSeparator != 0)
|
|
tmp = strchr(ch, beforeSeparator);
|
|
|
|
if (tmp != NULL)
|
|
{
|
|
if (ind < tmp)
|
|
return ind;
|
|
}
|
|
else
|
|
return ind;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void sip_uri_unescape(char *string)
|
|
{
|
|
int alloc = strlen (string) + 1;
|
|
unsigned char in;
|
|
int index = 0;
|
|
unsigned int hex;
|
|
char *ptr;
|
|
|
|
if (string == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_uri_unescape: string is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return;
|
|
}
|
|
|
|
ptr = string;
|
|
while (--alloc > 0)
|
|
{
|
|
in = *ptr;
|
|
if ('%' == in)
|
|
{
|
|
// encoded part
|
|
if (sscanf (ptr + 1, "%02X", &hex) == 1)
|
|
{
|
|
in = (unsigned char) hex;
|
|
if (*(ptr + 2) &&
|
|
((*(ptr + 2) >= '0' && *(ptr + 2) <= '9') ||
|
|
(*(ptr + 2) >= 'a' && *(ptr + 2) <= 'f') ||
|
|
(*(ptr + 2) >= 'A' && *(ptr + 2) <= 'F')))
|
|
{
|
|
alloc -= 2;
|
|
ptr += 2;
|
|
}
|
|
else
|
|
{
|
|
alloc -= 1;
|
|
ptr += 1;
|
|
}
|
|
}
|
|
}
|
|
string[index++] = in;
|
|
ptr++;
|
|
}
|
|
string[index] = 0; // terminate it
|
|
}
|
|
|
|
// in quoted-string, many characters can be escaped...
|
|
// sip_quote_find returns the next quote that is not escaped
|
|
char *sip_quote_find(char *qstring)
|
|
{
|
|
char *quote;
|
|
int i = 1;
|
|
|
|
if (qstring == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_quote_find: qstring is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return NULL;
|
|
}
|
|
|
|
quote = strchr(qstring, '"');
|
|
if (quote == qstring) // the first char matches and is not escaped...
|
|
return quote;
|
|
|
|
if (quote == NULL)
|
|
return NULL; // no quote at all...
|
|
|
|
/* this is now the nasty cases where '"' is escaped
|
|
'" jonathan ros \\\""'
|
|
| |
|
|
'" jonathan ros \\"'
|
|
| |
|
|
'" jonathan ros \""'
|
|
| |
|
|
we must count the number of preceeding '\' */
|
|
|
|
for (;;)
|
|
{
|
|
if (0 == strncmp(quote - i, "\\", 1))
|
|
i++;
|
|
else
|
|
{
|
|
if (i % 2 == 1) // the '"' was not escaped
|
|
return quote;
|
|
|
|
// else continue with the next '"'
|
|
quote = strchr (quote + 1, '"');
|
|
if (quote == NULL)
|
|
return NULL;
|
|
i = 1;
|
|
}
|
|
if (quote - i == qstring - 1)
|
|
// example: "\"john"
|
|
// example: "\\"jack"
|
|
{
|
|
// special case where the string start with '\'
|
|
if (*qstring == '\\')
|
|
i++; // an escape char was not counted
|
|
if (i % 2 == 0) // the '"' was not escaped
|
|
return quote;
|
|
else
|
|
{ // else continue with the next '"'
|
|
qstring = quote + 1; // reset qstring because
|
|
// (*quote+1) may be also == to '\\'
|
|
quote = strchr(quote + 1, '"');
|
|
if (quote == NULL)
|
|
return NULL;
|
|
i = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int sip_uri_param_set(SIP_GEN_PARA *urlParam, char *pname, char *pvalue)
|
|
{
|
|
BYTE flag = 0;
|
|
|
|
if ((urlParam == NULL) || (pname == NULL) || (pvalue == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_uri_param_set: urlParm pname or pvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrspace(pname);
|
|
sip_clrspace(pvalue);
|
|
|
|
if (strcmp(pname, SIP_PNAME_TAG) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_TAG;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_STRING;
|
|
}
|
|
else if (strcmp(pname, SIP_PNAME_BRANCH) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_BRANCH;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_STRING;
|
|
}
|
|
else if (strcmp(pname, SIP_PNAME_EXPIRES) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_EXPIRES;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_VALUE;
|
|
urlParam->para.paraVal[0] = atol(pvalue);
|
|
}
|
|
else if (strcasecmp(pname, SIP_PNAME_USER) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_USER;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_STRING;
|
|
}
|
|
else if (strcmp(pname, SIP_PNAME_LR) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_LR;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_TAG;
|
|
}
|
|
else if (strcmp(pname, SIP_PNAME_BOUNDARY) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_BOUNDARY;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_STRING;
|
|
}
|
|
else if (strcmp(pname, SIP_PNAME_HANDLING) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_HANDLING;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_STRING;
|
|
}
|
|
else if (strcmp(pname, SIP_PNAME_TRANSPORT) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_TRANSPORT;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_STRING;
|
|
}
|
|
else if (strcmp(pname, SIP_PNAME_RPORT) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_RPOTR;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_VALUE;
|
|
if (pvalue[0] == '\0')
|
|
urlParam->para.paraVal[0] = 0xFFFFFFFF;
|
|
else
|
|
urlParam->para.paraVal[0] = atol(pvalue);
|
|
}
|
|
else if (strcmp(pname, SIP_PNAME_VERSION) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_VERSION;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_STRING;
|
|
}
|
|
else if (strcmp(pname, SIP_PNAME_BASE) == 0)
|
|
{
|
|
urlParam->paraName = SIP_API_PNAME_BASE;
|
|
urlParam->paraType = flag = SIP_API_PTYPE_STRING;
|
|
}
|
|
|
|
if (flag)
|
|
{
|
|
if (flag == SIP_API_PTYPE_STRING)
|
|
strcpy(urlParam->para.paraStr, pvalue);
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int sip_uri_param_add(SIP_GEN_PARAMS *urlParams, char *pname, char *pvalue)
|
|
{
|
|
SIP_GEN_PARA *urlParam;
|
|
|
|
if ((urlParams == NULL) || (pname == NULL) || (pvalue == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_uri_param_add: urlParms pname or pvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (urlParams->paraNum > SIP_MAX_PARA_NUM)
|
|
return -1;
|
|
|
|
urlParam = &urlParams->para[urlParams->paraNum];
|
|
|
|
if (sip_uri_param_set(urlParam, pname, pvalue) < 0)
|
|
return -1;
|
|
|
|
urlParams->paraNum++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_uri_parse_params(SIP_URI *sipUri, char *params)
|
|
{
|
|
char pname[64];
|
|
char pvalue[128];
|
|
|
|
char *comma;
|
|
char *equal;
|
|
|
|
if ((sipUri == NULL) || (params == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_uri_parse_params: sipUri or params is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
// find '=' which is the separator for one param
|
|
// find ';' which is the separator for multiple params
|
|
|
|
equal = sip_next_separator(params + 1, '=', ';');
|
|
comma = strchr(params + 1, ';');
|
|
|
|
while (comma != NULL)
|
|
{
|
|
if (equal == NULL)
|
|
{
|
|
equal = comma;
|
|
pvalue[0] = '\0';
|
|
}
|
|
else
|
|
{
|
|
if ((comma - equal < 2) || (comma - equal > 128))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "uri param value length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_strncpy(pvalue, equal + 1, comma - equal - 1);
|
|
sip_uri_unescape(pvalue);
|
|
}
|
|
|
|
if ((equal - params < 2) || (equal - params > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "uri param name length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_strncpy(pname, params + 1, equal - params - 1);
|
|
sip_uri_unescape(pname);
|
|
|
|
sip_uri_uparam_add(sipUri, pname, pvalue);
|
|
|
|
params = comma;
|
|
equal = sip_next_separator(params + 1, '=', ';');
|
|
comma = strchr(params + 1, ';');
|
|
}
|
|
|
|
// this is the last header (comma==NULL)
|
|
comma = params + strlen (params);
|
|
|
|
if (equal == NULL)
|
|
{
|
|
equal = comma; /* at the end */
|
|
pvalue[0] = '\0';
|
|
}
|
|
else
|
|
{
|
|
if ((comma - equal < 2) || (comma - equal > 128))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "uri last param value length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_strncpy(pvalue, equal + 1, comma - equal - 1);
|
|
}
|
|
|
|
if ((equal - params < 2) || (equal - params > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "uri last param name length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_strncpy(pname, params + 1, equal - params - 1);
|
|
|
|
sip_uri_uparam_add(sipUri, pname, pvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_generic_param_parseall(SIP_GEN_PARAMS *genParams, char *params)
|
|
{
|
|
char pname[32];
|
|
char pvalue[64];
|
|
char *comma;
|
|
char *equal;
|
|
char *tmp;
|
|
|
|
if ((genParams == NULL) || (params == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_generic_param_parseall: genParams or params is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
// find '=' which is the separator for one param
|
|
// find ';' which is the separator for multiple params
|
|
|
|
equal = sip_next_separator(params + 1, '=', ';');
|
|
comma = strchr(params + 1, ';');
|
|
|
|
while (comma != NULL)
|
|
{
|
|
if (equal == NULL)
|
|
{
|
|
equal = comma;
|
|
pvalue[0] = '\0';
|
|
}
|
|
else
|
|
{
|
|
// check for NULL param with an '=' character
|
|
tmp = equal + 1;
|
|
|
|
for (; *tmp == '\t' || *tmp == ' '; tmp++)
|
|
{
|
|
}
|
|
|
|
pvalue[0] = '\0';
|
|
|
|
if ((*tmp != ',') && (*tmp != '\0'))
|
|
{
|
|
if ((comma - equal < 2) || (comma - equal > 64))//comma - equal >128
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "param value length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(pvalue, equal + 1, comma - equal - 1);
|
|
}
|
|
}
|
|
|
|
if ((equal - params < 2) || (equal - params > 32))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "param name length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(pname, params + 1, equal - params - 1);
|
|
|
|
sip_generic_param_add(genParams, pname, pvalue);
|
|
|
|
params = comma;
|
|
|
|
equal = sip_next_separator(params + 1, '=', ';');
|
|
comma = strchr(params + 1, ';');
|
|
}
|
|
|
|
// this is the last header (comma==NULL)
|
|
comma = params + strlen (params);
|
|
|
|
if (equal == NULL)
|
|
{
|
|
equal = comma; /* at the end */
|
|
pvalue[0] = '\0';
|
|
}
|
|
else
|
|
{
|
|
// check for NULL param with an '=' character
|
|
tmp = equal + 1;
|
|
|
|
for (; *tmp == '\t' || *tmp == ' '; tmp++)
|
|
{
|
|
}
|
|
|
|
pvalue[0] = '\0';
|
|
|
|
if (*tmp != ',' && *tmp != '\0')
|
|
{
|
|
if ((comma - equal < 2) || (comma - equal > 64))//comma - equal >128
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "last param value length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(pvalue, equal + 1, comma - equal - 1);
|
|
}
|
|
}
|
|
|
|
if ((equal - params < 2) || (equal - params > 32))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "last param name length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(pname, params + 1, equal - params - 1);
|
|
|
|
sip_generic_param_add(genParams, pname, pvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Parse code start
|
|
|
|
int sip_uri_parse(SIP_URI *sipUri, char *buf)
|
|
{
|
|
char *userName;
|
|
char *password;
|
|
char *host;
|
|
char *port;
|
|
char *params;
|
|
char *headers;
|
|
char *tmp;
|
|
char temp[128];
|
|
BYTE len;
|
|
|
|
// basic tests
|
|
if ((sipUri == NULL) || (buf == NULL) || (buf[0] == '\0'))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_uri_parse: sipUri or buf is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
tmp = strchr(buf, ':');
|
|
if (tmp == NULL)
|
|
return -1;
|
|
|
|
len = tmp - buf;
|
|
|
|
if ((len < 2) || (len > 128))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "uri type length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(temp, buf, len);
|
|
if (sip_uri_type_api_conv(temp, &sipUri->uriType, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
/* law number 1:
|
|
if ('?' exists && is_located_after '@')
|
|
or if ('?' exists && '@' is not there -no userName-)
|
|
=====> HEADER_PARAM EXIST
|
|
=====> start at index(?)
|
|
=====> end at the end of url
|
|
*/
|
|
|
|
// find the beginning of host
|
|
userName = strchr(tmp, ':');//userName = strchr(buf, ':');
|
|
// if ':' does not exist, the url is not valid
|
|
if (userName == NULL)
|
|
return -1;
|
|
|
|
host = strchr(tmp, '@');//host = strchr(buf, '@');
|
|
|
|
if (host == NULL)
|
|
host = userName;
|
|
else if (userName[1] == '@') // userName is empty
|
|
host = userName + 1;
|
|
else
|
|
{ // userName exists
|
|
password = sip_next_separator(userName + 1, ':', '@');
|
|
|
|
if (password == NULL)
|
|
password = host;
|
|
else
|
|
{ // password exists
|
|
if ((host - password < 2) || (host - password > 16))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "password length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(sipUri->password, password + 1, host - password - 1);
|
|
sip_uri_unescape(sipUri->password);
|
|
}
|
|
|
|
if ((password - userName < 2) || (password - userName > 64))//password - userName > 128
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "uri userName length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(sipUri->userName, userName + 1, password - userName - 1);
|
|
sip_uri_unescape(sipUri->userName);
|
|
}
|
|
|
|
// search for header after host
|
|
headers = strchr (host, '?');
|
|
|
|
if (headers == NULL)
|
|
headers = buf + strlen(buf);
|
|
else
|
|
{
|
|
// headers exist
|
|
// sip_uri_parse_headers(url, headers);
|
|
}
|
|
|
|
// search for params after host
|
|
params = strchr(host, ';'); /* search for params after host */
|
|
if (params == NULL)
|
|
params = headers;
|
|
else
|
|
{ /* params exist */
|
|
if ((headers - params + 1 < 2) || (headers - params + 1 > 128))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "uri params length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(temp, params, headers - params);
|
|
sip_uri_parse_params(sipUri, temp);
|
|
}
|
|
|
|
port = params - 1;
|
|
while (port > host && *port != ']' && *port != ':')
|
|
port--;
|
|
if (*port == ':')
|
|
{
|
|
if (host == port)
|
|
port = params;
|
|
else
|
|
{
|
|
if ((params - port < 2) || (params - port > 8))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "port length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1; // error cases
|
|
}
|
|
sip_clrncpy(temp, port + 1, params - port - 1);
|
|
sipUri->port = strtoul(temp, NULL, 10);
|
|
}
|
|
}
|
|
else
|
|
port = params;
|
|
|
|
// adjust port for ipv6 address
|
|
tmp = port;
|
|
while (tmp > host && *tmp != ']')
|
|
tmp--;
|
|
if (*tmp == ']')
|
|
{
|
|
port = tmp;
|
|
while (host < port && *host != '[')
|
|
host++;
|
|
if (host >= port)
|
|
return -1;
|
|
}
|
|
|
|
if ((port - host < 2) || (port - host > 128))//port - host > 256
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "uri domain length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(sipUri->host.addr.domain, host + 1, port - host - 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_from_parse(SIP_HDR_FROM *from, char *hvalue)
|
|
{
|
|
char *dispName;
|
|
char *url;
|
|
char *urlEnd;
|
|
char *genParams;
|
|
char *first;
|
|
char *second;
|
|
char *host;
|
|
char tmp[256];
|
|
WORD len;
|
|
|
|
if ((from == NULL) || (hvalue == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_from_parse: from or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
/* How to parse:
|
|
we'll place the pointers:
|
|
dispName => beginning of displayname
|
|
url => beginning of url
|
|
url_end => end of url
|
|
gen_params => beginning of params
|
|
|
|
examples:
|
|
|
|
jack <sip:jack@atosc.org>;tag=34erZ
|
|
^ ^ ^ ^
|
|
|
|
sip:jack@atosc.org;tag=34erZ
|
|
^ ^^
|
|
*/
|
|
|
|
dispName = strchr(hvalue, '"');
|
|
|
|
url = strchr (hvalue, '<');
|
|
if (url != NULL)
|
|
{
|
|
urlEnd = strchr (url, '>');
|
|
if (urlEnd == NULL)
|
|
return -1;
|
|
}
|
|
|
|
/* SIPit day2: this case was not supported
|
|
first '"' is placed after '<' and after '>'
|
|
<sip:ixion@62.254.248.117;method=INVITE>;description="OPEN";expires=28800
|
|
if the fisrt quote is after '<' then
|
|
this is not a quote for a dispName.
|
|
*/
|
|
|
|
if (dispName != NULL)
|
|
{
|
|
if (dispName > url)
|
|
dispName = NULL;
|
|
}
|
|
|
|
if ((dispName == NULL) && (url != NULL))
|
|
{// dispName IS A '*token' (not a quoted-string)
|
|
if (hvalue != url) // dispName exists
|
|
{
|
|
len = url - hvalue;
|
|
|
|
if ((len + 1 < 2) || len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "uri dispName length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(from->dispName, hvalue, len);
|
|
}
|
|
|
|
url++; // place pointer on the beginning of url
|
|
}
|
|
else
|
|
{
|
|
if ((dispName != NULL) && (url != NULL))
|
|
{ // dispName IS A quoted-string (not a '*token')
|
|
// search for quotes
|
|
first = sip_quote_find (hvalue);
|
|
second = sip_quote_find (first + 1);
|
|
|
|
if (second == NULL)
|
|
return -1; // if there is only 1 quote: failure
|
|
|
|
if ((first > url))
|
|
return -1;
|
|
|
|
len = second - first + 1;
|
|
|
|
if ((len + 1) >= 2)
|
|
{
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "dispName length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(from->dispName, first, len);
|
|
}
|
|
// else dispName is empty?
|
|
url = strchr (second + 1, '<');
|
|
|
|
if (url == NULL)
|
|
return -1; // '<' MUST exist
|
|
|
|
url++;
|
|
}
|
|
else
|
|
url = hvalue; // field does not contains '<' and '>'
|
|
}
|
|
|
|
// DISPLAY-NAME SET
|
|
// START of URL KNOWN
|
|
|
|
urlEnd = strchr(url, '>');
|
|
|
|
if (urlEnd == NULL) // sip:jack@atosc.org;tag=023
|
|
{ // We are sure ';' is the delimiter for from-parameters
|
|
host = strchr(url, '@');
|
|
|
|
if (host != NULL)
|
|
genParams = strchr(host, ';');
|
|
else
|
|
genParams = strchr(url, ';');
|
|
|
|
if (genParams != NULL)
|
|
urlEnd = genParams - 1;
|
|
else
|
|
urlEnd = url + strlen(url);
|
|
}
|
|
else // jack <sip:jack@atosc.org;user=phone>;tag=azer
|
|
{
|
|
genParams = strchr(urlEnd, ';');
|
|
urlEnd--; // place pointer on the beginning of url
|
|
}
|
|
|
|
if (genParams != NULL) // now we are sure a param exist
|
|
{
|
|
if (sip_generic_param_parseall(&from->params, genParams) == -1)
|
|
return -1;
|
|
}
|
|
|
|
// set the url
|
|
len = urlEnd - url + 1;
|
|
|
|
if ((len + 1 < 7) || len > 256)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "uri length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, url, len);
|
|
|
|
if (sip_uri_parse(&from->url, tmp) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_contact_parse(SIP_HDR_CONTACT *contact, char *hvalue)
|
|
{
|
|
return sip_from_parse((SIP_HDR_FROM *)contact, hvalue);
|
|
}
|
|
|
|
int sip_via_parse(SIP_HDR_VIA *via, char *hvalue)
|
|
{
|
|
char *version;
|
|
char *protocol;
|
|
char *host;
|
|
char *port;
|
|
char *viaParams;
|
|
char tmp[128];
|
|
char *comment;
|
|
char *ipv6host;
|
|
|
|
if ((via == NULL) || (hvalue == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_via_parse: via or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
version = strchr(hvalue, '/');
|
|
if (version == NULL)
|
|
return -1;
|
|
|
|
protocol = strchr(version + 1, '/');
|
|
if (protocol == NULL)
|
|
return -1;
|
|
|
|
// set the version
|
|
if ((protocol - version < 2) || (protocol - version > 128))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "via version length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, version - 3, protocol - version + 3);
|
|
|
|
if (sip_ver_api_conv(tmp, &via->version, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
// Here: we avoid matching an additionnal space
|
|
host = strchr(protocol + 1, ' ');
|
|
|
|
if (host == NULL)
|
|
return -1;
|
|
if (host == protocol + 1)
|
|
{ // there are extra SPACE characters
|
|
while (0 == strncmp(host, " ", 1))
|
|
{
|
|
host++;
|
|
|
|
if (strlen(host) == 1)
|
|
return -1; // via is malformed
|
|
}
|
|
// here, we match the real space located after the protocol name
|
|
host = strchr(host + 1, ' ');
|
|
|
|
if (host == NULL)
|
|
return -1;
|
|
}
|
|
|
|
// set the protocol
|
|
if ((host - protocol < 2) || (host - protocol > 128))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "via protocol length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, protocol + 1, host - protocol - 1);
|
|
|
|
if (sip_proto_api_conv(tmp, &via->protocol, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
// comments in Via are not allowed any more in the latest draft (09)
|
|
comment = strchr(host, '(');
|
|
|
|
if (comment != NULL)
|
|
{
|
|
/*
|
|
char *end_comment;
|
|
|
|
end_comment = strchr (host, ')');
|
|
if (end_comment == NULL)
|
|
return -1; // if '(' exist ')' MUST exist
|
|
if (end_comment - comment < 2)
|
|
return -1;
|
|
via->comment = (char *) osip_malloc (end_comment - comment);
|
|
if (via->comment == NULL)
|
|
return -1;
|
|
sip_strncpy (via->comment, comment + 1, end_comment - comment - 1);
|
|
comment--;
|
|
*/
|
|
return -1;
|
|
}
|
|
else
|
|
comment = host + strlen(host);
|
|
|
|
viaParams = strchr(host, ';');
|
|
|
|
if ((viaParams != NULL) && (viaParams < comment))
|
|
{
|
|
if (comment - viaParams + 1 < 2)
|
|
return -1;
|
|
sip_strncpy(tmp, viaParams, comment - viaParams);
|
|
sip_generic_param_parseall(&via->params, tmp);
|
|
}
|
|
|
|
if (viaParams == NULL)
|
|
viaParams = comment;
|
|
|
|
// add ipv6 support (0.8.4)
|
|
// Via: SIP/2.0/UDP [mlke::zeezf:ezfz:zef:zefzf]:port;....
|
|
ipv6host = strchr(host, '[');
|
|
if (ipv6host != NULL && ipv6host < viaParams)
|
|
{
|
|
/*
|
|
port = strchr (ipv6host, ']');
|
|
if (port == NULL || port > via_params)
|
|
return -1;
|
|
|
|
if (port - ipv6host < 2)
|
|
return -1;
|
|
via->host = (char *) osip_malloc (port - ipv6host);
|
|
if (via->host == NULL)
|
|
return -1;
|
|
sip_clrncpy (via->host, ipv6host + 1, port - ipv6host - 1);
|
|
|
|
port = strchr (port, ':');
|
|
*/
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
port = strchr(host, ':');
|
|
ipv6host = NULL;
|
|
}
|
|
|
|
if ((port != NULL) && (port < viaParams))
|
|
{
|
|
if ((viaParams - port < 2) || (viaParams - port > 128))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "via port length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, port + 1, viaParams - port - 1);
|
|
via->url.port = atol(tmp);
|
|
}
|
|
else
|
|
port = viaParams;
|
|
|
|
// host is already set in the case of ipv6
|
|
if (ipv6host != NULL)
|
|
return 0;
|
|
|
|
if ((port - host < 2) || (port - host > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "via domain length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(via->url.domain, host + 1, port - host - 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_to_parse(SIP_HDR_TO *to, char *hvalue)
|
|
{
|
|
return sip_from_parse((SIP_HDR_FROM *)to, hvalue);
|
|
}
|
|
|
|
int sip_proxy_require_parse(SIP_HDR_PROXY_REQUIRE *proxyRequire, char *hvalue)
|
|
{
|
|
int len;
|
|
char tmp[64];
|
|
|
|
if (proxyRequire == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_via_parse: proxyRequire or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (hvalue == NULL || hvalue[0] == '\0')
|
|
return 0;
|
|
|
|
len = strlen(hvalue);
|
|
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "proxy require value is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, len);
|
|
|
|
if (sip_option_tag_api_conv(tmp, &proxyRequire->optionTag, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_record_route_parse(SIP_HDR_RECORD_ROUTE *recRoute, char *hvalue)
|
|
{
|
|
return sip_from_parse((SIP_HDR_FROM *)recRoute, hvalue);
|
|
}
|
|
|
|
int sip_require_parse(SIP_HDR_REQUIRE *require, char *hvalue)
|
|
{
|
|
int len;
|
|
char tmp[64];
|
|
|
|
if (require == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_require_parse: require or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (hvalue == NULL || hvalue[0] == '\0')
|
|
return 0;
|
|
|
|
len = strlen(hvalue);
|
|
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "require value is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, len);
|
|
|
|
if (sip_option_tag_api_conv(tmp, &require->optionTag, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_route_parse(SIP_HDR_ROUTE *route, char *hvalue)
|
|
{
|
|
return sip_from_parse((SIP_HDR_FROM *)route, hvalue);
|
|
}
|
|
|
|
int sip_call_id_parse(SIP_HDR_CALL_ID *callId, char *hvalue)
|
|
{
|
|
char *host;
|
|
char *end;
|
|
WORD len;
|
|
|
|
if ((callId == NULL) || (hvalue == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_call_id_parse: callId or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
strcpy(callId->value, "");
|
|
strcpy(callId->host, "");
|
|
|
|
host = strchr(hvalue, '@'); /* SEARCH FOR '@' */
|
|
end = hvalue + strlen (hvalue);
|
|
|
|
if (host == NULL)
|
|
host = end;
|
|
else
|
|
{
|
|
len = end - host - 1;
|
|
|
|
if ((len + 2 < 2) || (len > 256))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "callId host length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(callId->host, host + 1, len);
|
|
}
|
|
|
|
len = host - hvalue;
|
|
|
|
if ((len + 1 < 2) || (len > 128))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "callId value length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(callId->value, hvalue, len);
|
|
|
|
return 0; /* ok */
|
|
}
|
|
|
|
int sip_cseq_parse(SIP_HDR_CSEQ *cseq, char *hvalue)
|
|
{
|
|
char *method = NULL;
|
|
char *end = NULL;
|
|
BYTE tmp[128], len;
|
|
|
|
if ((cseq == NULL) || (hvalue == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_cseq_parse: cseq or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
cseq->value = 0;
|
|
cseq->method = 0;
|
|
|
|
method = strchr(hvalue, ' '); /* SEARCH FOR SPACE */
|
|
end = hvalue + strlen (hvalue);
|
|
|
|
if (method == NULL)
|
|
return -1;
|
|
|
|
len = method - hvalue;
|
|
if ((len + 1 < 2) || (len > 128))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "cseq value length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy((char *)tmp, hvalue, len);
|
|
cseq->value = atol((char *)tmp);
|
|
|
|
len = end - method;
|
|
|
|
if ((len + 1 < 2) || (len > 128))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "cseq method length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy((char *)tmp, method + 1, len);
|
|
|
|
if (sip_method_api_conv((char *)tmp, &cseq->method, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0; /* ok */
|
|
}
|
|
|
|
int sip_expires_parse(SIP_HDR_EXPIRES *expires, char *hvalue)
|
|
{
|
|
if ((expires == NULL) || (hvalue == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_expires_parse: expires or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
expires->value = atol(hvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_mime_version_parse(SIP_HDR_MIME_VERSION *mimiVer, char *hvalue)
|
|
{
|
|
int len;
|
|
BYTE *mimeVersion;
|
|
char tmp[64];
|
|
|
|
if ((mimiVer == NULL) || (hvalue == NULL || hvalue[0] == '\0'))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_mime_version_parse: mimiVer or value is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
len = strlen(hvalue);
|
|
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "mime version value length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
mimeVersion = &mimiVer ->mimeVersion;
|
|
|
|
sip_clrncpy(tmp, hvalue, len);
|
|
|
|
if (sip_mime_version_api_conv(tmp, mimeVersion, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_time_stamp_parse(SIP_HDR_TIMESTAMP *hdrTimeStamp, char *hvalue)
|
|
{
|
|
if (hdrTimeStamp == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_time_stamp_parse: hdrTimeStamp is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (hvalue == NULL || hvalue[0] == '\0')
|
|
return 0;
|
|
|
|
hdrTimeStamp->timeStamp = atoll(hvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_max_forwards_parse(SIP_HDR_MAX_FORWARDS *maxForwards, char *hvalue)
|
|
{
|
|
if ((maxForwards == NULL) || (hvalue == NULL) || (hvalue[0] == '\0'))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_max_forwards_parse: maxForwards or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
maxForwards->value = atol(hvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_user_agent_parse(SIP_HDR_USER_AGENT *userAgent, char *hvalue)
|
|
{
|
|
if (userAgent == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_user_agent_parse: userAgent is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (hvalue == NULL || hvalue[0] == '\0')
|
|
return 0;
|
|
|
|
strcpy ((char *)userAgent->agent, hvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_server_parse( SIP_HDR_SERVER *server, char *hvalue)
|
|
{
|
|
if (server == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_server_parse: server is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (hvalue == NULL || hvalue[0] == '\0')
|
|
return 0;
|
|
|
|
strcpy ((char *)server->server, hvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_subject_parse(SIP_HDR_SUBJECT *subject, char *hvalue)
|
|
{
|
|
if (subject == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_subject_parse: subject is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (hvalue == NULL || hvalue[0] == '\0')
|
|
return 0;
|
|
|
|
strcpy ((char *)subject->subject, hvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_supported_parse(SIP_HDR_SUPPORTED *supported, char *hvalue)
|
|
{
|
|
int len;
|
|
char tmp[64];
|
|
|
|
if (supported == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_supported_parse: supported is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (hvalue == NULL || hvalue[0] == '\0')
|
|
return 0;
|
|
|
|
len = strlen(hvalue);
|
|
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "supported value length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, len);
|
|
|
|
if (sip_option_tag_api_conv(tmp, &supported->optionTag, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_unsupported_parse(SIP_HDR_UNSUPPORTED *unsupported, char *hvalue)
|
|
{
|
|
int len;
|
|
char tmp[64];
|
|
|
|
if (unsupported == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_unsupported_parse: unsupported is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (hvalue == NULL || hvalue[0] == '\0')
|
|
return 0;
|
|
|
|
len = strlen(hvalue);
|
|
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "unsupported value length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, len);
|
|
|
|
if (sip_option_tag_api_conv(tmp, &unsupported->optionTag, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_content_type_parse(SIP_CONTENT_TYPE *contentType, char *hvalue)
|
|
{
|
|
char *subType;
|
|
char *sipContentTypeParams;
|
|
char tmp[64];
|
|
|
|
if (contentType == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_content_type_parse: contentType is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
/* How to parse:
|
|
|
|
we'll place the pointers:
|
|
subType => beginning of subtype
|
|
sipContentTypeParams => beginning of params
|
|
|
|
examples:
|
|
|
|
application/multipart ; boundary=
|
|
^ ^
|
|
*/
|
|
|
|
if (hvalue == NULL || hvalue[0] == '\0')
|
|
return 0;
|
|
|
|
subType = strchr(hvalue, '/');
|
|
sipContentTypeParams = strchr(hvalue, ';');
|
|
|
|
if (subType == NULL)
|
|
return -1;
|
|
|
|
if (sipContentTypeParams != NULL)
|
|
{
|
|
if (sip_generic_param_parseall(&contentType->params, sipContentTypeParams) == -1)
|
|
return -1;
|
|
}
|
|
else
|
|
sipContentTypeParams = subType + strlen(subType);
|
|
|
|
if ((subType - hvalue + 1 < 2) || (subType - hvalue > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "content type value length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, subType - hvalue);
|
|
|
|
if (sip_content_type_api_conv(tmp, &contentType->type, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
if ((sipContentTypeParams - subType < 2) || (sipContentTypeParams - subType > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "content type params length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, subType + 1, sipContentTypeParams - subType - 1);
|
|
|
|
if (sip_content_sub_type_api_conv(tmp, &contentType->subType, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_content_disposition_parse(SIP_CONTENT_DISPOSITION *contentDisposition, char *hvalue)
|
|
{
|
|
char *sipContentDispositionParams;
|
|
char tmp[64];
|
|
|
|
if (contentDisposition == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_content_disposition_parse: contentDisposition is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (hvalue == NULL || hvalue[0] == '\0')
|
|
return 0;
|
|
|
|
sipContentDispositionParams = strchr(hvalue, ';');
|
|
|
|
if (sipContentDispositionParams != NULL)
|
|
{
|
|
if (sip_generic_param_parseall(&contentDisposition->params, sipContentDispositionParams) == -1)
|
|
return -1;
|
|
}
|
|
else
|
|
sipContentDispositionParams = hvalue + strlen(hvalue);
|
|
|
|
if ((sipContentDispositionParams - hvalue < 2) || (sipContentDispositionParams - hvalue > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "content disposition value length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, sipContentDispositionParams - hvalue);
|
|
|
|
if (sip_content_disposition_api_conv(tmp, &contentDisposition->contentDisposition, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_content_language_parse(BYTE *contentLanguage, char *hvalue)
|
|
{
|
|
int len;
|
|
char tmp[64];
|
|
|
|
if (contentLanguage == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_content_language_parse: contentLanguage is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
len = strlen(hvalue);
|
|
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "content language value length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, len);
|
|
|
|
if (sip_content_language_api_conv(tmp, contentLanguage, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_content_encoding_parse(BYTE *contentEncoding, char *hvalue)
|
|
{
|
|
int len;
|
|
char tmp[64];
|
|
|
|
if (contentEncoding == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_content_encoding_parse: contentEncoding is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
len = strlen(hvalue);
|
|
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "content encoding value length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, len);
|
|
|
|
if (sip_content_encoding_api_conv(tmp, contentEncoding, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_content_length_parse(SIP_ENTITY *sipEntity, char *hvalue)
|
|
{
|
|
if (sipEntity == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_content_length_parse: sipEntity is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
sipEntity->sipHdrContentLength = atol(hvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_accept_parse(SIP_HDR_ACCEPT *accept, char *hvalue)
|
|
{
|
|
char *subType;
|
|
char *sipAccepttTypeParams;
|
|
char tmp[64];
|
|
|
|
if (accept == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_accept_parse: accept is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
subType = strchr(hvalue, '/');
|
|
sipAccepttTypeParams = strchr(hvalue, ';');
|
|
|
|
if (subType == NULL)
|
|
return -1;
|
|
|
|
if (sipAccepttTypeParams != NULL)
|
|
{
|
|
if (sip_generic_param_parseall(&accept->params, sipAccepttTypeParams) == -1)
|
|
return -1;
|
|
}
|
|
else
|
|
sipAccepttTypeParams = subType + strlen(subType);
|
|
|
|
if ((subType - hvalue + 1 < 2) || (subType - hvalue > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "accept type length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, subType - hvalue);
|
|
|
|
if (sip_accept_type_api_conv(tmp, &accept->type, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
if ((sipAccepttTypeParams - subType < 2) || (sipAccepttTypeParams - subType > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "accept sub type length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, subType + 1, sipAccepttTypeParams - subType - 1);
|
|
|
|
if (sip_accept_sub_type_api_conv(tmp, &accept->subType, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_accept_encoding_parse(SIP_HDR_ACCEPT_ENCODING *encoding, char *hvalue)
|
|
{
|
|
char *sipAcceptEncodingParams;
|
|
char tmp[64];
|
|
|
|
if (encoding == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_accept_encoding_parse: encoding is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
sipAcceptEncodingParams = strchr(hvalue, ';');
|
|
|
|
if (sipAcceptEncodingParams != NULL)
|
|
{
|
|
if (sip_generic_param_parseall(&encoding->params, sipAcceptEncodingParams) == -1)
|
|
return -1;
|
|
}
|
|
else
|
|
sipAcceptEncodingParams = hvalue + strlen(hvalue);
|
|
|
|
if ((sipAcceptEncodingParams - hvalue < 2) || (sipAcceptEncodingParams - hvalue > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "accept encoding length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, sipAcceptEncodingParams - hvalue);
|
|
|
|
if (sip_accept_encoding_api_conv(tmp, &encoding->acceptEncoding, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_accept_language_parse(SIP_HDR_ACCEPT_LANGUAGE *language, char *hvalue)
|
|
{
|
|
char *sipAcceptLanguageParams;
|
|
char tmp[64];
|
|
|
|
if (language == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_accept_language_parse: language is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
sipAcceptLanguageParams = strchr(hvalue, ';');
|
|
|
|
if (sipAcceptLanguageParams != NULL)
|
|
{
|
|
if (sip_generic_param_parseall(&language->params, sipAcceptLanguageParams) == -1)
|
|
return -1;
|
|
}
|
|
else
|
|
sipAcceptLanguageParams = hvalue + strlen(hvalue);
|
|
|
|
if ((sipAcceptLanguageParams - hvalue < 2) || (sipAcceptLanguageParams - hvalue > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "accept language value length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, sipAcceptLanguageParams - hvalue);
|
|
|
|
if (sip_accept_language_api_conv(tmp, &language->acceptLanguage, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_allow_parse(SIP_HDR_ALLOW *allow, char *hvalue)
|
|
{
|
|
char *comma;
|
|
char *buf = hvalue;
|
|
char tmp[64];
|
|
int ret;
|
|
|
|
if (allow == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_allow_parse: allow is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
allow->num = 0;
|
|
|
|
for (;;)
|
|
{
|
|
comma = strchr(buf, ',');
|
|
|
|
if (comma == NULL)
|
|
{
|
|
comma = buf + strlen(buf);
|
|
break;
|
|
}
|
|
|
|
if ((comma - buf < 2) || (comma - buf > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "allow method length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, buf, comma - buf);
|
|
|
|
if ((ret = sip_allow_api_conv(tmp, &allow->allowMethod[allow->num], SIP_STR_TO_API)) == -1)
|
|
return -1;
|
|
|
|
if (ret == 0)
|
|
allow->num = allow->num + 1;
|
|
|
|
buf = comma + 1;
|
|
}
|
|
|
|
if ((comma - buf < 2) || (comma - buf > 64))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "allow last method length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, buf, comma - buf);
|
|
|
|
if ((ret = sip_allow_api_conv(tmp, &allow->allowMethod[allow->num], SIP_STR_TO_API)) == -1)
|
|
return -1;
|
|
|
|
if (ret == 0)
|
|
allow->num = allow->num + 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_date_time_parse(SIP_HDR_DATE *date, char *time)
|
|
{
|
|
int i;
|
|
int len;
|
|
char *buf;
|
|
char *colon;
|
|
char tmp[64];
|
|
|
|
if (date == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_date_time_parse: date is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((time == NULL) || (time[0] == '\0'))
|
|
return 0;
|
|
|
|
buf = time;
|
|
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
if (((colon = strchr(buf, ':')) == NULL) || (colon < buf))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "Malformed date time\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (colon - buf > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "date time length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, buf, colon - buf);
|
|
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
date->hour = atoi(tmp);
|
|
break;
|
|
case 1:
|
|
date->min = atoi(tmp);
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
buf = colon + 1;
|
|
}
|
|
|
|
len = strlen(buf);
|
|
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "date time second length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, buf, len);
|
|
|
|
date->sec = atoi(tmp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_date_parse(SIP_HDR_DATE *date, char *hvalue)
|
|
{
|
|
int i;
|
|
int len;
|
|
char *comma;
|
|
char *sp;
|
|
char *nextSp;
|
|
char tmp[64];
|
|
|
|
if (date == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_date_time_parse: date is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
if (((comma = strchr(hvalue, ',')) == NULL) || (comma <= hvalue))
|
|
return -1;
|
|
|
|
if (comma - hvalue > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "date weekday length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, hvalue, comma - hvalue);
|
|
|
|
sip_date_weekday_api_conv(tmp, &date->wkDay, SIP_STR_TO_API);
|
|
|
|
if (comma[1] == ' ')
|
|
sp = comma + 2;
|
|
else
|
|
sp = comma + 1;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
if (((nextSp = strchr(sp, ' ')) == NULL) || (nextSp < sp))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "Malformed sip date\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (nextSp - sp > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "date length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, sp, nextSp - sp);
|
|
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
date->mDay = atoi(tmp);
|
|
break;
|
|
case 1:
|
|
if (sip_date_month_api_conv(tmp, &date->mon, SIP_STR_TO_API) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
break;
|
|
case 2:
|
|
date->year = atol(tmp);
|
|
break;
|
|
case 3:
|
|
sip_date_time_parse(date, tmp);
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
sp = nextSp + 1;
|
|
}
|
|
|
|
len = strlen(sp);
|
|
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "date type length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, sp, len);
|
|
|
|
if (sip_date_type_api_conv(tmp, &date->dateType, SIP_STR_TO_API) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_refer_to_parse(SIP_HDR_REFER_TO *referTo, char *hvalue)
|
|
{
|
|
return sip_from_parse((SIP_HDR_FROM *)referTo, hvalue);
|
|
}
|
|
|
|
int sip_envet_parse(SIP_HDR_EVENT *event, char *hvalue)
|
|
{
|
|
if ((event == NULL) || (hvalue == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_envet_parse: event or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
strcpy(event->event, hvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_subscription_state_parse(SIP_HDR_SUBSCRIPTION_STATE *subscriptionState, char *hvalue)
|
|
{
|
|
if ((subscriptionState == NULL) || (hvalue == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_subscription_state_parse: subscriptionState or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
strcpy(subscriptionState->subscriptionState, hvalue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_accept(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_ACCEPT *accept;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_accept: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
{
|
|
// sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_ACCEPT_EMPTY_MASK;
|
|
return 0;
|
|
}
|
|
|
|
accept = &sip->sipApiMsg.sipMsg.sipHdrAccept;
|
|
|
|
if (sip_accept_parse(accept, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip accept parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_ACCEPT_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_accept_encoding(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_ACCEPT_ENCODING *encoding;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_accept_encoding: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
encoding = &sip->sipApiMsg.sipMsg.sipHdrAcceptEncoding;
|
|
|
|
if (sip_accept_encoding_parse(encoding, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip accept encoding parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_ACCEPT_ENCODING_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_accept_language(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_ACCEPT_LANGUAGE *language;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_accept_language: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
language = &sip->sipApiMsg.sipMsg.sipHdrAcceptLanguage;
|
|
|
|
if (sip_accept_language_parse(language, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip accept language failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_ACCEPT_LANGUAGE_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_alert_info(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_allow(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_ALLOW *allow;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_allow: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
allow = &sip->sipApiMsg.sipMsg.sipHdrAllow;
|
|
|
|
if (sip_allow_parse(allow, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip allow parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_ALLOW_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_authentication_info(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_authorization(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_content_type(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_CONTENT_TYPE *contentType;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_content_type: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
contentType = &sip->sipApiMsg.sipMsg.sipEntity.sipHdrContentType;
|
|
|
|
if (sip_content_type_parse(contentType, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip content type parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipEntity.sipEntityHdrFlag[0] |= SIP_HDR_CONTENT_TYPE_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_content_disposition(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_CONTENT_DISPOSITION *contentDisposition;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_content_disposition: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
contentDisposition= &sip->sipApiMsg.sipMsg.sipEntity.sipHdrContentDisposition;
|
|
|
|
if (sip_content_disposition_parse(contentDisposition, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipEncBuf, "sip content disposition parse failed\r\n");
|
|
sip_log_err(sipEncBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipEntity.sipEntityHdrFlag[0] |= SIP_HDR_CONTENT_DISPOSITION_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_content_encoding(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
BYTE *contentEncoding;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_content_encoding: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
contentEncoding = &sip->sipApiMsg.sipMsg.sipEntity.sipHdrContentEncoding;
|
|
|
|
if (sip_content_encoding_parse(contentEncoding, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip content encoding parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipEntity.sipEntityHdrFlag[0] |= SIP_HDR_CONTENT_ENCODING_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_content_language(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
BYTE *contentLanguage;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_content_language: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
contentLanguage = &sip->sipApiMsg.sipMsg.sipEntity.sipHdrContentLanguage;
|
|
|
|
if (sip_content_language_parse(contentLanguage, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip content language parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipEntity.sipEntityHdrFlag[0] |= SIP_HDR_CONTENT_LANGUAGE_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_content_length(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_ENTITY *sipEntity;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_content_length: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
sipEntity = &sip->sipApiMsg.sipMsg.sipEntity;
|
|
|
|
if (sip_content_length_parse(sipEntity, hvalue) < 0)
|
|
return -1;
|
|
|
|
sip->sipApiMsg.sipMsg.sipEntity.sipEntityHdrFlag[0] |= SIP_HDR_CONTENT_LENGTH_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_call_id(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_CALL_ID *hdrCallId;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_call_id: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
hdrCallId = &sip->sipApiMsg.sipMsg.sipHdrCallId;
|
|
|
|
if (sip_call_id_parse(hdrCallId, hvalue) < 0)
|
|
{
|
|
strcpy(hdrCallId->value, "");
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_CALL_ID_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_cseq(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_CSEQ *hdrCseq;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_cseq: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
hdrCseq = &sip->sipApiMsg.sipMsg.sipHdrCseq;
|
|
|
|
if (sip_cseq_parse(hdrCseq, hvalue) < 0)
|
|
{
|
|
hdrCseq->value = 0;
|
|
hdrCseq->method = 0;
|
|
sprintf((char *)sipAsciTempBuf, "sip cseq parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_CSEQ_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_date(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_DATE *date;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_date: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
date = &sip->sipApiMsg.sipMsg.sipHdrDate;
|
|
|
|
if (sip_date_parse(date, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip date parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_DATE_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_expires(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_EXPIRES *expires;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_expires: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
expires = &sip->sipApiMsg.sipMsg.sipHdrExpires;
|
|
|
|
if (sip_expires_parse(expires, hvalue) < 0)
|
|
return -1;
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_EXPIRES_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_call_info(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_error_info(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_event(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_EVENT *event;
|
|
|
|
if ((sip == NULL) || (hvalue == NULL) || (hvalue[0] == '\0'))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_event: sip or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
event = &sip->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrEvent;
|
|
|
|
if (sip_envet_parse(event, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip event parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_EVENT_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_from(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_FROM *hdrFrom;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_from: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
hdrFrom = &sip->sipApiMsg.sipMsg.sipHdrFrom;
|
|
|
|
if (sip_from_parse(hdrFrom, hvalue) < 0)
|
|
return -1;
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_FROM_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_contact(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_CONTACTS *contacts;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_contact: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
contacts = &sip->sipApiMsg.sipMsg.sipHdrContacts;
|
|
|
|
if (contacts->num >= SIP_MAX_NUM_OF_CONTACTS)
|
|
return -1;
|
|
|
|
if (sip_contact_parse(&contacts->contacts[contacts->num], hvalue) < 0)
|
|
return -1;
|
|
|
|
contacts->head = 0;
|
|
contacts->num++;
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_CONTACT_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_mime_version(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_MIME_VERSION *mimeVer;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_mime_version: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
mimeVer = &sip->sipApiMsg.sipMsg.sipHdrMimeVer;
|
|
|
|
if (sip_mime_version_parse(mimeVer, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip mime version parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_MIME_VERSION_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_proxy_authenticate(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_proxy_authentication_info(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_proxy_authorization(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_proxy_require(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_PROXY_REQUIRE *proxyRequire;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_proxy_require: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
proxyRequire = &sip->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrProxyRequire;
|
|
|
|
if (sip_proxy_require_parse(proxyRequire, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip proxy require parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |=SIP_HDR_PROXY_REQUIRE_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_record_route(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_RECORD_ROUTES *recRoutes;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_record_route: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
recRoutes = &sip->sipApiMsg.sipMsg.sipHdrRecordRoutes;
|
|
|
|
if (recRoutes->num >= SIP_MAX_NUM_OF_RECORD_ROUTES)
|
|
return -1;
|
|
|
|
if (sip_record_route_parse(&recRoutes->recRoutes[recRoutes->num + 1], hvalue) < 0)
|
|
return -1;
|
|
|
|
if (recRoutes->num == 0)
|
|
recRoutes->head = 1;
|
|
|
|
recRoutes->num++;
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_RECORD_ROUTE_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_refer_to(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_REFER_TO *referTo;
|
|
|
|
if ((sip == NULL) || (hvalue == NULL) || (hvalue[0] == '\0'))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_refer_to: sip or hvalue is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
referTo = &sip->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrReferTo;
|
|
|
|
if (sip_refer_to_parse(referTo, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip refer-to parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_REFER_TO_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_require(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_REQUIRE *require;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_require: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
require = &sip->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrRequire;
|
|
|
|
if (sip_require_parse(require, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip require parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_REQUIRE_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_route(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_ROUTES *routes;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_route: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
routes = &sip->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrRoutes;
|
|
|
|
if (routes->num >= SIP_MAX_NUM_OF_RECORD_ROUTES)
|
|
return -1;
|
|
|
|
if (sip_route_parse(&routes->routes[routes->num + 1], hvalue) < 0)
|
|
return -1;
|
|
|
|
if (routes->num == 0)
|
|
routes->head = 1;
|
|
|
|
routes->num++;
|
|
|
|
sip->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_ROUTE_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_server(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_SERVER *server;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_server: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
server = &sip->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipRspHdr.sipHdrServer;
|
|
|
|
if (sip_server_parse(server, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip server parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_SERVER_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_subject(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_SUBJECT *subject;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_subject: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
subject = &sip->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrSubject;
|
|
|
|
if (sip_subject_parse(subject, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip subject parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_SUBJECT_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_subscription_state(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_SUBSCRIPTION_STATE *subscriptionState;
|
|
|
|
if ((sip == NULL) || (hvalue == NULL) || (hvalue[0] == '\0'))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_subscription_state: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
subscriptionState = &sip->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrSubscriptionState;
|
|
|
|
if (sip_subscription_state_parse(subscriptionState, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip subscription state parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_SUBSCRIPTION_STATE_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_supported(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_SUPPORTED *supported;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_supported: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
supported = &sip->sipApiMsg.sipMsg.sipHdrSupported;
|
|
|
|
if (sip_supported_parse(supported, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip supported parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_SUPPORTED_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_to(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_TO *hdrTo;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_to: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
hdrTo = &sip->sipApiMsg.sipMsg.sipHdrTo;
|
|
|
|
if (sip_to_parse(hdrTo, hvalue) < 0)
|
|
return -1;
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_TO_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_time_stamp(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_TIMESTAMP *hdrTimeStamp;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_time_stamp: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
hdrTimeStamp = &sip->sipApiMsg.sipMsg.sipHdrStamp;
|
|
|
|
if (sip_time_stamp_parse(hdrTimeStamp, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip time stamp parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_TIMESTAMP_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_unsupported(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_UNSUPPORTED *unsupported;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_unsupported: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
unsupported = &sip->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipRspHdr.sipHdrUnsupported;
|
|
|
|
if (sip_unsupported_parse(unsupported, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip unsupported parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_UNSUPPORTED_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_user_agent(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_USER_AGENT *userAgent;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_user_agent: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
userAgent = &sip->sipApiMsg.sipMsg.sipHdrUserAgent;
|
|
|
|
if (sip_user_agent_parse(userAgent, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip user agent parse failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_USER_AGENT_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_via(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_VIAS *vias;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_via: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
vias = &sip->sipApiMsg.sipMsg.sipHdrVias;
|
|
|
|
if (vias->num >= SIP_MAX_NUM_OF_VIAS)
|
|
return -1;
|
|
|
|
if (sip_via_parse(&vias->vias[vias->num + 1], hvalue) < 0)
|
|
return -1;
|
|
|
|
if (vias->num == 0)
|
|
vias->head = 1;
|
|
|
|
vias->num++;
|
|
|
|
sip->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_VIA_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_www_authenticate(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_max_forwards(SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
SIP_HDR_MAX_FORWARDS *hdrMaxForwards;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_max_forwards: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((hvalue == NULL) || (hvalue[0] == '\0'))
|
|
return 0;
|
|
|
|
hdrMaxForwards = &sip->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrMaxForwards;
|
|
|
|
if (sip_max_forwards_parse(hdrMaxForwards, hvalue) < 0)
|
|
return -1;
|
|
|
|
sip->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_MAX_FORWARDS_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void sip_tolower(char *str)
|
|
{
|
|
int i;
|
|
int len;
|
|
|
|
if (str == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_tolower: str is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return;
|
|
}
|
|
|
|
len = strlen(str);
|
|
|
|
for (i = 0; i <= len - 1; i++)
|
|
{
|
|
if ('A' <= str[i] && str[i] <= 'Z')
|
|
str[i] = str[i] + 32;
|
|
}
|
|
}
|
|
|
|
int sip_find_next_crlf(char *startOfHeader, char **endOfHeader)
|
|
{
|
|
char *soh = startOfHeader;
|
|
|
|
*endOfHeader = NULL;
|
|
|
|
while (('\r' != *soh) && ('\n' != *soh))
|
|
{
|
|
if (*soh)
|
|
soh++;
|
|
else
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "Final CRLF is missing\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// case 1: CRLF is the separator
|
|
// case 2 or 3: CR or LF is the separator
|
|
if (('\r' == soh[0]) && ('\n' == soh[1]))
|
|
soh = soh + 1;
|
|
|
|
// VERIFY if TMP is the end of header or LWS.
|
|
// LWS are extra SP, HT, CR and LF contained in headers.
|
|
if ((' ' == soh[1]) || ('\t' == soh[1]))
|
|
{
|
|
// incoming message that potentially
|
|
// contains LWS must be processed with
|
|
// sip_util_replace_all_lws(char *)
|
|
sprintf((char *)sipAsciTempBuf, "Message that contains LWS must be processed with sip_util_replace_all_lws(char *tmp) before being parsed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
*endOfHeader = soh + 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// For better performance
|
|
// Calculates a hash value for the given string
|
|
DWORD sip_hash(char *str)
|
|
{
|
|
DWORD hash = 5373;//5381
|
|
int c;
|
|
|
|
if (str == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_hash: str is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
}
|
|
|
|
while ((c = *str++) != '\0')
|
|
hash = (hash << 4) + hash + c;//5
|
|
|
|
return hash;
|
|
}
|
|
|
|
// This method must be called before using the parser
|
|
int sip_parser_init(void)
|
|
{
|
|
int i = 0;
|
|
int count = 0;
|
|
DWORD hash;
|
|
|
|
sipParseConfig[i].hname = SIP_HNAME_ACCEPT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_accept);
|
|
sipParseConfig[i].hname = SIP_HNAME_ACCEPT_ENCODING;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_accept_encoding);
|
|
sipParseConfig[i].hname = SIP_HNAME_ACCEPT_LANGUAGE;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_accept_language);
|
|
sipParseConfig[i].hname = SIP_HNAME_ALERT_INFO;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_alert_info);
|
|
sipParseConfig[i].hname = SIP_HNAME_ALLOW;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_allow);
|
|
/* sipParseConfig[i].hname = SIP_HNAME_AUTHENTICATION_INFO;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_authentication_info);
|
|
sipParseConfig[i].hname = SIP_HNAME_AUTHORIZATION;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_authorization);*/
|
|
sipParseConfig[i].hname = SIP_HNAME_CONTENT_TYPE_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_content_type);
|
|
sipParseConfig[i].hname = SIP_HNAME_CALL_ID;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_call_id);
|
|
sipParseConfig[i].hname = SIP_HNAME_CALL_INFO;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_call_info);
|
|
sipParseConfig[i].hname = SIP_HNAME_CONTACT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_contact);
|
|
sipParseConfig[i].hname = SIP_HNAME_CONTENT_ENCODING;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_content_encoding);
|
|
sipParseConfig[i].hname = SIP_HNAME_CONTENT_LENGTH;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_content_length);
|
|
sipParseConfig[i].hname = SIP_HNAME_CONTENT_TYPE;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_content_type);
|
|
sipParseConfig[i].hname = SIP_HNAME_CONTENT_DISPOSITION;
|
|
sipParseConfig[i++].setheader =(&sip_message_set_content_disposition);
|
|
sipParseConfig[i].hname = SIP_HNAME_CONTENT_LANGUAGE;
|
|
sipParseConfig[i++].setheader =(&sip_message_set_content_language);
|
|
sipParseConfig[i].hname = SIP_HNAME_CSEQ;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_cseq);
|
|
sipParseConfig[i].hname = SIP_HNAME_CONTENT_ENCODING_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_content_encoding);
|
|
sipParseConfig[i].hname = SIP_HNAME_SIPDATE;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_date);
|
|
sipParseConfig[i].hname = SIP_HNAME_EXPIRES;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_expires);
|
|
sipParseConfig[i].hname = SIP_HNAME_ERROR_INFO;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_error_info);
|
|
sipParseConfig[i].hname = SIP_HNAME_EVENT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_event);
|
|
sipParseConfig[i].hname = SIP_HNAME_FROM_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_from);
|
|
sipParseConfig[i].hname = SIP_HNAME_FROM;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_from);
|
|
sipParseConfig[i].hname = SIP_HNAME_CALL_ID_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_call_id);
|
|
sipParseConfig[i].hname = SIP_HNAME_CONTENT_LENGTH_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_content_length);
|
|
sipParseConfig[i].hname = SIP_HNAME_CONTACT_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_contact);
|
|
sipParseConfig[i].hname = SIP_HNAME_MIME_VERSION;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_mime_version);
|
|
sipParseConfig[i].hname = SIP_HNAME_PROXY_AUTHENTICATE;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_proxy_authenticate);
|
|
/* sipParseConfig[i].hname = SIP_HNAME_PROXY_AUTHENTICATION_INFO;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_proxy_authentication_info);
|
|
sipParseConfig[i].hname = SIP_HNAME_PROXY_AUTHORIZATION;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_proxy_authorization);*/
|
|
sipParseConfig[i].hname = SIP_HNAME_PROXY_REQUIRE;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_proxy_require);
|
|
sipParseConfig[i].hname = SIP_HNAME_RECORD_ROUTE;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_record_route);
|
|
sipParseConfig[i].hname = SIP_HNAME_REQUIRE;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_require);
|
|
sipParseConfig[i].hname = SIP_HNAME_ROUTE;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_route);
|
|
sipParseConfig[i].hname = SIP_HNAME_REFER_TO_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_refer_to);
|
|
sipParseConfig[i].hname = SIP_HNAME_REFER_TO;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_refer_to);
|
|
sipParseConfig[i].hname = SIP_HNAME_SERVER;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_server);
|
|
sipParseConfig[i].hname = SIP_HNAME_SUBJECT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_subject);
|
|
sipParseConfig[i].hname = SIP_HNAME_SUBJECT_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_subject);
|
|
sipParseConfig[i].hname = SIP_HNAME_SUPPORTED_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_supported);
|
|
sipParseConfig[i].hname = SIP_HNAME_SUPPORTED;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_supported);
|
|
sipParseConfig[i].hname = SIP_HNAME_TO_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_to);
|
|
sipParseConfig[i].hname = SIP_HNAME_TO;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_to);
|
|
sipParseConfig[i].hname = SIP_HNAME_TIMESTAMP;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_time_stamp);
|
|
sipParseConfig[i].hname = SIP_HNAME_USER_AGENT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_user_agent);
|
|
sipParseConfig[i].hname = SIP_HNAME_UNSUPPORTED;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_unsupported);
|
|
sipParseConfig[i].hname = SIP_HNAME_SUBSCRIPTION_STATE;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_subscription_state);
|
|
sipParseConfig[i].hname = SIP_HNAME_VIA_SHORT;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_via);
|
|
sipParseConfig[i].hname = SIP_HNAME_VIA;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_via);
|
|
sipParseConfig[i].hname = SIP_HNAME_WWW_AUTHENTICATE;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_www_authenticate);
|
|
sipParseConfig[i].hname = SIP_HNAME_MAX_FORWARDS;
|
|
sipParseConfig[i++].setheader = (&sip_message_set_max_forwards);
|
|
|
|
// build up hash table for fast header lookup
|
|
|
|
// initialize the table
|
|
for (i = 0; i < SIP_HASH_TABLE_SIZE; i++)
|
|
{
|
|
sipHdrRefTable[i] = -1; // no entry
|
|
}
|
|
|
|
for (i = 0; i < SIP_MAX_NUM_OF_HEADERS; i++)
|
|
{
|
|
// Calculate hash value using lower case
|
|
hash = sip_hash(sipParseConfig[i].hname);
|
|
hash = hash%SIP_HASH_TABLE_SIZE;
|
|
|
|
while(sipHdrRefTable[hash] != -1)
|
|
{
|
|
hash = (hash+1)%SIP_HASH_TABLE_SIZE;
|
|
if (++count >= SIP_HASH_TABLE_SIZE)
|
|
{
|
|
printf("Conflict with current hash table size\r\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
sipHdrRefTable[hash] = i;
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// improved look-up mechanism
|
|
// precondition: hname is all lowercase
|
|
int sip_message_is_known_header (char *hname)
|
|
{
|
|
unsigned int hash;
|
|
int index;
|
|
int count = 0;
|
|
|
|
hash = sip_hash(hname);
|
|
hash = hash % SIP_HASH_TABLE_SIZE;
|
|
index = sipHdrRefTable[hash];
|
|
|
|
while ((index == -1) || (strcmp(sipParseConfig[index].hname, hname) != 0))
|
|
{
|
|
hash = (hash+1) % SIP_HASH_TABLE_SIZE;
|
|
index = sipHdrRefTable[hash];
|
|
if (++count >= SIP_HASH_TABLE_SIZE)
|
|
return -1;
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
// This method calls the method that is able to parse the header
|
|
int sip_message_call_method(int i, SIP_API_STRUCT *sip, char *hvalue)
|
|
{
|
|
return sipParseConfig[i].setheader(sip, hvalue);
|
|
}
|
|
|
|
int sip_message_set_header(SIP_API_STRUCT *sip, char *hname, char *hvalue)
|
|
{
|
|
int index;
|
|
|
|
if (sip == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_message_set_header: sip is NULL\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (hname == NULL)
|
|
return -1;
|
|
|
|
// some headers are analysed completely
|
|
// this method is used for selective parsing
|
|
index = sip_message_is_known_header(hname);
|
|
if (index >= 0)
|
|
{
|
|
if (sip_message_call_method(index, sip, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "Could not set header: \"%s\" %s\r\n", hname, hvalue);
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Doesn't support unknown header parsing for the moment
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_message_set_multiple_header(SIP_API_STRUCT *sip, char *hname, char *hvalue)
|
|
{
|
|
char *ptr; // current location of the search
|
|
char *comma; // This is the separator we are elooking for
|
|
//char *beg; // beg of a header
|
|
//char *end; // end of a header
|
|
//char *quote1; // first quote of a pair of quotes
|
|
//char *quote2; // second quuote of a pair of quotes
|
|
size_t hname_len;
|
|
|
|
// Find header based upon lowercase comparison
|
|
sip_tolower(hname);
|
|
|
|
if (hvalue == NULL)
|
|
{
|
|
if (sip_message_set_header(sip, hname, hvalue) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
ptr = hvalue;
|
|
comma = strchr(ptr, ',');
|
|
|
|
hname_len = strlen(hname);
|
|
|
|
if (comma == NULL
|
|
|| (hname_len == 4 && strncmp (hname, "date", 4) == 0)
|
|
|| (hname_len == 5 && strncmp (hname, "allow", 5) == 0)
|
|
|| (hname_len == 2 && strncmp (hname, "to", 2) == 0)
|
|
|| (hname_len == 4 && strncmp (hname, "from", 4) == 0)
|
|
|| (hname_len == 3 && strncmp (hname, "via", 3) == 0)
|
|
|| (hname_len == 7 && strncmp (hname, "call-id", 7) == 0)
|
|
|| (hname_len == 4 && strncmp (hname, "cseq", 4) == 0)
|
|
|| (hname_len == 7 && strncmp (hname, "subject", 7) == 0)
|
|
|| (hname_len == 7 && strncmp (hname, "expires", 7) == 0)
|
|
|| (hname_len == 7 && strncmp (hname, "contact", 7) == 0)
|
|
|| (hname_len == 6 && strncmp (hname, "server", 6) == 0)
|
|
|| (hname_len == 9 && strncmp (hname, "supported", 9) == 0)
|
|
|| (hname_len == 6 && strncmp (hname, "accept", 6) == 0)
|
|
|| (hname_len == 11 && strncmp (hname, "unsupported", 11) == 0)
|
|
|| (hname_len == 15 && strncmp (hname, "accept-language", 15) == 0)
|
|
|| (hname_len == 15 && strncmp (hname, "accept-encoding", 15) == 0)
|
|
|| (hname_len == 10 && strncmp (hname, "user-agent", 10) == 0)
|
|
|| (hname_len == 16 && strncmp (hname, "www-authenticate", 16) == 0)
|
|
|| (hname_len == 19 && strncmp (hname, "authentication-info", 19) == 0)
|
|
|| (hname_len == 18 && strncmp (hname, "proxy-authenticate", 18) == 0)
|
|
|| (hname_len == 19 && strncmp (hname, "proxy-authorization", 19) == 0)
|
|
|| (hname_len == 25 && strncmp (hname, "proxy-authentication-info", 25) == 0)
|
|
|| (hname_len == 12 && strncmp (hname, "organization", 12) == 0)
|
|
|| (hname_len == 13 && strncmp (hname, "authorization", 13) == 0)
|
|
|| (hname_len == 12 && strncmp (hname, "max-forwards", 12) == 0)
|
|
|| (hname_len == 12 && strncmp (hname, "content-type", 12) == 0)
|
|
|| (hname_len == 14 && strncmp (hname, "content-length", 14) == 0))
|
|
// there is no multiple header! likely
|
|
// to happen most of the time...
|
|
// or hname is a TEXT-UTF8-TRIM and may
|
|
// contain a comma. this is not a separator
|
|
// THIS DOES NOT WORK FOR UNKNOWN HEADER!!!!
|
|
{
|
|
if ((sip->sipApiType == SIP_API_REQ_MSG)
|
|
&& ((hname_len == 11 && strncmp (hname, "unsupported", 11) == 0)
|
|
|| (hname_len == 6 && strncmp (hname, "server", 6) == 0)))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip request msg have res header\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return 0;
|
|
}
|
|
else if ((sip->sipApiType == SIP_API_RES_MSG)
|
|
&& (((hname_len == 12) && (strncmp (hname, "max-forwards", 12) == 0))
|
|
|| ((hname_len == 13) && (strncmp (hname, "proxy-require", 13) == 0))
|
|
|| ((hname_len == 5) && (strncmp (hname, "route", 5) == 0))
|
|
|| ((hname_len == 7) && (strncmp (hname, "require", 7) == 0))
|
|
// || ((hname_len == 10) && (strncmp (hname, "user-agent", 10) == 0))
|
|
|| ((hname_len == 7) && (strncmp (hname, "subject", 7) == 0))
|
|
|| ((hname_len == 5) && (strncmp (hname, "event", 5) == 0))
|
|
|| ((hname_len == 8) && (strncmp (hname, "refer-to", 8) == 0))
|
|
|| ((hname_len == 18) && (strncmp (hname, "subscription-state", 18) == 0))))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip response msg have req header\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return 0;
|
|
}
|
|
|
|
if ((strncmp (hname, "refer-to", 8) == 0) && ((sip->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] & SIP_HDR_REFER_TO_MASK) == SIP_HDR_REFER_TO_MASK))
|
|
{
|
|
//sip_send_400();
|
|
return -1;
|
|
}
|
|
|
|
if (sip_message_set_header(sip, hname, hvalue) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Doesn't support multiple headers per line for the moment
|
|
return 0;
|
|
}
|
|
|
|
int sip_msg_headers_parse(SIP_API_STRUCT *sip, char *buf, char **body)
|
|
{
|
|
char *colonIndex;
|
|
char hname[64];
|
|
char hvalue[256];
|
|
char *startOfHeader;
|
|
char *endOfHeader;
|
|
char *end;
|
|
WORD len;
|
|
|
|
if ((sip == NULL) || (buf == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_msg_headers_parse: sip or buf is NULL\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
startOfHeader = buf;
|
|
|
|
for (;;)
|
|
{
|
|
if (startOfHeader[0] == '\0')
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "SIP message does not end with CRLFCRLF\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return 0;
|
|
}
|
|
|
|
if (sip_find_next_crlf(startOfHeader, &endOfHeader) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "End of header Not found\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
// the list of headers MUST always end with
|
|
// CRLFCRLF (also CRCR and LFLF are allowed)
|
|
if ((startOfHeader[0] == '\r') || (startOfHeader[0] == '\n'))
|
|
{
|
|
*body = startOfHeader;
|
|
return 0;
|
|
}
|
|
|
|
// find the header name
|
|
colonIndex = strchr(startOfHeader, ':');
|
|
if (colonIndex == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "colon Not found\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
if (colonIndex - startOfHeader + 1 < 2)
|
|
return -1;
|
|
if (endOfHeader <= colonIndex)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "Malformed message\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((len = colonIndex - startOfHeader) > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "header name length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(hname, startOfHeader, len);
|
|
|
|
// END of header is (end_of_header-2) if header separation is CRLF
|
|
// END of header is (end_of_header-1) if header separation is CR or LF
|
|
if ((endOfHeader[-2] == '\r') || (endOfHeader[-2] == '\n'))
|
|
end = endOfHeader - 2;
|
|
else
|
|
end = endOfHeader - 1;
|
|
if ((end - colonIndex) < 2)
|
|
strcpy(hvalue, ""); // some headers (subject) can be empty
|
|
else
|
|
{
|
|
if ((len = end - colonIndex - 1) > 256)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "header value length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(hvalue, colonIndex + 1, len);
|
|
}
|
|
|
|
// hvalue MAY contains multiple value. In this case, they
|
|
// are separated by commas. But, a comma may be part of a
|
|
// quoted-string ("here, and there" is an example where the
|
|
// comma is not a separator!)
|
|
if (sip_message_set_multiple_header(sip, hname, hvalue) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "End of header Not found\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
// continue on the next header
|
|
startOfHeader = endOfHeader;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int sip_msg_start_line_parse_req(SIP_MSG *dest, char *buf, char **nextHeader)
|
|
{
|
|
char *p1, *p2, *hp;
|
|
char tmp[256];
|
|
SIP_START_LINE *startLine;
|
|
WORD len;
|
|
|
|
if ((dest == NULL) || (buf == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_msg_start_line_parse_req: dest or buf is NULL\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
startLine = &dest->sipStartLine;
|
|
*nextHeader = buf;
|
|
|
|
// The first token is the method name
|
|
p2 = strchr(buf, ' ');
|
|
if (p2 == NULL)
|
|
return -1;
|
|
if (*(p2 + 1) == '\0' || *(p2 + 2) == '\0')
|
|
return -1;
|
|
if (p2 - buf == 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "No space is allowed here\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if ((len = p2 - buf) > 256)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "request method length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, buf, len);
|
|
if (sip_method_api_conv(tmp, &startLine->sipMethod, SIP_STR_TO_API) < 0)
|
|
return -2;
|
|
|
|
// The second token is a sip-url or a uri
|
|
p1 = strchr(p2 + 2, ' '); // no space allowed inside sip-url
|
|
if (p1 == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "Uncompliant request-uri\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (p1 - p2 < 2)
|
|
return -1;
|
|
|
|
if ((len = p1 - p2 - 1) > 256)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "request uri length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, p2 + 1, len);
|
|
if (sip_uri_parse(&startLine->requestUri, tmp) < 0)
|
|
return -1;
|
|
|
|
// find the the version and the beginning of headers
|
|
hp = p1;
|
|
while ((*hp != '\r') && (*hp != '\n'))
|
|
{
|
|
if (*hp)
|
|
hp++;
|
|
else
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "No crlf found\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (hp - p1 < 2)
|
|
return -1;
|
|
|
|
if ((len = hp - p1 - 1) > 256)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "request startLine version length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, p1 + 1, len);
|
|
|
|
if (sip_ver_api_conv(tmp, &startLine->sipVersion, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
hp++;
|
|
|
|
if ((*hp) && ('\r' == hp[-1]) && ('\n' == hp[0]))
|
|
hp++;
|
|
|
|
(*nextHeader) = hp;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_msg_start_line_parse_resp(SIP_MSG *dest, char *buf, char **nextHeader)
|
|
{
|
|
char *hp;
|
|
char tmp[128];
|
|
char *statuscode;
|
|
char *reasonphrase;
|
|
BYTE len;
|
|
SIP_START_LINE *startLine;
|
|
|
|
if ((dest == NULL) || (buf == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_msg_start_line_parse_req: dest or buf is NULL\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
startLine = &dest->sipStartLine;
|
|
*nextHeader = buf;
|
|
|
|
statuscode = strchr(buf, ' '); // Search for first SPACE
|
|
if (statuscode == NULL)
|
|
return -1;
|
|
|
|
if ((len = statuscode - buf) > 128)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "response startLine vesion length out of range\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(tmp, buf, len);
|
|
|
|
if (sip_ver_api_conv(tmp, &startLine->sipVersion, SIP_STR_TO_API) < 0)
|
|
return -1;
|
|
|
|
reasonphrase = strchr(statuscode + 1, ' ');
|
|
|
|
if (reasonphrase == NULL)
|
|
return -1;
|
|
|
|
if (sscanf(statuscode + 1, "%d", &startLine->statusCode) != 1)
|
|
return -1;
|
|
|
|
if (startLine->statusCode == 0)
|
|
return -1;
|
|
|
|
hp = reasonphrase;
|
|
while ((*hp != '\r') && (*hp != '\n'))
|
|
{
|
|
if (*hp)
|
|
hp++;
|
|
else
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "No crlf found\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if ((len = hp - reasonphrase - 1) > 128)
|
|
len =128;
|
|
|
|
sip_clrncpy(startLine->reasonPhrase, reasonphrase + 1, len);
|
|
|
|
hp++;
|
|
if ((*hp) && ('\r' == hp[-1]) && ('\n' == hp[0]))
|
|
hp++;
|
|
|
|
(*nextHeader) = hp;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_msg_start_line_parse(SIP_API_STRUCT *dest, char *buf, char **nextHeader)
|
|
{
|
|
int ret;
|
|
|
|
if ((dest == NULL) || (buf == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_msg_start_line_parse: dest or buf is NULL\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (strncmp(buf, "SIP/", 4) == 0)
|
|
{
|
|
dest->sipApiType = SIP_API_RES_MSG;
|
|
if (sip_msg_start_line_parse_resp(&dest->sipApiMsg.sipMsg, buf, nextHeader) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_msg_start_line_parse: parse resp failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dest->sipApiType = SIP_API_REQ_MSG;
|
|
if ((ret = sip_msg_start_line_parse_req(&dest->sipApiMsg.sipMsg, buf, nextHeader)) < 0)
|
|
{
|
|
if (ret == -2)
|
|
{
|
|
//sip_send_allow(buf);
|
|
}
|
|
sprintf((char *)sipAsciTempBuf, "sip_msg_start_line_parse: parse req failed\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return dest->sipApiType;
|
|
}
|
|
|
|
int sip_sub_body_headers_pars(SIP_MESSAGE_BODYS *sipBodys, char *buf, char **body)
|
|
{
|
|
char *colonIndex;
|
|
char hname[64];
|
|
char hvalue[128];
|
|
char *startOfHeader;
|
|
char *endOfHeader;
|
|
char *end;
|
|
BYTE len;
|
|
SIP_CONTENT_TYPE *contentType;
|
|
SIP_CONTENT_DISPOSITION *contentDisposition;
|
|
|
|
if ((sipBodys == NULL) || (buf == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_sub_body_headers_pars: sipBodys or buf is NULL\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
startOfHeader = buf;
|
|
|
|
for (;;)
|
|
{
|
|
if (startOfHeader[0] == '\0')
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "SIP message does not end with CRLFCRLF\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return 0;
|
|
}
|
|
|
|
if (sip_find_next_crlf(startOfHeader, &endOfHeader) < 0)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "End of header Not found\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
// the list of headers MUST always end with
|
|
// CRLFCRLF (also CRCR and LFLF are allowed)
|
|
if ((startOfHeader[0] == '\r') || (startOfHeader[0] == '\n'))
|
|
{
|
|
*body = startOfHeader;
|
|
return 0;
|
|
}
|
|
|
|
// find the header name
|
|
if ((colonIndex = strchr(startOfHeader, ':')) == NULL)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "End of header Not found\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
if (colonIndex - startOfHeader + 1 < 2)
|
|
return -1;
|
|
|
|
if (endOfHeader <= colonIndex)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "Malformed message\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
len = colonIndex - startOfHeader;
|
|
|
|
if (len > 64)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sub body header name length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(hname, startOfHeader, len);
|
|
|
|
// END of header is (end_of_header-2) if header separation is CRLF
|
|
// END of header is (end_of_header-1) if header separation is CR or LF
|
|
if ((endOfHeader[-2] == '\r') || (endOfHeader[-2] == '\n'))
|
|
end = endOfHeader - 2;
|
|
else
|
|
end = endOfHeader - 1;
|
|
|
|
if ((end - colonIndex) < 2)
|
|
strcpy(hvalue, ""); // some headers (subject) can be empty
|
|
else
|
|
{
|
|
len = end - colonIndex - 1;
|
|
|
|
if (len > 128)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sub body header value length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy(hvalue, colonIndex + 1, len);
|
|
}
|
|
|
|
// hvalue MAY contains multiple value. In this case, they
|
|
// are separated by commas. But, a comma may be part of a
|
|
// quoted-string ("here, and there" is an example where the
|
|
// comma is not a separator!)
|
|
if ( (strcasecmp(hname, "c") == 0) || (strcasecmp(hname, "content-type") == 0))
|
|
{
|
|
contentType = &sipBodys->sipBody[sipBodys->sipBodyNum].sipBodyContentType;
|
|
|
|
sip_content_type_parse(contentType, hvalue);
|
|
|
|
sipBodys->sipBody[sipBodys->sipBodyNum].sipBodyHdrFlg[0] |= SIP_HDR_CONTENT_TYPE_MASK;
|
|
}
|
|
else if (strcasecmp(hname, "content-disposition") == 0)
|
|
{
|
|
contentDisposition = &sipBodys->sipBody[sipBodys->sipBodyNum].sipBodyContentDisposition;
|
|
|
|
sip_content_disposition_parse(contentDisposition, hvalue);
|
|
|
|
sipBodys->sipBody[sipBodys->sipBodyNum].sipBodyHdrFlg[0] |= SIP_HDR_CONTENT_DISPOSITION_MASK;
|
|
}
|
|
|
|
// continue on the next header
|
|
startOfHeader = endOfHeader;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int sip_sub_body_parse(SIP_MESSAGE_BODYS *sipBodys, char *buf, char *boundary)
|
|
{
|
|
BYTE boundaryLen;
|
|
char *subBody;
|
|
char *nextBoundary;
|
|
char endBoundary[64] = "";
|
|
|
|
if ((buf == NULL) || (boundary == NULL) || (sipBodys == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "buff boundary or sipBodys is NULL\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
// memset((BYTE *)sipBodys, 0, sizeof(SIP_MESSAGE_BODYS));
|
|
|
|
subBody = buf;
|
|
boundaryLen = strlen(boundary);
|
|
sprintf(endBoundary, "%s--", boundary);
|
|
|
|
if ((strncmp(subBody, boundary, boundaryLen) != 0)
|
|
|| (strncmp(subBody, endBoundary, boundaryLen + 2) == 0) ||(strstr(subBody, endBoundary) == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "malformed message body\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
if (strncmp(subBody, endBoundary, boundaryLen + 2) == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
while (('\r' != *subBody) && ('\n' != *subBody))
|
|
{
|
|
if (*subBody)
|
|
subBody++;
|
|
else
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "Final CRLF is missing\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (('\r' == subBody[0]) && ('\n' == subBody[1]))
|
|
subBody = subBody + 2;
|
|
else
|
|
subBody = subBody + 1;
|
|
|
|
if (((nextBoundary = strstr(subBody, boundary)) == NULL)
|
|
|| (nextBoundary < subBody))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "message end without boundary\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_sub_body_headers_pars(sipBodys, subBody, &subBody);
|
|
|
|
if (nextBoundary-subBody > SIP_MAX_BODY_LEN)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sub body message length is too long\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sip_clrncpy((char *)sipBodys->sipBody[sipBodys->sipBodyNum].msgBody, subBody, nextBoundary-subBody);
|
|
|
|
sipBodys->sipBodyNum++;
|
|
|
|
subBody = nextBoundary;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sip_body_parse(SIP_API_STRUCT *sip, char *buf, WORD len)
|
|
{
|
|
int i;
|
|
char boundary[32];
|
|
SIP_MESSAGE_BODYS *sipBodys;
|
|
SIP_CONTENT_TYPE *contentType;
|
|
WORD contentLength;
|
|
|
|
if ((sip == NULL) || (buf == NULL))
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_body_parse: sip or buf is NULL\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
sipBodys = &sip->sipApiMsg.sipMsg.sipEntity.sipBodys;
|
|
contentType = &sip->sipApiMsg.sipMsg.sipEntity.sipHdrContentType;
|
|
contentLength = sip->sipApiMsg.sipMsg.sipEntity.sipHdrContentLength;
|
|
|
|
if ((contentType->type == SIP_CONTENT_TYPE_APPLICATION)
|
|
&& (contentType->subType == SIP_CONTENT_SUB_TYPE_SDP))
|
|
{
|
|
if (contentLength > len)
|
|
{
|
|
sprintf((char *)sipAsciTempBuf, "sip_body_parse:contentLength wrong\r\n");
|
|
sip_log_err(sipAsciTempBuf);
|
|
return -1;
|
|
}
|
|
|
|
strncpy((char *)sip->sipApiMsg.sipMsg.sipEntity.sipBodys.sipBody[0].msgBody, buf, contentLength + 2);
|
|
sip->sipApiMsg.sipMsg.sipEntity.sipBodys.sipBodyNum = 1;
|
|
|
|
return 0;
|
|
}
|
|
else if ((contentType->type == SIP_CONTENT_TYPE_APPLICATION)
|
|
&& (contentType->subType == SIP_CONTENT_SUB_TYPE_ISUP))
|
|
{
|
|
if (contentLength > len)
|
|
return -1;
|
|
|
|
strncpy((char *)sip->sipApiMsg.sipMsg.sipEntity.sipBodys.sipBody[0].msgBody, buf, contentLength + 2);
|
|
sip->sipApiMsg.sipMsg.sipEntity.sipBodys.sipBodyNum = 1;
|
|
|
|
return 0;
|
|
}
|
|
else if ((contentType->type == SIP_CONTENT_TYPE_MULTIPART)
|
|
&& (contentType->subType == SIP_CONTENT_SUB_TYPE_MIXED))
|
|
{
|
|
if (contentLength > len)
|
|
return -1;
|
|
|
|
for (i = 0; i < contentType->params.paraNum; i++)
|
|
{
|
|
if (contentType->params.para[i].paraName == SIP_API_PNAME_BOUNDARY)
|
|
{
|
|
sprintf(boundary, "--%s", contentType->params.para[i].para.paraStr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
sip_sub_body_parse(sipBodys, buf, boundary);
|
|
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|