evsub_msg.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include <pjsip-simple/evsub_msg.h>
  20. #include <pjsip/print_util.h>
  21. #include <pjsip/sip_parser.h>
  22. #include <pjlib-util/string.h>
  23. #include <pj/pool.h>
  24. #include <pj/string.h>
  25. #include <pj/except.h>
  26. /*
  27. * Event header.
  28. */
  29. static int pjsip_event_hdr_print( pjsip_event_hdr *hdr,
  30. char *buf, pj_size_t size);
  31. static pjsip_event_hdr* pjsip_event_hdr_clone( pj_pool_t *pool,
  32. const pjsip_event_hdr *hdr);
  33. static pjsip_event_hdr* pjsip_event_hdr_shallow_clone( pj_pool_t *pool,
  34. const pjsip_event_hdr*);
  35. static pjsip_hdr_vptr event_hdr_vptr =
  36. {
  37. (pjsip_hdr_clone_fptr) &pjsip_event_hdr_clone,
  38. (pjsip_hdr_clone_fptr) &pjsip_event_hdr_shallow_clone,
  39. (pjsip_hdr_print_fptr) &pjsip_event_hdr_print,
  40. };
  41. PJ_DEF(pjsip_event_hdr*) pjsip_event_hdr_create(pj_pool_t *pool)
  42. {
  43. pjsip_event_hdr *hdr = PJ_POOL_ZALLOC_T(pool, pjsip_event_hdr);
  44. hdr->type = PJSIP_H_OTHER;
  45. hdr->name.ptr = "Event";
  46. hdr->name.slen = 5;
  47. hdr->sname.ptr = "o";
  48. hdr->sname.slen = 1;
  49. hdr->vptr = &event_hdr_vptr;
  50. pj_list_init(hdr);
  51. pj_list_init(&hdr->other_param);
  52. return hdr;
  53. }
  54. static int pjsip_event_hdr_print( pjsip_event_hdr *hdr,
  55. char *buf, pj_size_t size)
  56. {
  57. char *p = buf;
  58. char *endbuf = buf+size;
  59. pj_ssize_t printed;
  60. const pjsip_parser_const_t *pc = pjsip_parser_const();
  61. copy_advance(p, hdr->name);
  62. *p++ = ':';
  63. *p++ = ' ';
  64. copy_advance(p, hdr->event_type);
  65. copy_advance_pair(p, ";id=", 4, hdr->id_param);
  66. printed = pjsip_param_print_on(&hdr->other_param, p, endbuf-p,
  67. &pc->pjsip_TOKEN_SPEC,
  68. &pc->pjsip_TOKEN_SPEC, ';');
  69. if (printed < 0)
  70. return (int)printed;
  71. p += printed;
  72. return (int)(p - buf);
  73. }
  74. static pjsip_event_hdr* pjsip_event_hdr_clone( pj_pool_t *pool,
  75. const pjsip_event_hdr *rhs)
  76. {
  77. pjsip_event_hdr *hdr = pjsip_event_hdr_create(pool);
  78. pj_strdup(pool, &hdr->event_type, &rhs->event_type);
  79. pj_strdup(pool, &hdr->id_param, &rhs->id_param);
  80. pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param);
  81. return hdr;
  82. }
  83. static pjsip_event_hdr*
  84. pjsip_event_hdr_shallow_clone( pj_pool_t *pool,
  85. const pjsip_event_hdr *rhs )
  86. {
  87. pjsip_event_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_event_hdr);
  88. pj_memcpy(hdr, rhs, sizeof(*hdr));
  89. pjsip_param_shallow_clone(pool, &hdr->other_param, &rhs->other_param);
  90. return hdr;
  91. }
  92. /*
  93. * Allow-Events header.
  94. */
  95. PJ_DEF(pjsip_allow_events_hdr*) pjsip_allow_events_hdr_create(pj_pool_t *pool)
  96. {
  97. const pj_str_t STR_ALLOW_EVENTS = { "Allow-Events", 12};
  98. pjsip_allow_events_hdr *hdr;
  99. hdr = pjsip_generic_array_hdr_create(pool, &STR_ALLOW_EVENTS);
  100. if (hdr) {
  101. hdr->sname.ptr = "u";
  102. hdr->sname.slen = 1;
  103. }
  104. return hdr;
  105. }
  106. /*
  107. * Subscription-State header.
  108. */
  109. static int pjsip_sub_state_hdr_print(pjsip_sub_state_hdr *hdr,
  110. char *buf, pj_size_t size);
  111. static pjsip_sub_state_hdr*
  112. pjsip_sub_state_hdr_clone(pj_pool_t *pool,
  113. const pjsip_sub_state_hdr *hdr);
  114. static pjsip_sub_state_hdr*
  115. pjsip_sub_state_hdr_shallow_clone(pj_pool_t *pool,
  116. const pjsip_sub_state_hdr*);
  117. static pjsip_hdr_vptr sub_state_hdr_vptr =
  118. {
  119. (pjsip_hdr_clone_fptr) &pjsip_sub_state_hdr_clone,
  120. (pjsip_hdr_clone_fptr) &pjsip_sub_state_hdr_shallow_clone,
  121. (pjsip_hdr_print_fptr) &pjsip_sub_state_hdr_print,
  122. };
  123. PJ_DEF(pjsip_sub_state_hdr*) pjsip_sub_state_hdr_create(pj_pool_t *pool)
  124. {
  125. pj_str_t sub_state = { "Subscription-State", 18 };
  126. pjsip_sub_state_hdr *hdr = PJ_POOL_ZALLOC_T(pool, pjsip_sub_state_hdr);
  127. hdr->type = PJSIP_H_OTHER;
  128. hdr->name = hdr->sname = sub_state;
  129. hdr->vptr = &sub_state_hdr_vptr;
  130. hdr->expires_param = PJSIP_EXPIRES_NOT_SPECIFIED;
  131. hdr->retry_after = -1;
  132. pj_list_init(hdr);
  133. pj_list_init(&hdr->other_param);
  134. return hdr;
  135. }
  136. static int pjsip_sub_state_hdr_print(pjsip_sub_state_hdr *hdr,
  137. char *buf, pj_size_t size)
  138. {
  139. char *p = buf;
  140. char *endbuf = buf+size;
  141. pj_ssize_t printed;
  142. const pjsip_parser_const_t *pc = pjsip_parser_const();
  143. copy_advance(p, hdr->name);
  144. *p++ = ':';
  145. *p++ = ' ';
  146. copy_advance_escape(p, hdr->sub_state, pc->pjsip_TOKEN_SPEC);
  147. copy_advance_pair_escape(p, ";reason=", 8, hdr->reason_param,
  148. pc->pjsip_TOKEN_SPEC);
  149. if (hdr->expires_param != PJSIP_EXPIRES_NOT_SPECIFIED) {
  150. pj_memcpy(p, ";expires=", 9);
  151. p += 9;
  152. printed = pj_utoa(hdr->expires_param, p);
  153. p += printed;
  154. }
  155. if (hdr->retry_after >= 0) {
  156. pj_memcpy(p, ";retry-after=", 13);
  157. p += 13;
  158. printed = pj_utoa(hdr->retry_after, p);
  159. p += printed;
  160. }
  161. printed = pjsip_param_print_on( &hdr->other_param, p, endbuf-p,
  162. &pc->pjsip_TOKEN_SPEC,
  163. &pc->pjsip_TOKEN_SPEC,
  164. ';');
  165. if (printed < 0)
  166. return (int)printed;
  167. p += printed;
  168. return (int)(p - buf);
  169. }
  170. static pjsip_sub_state_hdr*
  171. pjsip_sub_state_hdr_clone(pj_pool_t *pool,
  172. const pjsip_sub_state_hdr *rhs)
  173. {
  174. pjsip_sub_state_hdr *hdr = pjsip_sub_state_hdr_create(pool);
  175. pj_strdup(pool, &hdr->sub_state, &rhs->sub_state);
  176. pj_strdup(pool, &hdr->reason_param, &rhs->reason_param);
  177. hdr->retry_after = rhs->retry_after;
  178. hdr->expires_param = rhs->expires_param;
  179. pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param);
  180. return hdr;
  181. }
  182. static pjsip_sub_state_hdr*
  183. pjsip_sub_state_hdr_shallow_clone(pj_pool_t *pool,
  184. const pjsip_sub_state_hdr *rhs)
  185. {
  186. pjsip_sub_state_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_sub_state_hdr);
  187. pj_memcpy(hdr, rhs, sizeof(*hdr));
  188. pjsip_param_shallow_clone(pool, &hdr->other_param, &rhs->other_param);
  189. return hdr;
  190. }
  191. /*
  192. * Parse Event header.
  193. */
  194. static pjsip_hdr *parse_hdr_event(pjsip_parse_ctx *ctx)
  195. {
  196. pjsip_event_hdr *hdr = pjsip_event_hdr_create(ctx->pool);
  197. const pj_str_t id_param = { "id", 2 };
  198. const pjsip_parser_const_t *pc = pjsip_parser_const();
  199. pj_scan_get(ctx->scanner, &pc->pjsip_TOKEN_SPEC, &hdr->event_type);
  200. while (*ctx->scanner->curptr == ';') {
  201. pj_str_t pname, pvalue;
  202. pj_scan_get_char(ctx->scanner);
  203. pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0);
  204. if (pj_stricmp(&pname, &id_param)==0) {
  205. hdr->id_param = pvalue;
  206. } else {
  207. pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
  208. param->name = pname;
  209. param->value = pvalue;
  210. pj_list_push_back(&hdr->other_param, param);
  211. }
  212. }
  213. pjsip_parse_end_hdr_imp( ctx->scanner );
  214. return (pjsip_hdr*)hdr;
  215. }
  216. /*
  217. * Parse Subscription-State header.
  218. */
  219. static pjsip_hdr* parse_hdr_sub_state( pjsip_parse_ctx *ctx )
  220. {
  221. pjsip_sub_state_hdr *hdr = pjsip_sub_state_hdr_create(ctx->pool);
  222. const pj_str_t reason = { "reason", 6 },
  223. expires = { "expires", 7 },
  224. retry_after = { "retry-after", 11 };
  225. const pjsip_parser_const_t *pc = pjsip_parser_const();
  226. pj_scan_get(ctx->scanner, &pc->pjsip_TOKEN_SPEC, &hdr->sub_state);
  227. while (*ctx->scanner->curptr == ';') {
  228. pj_str_t pname, pvalue;
  229. pj_scan_get_char(ctx->scanner);
  230. pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0);
  231. if (pj_stricmp(&pname, &reason) == 0) {
  232. hdr->reason_param = pvalue;
  233. } else if (pj_stricmp(&pname, &expires) == 0) {
  234. hdr->expires_param = pj_strtoul(&pvalue);
  235. if (hdr->expires_param == PJSIP_EXPIRES_NOT_SPECIFIED)
  236. hdr->expires_param--;
  237. } else if (pj_stricmp(&pname, &retry_after) == 0) {
  238. hdr->retry_after = pj_strtoul(&pvalue);
  239. } else {
  240. pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
  241. param->name = pname;
  242. param->value = pvalue;
  243. pj_list_push_back(&hdr->other_param, param);
  244. }
  245. }
  246. pjsip_parse_end_hdr_imp( ctx->scanner );
  247. return (pjsip_hdr*)hdr;
  248. }
  249. /*
  250. * Register header parsers.
  251. */
  252. PJ_DEF(pj_status_t) pjsip_evsub_init_parser(void)
  253. {
  254. pj_status_t status;
  255. status = pjsip_register_hdr_parser( "Event", "o",
  256. &parse_hdr_event);
  257. PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
  258. status = pjsip_register_hdr_parser( "Subscription-State", NULL,
  259. &parse_hdr_sub_state);
  260. PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
  261. return PJ_SUCCESS;
  262. }