sip_extra.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433
  1. /*
  2. * This file is part of the Sofia-SIP package
  3. *
  4. * Copyright (C) 2005 Nokia Corporation.
  5. *
  6. * Contact: Pekka Pessi <pekka.pessi@nokia.com>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * as published by the Free Software Foundation; either version 2.1 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21. * 02110-1301 USA
  22. *
  23. */
  24. /**@CFILE sip_extra.c
  25. * @brief Non-critical SIP headers
  26. *
  27. * This file contains implementation of @CallInfo, @ErrorInfo,
  28. * @Organization, @Priority, @RetryAfter, @Server, @Subject,
  29. * @Timestamp, and @UserAgent headers.
  30. *
  31. * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
  32. *
  33. * @date Created: Tue Jun 13 02:57:51 2000 ppessi
  34. */
  35. #include "config.h"
  36. /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */
  37. #define MSG_PUB_T struct sip_s
  38. #define MSG_HDR_T union sip_header_u
  39. #include "sofia-sip/sip_parser.h"
  40. #include "sofia-sip/sip_extra.h"
  41. #include "../su/sofia-sip/su_alloc.h"
  42. #include <stdio.h>
  43. #include <stddef.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <limits.h>
  47. #
  48. #include <assert.h>
  49. /* ====================================================================== */
  50. static issize_t sip_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen);
  51. static isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset);
  52. static char *sip_info_dup_one(sip_header_t *dst,
  53. sip_header_t const *src,
  54. char *b,
  55. isize_t xtra);
  56. #define sip_info_update NULL
  57. /* ====================================================================== */
  58. /**@SIP_HEADER sip_call_info Call-Info Header
  59. *
  60. * The Call-Info header provides additional information about the caller or
  61. * callee. Its syntax is defined in @RFC3261 as follows:
  62. *
  63. * @code
  64. * Call-Info = "Call-Info" HCOLON info *(COMMA info)
  65. * info = LAQUOT absoluteURI RAQUOT *( SEMI info-param)
  66. * info-param = ( "purpose" EQUAL ( "icon" / "info"
  67. * / "card" / token ) ) / generic-param
  68. * @endcode
  69. *
  70. *
  71. * The parsed Call-Info header is stored in #sip_call_info_t structure.
  72. */
  73. /**@ingroup sip_call_info
  74. * @typedef struct sip_call_info_s sip_call_info_t;
  75. *
  76. * The structure #sip_call_info_t contains representation of an
  77. * @CallInfo header.
  78. *
  79. * The #sip_call_info_t is defined as follows:
  80. * @code
  81. * struct sip_call_info_s
  82. * {
  83. * sip_common_t ci_common[1]; // Common fragment info
  84. * sip_call_info_t *ci_next; // Link to next @CallInfo
  85. * url_t ci_url[1]; // URI to call info
  86. * msg_param_t const *ci_params; // List of parameters
  87. * char const *ci_purpose; // Value of @b purpose parameter
  88. * };
  89. * @endcode
  90. */
  91. #define sip_call_info_dup_xtra sip_info_dup_xtra
  92. #define sip_call_info_dup_one sip_info_dup_one
  93. static msg_update_f sip_call_info_update;
  94. msg_hclass_t sip_call_info_class[] =
  95. SIP_HEADER_CLASS(call_info, "Call-Info", "",
  96. ci_params, append, call_info);
  97. issize_t sip_call_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  98. {
  99. issize_t retval = sip_info_d(home, h, s, slen);
  100. if (retval == 0)
  101. for (;h; h = h->sh_next)
  102. msg_header_update_params(h->sh_common, 0);
  103. return retval;
  104. }
  105. issize_t sip_call_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  106. {
  107. sip_call_info_t *ci = (sip_call_info_t *)h;
  108. assert(sip_call_info_p(h));
  109. return sip_name_addr_e(b, bsiz, f, NULL, 1, ci->ci_url, ci->ci_params, NULL);
  110. }
  111. /** @internal
  112. * Update parameter in a @CallInfo object.
  113. *
  114. */
  115. static int
  116. sip_call_info_update(msg_common_t *h,
  117. char const *name, isize_t namelen,
  118. char const *value)
  119. {
  120. sip_call_info_t *ci = (sip_call_info_t *)h;
  121. if (name == NULL) {
  122. ci->ci_purpose = NULL;
  123. }
  124. else if (namelen == strlen("purpose") &&
  125. su_casenmatch(name, "purpose", namelen)) {
  126. ci->ci_purpose = value;
  127. }
  128. return 0;
  129. }
  130. /* ====================================================================== */
  131. /**@SIP_HEADER sip_error_info Error-Info Header
  132. *
  133. * The Error-Info header provides a pointer to additional information about
  134. * the error status response. Its syntax is defined in @RFC3261 as follows:
  135. *
  136. * @code
  137. * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri)
  138. * error-uri = LAQUOT absoluteURI RAQUOT *( SEMI generic-param )
  139. * @endcode
  140. *
  141. *
  142. * The parsed Error-Info header is stored in #sip_error_info_t structure.
  143. */
  144. /**@ingroup sip_error_info
  145. * @typedef struct sip_error_info_s sip_error_info_t;
  146. *
  147. * The structure #sip_error_info_t contains representation of an
  148. * @ErrorInfo header.
  149. *
  150. * The #sip_error_info_t is defined as follows:
  151. * @code
  152. * struct sip_error_info_s
  153. * {
  154. * sip_common_t ei_common[1]; // Common fragment info
  155. * sip_error_info_t *ei_next; // Link to next @ErrorInfo
  156. * url_t ei_url[1]; // URI to error info
  157. * msg_param_t const *ei_params; // List of parameters
  158. * };
  159. * @endcode
  160. */
  161. msg_hclass_t sip_error_info_class[] =
  162. SIP_HEADER_CLASS(error_info, "Error-Info", "",
  163. ei_params, append, info);
  164. issize_t sip_error_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  165. {
  166. return sip_info_d(home, h, s, slen);
  167. }
  168. issize_t sip_error_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  169. {
  170. sip_error_info_t const *ei = h->sh_error_info;
  171. assert(sip_error_info_p(h));
  172. return sip_name_addr_e(b, bsiz, f,
  173. NULL, 1, ei->ei_url, ei->ei_params, NULL);
  174. }
  175. /* ====================================================================== */
  176. /**@SIP_HEADER sip_alert_info Alert-Info Header
  177. *
  178. * When present in an INVITE request, the Alert-Info header field
  179. * specifies an alternative ring tone to the UAS. When present in a 180
  180. * (Ringing) response, the Alert-Info header field specifies an
  181. * alternative ringback tone to the UAC. A typical usage is for a proxy
  182. * to insert this header field to provide a distinctive ring feature.
  183. *
  184. * @code
  185. * Alert-Info = "Alert-Info" HCOLON alert-param *(COMMA alert-param)
  186. * alert-param = LAQUOT absoluteURI RAQUOT *(SEMI generic-param)
  187. * @endcode
  188. *
  189. * The parsed Alert-Info header is stored in #sip_alert_info_t structure.
  190. *
  191. * @NEW_1_12_7. In order to use @b Alert-Info header, initialize the SIP
  192. * parser before calling nta_agent_create() or nua_create() with, e.g.,
  193. * sip_update_default_mclass(sip_extend_mclass(NULL)).
  194. * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
  195. * as return of sip_extend_mclass(NULL) requires to be freed.
  196. *
  197. * The #sip_t structure does not contain a @a sip_alert_info field, but
  198. * sip_alert_info() function should be used for accessing the @b Alert-Info
  199. * header structure.
  200. */
  201. /**@ingroup sip_alert_info
  202. * @typedef struct sip_alert_info_s sip_alert_info_t;
  203. *
  204. * The structure #sip_alert_info_t contains representation of an
  205. * @AlertInfo header.
  206. *
  207. * The #sip_alert_info_t is defined as follows:
  208. * @code
  209. * struct sip_alert_info_s
  210. * {
  211. * sip_common_t ai_common[1]; // Common fragment info
  212. * sip_alert_info_t *ai_next; // Link to next @AlertInfo
  213. * url_t ai_url[1]; // URI to alert info
  214. * msg_param_t const *ai_params; // List of optional parameters
  215. * };
  216. * @endcode
  217. *
  218. * @NEW_1_12_7.
  219. */
  220. msg_hclass_t sip_alert_info_class[] =
  221. SIP_HEADER_CLASS(alert_info, "Alert-Info", "",
  222. ai_params, append, info);
  223. issize_t sip_alert_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  224. {
  225. return sip_info_d(home, h, s, slen);
  226. }
  227. issize_t sip_alert_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  228. {
  229. sip_alert_info_t *ai = (sip_alert_info_t *)h;
  230. return sip_name_addr_e(b, bsiz, f, NULL, 1, ai->ai_url, ai->ai_params, NULL);
  231. }
  232. /* ====================================================================== */
  233. /**@SIP_HEADER sip_reply_to Reply-To Header
  234. *
  235. * The @b Reply-To header field contains a logical return URI that may be
  236. * different from the @From header field. For example, the URI MAY be used to
  237. * return missed calls or unestablished sessions. If the user wished to
  238. * remain anonymous, the header field SHOULD either be omitted from the
  239. * request or populated in such a way that does not reveal any private
  240. * information. Its syntax is defined in @RFC3261 as follows:
  241. *
  242. * @code
  243. * Reply-To = "Reply-To" HCOLON rplyto-spec
  244. * rplyto-spec = ( name-addr / addr-spec )
  245. * *( SEMI rplyto-param )
  246. * rplyto-param = generic-param
  247. * @endcode
  248. *
  249. * The parsed Reply-To header is stored in #sip_reply_to_t structure.
  250. *
  251. * @sa sip_update_default_mclass()
  252. *
  253. * @NEW_1_12_7. In order to use @b Reply-To header,
  254. * initialize the SIP parser before calling nta_agent_create() or
  255. * nua_create() with, e.g.,
  256. * sip_update_default_mclass(sip_extend_mclass(NULL)).
  257. * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
  258. * as return of sip_extend_mclass(NULL) requires to be freed.
  259. *
  260. * @note
  261. * The #sip_t structure does not contain a @a sip_reply_to field, but
  262. * sip_reply_to() function should be used for accessing the @b Reply-To
  263. * header structure.
  264. */
  265. /**@ingroup sip_reply_to
  266. * @typedef struct msg_list_s sip_reply_to_t;
  267. *
  268. * The structure #sip_reply_to_t contains representation of SIP
  269. * @ReplyTo header.
  270. *
  271. * The #sip_reply_to_t is defined as follows:
  272. * @code
  273. * struct sip_reply_to_s
  274. * {
  275. * sip_common_t rplyto_common[1]; // Common fragment info
  276. * sip_reply_to_t *rplyto_next; // Dummy link to next header
  277. * char const *rplyto_display; // Display name
  278. * url_t rplyto_url[1]; // Return URI
  279. * msg_param_t const *rplyto_params; // List of optional parameters
  280. * };
  281. * @endcode
  282. */
  283. static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset);
  284. static char *sip_reply_to_dup_one(sip_header_t *dst,
  285. sip_header_t const *src,
  286. char *b,
  287. isize_t xtra);
  288. #define sip_reply_to_update NULL
  289. msg_hclass_t sip_reply_to_class[] =
  290. SIP_HEADER_CLASS(reply_to, "Reply-To", "", rplyto_params, single, reply_to);
  291. issize_t sip_reply_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  292. {
  293. sip_reply_to_t *rplyto = (sip_reply_to_t *)h;
  294. return sip_name_addr_d(home,
  295. &s,
  296. &rplyto->rplyto_display,
  297. rplyto->rplyto_url,
  298. &rplyto->rplyto_params,
  299. NULL);
  300. }
  301. issize_t sip_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
  302. {
  303. sip_reply_to_t *rplyto = (sip_reply_to_t *)h;
  304. return sip_name_addr_e(b, bsiz,
  305. flags,
  306. rplyto->rplyto_display,
  307. MSG_IS_CANONIC(flags), rplyto->rplyto_url,
  308. rplyto->rplyto_params,
  309. NULL);
  310. }
  311. static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset)
  312. {
  313. sip_reply_to_t const *rplyto = (sip_reply_to_t const *)h;
  314. return sip_name_addr_xtra(rplyto->rplyto_display,
  315. rplyto->rplyto_url,
  316. rplyto->rplyto_params,
  317. offset);
  318. }
  319. /**@internal Duplicate one sip_reply_to_t object. */
  320. static char *sip_reply_to_dup_one(sip_header_t *dst, sip_header_t const *src,
  321. char *b, isize_t xtra)
  322. {
  323. sip_reply_to_t *rplyto = (sip_reply_to_t *)dst;
  324. sip_reply_to_t const *o = (sip_reply_to_t *)src;
  325. return sip_name_addr_dup(&rplyto->rplyto_display, o->rplyto_display,
  326. rplyto->rplyto_url, o->rplyto_url,
  327. &rplyto->rplyto_params, o->rplyto_params,
  328. b, xtra);
  329. }
  330. /* ====================================================================== */
  331. /**@SIP_HEADER sip_in_reply_to In-Reply-To Header
  332. *
  333. * The @b In-Reply-To request header field enumerates the
  334. * @ref sip_call_id "Call-IDs" that this call references or returns.
  335. * Its syntax is defined in @RFC3261 as follows:
  336. *
  337. * @code
  338. * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid)
  339. * @endcode
  340. *
  341. * The parsed In-Reply-To header is stored in #sip_in_reply_to_t structure.
  342. */
  343. /**@ingroup sip_in_reply_to
  344. * @typedef struct msg_list_s sip_in_reply_to_t;
  345. *
  346. * The structure #sip_in_reply_to_t contains representation of SIP
  347. * @InReplyTo header.
  348. *
  349. * The #sip_in_reply_to_t is defined as follows:
  350. * @code
  351. * typedef struct msg_list_s
  352. * {
  353. * msg_common_t k_common[1]; // Common fragment info
  354. * msg_list_t *k_next; // Link to next header
  355. * msg_param_t *k_items; // List of call ids
  356. * } sip_in_reply_to_t;
  357. * @endcode
  358. */
  359. msg_hclass_t sip_in_reply_to_class[] =
  360. SIP_HEADER_CLASS_LIST(in_reply_to, "In-Reply-To", "", list);
  361. issize_t sip_in_reply_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  362. {
  363. return msg_list_d(home, h, s, slen);
  364. }
  365. issize_t sip_in_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  366. {
  367. assert(sip_in_reply_to_p(h));
  368. return msg_list_e(b, bsiz, h, f);
  369. }
  370. /* ====================================================================== */
  371. /**@SIP_HEADER sip_organization Organization Header
  372. *
  373. * The Organization header field conveys the name of the organization to
  374. * which the entity issuing the request or response belongs. Its syntax is
  375. * defined in @RFC3261 as follows:
  376. *
  377. * @code
  378. * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM]
  379. * @endcode
  380. *
  381. *
  382. * The parsed Organization header is stored in #sip_organization_t structure.
  383. */
  384. /**@ingroup sip_organization
  385. * @typedef struct msg_generic_s sip_organization_t;
  386. *
  387. * The structure #sip_organization_t contains representation of a SIP
  388. * @Organization header.
  389. *
  390. * The #sip_organization_t is defined as follows:
  391. * @code
  392. * typedef struct msg_generic_s
  393. * {
  394. * msg_common_t g_common[1]; // Common fragment info
  395. * msg_generic_t *g_next; // Link to next header
  396. * char const *g_string; // Organization text
  397. * } sip_organization_t;
  398. * @endcode
  399. */
  400. msg_hclass_t sip_organization_class[] =
  401. SIP_HEADER_CLASS_G(organization, "Organization", "", single);
  402. issize_t sip_organization_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  403. {
  404. return sip_generic_d(home, h, s, slen);
  405. }
  406. issize_t sip_organization_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  407. {
  408. assert(sip_organization_p(h));
  409. return sip_generic_e(b, bsiz, h, f);
  410. }
  411. /* ====================================================================== */
  412. /**@SIP_HEADER sip_priority Priority Header
  413. *
  414. * The Priority request-header field indicates the urgency of the request as
  415. * perceived by the client. Its syntax is defined in @RFC3261 as follows:
  416. *
  417. * @code
  418. * Priority = "Priority" HCOLON priority-value
  419. * priority-value = "emergency" / "urgent" / "normal"
  420. * / "non-urgent" / other-priority
  421. * other-priority = token
  422. * @endcode
  423. *
  424. *
  425. * The parsed Priority header is stored in #sip_priority_t structure.
  426. */
  427. /**@ingroup sip_priority
  428. * @typedef struct msg_generic_s sip_priority_t;
  429. *
  430. * The structure #sip_priority_t contains representation of a SIP
  431. * @Priority header.
  432. *
  433. * The #sip_priority_t is defined as follows:
  434. * @code
  435. * typedef struct msg_generic_s
  436. * {
  437. * msg_common_t g_common[1]; // Common fragment info
  438. * msg_generic_t *g_next; // Dummy link to next header
  439. * char const *g_string; // Priority token
  440. * } sip_priority_t;
  441. * @endcode
  442. */
  443. msg_hclass_t sip_priority_class[] =
  444. SIP_HEADER_CLASS_G(priority, "Priority", "", single);
  445. issize_t sip_priority_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  446. {
  447. sip_priority_t *priority = (sip_priority_t *)h;
  448. if (msg_token_d(&s, &priority->g_string) < 0)
  449. return -1;
  450. if (*s && !IS_LWS(*s)) /* Something extra after priority token? */
  451. return -1;
  452. return 0;
  453. }
  454. issize_t sip_priority_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  455. {
  456. assert(sip_priority_p(h));
  457. return sip_generic_e(b, bsiz, h, f);
  458. }
  459. /* ====================================================================== */
  460. /**@SIP_HEADER sip_server Server Header
  461. *
  462. * The Server response-header field contains information about the software
  463. * used by the user agent server to handle the request. Its syntax is
  464. * defined in @RFC2616 section 14.38 and @RFC3261 as follows:
  465. *
  466. * @code
  467. * Server = "Server" HCOLON server-val *(LWS server-val)
  468. * server-val = product / comment
  469. * product = token [SLASH product-version]
  470. * product-version = token
  471. * @endcode
  472. *
  473. * The parsed Server header is stored in #sip_server_t structure.
  474. */
  475. /**@ingroup sip_server
  476. * @typedef struct msg_generic_s sip_server_t;
  477. *
  478. * The structure #sip_server_t contains representation of a SIP
  479. * @Server header.
  480. *
  481. * The #sip_server_t is defined as follows:
  482. * @code
  483. * typedef struct msg_generic_s
  484. * {
  485. * msg_common_t g_common[1]; // Common fragment info
  486. * msg_generic_t *g_next; // Link to next header
  487. * char const *g_string; // Server tokens
  488. * } sip_server_t;
  489. * @endcode
  490. */
  491. msg_hclass_t sip_server_class[] =
  492. SIP_HEADER_CLASS_G(server, "Server", "", single);
  493. issize_t sip_server_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  494. {
  495. return sip_generic_d(home, h, s, slen);
  496. }
  497. issize_t sip_server_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  498. {
  499. assert(sip_server_p(h));
  500. return sip_generic_e(b, bsiz, h, f);
  501. }
  502. /* ====================================================================== */
  503. /**@SIP_HEADER sip_subject Subject Header
  504. *
  505. * The Subject header provides a summary or indicates the nature of the
  506. * request. Its syntax is defined in @RFC3261 as follows:
  507. *
  508. * @code
  509. * Subject = ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM]
  510. * @endcode
  511. *
  512. * The parsed Subject header is stored in #sip_subject_t structure.
  513. */
  514. /**@ingroup sip_subject
  515. * @typedef struct msg_generic_s sip_subject_t;
  516. *
  517. * The structure #sip_subject_t contains representation of a SIP
  518. * @Subject header.
  519. *
  520. * The #sip_subject_t is defined as follows:
  521. * @code
  522. * typedef struct msg_generic_s
  523. * {
  524. * msg_common_t g_common[1]; // Common fragment info
  525. * msg_generic_t *g_next; // Link to next header
  526. * char const *g_string; // Subject text
  527. * } sip_subject_t;
  528. * @endcode
  529. */
  530. msg_hclass_t sip_subject_class[] =
  531. SIP_HEADER_CLASS_G(subject, "Subject", "s", single);
  532. issize_t sip_subject_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  533. {
  534. return sip_generic_d(home, h, s, slen);
  535. }
  536. issize_t sip_subject_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  537. {
  538. assert(sip_subject_p(h));
  539. return sip_generic_e(b, bsiz, h, f);
  540. }
  541. /* ====================================================================== */
  542. /**@SIP_HEADER sip_timestamp Timestamp Header
  543. *
  544. * The @b Timestamp header describes when the client sent the request to the
  545. * server, and it is used by the client to adjust its retransmission
  546. * intervals. Its syntax is defined in @RFC3261 as follows:
  547. *
  548. * @code
  549. * Timestamp = "Timestamp" HCOLON 1*(DIGIT)
  550. * [ "." *(DIGIT) ] [ LWS delay ]
  551. * delay = *(DIGIT) [ "." *(DIGIT) ]
  552. * @endcode
  553. *
  554. * The parsed Timestamp header is stored in #sip_timestamp_t structure.
  555. */
  556. /**@ingroup sip_timestamp
  557. * @typedef struct sip_timestamp_s sip_timestamp_t;
  558. *
  559. * The structure #sip_timestamp_t contains representation of a SIP
  560. * @Timestamp header.
  561. *
  562. * The #sip_timestamp_t is defined as follows:
  563. * @code
  564. * typedef struct sip_timestamp_s
  565. * {
  566. * sip_common_t ts_common[1]; // Common fragment info
  567. * sip_error_t *ts_next; // Dummy link
  568. * char const *ts_stamp; // Original timestamp
  569. * char const *ts_delay; // Delay at UAS
  570. * } sip_timestamp_t;
  571. * @endcode
  572. */
  573. static isize_t sip_timestamp_dup_xtra(sip_header_t const *h, isize_t offset);
  574. static char *sip_timestamp_dup_one(sip_header_t *dst,
  575. sip_header_t const *src,
  576. char *b,
  577. isize_t xtra);
  578. #define sip_timestamp_update NULL
  579. msg_hclass_t sip_timestamp_class[] =
  580. SIP_HEADER_CLASS(timestamp, "Timestamp", "", ts_common, single,
  581. timestamp);
  582. issize_t sip_timestamp_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  583. {
  584. sip_timestamp_t *ts = (sip_timestamp_t*)h;
  585. ts->ts_stamp = s;
  586. s += span_digit(s);
  587. if (s == ts->ts_stamp)
  588. return -1;
  589. if (*s == '.') { s += span_digit(s + 1) + 1; }
  590. if (IS_LWS(*s)) {
  591. *s = '\0';
  592. s += span_lws(s + 1) + 1;
  593. ts->ts_delay = s;
  594. s += span_digit(s); if (*s == '.') { s += span_digit(s + 1) + 1; }
  595. }
  596. if (!*s || IS_LWS(*s))
  597. *s++ = '\0';
  598. else
  599. return -1;
  600. return 0;
  601. }
  602. issize_t sip_timestamp_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  603. {
  604. sip_timestamp_t const *ts = h->sh_timestamp;
  605. char *end = b + bsiz, *b0 = b;
  606. assert(sip_timestamp_p(h));
  607. MSG_STRING_E(b, end, ts->ts_stamp);
  608. if (ts->ts_delay) {
  609. MSG_CHAR_E(b, end, ' ');
  610. MSG_STRING_E(b, end, ts->ts_delay);
  611. }
  612. MSG_TERM_E(b, end);
  613. return b - b0;
  614. }
  615. static
  616. isize_t sip_timestamp_dup_xtra(sip_header_t const *h, isize_t offset)
  617. {
  618. sip_timestamp_t const *ts = h->sh_timestamp;
  619. offset += MSG_STRING_SIZE(ts->ts_stamp);
  620. offset += MSG_STRING_SIZE(ts->ts_delay);
  621. return offset;
  622. }
  623. static
  624. char *sip_timestamp_dup_one(sip_header_t *dst,
  625. sip_header_t const *src,
  626. char *b,
  627. isize_t xtra)
  628. {
  629. sip_timestamp_t *ts = dst->sh_timestamp;
  630. sip_timestamp_t const *o = src->sh_timestamp;
  631. char *end = b + xtra;
  632. MSG_STRING_DUP(b, ts->ts_stamp, o->ts_stamp);
  633. MSG_STRING_DUP(b, ts->ts_delay, o->ts_delay);
  634. assert(b <= end); (void)end;
  635. return b;
  636. }
  637. /* ====================================================================== */
  638. /**@SIP_HEADER sip_user_agent User-Agent Header
  639. *
  640. * The User-Agent header contains information about the client user agent
  641. * originating the request. Its syntax is defined in [H14.43, S10.45] as
  642. * follows:
  643. *
  644. * @code
  645. * User-Agent = "User-Agent" HCOLON server-val *(LWS server-val)
  646. * server-val = product / comment
  647. * product = token [SLASH product-version]
  648. * product-version = token
  649. * @endcode
  650. *
  651. * The parsed User-Agent header is stored in #sip_user_agent_t structure.
  652. */
  653. /**@ingroup sip_user_agent
  654. * @typedef struct msg_generic_s sip_user_agent_t;
  655. *
  656. * The structure #sip_user_agent_t contains representation of a SIP
  657. * @UserAgent header.
  658. *
  659. * The #sip_user_agent_t is defined as follows:
  660. * @code
  661. * typedef struct msg_generic_s
  662. * {
  663. * msg_common_t g_common[1]; // Common fragment info
  664. * msg_generic_t *g_next; // Link to next header
  665. * char const *g_string; // User-Agent components
  666. * } sip_user_agent_t;
  667. * @endcode
  668. */
  669. msg_hclass_t sip_user_agent_class[] =
  670. SIP_HEADER_CLASS_G(user_agent, "User-Agent", "", single);
  671. issize_t sip_user_agent_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  672. {
  673. return sip_generic_d(home, h, s, slen);
  674. }
  675. issize_t sip_user_agent_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  676. {
  677. assert(sip_user_agent_p(h));
  678. return sip_generic_e(b, bsiz, h, f);
  679. }
  680. /* ====================================================================== */
  681. /**@SIP_HEADER sip_etag SIP-ETag Header
  682. *
  683. * The @b SIP-ETag header field identifies the published event state. Its
  684. * syntax is defined in @RFC3903 as follows:
  685. *
  686. * @code
  687. * SIP-ETag = "SIP-ETag" HCOLON entity-tag
  688. * entity-tag = token
  689. * @endcode
  690. *
  691. * The parsed SIP-ETag header is stored in #sip_etag_t structure.
  692. */
  693. /**@ingroup sip_etag
  694. * @typedef struct msg_generic_s sip_etag_t;
  695. *
  696. * The structure #sip_etag_t contains representation of a SIP
  697. * @SIPETag header.
  698. *
  699. * The #sip_etag_t is defined as follows:
  700. * @code
  701. * typedef struct msg_generic_s
  702. * {
  703. * msg_common_t g_common[1]; // Common fragment info
  704. * msg_generic_t *g_next; // Link to next header
  705. * char const *g_string; // entity-tag
  706. * } sip_etag_t;
  707. * @endcode
  708. */
  709. msg_hclass_t sip_etag_class[] =
  710. SIP_HEADER_CLASS_G(etag, "SIP-ETag", "", single);
  711. issize_t sip_etag_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  712. {
  713. sip_etag_t *etag = (sip_etag_t *)h;
  714. return msg_token_d(&s, &etag->g_value);
  715. }
  716. issize_t sip_etag_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  717. {
  718. return msg_generic_e(b, bsiz, h, f);
  719. }
  720. /* ====================================================================== */
  721. /**@SIP_HEADER sip_if_match SIP-If-Match Header
  722. *
  723. * The @b SIP-If-Match header field identifies the specific entity of event
  724. * state that the request is refreshing, modifying or removing. Its syntax
  725. * is defined in @RFC3903 as follows:
  726. *
  727. * @code
  728. * SIP-If-Match = "SIP-If-Match" HCOLON entity-tag
  729. * entity-tag = token
  730. * @endcode
  731. *
  732. * The parsed SIP-If-Match header is stored in #sip_if_match_t structure.
  733. */
  734. /**@ingroup sip_if_match
  735. * @typedef struct msg_generic_s sip_if_match_t;
  736. *
  737. * The structure #sip_if_match_t contains representation of a SIP
  738. * @SIPIfMatch header.
  739. *
  740. * The #sip_if_match_t is defined as follows:
  741. * @code
  742. * typedef struct msg_generic_s
  743. * {
  744. * msg_common_t g_common[1]; // Common fragment info
  745. * msg_generic_t *g_next; // Link to next header
  746. * char const *g_string; // entity-tag
  747. * } sip_if_match_t;
  748. * @endcode
  749. */
  750. msg_hclass_t sip_if_match_class[] =
  751. SIP_HEADER_CLASS_G(if_match, "SIP-If-Match", "", single);
  752. issize_t sip_if_match_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  753. {
  754. return sip_etag_d(home, h, s, slen);
  755. }
  756. issize_t sip_if_match_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  757. {
  758. return sip_etag_e(b, bsiz, h, f);
  759. }
  760. /* ====================================================================== */
  761. /** Parsing @CallInfo, @ErrorInfo. */
  762. static
  763. issize_t sip_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
  764. {
  765. sip_call_info_t *ci;
  766. char *end;
  767. for(;;) {
  768. ci = h->sh_call_info;
  769. end = s + slen;
  770. while (*s == ',')
  771. s += span_lws(s + 1) + 1;
  772. if (sip_name_addr_d(home, &s, NULL, ci->ci_url, &ci->ci_params, NULL) < 0)
  773. return -1;
  774. slen = end - s;
  775. msg_parse_next_field_without_recursion();
  776. }
  777. }
  778. isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset)
  779. {
  780. sip_call_info_t const *ci = h->sh_call_info;
  781. return sip_name_addr_xtra(NULL,
  782. ci->ci_url,
  783. ci->ci_params,
  784. offset);
  785. }
  786. char *sip_info_dup_one(sip_header_t *dst,
  787. sip_header_t const *src,
  788. char *b,
  789. isize_t xtra)
  790. {
  791. sip_call_info_t *ci = dst->sh_call_info;
  792. sip_call_info_t const *o = src->sh_call_info;
  793. return sip_name_addr_dup(NULL, NULL,
  794. ci->ci_url, o->ci_url,
  795. &ci->ci_params, o->ci_params,
  796. b, xtra);
  797. }
  798. /* ====================================================================== */
  799. #if SU_HAVE_EXPERIMENTAL
  800. /**@SIP_HEADER sip_suppress_body_if_match Suppress-Body-If-Match Header
  801. *
  802. * The @b Suppress-Body-If-Match header field identifies a SIP event content
  803. * already known by the watcher. Its syntax is defined in
  804. * draft-niemi-sip-subnot-etags-01 as follows:
  805. *
  806. * @code
  807. * Suppress-Body-If-Match = "Suppress-Body-If-Match" HCOLON entity-tag
  808. * entity-tag = token
  809. * @endcode
  810. *
  811. * The parsed Suppress-Body-If-Match header is stored in
  812. * #sip_suppress_body_if_match_t structure.
  813. *
  814. * @sa @RFC3265, draft-niemi-sip-subnot-etags-01.txt
  815. *
  816. * @EXP_1_12_5.
  817. * In order to use @b Suppress-Body-If-Match header,
  818. * initialize the SIP parser with, e.g.,
  819. * sip_update_default_mclass(sip_extend_mclass(NULL)).
  820. * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
  821. * as return of sip_extend_mclass(NULL) requires to be freed.
  822. *
  823. * @note
  824. * The #sip_t structure does not contain a @a
  825. * sip_suppress_body_if_match field, but sip_suppress_body_if_match()
  826. * function should be used for accessing the @b Suppress-Body-If-Match
  827. * header structure.
  828. */
  829. /**@ingroup sip_suppress_body_if_match
  830. * @typedef struct sip_suppress_body_if_match_s sip_suppress_body_if_match_t;
  831. *
  832. * The structure #sip_suppress_body_if_match_t contains representation of a
  833. * SIP @SuppressBodyIfMatch header.
  834. *
  835. * The #sip_suppress_body_if_match_t is defined as follows:
  836. * @code
  837. * typedef struct sip_suppress_body_if_match_s
  838. * {
  839. * sip_common_t sbim_common[1]; // Common fragment info
  840. * sip_error_t *sbim_next; // Dummy link to next header
  841. * char const *sbim_tag; // entity-tag
  842. * } sip_suppress_body_if_match_t;
  843. * @endcode
  844. */
  845. #define sip_suppress_body_if_match_dup_xtra msg_generic_dup_xtra
  846. #define sip_suppress_body_if_match_dup_one msg_generic_dup_one
  847. #define sip_suppress_body_if_match_update NULL
  848. msg_hclass_t sip_suppress_body_if_match_class[] =
  849. SIP_HEADER_CLASS(suppress_body_if_match,
  850. "Suppress-Body-If-Match", "",
  851. sbim_common, single, suppress_body_if_match);
  852. issize_t sip_suppress_body_if_match_d(su_home_t *home,
  853. sip_header_t *h,
  854. char *s, isize_t slen)
  855. {
  856. sip_suppress_body_if_match_t *sbim = (void *)h;
  857. return msg_token_d(&s, &sbim->sbim_tag);
  858. }
  859. issize_t sip_suppress_body_if_match_e(char b[], isize_t bsiz,
  860. sip_header_t const *h,
  861. int f)
  862. {
  863. return sip_etag_e(b, bsiz, h, f);
  864. }
  865. /* ====================================================================== */
  866. /**@SIP_HEADER sip_suppress_notify_if_match Suppress-Notify-If-Match Header
  867. *
  868. * The @b Suppress-Notify-If-Match header is used to suppress
  869. * superfluous NOTIFY transactions. Its syntax is defined in
  870. * draft-niemi-sip-subnot-etags-01 as follows:
  871. *
  872. * @code
  873. * Suppress-Notify-If-Match = "Suppress-Notify-If-Match" HCOLON entity-tag
  874. * entity-tag = token
  875. * @endcode
  876. *
  877. * The parsed Suppress-Notify-If-Match header is stored in
  878. * #sip_suppress_notify_if_match_t structure.
  879. *
  880. * @sa @RFC3265, draft-niemi-sip-subnot-etag-01
  881. *
  882. * @EXP_1_12_5.
  883. * In order to use @b Suppress-Notify-If-Match header,
  884. * initialize the SIP parser with, e.g.,
  885. * sip_update_default_mclass(sip_extend_mclass(NULL)).
  886. * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
  887. * as return of sip_extend_mclass(NULL) requires to be freed.
  888. *
  889. * @note
  890. * The #sip_t struct does not contain @a sip_suppress_notify_if_match field,
  891. * but sip_suppress_notify_if_match() function should be used for accessing
  892. * the @b Suppress-Notify-If-Match header structure.
  893. */
  894. /**@ingroup sip_suppress_notify_if_match
  895. * @typedef struct sip_suppress_notify_if_match_s \
  896. * sip_suppress_notify_if_match_t;
  897. *
  898. * The structure #sip_suppress_notify_if_match_t contains representation of a
  899. * SIP @SuppressNotifyIfMatch header.
  900. *
  901. * The #sip_suppress_notify_if_match_t is defined as follows:
  902. * @code
  903. * typedef struct sip_suppress_notify_if_match_s
  904. * {
  905. * sip_common_t snim_common[1]; // Common fragment info
  906. * sip_error_t *snim_next; // Dummy link to next header
  907. * char const *snim_tag; // entity-tag
  908. * } sip_suppress_notify_if_match_t;
  909. * @endcode
  910. */
  911. #define sip_suppress_notify_if_match_dup_xtra msg_generic_dup_xtra
  912. #define sip_suppress_notify_if_match_dup_one msg_generic_dup_one
  913. #define sip_suppress_notify_if_match_update NULL
  914. msg_hclass_t sip_suppress_notify_if_match_class[] =
  915. SIP_HEADER_CLASS(suppress_notify_if_match,
  916. "Suppress-Notify-If-Match", "",
  917. snim_common, single, suppress_notify_if_match);
  918. issize_t sip_suppress_notify_if_match_d(su_home_t *home,
  919. sip_header_t *h,
  920. char *s, isize_t slen)
  921. {
  922. sip_suppress_notify_if_match_t *snim = (void *)h;
  923. return msg_token_d(&s, &snim->snim_tag);
  924. }
  925. issize_t sip_suppress_notify_if_match_e(char b[], isize_t bsiz,
  926. sip_header_t const *h,
  927. int f)
  928. {
  929. return msg_generic_e(b, bsiz, h, f);
  930. }
  931. #endif
  932. #if SIP_HAVE_REMOTE_PARTY_ID
  933. /**@SIP_HEADER sip_remote_party_id Remote-Party-ID Header
  934. *
  935. * The syntax of the Remote-Party-ID header is described as follows:
  936. * @code
  937. * Remote-Party-ID = "Remote-Party-ID" HCOLON rpid *(COMMA rpid)
  938. *
  939. * rpid = [display-name] LAQUOT addr-spec RAQUOT
  940. * *(SEMI rpi-token)
  941. *
  942. * rpi-token = rpi-screen / rpi-pty-type /
  943. * rpi-id-type / rpi-privacy / other-rpi-token
  944. *
  945. * rpi-screen = "screen" EQUAL ("no" / "yes")
  946. *
  947. * rpi-pty-type = "party" EQUAL ("calling" / "called" / token)
  948. *
  949. * rpi-id-type = "id-type" EQUAL ("subscriber" / "user" /
  950. * "term" / token)
  951. *
  952. * rpi-privacy = "privacy" EQUAL
  953. * ( rpi-priv-element
  954. * / (LDQUOT rpi-priv-element
  955. * *(COMMA rpi-priv-element) RDQUOT) )
  956. *
  957. * rpi-priv-element = ("full" / "name" / "uri" / "off" / token)
  958. * ["-" ( "network" / token )]
  959. *
  960. * other-rpi-token = ["-"] token [EQUAL (token / quoted-string)]
  961. *
  962. * @endcode
  963. *
  964. * @sa sip_update_default_mclass(), draft-ietf-sip-privacy-04.txt, @RFC3325
  965. *
  966. * @NEW_1_12_7. In order to use @b Remote-Party-ID header,
  967. * initialize the SIP parser before calling nta_agent_create() or
  968. * nua_create() with, e.g.,
  969. * sip_update_default_mclass(sip_extend_mclass(NULL)).
  970. * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
  971. * as return of sip_extend_mclass(NULL) requires to be freed.
  972. *
  973. * @note
  974. * The #sip_t structure does not contain @a sip_remote_party_id field, but
  975. * sip_remote_party_id() function should be used for accessing the @b
  976. * Remote-Party-ID header structure.
  977. */
  978. /**@ingroup sip_remote_party_id
  979. * @typedef typedef struct sip_remote_party_id_s sip_remote_party_id_t;
  980. *
  981. * The structure #sip_remote_party_id_t contains representation of SIP
  982. * @RemotePartyID header.
  983. *
  984. * The #sip_remote_party_id_t is defined as follows:
  985. * @code
  986. * typedef struct sip_remote_party_id_s {
  987. * sip_common_t rpid_common[1]; // Common fragment info
  988. * sip_remote_party_id_t *rpid_next; // Link to next
  989. * char const *rpid_display; // Display name
  990. * url_t rpid_url[1]; // URL
  991. * sip_param_t const *rpid_params; // Parameters
  992. * // Shortcuts to screen, party, id-type and privacy parameters
  993. * char const *rpid_screen, *rpid_party, *rpid_id_type, *rpid_privacy;
  994. * } sip_remote_party_id_t;
  995. * @endcode
  996. */
  997. extern msg_xtra_f sip_remote_party_id_dup_xtra;
  998. extern msg_dup_f sip_remote_party_id_dup_one;
  999. static msg_update_f sip_remote_party_id_update;
  1000. msg_hclass_t sip_remote_party_id_class[] =
  1001. SIP_HEADER_CLASS(remote_party_id, "Remote-Party-ID", "",
  1002. rpid_params, append, remote_party_id);
  1003. issize_t sip_remote_party_id_d(su_home_t *home, sip_header_t *h,
  1004. char *s, isize_t slen)
  1005. {
  1006. sip_remote_party_id_t *rpid;
  1007. for(;;) {
  1008. rpid = (sip_remote_party_id_t *)h;
  1009. while (*s == ',') /* Ignore empty entries (comma-whitespace) */
  1010. *s = '\0', s += span_lws(s + 1) + 1;
  1011. if (sip_name_addr_d(home, &s,
  1012. &rpid->rpid_display,
  1013. rpid->rpid_url,
  1014. &rpid->rpid_params, NULL) == -1)
  1015. return -1;
  1016. msg_parse_next_field_without_recursion();
  1017. }
  1018. }
  1019. issize_t sip_remote_party_id_e(char b[], isize_t bsiz,
  1020. sip_header_t const *h, int f)
  1021. {
  1022. sip_remote_party_id_t const *rpid = (sip_remote_party_id_t *)h;
  1023. return sip_name_addr_e(b, bsiz, f,
  1024. rpid->rpid_display, 1,
  1025. rpid->rpid_url,
  1026. rpid->rpid_params,
  1027. NULL);
  1028. }
  1029. /** Calculate size of extra data required for duplicating one
  1030. * sip_remote_party_id_t header.
  1031. */
  1032. isize_t sip_remote_party_id_dup_xtra(sip_header_t const *h, isize_t offset)
  1033. {
  1034. sip_remote_party_id_t const *rpid = (sip_remote_party_id_t *)h;
  1035. return sip_name_addr_xtra(rpid->rpid_display,
  1036. rpid->rpid_url,
  1037. rpid->rpid_params,
  1038. offset);
  1039. }
  1040. /** Duplicate one sip_remote_party_id_t object */
  1041. char *sip_remote_party_id_dup_one(sip_header_t *dst,
  1042. sip_header_t const *src,
  1043. char *b, isize_t xtra)
  1044. {
  1045. sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)dst;
  1046. sip_remote_party_id_t const *o = (sip_remote_party_id_t const *)src;
  1047. return sip_name_addr_dup(&rpid->rpid_display, o->rpid_display,
  1048. rpid->rpid_url, o->rpid_url,
  1049. &rpid->rpid_params, o->rpid_params,
  1050. b, xtra);
  1051. }
  1052. static int sip_remote_party_id_update(msg_common_t *h,
  1053. char const *name, isize_t namelen,
  1054. char const *value)
  1055. {
  1056. sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)h;
  1057. if (name == NULL) {
  1058. rpid->rpid_screen = NULL;
  1059. rpid->rpid_party = NULL;
  1060. rpid->rpid_id_type = NULL;
  1061. rpid->rpid_privacy = NULL;
  1062. }
  1063. #define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s)))
  1064. else if (MATCH(screen))
  1065. rpid->rpid_screen = value;
  1066. else if (MATCH(party))
  1067. rpid->rpid_party = value;
  1068. else if (MATCH(id-type))
  1069. rpid->rpid_id_type = value;
  1070. else if (MATCH(privacy))
  1071. rpid->rpid_privacy = value;
  1072. #undef MATCH
  1073. return 0;
  1074. }
  1075. #endif
  1076. #if SIP_HAVE_P_ASSERTED_IDENTITY
  1077. /**@SIP_HEADER sip_p_asserted_identity P-Asserted-Identity Header
  1078. *
  1079. * The P-Asserted-Identity header is used used among trusted SIP entities
  1080. * (typically intermediaries) to carry the identity of the user sending a
  1081. * SIP message as it was verified by authentication. It is "defined" in
  1082. * @RFC3325 section 9.1 as follows:
  1083. *
  1084. * @code
  1085. * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
  1086. * *(COMMA PAssertedID-value)
  1087. * PAssertedID-value = name-addr / addr-spec
  1088. * @endcode
  1089. *
  1090. * @sa @RFC3325, @PPreferredIdentity
  1091. *
  1092. * @NEW_1_12_7. In order to use @b P-Asserted-Identity header,
  1093. * initialize the SIP parser before calling nta_agent_create() or
  1094. * nua_create() with, e.g.,
  1095. * sip_update_default_mclass(sip_extend_mclass(NULL)).
  1096. * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
  1097. * as return of sip_extend_mclass(NULL) requires to be freed.
  1098. *
  1099. * @note
  1100. * The #sip_t structure does not contain @a sip_p_asserted_identity field,
  1101. * but sip_p_asserted_identity() function should be used for accessing the
  1102. * @b P-Asserted-Identity header structure.
  1103. */
  1104. /**@ingroup sip_p_asserted_identity
  1105. * @typedef typedef struct sip_p_asserted_identity_s sip_p_asserted_identity_t;
  1106. *
  1107. * The structure #sip_p_asserted_identity_t contains representation of SIP
  1108. * @PAssertedIdentity header.
  1109. *
  1110. * The #sip_p_asserted_identity_t is defined as follows:
  1111. * @code
  1112. * typedef struct sip_p_asserted_identity_s {
  1113. * sip_common_t paid_common[1]; // Common fragment info
  1114. * sip_p_asserted_identity_t *paid_next; // Link to next
  1115. * char const *paid_display; // Display name
  1116. * url_t paid_url[1]; // URL
  1117. * } sip_p_asserted_identity_t;
  1118. * @endcode
  1119. */
  1120. static msg_xtra_f sip_p_asserted_identity_dup_xtra;
  1121. static msg_dup_f sip_p_asserted_identity_dup_one;
  1122. #define sip_p_asserted_identity_update NULL
  1123. msg_hclass_t sip_p_asserted_identity_class[] =
  1124. SIP_HEADER_CLASS(p_asserted_identity, "P-Asserted-Identity", "",
  1125. paid_common, append, p_asserted_identity);
  1126. issize_t sip_p_asserted_identity_d(su_home_t *home, sip_header_t *h,
  1127. char *s, isize_t slen)
  1128. {
  1129. sip_p_asserted_identity_t *paid;
  1130. for(;;) {
  1131. paid = (sip_p_asserted_identity_t *)h;
  1132. while (*s == ',') /* Ignore empty entries (comma-whitespace) */
  1133. *s = '\0', s += span_lws(s + 1) + 1;
  1134. if (sip_name_addr_d(home, &s,
  1135. &paid->paid_display,
  1136. paid->paid_url,
  1137. NULL, NULL) == -1)
  1138. return -1;
  1139. msg_parse_next_field_without_recursion();
  1140. }
  1141. }
  1142. issize_t sip_p_asserted_identity_e(char b[], isize_t bsiz,
  1143. sip_header_t const *h, int f)
  1144. {
  1145. sip_p_asserted_identity_t const *paid = (sip_p_asserted_identity_t *)h;
  1146. return sip_name_addr_e(b, bsiz, f,
  1147. paid->paid_display, MSG_IS_CANONIC(f),
  1148. paid->paid_url,
  1149. NULL,
  1150. NULL);
  1151. }
  1152. isize_t sip_p_asserted_identity_dup_xtra(sip_header_t const *h, isize_t offset)
  1153. {
  1154. sip_p_asserted_identity_t const *paid = (sip_p_asserted_identity_t *)h;
  1155. return sip_name_addr_xtra(paid->paid_display,
  1156. paid->paid_url,
  1157. NULL,
  1158. offset);
  1159. }
  1160. /** Duplicate one sip_p_asserted_identity_t object */
  1161. char *sip_p_asserted_identity_dup_one(sip_header_t *dst,
  1162. sip_header_t const *src,
  1163. char *b, isize_t xtra)
  1164. {
  1165. sip_p_asserted_identity_t *paid = (sip_p_asserted_identity_t *)dst;
  1166. sip_p_asserted_identity_t const *o = (sip_p_asserted_identity_t *)src;
  1167. return sip_name_addr_dup(&paid->paid_display, o->paid_display,
  1168. paid->paid_url, o->paid_url,
  1169. NULL, NULL,
  1170. b, xtra);
  1171. }
  1172. #endif
  1173. #if SIP_HAVE_P_PREFERRED_IDENTITY
  1174. /**@SIP_HEADER sip_p_preferred_identity P-Preferred-Identity Header
  1175. *
  1176. * The P-Preferred-Identity header is used used among trusted SIP entities
  1177. * (typically intermediaries) to carry the identity of the user sending a
  1178. * SIP message as it was verified by authentication. It is "defined" in
  1179. * @RFC3325 section 9.1 as follows:
  1180. *
  1181. * @code
  1182. * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
  1183. * *(COMMA PPreferredID-value)
  1184. * PPreferredID-value = name-addr / addr-spec
  1185. * @endcode
  1186. *
  1187. * @sa @RFC3325, @PAssertedIdentity
  1188. *
  1189. * @NEW_1_12_7. In order to use @b P-Preferred-Identity header,
  1190. * initialize the SIP parser before calling nta_agent_create() or
  1191. * nua_create() with, e.g.,
  1192. * sip_update_default_mclass(sip_extend_mclass(NULL)).
  1193. * When finish don't forget to call sip_destroy_mclass(sip_default_mclass());
  1194. * as return of sip_extend_mclass(NULL) requires to be freed.
  1195. *
  1196. * @note
  1197. * The #sip_t structure does not contain @a sip_p_preferred_identity field,
  1198. * but sip_p_preferred_identity() function should be used for accessing the
  1199. * @b P-Preferred-Identity header structure.
  1200. */
  1201. /**@ingroup sip_p_preferred_identity
  1202. * @typedef typedef struct sip_p_preferred_identity_s sip_p_preferred_identity_t;
  1203. *
  1204. * The structure #sip_p_preferred_identity_t contains representation of SIP
  1205. * @PPreferredIdentity header.
  1206. *
  1207. * The #sip_p_preferred_identity_t is defined as follows:
  1208. * @code
  1209. * typedef struct sip_p_preferred_identity_s {
  1210. * sip_common_t ppid_common[1]; // Common fragment info
  1211. * sip_p_preferred_identity_t *ppid_next; // Link to next
  1212. * char const *ppid_display; // Display name
  1213. * url_t ppid_url[1]; // URL
  1214. * } sip_p_preferred_identity_t;
  1215. * @endcode
  1216. */
  1217. msg_hclass_t sip_p_preferred_identity_class[] =
  1218. SIP_HEADER_CLASS(p_preferred_identity, "P-Preferred-Identity", "",
  1219. ppid_common, append, p_asserted_identity);
  1220. issize_t sip_p_preferred_identity_d(su_home_t *home, sip_header_t *h,
  1221. char *s, isize_t slen)
  1222. {
  1223. return sip_p_asserted_identity_d(home, h, s, slen);
  1224. }
  1225. issize_t sip_p_preferred_identity_e(char b[], isize_t bsiz,
  1226. sip_header_t const *h, int f)
  1227. {
  1228. return sip_p_asserted_identity_e(b, bsiz, h, f);
  1229. }
  1230. #endif