Files
svc.ems/plat/sip/src/sip_msg_parse.c
2024-09-27 15:39:34 +08:00

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;
}