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