718 lines
23 KiB
C
718 lines
23 KiB
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
|
|
*
|
|
*/
|
|
|
|
/**@CFILE sip_mime.c
|
|
*
|
|
* MIME-related SIP headers
|
|
*
|
|
* @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/sip_parser.h"
|
|
#include "sofia-sip/msg_mime_protos.h"
|
|
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
/* ====================================================================== */
|
|
|
|
/**@SIP_HEADER sip_accept Accept Header
|
|
*
|
|
* The @b Accept request-header field can be used to specify certain media
|
|
* types which are acceptable for the response. Its syntax is defined in
|
|
* [H14.1, S10.6] as follows:
|
|
*
|
|
* @code
|
|
* Accept = "Accept" HCOLON
|
|
* [ accept-range *(COMMA accept-range) ]
|
|
* accept-range = media-range *(SEMI accept-param)
|
|
* media-range = ( "*" "/" "*"
|
|
* / ( m-type SLASH "*" )
|
|
* / ( m-type SLASH m-subtype )
|
|
* ) *( SEMI m-parameter )
|
|
* accept-param = ("q" EQUAL qvalue) / generic-param
|
|
* qvalue = ( "0" [ "." 0*3DIGIT ] )
|
|
* / ( "1" [ "." 0*3("0") ] )
|
|
* generic-param = token [ EQUAL gen-value ]
|
|
* gen-value = token / host / quoted-string
|
|
* @endcode
|
|
*
|
|
*
|
|
* The parsed Accept header is stored in #sip_accept_t structure.
|
|
*/
|
|
|
|
/**@ingroup sip_accept
|
|
* @typedef typedef struct sip_accept_s sip_accept_t;
|
|
*
|
|
* The structure #sip_accept_t contains representation of SIP
|
|
* @Accept header.
|
|
*
|
|
* The #sip_accept_t is defined as follows:
|
|
* @code
|
|
* typedef struct sip_accept_s {
|
|
* sip_common_t ac_common[1]; // Common fragment info
|
|
* sip_accept_t *ac_next; // Pointer to next @Acceptheader
|
|
* char const *ac_type; // Pointer to type/subtype
|
|
* char const *ac_subtype; // Points after first slash in type
|
|
* msg_param_t const *ac_params; // List of parameters
|
|
* char const *ac_q; // Value of q parameter
|
|
* } sip_accept_t;
|
|
* @endcode
|
|
*/
|
|
|
|
#define sip_accept_dup_xtra msg_accept_dup_xtra
|
|
#define sip_accept_dup_one msg_accept_dup_one
|
|
#define sip_accept_update msg_accept_update
|
|
|
|
msg_hclass_t sip_accept_class[] =
|
|
SIP_HEADER_CLASS(accept, "Accept", "", ac_params, apndlist, accept);
|
|
|
|
issize_t sip_accept_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|
{
|
|
return msg_accept_d(home, h, s, slen);
|
|
}
|
|
|
|
issize_t sip_accept_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
|
{
|
|
return msg_accept_e(b, bsiz, h, flags);
|
|
}
|
|
|
|
#if SIP_HAVE_ACCEPT_DISPOSITION
|
|
/* ====================================================================== */
|
|
|
|
/**@SIP_HEADER sip_accept_disposition Accept-Disposition Header
|
|
*
|
|
* The Accept-Disposition header field is used to indicate what content
|
|
* disposition types are acceptable to a client or server. Its syntax is
|
|
* defined in draft-lennox-sip-reg-payload-01.txt section 3.2 as follows:
|
|
*
|
|
* @code
|
|
* Accept-Disposition = "Accept-Disposition" ":"
|
|
* #( (disposition-type | "*") *( ";" generic-param ) )
|
|
* @endcode
|
|
*
|
|
*
|
|
* The parsed Accept-Disposition header
|
|
* is stored in #sip_accept_disposition_t structure.
|
|
*/
|
|
|
|
msg_hclass_t sip_accept_disposition_class[] =
|
|
SIP_HEADER_CLASS(accept_disposition, "Accept-Disposition", "",
|
|
ad_params, apndlist, accept_disposition);
|
|
|
|
issize_t sip_accept_disposition_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|
{
|
|
sip_accept_disposition_t *ad = (sip_accept_disposition_t *)h;
|
|
|
|
assert(h);
|
|
|
|
/* Ignore empty entries (comma-whitespace) */
|
|
while (*s == ',')
|
|
s += span_lws(s + 1) + 1;
|
|
|
|
/* "Accept:" #(type/subtyp ; *(parameters))) */
|
|
if (/* Parse protocol */
|
|
sip_version_d(&s, &ad->ad_type) == -1 ||
|
|
(ad->ad_subtype = strchr(ad->ad_type, '/')) == NULL ||
|
|
(*s == ';' && msg_params_d(home, &s, &ad->ad_params) == -1))
|
|
return -1;
|
|
|
|
if (ad->ad_subtype) ad->ad_subtype++;
|
|
|
|
return msg_parse_next_field(home, h, s, slen);
|
|
}
|
|
|
|
issize_t sip_accept_disposition_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
|
{
|
|
char *b0 = b, *end = b + bsiz;
|
|
sip_accept_disposition_t const *ad = h->sh_accept_disposition;
|
|
|
|
MSG_STRING_E(b, end, ad->ad_type);
|
|
MSG_PARAMS_E(b, end, ad->ad_params, flags);
|
|
MSG_TERM_E(b, end);
|
|
|
|
return b - b0;
|
|
}
|
|
#endif
|
|
|
|
/* ====================================================================== */
|
|
|
|
/**@SIP_HEADER sip_accept_encoding Accept-Encoding Header
|
|
*
|
|
* The Accept-Encoding header is similar to Accept, but restricts the
|
|
* content-codings that are acceptable in the response. Its syntax is
|
|
* defined in [H14.3, S10.7] as follows:
|
|
*
|
|
* @code
|
|
* Accept-Encoding = "Accept-Encoding" HCOLON
|
|
* [ encoding *(COMMA encoding) ]
|
|
* encoding = codings *(SEMI accept-param)
|
|
* codings = content-coding / "*"
|
|
* content-coding = token
|
|
* @endcode
|
|
*
|
|
*
|
|
* The parsed Accept-Encoding header
|
|
* is stored in #sip_accept_encoding_t structure.
|
|
*/
|
|
|
|
/**@ingroup sip_accept_encoding
|
|
* @typedef typedef struct msg_accept_any_s sip_accept_encoding_t;
|
|
*
|
|
* The structure #sip_accept_encoding_t contains representation of SIP
|
|
* @AcceptEncoding header.
|
|
*
|
|
* The #sip_accept_encoding_t is defined as follows:
|
|
* @code
|
|
* typedef struct {
|
|
* msg_common_t aa_common[1]; // Common fragment info
|
|
* sip_accept_encoding_t *aa_next; // Pointer to next @AcceptEncoding header
|
|
* char const *aa_value; // Encoding token
|
|
* msg_param_t const *aa_params; // List of parameters
|
|
* char const *aa_q; // Value of q parameter
|
|
* } sip_accept_encoding_t;
|
|
* @endcode
|
|
*/
|
|
|
|
#define sip_accept_encoding_dup_xtra msg_accept_any_dup_xtra
|
|
#define sip_accept_encoding_dup_one msg_accept_any_dup_one
|
|
#define sip_accept_encoding_update msg_accept_any_update
|
|
|
|
msg_hclass_t sip_accept_encoding_class[] =
|
|
SIP_HEADER_CLASS(accept_encoding, "Accept-Encoding", "",
|
|
aa_params, apndlist, accept_encoding);
|
|
|
|
issize_t sip_accept_encoding_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|
{
|
|
issize_t retval = msg_accept_encoding_d(home, h, s, slen);
|
|
|
|
if (retval == -2) {
|
|
/* Empty Accept-Encoding list is not an error */
|
|
sip_accept_encoding_t *aa = (sip_accept_encoding_t *)h;
|
|
aa->aa_value = "";
|
|
retval = 0;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
issize_t sip_accept_encoding_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|
{
|
|
return msg_accept_encoding_e(b, bsiz, h, f);
|
|
}
|
|
|
|
/* ====================================================================== */
|
|
|
|
/**@SIP_HEADER sip_accept_language Accept-Language Header
|
|
*
|
|
* The Accept-Language header can be used to allow the client to indicate to
|
|
* the server in which language it would prefer to receive reason phrases,
|
|
* session descriptions or status responses carried as message bodies. Its
|
|
* syntax is defined in [H14.4, S10.8] as follows:
|
|
*
|
|
* @code
|
|
* Accept-Language = "Accept-Language" HCOLON
|
|
* [ language *(COMMA language) ]
|
|
* language = language-range *(SEMI accept-param)
|
|
* language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) / "*" )
|
|
* @endcode
|
|
*
|
|
*
|
|
* The parsed Accept-Language header
|
|
* is stored in #sip_accept_language_t structure.
|
|
*/
|
|
|
|
/**@ingroup sip_accept_language
|
|
* @typedef typedef struct msg_accept_any_s sip_accept_language_t;
|
|
*
|
|
* The structure #sip_accept_language_t contains representation of SIP
|
|
* @AcceptLanguage header.
|
|
*
|
|
* The #sip_accept_language_t is defined as follows:
|
|
* @code
|
|
* typedef struct {
|
|
* msg_common_t aa_common[1]; // Common fragment info
|
|
* sip_accept_language_t *aa_next; // Pointer to next <language>
|
|
* char const *aa_value; // Language-range
|
|
* msg_param_t const *aa_params; // List of accept-parameters
|
|
* char const *aa_q; // Value of q parameter
|
|
* } sip_accept_language_t;
|
|
* @endcode
|
|
*/
|
|
|
|
#define sip_accept_language_dup_xtra msg_accept_any_dup_xtra
|
|
#define sip_accept_language_dup_one msg_accept_any_dup_one
|
|
#define sip_accept_language_update msg_accept_any_update
|
|
|
|
msg_hclass_t sip_accept_language_class[] =
|
|
SIP_HEADER_CLASS(accept_language, "Accept-Language", "",
|
|
aa_params, apndlist, accept_language);
|
|
|
|
issize_t sip_accept_language_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|
{
|
|
int retval = msg_accept_language_d(home, h, s, slen);
|
|
|
|
if (retval == -2) {
|
|
/* Empty Accept-Language list is not an error */
|
|
((sip_accept_language_t *)h)->aa_value = "";
|
|
retval = 0;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
issize_t sip_accept_language_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|
{
|
|
return msg_accept_language_e(b, bsiz, h, f);
|
|
}
|
|
|
|
/* ====================================================================== */
|
|
|
|
/**@SIP_HEADER sip_content_disposition Content-Disposition Header
|
|
*
|
|
* The Content-Disposition header field describes how the message body or,
|
|
* in the case of multipart messages, a message body part is to be
|
|
* interpreted by the UAC or UAS. Its syntax is defined in @RFC3261
|
|
* as follows:
|
|
*
|
|
* @code
|
|
* Content-Disposition = "Content-Disposition" HCOLON
|
|
* disp-type *( SEMI disp-param )
|
|
* disp-type = "render" / "session" / "icon" / "alert"
|
|
* / disp-extension-token
|
|
* disp-param = handling-param / generic-param
|
|
* handling-param = "handling" EQUAL
|
|
* ( "optional" / "required"
|
|
* / other-handling )
|
|
* other-handling = token
|
|
* disp-extension-token = token
|
|
* @endcode
|
|
*
|
|
* The Content-Disposition header was extended by
|
|
* draft-lennox-sip-reg-payload-01.txt section 3.1 as follows:
|
|
*
|
|
* @code
|
|
* Content-Disposition = "Content-Disposition" ":"
|
|
* disposition-type *( ";" disposition-param )
|
|
* disposition-type = "script" | "sip-cgi" | token
|
|
* disposition-param = action-param
|
|
* | modification-date-param
|
|
* | generic-param
|
|
* action-param = "action" "=" action-value
|
|
* action-value = "store" | "remove" | token
|
|
* modification-date-param = "modification-date" "=" quoted-date-time
|
|
* quoted-date-time = <"> SIP-date <">
|
|
* @endcode
|
|
*
|
|
* The parsed Content-Disposition header
|
|
* is stored in #sip_content_disposition_t structure.
|
|
*/
|
|
|
|
/**@ingroup sip_content_disposition
|
|
* @typedef struct msg_content_disposition_s sip_content_disposition_t;
|
|
*
|
|
* The structure #sip_content_disposition_t contains representation of an
|
|
* @ContentDisposition header.
|
|
*
|
|
* The #sip_content_disposition_t is defined as follows:
|
|
* @code
|
|
* typedef struct msg_content_disposition_s
|
|
* {
|
|
* msg_common_t cd_common[1]; // Common fragment info
|
|
* msg_error_t *cd_next; // Link to next (dummy)
|
|
* char const *cd_type; // Disposition type
|
|
* msg_param_t const *cd_params; // List of parameters
|
|
* char const *cd_handling; // Value of @b handling parameter
|
|
* unsigned cd_required:1; // True if handling=required
|
|
* unsigned cd_optional:1; // True if handling=optional
|
|
* } sip_content_disposition_t;
|
|
* @endcode
|
|
*/
|
|
|
|
static msg_xtra_f sip_content_disposition_dup_xtra;
|
|
static msg_dup_f sip_content_disposition_dup_one;
|
|
#define sip_content_disposition_update msg_content_disposition_update
|
|
|
|
msg_hclass_t sip_content_disposition_class[] =
|
|
SIP_HEADER_CLASS(content_disposition, "Content-Disposition", "", cd_params,
|
|
single, content_disposition);
|
|
|
|
issize_t sip_content_disposition_d(su_home_t *home, sip_header_t *h,
|
|
char *s, isize_t slen)
|
|
{
|
|
return msg_content_disposition_d(home, h, s, slen);
|
|
}
|
|
|
|
issize_t sip_content_disposition_e(char b[], isize_t bsiz,
|
|
sip_header_t const *h, int f)
|
|
{
|
|
return msg_content_disposition_e(b, bsiz, h, f);
|
|
}
|
|
|
|
static
|
|
isize_t sip_content_disposition_dup_xtra(sip_header_t const *h, isize_t offset)
|
|
{
|
|
return msg_content_disposition_dup_xtra(h, offset);
|
|
}
|
|
|
|
/** Duplicate one #sip_content_disposition_t object */
|
|
static
|
|
char *sip_content_disposition_dup_one(sip_header_t *dst,
|
|
sip_header_t const *src,
|
|
char *b, isize_t xtra)
|
|
{
|
|
return msg_content_disposition_dup_one(dst, src, b, xtra);
|
|
}
|
|
|
|
|
|
/* ====================================================================== */
|
|
|
|
/**@SIP_HEADER sip_content_encoding Content-Encoding Header
|
|
*
|
|
* The Content-Encoding header indicates what additional content codings
|
|
* have been applied to the entity-body. Its syntax is defined in @RFC3261
|
|
* as follows:
|
|
*
|
|
* @code
|
|
* Content-Encoding = ( "Content-Encoding" / "e" ) HCOLON
|
|
* content-coding *(COMMA content-coding)
|
|
* content-coding = token
|
|
* @endcode
|
|
*
|
|
* The parsed Content-Encoding header
|
|
* is stored in #sip_content_encoding_t structure.
|
|
*/
|
|
|
|
/**@ingroup sip_content_encoding
|
|
* @typedef struct msg_list_s sip_content_encoding_t;
|
|
*
|
|
* The structure #sip_content_encoding_t contains representation of an
|
|
* @ContentEncoding header.
|
|
*
|
|
* The #sip_content_encoding_t is defined as follows:
|
|
* @code
|
|
* typedef struct msg_list_s
|
|
* {
|
|
* msg_common_t k_common[1]; // Common fragment info
|
|
* msg_list_t *k_next; // Link to next header
|
|
* msg_param_t *k_items; // List of items
|
|
* } sip_content_encoding_t;
|
|
* @endcode
|
|
*/
|
|
|
|
msg_hclass_t sip_content_encoding_class[] =
|
|
SIP_HEADER_CLASS_LIST(content_encoding, "Content-Encoding", "e", list);
|
|
|
|
issize_t sip_content_encoding_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|
{
|
|
return msg_list_d(home, h, s, slen);
|
|
}
|
|
|
|
issize_t sip_content_encoding_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|
{
|
|
return msg_list_e(b, bsiz, h, f);
|
|
}
|
|
|
|
/* ====================================================================== */
|
|
|
|
/**@SIP_HEADER sip_content_language Content-Language Header
|
|
*
|
|
* The Content-Language header @RFC2616 section 14.12 describes the natural language(s) of
|
|
* the intended audience for the enclosed entity. Note that this might not
|
|
* be equivalent to all the languages used within the entity-body. Its
|
|
* syntax is defined in @RFC3261 as follows:
|
|
*
|
|
* @code
|
|
* Content-Language = "Content-Language" HCOLON
|
|
* language-tag *(COMMA language-tag)
|
|
* language-tag = primary-tag *( "-" subtag )
|
|
* primary-tag = 1*8ALPHA
|
|
* subtag = 1*8ALPHA
|
|
* @endcode
|
|
*
|
|
* The parsed Content-Language header
|
|
* is stored in #sip_content_language_t structure.
|
|
*/
|
|
|
|
/**@ingroup sip_content_language
|
|
* @typedef typedef struct msg_content_language_s sip_content_language_t;
|
|
*
|
|
* The structure #sip_content_language_t contains representation of
|
|
* @ContentLanguage header.
|
|
*
|
|
* The #sip_content_language_t is defined as follows:
|
|
* @code
|
|
* typedef struct {
|
|
* msg_common_t k_common[1]; // Common fragment info
|
|
* msg_content_language_t *k_next; // (Content-Encoding header)
|
|
* msg_param_t *k_items; // List of languages
|
|
* } sip_content_language_t;
|
|
* @endcode
|
|
*/
|
|
|
|
msg_hclass_t sip_content_language_class[] =
|
|
SIP_HEADER_CLASS_LIST(content_language, "Content-Language", "", list);
|
|
|
|
issize_t sip_content_language_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|
{
|
|
return msg_list_d(home, h, s, slen);
|
|
}
|
|
|
|
issize_t sip_content_language_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|
{
|
|
return msg_list_e(b, bsiz, h, f);
|
|
}
|
|
|
|
/* ====================================================================== */
|
|
|
|
/**@SIP_HEADER sip_content_type Content-Type Header
|
|
*
|
|
* The Content-Type header indicates the media type of the message-body sent
|
|
* to the recipient. Its syntax is defined in [H3.7, S] as
|
|
* follows:
|
|
*
|
|
* @code
|
|
* Content-Type = ( "Content-Type" / "c" ) HCOLON media-type
|
|
* media-type = m-type SLASH m-subtype *(SEMI m-parameter)
|
|
* m-type = discrete-type / composite-type
|
|
* discrete-type = "text" / "image" / "audio" / "video"
|
|
* / "application" / extension-token
|
|
* composite-type = "message" / "multipart" / extension-token
|
|
* extension-token = ietf-token / x-token
|
|
* ietf-token = token
|
|
* x-token = "x-" token
|
|
* m-subtype = extension-token / iana-token
|
|
* iana-token = token
|
|
* m-parameter = m-attribute EQUAL m-value
|
|
* m-attribute = token
|
|
* m-value = token / quoted-string
|
|
* @endcode
|
|
*
|
|
* The parsed Content-Type header is stored in #sip_content_type_t structure.
|
|
*/
|
|
|
|
/**@ingroup sip_content_type
|
|
* @typedef typedef struct sip_content_type_s sip_content_type_t;
|
|
*
|
|
* The structure #sip_content_type_t contains representation of SIP
|
|
* @ContentType header.
|
|
*
|
|
* The #sip_content_type_t is defined as follows:
|
|
* @code
|
|
* typedef struct sip_content_type_s {
|
|
* sip_common_t c_common[1]; // Common fragment info
|
|
* sip_unknown_t *c_next; // Dummy link to next
|
|
* char const *c_type; // Pointer to type/subtype
|
|
* char const *c_subtype; // Points after first slash in type
|
|
* msg_param_t const *c_params; // List of parameters
|
|
* } sip_content_type_t;
|
|
* @endcode
|
|
*
|
|
* The whitespace in the @a c_type is always removed when parsing.
|
|
*/
|
|
|
|
static msg_xtra_f sip_content_type_dup_xtra;
|
|
static msg_dup_f sip_content_type_dup_one;
|
|
#define sip_content_type_update NULL
|
|
|
|
msg_hclass_t sip_content_type_class[] =
|
|
SIP_HEADER_CLASS(content_type, "Content-Type", "c", c_params,
|
|
single, content_type);
|
|
|
|
issize_t sip_content_type_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|
{
|
|
sip_content_type_t *c;
|
|
|
|
assert(h);
|
|
|
|
c = h->sh_content_type;
|
|
|
|
/* "Content-type:" type/subtyp *(; parameter))) */
|
|
if (/* Parse protocol */
|
|
sip_version_d(&s, &c->c_type) == -1 || /* compacts token / token */
|
|
(c->c_subtype = strchr(c->c_type, '/')) == NULL ||
|
|
(*s == ';' && msg_params_d(home, &s, &c->c_params) == -1) ||
|
|
(*s != '\0'))
|
|
return -1;
|
|
|
|
c->c_subtype++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
issize_t sip_content_type_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
|
{
|
|
char *b0 = b, *end = b + bsiz;
|
|
sip_content_type_t const *c = h->sh_content_type;
|
|
|
|
MSG_STRING_E(b, end, c->c_type);
|
|
MSG_PARAMS_E(b, end, c->c_params, flags);
|
|
MSG_TERM_E(b, end);
|
|
|
|
return b - b0;
|
|
}
|
|
|
|
static
|
|
isize_t sip_content_type_dup_xtra(sip_header_t const *h, isize_t offset)
|
|
{
|
|
sip_content_type_t const *c = h->sh_content_type;
|
|
|
|
MSG_PARAMS_SIZE(offset, c->c_params);
|
|
offset += MSG_STRING_SIZE(c->c_type);
|
|
|
|
return offset;
|
|
}
|
|
|
|
/** Duplicate one #sip_content_type_t object */
|
|
static
|
|
char *sip_content_type_dup_one(sip_header_t *dst, sip_header_t const *src,
|
|
char *b, isize_t xtra)
|
|
{
|
|
sip_content_type_t *c = dst->sh_content_type;
|
|
sip_content_type_t const *o = src->sh_content_type;
|
|
char *end = b + xtra;
|
|
|
|
b = msg_params_dup(&c->c_params, o->c_params, b, xtra);
|
|
MSG_STRING_DUP(b, c->c_type, o->c_type);
|
|
c->c_subtype = strchr(c->c_type, '/');
|
|
c->c_subtype++;
|
|
|
|
assert(b <= end); (void)end;
|
|
|
|
return b;
|
|
}
|
|
|
|
/* ====================================================================== */
|
|
|
|
/**@SIP_HEADER sip_mime_version MIME-Version Header
|
|
*
|
|
* MIME-Version header indicates what version of the MIME protocol was used
|
|
* to construct the message. Its syntax is defined in [H19.4.1, S10.28]
|
|
* as follows:
|
|
*
|
|
* @code
|
|
* MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT
|
|
* @endcode
|
|
*
|
|
* The parsed MIME-Version header is stored in #sip_mime_version_t structure.
|
|
*/
|
|
|
|
/**@ingroup sip_mime_version
|
|
* @typedef struct msg_generic_s sip_mime_version_t;
|
|
*
|
|
* The structure #sip_mime_version_t contains representation of an
|
|
* @MIMEVersion header.
|
|
*
|
|
* The #sip_mime_version_t is defined as follows:
|
|
* @code
|
|
* typedef struct msg_generic_s
|
|
* {
|
|
* msg_common_t g_common[1]; // Common fragment info
|
|
* msg_generic_t *g_next; // Link to next header
|
|
* char const *g_string; // Header value
|
|
* } sip_mime_version_t;
|
|
* @endcode
|
|
*/
|
|
|
|
msg_hclass_t sip_mime_version_class[] =
|
|
SIP_HEADER_CLASS_G(mime_version, "MIME-Version", "", single);
|
|
|
|
issize_t sip_mime_version_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|
{
|
|
return sip_generic_d(home, h, s, slen);
|
|
}
|
|
|
|
issize_t sip_mime_version_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|
{
|
|
return sip_generic_e(b, bsiz, h, f);
|
|
}
|
|
|
|
/* ====================================================================== */
|
|
|
|
/**@SIP_HEADER sip_warning Warning Header
|
|
*
|
|
* The Warning response-header field is used to carry additional information
|
|
* about the status of a response. Its syntax is defined in @RFC3261 as
|
|
* follows:
|
|
*
|
|
* @code
|
|
* Warning = "Warning" HCOLON warning-value *(COMMA warning-value)
|
|
* warning-value = warn-code SP warn-agent SP warn-text
|
|
* warn-code = 3DIGIT
|
|
* warn-agent = hostport / pseudonym
|
|
* ; the name or pseudonym of the server adding
|
|
* ; the Warning header, for use in debugging
|
|
* warn-text = quoted-string
|
|
* pseudonym = token
|
|
* @endcode
|
|
*
|
|
* The parsed Warning header is stored in #sip_warning_t structure.
|
|
*/
|
|
|
|
/**@ingroup sip_warning
|
|
* @typedef struct msg_warning_s sip_warning_t;
|
|
*
|
|
* The structure #sip_warning_t contains representation of an
|
|
* @Warning header.
|
|
*
|
|
* The #sip_warning_t is defined as follows:
|
|
* @code
|
|
* typedef struct msg_warning_s
|
|
* {
|
|
* msg_common_t w_common[1]; // Common fragment info
|
|
* msg_warning_t *w_next; // Link to next @Warning header
|
|
* unsigned w_code; // Warning code
|
|
* char const *w_host; // Hostname or pseudonym
|
|
* char const *w_port; // Port number
|
|
* char const *w_text; // Warning text
|
|
* } sip_warning_t;
|
|
* @endcode
|
|
*/
|
|
|
|
#define sip_warning_dup_xtra msg_warning_dup_xtra
|
|
#define sip_warning_dup_one msg_warning_dup_one
|
|
#define sip_warning_update NULL
|
|
|
|
msg_hclass_t sip_warning_class[] =
|
|
SIP_HEADER_CLASS(warning, "Warning", "", w_common, append, warning);
|
|
|
|
issize_t sip_warning_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|
{
|
|
return msg_warning_d(home, h, s, slen);
|
|
}
|
|
issize_t sip_warning_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|
{
|
|
return msg_warning_e(b, bsiz, h, f);
|
|
}
|