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

📄 msg_mclass.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@ingroup msg_parser  * @CFILE msg_mclass.c * * Message factory object. * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Wed Jun  5 14:34:24 2002 ppessi */#include "config.h"#include <stddef.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <assert.h>#include <limits.h>#include <errno.h>#include <stdarg.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/su.h>#include <sofia-sip/su_alloc.h>#include "msg_internal.h"#include "sofia-sip/msg_parser.h"#include "sofia-sip/msg_mclass.h"#include "sofia-sip/msg_mclass_hash.h"/** Clone a message class. * * @relatesalso msg_mclass_s * * The function msg_mclass_clone() makes a copy of message class object @a * old. It is possible to resize the hash table by giving a non-zero @a * newsize. If @a newsize is 0, the size of hash table is not changed. If @a * empty is true, the copied message class object will not recognize any * headers. This is useful if more fine-grained control of parsing process * is required, for instance. *  * @param[in] old      pointer to the message class object to be copied  * @param[in] newsize  size of hash table in the copied object  * @param[in] empty    if true, resulting copy does not contain any headers  *  * @return  * The function msg_mclass_clone() returns a pointer to a newly * copied message class object, or NULL upon an error. * The returned message class object can be freed with free(). * * @ERRORS * @ERROR ENOMEM * A memory allocation failed. * @ERROR EINVAL * The function was given invalid arguments. *  * @note The empty parser can handle request/status line. All headers are * put into list of unknown headers (unless they are malformed, and they are * put into list of erronous headers). However, SIP, RTSP, and HTTP * protocols all require that the parser recognizes @b Content-Length header * before they can extract the message body from the data received from * network. * */msg_mclass_t *msg_mclass_clone(msg_mclass_t const *old, int newsize, int empty){  size_t size, shortsize;  msg_mclass_t *mc;   int identical;  unsigned short i;  if (newsize == 0)    newsize = old->mc_hash_size;  if (newsize < old->mc_hash_used ||      (unsigned)newsize > USHRT_MAX / sizeof(msg_header_t *)) {    errno = EINVAL;    return NULL;  }  size = offsetof(msg_mclass_t, mc_hash[newsize]);  if (old->mc_short)    shortsize = MC_SHORT_SIZE * (sizeof old->mc_short[0]);  else    shortsize = 0;  mc = malloc(size + shortsize);  identical = newsize == old->mc_hash_size && !empty;  if (mc) {    if (!identical) {      memcpy(mc, old, offsetof(msg_mclass_t, mc_hash));      memset(mc->mc_hash, 0, size - offsetof(msg_mclass_t, mc_hash));      mc->mc_short = NULL;      mc->mc_hash_size = newsize;      mc->mc_hash_used = 0;      for (i = 0; !empty && i < old->mc_hash_size; i++) {	msg_mclass_insert(mc, &old->mc_hash[i]);      }    }    else {      memcpy(mc, old, size);      mc->mc_short = NULL;    }        if (shortsize) {      if (empty)	mc->mc_short = memset((char *)mc + size, 0, shortsize);      else	mc->mc_short = memcpy((char *)mc + size, old->mc_short, shortsize);    }  }  return mc;}/**Add a new header to the message class. * * @relatesalso msg_mclass_s * * Insert a header class @a hc to the message class object @a mc. If the * given @a offset of the header in @ref msg_pub_t "public message * structure" is zero, the function extends the public message structure in * order to store newly inserted header there. * * @param[in,out] mc       pointer to a message class object  * @param[in]     hc       pointer to a header class object  * @param[in]     offset   offset of the header in *                         @ref msg_pub_t "public message structure" * * If the @a offset is 0, the msg_mclass_insert_header() increases size of * the public message structure and places the header at the end of message. * * @return Number of collisions in hash table, or -1 upon an error. *  * @deprecated Use msg_mclass_insert_with_mask() instead. */int msg_mclass_insert_header(msg_mclass_t *mc, 			     msg_hclass_t *hc,			     unsigned short offset){  msg_href_t hr[1];  if (mc == NULL || hc == NULL) {    errno = EINVAL;    return -1;  }  if (msg_hclass_offset(mc, NULL, hc))    return (void)(errno = EEXIST), -1;  if (offset == 0)    offset = mc->mc_msize, mc->mc_msize += sizeof(msg_header_t *);  assert(offset < mc->mc_msize);  hr->hr_class = hc;  hr->hr_offset = offset;  return msg_mclass_insert(mc, hr);}/**Add a new header to the message class. * * @relatesalso msg_mclass_s * * Insert a header class @a hc to the message class @a mc. If the given @a * offset of the header in @ref msg_pub_t "public message structure" is * zero, extend the size of the public message structure in order to store * headers at the end of structure. * * @param[in,out] mc       pointer to a message class * @param[in]     hc       pointer to a header class * @param[in]     offset   offset of the header in  *                         @ref msg_pub_t "public message structure"  * @param[in]     flags    classification flags for the header  * * @return Number of collisions in hash table, or -1 upon an error. */int msg_mclass_insert_with_mask(msg_mclass_t *mc, 				msg_hclass_t *hc,				unsigned short offset,				unsigned short flags){  msg_href_t hr[1];  if (mc == NULL || hc == NULL) {    errno = EINVAL;    return -1;  }  if (msg_hclass_offset(mc, NULL, hc))    return (void)(errno = EEXIST), -1;  if (offset == 0)    offset = mc->mc_msize, mc->mc_msize += sizeof(msg_header_t *);  assert(offset < mc->mc_msize);  hr->hr_class = hc;  hr->hr_offset = offset;  hr->hr_flags = flags;  return msg_mclass_insert(mc, hr);}/** Add a header reference to the message class. * * @relatesalso msg_mclass_s * * @param[in,out] mc       pointer to a message class object  * @param[in]     hr       header reference object  * * @return Number of collisions in hash table, or -1 upon an error. */int msg_mclass_insert(msg_mclass_t *mc, msg_href_t const *hr){  int j, j0;  int N;  int collisions = 0;  msg_hclass_t *hc;  if (mc == NULL) {    errno = EINVAL;    return -1;  }  if (hr == NULL || (hc = hr->hr_class) == NULL)     return 0;  /* Add short form */  if (mc->mc_short && hc->hc_short[0]) {    char compact = hc->hc_short[0];    msg_href_t *shorts = (msg_href_t *)mc->mc_short;    if (compact < 'a' || compact > 'z')      return -1;    if (shorts[compact - 'a'].hr_class && 	shorts[compact - 'a'].hr_class != hc)      return -1;          shorts[compact - 'a'] = *hr;  }  N = mc->mc_hash_size;  j0 = msg_header_name_hash(hc->hc_name, NULL) % N;  for (j = j0; mc->mc_hash[j].hr_class; ) {    collisions++;    if (mc->mc_hash[j].hr_class == hc)      return -1;    j = (j + 1) % N;    if (j == j0)      return -1;  }  mc->mc_hash[j] = hr[0];  mc->mc_hash_used++;    return collisions;}/** Calculate length of line ending (0, 1 or 2). @internal */#define CRLF_TEST(cr, lf) ((cr) == '\r' ? ((lf) == '\n') + 1 : (cr)=='\n')/**Search for a header class. * * @relatesalso msg_mclass_s * * The function msg_find_hclass() searches for a header class from a message * class based on the contents of the header to be parsed. The buffer @a s * should point to the first character in the header name. * * @param[in]  mc   message class object  * @param[in]  s    header contents  * @param[out] return_start_of_content start of header content (may be NULL) * * @return The function msg_find_hclass() returns a pointer to a header * reference structure. A pointer to a header reference for unknown headers * is returned, if the header is not included in the message class. * * @par * The return-value parameter @a return_start_of_content will contain the * start of the header contents within @a s, or 0 upon an error parsing the * header name and following colon. * * @par  * Upon a fatal error, a NULL pointer is returned. */msg_href_t const *msg_find_hclass(msg_mclass_t const *mc, 				  char const *s, 				  isize_t *return_start_of_content){  msg_href_t const *hr;  short i, N, m;  isize_t len;  assert(mc);  N = mc->mc_hash_size;  i = msg_header_name_hash(s, &len) % N;  if (len == 0 || len > HC_LEN_MAX) {    if (return_start_of_content)      *return_start_of_content = 0;    return mc->mc_error;  }  m = (short)len;  if (m == 1 && mc->mc_short) {    short c = s[0];    if (c >= 'a' && c <= 'z')      hr = &mc->mc_short[c - 'a'];    else if (c >= 'A' && c <= 'Z')      hr = &mc->mc_short[c - 'A'];    else      hr = mc->mc_unknown;    if (hr->hr_class == NULL)      hr = mc->mc_unknown;  }  else {    msg_hclass_t *hc;    /* long form */    for (hr = NULL; (hc = mc->mc_hash[i].hr_class); i = (i + 1) % N) {      if (m == hc->hc_len && strncasecmp(s, hc->hc_name, m) == 0) {	hr = &mc->mc_hash[i];	break;      }    }    if (hr == NULL)      hr = mc->mc_unknown;  }  if (!return_start_of_content)	/* Just header name */    return hr;  if (s[len] == ':') {		/* Fast path */    *return_start_of_content = ++len;    return hr;  }  if (IS_LWS(s[len])) {    int crlf = 0;    do {      len += span_ws(s + len + crlf) + crlf; /* Skip lws before colon */      crlf = CRLF_TEST(s[len], s[len + 1]);    }    while (IS_WS(s[len + crlf]));  }  if (s[len++] != ':')		/* Colon is required in header */    len = 0;  *return_start_of_content = len;  return hr;}

⌨️ 快捷键说明

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