12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433 |
- /*
- * 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_extra.c
- * @brief Non-critical SIP headers
- *
- * This file contains implementation of @CallInfo, @ErrorInfo,
- * @Organization, @Priority, @RetryAfter, @Server, @Subject,
- * @Timestamp, and @UserAgent 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/sip_extra.h"
- #include "../su/sofia-sip/su_alloc.h"
- #include <stdio.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
- #
- #include <assert.h>
- /* ====================================================================== */
- static issize_t sip_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen);
- static isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset);
- static char *sip_info_dup_one(sip_header_t *dst,
- sip_header_t const *src,
- char *b,
- isize_t xtra);
- #define sip_info_update NULL
- /* ====================================================================== */
- /**@SIP_HEADER sip_call_info Call-Info Header
- *
- * The Call-Info header provides additional information about the caller or
- * callee. Its syntax is defined in @RFC3261 as follows:
- *
- * @code
- * Call-Info = "Call-Info" HCOLON info *(COMMA info)
- * info = LAQUOT absoluteURI RAQUOT *( SEMI info-param)
- * info-param = ( "purpose" EQUAL ( "icon" / "info"
- * / "card" / token ) ) / generic-param
- * @endcode
- *
- *
- * The parsed Call-Info header is stored in #sip_call_info_t structure.
- */
- /**@ingroup sip_call_info
- * @typedef struct sip_call_info_s sip_call_info_t;
- *
- * The structure #sip_call_info_t contains representation of an
- * @CallInfo header.
- *
- * The #sip_call_info_t is defined as follows:
- * @code
- * struct sip_call_info_s
- * {
- * sip_common_t ci_common[1]; // Common fragment info
- * sip_call_info_t *ci_next; // Link to next @CallInfo
- * url_t ci_url[1]; // URI to call info
- * msg_param_t const *ci_params; // List of parameters
- * char const *ci_purpose; // Value of @b purpose parameter
- * };
- * @endcode
- */
- #define sip_call_info_dup_xtra sip_info_dup_xtra
- #define sip_call_info_dup_one sip_info_dup_one
- static msg_update_f sip_call_info_update;
- msg_hclass_t sip_call_info_class[] =
- SIP_HEADER_CLASS(call_info, "Call-Info", "",
- ci_params, append, call_info);
- issize_t sip_call_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
- {
- issize_t retval = sip_info_d(home, h, s, slen);
- if (retval == 0)
- for (;h; h = h->sh_next)
- msg_header_update_params(h->sh_common, 0);
- return retval;
- }
- issize_t sip_call_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- sip_call_info_t *ci = (sip_call_info_t *)h;
- assert(sip_call_info_p(h));
- return sip_name_addr_e(b, bsiz, f, NULL, 1, ci->ci_url, ci->ci_params, NULL);
- }
- /** @internal
- * Update parameter in a @CallInfo object.
- *
- */
- static int
- sip_call_info_update(msg_common_t *h,
- char const *name, isize_t namelen,
- char const *value)
- {
- sip_call_info_t *ci = (sip_call_info_t *)h;
- if (name == NULL) {
- ci->ci_purpose = NULL;
- }
- else if (namelen == strlen("purpose") &&
- su_casenmatch(name, "purpose", namelen)) {
- ci->ci_purpose = value;
- }
- return 0;
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_error_info Error-Info Header
- *
- * The Error-Info header provides a pointer to additional information about
- * the error status response. Its syntax is defined in @RFC3261 as follows:
- *
- * @code
- * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri)
- * error-uri = LAQUOT absoluteURI RAQUOT *( SEMI generic-param )
- * @endcode
- *
- *
- * The parsed Error-Info header is stored in #sip_error_info_t structure.
- */
- /**@ingroup sip_error_info
- * @typedef struct sip_error_info_s sip_error_info_t;
- *
- * The structure #sip_error_info_t contains representation of an
- * @ErrorInfo header.
- *
- * The #sip_error_info_t is defined as follows:
- * @code
- * struct sip_error_info_s
- * {
- * sip_common_t ei_common[1]; // Common fragment info
- * sip_error_info_t *ei_next; // Link to next @ErrorInfo
- * url_t ei_url[1]; // URI to error info
- * msg_param_t const *ei_params; // List of parameters
- * };
- * @endcode
- */
- msg_hclass_t sip_error_info_class[] =
- SIP_HEADER_CLASS(error_info, "Error-Info", "",
- ei_params, append, info);
- issize_t sip_error_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
- {
- return sip_info_d(home, h, s, slen);
- }
- issize_t sip_error_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- sip_error_info_t const *ei = h->sh_error_info;
- assert(sip_error_info_p(h));
- return sip_name_addr_e(b, bsiz, f,
- NULL, 1, ei->ei_url, ei->ei_params, NULL);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_alert_info Alert-Info Header
- *
- * When present in an INVITE request, the Alert-Info header field
- * specifies an alternative ring tone to the UAS. When present in a 180
- * (Ringing) response, the Alert-Info header field specifies an
- * alternative ringback tone to the UAC. A typical usage is for a proxy
- * to insert this header field to provide a distinctive ring feature.
- *
- * @code
- * Alert-Info = "Alert-Info" HCOLON alert-param *(COMMA alert-param)
- * alert-param = LAQUOT absoluteURI RAQUOT *(SEMI generic-param)
- * @endcode
- *
- * The parsed Alert-Info header is stored in #sip_alert_info_t structure.
- *
- * @NEW_1_12_7. In order to use @b Alert-Info header, initialize the SIP
- * parser before calling nta_agent_create() or nua_create() with, e.g.,
- * sip_update_default_mclass(sip_extend_mclass(NULL)).
- * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
- * as return of sip_extend_mclass(NULL) requires to be freed.
- *
- * The #sip_t structure does not contain a @a sip_alert_info field, but
- * sip_alert_info() function should be used for accessing the @b Alert-Info
- * header structure.
- */
- /**@ingroup sip_alert_info
- * @typedef struct sip_alert_info_s sip_alert_info_t;
- *
- * The structure #sip_alert_info_t contains representation of an
- * @AlertInfo header.
- *
- * The #sip_alert_info_t is defined as follows:
- * @code
- * struct sip_alert_info_s
- * {
- * sip_common_t ai_common[1]; // Common fragment info
- * sip_alert_info_t *ai_next; // Link to next @AlertInfo
- * url_t ai_url[1]; // URI to alert info
- * msg_param_t const *ai_params; // List of optional parameters
- * };
- * @endcode
- *
- * @NEW_1_12_7.
- */
- msg_hclass_t sip_alert_info_class[] =
- SIP_HEADER_CLASS(alert_info, "Alert-Info", "",
- ai_params, append, info);
- issize_t sip_alert_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
- {
- return sip_info_d(home, h, s, slen);
- }
- issize_t sip_alert_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- sip_alert_info_t *ai = (sip_alert_info_t *)h;
- return sip_name_addr_e(b, bsiz, f, NULL, 1, ai->ai_url, ai->ai_params, NULL);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_reply_to Reply-To Header
- *
- * The @b Reply-To header field contains a logical return URI that may be
- * different from the @From header field. For example, the URI MAY be used to
- * return missed calls or unestablished sessions. If the user wished to
- * remain anonymous, the header field SHOULD either be omitted from the
- * request or populated in such a way that does not reveal any private
- * information. Its syntax is defined in @RFC3261 as follows:
- *
- * @code
- * Reply-To = "Reply-To" HCOLON rplyto-spec
- * rplyto-spec = ( name-addr / addr-spec )
- * *( SEMI rplyto-param )
- * rplyto-param = generic-param
- * @endcode
- *
- * The parsed Reply-To header is stored in #sip_reply_to_t structure.
- *
- * @sa sip_update_default_mclass()
- *
- * @NEW_1_12_7. In order to use @b Reply-To header,
- * initialize the SIP parser before calling nta_agent_create() or
- * nua_create() with, e.g.,
- * sip_update_default_mclass(sip_extend_mclass(NULL)).
- * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
- * as return of sip_extend_mclass(NULL) requires to be freed.
- *
- * @note
- * The #sip_t structure does not contain a @a sip_reply_to field, but
- * sip_reply_to() function should be used for accessing the @b Reply-To
- * header structure.
- */
- /**@ingroup sip_reply_to
- * @typedef struct msg_list_s sip_reply_to_t;
- *
- * The structure #sip_reply_to_t contains representation of SIP
- * @ReplyTo header.
- *
- * The #sip_reply_to_t is defined as follows:
- * @code
- * struct sip_reply_to_s
- * {
- * sip_common_t rplyto_common[1]; // Common fragment info
- * sip_reply_to_t *rplyto_next; // Dummy link to next header
- * char const *rplyto_display; // Display name
- * url_t rplyto_url[1]; // Return URI
- * msg_param_t const *rplyto_params; // List of optional parameters
- * };
- * @endcode
- */
- static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset);
- static char *sip_reply_to_dup_one(sip_header_t *dst,
- sip_header_t const *src,
- char *b,
- isize_t xtra);
- #define sip_reply_to_update NULL
- msg_hclass_t sip_reply_to_class[] =
- SIP_HEADER_CLASS(reply_to, "Reply-To", "", rplyto_params, single, reply_to);
- issize_t sip_reply_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
- {
- sip_reply_to_t *rplyto = (sip_reply_to_t *)h;
- return sip_name_addr_d(home,
- &s,
- &rplyto->rplyto_display,
- rplyto->rplyto_url,
- &rplyto->rplyto_params,
- NULL);
- }
- issize_t sip_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
- {
- sip_reply_to_t *rplyto = (sip_reply_to_t *)h;
- return sip_name_addr_e(b, bsiz,
- flags,
- rplyto->rplyto_display,
- MSG_IS_CANONIC(flags), rplyto->rplyto_url,
- rplyto->rplyto_params,
- NULL);
- }
- static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset)
- {
- sip_reply_to_t const *rplyto = (sip_reply_to_t const *)h;
- return sip_name_addr_xtra(rplyto->rplyto_display,
- rplyto->rplyto_url,
- rplyto->rplyto_params,
- offset);
- }
- /**@internal Duplicate one sip_reply_to_t object. */
- static char *sip_reply_to_dup_one(sip_header_t *dst, sip_header_t const *src,
- char *b, isize_t xtra)
- {
- sip_reply_to_t *rplyto = (sip_reply_to_t *)dst;
- sip_reply_to_t const *o = (sip_reply_to_t *)src;
- return sip_name_addr_dup(&rplyto->rplyto_display, o->rplyto_display,
- rplyto->rplyto_url, o->rplyto_url,
- &rplyto->rplyto_params, o->rplyto_params,
- b, xtra);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_in_reply_to In-Reply-To Header
- *
- * The @b In-Reply-To request header field enumerates the
- * @ref sip_call_id "Call-IDs" that this call references or returns.
- * Its syntax is defined in @RFC3261 as follows:
- *
- * @code
- * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid)
- * @endcode
- *
- * The parsed In-Reply-To header is stored in #sip_in_reply_to_t structure.
- */
- /**@ingroup sip_in_reply_to
- * @typedef struct msg_list_s sip_in_reply_to_t;
- *
- * The structure #sip_in_reply_to_t contains representation of SIP
- * @InReplyTo header.
- *
- * The #sip_in_reply_to_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 call ids
- * } sip_in_reply_to_t;
- * @endcode
- */
- msg_hclass_t sip_in_reply_to_class[] =
- SIP_HEADER_CLASS_LIST(in_reply_to, "In-Reply-To", "", list);
- issize_t sip_in_reply_to_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_in_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- assert(sip_in_reply_to_p(h));
- return msg_list_e(b, bsiz, h, f);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_organization Organization Header
- *
- * The Organization header field conveys the name of the organization to
- * which the entity issuing the request or response belongs. Its syntax is
- * defined in @RFC3261 as follows:
- *
- * @code
- * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM]
- * @endcode
- *
- *
- * The parsed Organization header is stored in #sip_organization_t structure.
- */
- /**@ingroup sip_organization
- * @typedef struct msg_generic_s sip_organization_t;
- *
- * The structure #sip_organization_t contains representation of a SIP
- * @Organization header.
- *
- * The #sip_organization_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; // Organization text
- * } sip_organization_t;
- * @endcode
- */
- msg_hclass_t sip_organization_class[] =
- SIP_HEADER_CLASS_G(organization, "Organization", "", single);
- issize_t sip_organization_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_organization_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- assert(sip_organization_p(h));
- return sip_generic_e(b, bsiz, h, f);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_priority Priority Header
- *
- * The Priority request-header field indicates the urgency of the request as
- * perceived by the client. Its syntax is defined in @RFC3261 as follows:
- *
- * @code
- * Priority = "Priority" HCOLON priority-value
- * priority-value = "emergency" / "urgent" / "normal"
- * / "non-urgent" / other-priority
- * other-priority = token
- * @endcode
- *
- *
- * The parsed Priority header is stored in #sip_priority_t structure.
- */
- /**@ingroup sip_priority
- * @typedef struct msg_generic_s sip_priority_t;
- *
- * The structure #sip_priority_t contains representation of a SIP
- * @Priority header.
- *
- * The #sip_priority_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; // Dummy link to next header
- * char const *g_string; // Priority token
- * } sip_priority_t;
- * @endcode
- */
- msg_hclass_t sip_priority_class[] =
- SIP_HEADER_CLASS_G(priority, "Priority", "", single);
- issize_t sip_priority_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
- {
- sip_priority_t *priority = (sip_priority_t *)h;
- if (msg_token_d(&s, &priority->g_string) < 0)
- return -1;
- if (*s && !IS_LWS(*s)) /* Something extra after priority token? */
- return -1;
- return 0;
- }
- issize_t sip_priority_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- assert(sip_priority_p(h));
- return sip_generic_e(b, bsiz, h, f);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_server Server Header
- *
- * The Server response-header field contains information about the software
- * used by the user agent server to handle the request. Its syntax is
- * defined in @RFC2616 section 14.38 and @RFC3261 as follows:
- *
- * @code
- * Server = "Server" HCOLON server-val *(LWS server-val)
- * server-val = product / comment
- * product = token [SLASH product-version]
- * product-version = token
- * @endcode
- *
- * The parsed Server header is stored in #sip_server_t structure.
- */
- /**@ingroup sip_server
- * @typedef struct msg_generic_s sip_server_t;
- *
- * The structure #sip_server_t contains representation of a SIP
- * @Server header.
- *
- * The #sip_server_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; // Server tokens
- * } sip_server_t;
- * @endcode
- */
- msg_hclass_t sip_server_class[] =
- SIP_HEADER_CLASS_G(server, "Server", "", single);
- issize_t sip_server_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_server_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- assert(sip_server_p(h));
- return sip_generic_e(b, bsiz, h, f);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_subject Subject Header
- *
- * The Subject header provides a summary or indicates the nature of the
- * request. Its syntax is defined in @RFC3261 as follows:
- *
- * @code
- * Subject = ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM]
- * @endcode
- *
- * The parsed Subject header is stored in #sip_subject_t structure.
- */
- /**@ingroup sip_subject
- * @typedef struct msg_generic_s sip_subject_t;
- *
- * The structure #sip_subject_t contains representation of a SIP
- * @Subject header.
- *
- * The #sip_subject_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; // Subject text
- * } sip_subject_t;
- * @endcode
- */
- msg_hclass_t sip_subject_class[] =
- SIP_HEADER_CLASS_G(subject, "Subject", "s", single);
- issize_t sip_subject_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_subject_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- assert(sip_subject_p(h));
- return sip_generic_e(b, bsiz, h, f);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_timestamp Timestamp Header
- *
- * The @b Timestamp header describes when the client sent the request to the
- * server, and it is used by the client to adjust its retransmission
- * intervals. Its syntax is defined in @RFC3261 as follows:
- *
- * @code
- * Timestamp = "Timestamp" HCOLON 1*(DIGIT)
- * [ "." *(DIGIT) ] [ LWS delay ]
- * delay = *(DIGIT) [ "." *(DIGIT) ]
- * @endcode
- *
- * The parsed Timestamp header is stored in #sip_timestamp_t structure.
- */
- /**@ingroup sip_timestamp
- * @typedef struct sip_timestamp_s sip_timestamp_t;
- *
- * The structure #sip_timestamp_t contains representation of a SIP
- * @Timestamp header.
- *
- * The #sip_timestamp_t is defined as follows:
- * @code
- * typedef struct sip_timestamp_s
- * {
- * sip_common_t ts_common[1]; // Common fragment info
- * sip_error_t *ts_next; // Dummy link
- * char const *ts_stamp; // Original timestamp
- * char const *ts_delay; // Delay at UAS
- * } sip_timestamp_t;
- * @endcode
- */
- static isize_t sip_timestamp_dup_xtra(sip_header_t const *h, isize_t offset);
- static char *sip_timestamp_dup_one(sip_header_t *dst,
- sip_header_t const *src,
- char *b,
- isize_t xtra);
- #define sip_timestamp_update NULL
- msg_hclass_t sip_timestamp_class[] =
- SIP_HEADER_CLASS(timestamp, "Timestamp", "", ts_common, single,
- timestamp);
- issize_t sip_timestamp_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
- {
- sip_timestamp_t *ts = (sip_timestamp_t*)h;
- ts->ts_stamp = s;
- s += span_digit(s);
- if (s == ts->ts_stamp)
- return -1;
- if (*s == '.') { s += span_digit(s + 1) + 1; }
- if (IS_LWS(*s)) {
- *s = '\0';
- s += span_lws(s + 1) + 1;
- ts->ts_delay = s;
- s += span_digit(s); if (*s == '.') { s += span_digit(s + 1) + 1; }
- }
- if (!*s || IS_LWS(*s))
- *s++ = '\0';
- else
- return -1;
- return 0;
- }
- issize_t sip_timestamp_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- sip_timestamp_t const *ts = h->sh_timestamp;
- char *end = b + bsiz, *b0 = b;
- assert(sip_timestamp_p(h));
- MSG_STRING_E(b, end, ts->ts_stamp);
- if (ts->ts_delay) {
- MSG_CHAR_E(b, end, ' ');
- MSG_STRING_E(b, end, ts->ts_delay);
- }
- MSG_TERM_E(b, end);
- return b - b0;
- }
- static
- isize_t sip_timestamp_dup_xtra(sip_header_t const *h, isize_t offset)
- {
- sip_timestamp_t const *ts = h->sh_timestamp;
- offset += MSG_STRING_SIZE(ts->ts_stamp);
- offset += MSG_STRING_SIZE(ts->ts_delay);
- return offset;
- }
- static
- char *sip_timestamp_dup_one(sip_header_t *dst,
- sip_header_t const *src,
- char *b,
- isize_t xtra)
- {
- sip_timestamp_t *ts = dst->sh_timestamp;
- sip_timestamp_t const *o = src->sh_timestamp;
- char *end = b + xtra;
- MSG_STRING_DUP(b, ts->ts_stamp, o->ts_stamp);
- MSG_STRING_DUP(b, ts->ts_delay, o->ts_delay);
- assert(b <= end); (void)end;
- return b;
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_user_agent User-Agent Header
- *
- * The User-Agent header contains information about the client user agent
- * originating the request. Its syntax is defined in [H14.43, S10.45] as
- * follows:
- *
- * @code
- * User-Agent = "User-Agent" HCOLON server-val *(LWS server-val)
- * server-val = product / comment
- * product = token [SLASH product-version]
- * product-version = token
- * @endcode
- *
- * The parsed User-Agent header is stored in #sip_user_agent_t structure.
- */
- /**@ingroup sip_user_agent
- * @typedef struct msg_generic_s sip_user_agent_t;
- *
- * The structure #sip_user_agent_t contains representation of a SIP
- * @UserAgent header.
- *
- * The #sip_user_agent_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; // User-Agent components
- * } sip_user_agent_t;
- * @endcode
- */
- msg_hclass_t sip_user_agent_class[] =
- SIP_HEADER_CLASS_G(user_agent, "User-Agent", "", single);
- issize_t sip_user_agent_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_user_agent_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- assert(sip_user_agent_p(h));
- return sip_generic_e(b, bsiz, h, f);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_etag SIP-ETag Header
- *
- * The @b SIP-ETag header field identifies the published event state. Its
- * syntax is defined in @RFC3903 as follows:
- *
- * @code
- * SIP-ETag = "SIP-ETag" HCOLON entity-tag
- * entity-tag = token
- * @endcode
- *
- * The parsed SIP-ETag header is stored in #sip_etag_t structure.
- */
- /**@ingroup sip_etag
- * @typedef struct msg_generic_s sip_etag_t;
- *
- * The structure #sip_etag_t contains representation of a SIP
- * @SIPETag header.
- *
- * The #sip_etag_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; // entity-tag
- * } sip_etag_t;
- * @endcode
- */
- msg_hclass_t sip_etag_class[] =
- SIP_HEADER_CLASS_G(etag, "SIP-ETag", "", single);
- issize_t sip_etag_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
- {
- sip_etag_t *etag = (sip_etag_t *)h;
- return msg_token_d(&s, &etag->g_value);
- }
- issize_t sip_etag_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- return msg_generic_e(b, bsiz, h, f);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_if_match SIP-If-Match Header
- *
- * The @b SIP-If-Match header field identifies the specific entity of event
- * state that the request is refreshing, modifying or removing. Its syntax
- * is defined in @RFC3903 as follows:
- *
- * @code
- * SIP-If-Match = "SIP-If-Match" HCOLON entity-tag
- * entity-tag = token
- * @endcode
- *
- * The parsed SIP-If-Match header is stored in #sip_if_match_t structure.
- */
- /**@ingroup sip_if_match
- * @typedef struct msg_generic_s sip_if_match_t;
- *
- * The structure #sip_if_match_t contains representation of a SIP
- * @SIPIfMatch header.
- *
- * The #sip_if_match_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; // entity-tag
- * } sip_if_match_t;
- * @endcode
- */
- msg_hclass_t sip_if_match_class[] =
- SIP_HEADER_CLASS_G(if_match, "SIP-If-Match", "", single);
- issize_t sip_if_match_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
- {
- return sip_etag_d(home, h, s, slen);
- }
- issize_t sip_if_match_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
- {
- return sip_etag_e(b, bsiz, h, f);
- }
- /* ====================================================================== */
- /** Parsing @CallInfo, @ErrorInfo. */
- static
- issize_t sip_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
- {
- sip_call_info_t *ci;
- char *end;
- for(;;) {
- ci = h->sh_call_info;
- end = s + slen;
- while (*s == ',')
- s += span_lws(s + 1) + 1;
- if (sip_name_addr_d(home, &s, NULL, ci->ci_url, &ci->ci_params, NULL) < 0)
- return -1;
- slen = end - s;
- msg_parse_next_field_without_recursion();
- }
- }
- isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset)
- {
- sip_call_info_t const *ci = h->sh_call_info;
- return sip_name_addr_xtra(NULL,
- ci->ci_url,
- ci->ci_params,
- offset);
- }
- char *sip_info_dup_one(sip_header_t *dst,
- sip_header_t const *src,
- char *b,
- isize_t xtra)
- {
- sip_call_info_t *ci = dst->sh_call_info;
- sip_call_info_t const *o = src->sh_call_info;
- return sip_name_addr_dup(NULL, NULL,
- ci->ci_url, o->ci_url,
- &ci->ci_params, o->ci_params,
- b, xtra);
- }
- /* ====================================================================== */
- #if SU_HAVE_EXPERIMENTAL
- /**@SIP_HEADER sip_suppress_body_if_match Suppress-Body-If-Match Header
- *
- * The @b Suppress-Body-If-Match header field identifies a SIP event content
- * already known by the watcher. Its syntax is defined in
- * draft-niemi-sip-subnot-etags-01 as follows:
- *
- * @code
- * Suppress-Body-If-Match = "Suppress-Body-If-Match" HCOLON entity-tag
- * entity-tag = token
- * @endcode
- *
- * The parsed Suppress-Body-If-Match header is stored in
- * #sip_suppress_body_if_match_t structure.
- *
- * @sa @RFC3265, draft-niemi-sip-subnot-etags-01.txt
- *
- * @EXP_1_12_5.
- * In order to use @b Suppress-Body-If-Match header,
- * initialize the SIP parser with, e.g.,
- * sip_update_default_mclass(sip_extend_mclass(NULL)).
- * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
- * as return of sip_extend_mclass(NULL) requires to be freed.
- *
- * @note
- * The #sip_t structure does not contain a @a
- * sip_suppress_body_if_match field, but sip_suppress_body_if_match()
- * function should be used for accessing the @b Suppress-Body-If-Match
- * header structure.
- */
- /**@ingroup sip_suppress_body_if_match
- * @typedef struct sip_suppress_body_if_match_s sip_suppress_body_if_match_t;
- *
- * The structure #sip_suppress_body_if_match_t contains representation of a
- * SIP @SuppressBodyIfMatch header.
- *
- * The #sip_suppress_body_if_match_t is defined as follows:
- * @code
- * typedef struct sip_suppress_body_if_match_s
- * {
- * sip_common_t sbim_common[1]; // Common fragment info
- * sip_error_t *sbim_next; // Dummy link to next header
- * char const *sbim_tag; // entity-tag
- * } sip_suppress_body_if_match_t;
- * @endcode
- */
- #define sip_suppress_body_if_match_dup_xtra msg_generic_dup_xtra
- #define sip_suppress_body_if_match_dup_one msg_generic_dup_one
- #define sip_suppress_body_if_match_update NULL
- msg_hclass_t sip_suppress_body_if_match_class[] =
- SIP_HEADER_CLASS(suppress_body_if_match,
- "Suppress-Body-If-Match", "",
- sbim_common, single, suppress_body_if_match);
- issize_t sip_suppress_body_if_match_d(su_home_t *home,
- sip_header_t *h,
- char *s, isize_t slen)
- {
- sip_suppress_body_if_match_t *sbim = (void *)h;
- return msg_token_d(&s, &sbim->sbim_tag);
- }
- issize_t sip_suppress_body_if_match_e(char b[], isize_t bsiz,
- sip_header_t const *h,
- int f)
- {
- return sip_etag_e(b, bsiz, h, f);
- }
- /* ====================================================================== */
- /**@SIP_HEADER sip_suppress_notify_if_match Suppress-Notify-If-Match Header
- *
- * The @b Suppress-Notify-If-Match header is used to suppress
- * superfluous NOTIFY transactions. Its syntax is defined in
- * draft-niemi-sip-subnot-etags-01 as follows:
- *
- * @code
- * Suppress-Notify-If-Match = "Suppress-Notify-If-Match" HCOLON entity-tag
- * entity-tag = token
- * @endcode
- *
- * The parsed Suppress-Notify-If-Match header is stored in
- * #sip_suppress_notify_if_match_t structure.
- *
- * @sa @RFC3265, draft-niemi-sip-subnot-etag-01
- *
- * @EXP_1_12_5.
- * In order to use @b Suppress-Notify-If-Match header,
- * initialize the SIP parser with, e.g.,
- * sip_update_default_mclass(sip_extend_mclass(NULL)).
- * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
- * as return of sip_extend_mclass(NULL) requires to be freed.
- *
- * @note
- * The #sip_t struct does not contain @a sip_suppress_notify_if_match field,
- * but sip_suppress_notify_if_match() function should be used for accessing
- * the @b Suppress-Notify-If-Match header structure.
- */
- /**@ingroup sip_suppress_notify_if_match
- * @typedef struct sip_suppress_notify_if_match_s \
- * sip_suppress_notify_if_match_t;
- *
- * The structure #sip_suppress_notify_if_match_t contains representation of a
- * SIP @SuppressNotifyIfMatch header.
- *
- * The #sip_suppress_notify_if_match_t is defined as follows:
- * @code
- * typedef struct sip_suppress_notify_if_match_s
- * {
- * sip_common_t snim_common[1]; // Common fragment info
- * sip_error_t *snim_next; // Dummy link to next header
- * char const *snim_tag; // entity-tag
- * } sip_suppress_notify_if_match_t;
- * @endcode
- */
- #define sip_suppress_notify_if_match_dup_xtra msg_generic_dup_xtra
- #define sip_suppress_notify_if_match_dup_one msg_generic_dup_one
- #define sip_suppress_notify_if_match_update NULL
- msg_hclass_t sip_suppress_notify_if_match_class[] =
- SIP_HEADER_CLASS(suppress_notify_if_match,
- "Suppress-Notify-If-Match", "",
- snim_common, single, suppress_notify_if_match);
- issize_t sip_suppress_notify_if_match_d(su_home_t *home,
- sip_header_t *h,
- char *s, isize_t slen)
- {
- sip_suppress_notify_if_match_t *snim = (void *)h;
- return msg_token_d(&s, &snim->snim_tag);
- }
- issize_t sip_suppress_notify_if_match_e(char b[], isize_t bsiz,
- sip_header_t const *h,
- int f)
- {
- return msg_generic_e(b, bsiz, h, f);
- }
- #endif
- #if SIP_HAVE_REMOTE_PARTY_ID
- /**@SIP_HEADER sip_remote_party_id Remote-Party-ID Header
- *
- * The syntax of the Remote-Party-ID header is described as follows:
- * @code
- * Remote-Party-ID = "Remote-Party-ID" HCOLON rpid *(COMMA rpid)
- *
- * rpid = [display-name] LAQUOT addr-spec RAQUOT
- * *(SEMI rpi-token)
- *
- * rpi-token = rpi-screen / rpi-pty-type /
- * rpi-id-type / rpi-privacy / other-rpi-token
- *
- * rpi-screen = "screen" EQUAL ("no" / "yes")
- *
- * rpi-pty-type = "party" EQUAL ("calling" / "called" / token)
- *
- * rpi-id-type = "id-type" EQUAL ("subscriber" / "user" /
- * "term" / token)
- *
- * rpi-privacy = "privacy" EQUAL
- * ( rpi-priv-element
- * / (LDQUOT rpi-priv-element
- * *(COMMA rpi-priv-element) RDQUOT) )
- *
- * rpi-priv-element = ("full" / "name" / "uri" / "off" / token)
- * ["-" ( "network" / token )]
- *
- * other-rpi-token = ["-"] token [EQUAL (token / quoted-string)]
- *
- * @endcode
- *
- * @sa sip_update_default_mclass(), draft-ietf-sip-privacy-04.txt, @RFC3325
- *
- * @NEW_1_12_7. In order to use @b Remote-Party-ID header,
- * initialize the SIP parser before calling nta_agent_create() or
- * nua_create() with, e.g.,
- * sip_update_default_mclass(sip_extend_mclass(NULL)).
- * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
- * as return of sip_extend_mclass(NULL) requires to be freed.
- *
- * @note
- * The #sip_t structure does not contain @a sip_remote_party_id field, but
- * sip_remote_party_id() function should be used for accessing the @b
- * Remote-Party-ID header structure.
- */
- /**@ingroup sip_remote_party_id
- * @typedef typedef struct sip_remote_party_id_s sip_remote_party_id_t;
- *
- * The structure #sip_remote_party_id_t contains representation of SIP
- * @RemotePartyID header.
- *
- * The #sip_remote_party_id_t is defined as follows:
- * @code
- * typedef struct sip_remote_party_id_s {
- * sip_common_t rpid_common[1]; // Common fragment info
- * sip_remote_party_id_t *rpid_next; // Link to next
- * char const *rpid_display; // Display name
- * url_t rpid_url[1]; // URL
- * sip_param_t const *rpid_params; // Parameters
- * // Shortcuts to screen, party, id-type and privacy parameters
- * char const *rpid_screen, *rpid_party, *rpid_id_type, *rpid_privacy;
- * } sip_remote_party_id_t;
- * @endcode
- */
- extern msg_xtra_f sip_remote_party_id_dup_xtra;
- extern msg_dup_f sip_remote_party_id_dup_one;
- static msg_update_f sip_remote_party_id_update;
- msg_hclass_t sip_remote_party_id_class[] =
- SIP_HEADER_CLASS(remote_party_id, "Remote-Party-ID", "",
- rpid_params, append, remote_party_id);
- issize_t sip_remote_party_id_d(su_home_t *home, sip_header_t *h,
- char *s, isize_t slen)
- {
- sip_remote_party_id_t *rpid;
- for(;;) {
- rpid = (sip_remote_party_id_t *)h;
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
- if (sip_name_addr_d(home, &s,
- &rpid->rpid_display,
- rpid->rpid_url,
- &rpid->rpid_params, NULL) == -1)
- return -1;
- msg_parse_next_field_without_recursion();
- }
- }
- issize_t sip_remote_party_id_e(char b[], isize_t bsiz,
- sip_header_t const *h, int f)
- {
- sip_remote_party_id_t const *rpid = (sip_remote_party_id_t *)h;
- return sip_name_addr_e(b, bsiz, f,
- rpid->rpid_display, 1,
- rpid->rpid_url,
- rpid->rpid_params,
- NULL);
- }
- /** Calculate size of extra data required for duplicating one
- * sip_remote_party_id_t header.
- */
- isize_t sip_remote_party_id_dup_xtra(sip_header_t const *h, isize_t offset)
- {
- sip_remote_party_id_t const *rpid = (sip_remote_party_id_t *)h;
- return sip_name_addr_xtra(rpid->rpid_display,
- rpid->rpid_url,
- rpid->rpid_params,
- offset);
- }
- /** Duplicate one sip_remote_party_id_t object */
- char *sip_remote_party_id_dup_one(sip_header_t *dst,
- sip_header_t const *src,
- char *b, isize_t xtra)
- {
- sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)dst;
- sip_remote_party_id_t const *o = (sip_remote_party_id_t const *)src;
- return sip_name_addr_dup(&rpid->rpid_display, o->rpid_display,
- rpid->rpid_url, o->rpid_url,
- &rpid->rpid_params, o->rpid_params,
- b, xtra);
- }
- static int sip_remote_party_id_update(msg_common_t *h,
- char const *name, isize_t namelen,
- char const *value)
- {
- sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)h;
- if (name == NULL) {
- rpid->rpid_screen = NULL;
- rpid->rpid_party = NULL;
- rpid->rpid_id_type = NULL;
- rpid->rpid_privacy = NULL;
- }
- #define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s)))
- else if (MATCH(screen))
- rpid->rpid_screen = value;
- else if (MATCH(party))
- rpid->rpid_party = value;
- else if (MATCH(id-type))
- rpid->rpid_id_type = value;
- else if (MATCH(privacy))
- rpid->rpid_privacy = value;
- #undef MATCH
- return 0;
- }
- #endif
- #if SIP_HAVE_P_ASSERTED_IDENTITY
- /**@SIP_HEADER sip_p_asserted_identity P-Asserted-Identity Header
- *
- * The P-Asserted-Identity header is used used among trusted SIP entities
- * (typically intermediaries) to carry the identity of the user sending a
- * SIP message as it was verified by authentication. It is "defined" in
- * @RFC3325 section 9.1 as follows:
- *
- * @code
- * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
- * *(COMMA PAssertedID-value)
- * PAssertedID-value = name-addr / addr-spec
- * @endcode
- *
- * @sa @RFC3325, @PPreferredIdentity
- *
- * @NEW_1_12_7. In order to use @b P-Asserted-Identity header,
- * initialize the SIP parser before calling nta_agent_create() or
- * nua_create() with, e.g.,
- * sip_update_default_mclass(sip_extend_mclass(NULL)).
- * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
- * as return of sip_extend_mclass(NULL) requires to be freed.
- *
- * @note
- * The #sip_t structure does not contain @a sip_p_asserted_identity field,
- * but sip_p_asserted_identity() function should be used for accessing the
- * @b P-Asserted-Identity header structure.
- */
- /**@ingroup sip_p_asserted_identity
- * @typedef typedef struct sip_p_asserted_identity_s sip_p_asserted_identity_t;
- *
- * The structure #sip_p_asserted_identity_t contains representation of SIP
- * @PAssertedIdentity header.
- *
- * The #sip_p_asserted_identity_t is defined as follows:
- * @code
- * typedef struct sip_p_asserted_identity_s {
- * sip_common_t paid_common[1]; // Common fragment info
- * sip_p_asserted_identity_t *paid_next; // Link to next
- * char const *paid_display; // Display name
- * url_t paid_url[1]; // URL
- * } sip_p_asserted_identity_t;
- * @endcode
- */
- static msg_xtra_f sip_p_asserted_identity_dup_xtra;
- static msg_dup_f sip_p_asserted_identity_dup_one;
- #define sip_p_asserted_identity_update NULL
- msg_hclass_t sip_p_asserted_identity_class[] =
- SIP_HEADER_CLASS(p_asserted_identity, "P-Asserted-Identity", "",
- paid_common, append, p_asserted_identity);
- issize_t sip_p_asserted_identity_d(su_home_t *home, sip_header_t *h,
- char *s, isize_t slen)
- {
- sip_p_asserted_identity_t *paid;
- for(;;) {
- paid = (sip_p_asserted_identity_t *)h;
- while (*s == ',') /* Ignore empty entries (comma-whitespace) */
- *s = '\0', s += span_lws(s + 1) + 1;
- if (sip_name_addr_d(home, &s,
- &paid->paid_display,
- paid->paid_url,
- NULL, NULL) == -1)
- return -1;
- msg_parse_next_field_without_recursion();
- }
- }
- issize_t sip_p_asserted_identity_e(char b[], isize_t bsiz,
- sip_header_t const *h, int f)
- {
- sip_p_asserted_identity_t const *paid = (sip_p_asserted_identity_t *)h;
- return sip_name_addr_e(b, bsiz, f,
- paid->paid_display, MSG_IS_CANONIC(f),
- paid->paid_url,
- NULL,
- NULL);
- }
- isize_t sip_p_asserted_identity_dup_xtra(sip_header_t const *h, isize_t offset)
- {
- sip_p_asserted_identity_t const *paid = (sip_p_asserted_identity_t *)h;
- return sip_name_addr_xtra(paid->paid_display,
- paid->paid_url,
- NULL,
- offset);
- }
- /** Duplicate one sip_p_asserted_identity_t object */
- char *sip_p_asserted_identity_dup_one(sip_header_t *dst,
- sip_header_t const *src,
- char *b, isize_t xtra)
- {
- sip_p_asserted_identity_t *paid = (sip_p_asserted_identity_t *)dst;
- sip_p_asserted_identity_t const *o = (sip_p_asserted_identity_t *)src;
- return sip_name_addr_dup(&paid->paid_display, o->paid_display,
- paid->paid_url, o->paid_url,
- NULL, NULL,
- b, xtra);
- }
- #endif
- #if SIP_HAVE_P_PREFERRED_IDENTITY
- /**@SIP_HEADER sip_p_preferred_identity P-Preferred-Identity Header
- *
- * The P-Preferred-Identity header is used used among trusted SIP entities
- * (typically intermediaries) to carry the identity of the user sending a
- * SIP message as it was verified by authentication. It is "defined" in
- * @RFC3325 section 9.1 as follows:
- *
- * @code
- * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
- * *(COMMA PPreferredID-value)
- * PPreferredID-value = name-addr / addr-spec
- * @endcode
- *
- * @sa @RFC3325, @PAssertedIdentity
- *
- * @NEW_1_12_7. In order to use @b P-Preferred-Identity header,
- * initialize the SIP parser before calling nta_agent_create() or
- * nua_create() with, e.g.,
- * sip_update_default_mclass(sip_extend_mclass(NULL)).
- * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
- * as return of sip_extend_mclass(NULL) requires to be freed.
- *
- * @note
- * The #sip_t structure does not contain @a sip_p_preferred_identity field,
- * but sip_p_preferred_identity() function should be used for accessing the
- * @b P-Preferred-Identity header structure.
- */
- /**@ingroup sip_p_preferred_identity
- * @typedef typedef struct sip_p_preferred_identity_s sip_p_preferred_identity_t;
- *
- * The structure #sip_p_preferred_identity_t contains representation of SIP
- * @PPreferredIdentity header.
- *
- * The #sip_p_preferred_identity_t is defined as follows:
- * @code
- * typedef struct sip_p_preferred_identity_s {
- * sip_common_t ppid_common[1]; // Common fragment info
- * sip_p_preferred_identity_t *ppid_next; // Link to next
- * char const *ppid_display; // Display name
- * url_t ppid_url[1]; // URL
- * } sip_p_preferred_identity_t;
- * @endcode
- */
- msg_hclass_t sip_p_preferred_identity_class[] =
- SIP_HEADER_CLASS(p_preferred_identity, "P-Preferred-Identity", "",
- ppid_common, append, p_asserted_identity);
- issize_t sip_p_preferred_identity_d(su_home_t *home, sip_header_t *h,
- char *s, isize_t slen)
- {
- return sip_p_asserted_identity_d(home, h, s, slen);
- }
- issize_t sip_p_preferred_identity_e(char b[], isize_t bsiz,
- sip_header_t const *h, int f)
- {
- return sip_p_asserted_identity_e(b, bsiz, h, f);
- }
- #endif
|