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