/** Parse SIP version. * * Parse a SIP version string. Update the * pointer at @a ss to first non-LWS character after the version string. * * @param ss string to be parsed [IN/OUT] * @param ver value result for version [OUT] * * @retval 0 when successful, * @retval -1 upon an error. */ int sip_version_d(char **ss, char const **ver) { char *s = *ss; char const *result; size_t const version_size = sizeof(sip_version_2_0) - 1; if (su_casenmatch(s, sip_version_2_0, version_size) && !IS_TOKEN(s[version_size])) { result = sip_version_2_0; s += version_size; } else { /* Version consists of two tokens, separated by / */ size_t l1 = 0, l2 = 0, n; result = s; l1 = span_token(s); for (n = l1; IS_LWS(s[n]); n++) {} if (s[n] == '/') { for (n++; IS_LWS(s[n]); n++) {} l2 = span_token(s + n); n += l2; } if (l1 == 0 || l2 == 0) return -1; /* If there is extra ws between tokens, compact version */ if (n > l1 + 1 + l2) { s[l1] = '/'; memmove(s + l1 + 1, s + n - l2, l2); s[l1 + 1 + l2] = 0; /* Compare again with compacted version */ if (su_casematch(s, sip_version_2_0)) result = sip_version_2_0; } s += n; } while (IS_WS(*s)) *s++ = '\0'; *ss = s; if (ver) *ver = result; return 0; }
static size_t span_attribute_value(char *s) { size_t n; n = span_token_lws(s); if (n > 0 && s[n] == '=') { n += 1 + span_lws(s + n + 1); if (s[n] == '"') n += span_quoted(s + n); else n += span_token(s + n); n += span_lws(s + n); } return n; }
/** Set various outbound and nat-traversal related options. */ int outbound_set_options(outbound_t *ob, char const *_options, unsigned interval, unsigned stream_interval) { struct outbound_prefs prefs[1] = {{ 0 }}; char *s, *options = su_strdup(NULL, _options); int invalid; prefs->interval = interval; prefs->stream_interval = stream_interval; #define MATCH(v) (len == sizeof(#v) - 1 && su_casenmatch(#v, s, len)) if (options) { for (s = options; s[0]; s++) if (s[0] == '-') s[0] = '_'; } prefs->gruuize = 1; prefs->outbound = 0; prefs->natify = 1; prefs->okeepalive = -1; prefs->validate = 1; prefs->use_rport = 1; for (s = options; s && s[0]; ) { size_t len = span_token(s); int value = 1; if (len > 3 && su_casenmatch(s, "no_", 3)) value = 0, s += 3, len -= 3; else if (len > 4 && su_casenmatch(s, "not_", 4)) value = 0, s += 4, len -= 4; if (len == 0) break; else if (MATCH(gruuize)) prefs->gruuize = value; else if (MATCH(outbound)) prefs->outbound = value; else if (MATCH(natify)) prefs->natify = value; else if (MATCH(validate)) prefs->validate = value; else if (MATCH(options_keepalive)) prefs->okeepalive = value; else if (MATCH(use_connect)) prefs->use_connect = value; else if (MATCH(use_rport)) prefs->use_rport = value; else if (MATCH(use_socks)) prefs->use_socks = value; else if (MATCH(use_upnp)) prefs->use_upnp = value; else if (MATCH(use_stun)) prefs->use_stun = value; else SU_DEBUG_1(("outbound(%p): unknown option \"%.*s\"\n", (void *)ob->ob_owner, (int)len, s)); s += len; len = strspn(s, " \t\n\r,;"); if (len == 0) break; s += len; } invalid = s && s[0]; if (invalid) SU_DEBUG_1(("outbound(%p): invalid options \"%s\"\n", (void *)ob->ob_owner, options)); su_free(NULL, options); if (invalid) return -1; if (prefs->natify && !(prefs->outbound || prefs->use_connect || prefs->use_rport || prefs->use_socks || prefs->use_upnp || prefs->use_stun)) { SU_DEBUG_1(("outbound(%p): no nat traversal method given\n", (void *)ob->ob_owner)); } ob->ob_prefs = *prefs; ob->ob_reg_id = prefs->outbound ? 1 : 0; return 0; }