Commit c197093b authored by Pekka Pessi's avatar Pekka Pessi

sip: added Refer-Sub header.

darcs-hash:20061005232553-65a35-345806fe532524155ad247e049ff456d8123b02d.gz
parent 69380514
Description of Adding a SIP Header to Sofia SIP
===============================================
by Pekka Pessi (2002-08-16, updated 2006-05-11)
by Pekka Pessi (2002-08-16, updated 2006-10-03)
There are two ways to extend the Sofia SIP parser, either including a
standard header in normal distribution or putting the non-standar extension
headers into a separate library.
There are three ways to extend the Sofia SIP parser, including a standard
header in sip_t structure, including a standard header in extra headers or
putting the extension headers into a separate library.
Probalem with extending #sip_t is that it breaks binary compatibility.
In the text below, we use "Example" header as our example with following
ABNF:
......
......@@ -23,9 +23,11 @@ check_PROGRAMS = torture_sip \
# Rules for building the targets
GENERATED_H = sofia-sip/sip_hclasses.h \
sofia-sip/sip_protos.h sofia-sip/sip_tag.h
sofia-sip/sip_protos.h sofia-sip/sip_tag.h \
sofia-sip/sip_extra.h
H_IN = sofia-sip/sip_hclasses.h.in \
sofia-sip/sip_protos.h.in sofia-sip/sip_tag.h.in
sofia-sip/sip_protos.h.in sofia-sip/sip_tag.h.in \
sofia-sip/sip_extra.h.in
PUBLIC_H = sofia-sip/sip.h sofia-sip/sip_util.h \
sofia-sip/sip_header.h sofia-sip/sip_parser.h \
......@@ -68,7 +70,7 @@ date_test_LDFLAGS = -static
EXTRA_DIST = Doxyfile sip.docs sip_parser.docs sip.doxyaliases \
ADD-A-HEADER GRAMMAR sip_bad_mask \
sip_parser_table.c.in sip_tag.c.in \
sip_bad_mask \
sip_extra_headers.txt \
images/sip-parser.eps images/sip-parser.gif \
images/sip-parser2.eps images/sip-parser2.gif \
images/sip-parser3.eps images/sip-parser3.gif \
......@@ -130,10 +132,20 @@ sofia-sip/sip_tag.h: sofia-sip/sip.h
@-mkdir sofia-sip 2>/dev/null || true
$(AWK_SIP_AWK) PR=$@ TEMPLATE=$(srcdir)/sofia-sip/sip_tag.h.in $<
sip_tag.c: sofia-sip/sip.h
$(AWK_SIP_AWK) PR=$@ TEMPLATE=$(srcdir)/sip_tag.c.in $<
sip_tag.c: sofia-sip/sip.h sip_extra_headers.txt
$(AWK_SIP_AWK) PR=$@ TEMPLATE=$(srcdir)/sip_tag.c.in $< \
sip_extra_headers.txt
sip_parser_table.c: sofia-sip/sip.h
$(AWK_SIP_AWK) PT=$@ TEMPLATE=$(srcdir)/sip_parser_table.c.in \
FLAGFILE=$(srcdir)/sip_bad_mask \
MC_HASH_SIZE=127 MC_SHORT_SIZE=26 $<
sofia-sip/sip_extra.h: sofia-sip/sip_extra.h.in sip_extra_headers.txt
@-mkdir -p sofia-sip 2>/dev/null
${AWK_SIP_AWK} PR=$@ NO_FIRST=1 NO_LAST=1 \
PACKAGE_NAME="${PACKAGE_NAME}" \
PACKAGE_VERSION="${PACKAGE_VERSION}" \
TEMPLATE1=${srcdir}/sofia-sip/sip_hclasses.h.in \
TEMPLATE2=${srcdir}/sofia-sip/sip_protos.h.in \
TEMPLATE=$< sip_extra_headers.txt
#
# This file specifies extra SIP headers not included in default parser table
# (nor in sip_t structure)
#
# The file format is:
# C-name @SINCE sip_t-like-comment
#
#### EXTRA HEADER LIST STARTS HERE ####
refer_sub @VERSION_1_12_4 /**< Refer-Sub header */
#### EXTRA HEADER LIST ENDS HERE ####
......@@ -40,6 +40,7 @@
#define MSG_HDR_T union sip_header_u
#include "sofia-sip/sip_parser.h"
#include "sofia-sip/sip_extra.h"
#include <stddef.h>
#include <stdlib.h>
......@@ -437,3 +438,117 @@ static int sip_replaces_update(msg_common_t *h,
return 0;
}
/* ====================================================================== */
/**@SIP_HEADER sip_refer_sub Refer-Sub Header
*
* SIP header field @b Refer-Sub is meaningful and MAY be used with a REFER
* request and the corresponding 2XX response only. This header field set to
* "false" specifies that a REFER-Issuer requests that the REFER-Recipient
* doesn't establish an implicit subscription and the resultant dialog.
*
* Refer-Sub = "Refer-Sub" HCOLON refer-sub-value *(SEMI exten)
* refer-sub-value = "true" / "false"
* exten = generic-param
*
* The parsed Refer-Sub header is stored in #sip_refer_sub_t structure.
*
* @since New in @VERSION_1_12_4. Note that #sip_t does not contain @c
* sip_refer_sub field, but use sip_refer_sub() accessor function.
*
* @sa @RFC4488, nua_refer(), #nua_i_refer
*/
/**@ingroup sip_refer_sub
*
* @typedef typedef struct sip_refer_sub_s sip_refer_sub_t;
*
* The structure #sip_refer_sub_t contains representation of @ReferSub
* header.
*
* The #sip_refer_sub_t is defined as follows:
* @code
* typedef struct sip_refer_sub_s
* {
* sip_common_t rs_common[1]; // Common fragment info
* sip_error_t *rs_next; // Dummy link to next
* char const *rs_value; // "true" or "false"
* msg_param_t const *rs_params; // List of extension parameters
* } sip_refer_sub_t;
* @endcode
*
* @since New in @VERSION_1_12_4.
*/
static msg_xtra_f sip_refer_sub_dup_xtra;
static msg_dup_f sip_refer_sub_dup_one;
#define sip_refer_sub_update NULL
msg_hclass_t sip_refer_sub_class[] =
SIP_HEADER_CLASS(refer_sub, "Refer-Sub", "", rs_params, single, refer_sub);
/** Decode (parse) @ReferSub header */
issize_t sip_refer_sub_d(su_home_t *home,
sip_header_t *h,
char *s, isize_t slen)
{
sip_refer_sub_t *rs = (sip_refer_sub_t *)h;
if (msg_token_d(&s, &rs->rs_value) < 0)
return -1;
if (strcasecmp(rs->rs_value, "false") &&
strcasecmp(rs->rs_value, "true"))
return -1;
if (*s)
if (msg_params_d(home, &s, &rs->rs_params) == -1)
return -1;
return s - rs->rs_value;
}
/** Encode (print) @ReferSub header */
issize_t sip_refer_sub_e(char b[], isize_t bsiz,
sip_header_t const *h,
int flags)
{
char *b0 = b, *end = b + bsiz;
sip_refer_sub_t const *rs = (sip_refer_sub_t *)h;
assert(sip_is_refer_sub(h));
MSG_STRING_E(b, end, rs->rs_value);
MSG_PARAMS_E(b, end, rs->rs_params, flags);
MSG_TERM_E(b, end);
return b - b0;
}
/** Calculate extra storage used by @ReferSub header field */
isize_t sip_refer_sub_dup_xtra(sip_header_t const *h, isize_t offset)
{
sip_refer_sub_t const *rs = (sip_refer_sub_t *)h;
MSG_PARAMS_SIZE(offset, rs->rs_params);
offset += MSG_STRING_SIZE(rs->rs_value);
return offset;
}
/** Duplicate a @ReferSub header field */
char *sip_refer_sub_dup_one(sip_header_t *dst, sip_header_t const *src,
char *b, isize_t xtra)
{
sip_refer_sub_t *rs_dst = (sip_refer_sub_t *)dst;
sip_refer_sub_t const *rs_src = (sip_refer_sub_t *)src;
char *end = b + xtra;
b = msg_params_dup(&rs_dst->rs_params, rs_src->rs_params, b, xtra);
MSG_STRING_DUP(b, rs_dst->rs_value, rs_src->rs_value);
assert(b <= end);
return b;
}
......@@ -68,6 +68,8 @@ tag_typedef_t siptag_header_str = STRTAG_TYPEDEF(header_str);
tag_typedef_t siptag_end = TAG_TYPEDEF(tag_end, end);
extern msg_hclass_t sip_#xxxxxx#_class[];
/**@ingroup sip_#xxxxxx#
* Tag for @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" object.
*/
......
/**@file sofia-sip/sip_extra.h.in
*
* Template for <sofia-sip/sip_extra.h>.
*
* @date Created: Thu Oct 5 19:10:58 EEST 2006
*/
/* -*- C -*-
*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2006 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
*
*/
#ifndef SIP_EXTRAS_H
/** Defined when <sofia-sip/sip_extras.h> has been included. */
#define SIP_EXTRAS_H
/**@file sofia-sip/sip_extras.h
*
* @brief Extra headers for SIP.
*
* #AUTO#
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>.
*/
#ifndef SIP_H
#include <sofia-sip/sip.h>
#endif
#ifndef SIP_HEADER_H
#include <sofia-sip/sip_header.h>
#endif
SOFIA_BEGIN_DECLS
typedef struct sip_refer_sub_s sip_refer_sub_t;
/**@ingroup sip_refer_sub
* @brief Structure for @ReferSub header.
*/
struct sip_refer_sub_s
{
sip_common_t rs_common[1]; /**< Common fragment info */
sip_error_t *rs_next; /**< Dummy link to next */
char const *rs_value; /**< "true" or "false" */
msg_param_t const *rs_params; /**< List of extension parameters */
};
/* Foo */
SOFIA_END_DECLS
#endif /** !defined(SIP_EXTRAS_H) */
......@@ -54,6 +54,8 @@ enum {
/**@ingroup sip_#xxxxxx# @internal
*
* Hash of @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#".
*
* @since New in #version#.
*/
sip_#xxxxxx#_hash = #hash#
};
......@@ -66,6 +68,8 @@ enum {
* manipulate the #sip_#xxxxxx#_t header structure.
*
* @ingroup sip_#xxxxxx#
*
* @since New in #version#.
*/
SIP_DLL extern msg_hclass_t sip_#xxxxxx#_class[];
......
......@@ -132,6 +132,7 @@ SOFIAPUBFUN issize_t sip_#xxxxxx#_e(char b[], isize_t bsiz,
/**Access a SIP @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#"
* structure #sip_#xxxxxx#_t from #sip_t.
*
* @since New in #version#.
*/
#define sip_#xxxxxx#(sip) \
((sip_#xxxxxx#_t *)msg_header_access((msg_pub_t*)(sip), sip_#xxxxxx#_class))
......@@ -148,6 +149,8 @@ SOFIAPUBFUN issize_t sip_#xxxxxx#_e(char b[], isize_t bsiz,
*
* @endcode
* @HI
*
* @since New in #version#.
*/
#define SIP_#XXXXXX#_INIT() SIP_HDR_INIT(#xxxxxx#)
......@@ -164,6 +167,8 @@ SOFIAPUBFUN issize_t sip_#xxxxxx#_e(char b[], isize_t bsiz,
*
* @endcode
* @HI
*
* @since New in #version#.
*/
#if SU_HAVE_INLINE
su_inline sip_#xxxxxx#_t *sip_#xxxxxx#_init(sip_#xxxxxx#_t x[1])
......@@ -185,6 +190,8 @@ su_inline sip_#xxxxxx#_t *sip_#xxxxxx#_init(sip_#xxxxxx#_t x[1])
*
* @retval 1 (true) if the @a header is an instance of header #xxxxxx#
* @retval 0 (false) otherwise
*
* @since New in #version#.
*/
#if SU_HAVE_INLINE
su_inline int sip_is_#xxxxxx#(sip_header_t const *header)
......@@ -224,6 +231,8 @@ int sip_is_#xxxxxx#(sip_header_t const *header);
* A pointer to the
* newly duplicated #sip_#xxxxxx#_t header structure, or NULL
* upon an error.
*
* @since New in #version#.
*/
#if SU_HAVE_INLINE
su_inline
......@@ -266,6 +275,8 @@ sip_#xxxxxx#_t *sip_#xxxxxx#_dup(su_home_t *home, sip_#xxxxxx#_t const *hdr)
*
* @return
* A pointer to newly copied header structure, or NULL upon an error.
*
* @since New in #version#.
*/
#if SU_HAVE_INLINE
su_inline
......@@ -295,6 +306,8 @@ sip_#xxxxxx#_t *sip_#xxxxxx#_copy(su_home_t *home, sip_#xxxxxx#_t const *hdr)
* @return
* A pointer to newly maked #sip_#xxxxxx#_t header structure, or NULL upon an
* error.
*
* @since New in #version#.
*/
#if SU_HAVE_INLINE
su_inline
......@@ -325,6 +338,8 @@ su_inline sip_#xxxxxx#_t *sip_#xxxxxx#_make(su_home_t *home, char const *s)
* makes header structure, or NULL upon an error.
*
* @HIDE
*
* @since New in #version#.
*/
#if SU_HAVE_INLINE
su_inline
......
......@@ -193,6 +193,8 @@ SOFIAPUBVAR tag_typedef_t siptag_header_str_ref;
* The corresponding tag taking reference parameter is
* SIPTAG_#XXXXXX#_REF().
*
* @since New in #version#.
*
* @HIDE
*/
#define SIPTAG_#XXXXXX#(x) siptag_#xxxxxx#, siptag_#xxxxxx#_v(x)
......@@ -223,6 +225,8 @@ SOFIAPUBVAR tag_typedef_t siptag_#xxxxxx#_ref;
* The corresponding tag taking reference parameter is
* SIPTAG_#XXXXXX#_STR_REF().
*
* @since New in #version#.
*
* @HIDE
*/
#define SIPTAG_#XXXXXX#_STR(s) siptag_#xxxxxx#_str, tag_str_v(s)
......
......@@ -60,6 +60,8 @@
#include <sofia-sip/msg_mclass.h>
#include <sofia-sip/msg_mclass_hash.h>
#include <sofia-sip/sip_extra.h>
int tstflags;
#define TSTFLAGS tstflags
......@@ -2067,6 +2069,7 @@ int test_refer(void)
"Refer-To: <sip:2000@10.3.3.104?Replaces=7d84c014-321368da-efa90f41%40"
"10.3.3.8%3Bto-tag%3DpaNKgBB9vQe3D%3Bfrom-tag%3D93AC8D50-7CF6DAAF>\r\n"
"Referred-By: \"Anthony Minessale\" <sip:polycom500@10.3.3.104>\r\n"
"Refer-Sub: true\r\n"
"Max-Forwards: 70\r\n"
"Content-Length: 0\r\n"
"\r\n";
......@@ -2075,15 +2078,20 @@ int test_refer(void)
msg_iovec_t *iovec;
isize_t veclen, i, size;
char *back;
sip_refer_sub_t *rs;
TEST_1(home = su_home_create());
/* Add Refer-Sub to our parser */
TEST_1(msg_mclass_insert_with_mask(test_mclass, sip_refer_sub_class,
0, 0) >= 0);
msg = read_message(0, m); TEST_1(msg); TEST_1(sip = sip_object(msg));
TEST_1(sip->sip_refer_to);
TEST_S(sip->sip_refer_to->r_url->url_headers,
"Replaces=7d84c014-321368da-efa90f41%40"
"10.3.3.8%3Bto-tag%3DpaNKgBB9vQe3D%3Bfrom-tag%3D93AC8D50-7CF6DAAF");
TEST_SIZE(msg_prepare(msg), strlen(m));
TEST(msg_prepare(msg), strlen(m));
TEST_1(veclen = msg_iovec(msg, NULL, ISIZE_MAX));
TEST_1(iovec = su_zalloc(msg_home(home), veclen * (sizeof iovec[0])));
TEST_SIZE(msg_iovec(msg, iovec, veclen), veclen);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment