blob: 19058b15c97835de6868da4acd88d46f2ede836e [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;
Benny Prijono1f61a8f2007-08-16 10:11:44 +000064 const pjsip_parser_const_t *pc = pjsip_parser_const();
Benny Prijono834aee32006-02-19 01:38:06 +000065
66 copy_advance(p, hdr->name);
67 *p++ = ':';
68 *p++ = ' ';
69
70 copy_advance(p, hdr->event_type);
71 copy_advance_pair(p, ";id=", 4, hdr->id_param);
72
73 printed = pjsip_param_print_on(&hdr->other_param, p, endbuf-p,
Benny Prijono1f61a8f2007-08-16 10:11:44 +000074 &pc->pjsip_TOKEN_SPEC,
75 &pc->pjsip_TOKEN_SPEC, ';');
Benny Prijono834aee32006-02-19 01:38:06 +000076 if (printed < 0)
77 return printed;
78
79 p += printed;
80 return p - buf;
81}
82
83static pjsip_event_hdr* pjsip_event_hdr_clone( pj_pool_t *pool,
84 const pjsip_event_hdr *rhs)
85{
86 pjsip_event_hdr *hdr = pjsip_event_hdr_create(pool);
87 pj_strdup(pool, &hdr->event_type, &rhs->event_type);
88 pj_strdup(pool, &hdr->id_param, &rhs->id_param);
89 pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param);
90 return hdr;
91}
92
93static pjsip_event_hdr*
94pjsip_event_hdr_shallow_clone( pj_pool_t *pool,
95 const pjsip_event_hdr *rhs )
96{
Benny Prijono9d4469d2007-05-02 05:14:29 +000097 pjsip_event_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_event_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +000098 pj_memcpy(hdr, rhs, sizeof(*hdr));
99 pjsip_param_shallow_clone(pool, &hdr->other_param, &rhs->other_param);
100 return hdr;
101}
102
103
104/*
105 * Allow-Events header.
106 */
107PJ_DEF(pjsip_allow_events_hdr*) pjsip_allow_events_hdr_create(pj_pool_t *pool)
108{
109 const pj_str_t STR_ALLOW_EVENTS = { "Allow-Events", 12};
110 pjsip_allow_events_hdr *hdr;
111
112 hdr = pjsip_generic_array_hdr_create(pool, &STR_ALLOW_EVENTS);
113
114 if (hdr) {
115 hdr->sname.ptr = "u";
116 hdr->sname.slen = 1;
117 }
118
119 return hdr;
120}
121
122
123/*
124 * Subscription-State header.
125 */
126static int pjsip_sub_state_hdr_print(pjsip_sub_state_hdr *hdr,
127 char *buf, pj_size_t size);
128static pjsip_sub_state_hdr*
129pjsip_sub_state_hdr_clone(pj_pool_t *pool,
130 const pjsip_sub_state_hdr *hdr);
131static pjsip_sub_state_hdr*
132pjsip_sub_state_hdr_shallow_clone(pj_pool_t *pool,
133 const pjsip_sub_state_hdr*);
134
135static pjsip_hdr_vptr sub_state_hdr_vptr =
136{
137 (pjsip_hdr_clone_fptr) &pjsip_sub_state_hdr_clone,
138 (pjsip_hdr_clone_fptr) &pjsip_sub_state_hdr_shallow_clone,
139 (pjsip_hdr_print_fptr) &pjsip_sub_state_hdr_print,
140};
141
142
143PJ_DEF(pjsip_sub_state_hdr*) pjsip_sub_state_hdr_create(pj_pool_t *pool)
144{
145 pj_str_t sub_state = { "Subscription-State", 18 };
Benny Prijono9d4469d2007-05-02 05:14:29 +0000146 pjsip_sub_state_hdr *hdr = PJ_POOL_ZALLOC_T(pool, pjsip_sub_state_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +0000147 hdr->type = PJSIP_H_OTHER;
148 hdr->name = hdr->sname = sub_state;
149 hdr->vptr = &sub_state_hdr_vptr;
150 hdr->expires_param = -1;
151 hdr->retry_after = -1;
152 pj_list_init(hdr);
153 pj_list_init(&hdr->other_param);
154 return hdr;
155}
156
157static int pjsip_sub_state_hdr_print(pjsip_sub_state_hdr *hdr,
158 char *buf, pj_size_t size)
159{
160 char *p = buf;
161 char *endbuf = buf+size;
162 int printed;
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000163 const pjsip_parser_const_t *pc = pjsip_parser_const();
Benny Prijono834aee32006-02-19 01:38:06 +0000164
165 copy_advance(p, hdr->name);
166 *p++ = ':';
167 *p++ = ' ';
168
169 copy_advance(p, hdr->sub_state);
170 copy_advance_pair(p, ";reason=", 8, hdr->reason_param);
171 if (hdr->expires_param >= 0) {
172 pj_memcpy(p, ";expires=", 9);
173 p += 9;
174 printed = pj_utoa(hdr->expires_param, p);
175 p += printed;
176 }
177 if (hdr->retry_after >= 0) {
178 pj_memcpy(p, ";retry-after=", 13);
179 p += 9;
180 printed = pj_utoa(hdr->retry_after, p);
181 p += printed;
182 }
183
184 printed = pjsip_param_print_on( &hdr->other_param, p, endbuf-p,
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000185 &pc->pjsip_TOKEN_SPEC,
186 &pc->pjsip_TOKEN_SPEC,
Benny Prijono834aee32006-02-19 01:38:06 +0000187 ';');
188 if (printed < 0)
189 return printed;
190
191 p += printed;
192
193 return p - buf;
194}
195
196static pjsip_sub_state_hdr*
197pjsip_sub_state_hdr_clone(pj_pool_t *pool,
198 const pjsip_sub_state_hdr *rhs)
199{
200 pjsip_sub_state_hdr *hdr = pjsip_sub_state_hdr_create(pool);
201 pj_strdup(pool, &hdr->sub_state, &rhs->sub_state);
202 pj_strdup(pool, &hdr->reason_param, &rhs->reason_param);
203 hdr->retry_after = rhs->retry_after;
204 hdr->expires_param = rhs->expires_param;
205 pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param);
206 return hdr;
207}
208
209static pjsip_sub_state_hdr*
210pjsip_sub_state_hdr_shallow_clone(pj_pool_t *pool,
211 const pjsip_sub_state_hdr *rhs)
212{
Benny Prijono9d4469d2007-05-02 05:14:29 +0000213 pjsip_sub_state_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_sub_state_hdr);
Benny Prijono834aee32006-02-19 01:38:06 +0000214 pj_memcpy(hdr, rhs, sizeof(*hdr));
215 pjsip_param_shallow_clone(pool, &hdr->other_param, &rhs->other_param);
216 return hdr;
217}
218
219
220/*
221 * Parse Event header.
222 */
223static pjsip_hdr *parse_hdr_event(pjsip_parse_ctx *ctx)
224{
225 pjsip_event_hdr *hdr = pjsip_event_hdr_create(ctx->pool);
226 const pj_str_t id_param = { "id", 2 };
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000227 const pjsip_parser_const_t *pc = pjsip_parser_const();
Benny Prijono834aee32006-02-19 01:38:06 +0000228
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000229 pj_scan_get(ctx->scanner, &pc->pjsip_TOKEN_SPEC, &hdr->event_type);
Benny Prijono834aee32006-02-19 01:38:06 +0000230
231 while (*ctx->scanner->curptr == ';') {
232 pj_str_t pname, pvalue;
233
234 pj_scan_get_char(ctx->scanner);
235 pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0);
236
237 if (pj_stricmp(&pname, &id_param)==0) {
238 hdr->id_param = pvalue;
239 } else {
Benny Prijono9d4469d2007-05-02 05:14:29 +0000240 pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
Benny Prijono834aee32006-02-19 01:38:06 +0000241 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/*
251 * Parse Subscription-State header.
252 */
253static pjsip_hdr* parse_hdr_sub_state( pjsip_parse_ctx *ctx )
254{
255 pjsip_sub_state_hdr *hdr = pjsip_sub_state_hdr_create(ctx->pool);
256 const pj_str_t reason = { "reason", 6 },
257 expires = { "expires", 7 },
258 retry_after = { "retry-after", 11 };
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000259 const pjsip_parser_const_t *pc = pjsip_parser_const();
260
261 pj_scan_get(ctx->scanner, &pc->pjsip_TOKEN_SPEC, &hdr->sub_state);
Benny Prijono834aee32006-02-19 01:38:06 +0000262
263 while (*ctx->scanner->curptr == ';') {
264 pj_str_t pname, pvalue;
265
266 pj_scan_get_char(ctx->scanner);
267 pjsip_parse_param_imp(ctx->scanner, ctx->pool, &pname, &pvalue, 0);
268
269 if (pj_stricmp(&pname, &reason) == 0) {
270 hdr->reason_param = pvalue;
271
272 } else if (pj_stricmp(&pname, &expires) == 0) {
273 hdr->expires_param = pj_strtoul(&pvalue);
274
275 } else if (pj_stricmp(&pname, &retry_after) == 0) {
276 hdr->retry_after = pj_strtoul(&pvalue);
277
278 } else {
Benny Prijono9d4469d2007-05-02 05:14:29 +0000279 pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
Benny Prijono834aee32006-02-19 01:38:06 +0000280 param->name = pname;
281 param->value = pvalue;
282 pj_list_push_back(&hdr->other_param, param);
283 }
284 }
285
286 pjsip_parse_end_hdr_imp( ctx->scanner );
287 return (pjsip_hdr*)hdr;
288}
289
290/*
291 * Register header parsers.
292 */
293PJ_DEF(void) pjsip_evsub_init_parser(void)
294{
295 pjsip_register_hdr_parser( "Event", NULL,
296 &parse_hdr_event);
297
298 pjsip_register_hdr_parser( "Subscription-State", NULL,
299 &parse_hdr_sub_state);
300}
301