issize_t msg_accept_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen)
{
- msg_accept_t *ac = (msg_accept_t *)h;
-
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
-
- if (*s == '\0') {
- /* Empty Accept list is not an error */
- ac->ac_type = ac->ac_subtype = "";
- return 0;
- }
-
- /* "Accept:" #(type/subtyp ; *(parameters))) */
- if (msg_mediatype_d(&s, &ac->ac_type) == -1)
- return -1;
- if (!(ac->ac_subtype = strchr(ac->ac_type, '/')))
- return -1;
- ac->ac_subtype++;
-
- if (*s == ';' && msg_params_d(home, &s, &ac->ac_params) == -1)
- return -1;
+ msg_accept_t *ac;
+
+ for(;;) {
+ ac = (msg_accept_t *)h;
+
+ while (*s == ',') /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
+
+ if (*s == '\0') {
+ /* Empty Accept list is not an error */
+ ac->ac_type = ac->ac_subtype = "";
+ return 0;
+ }
+
+ /* "Accept:" #(type/subtyp ; *(parameters))) */
+ if (msg_mediatype_d(&s, &ac->ac_type) == -1)
+ return -1;
+ if (!(ac->ac_subtype = strchr(ac->ac_type, '/')))
+ return -1;
+ ac->ac_subtype++;
+
+ if (*s == ';' && msg_params_d(home, &s, &ac->ac_params) == -1)
+ return -1;
+
+ msg_parse_next_field_without_recursion();
+ }
- return msg_parse_next_field(home, h, s, slen);
}
issize_t msg_accept_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
char *s, isize_t slen)
{
/** @relatesalso msg_accept_any_s */
- msg_accept_any_t *aa = (msg_accept_any_t *)h;
+ msg_accept_any_t *aa;
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
+ for(;;) {
+ aa = (msg_accept_any_t *)h;
+ while (*s == ',') /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
- if (*s == '\0')
- return -2; /* Empty list */
+ if (*s == '\0')
+ return -2; /* Empty list */
- /* "Accept-*:" 1#(token *(SEMI accept-param)) */
- if (msg_token_d(&s, &aa->aa_value) == -1)
- return -1;
+ /* "Accept-*:" 1#(token *(SEMI accept-param)) */
+ if (msg_token_d(&s, &aa->aa_value) == -1)
+ return -1;
- if (*s == ';' && msg_params_d(home, &s, &aa->aa_params) == -1)
- return -1;
+ if (*s == ';' && msg_params_d(home, &s, &aa->aa_params) == -1)
+ return -1;
+
+ msg_parse_next_field_without_recursion();
+ }
- return msg_parse_next_field(home, h, s, slen);
}
/** Encode an Accept-* header field. */
issize_t msg_warning_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen)
{
- msg_warning_t *w = (msg_warning_t *)h;
+ msg_warning_t *w;
char *text;
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
-
- /* Parse protocol */
- if (!IS_DIGIT(*s))
- return -1;
- w->w_code = strtoul(s, &s, 10);
- skip_lws(&s);
-
- /* Host (and port) */
- if (msg_hostport_d(&s, &w->w_host, &w->w_port) == -1)
- return -1;
- if (msg_quoted_d(&s, &text) == -1)
- return -1;
- if (msg_unquote(text, text) == NULL)
- return -1;
-
- w->w_text = text;
+ for(;;) {
+ w = (msg_warning_t *)h;
+ while (*s == ',') /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
+
+ /* Parse protocol */
+ if (!IS_DIGIT(*s))
+ return -1;
+ w->w_code = strtoul(s, &s, 10);
+ skip_lws(&s);
+
+ /* Host (and port) */
+ if (msg_hostport_d(&s, &w->w_host, &w->w_port) == -1)
+ return -1;
+ if (msg_quoted_d(&s, &text) == -1)
+ return -1;
+ if (msg_unquote(text, text) == NULL)
+ return -1;
+
+ w->w_text = text;
+
+ msg_parse_next_field_without_recursion();
+ }
- return msg_parse_next_field(home, h, s, slen);
}
issize_t msg_warning_e(char b[], isize_t bsiz, msg_header_t const *h, int f)
return h;
}
+
/** Complete this header field and parse next header field.
*
* This function completes parsing a multi-field header like @Accept,
return hc->hc_parse(home, h, s, end - s);
}
+
/** Decode a message header. */
msg_header_t *msg_header_d(su_home_t *home, msg_t const *msg, char const *b)
{
SOFIAPUBFUN issize_t msg_parse_next_field(su_home_t *home, msg_header_t *prev,
char *s, isize_t slen);
+#define msg_parse_next_field_without_recursion() { \
+ msg_header_t *prev = h; \
+ msg_hclass_t *hc = prev->sh_class; \
+ char *end = s + slen; \
+ \
+ if (*s && *s != ',') \
+ return -1; \
+ \
+ if (msg_header_update_params(prev->sh_common, 0) < 0) \
+ return -1; \
+ \
+ while (*s == ',') \
+ *s = '\0', s += span_lws(s + 1) + 1; \
+ \
+ if (*s == 0) \
+ return 0; \
+ \
+ h = msg_header_alloc(home, hc, 0); \
+ if (!h) \
+ return -1; \
+ \
+ prev->sh_succ = h, h->sh_prev = &prev->sh_succ; \
+ prev->sh_next = h; \
+ slen = end - s; \
+ }
+
+
+
/** Terminate encoding. @HI */
#define MSG_TERM_E(p, e) ((p) < (e) ? (p)[0] = '\0' : '\0')
char *s,
isize_t slen)
{
- sip_contact_t *m = (sip_contact_t *)h;
+ sip_contact_t *m;
assert(h);
+ for(;;) {
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
+ m = (sip_contact_t *)h;
- if (sip_name_addr_d(home, &s, &m->m_display, m->m_url,
- &m->m_params, &m->m_comment) == -1)
- return -1;
+ while (*s == ',') /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
+
+ if (sip_name_addr_d(home, &s, &m->m_display, m->m_url,
+ &m->m_params, &m->m_comment) == -1)
+ return -1;
+
+ msg_parse_next_field_without_recursion();
+ }
- return msg_parse_next_field(home, h, s, slen);
}
char *s,
isize_t slen)
{
- sip_route_t *r = (sip_route_t *)h;
+ sip_route_t *r;
+
assert(h);
+ for (;;) {
+ r = (sip_route_t *)h;
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
+ while (*s == ',') { /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
+ }
- if (sip_name_addr_d(home, &s, &r->r_display,
- r->r_url, &r->r_params, NULL) < 0)
- return -1;
+ if (sip_name_addr_d(home, &s, &r->r_display, r->r_url, &r->r_params, NULL) < 0) {
+ return -1;
+ }
+
+ msg_parse_next_field_without_recursion();
+ }
- return msg_parse_next_field(home, h, s, slen);
}
issize_t sip_any_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
issize_t sip_via_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
- sip_via_t *v = (sip_via_t *)h;
+ sip_via_t *v;
assert(h);
-
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
-
- /* sent-protocol sent-by *( ";" via-params ) [ comment ] */
-
- /* Parse protocol */
- if (sip_transport_d(&s, &v->v_protocol) == -1)
- return -1;
- /* Host (and port) */
- if (msg_hostport_d(&s, &v->v_host, &v->v_port) == -1)
- return -1;
- /* Parameters */
- if (*s == ';' && msg_params_d(home, &s, &v->v_params) == -1)
- return -1;
- /* Comment */
- if (*s == '(' && msg_comment_d(&s, &v->v_comment) == -1)
- return -1;
-
- return msg_parse_next_field(home, h, s, slen);
+ for (;;) {
+ v = (sip_via_t *)h;
+
+ while (*s == ',') /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
+
+ /* sent-protocol sent-by *( ";" via-params ) [ comment ] */
+
+ /* Parse protocol */
+ if (sip_transport_d(&s, &v->v_protocol) == -1)
+ return -1;
+ /* Host (and port) */
+ if (msg_hostport_d(&s, &v->v_host, &v->v_port) == -1)
+ return -1;
+ /* Parameters */
+ if (*s == ';' && msg_params_d(home, &s, &v->v_params) == -1)
+ return -1;
+ /* Comment */
+ if (*s == '(' && msg_comment_d(&s, &v->v_comment) == -1)
+ return -1;
+
+ msg_parse_next_field_without_recursion();
+ }
}
issize_t sip_via_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
issize_t sip_caller_prefs_d(su_home_t *home, sip_header_t *h,
char *s, isize_t slen)
{
- sip_caller_prefs_t *cp = (sip_caller_prefs_t *)h;
- url_t url[1];
- char const *ignore = NULL;
- int kludge = 0;
-
- assert(h);
-
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
-
- /* Kludge: support PoC IS spec with a typo... */
- if (su_casenmatch(s, "*,", 2))
- s[1] = ';', kludge = 0;
- else if (s[0] != '*' && s[0] != '<') {
- /* Kludge: missing URL - */
- size_t n = span_attribute_value(s);
- kludge = n > 0 && (s[n] == '\0' || s[n] == ',' || s[n] == ';');
- }
-
- if (kludge) {
- if (msg_any_list_d(home, &s, (msg_param_t **)&cp->cp_params,
- msg_attribute_value_scanner, ';') == -1)
- return -1;
- }
- /* Parse params (and ignore display name and url) */
- else if (sip_name_addr_d(home, &s, &ignore, url, &cp->cp_params, NULL)
- == -1)
- return -1;
- /* Be liberal... */
- /* if (url->url_type != url_any)
- return -1; */
-
- return msg_parse_next_field(home, h, s, slen);
+ for(;;) {
+ sip_caller_prefs_t *cp = (sip_caller_prefs_t *)h;
+ url_t url[1];
+ char const *ignore = NULL;
+ int kludge = 0;
+
+ assert(h);
+
+ while (*s == ',') /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
+
+ /* Kludge: support PoC IS spec with a typo... */
+ if (su_casenmatch(s, "*,", 2))
+ s[1] = ';', kludge = 0;
+ else if (s[0] != '*' && s[0] != '<') {
+ /* Kludge: missing URL - */
+ size_t n = span_attribute_value(s);
+ kludge = n > 0 && (s[n] == '\0' || s[n] == ',' || s[n] == ';');
+ }
+
+ if (kludge) {
+ if (msg_any_list_d(home, &s, (msg_param_t **)&cp->cp_params,
+ msg_attribute_value_scanner, ';') == -1)
+ return -1;
+ }
+ /* Parse params (and ignore display name and url) */
+ else if (sip_name_addr_d(home, &s, &ignore, url, &cp->cp_params, NULL)
+ == -1)
+ return -1;
+ /* Be liberal... */
+ /* if (url->url_type != url_any)
+ return -1; */
+ msg_parse_next_field_without_recursion();
+ }
+
}
static
#define MSG_PUB_T struct sip_s
#define MSG_HDR_T union sip_header_u
+
#include "sofia-sip/sip_parser.h"
#include "sofia-sip/sip_extra.h"
+#include "../su/sofia-sip/su_alloc.h"
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
-
+#
#include <assert.h>
/* ====================================================================== */
sip_call_info_t *ci = h->sh_call_info;
char *end = s + slen;
- assert(h);
+ for(;;) {
+ ci = h->sh_call_info;
+ end = s + slen;
- while (*s == ',')
- s += span_lws(s + 1) + 1;
+ while (*s == ',')
+ s += span_lws(s + 1) + 1;
- if (sip_name_addr_d(home, &s, NULL, ci->ci_url, &ci->ci_params, NULL) < 0)
- return -1;
+ if (sip_name_addr_d(home, &s, NULL, ci->ci_url, &ci->ci_params, NULL) < 0)
+ return -1;
- /* Recurse */
- return msg_parse_next_field(home, h, s, end - s);
+ slen = end - s;
+ msg_parse_next_field_without_recursion();
+ }
}
isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset)
issize_t sip_remote_party_id_d(su_home_t *home, sip_header_t *h,
char *s, isize_t slen)
{
- sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)h;
+ sip_remote_party_id_t *rpid;
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
+ for(;;) {
+ rpid = (sip_remote_party_id_t *)h;
- if (sip_name_addr_d(home, &s,
- &rpid->rpid_display,
- rpid->rpid_url,
- &rpid->rpid_params, NULL) == -1)
- return -1;
+ while (*s == ',') /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
+
+ if (sip_name_addr_d(home, &s,
+ &rpid->rpid_display,
+ rpid->rpid_url,
+ &rpid->rpid_params, NULL) == -1)
+ return -1;
+
+ msg_parse_next_field_without_recursion();
+ }
- return msg_parse_next_field(home, h, s, slen);
}
issize_t sip_remote_party_id_e(char b[], isize_t bsiz,
issize_t sip_p_asserted_identity_d(su_home_t *home, sip_header_t *h,
char *s, isize_t slen)
{
- sip_p_asserted_identity_t *paid = (sip_p_asserted_identity_t *)h;
+ sip_p_asserted_identity_t *paid;
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
+ for(;;) {
+ paid = (sip_p_asserted_identity_t *)h;
+ while (*s == ',') /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
- if (sip_name_addr_d(home, &s,
- &paid->paid_display,
- paid->paid_url,
- NULL, NULL) == -1)
- return -1;
+ if (sip_name_addr_d(home, &s,
+ &paid->paid_display,
+ paid->paid_url,
+ NULL, NULL) == -1)
+ return -1;
+
+ msg_parse_next_field_without_recursion();
+ }
- return msg_parse_next_field(home, h, s, slen);
}
issize_t sip_p_asserted_identity_e(char b[], isize_t bsiz,
issize_t sip_accept_disposition_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
- sip_accept_disposition_t *ad = (sip_accept_disposition_t *)h;
+ sip_accept_disposition_t *ad;
- assert(h);
+ assert(h);
- /* Ignore empty entries (comma-whitespace) */
- while (*s == ',')
- s += span_lws(s + 1) + 1;
+ for(;;) {
+ ad = (sip_accept_disposition_t *)h;
+ /* Ignore empty entries (comma-whitespace) */
+ while (*s == ',')
+ s += span_lws(s + 1) + 1;
- /* "Accept:" #(type/subtyp ; *(parameters))) */
- if (/* Parse protocol */
- sip_version_d(&s, &ad->ad_type) == -1 ||
- (ad->ad_subtype = strchr(ad->ad_type, '/')) == NULL ||
- (*s == ';' && msg_params_d(home, &s, &ad->ad_params) == -1))
- return -1;
+ /* "Accept:" #(type/subtyp ; *(parameters))) */
+ if (/* Parse protocol */
+ sip_version_d(&s, &ad->ad_type) == -1 ||
+ (ad->ad_subtype = strchr(ad->ad_type, '/')) == NULL ||
+ (*s == ';' && msg_params_d(home, &s, &ad->ad_params) == -1))
+ return -1;
- if (ad->ad_subtype) ad->ad_subtype++;
+ if (ad->ad_subtype) ad->ad_subtype++;
+
+ msg_parse_next_field_without_recursion();
+ }
- return msg_parse_next_field(home, h, s, slen);
}
issize_t sip_accept_disposition_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
issize_t sip_reason_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
- sip_reason_t *re = (sip_reason_t *)h;
- size_t n;
+ sip_reason_t *re;
+ size_t n;
+ for (;;) {
+ re = (sip_reason_t *)h;
+
+ while (*s == ',') /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
+
+ re->re_protocol = s;
+ if ((n = span_token(s)) == 0)
+ return -1;
+ s += n; while (IS_LWS(*s)) *s++ = '\0';
+ if (*s == ';' && msg_params_d(home, &s, &re->re_params) < 0)
+ return -1;
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
+ msg_parse_next_field_without_recursion();
+ }
- re->re_protocol = s;
- if ((n = span_token(s)) == 0)
- return -1;
- s += n; while (IS_LWS(*s)) *s++ = '\0';
- if (*s == ';' && msg_params_d(home, &s, &re->re_params) < 0)
- return -1;
- return msg_parse_next_field(home, h, s, slen);
}
issize_t sip_reason_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
static
issize_t sip_security_agree_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
- sip_security_agree_t *sa = (sip_security_agree_t *)h;
- isize_t n;
+ for (;;) {
+ sip_security_agree_t *sa = (sip_security_agree_t *)h;
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
+ isize_t n;
- if ((n = span_token(s)) == 0)
- return -1;
- sa->sa_mec = s; s += n; while (IS_LWS(*s)) *s++ = '\0';
- if (*s == ';' && msg_params_d(home, &s, &sa->sa_params) < 0)
- return -1;
+ while (*s == ',') /* Ignore empty entries (comma-whitespace) */
+ *s = '\0', s += span_lws(s + 1) + 1;
+
+ if ((n = span_token(s)) == 0)
+ return -1;
+ sa->sa_mec = s; s += n; while (IS_LWS(*s)) *s++ = '\0';
+ if (*s == ';' && msg_params_d(home, &s, &sa->sa_params) < 0)
+ return -1;
+
+ msg_parse_next_field_without_recursion();
+ }
- return msg_parse_next_field(home, h, s, slen);
}
static