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

📄 msg_parser.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 5 页
字号:
int msg_header_e(char b[], int bsiz, msg_header_t const *h, int flags){  int n, m;  assert(h); assert(h->sh_class);  if (h == NULL || h->sh_class == NULL)    return -1;  n = msg_header_name_e(b, bsiz, h, flags);  m = h->sh_class->hc_print(b + n, bsiz > n ? bsiz - n : 0, h, flags);  if (h->sh_class->hc_name) {    /* Ordinary header */    if (bsiz > n + m + strlen(CRLF))      strcpy(b + n + m, CRLF);    return n + m + strlen(CRLF);  }  else    return m;}/** Encode header name */static inlineintmsg_header_name_e(char b[], int bsiz, msg_header_t const *h, int flags){  int compact = MSG_IS_COMPACT(flags);  char const *name;  int n, n2;  if (compact && h->sh_class->hc_short[0])    name = h->sh_class->hc_short, n = 1;  else    name = h->sh_class->hc_name, n = h->sh_class->hc_len;  if (!name || !name[0])    return 0;  n2 = compact ? n + 1 : n + 2;  if (n2 < bsiz) {    memcpy(b, name, n);    b[n++] = ':';    if (!compact)      b[n++] = ' ';    b[n++] = '\0';  }  return n2;}/* ====================================================================== *//* Handling header chain */static inline void serialize_first(msg_t *msg, msg_header_t *h);static msg_header_t **serialize_one(msg_t *msg, msg_header_t *h,				    msg_header_t **prev);/** Return head of the fragment chain */msg_header_t **msg_chain_head(msg_t const *msg){  return msg ? (msg_header_t **)&msg->m_chain : NULL;}static inline msg_header_t **_msg_chain_head(msg_t const *msg){  return msg ? (msg_header_t **)&msg->m_chain : NULL;}/** Return tail of the fragment chain */static inline msg_header_t **msg_chain_tail(msg_t const *msg){  return msg ? msg->m_tail : NULL;}/** Serialize headers into the fragment chain. * * The msg_serialize() collects the headers and other message components in * the fragment chain. It should be called before msg_prepare(). * * @relates msg_s * * @param msg pointer to message object * @param pub public message structure * * @retval 0 when successful * @retval -1 upon an error */int msg_serialize(msg_t *msg, msg_pub_t *pub){  msg_header_t *h, **hh, **end;  msg_header_t **separator;  msg_header_t **payload;  msg_header_t **multipart;  msg_mclass_t const *mc = msg->m_class;  msg_header_t **tail, ***ptail;  if (!msg)    return errno = EINVAL, -1;  if (pub == NULL)    pub = msg->m_object;  /* There must be a first line */  if (pub->msg_request)    h = pub->msg_request;  else if (pub->msg_status)    h = pub->msg_status;  else    return errno = EINVAL, -1;  serialize_first(msg, h);  separator = (msg_header_t **)((char *)pub + mc->mc_separator->hr_offset);  payload = (msg_header_t **)((char *)pub + mc->mc_payload->hr_offset);  if (mc->mc_multipart->hr_class)    multipart = (msg_header_t **)((char *)pub + mc->mc_multipart->hr_offset);  else    multipart = NULL;  /* Find place to insert headers: before separator, payload and multipart */  if (*separator && !msg_header_is_removed(*separator))    ptail = &(*separator)->sh_prev;  else if (*payload && !msg_header_is_removed(*payload))    ptail = &(*payload)->sh_prev;  else if (multipart && *multipart && !msg_header_is_removed(*multipart))    ptail = &(*multipart)->sh_prev;  else    ptail = &msg->m_tail;  tail = *ptail;  end = (msg_header_t **)((char *)pub + pub->msg_size);  for (hh = pub->msg_headers; hh < end; hh++) {    if (!*hh)      continue;    if (hh == separator || hh == payload || hh == multipart)      continue;    tail = serialize_one(msg, *hh, tail);  }  /* Serialize separator, payload and multipart last */  if (*separator)    tail = serialize_one(msg, *separator, tail);  *ptail = tail;  /* Payload comes after separator but before multipart */  if (ptail != &(*separator)->sh_prev)    ;  else if (*payload && !msg_header_is_removed(*payload))    ptail = &(*payload)->sh_prev;  else if (multipart && *multipart && !msg_header_is_removed(*multipart))    ptail = &(*multipart)->sh_prev;  else    ptail = &msg->m_tail;  tail = *ptail;  if (*payload) {    tail = serialize_one(msg, *payload, tail);    *ptail = tail;  }  if (multipart && *multipart) {    msg_header_t *last;    last = msg_multipart_serialize(tail, (msg_multipart_t *)*multipart);    msg->m_tail = &last->sh_succ;  }  assert(msg->m_chain && msg_chain_errors(msg->m_chain) == 0);  return 0;}static inlinevoid serialize_first(msg_t *msg, msg_header_t *h){  if (msg_header_is_removed(h)) {    if ((h->sh_succ = msg->m_chain))      h->sh_succ->sh_prev = &h->sh_succ;    else      msg->m_tail = &h->sh_succ;    *(h->sh_prev = &msg->m_chain) = h;  }}staticmsg_header_t **serialize_one(msg_t *msg, msg_header_t *h, msg_header_t **prev){  msg_header_t *last;  msg_header_t *succ = *prev;  if (msg_header_is_removed(h)) {    /* Add the first header in the list to the chain */    *prev = h; h->sh_prev = prev;    for (last = h; last->sh_succ; last = last->sh_succ) {      /* Ensure that chain is connected */      assert(last->sh_next == last->sh_succ);      assert(last->sh_succ->sh_prev = &last->sh_succ);    }    prev = &last->sh_succ;  }  if ((h = h->sh_next)) {    assert(!msg_is_single(h));    if (msg_is_single(h)) {      for (; h; h = h->sh_next)	if (!msg_header_is_removed(h))	  msg_chain_remove(msg, h);    }    /* Add the rest of the headers in the list to the chain */    else for (; h; h = h->sh_next) {      if (msg_header_is_removed(h)) {	*prev = h; h->sh_prev = prev;	for (;h->sh_succ; h = h->sh_succ)	  assert(h->sh_succ == h->sh_next);	prev = &h->sh_succ;      }    }  }  *prev = succ;  return prev;}/**Fill an I/O vector with message contents. * * The function msg_iovec() calculates number of entries in the I/O vector * required to send a message @a msg. It also fills in the I/O vector array, * if it is provided by the caller and it is large enough. * * @param msg * @param vec * @param veclen * * @return * The function msg_iovec() returns the number of entries in I/O * vector required by @a msg, or 0 upon an error. * * @note The caller should check that the I/O vector @a vec has enough * entries. If the @a vec is too short, it should allocate big enough * vector and re-invoke msg_iovec(). */int msg_iovec(msg_t *msg, msg_iovec_t vec[], int veclen){  int len = 0, n = 0;  char const *p = NULL;  msg_header_t *h;  unsigned total = 0;  if (veclen <= 0)    veclen = 0;  for (h = msg->m_chain; h; h = h->sh_succ) {    if (h->sh_data != p) {      p = h->sh_data; len = h->sh_len;      if (p == NULL)	return 0;      if (vec && n != veclen)	/* new iovec entry */	vec[n].mv_base = (void *)p, vec[n].mv_len  = len;      else	vec = NULL;      p += len; n++;    }    else {      /* extend old entry */      len = h->sh_len;      if (vec)	vec[n-1].mv_len += len;      p += len;    }    total += len;  }  msg->m_size = total;  assert(n > 0);  return n;}/** Insert a header to existing header chain. * * Headers are either inserted just before the payload, or after the first * line, depending on their type. * * @param msg  message object [IN] * @param pub  public message structure [IN/OUT] * @param prepend if true, add before same type of headers (instead after them) * @param head head of chain * @param h    header to insert * */staticvoid msg_insert_chain(msg_t *msg,		      msg_pub_t *pub,		      int prepend,		      msg_header_t **head,		      msg_header_t *h){  msg_mclass_t const *mc = msg->m_class;  msg_header_t **hh;  msg_header_t **separator;  msg_header_t **payload;    assert(msg && pub && head && h);  separator = (msg_header_t **)((char *)pub + mc->mc_separator->hr_offset);  payload = (msg_header_t **)((char *)pub + mc->mc_payload->hr_offset);  if (msg_is_request(h)) {    if (pub->msg_status)      pub->msg_status = NULL;    hh = head;  }  else if (msg_is_status(h)) {    if (pub->msg_request)      pub->msg_request = NULL;    hh = head;  }  else if (msg_is_payload(h)) {    /* Append */    hh = msg_chain_tail(msg);  }  else if (prepend) {    if (!msg_is_request(*head) && !msg_is_status(*head))      hh = head;    else      hh = &((*head)->sh_succ);  }  /* Append headers before separator or payload */  else if (*separator && (*separator)->sh_prev)    hh = (*separator)->sh_prev;  else if (*payload && (*payload)->sh_prev)    hh = (*payload)->sh_prev;  else    hh = msg_chain_tail(msg);  msg_insert_here_in_chain(msg, hh, h);}/** Insert one or more message header to the chain. * * The function msg_insert_here_in_chain() appends message header to the * chain of headers after the given header. * * @param msg  message * @param prev pointer to h_succ of previous fragment in the list * @param h    header to be inserted. * * @return The pointer to the last header inserted. */staticvoid msg_insert_here_in_chain(msg_t *msg,			      msg_header_t **prev,			      msg_header_t *h){  if (h) {    msg_header_t *last, *next;    assert(h->sh_prev == NULL);    assert(prev);    assert(!msg_chain_errors(h));    for (last = h; last->sh_succ; last = last->sh_succ)      ;    last->sh_succ = next = *prev;    *prev = h;    h->sh_prev = prev;    if (next)      next->sh_prev = &last->sh_succ;    else      msg->m_tail = &last->sh_succ;    assert(msg->m_chain && msg_chain_errors(msg->m_chain) == 0);  }}/** * Remove a message from header chain. * * The function @c msg_chain_remove() removes a message header from the header * chain. * * @param msg  pointer to the message * @param h    pointer to the header in the list to be removed * * @return The pointer to the header just removed. */static inlinemsg_header_t *msg_chain_remove(msg_t *msg, msg_header_t *h){  if (h) {    if (h->sh_prev) {      assert(*h->sh_prev == h);      assert(h->sh_succ == NULL || h->sh_succ->sh_prev == &h->sh_succ);      *h->sh_prev = h->sh_succ;    }    if (h->sh_succ)      h->sh_succ->sh_prev = h->sh_prev;    else if (msg && h->sh_prev)      msg->m_tail = h->sh_prev;    h->sh_succ = NULL; h->sh_prev = NULL;    if (msg)      assert(msg_chain_errors(msg->m_chain) == 0);  }  return h;}#ifndef NDEBUG/**Check if header chain contains any loops. * * @return * Return 0 if no loop, -1 otherwise. */staticint msg_chain_loop(msg_header_t const *h){  msg_header_t const *h2;  if (!h) return 0;  for (h2 = h->sh_succ; h && h2 && h2->sh_succ; h = h->sh_succ) {    if (h == h2 || h == h2->sh_succ)      return 1;    h2 = h2->sh_succ->sh_succ;    if (h == h2)      return 1;  }  return 0;}/** Check header chain consistency. * * @return * Return 0 if consistent, number of errors otherwise. */staticint msg_chain_errors(msg_header_t const *h){  if (msg_chain_loop(h))    return -1;  for (; h; h = h->sh_succ) {    if (h->sh_succ && h->sh_succ->sh_prev != &h->sh_succ)      return -1;    if (h->sh_prev && h != (*h->sh_prev))      return -1;  }  return 0;}#endif/* ====================================================================== *//* Handling message structure - allocating, adding and removing headers *//** Allocate a header structure * * The msg_header_alloc() function allocates a generic MO header structure * and returns a pointer to it. * * @param home  memory home * @param hc    header class * @param extra amount of extra memory to be allocated after header structure * * @return * A pointer to the newly created header object, or @c NULL upon an error. */msg_header_t *msg_header_alloc(su_home_t *home,			       msg_hclass_t *hc,			       int extra){  int size = hc->hc_size;  msg_header_t *h = su_alloc(home, size + extra);  if (h) {    memset(h, 0, size);    h->sh_class = hc;  }  return h;}/**Add a (list of) header(s) to the header structure and fragment chain. * * The function @c msg_header_add() 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. * * If the header is a prepend header, the new header is inserted before * existing headers of the same class. If the header is an append header, * the new header is inserted after existing 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 * added 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_add(msg_t *msg,		   msg_pub_t *pub,		   msg_header_t **hh,		   msg_header_t *h){  msg_header_t **head, *old = NULL, *end;  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) {

⌨️ 快捷键说明

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