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

📄 msg_parser.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_parser.c * * HTTP-like message parser engine. * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Thu Oct  5 14:01:24 2000 ppessi * *//*#define NDEBUG*/#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_header.h"#include "sofia-sip/bnf.h"#include "sofia-sip/msg_parser.h"#include "sofia-sip/msg_mclass.h"#include "sofia-sip/msg_mclass_hash.h"#include "sofia-sip/msg_mime.h"#if HAVE_FUNC#elif HAVE_FUNCTION#define __func__ __FUNCTION__#elsestatic char const __func__[] = "msg_parser";#endifstatic int _msg_header_add_dup_as(msg_t *msg,				  msg_pub_t *pub,				  msg_hclass_t *hc,				  msg_header_t const *src);static void msg_insert_chain(msg_t *msg, msg_pub_t *pub, int prepend,			     msg_header_t **head, msg_header_t *h);static void msg_insert_here_in_chain(msg_t *msg,				     msg_header_t **prev,				     msg_header_t *h);su_inline msg_header_t *msg_chain_remove(msg_t *msg, msg_header_t *h);#ifndef NDEBUGstatic int msg_chain_loop(msg_header_t const *h);static int msg_chain_errors(msg_header_t const *h);#endif/* ====================================================================== *//* Message properties *//** Get message flags. */unsigned msg_get_flags(msg_t const *msg, unsigned mask){  return msg ? msg->m_object->msg_flags & mask : 0;}/** Set message flags. */unsigned msg_set_flags(msg_t *msg, unsigned mask){  return msg ? msg->m_object->msg_flags |= mask : 0;}/** Clear message flags. */unsigned msg_zap_flags(msg_t *msg, unsigned mask){  return msg ? msg->m_object->msg_flags &= ~mask : 0;}/** Test if streaming is in progress. */int msg_is_streaming(msg_t const *msg){  return msg && msg->m_streaming != 0;}/** Enable/disable streaming */void msg_set_streaming(msg_t *msg, enum msg_streaming_status what){  if (msg)    msg->m_streaming = what != 0;}/* ---------------------------------------------------------------------- *//** Test if header is not in the chain */#define msg_header_is_removed(h) ((h)->sh_prev == NULL)su_inline int msg_is_request(msg_header_t const *h){  return h->sh_class->hc_hash == msg_request_hash;}su_inline int msg_is_status(msg_header_t const *h){  return h->sh_class->hc_hash == msg_status_hash;}/* ====================================================================== *//* Message buffer management *//** Allocate a buffer of @a size octets, with slack of #msg_min_size. */void *msg_buf_alloc(msg_t *msg, usize_t size){  struct msg_mbuffer_s *mb = msg->m_buffer;  size_t room = mb->mb_size - mb->mb_commit - mb->mb_used;  size_t target_size;  if (mb->mb_data && room >= (unsigned)size)    return mb->mb_data + mb->mb_used + mb->mb_commit;  target_size =    msg_min_size * ((size + mb->mb_commit) / msg_min_size + 1) - mb->mb_commit;  return msg_buf_exact(msg, target_size);}/** Allocate a buffer exactly of @a size octets, without any slack. */void *msg_buf_exact(msg_t *msg, usize_t size){  struct msg_mbuffer_s *mb = msg->m_buffer;  size_t room = mb->mb_size - mb->mb_commit - mb->mb_used;  char *buffer;  int realloc;  if (mb->mb_data && room >= (unsigned)size)    return mb->mb_data + mb->mb_used + mb->mb_commit;  size += mb->mb_commit;  if (msg->m_maxsize && msg->m_size + size > msg->m_maxsize + 1) {    msg->m_object->msg_flags |= MSG_FLG_TOOLARGE;    errno = msg->m_errno = ENOBUFS;    return NULL;  }  realloc = !mb->mb_used && !msg->m_set_buffer;  if (realloc)    buffer = su_realloc(msg->m_home, mb->mb_data, size);  else    buffer = su_alloc(msg->m_home, size);  if (!buffer)    return NULL;  if (!realloc && mb->mb_commit && mb->mb_data)    memcpy(buffer, mb->mb_data + mb->mb_used, mb->mb_commit);  msg->m_set_buffer = 0;  mb->mb_data = buffer;  mb->mb_size = size;  mb->mb_used = 0;  return buffer + mb->mb_commit;}/** Commit data into buffer. */usize_t msg_buf_commit(msg_t *msg, usize_t size, int eos){  if (msg) {    struct msg_mbuffer_s *mb = msg->m_buffer;    assert(mb->mb_used + mb->mb_commit + size <= mb->mb_size);    mb->mb_commit += size;    mb->mb_eos = eos;    if (mb->mb_used == 0 && !msg->m_chunk && !msg->m_set_buffer) {      size_t slack = mb->mb_size - mb->mb_commit;      if (eos || slack >= msg_min_size) {	/* realloc and cut down buffer */	size_t new_size;	void *new_data;		if (eos)	  new_size = mb->mb_commit + 1;	else	  new_size = mb->mb_commit + msg_min_size;	new_data = su_realloc(msg->m_home, mb->mb_data, new_size);	if (new_data) {	  mb->mb_data = new_data, mb->mb_size = new_size;	}      }    }  }  return 0;}/** Get length of committed data */usize_t msg_buf_committed(msg_t const *msg){  if (msg)    return msg->m_buffer->mb_commit;  else    return 0;}/** Get committed data */void *msg_buf_committed_data(msg_t const *msg){  return msg && msg->m_buffer->mb_data ?    msg->m_buffer->mb_data + msg->m_buffer->mb_used    : NULL;}usize_t msg_buf_size(msg_t const *msg){  assert(msg);  if (msg) {    struct msg_mbuffer_s const *mb = msg->m_buffer;    return mb->mb_size - mb->mb_commit - mb->mb_used;  }  else    return 0;}su_inlinevoid msg_buf_used(msg_t *msg, usize_t used){  msg->m_size += used;  msg->m_buffer->mb_used += used;  if (msg->m_buffer->mb_commit > used)    msg->m_buffer->mb_commit -= used;  else    msg->m_buffer->mb_commit = 0;}/** Set buffer. */void msg_buf_set(msg_t *msg, void *b, usize_t size){  if (msg) {    struct msg_mbuffer_s *mb = msg->m_buffer;    assert(!msg->m_set_buffer);	/* This can be set only once */    mb->mb_data = b;    mb->mb_size = size;    mb->mb_used = 0;    mb->mb_commit = 0;    mb->mb_eos  = 0;    msg->m_set_buffer = 1;  }}/** Move unparsed data from src to dst */void *msg_buf_move(msg_t *dst, msg_t const *src){  void *retval;  struct msg_mbuffer_s *db = dst->m_buffer;  struct msg_mbuffer_s const *sb = src->m_buffer;  if (!dst || !src)    return NULL;  if (sb->mb_eos)    retval = msg_buf_exact(dst, sb->mb_commit + 1);  else    retval = msg_buf_alloc(dst, sb->mb_commit + 1);  if (retval == NULL)    return NULL;  memcpy(retval, sb->mb_data + sb->mb_used, sb->mb_commit);  db->mb_commit += sb->mb_commit;  db->mb_eos = sb->mb_eos;  return retval;}/**Obtain I/O vector for receiving the data. * * @relatesalso msg_s * * Allocate buffers for receiving @a n bytes * of data available from network. Function returns the buffers in the I/O vector * @a vec. The @a vec is allocated by the caller, the available length is * given as @a veclen. If the protocol is message-oriented like UDP or SCTP * and the available data ends at message boundary, the caller should set * the @a exact as 1. Otherwise some extra buffer (known as @em slack) is * allocated). * * Currently, the msg_recv_iovec() allocates receive buffers in at most two * blocks, so the caller should allocate at least two elements for the I/O * vector @a vec. * * @param[in]  msg     message object  * @param[out] vec     I/O vector  * @param[in]  veclen  available length of @a vec  * @param[in]  n       number of possibly available bytes

⌨️ 快捷键说明

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