⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msg_parser.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
  case msg_kind_single:  case msg_kind_list:    old = (*hh);    break;  case msg_kind_append:  case msg_kind_apndlist:    while (*hh)      hh = &(*hh)->sh_next;    break;  case msg_kind_prepend:    for (end = h; end->sh_next; end = end->sh_next)      ;    end->sh_next = *hh;  }  if (*head) {    /* Insert into existing fragment chain */    msg_insert_chain(msg, pub, msg_is_prepend(h), head, h);    /* Remove replaced fragment */    if (old)      msg_chain_remove(msg, old);  }  /* Insert into header list */  *hh = h;  return 0;}/**Prepend a (list of) header(s) to the header structure and fragment chain. * * The function @c msg_header_prepend() adds a header or list of headers into * the given place within the message structure. It also inserts the headers * into the the message fragment chain, if it exists. * * Unlike msg_header_add(), msg_header_prepend() always inserts header @a h * before other headers of the same class. If the header is a singleton, * existing headers of the same class are removed. If the header is a list * header, the values in the new header are prepended to the existing list. * * @param msg message owning the fragment chain * @param pub public message structure * @param hh  place in message structure to which header is added * @param h   list of header(s) to be added */int msg_header_prepend(msg_t *msg,		       msg_pub_t *pub,		       msg_header_t **hh,		       msg_header_t *h){  msg_header_t **head, *old = NULL, *end;  assert(msg && pub);  if (msg == NULL || h == NULL || h == MSG_HEADER_NONE || hh == NULL)    return -1;  if (pub == NULL)    pub = msg->m_object;  head = _msg_chain_head(msg);  if (*head) {    msg_header_t *sh, **prev;    for (sh = h, prev = NULL; sh; sh = sh->sh_next) {      sh->sh_succ = sh->sh_next;      sh->sh_prev = prev;      prev = &sh->sh_succ;    }  }  switch (h->sh_class->hc_kind) {  case msg_kind_single:  case msg_kind_list:    old = (*hh);    break;  case msg_kind_append:  case msg_kind_apndlist:  case msg_kind_prepend:    for (end = h; end->sh_next; end = end->sh_next)      ;    end->sh_next = *hh;    break;  }  if (*head) {    /* Insert into existing fragment chain */    msg_insert_chain(msg, pub, 1, head, h);    /* Remove replaced fragment */    if (old)      msg_chain_remove(msg, old);  }  /* Insert into header list */  *hh = h;  return 0;}/** Find place to insert header of the class @a hc. */msg_header_t **msg_hclass_offset(msg_mclass_t const *mc, msg_pub_t const *mo, msg_hclass_t *hc){  int i;  assert(mc && hc);  if (mc == NULL || hc == NULL)    return NULL;  if (hc->hc_hash > 0) {    unsigned j, N = mc->mc_hash_size;    for (j = hc->hc_hash % N; mc->mc_hash[j].hr_class; j = (j + 1) % N)      if (mc->mc_hash[j].hr_class == hc) {	return (msg_header_t **)((char *)mo + mc->mc_hash[j].hr_offset);      }  }  else    /* Header has no name. */    for (i = 0; i <= 6; i++)      if (hc->hc_hash == mc->mc_request[i].hr_class->hc_hash)	return (msg_header_t **)((char *)mo + mc->mc_request[i].hr_offset);  return NULL;}/** Append a parsed header object into the message structure */static inline voidappend_parsed(msg_t *msg, msg_pub_t *mo, msg_header_t **hh, msg_header_t *h,	      int always_into_chain){  assert(msg); assert(hh); assert(hh != (void *)mo);  if (msg->m_chain || always_into_chain)    msg_insert_here_in_chain(msg, msg_chain_tail(msg), h);  if (*hh && msg_is_single(h)) {    /* If there is multiple instances of single headers,       put the extra headers into the list of erroneous headers */    hh = (msg_header_t**)&mo->msg_error;    /* Flag this as fatal error */    mo->msg_flags |= MSG_FLG_ERROR;  }  while (*hh)    hh = &(*hh)->sh_next;  *hh = h;}/**Duplicate and add a (list of) header(s) to the message. * * The function @c msg_header_add_dup() duplicates and adds a (list of) * header(s) into a message structure. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status).  Other * headers are inserted after the request or status. * * If the header is a singleton, existing headers with the same class are * removed. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param src list of header(s) to be added */int msg_header_add_dup(msg_t *msg,		       msg_pub_t *pub,		       msg_header_t const *src){  msg_header_t *h, **hh = NULL;  msg_hclass_t *hc = NULL;  if (msg == NULL)    return -1;  if (src == NULL || src == MSG_HEADER_NONE)    return 0;  if (pub == NULL)    pub = msg->m_object;  for ( ;src; src = src->sh_next) {    assert(src->sh_class);    if (!src->sh_class)      return -1;    if (hc != src->sh_class)      hh = msg_hclass_offset(msg->m_class, pub, hc = src->sh_class);    if (hh == NULL)      return -1;    if (!*hh || hc->hc_kind != msg_kind_list) {      int size = hc->hc_size;      int xtra = hc->hc_dxtra(src, size) - size;      char *end;      if (!(h = msg_header_alloc(msg_home(msg), hc, xtra)))	return -1;			/* error */      if (!(end = hc->hc_dup_one(h, src, (char *)h + size, xtra)))	return -1;			/* error */      if (hc->hc_update)	msg_header_update_params(h->sh_common, 0);      assert(end == (char *)h + size + xtra);      if (msg_header_add(msg, pub, hh, h) < 0)	return -1;      hh = &h->sh_next;    }    else {      /* Add list items */      msg_header_t *h = *hh;      msg_param_t **d, **s;      d = msg_header_params(h->sh_common); assert(d);      s = msg_header_params(src->sh_common);      if (!s || !*s)	return 0;      msg_fragment_clear(h->sh_common);      /* Remove empty headers */      for (hh = &h->sh_next; *hh; *hh = (*hh)->sh_next)	msg_chain_remove(msg, *hh);      if (msg_params_join(msg_home(msg), d, *s, 2 /* prune case */, 1) < 0)	return -1;    }  }  if (src)    return -1;  return 0;}/**Duplicate a header as a given type and add the duplicate into message. * * The function @c msg_header_add_dup_as() duplicates a header as a instance * of the given header class. It adds the new copy into the message. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status).  Other * headers are inserted after the request or status. * * If the header is a singleton, existing headers with the same class are * removed. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param hc  header class for header target type * @param src list of header(s) to be duplicated and added */int msg_header_add_dup_as(msg_t *msg,			  msg_pub_t *pub,			  msg_hclass_t *hc,			  msg_header_t const *src){  if (msg == NULL || hc == NULL)    return -1;  if (src == NULL || src == MSG_HEADER_NONE)    return 0;  if (pub == NULL)    pub = msg->m_object;  return _msg_header_add_dup_as(msg, pub, hc, src);}/** Duplicate and add a (list of) header to a message */staticint _msg_header_add_dup_as(msg_t *msg,			   msg_pub_t *pub,			   msg_hclass_t *hc,			   msg_header_t const *src){  msg_header_t *h, **hh;  hh = msg_hclass_offset(msg->m_class, pub, hc);  if (hh == NULL)    return -1;  if (*hh && hc->hc_kind == msg_kind_list) {    /* Add list items */    msg_header_t *h = *hh;    msg_param_t **d, **s;    d = msg_header_params(h->sh_common); assert(d);    s = msg_header_params(src->sh_common);    if (!s || !*s)      return 0;    msg_fragment_clear(h->sh_common);    /* Remove empty headers */    for (hh = &h->sh_next; *hh; *hh = (*hh)->sh_next)      msg_chain_remove(msg, *hh);    return msg_params_join(msg_home(msg), d, *s, 2 /* prune case */, 1);  }  if (!(h = msg_header_dup_as(msg_home(msg), hc, src)))    return -1;  return msg_header_add(msg, pub, hh, h);}/** Parse a string as a given header field and add result to the message. */int msg_header_add_make(msg_t *msg,			msg_pub_t *pub,			msg_hclass_t *hc,			char const *s){  msg_header_t *h, **hh;  if (msg == NULL)    return -1;  if (pub == NULL)    pub = msg->m_object;  hh = msg_hclass_offset(msg->m_class, pub, hc);  if (hh == NULL)    return -1;  if (!s)    return 0;  if (*hh && hc->hc_kind == msg_kind_list) {    /* Add list items */    msg_header_t *h = *hh;    msg_param_t **d;    char *s0;    skip_lws(&s);    d = msg_header_params(h->sh_common); assert(d);    msg_fragment_clear(h->sh_common);    /* Remove empty headers */    for (hh = &h->sh_next; *hh; *hh = (*hh)->sh_next)      msg_chain_remove(msg, *hh);    s0 = su_strdup(msg_home(msg), s);    if (!s0 || msg_commalist_d(msg_home(msg), &s0, d, msg_token_scan) < 0)      return -1;    return 0;  }  if (!(h = msg_header_make(msg_home(msg), hc, s)))    return -1;  return msg_header_add(msg, pub, hh, h);}/** Parse a string and add resulting headers to the message. * * The function @a msg_header_add_str() parses a string and adds resulting * header objects to the message object. */int msg_header_add_str(msg_t *msg,		       msg_pub_t *pub,		       char const *str){  char *s;  if (!msg)    return -1;  if (pub == NULL)    pub = msg->m_object;  if (!str)    return 0;  s = su_strdup(msg_home(msg), str);  if (s) {    int ssiz = strlen(s), used = 0, n = 1;    while (ssiz > used) {      if (IS_CRLF(s[used]))	break;      n = msg_extract_header(msg, pub, s + used, ssiz - used, 1);      if (n <= 0)	break;      used += n;    }    if (n > 0 && ssiz > used) {      used += CRLF_TEST(s + used);      if (ssiz > used)	msg_extract_payload(msg, pub, NULL, ssiz - used,			    s + used, ssiz - used, 1);    }    if (n <= 0)      return -1;    return 0;  }  return -1;}/** Insert a (list of) header(s) to the fragment chain. * * The function @c msg_header_insert() inserts header or list of headers * into a message structure.  It also inserts them into the the message * fragment chain, if it exists. * * When inserting headers into the fragment chain, a request (or status) is * inserted first and replaces the existing request (or status).  Other * headers are inserted after the request or status. * * If the header is a singleton, existing headers with the same class are * removed. * * @param msg message object owning the fragment chain * @param pub public message structure to which header is added * @param h   list of header(s) to be added */int msg_header_insert(msg_t *msg, msg_pub_t *pub, msg_header_t *h){  msg_header_t **hh;  assert(msg);  if (msg == NULL || h == NULL || h == MSG_HEADER_NONE ||       h->sh_class == NULL)    return -1;  if (pub == NULL)    pub = msg->m_object;  hh = msg_hclass_offset(msg->m_class, pub, h->sh_class);  return msg_header_add(msg, pub, hh, h);}/**Remove a header from the header structure and fragment chain. * * The function @c msg_header_remove() removes a header from a message * structure.  It also removes the message from the message fragment chain * and clears the encoding of other headers objects that share same * encoding. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param h   header to be removed */int msg_header_remove(msg_t *msg, msg_pub_t *pub, msg_header_t *h){  msg_header_t **hh, **hh0;  if (msg == NULL || h == NULL || h == MSG_HEADER_NONE ||       h->sh_class == NULL)    return -1;  if (pub == NULL)    pub = msg->m_object;  /* First, remove from public structure (msg_pub_t) */  hh0 = msg_hclass_offset(msg->m_class, pub, h->sh_class);  if (!hh0)    return -1;  for (hh = hh0; *hh; hh = &(*hh)->sh_next) {    if (*hh == h) {      *hh = h->sh_next;      break;    }  }  if (h->sh_data) {    void const *data = (char *)h->sh_data + h->sh_len;    for (hh = hh0; *hh; hh = &(*hh)->sh_next) {      if (data == (char *)(*hh)->sh_data + (*hh)->sh_len) {	(*hh)->sh_data = NULL, (*hh)->sh_len = 0;      }    }  }  msg_chain_remove(msg, h);  return 0;}/**Remove a header list from the header structure and fragment chain. * * The function @c msg_header_remove_all() removes a list of headers from a * message structure. It also removes the message from the message fragment * chain and clears the encoding of other headers objects that share same * encoding. * * @param msg message owning the fragment chain * @param pub public message structure to which header is added * @param h   header list to be removed */int msg_header_remove_all(msg_t *msg, msg_pub_t *pub, msg_header_t *h){  msg_header_t **hh, **hh0;  void const *data;  if (msg == NULL || h == NULL || h == MSG_HEADER_NONE ||       h->sh_class == NULL)    return -1;  if (pub == NULL)    pub = msg->m_object;  hh0 = msg_hclass_offset(msg->m_class, pub, h->sh_class);  if (!hh0)    return -1;  data = (char *)h->sh_data + h->sh_len;  /* First, remove from public structure (msg_pub_t) */  for (hh = hh0; *hh; hh = &(*hh)->sh_next) {    if (*hh == h) {      break;    }    if (data && data == (char *)(*hh)->sh_data + (*hh)->sh_len) {      h->sh_data = NULL, h->sh_len = 0;      (*hh)->sh_data = NULL, (*hh)->sh_len = 0;    }  }  /* Remove from header chain */  while (h) {    h->sh_data = NULL, h->sh_len = 0;    msg_chain_remove(msg, h);    h = h->sh_nex

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -