blob: 467345d9fcfa86786641bb9290e3bb788180a957 [file] [log] [blame]
Benny Prijono834aee32006-02-19 01:38:06 +00001/* $Id$ */
2/*
Benny Prijonoa771a512007-02-19 01:13:53 +00003 * Copyright (C) 2003-2007 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>
22#include <pj/pool.h>
23#include <pj/string.h>
24#include <pj/except.h>
25
26/*
27 * Event header.
28 */
29static int pjsip_event_hdr_print( pjsip_event_hdr *hdr,
30 char *buf, pj_size_t size);
31static pjsip_event_hdr* pjsip_event_hdr_clone( pj_pool_t *pool,
32 const pjsip_event_hdr *hdr);
33static pjsip_event_hdr* pjsip_event_hdr_shallow_clone( pj_pool_t *pool,
34 const pjsip_event_hdr*);
35
36static pjsip_hdr_vptr event_hdr_vptr =
37{
38 (pjsip_hdr_clone_fptr) &pjsip_event_hdr_clone,
39 (pjsip_hdr_clone_fptr) &pjsip_event_hdr_shallow_clone,
40 (pjsip_hdr_print_fptr) &pjsip_event_hdr_print,
41};
42
43
44PJ_DEF(pjsip_event_hdr*) pjsip_event_hdr_create(pj_pool_t *pool)
45{
Benny Prijono9d4469d2007-05-02 05:14:29 +000046 pjsip_event_hdr *hdr = PJ_POOL_ZALLOC_T(pool, pjsip_event_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +000047 hdr->type = PJSIP_H_OTHER;
48 hdr->name.ptr = "Event";
49 hdr->name.slen = 5;
50 hdr->sname.ptr = "o";
51 hdr->sname.slen = 1;
52 hdr->vptr = &event_hdr_vptr;
53 pj_list_init(hdr);
54 pj_list_init(&hdr->other_param);
55 return hdr;
56}
57
58static int pjsip_event_hdr_print( pjsip_event_hdr *hdr,
59 char *buf, pj_size_t size)
60{
61 char *p = buf;
62 char *endbuf = buf+size;
63 int printed;
64
65 copy_advance(p, hdr->name);
66 *p++ = ':';
67 *p++ = ' ';
68
69 copy_advance(p, hdr->event_type);
70 copy_advance_pair(p, ";id=", 4, hdr->id_param);
71
72 printed = pjsip_param_print_on(&hdr->other_param, p, endbuf-p,
Benny Prijonof55c02f2006-07-17 10:04:12 +000073 &pjsip_TOKEN_SPEC,
74 &pjsip_TOKEN_SPEC, ';');
Benny Prijono834aee32006-02-19 01:38:06 +000075 if (printed < 0)
76 return printed;
77
78 p += printed;
79 return p - buf;
80}
81
82static pjsip_event_hdr* pjsip_event_hdr_clone( pj_pool_t *pool,
83 const pjsip_event_hdr *rhs)
84{
85 pjsip_event_hdr *hdr = pjsip_event_hdr_create(pool);
86 pj_strdup(pool, &hdr->event_type, &rhs->event_type);
87 pj_strdup(pool, &hdr->id_param, &rhs->id_param);
88 pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param);
89 return hdr;
90}
91
92static pjsip_event_hdr*
93pjsip_event_hdr_shallow_clone( pj_pool_t *pool,
94 const pjsip_event_hdr *rhs )
95{
Benny Prijono9d4469d2007-05-02 05:14:29 +000096 pjsip_event_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_event_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +000097 pj_memcpy(hdr, rhs, sizeof(*hdr));
98 pjsip_param_shallow_clone(pool, &hdr->other_param, &rhs->other_param);
99 return hdr;
100}
101
102
103/*
104 * Allow-Events header.
105 */
106PJ_DEF(pjsip_allow_events_hdr*) pjsip_allow_events_hdr_create(pj_pool_t *pool)
107{
108 const pj_str_t STR_ALLOW_EVENTS = { "Allow-Events", 12};
109 pjsip_allow_events_hdr *hdr;
110
111 hdr = pjsip_generic_array_hdr_create(pool, &STR_ALLOW_EVENTS);
112
113 if (hdr) {
114 hdr->sname.ptr = "u";
115 hdr->sname.slen = 1;
116 }
117
118 return hdr;
119}
120
121
122/*
123 * Subscription-State header.
124 */
125static int pjsip_sub_state_hdr_print(pjsip_sub_state_hdr *hdr,
126 char *buf, pj_size_t size);
127static pjsip_sub_state_hdr*
128pjsip_sub_state_hdr_clone(pj_pool_t *pool,
129 const pjsip_sub_state_hdr *hdr);
130static pjsip_sub_state_hdr*
131pjsip_sub_state_hdr_shallow_clone(pj_pool_t *pool,
132 const pjsip_sub_state_hdr*);
133
134static pjsip_hdr_vptr sub_state_hdr_vptr =
135{
136 (pjsip_hdr_clone_fptr) &pjsip_sub_state_hdr_clone,
137 (pjsip_hdr_clone_fptr) &pjsip_sub_state_hdr_shallow_clone,
138 (pjsip_hdr_print_fptr) &pjsip_sub_state_hdr_print,
139};
140
141
142PJ_DEF(pjsip_sub_state_hdr*) pjsip_sub_state_hdr_create(pj_pool_t *pool)
143{
144 pj_str_t sub_state = { "Subscription-State", 18 };
Benny Prijono9d4469d2007-05-02 05:14:29 +0000145 pjsip_sub_state_hdr *hdr = PJ_POOL_ZALLOC_T(pool, pjsip_sub_state_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +0000146 hdr->type = PJSIP_H_OTHER;
147 hdr->name = hdr->sname = sub_state;
148 hdr->vptr = &sub_state_hdr_vptr;
149 hdr->expires_param = -1;
150 hdr->retry_after = -1;
151 pj_list_init(hdr);
152 pj_list_init(&hdr->other_param);
153 return hdr;
154}
155
156static int pjsip_sub_state_hdr_print(pjsip_sub_state_hdr *hdr,
157 char *buf, pj_size_t size)
158{
159 char *p = buf;
160 char *endbuf = buf+size;
161 int printed;
162
163 copy_advance(p, hdr->name);
164 *p++ = ':';
165 *p++ = ' ';
166
167 copy_advance(p, hdr->sub_state);
168 copy_advance_pair(p, ";reason=", 8, hdr->reason_param);
169 if (hdr->expires_param >= 0) {
170 pj_memcpy(p, ";expires=", 9);
171 p += 9;
172 printed = pj_utoa(hdr->expires_param, p);
173 p += printed;
174 }
175 if (hdr->retry_after >= 0) {
176 pj_memcpy(p, ";retry-after=", 13);
177 p += 9;
178 printed = pj_utoa(hdr->retry_after, p);
179 p += printed;
180 }
181
182 printed = pjsip_param_print_on( &hdr->other_param, p, endbuf-p,
Benny Prijonof55c02f2006-07-17 10:04:12 +0000183 &pjsip_TOKEN_SPEC,
184 &pjsip_TOKEN_SPEC,
Benny Prijono834aee32006-02-19 01:38:06 +0000185 ';');
186 if (printed < 0)
187 return printed;
188
189 p += printed;
190
191 return p - buf;
192}
193
194static pjsip_sub_state_hdr*
195pjsip_sub_state_hdr_clone(pj_pool_t *pool,
196 const pjsip_sub_state_hdr *rhs)
197{
198 pjsip_sub_state_hdr *hdr = pjsip_sub_state_hdr_create(pool);
199 pj_strdup(pool, &hdr->sub_state, &rhs->sub_state);
200 pj_strdup(pool, &hdr->reason_param, &rhs->reason_param);
201 hdr->retry_after = rhs->retry_after;
202 hdr->expires_param = rhs->expires_param;
203 pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param);
204 return hdr;
205}
206
207static pjsip_sub_state_hdr*
208pjsip_sub_state_hdr_shallow_clone(pj_pool_t *pool,
209 const pjsip_sub_state_hdr *rhs)
210{
Benny Prijono9d4469d2007-05-02 05:14:29 +0000211 pjsip_sub_state_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_sub_state_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +0000212 pj_memcpy(hdr, rhs, sizeof(*hdr));
213 pjsip_param_shallow_clone(pool, &hdr->other_param, &rhs->other_param);
214 return hdr;
215}
216
217
218/*
219 * Parse Event header.
220 */
221static pjsip_hdr *parse_hdr_event(pjsip_parse_ctx *ctx)
222{
223 pjsip_event_hdr *hdr = pjsip_event_hdr_create(ctx->pool);
224 const pj_str_t id_param = { "id", 2 };
225
226 pj_scan_get(ctx->scanner, &pjsip_TOKEN_SPEC, &hdr->event_type);
227
228 while (*ctx->scanner->curptr == ';') {
229 pj_str_t pname, pvalue;
230
231 pj_scan_get_char(ctx->scanner);
232 pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0);
233
234 if (pj_stricmp(&pname, &id_param)==0) {
235 hdr->id_param = pvalue;
236 } else {
Benny Prijono9d4469d2007-05-02 05:14:29 +0000237 pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
Benny Prijono834aee32006-02-19 01:38:06 +0000238 param->name = pname;
239 param->value = pvalue;
240 pj_list_push_back(&hdr->other_param, param);
241 }
242 }
243 pjsip_parse_end_hdr_imp( ctx->scanner );
244 return (pjsip_hdr*)hdr;
245}
246
247/*
248 * Parse Subscription-State header.
249 */
250static pjsip_hdr* parse_hdr_sub_state( pjsip_parse_ctx *ctx )
251{
252 pjsip_sub_state_hdr *hdr = pjsip_sub_state_hdr_create(ctx->pool);
253 const pj_str_t reason = { "reason", 6 },
254 expires = { "expires", 7 },
255 retry_after = { "retry-after", 11 };
256 pj_scan_get(ctx->scanner, &pjsip_TOKEN_SPEC, &hdr->sub_state);
257
258 while (*ctx->scanner->curptr == ';') {
259 pj_str_t pname, pvalue;
260
261 pj_scan_get_char(ctx->scanner);
262 pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0);
263
264 if (pj_stricmp(&pname, &reason) == 0) {
265 hdr->reason_param = pvalue;
266
267 } else if (pj_stricmp(&pname, &expires) == 0) {
268 hdr->expires_param = pj_strtoul(&pvalue);
269
270 } else if (pj_stricmp(&pname, &retry_after) == 0) {
271 hdr->retry_after = pj_strtoul(&pvalue);
272
273 } else {
Benny Prijono9d4469d2007-05-02 05:14:29 +0000274 pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
Benny Prijono834aee32006-02-19 01:38:06 +0000275 param->name = pname;
276 param->value = pvalue;
277 pj_list_push_back(&hdr->other_param, param);
278 }
279 }
280
281 pjsip_parse_end_hdr_imp( ctx->scanner );
282 return (pjsip_hdr*)hdr;
283}
284
285/*
286 * Register header parsers.
287 */
288PJ_DEF(void) pjsip_evsub_init_parser(void)
289{
290 pjsip_register_hdr_parser( "Event", NULL,
291 &parse_hdr_event);
292
293 pjsip_register_hdr_parser( "Subscription-State", NULL,
294 &parse_hdr_sub_state);
295}
296