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

📄 msg_parser.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
 * @relates msg_s * * When parsing a transport stream, only the first message in the stream is * created with msg_create(). The rest of the messages should be created * with msg_next() after previous message has been completely received and * parsed. * */msg_t *msg_next(msg_t *msg){  msg_t *next;  unsigned n;  if (msg && msg->m_next) {    next = msg->m_next;    msg->m_next = NULL;    return next;  }  if ((n = msg_buf_committed(msg))) {    if (msg_buf_move(next = msg_create(msg->m_class, msg->m_oflags), msg)) {      msg_addr_copy(next, msg);      return next;    }    /* How to indicate error? */    msg_destroy(next);  }  return NULL;}/** Set next message of the stream */int msg_set_next(msg_t *msg, msg_t *next){  if (!msg || (next && next->m_next))    return -1;  if (msg->m_next && next)    next->m_next = msg->m_next;  msg->m_next = next;  return 0;}/** Clear committed data */void msg_clear_committed(msg_t *msg){  if (msg) {    unsigned n = msg_buf_committed(msg);    if (n)      msg_buf_used(msg, n);  }}#if 0struct sigcomp_udvm;struct sigcomp_udvm *msg_get_udvm(msg_t *msg);struct sigcomp_udvm *msg_set_udvm(msg_t *msg, struct sigcomp_udvm *);/** Save UDVM. */struct sigcomp_udvm *msg_set_udvm(msg_t *msg, struct sigcomp_udvm *udvm){  struct sigcomp_udvm *prev = NULL;  if (msg) {    prev = msg->m_udvm;    msg->m_udvm = udvm;  }  return prev;}/** Get saved UDVM */struct sigcomp_udvm *msg_get_udvm(msg_t *msg){  return msg ? msg->m_udvm : NULL;}#endif/** Mark message as complete. * * @relates msg_s */inlineunsigned msg_mark_as_complete(msg_t *msg, unsigned mask){  if (msg) {    msg->m_streaming = 0;    return msg->m_object->msg_flags |= mask | MSG_FLG_COMPLETE;  }  else {    return 0;  }}/** Return true if message is complete. * * @relates msg_s */int msg_is_complete(msg_t const *msg){  return msg && MSG_IS_COMPLETE(msg->m_object);}/** Return true if message has parsing errors. * * @relates msg_s*/int msg_has_error(msg_t const *msg){  return msg->m_object->msg_flags & MSG_FLG_ERROR;}/**Total size of message. * * @relates msg_s */unsigned msg_size(msg_t const *msg){  return msg ? msg->m_size : 0;}/** Set the maximum size of a message. * * @relates msg_s * * The function msg_maxsize() sets the maximum buffer size of a message. It * returns the previous maximum size. If the @a maxsize is 0, maximum size * is not set, but the current maximum size is returned. * * If the message size exceeds maxsize, msg_errno() returns ENOBUFS, * MSG_FLG_TOOLARGE and MSG_FLG_ERROR flags are set. */unsigned msg_maxsize(msg_t *msg, unsigned maxsize){  unsigned retval = 0;  if (msg) {    retval = msg->m_maxsize;    if (maxsize)      msg->m_maxsize = maxsize;  }  return retval;}/**Set the size of next fragment. * * @relates msg_s * * The function msg_streaming_size() sets the size of the message body for * streaming. */unsigned msg_streaming_size(msg_t *msg, unsigned ssize){  if (!msg)    return -1;  msg->m_ssize = ssize;  return 0;}/**Allocate a list of external buffers. * * @relates msg_s * * The function msg_buf_external() allocates at most msg_n_fragments * external buffers for the message body. * * @return The function msg_buf_external() returns number of allocated * buffers, or -1 upon an error. */int msg_buf_external(msg_t *msg,		     unsigned N,		     unsigned blocksize){  msg_buffer_t *ext, *b, **bb;  int i, I;  assert(N <= 128 * 1024);  if (msg == NULL)    return -1;  if (blocksize == 0)    blocksize = msg_min_block;  if (N == 0)    N = blocksize;  if (N > blocksize * msg_n_fragments)    N = blocksize * msg_n_fragments;  if (N > msg->m_ssize)    N = msg->m_ssize;  I = (N + blocksize - 1) / blocksize; assert(I <= msg_n_fragments);  for (i = 0, bb = &ext; i < I; i++) {    *bb = su_zalloc(msg_home(msg), sizeof **bb);    if (!*bb)      break;    bb = &(*bb)->b_next;  }  if (i == I)    for (b = ext, i = 0; b; b = b->b_next, i++) {      b->b_data = su_alloc(msg_home(msg), b->b_size = blocksize);      if (!b->b_data)	break;    }  if (i == I) {    /* Successful return */    for (bb = &msg->m_stream; *bb; bb = &(*bb)->b_next)      ;    *bb = ext;    if (msg->m_ssize != MSG_SSIZE_MAX)      for (b = ext; b; b = b->b_next) {	if (msg->m_ssize < b->b_size) {	  b->b_size = msg->m_ssize;	}	msg->m_ssize -= b->b_size;      }    return i;  }  for (b = ext; b; b = ext) {    ext = b->b_next;    su_free(msg_home(msg), b->b_data);    su_free(msg_home(msg), b);  }  return -1;}int msg_unref_external(msg_t *msg, msg_buffer_t *b){  if (msg && b) {    su_free(msg_home(msg), b->b_data);    su_free(msg_home(msg), b);    return 0;  }  errno = EINVAL;  return -1;}/* ====================================================================== *//* Parsing messages */static inline int extract_incomplete_chunks(msg_t *, int eos);static int extract_first(msg_t *, msg_pub_t *, char b[], int bsiz, int eos);static inline int extract_next(msg_t *, msg_pub_t *, char *, int, int, int);static int extract_header(msg_t *, msg_pub_t*,			  char b[], int bsiz, int eos, int copy);static msg_header_t *header_parse(msg_t *, msg_pub_t *, msg_href_t const *,				  char s[], int slen, int copy_buffer);static inline intextract_trailers(msg_t *msg, msg_pub_t *mo,		 char *b, int bsiz, int eos, int copy);/** Calculate length of line ending (0, 1 or 2) */#define CRLF_TEST(b) ((b)[0] == '\r' ? ((b)[1] == '\n') + 1 : (b)[0] =='\n')static inline voidappend_parsed(msg_t *msg, msg_pub_t *mo, msg_header_t **hh, msg_header_t *h,	      int always_into_chain);/**Extract and parse a message from internal buffer. * * @relates msg_s * * This function parses the internal buffer and adds the parsed fragments to * the message object. It marks the successfully parsed data as extracted. * * @param msg message to be parsed * * @retval positive if a complete message was parsed * @retval 0 if message was incomplete * @retval negative if an error occurred */int msg_extract(msg_t *msg){  msg_pub_t *mo = msg_object(msg);  msg_mclass_t const *mc;  char *b;  int m, bsiz, eos;  if (!msg || !msg->m_buffer->mb_data)    return -1;  assert(mo);  mc = msg->m_class;  mo = msg->m_object;  eos = msg->m_buffer->mb_eos;  if (msg->m_chunk) {    m = extract_incomplete_chunks(msg, eos);    if (m < 1 || MSG_IS_COMPLETE(mo))      return m;  }  if (mo->msg_flags & MSG_FLG_TRAILERS)    msg_set_streaming(msg, 0);  if (msg->m_buffer->mb_used + msg->m_buffer->mb_commit ==      msg->m_buffer->mb_size)    /* Why? When? */    return 0;  assert(msg->m_buffer->mb_used + msg->m_buffer->mb_commit <	 msg->m_buffer->mb_size);  m = 0;  b = msg->m_buffer->mb_data + msg->m_buffer->mb_used;  bsiz = msg->m_buffer->mb_commit;  b[bsiz] = '\0';  while (msg->m_buffer->mb_commit > 0) {    int flags = mo->msg_flags;    int copy = MSG_IS_EXTRACT_COPY(flags);    if (flags & MSG_FLG_COMPLETE)      break;    if (flags & MSG_FLG_TRAILERS)      m = extract_trailers(msg, mo, b, bsiz, eos, copy);    else if (flags & MSG_FLG_BODY)      m = mc->mc_extract_body(msg, mo, b, bsiz, eos);    else if (flags & MSG_FLG_HEADERS)      m = extract_next(msg, mo, b, bsiz, eos, copy);    else      m = extract_first(msg, mo, b, bsiz, eos);    if (m <= 0 || msg->m_chunk)      break;    b += m;    bsiz -= m;    msg_buf_used(msg, m);  }  if (eos && bsiz == 0)    msg_mark_as_complete(msg, 0);  if (m < 0 || (mo->msg_flags & MSG_FLG_ERROR)) {    msg_mark_as_complete(msg, MSG_FLG_ERROR);    return -1;  }  else if (!MSG_IS_COMPLETE(mo))    return 0;  else if (!(mo->msg_flags & MSG_FLG_HEADERS)) {    msg_mark_as_complete(msg, MSG_FLG_ERROR);    return -1;  }  else    return 1;}staticint extract_first(msg_t *msg, msg_pub_t *mo, char b[], int bsiz, int eos){  /* First line */  int k, l, m, n, crlf, xtra;  msg_header_t *h, **hh;  msg_href_t const *hr;  msg_mclass_t const *mc = msg->m_class;  for (k = 0; IS_LWS(b[k]); k++) /* Skip whitespace */    ;  if (!b[k]) return k;  /* If first token contains no /, this is request, otherwise status line */  l = span_token(b + k) + k;  if (b[l] != '/')    hr = mc->mc_request;  else    hr = mc->mc_status;  n = span_non_crlf(b + l) + l;  if (!b[n])    return eos ? -1 : 0;  crlf = CRLF_TEST(b + n);  for (m = n + crlf; IS_WS(b[m]); m++)    ;  /* In order to skip possible whitespace after first line, we don't parse     first line until first non-ws char from next one has been received */  if (!b[m] && !eos)    return 0;  xtra = MSG_IS_EXTRACT_COPY(mo->msg_flags) ? n + 1 - k : 0;  if (!(h = msg_header_alloc(msg_home(msg), hr->hr_class, xtra)))    return -1;  if (xtra) {    char *bb = memcpy(MSG_HEADER_DATA(h), b, xtra - 1);    h->sh_data = b, h->sh_len = n + crlf;    b = bb; n = xtra - 1;  }  else {    b = b + k; n = n - k;  }  b[n] = 0;  if (hr->hr_class->hc_parse(msg_home(msg), h, b, n) < 0)    return -1;  assert(hr->hr_offset);  hh = (msg_header_t**)((char *)mo + hr->hr_offset);  append_parsed(msg, mo, hh, h, 1);  mo->msg_flags |= MSG_FLG_HEADERS;  return m;}/* Extract header or message body */static inline intextract_next(msg_t *msg, msg_pub_t *mo, char *b, int bsiz, int eos, int copy){  if (IS_CRLF(b[0]))    return msg->m_class->mc_extract_body(msg, mo, b, bsiz, eos);  else    return extract_header(msg, mo, b, bsiz, eos, copy);}/** Extract a header. */int msg_extract_header(msg_t *msg, msg_pub_t *mo, char b[], int bsiz, int eos){  return extract_header(msg, mo, b, bsiz, eos, 0);}/** Extract a header from buffer @a b. */staticintextract_header(msg_t *msg, msg_pub_t *mo, char *b, int bsiz, int eos,	       int copy_buffer){  int len, n = 0, m, crlf = 0;  int name_len = 0, name_len_set = 0;  int error = 0, xtra;  msg_header_t *h;  msg_href_t const *hr;  msg_mclass_t const *mc = msg->m_class;  hr = msg_find_hclass(mc, b, &n); /* Get header name */  error = n == 0;  if (hr == NULL)		/* Panic */    return -1;  xtra = span_ws(b + n);  /* Find next crlf which is not followed by whitespace */  do {    n += xtra + crlf;    if (!eos && bsiz == n)      return 0;    m = span_non_crlf(b + n);    if (!name_len_set && m)      name_len = n, name_len_set = 1; /* First non-ws after COLON */    n += m;    crlf = CRLF_TEST(b + n);    xtra = span_ws(b + n + crlf);  }  while (xtra);  if (!eos && bsiz == n + crlf)    return 0;  if (hr->hr_class->hc_hash == msg_unknown_hash)    name_len = 0, name_len_set = 1;  if (error) {    msg->m_extract_err |= hr->hr_flags;    if (hr->hr_class->hc_critical)      mo->msg_flags |= MSG_FLG_ERROR;    hr = mc->mc_error;    copy_buffer = 1;    h = header_parse(msg, mo, hr, NULL, 0, 0);  }  else {    if (!name_len_set)      /* Empty header - nothing but name, COLON and LWS */      name_len = n;    else      /* Strip extra whitespace at the end of header */      while (n > name_len && IS_LWS(b[n - 1]))	n--, crlf++;    h = header_parse(msg, mo, hr, b + name_len, n - name_len, copy_buffer);  }  if (h == NULL)    return -1;  len = n + crlf;  /*   * If the header contains multiple header fields, set the pointer to the   * encodeded data correctly   */  while (h) {    if (copy_buffer)      h->sh_data = b, h->sh_len = len;    b += len, len = 0;    if (h->sh_succ)      assert(&h->sh_succ == h->sh_succ->sh_prev);    h = h->sh_next;  }  return n + crlf;}staticmsg_header_t *header_parse(msg_t *msg, msg_pub_t *mo,			   msg_href_t const *hr,			   char s[], int slen,			   int copy_buffer){  su_home_t *home = msg_home(msg);  msg_header_t *h, **hh;  msg_header_t *h0, *h_next;  msg_hclass_t *hc = hr->hr_class;  int n;  int add_to_list, clear = 0;  hh = (msg_header_t **)((char *)mo + hr->hr_offset);  add_to_list = (hc->hc_kind == msg_kind_list && !copy_buffer && *hh);  if (add_to_list)    h = *hh;

⌨️ 快捷键说明

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