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

📄 msg_parser.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
  else    h = msg_header_alloc(home, hc, copy_buffer ? slen + 1 : 0);  if (!h)    return NULL;  if (s) {    if (copy_buffer)      s = memcpy(MSG_HEADER_DATA(h), s, slen);    s[slen] = '\0';    if (hc->hc_kind == msg_kind_list && *hh) {      n = hc->hc_parse(home, *hh, s, slen);      /* Clear if adding new header disturbs existing headers */      clear = *hh != h && !copy_buffer;      if (clear)	msg_fragment_clear((*hh)->sh_common);    }    else      n = hc->hc_parse(home, h, s, slen);    if (n < 0) {      msg->m_extract_err |= hr->hr_flags;      if (hc->hc_critical)	mo->msg_flags |= MSG_FLG_ERROR;      clear = 0;      if (!add_to_list) {	/* Try to free memory allocated by hc->hc_parse() */	for (h0 = h; h0; h0 = h_next) {	  h_next = h0->sh_next;	  if (hc->hc_params) {	    msg_param_t *params = *(msg_param_t **)	      ((char *)h0 + hc->hc_params);	    if (params)	      su_free(home, params);	  }	  if (h0 != h)	    su_free(home, h0);	}	memset(h, 0, hc->hc_size);	h->sh_error->er_name = hc->hc_name;	hr = msg->m_class->mc_error;	h->sh_class = hr->hr_class;	hh = (msg_header_t **)((char *)mo + hr->hr_offset);      }    }  }  if (clear)    for (hh = &(*hh)->sh_next; *hh; *hh = (*hh)->sh_next)      msg_chain_remove(msg, *hh);  else if (h != *hh)    append_parsed(msg, mo, hh, h, 0);  return h;}/** Decode a message header. */msg_header_t *msg_header_d(su_home_t *home, msg_t const *msg, char const *b){  msg_mclass_t const *mc = msg->m_class;  msg_href_t const *hr = mc->mc_unknown;  int n;			/* Length of header contents */  int name_len, xtra;  msg_header_t *h;  char *bb;  n = strlen(b);  hr = msg_find_hclass(mc, b, &name_len);  if (hr == NULL)    return NULL;  /* Strip extra whitespace at the end and begin of header */  while (n > name_len && IS_LWS(b[n - 1]))    n--;  if (name_len < n && IS_LWS(b[name_len]))    name_len++;  xtra = (n - name_len);  if (!(h = msg_header_alloc(home, hr->hr_class, xtra + 1)))    return NULL;  bb = memcpy(MSG_HEADER_DATA(h), b + name_len, xtra), bb[xtra] = 0;  if (hr->hr_class->hc_parse(home, h, bb, xtra) < 0) {    hr = mc->mc_unknown;    su_free(home, h);    if (!(h = msg_header_alloc(home, hr->hr_class, n + 1)))      return NULL;    bb = memcpy(MSG_HEADER_DATA(h), b, n), bb[n] = 0;    if (hr->hr_class->hc_parse(home, h, bb, n) < 0) {      su_free(home, h), h = NULL;    }  }  return h;}/** Extract a separator line */int msg_extract_separator(msg_t *msg, msg_pub_t *mo,			  char b[], int bsiz, int eos){  msg_mclass_t const *mc = msg->m_class;  msg_href_t const *hr = mc->mc_separator;  int l = CRLF_TEST(b);  /* Separator length */  msg_header_t *h, **hh;  /* Even if a single CR *may* be a payload separator we cannot be sure */  if (l == 0 || (!eos && bsiz == 1 && b[0] == '\r'))    return 0;  /* Separator */  if (!(h = msg_header_alloc(msg_home(msg), hr->hr_class, 0)))    return -1;  if (hr->hr_class->hc_parse(msg_home(msg), h, b, l) < 0)    return -1;  h->sh_data = b, h->sh_len  = l;  hh = (msg_header_t **)((char *)mo + hr->hr_offset);  append_parsed(msg, mo, hh, h, 0);  return l;}static inline msg_header_t **msg_chain_tail(msg_t const *msg);/** Extract a message body of @a body_len bytes.  */int msg_extract_payload(msg_t *msg, msg_pub_t *mo,			msg_header_t **return_payload,			unsigned body_len,			char b[], int bsiz,			int eos){  msg_mclass_t const *mc = msg->m_class;  msg_href_t const *hr = mc->mc_payload;  msg_header_t *h, **hh, *h0;  msg_payload_t *pl;  char *x;  if (msg == NULL || mo == NULL)    return -1;  assert(!msg->m_chunk);  if (return_payload == NULL)    return_payload = &h0;  *return_payload = NULL;  assert(body_len > 0);  /* Allocate header structure for payload */  if (!(h = msg_header_alloc(msg_home(msg), hr->hr_class, 0)))    return -1;  hh = (msg_header_t **)((char *)mo + hr->hr_offset);  append_parsed(msg, mo, hh, h, 0);  pl = h->sh_payload;  *return_payload = h;  if (bsiz >= body_len) {    /* We have a complete body. */    h->sh_data = b, h->sh_len = body_len;    pl->pl_data = b, pl->pl_len = body_len;    return body_len;  }  if (msg->m_maxsize != 0 && body_len > msg->m_maxsize) {    mo->msg_flags |= MSG_FLG_TOOLARGE;    return -1;  }  assert(msg->m_buffer->mb_commit == bsiz);  assert(b == msg->m_buffer->mb_data + msg->m_buffer->mb_used);  if (msg->m_buffer->mb_used + body_len <= msg->m_buffer->mb_size) {    /* We don't have a complete body, but we have big enough buffer for it. */    msg->m_chunk = pl;    h->sh_data = b, h->sh_len  = bsiz;    pl->pl_data = b, pl->pl_len  = body_len;    if (msg->m_buffer->mb_used + body_len < msg->m_buffer->mb_size)      /* NUL-terminate payload */      b[body_len++] = '\0';    /* Mark the rest of the body as used in the buffer */    /* msg_buf_commit(msg, body_len - bsiz, eos); */    msg_buf_used(msg, body_len);    return bsiz;  }  /* We don't have big enough buffer for body. */  if (msg_get_flags(msg, MSG_FLG_CHUNKING)) {    /* Application supports chunking, use multiple chunks for payload */    unsigned current, rest;    current = msg->m_buffer->mb_size - msg->m_buffer->mb_used;    rest = body_len - current;    /* Use all the data from our current buffer */    msg_buf_used(msg, current);    msg->m_chunk = pl;    h->sh_data = b, h->sh_len = bsiz;    pl->pl_data = b, pl->pl_len  = current;    for (;current < body_len; current += rest) {      msg_header_t *h0 = h;      /* Allocate header structure for next payload chunk */      if (!(h = msg_header_alloc(msg_home(msg), hr->hr_class, 0)))	return -1;      if (msg->m_chain)	msg_insert_here_in_chain(msg, msg_chain_tail(msg), h);      h0->sh_next = h;      rest = body_len - current;      if (!msg->m_streaming) {	x = msg_buf_exact(msg, rest);	if (x == NULL) {	  mo->msg_flags |= MSG_FLG_TOOLARGE;	  return -1;	}      }      else {	x = NULL;      }      if (x) {	/* Mark the just-allocated buffer as used */	rest = msg->m_buffer->mb_size - msg->m_buffer->mb_used;	msg_buf_used(msg, rest);      }      pl = h->sh_payload;      h->sh_len = 0, pl->pl_len = rest;      h->sh_data = x, pl->pl_data = x;    }  }  else {    /* No chunking.     *     * Allocate a single buffer that contains enough free space for body.     *     * msg_buf_exact() also copies committed but un-used data     * from the old buffer (b[0] .. b[bsiz])     * to the new buffer (x[-bsiz-1]..b[-1])     */    if (!(x = msg_buf_exact(msg, body_len - bsiz + 1))) {      if (mo->msg_flags & MSG_FLG_TOOLARGE) {	msg_mark_as_complete(msg, MSG_FLG_TRUNC);	return bsiz;      }      return -1;    }    /* Fake un-received data as already received and then use it */    /* msg_buf_commit(msg, body_len - bsiz + 1, eos); */    msg_buf_used(msg, body_len + 1);    msg->m_chunk = h->sh_payload;    x -= bsiz; /* Start of un-used data */    x[body_len] = '\0';    h->sh_data = x, h->sh_len = bsiz;    pl->pl_data = x, pl->pl_len = body_len;    assert(MSG_CHUNK_AVAIL(pl) == body_len - bsiz);  }  return bsiz;}/** Extract incomplete chunks. */static inlineint extract_incomplete_chunks(msg_t *msg, int eos){  msg_payload_t *chunk;  for (chunk = msg->m_chunk; chunk; chunk = MSG_CHUNK_NEXT(chunk)) {    if (MSG_CHUNK_AVAIL(chunk) != 0)      break;    /* The incomplete payload fragment is now complete */    assert(MSG_CHUNK_BUFFER(chunk) == chunk->pl_data + chunk->pl_len);    msg->m_size += chunk->pl_common->h_len;  }  msg->m_chunk = chunk;  if (chunk) {    if (eos) {      msg_mark_as_complete(msg, MSG_FLG_TRUNC);      return 1;    }  }  else {    if (msg_get_flags(msg, MSG_FLG_FRAGS))      msg_mark_as_complete(msg, 0);  }  /**@retval 1 when message is complete   * @retval 0 when message is incomplete   * @retval -1 upon an error   */  return chunk == NULL;}/* Extract trailers */static inline intextract_trailers(msg_t *msg, msg_pub_t *mo,		 char *b, int bsiz, int eos, int copy){  if (IS_CRLF(b[0])) {    msg_mark_as_complete(msg, MSG_FLG_COMPLETE);    return CRLF_TEST(b);  }  else    return extract_header(msg, mo, b, bsiz, eos, copy);}/* ====================================================================== *//* Preparing (printing/encoding) a message structure for sending *//* Internal prototypes */static inline intmsg_header_name_e(char b[], int bsiz, msg_header_t const *h, int flags);static int msg_header_prepare(msg_mclass_t const *, int flags,			      msg_header_t *h, char *b, int bsiz);/**Encode all message fragments. * * @relates msg_s * * The function msg_prepare() prepares a message for sending. It encodes all * serialized fragments in the message. You have to call msg_serialize() * before calling msg_headers_prepare() in order to make sure that all the * heades and other message fragments are included in the chain. * * After encoding, the msg_common_s::h_data field will point to the encoding * result of size msg_common_s::h_len bytes in in each fragment. * * When multiple header fields are represented as a comma-separated list * within a single header line, the first fragment in the header will * contain all the text belonging to the header. The rest of the header * fields will have zero-length encoding with msg_common_s::h_data that * points to the end of the line. * * @return Total size of the encoded message in bytes, or -1 upon an error. * * @sa msg_extract(), msg_serialize() */int msg_prepare(msg_t *msg){  int total;  assert(msg->m_chain);  assert(msg_chain_errors(msg->m_chain) == 0);  /* Get rid of data that was received but not yet used (parsed) */  msg_clear_committed(msg);  total = msg_headers_prepare(msg, msg->m_chain, msg_object(msg)->msg_flags);  if (total != -1) {    msg->m_size = total;    msg->m_prepared = 1;  }  return total;}/** Clear 'prepared' flag. */void msg_unprepare(msg_t *msg){  if (msg) msg->m_prepared = 0;}/** Return true if message is prepared. */int msg_is_prepared(msg_t const *msg){  return msg && msg->m_prepared;}/**Encode headers in chain. * * The function msg_headers_prepare() encodes all the headers in the header * chain. You have to call msg_serialize() before calling * msg_headers_prepare() in order to make sure that all the heades and other * message fragments are included in the chain. * * @return * The size of all the headers in chain, or -1 upon an error. */int msg_headers_prepare(msg_t *msg, msg_header_t *headers, int flags){  msg_mclass_t const *mc = msg->m_class;  msg_header_t *h;  int n = 0, bsiz = 0, used = 0;  char *b;  unsigned total = 0;  b = msg_buf_alloc(msg, msg_min_size);  bsiz = msg_buf_size(msg);  if (!b)    return -1;  for (h = headers; h;) {    if (h->sh_data) {      total += h->sh_len;      h = h->sh_succ;      continue;    }    n = msg_header_prepare(mc, flags, h, b, bsiz - used);    if (n < 0) {      errno = EINVAL;      return -1;    }    if (used + n >= bsiz) {      /* Allocate next buffer */      if ((b = msg_buf_alloc(msg, n + 1)) == NULL)	return -1;      bsiz = msg_buf_size(msg); used = 0;      continue;    }    msg_buf_used(msg, n);    total += n;    used += n;    b += n;    h = h->sh_succ;  }  return total;}/** Encode a header or a list of headers */staticint msg_header_prepare(msg_mclass_t const *mc, int flags,		       msg_header_t *h, char *b, int bsiz){  msg_header_t *h0, *next;  msg_hclass_t *hc;  char const *s;  int n, m, middle = 0;  int compact, one_line_list, comma_list;  assert(h); assert(h->sh_class);  hc = h->sh_class;  compact = MSG_IS_COMPACT(flags);  one_line_list = compact || hc->hc_kind == msg_kind_apndlist;  comma_list = one_line_list || MSG_IS_COMMA_LISTS(flags);  for (h0 = h, n = 0; h; h = next) {    next = h->sh_succ;    if (!next || next->sh_class != hc || next->sh_data || !comma_list)      next = NULL;    if (!middle && hc->hc_name && hc->hc_name[0])      n += msg_header_name_e(b + n, bsiz >= n ? bsiz - n : 0, h, flags);    if ((m = hc->hc_print(b + n, bsiz >= n ? bsiz - n : 0, h, flags)) < 0) {      if (bsiz >= n + 64)	m = 2 * (bsiz - n);      else	m = 128;    }    n += m;    if (hc->hc_name) {      /* Encode continuation */      if (!next)	s = CRLF;      else if (compact)	s = ",";      else if (one_line_list)	s = ", ";      else	s = "," CRLF "\t";      m = strlen(s);      if (bsiz <= n + m) {	if (!next)	  return n + m;      }      else {	strcpy(b + n, s);      }      n += m;    }    middle = 1;  }  if (bsiz > n) {		/* XXX */    h0->sh_data = b, h0->sh_len = n;    for (h = h0; h; h = next) {      next = h->sh_succ;      if (!next || next->sh_class != hc || next->sh_data || !comma_list)	break;      else	next->sh_data = b, next->sh_len = 0;    }  }  return n;}/** Encode a header. * * The function msg_header_e() encodes a header field in the buffer @a * b[]. The encoding includes its name and trailing CRLF.  The function * returns the length of the encoding in bytes, excluding the final @c NUL. * The buffer @a b must be large enough for whole encoding, including the * final @c NUL. * * The @a flags parameter define how the encoding is done.  If the flags * specify @c MSG_DO_COMPACT, the encoding is compact (short form with * minimal whitespace). */

⌨️ 快捷键说明

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