blob: f2e59c9b48d35fd9b4c1ab68897768a1765ff37d [file] [log] [blame]
Benny Prijono834aee32006-02-19 01:38:06 +00001/* $Id$ */
2/*
Benny Prijono32177c02008-06-20 22:44:47 +00003 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono834aee32006-02-19 01:38:06 +00004 *
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>
Benny Prijono75130572008-07-17 13:53:41 +000022#include <pjlib-util/string.h>
Benny Prijono834aee32006-02-19 01:38:06 +000023#include <pj/pool.h>
24#include <pj/string.h>
25#include <pj/except.h>
26
27/*
28 * Event header.
29 */
30static int pjsip_event_hdr_print( pjsip_event_hdr *hdr,
31 char *buf, pj_size_t size);
32static pjsip_event_hdr* pjsip_event_hdr_clone( pj_pool_t *pool,
33 const pjsip_event_hdr *hdr);
34static pjsip_event_hdr* pjsip_event_hdr_shallow_clone( pj_pool_t *pool,
35 const pjsip_event_hdr*);
36
37static pjsip_hdr_vptr event_hdr_vptr =
38{
39 (pjsip_hdr_clone_fptr) &pjsip_event_hdr_clone,
40 (pjsip_hdr_clone_fptr) &pjsip_event_hdr_shallow_clone,
41 (pjsip_hdr_print_fptr) &pjsip_event_hdr_print,
42};
43
44
45PJ_DEF(pjsip_event_hdr*) pjsip_event_hdr_create(pj_pool_t *pool)
46{
Benny Prijono9d4469d2007-05-02 05:14:29 +000047 pjsip_event_hdr *hdr = PJ_POOL_ZALLOC_T(pool, pjsip_event_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +000048 hdr->type = PJSIP_H_OTHER;
49 hdr->name.ptr = "Event";
50 hdr->name.slen = 5;
51 hdr->sname.ptr = "o";
52 hdr->sname.slen = 1;
53 hdr->vptr = &event_hdr_vptr;
54 pj_list_init(hdr);
55 pj_list_init(&hdr->other_param);
56 return hdr;
57}
58
59static int pjsip_event_hdr_print( pjsip_event_hdr *hdr,
60 char *buf, pj_size_t size)
61{
62 char *p = buf;
63 char *endbuf = buf+size;
64 int printed;
Benny Prijono1f61a8f2007-08-16 10:11:44 +000065 const pjsip_parser_const_t *pc = pjsip_parser_const();
Benny Prijono834aee32006-02-19 01:38:06 +000066
67 copy_advance(p, hdr->name);
68 *p++ = ':';
69 *p++ = ' ';
70
71 copy_advance(p, hdr->event_type);
72 copy_advance_pair(p, ";id=", 4, hdr->id_param);
73
74 printed = pjsip_param_print_on(&hdr->other_param, p, endbuf-p,
Benny Prijono1f61a8f2007-08-16 10:11:44 +000075 &pc->pjsip_TOKEN_SPEC,
76 &pc->pjsip_TOKEN_SPEC, ';');
Benny Prijono834aee32006-02-19 01:38:06 +000077 if (printed < 0)
78 return printed;
79
80 p += printed;
81 return p - buf;
82}
83
84static pjsip_event_hdr* pjsip_event_hdr_clone( pj_pool_t *pool,
85 const pjsip_event_hdr *rhs)
86{
87 pjsip_event_hdr *hdr = pjsip_event_hdr_create(pool);
88 pj_strdup(pool, &hdr->event_type, &rhs->event_type);
89 pj_strdup(pool, &hdr->id_param, &rhs->id_param);
90 pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param);
91 return hdr;
92}
93
94static pjsip_event_hdr*
95pjsip_event_hdr_shallow_clone( pj_pool_t *pool,
96 const pjsip_event_hdr *rhs )
97{
Benny Prijono9d4469d2007-05-02 05:14:29 +000098 pjsip_event_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_event_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +000099 pj_memcpy(hdr, rhs, sizeof(*hdr));
100 pjsip_param_shallow_clone(pool, &hdr->other_param, &rhs->other_param);
101 return hdr;
102}
103
104
105/*
106 * Allow-Events header.
107 */
108PJ_DEF(pjsip_allow_events_hdr*) pjsip_allow_events_hdr_create(pj_pool_t *pool)
109{
110 const pj_str_t STR_ALLOW_EVENTS = { "Allow-Events", 12};
111 pjsip_allow_events_hdr *hdr;
112
113 hdr = pjsip_generic_array_hdr_create(pool, &STR_ALLOW_EVENTS);
114
115 if (hdr) {
116 hdr->sname.ptr = "u";
117 hdr->sname.slen = 1;
118 }
119
120 return hdr;
121}
122
123
124/*
125 * Subscription-State header.
126 */
127static int pjsip_sub_state_hdr_print(pjsip_sub_state_hdr *hdr,
128 char *buf, pj_size_t size);
129static pjsip_sub_state_hdr*
130pjsip_sub_state_hdr_clone(pj_pool_t *pool,
131 const pjsip_sub_state_hdr *hdr);
132static pjsip_sub_state_hdr*
133pjsip_sub_state_hdr_shallow_clone(pj_pool_t *pool,
134 const pjsip_sub_state_hdr*);
135
136static pjsip_hdr_vptr sub_state_hdr_vptr =
137{
138 (pjsip_hdr_clone_fptr) &pjsip_sub_state_hdr_clone,
139 (pjsip_hdr_clone_fptr) &pjsip_sub_state_hdr_shallow_clone,
140 (pjsip_hdr_print_fptr) &pjsip_sub_state_hdr_print,
141};
142
143
144PJ_DEF(pjsip_sub_state_hdr*) pjsip_sub_state_hdr_create(pj_pool_t *pool)
145{
146 pj_str_t sub_state = { "Subscription-State", 18 };
Benny Prijono9d4469d2007-05-02 05:14:29 +0000147 pjsip_sub_state_hdr *hdr = PJ_POOL_ZALLOC_T(pool, pjsip_sub_state_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +0000148 hdr->type = PJSIP_H_OTHER;
149 hdr->name = hdr->sname = sub_state;
150 hdr->vptr = &sub_state_hdr_vptr;
151 hdr->expires_param = -1;
152 hdr->retry_after = -1;
153 pj_list_init(hdr);
154 pj_list_init(&hdr->other_param);
155 return hdr;
156}
157
158static int pjsip_sub_state_hdr_print(pjsip_sub_state_hdr *hdr,
159 char *buf, pj_size_t size)
160{
161 char *p = buf;
162 char *endbuf = buf+size;
163 int printed;
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000164 const pjsip_parser_const_t *pc = pjsip_parser_const();
Benny Prijono834aee32006-02-19 01:38:06 +0000165
166 copy_advance(p, hdr->name);
167 *p++ = ':';
168 *p++ = ' ';
169
Benny Prijono75130572008-07-17 13:53:41 +0000170 copy_advance_escape(p, hdr->sub_state, pc->pjsip_TOKEN_SPEC);
171 copy_advance_pair_escape(p, ";reason=", 8, hdr->reason_param,
172 pc->pjsip_TOKEN_SPEC);
Benny Prijono834aee32006-02-19 01:38:06 +0000173 if (hdr->expires_param >= 0) {
174 pj_memcpy(p, ";expires=", 9);
175 p += 9;
176 printed = pj_utoa(hdr->expires_param, p);
177 p += printed;
178 }
179 if (hdr->retry_after >= 0) {
180 pj_memcpy(p, ";retry-after=", 13);
181 p += 9;
182 printed = pj_utoa(hdr->retry_after, p);
183 p += printed;
184 }
185
186 printed = pjsip_param_print_on( &hdr->other_param, p, endbuf-p,
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000187 &pc->pjsip_TOKEN_SPEC,
188 &pc->pjsip_TOKEN_SPEC,
Benny Prijono834aee32006-02-19 01:38:06 +0000189 ';');
190 if (printed < 0)
191 return printed;
192
193 p += printed;
194
195 return p - buf;
196}
197
198static pjsip_sub_state_hdr*
199pjsip_sub_state_hdr_clone(pj_pool_t *pool,
200 const pjsip_sub_state_hdr *rhs)
201{
202 pjsip_sub_state_hdr *hdr = pjsip_sub_state_hdr_create(pool);
203 pj_strdup(pool, &hdr->sub_state, &rhs->sub_state);
204 pj_strdup(pool, &hdr->reason_param, &rhs->reason_param);
205 hdr->retry_after = rhs->retry_after;
206 hdr->expires_param = rhs->expires_param;
207 pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param);
208 return hdr;
209}
210
211static pjsip_sub_state_hdr*
212pjsip_sub_state_hdr_shallow_clone(pj_pool_t *pool,
213 const pjsip_sub_state_hdr *rhs)
214{
Benny Prijono9d4469d2007-05-02 05:14:29 +0000215 pjsip_sub_state_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_sub_state_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +0000216 pj_memcpy(hdr, rhs, sizeof(*hdr));
217 pjsip_param_shallow_clone(pool, &hdr->other_param, &rhs->other_param);
218 return hdr;
219}
220
221
222/*
223 * Parse Event header.
224 */
225static pjsip_hdr *parse_hdr_event(pjsip_parse_ctx *ctx)
226{
227 pjsip_event_hdr *hdr = pjsip_event_hdr_create(ctx->pool);
228 const pj_str_t id_param = { "id", 2 };
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000229 const pjsip_parser_const_t *pc = pjsip_parser_const();
Benny Prijono834aee32006-02-19 01:38:06 +0000230
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000231 pj_scan_get(ctx->scanner, &pc->pjsip_TOKEN_SPEC, &hdr->event_type);
Benny Prijono834aee32006-02-19 01:38:06 +0000232
233 while (*ctx->scanner->curptr == ';') {
234 pj_str_t pname, pvalue;
235
236 pj_scan_get_char(ctx->scanner);
237 pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0);
238
239 if (pj_stricmp(&pname, &id_param)==0) {
240 hdr->id_param = pvalue;
241 } else {
Benny Prijono9d4469d2007-05-02 05:14:29 +0000242 pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
Benny Prijono834aee32006-02-19 01:38:06 +0000243 param->name = pname;
244 param->value = pvalue;
245 pj_list_push_back(&hdr->other_param, param);
246 }
247 }
248 pjsip_parse_end_hdr_imp( ctx->scanner );
249 return (pjsip_hdr*)hdr;
250}
251
252/*
253 * Parse Subscription-State header.
254 */
255static pjsip_hdr* parse_hdr_sub_state( pjsip_parse_ctx *ctx )
256{
257 pjsip_sub_state_hdr *hdr = pjsip_sub_state_hdr_create(ctx->pool);
258 const pj_str_t reason = { "reason", 6 },
259 expires = { "expires", 7 },
260 retry_after = { "retry-after", 11 };
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000261 const pjsip_parser_const_t *pc = pjsip_parser_const();
262
263 pj_scan_get(ctx->scanner, &pc->pjsip_TOKEN_SPEC, &hdr->sub_state);
Benny Prijono834aee32006-02-19 01:38:06 +0000264
265 while (*ctx->scanner->curptr == ';') {
266 pj_str_t pname, pvalue;
267
268 pj_scan_get_char(ctx->scanner);
269 pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0);
270
271 if (pj_stricmp(&pname, &reason) == 0) {
272 hdr->reason_param = pvalue;
273
274 } else if (pj_stricmp(&pname, &expires) == 0) {
275 hdr->expires_param = pj_strtoul(&pvalue);
276
277 } else if (pj_stricmp(&pname, &retry_after) == 0) {
278 hdr->retry_after = pj_strtoul(&pvalue);
279
280 } else {
Benny Prijono9d4469d2007-05-02 05:14:29 +0000281 pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
Benny Prijono834aee32006-02-19 01:38:06 +0000282 param->name = pname;
283 param->value = pvalue;
284 pj_list_push_back(&hdr->other_param, param);
285 }
286 }
287
288 pjsip_parse_end_hdr_imp( ctx->scanner );
289 return (pjsip_hdr*)hdr;
290}
291
292/*
293 * Register header parsers.
294 */
295PJ_DEF(void) pjsip_evsub_init_parser(void)
296{
297 pjsip_register_hdr_parser( "Event", NULL,
298 &parse_hdr_event);
299
300 pjsip_register_hdr_parser( "Subscription-State", NULL,
301 &parse_hdr_sub_state);
302}
303