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

📄 sip_basic.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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 * *//**@CFILE sip_basic.c * @brief Basic SIP headers. * * Implementation of header classes for basic SIP headers, like request and * status lines, payload, @CallID, @CSeq, @Contact, @ContentLength, @Date, * @Expires, @From, @Route, @RecordRoute, @To, and @Via. * * @author Pekka Pessi <Pekka.Pessi@nokia.com>. * * @date  Created: Tue Jun 13 02:57:51 2000 ppessi */#include "config.h"/* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */#define MSG_PUB_T       struct sip_s#define MSG_HDR_T       union sip_header_u#include <sofia-sip/su_alloc.h>#include <sofia-sip/string0.h>#include "sofia-sip/sip_parser.h"#include <sofia-sip/sip_util.h>#include <sofia-sip/sip_status.h>#include <sofia-sip/msg_date.h>#include <sofia-sip/su_uniqueid.h>#include <stddef.h>#include <stdlib.h>#include <assert.h>#include <stdio.h>#include <stdarg.h>#include <limits.h>/* ====================================================================== *//**@SIP_HEADER sip_request Request Line * * The request line is first line in a SIP request message.  Its syntax defined * in @RFC3261 as follows: *  * @code *    Request-Line   =  Method SP Request-URI SP SIP-Version CRLF *    Request-URI    =  SIP-URI / SIPS-URI / absoluteURI *    absoluteURI    =  scheme ":" ( hier-part / opaque-part ) *    hier-part      =  ( net-path / abs-path ) [ "?" query ] *    net-path       =  "//" authority [ abs-path ] *    abs-path       =  "/" path-segments *    opaque-part    =  uric-no-slash *uric *    uric           =  reserved / unreserved / escaped *    uric-no-slash  =  unreserved / escaped / ";" / "?" / ":" / "@" *                      / "&" / "=" / "+" / "$" / "," *    path-segments  =  segment *( "/" segment ) *    segment        =  *pchar *( ";" param ) *    param          =  *pchar *    pchar          =  unreserved / escaped / *                      ":" / "@" / "&" / "=" / "+" / "$" / "," *    scheme         =  ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) *    authority      =  srvr / reg-name *    srvr           =  [ [ userinfo "@" ] hostport ] *    reg-name       =  1*( unreserved / escaped / "$" / "," *                      / ";" / ":" / "@" / "&" / "=" / "+" ) *    query          =  *uric *    SIP-Version    =  "SIP" "/" 1*DIGIT "." 1*DIGIT * @endcode * * The parsed request-line is stored in #sip_request_t structure. *//**@ingroup sip_request * @typedef typedef struct sip_request_s sip_request_t; * * The structure #sip_request_t contains representation of SIP request line. * * The #sip_request_t is defined as follows: * @code * typedef struct sip_request_s { *   sip_common_t     rq_common[1];     // Common fragment info *   sip_unknown_t   *rq_next;          // Link to next (dummy) *   sip_method_t     rq_method;        // Method enum *   char const      *rq_method_name;   // Method name *   url_t            rq_url[1];        // RequestURI *   char const      *rq_version;       // Protocol version * } sip_request_t; * @endcode */#define sip_request_insert msg_request_insertstatic msg_xtra_f sip_request_dup_xtra;static msg_dup_f sip_request_dup_one;#define sip_request_update NULLmsg_hclass_t sip_request_class[] = SIP_HEADER_CLASS(request, NULL, "", rq_common, single_critical, request);/**Parse @ref sip_request "request line" from a a SIP message. */issize_t sip_request_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){  sip_request_t *rq = (sip_request_t *)h;  char *uri, *version;  if (msg_firstline_d(s, &uri, &version) < 0 || !uri || !version ||      (rq->rq_method = sip_method_d(&s, &rq->rq_method_name)) < 0 || *s ||      url_d(rq->rq_url, uri) < 0 ||      sip_version_d(&version, &rq->rq_version) < 0 || *version)    return -1;  return 0;}/**Encode @ref sip_request "request line" of a a SIP message. */issize_t sip_request_e(char b[], isize_t bsiz, sip_header_t const *h, int flags){  sip_request_t const *rq = (sip_request_t *)h;  return snprintf(b, bsiz, "%s " URL_FORMAT_STRING " %s" CRLF,		  rq->rq_method_name,		  URL_PRINT_ARGS(rq->rq_url),		  rq->rq_version);}isize_t sip_request_dup_xtra(sip_header_t const *h, isize_t offset){  sip_request_t const *rq = (sip_request_t *)h;  offset += url_xtra(rq->rq_url);  if (!rq->rq_method)    offset += MSG_STRING_SIZE(rq->rq_method_name);  offset += sip_version_xtra(rq->rq_version);  return offset;}/** Duplicate one request header. */char *sip_request_dup_one(sip_header_t *dst, sip_header_t const *src,			  char *b, isize_t xtra){  sip_request_t *rq = (sip_request_t *)dst;  sip_request_t const *o = (sip_request_t *)src;  char *end = b + xtra;  URL_DUP(b, end, rq->rq_url, o->rq_url);  if (!(rq->rq_method = o->rq_method))    MSG_STRING_DUP(b, rq->rq_method_name, o->rq_method_name);  else    rq->rq_method_name = o->rq_method_name;  sip_version_dup(&b, &rq->rq_version, o->rq_version);  assert(b <= end);  return b;}/**@ingroup sip_request * * Create a @ref sip_request "request line" object.  * * Create a request line object with * method enum @a method, method name @a name, request URI @a uri, and * protocol version @a version.  The memory for the header object is * allocated from the memory home @a home. * * @param home     memory home used to allocate #sip_request_t object * @param method   method enum * @param name     method name (required if method is not well-known) * @param uri      request URI * @param version  version string (defaults to "SIP/2.0" if NULL) * * @par Example * The following code fragment creates an OPTIONS request object: * @code *   sip_request_t *rq; *   rq = sip_request_create(home, SIP_METHOD_OPTIONS, requestURI, NULL); * @endcode * @note  * If you provide an non-NULL @a version string, it is not copied. The * version string @b MUST remain constant. */sip_request_t *sip_request_create(su_home_t *home,				  sip_method_t method, char const *name,				  url_string_t const *uri,				  char const *version){  size_t xtra;   sip_request_t *rq;  if (method)    name = sip_method_name(method, name);  if (!name)    return NULL;  if (!method)    method = sip_method_code(name);  xtra = url_xtra(uri->us_url) + (method ? 0 : strlen(name) + 1);  rq = (sip_request_t *)sip_header_alloc(home, sip_request_class, xtra);  if (rq) {    char *b = (char *)(rq + 1), *end = b + xtra;    rq->rq_method      = method;    rq->rq_method_name = name;    if (!method)       MSG_STRING_DUP(b, rq->rq_method_name, name);    URL_DUP(b, end, rq->rq_url, uri->us_url);    rq->rq_version = version ? version : SIP_VERSION_CURRENT;    assert(b == end);  }  return rq;}/* ====================================================================== *//**@SIP_HEADER sip_status Status Line * * The status line is first line in a response message.  It is defined in * @RFC3261 as follows: *  * @code *    Status-Line     =  SIP-Version SP Status-Code SP Reason-Phrase CRLF *    Status-Code     =  Informational *                   /   Redirection *                   /   Success *                   /   Client-Error *                   /   Server-Error *                   /   Global-Failure *                   /   extension-code *    extension-code  =  3DIGIT *    Reason-Phrase   =  *(reserved / unreserved / escaped *                       / UTF8-NONASCII / UTF8-CONT / SP / HTAB) * @endcode * * The parsed status line is stored in #sip_status_t structure. *//**@ingroup sip_status * @typedef typedef struct sip_status_s sip_status_t; * * The structure #sip_status_t contains representation of SIP  * @ref sip_status "status line". * * The #sip_status_t is defined as follows: * @code * typedef struct sip_status_s { *   sip_common_t   st_common[1];       // Common fragment info *   sip_unknown_t *st_next;            // Link to next (dummy) *   char const    *st_version;         // Protocol version *   int            st_status;          // Status code *   char const    *st_phrase;          // Status phrase * } sip_status_t; * @endcode */static msg_xtra_f sip_status_dup_xtra;static msg_dup_f sip_status_dup_one;#define sip_status_insert msg_status_insert#define sip_status_update NULLmsg_hclass_t sip_status_class[] = SIP_HEADER_CLASS(status, NULL, "", st_common, single_critical, status);/** Parse status line */issize_t sip_status_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen){  sip_status_t *st = (sip_status_t *)h;  char *status, *phrase;  unsigned long code;  if (msg_firstline_d(s, &status, &phrase) < 0 ||      sip_version_d(&s, &st->st_version) < 0 || *s ||      (code = strtoul(status, &status, 10)) >= INT_MAX || *status)    return -1;  st->st_status = code;  st->st_phrase = phrase;  return 0;}issize_t sip_status_e(char b[], isize_t bsiz, sip_header_t const *h, int flags){  sip_status_t const *st = (sip_status_t *)h;  int status;  assert(sip_is_status(h));  status = st->st_status;  if (status > 999 || status < 100)    status = 0;  return snprintf(b, bsiz, "%s %03u %s" CRLF,		  st->st_version,		  status,		  st->st_phrase);}/** Extra size of a #sip_status_t object. */isize_t sip_status_dup_xtra(sip_header_t const *h, isize_t offset){  sip_status_t const *st = (sip_status_t *)h;  offset += sip_version_xtra(st->st_version);  offset += MSG_STRING_SIZE(st->st_phrase);  return offset;}/** Duplicate one status header. */char *sip_status_dup_one(sip_header_t *dst, sip_header_t const *src,			 char *b, isize_t xtra){  sip_status_t *st = (sip_status_t *)dst;  sip_status_t const *o = (sip_status_t *)src;  char *end = b + xtra;  sip_version_dup(&b, &st->st_version, o->st_version);  st->st_status = o->st_status;  MSG_STRING_DUP(b, st->st_phrase, o->st_phrase);  assert(b <= end); (void)end;  return b;}/**@ingroup sip_status * * Create a @ref sip_status "status line" object. * * @param home    memory home used to allocate #sip_status_t object * @param status  status code (in range 100 - 699) * @param phrase  status phrase (may be NULL) * @param version version string (defaults to "SIP/2.0" if NULL) * * @note  * If you provide an non-NULL @a version string, it is not copied. The * string @b MUST remain constant. * * @return * A pointer to newly created @ref sip_status "status line" * structure when successful, or NULL upon an error. */sip_status_t *sip_status_create(su_home_t *home,				unsigned status,				char const *phrase,				char const *version){  sip_status_t *st;  if (status < 100 || status > 699)    return NULL;  if (phrase == NULL && (phrase = sip_status_phrase(status)) == NULL)    phrase = "";  if ((st = (sip_status_t *)sip_header_alloc(home, sip_status_class, 0))) {    st->st_status = status;    st->st_phrase = phrase;    st->st_version = version ? version : SIP_VERSION_CURRENT;  }  return st;}/* ====================================================================== *//**@SIP_HEADER sip_payload Message Body * * The payload structure contains the optional message body. The message * body stored in the #sip_payload_t structure has no internal structure, * but it is accessed as a byte array. Use @ref sdp_parser "SDP parser" to * parse SDP content, for instance. * * The message body is stored in a #sip_payload_t structure. *//**@ingroup sip_payload * @typedef typedef struct sip_payload_s sip_payload_t; * * The structure #sip_payload_t contains representation of SIP message payload. * * The #sip_payload_t is defined as follows: * @code * typedef struct sip_payload_s { *   msg_common_t    pl_common[1];      // Common fragment info *   msg_header_t   *pl_next;           // Next payload (if multipart message) *   char           *pl_data;           // Data - may contain NUL *   unsigned        pl_len;            // Length of message payload * } sip_payload_t; * @endcode */#define sip_payload_d 	     msg_payload_d#define sip_payload_e 	     msg_payload_e#define sip_payload_dup_xtra msg_payload_dup_xtra #define sip_payload_dup_one  msg_payload_dup_one#define sip_payload_update   NULLmsg_hclass_t sip_payload_class[] = SIP_HEADER_CLASS(payload, NULL, "", pl_common, single, payload);/**@ingroup sip_payload * * Create a @ref sip_payload "SIP payload" structure.  * * Create a new SIP payload structure. it * copies the given data to the the payload data, and NUL terminates it (it * allocates one extra byte for NUL).  If a NULL pointer is given as @a data, * sip_payload_create() allocates and zeroes a data buffer of @a len bytes. * * @param home memory home  * @param data payload data  * @param len  payload length * * @return A pointer to newly created * payload structure, if successful, and NULL upon an error. */ sip_payload_t *sip_payload_create(su_home_t *home, void const *data, isize_t len){  msg_hclass_t *hc = sip_payload_class;  sip_header_t *h = sip_header_alloc(home, hc, len + 1);  sip_payload_t *pl = (sip_payload_t *)h;  if (pl) {    char *b = sip_header_data(h);    if (data) {      memcpy(b, data, len);      b[len] = 0;    }

⌨️ 快捷键说明

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