blob: def46b5abe364fb2bb7727b848b8ab73b0281a0a [file] [log] [blame]
Benny Prijono0ca04b62005-12-30 23:50:15 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2006 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
20#include "test.h"
21#include <pjsip_core.h>
22#include <pjlib.h>
23
24#define HFIND(msg,h,H) ((pjsip_##h##_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_##H, NULL))
25
Benny Prijono85598d92006-01-07 18:44:25 +000026#define THIS_FILE "txdata_test.c"
27
28
Benny Prijono0ca04b62005-12-30 23:50:15 +000029/*
30 * This tests various core message creation functions.
31 */
Benny Prijono0c2bc612006-01-10 13:31:40 +000032static int core_txdata_test(void)
Benny Prijono0ca04b62005-12-30 23:50:15 +000033{
34 pj_status_t status;
35 pj_str_t target, from, to, contact, body;
36 pjsip_rx_data dummy_rdata;
37 pjsip_tx_data *invite, *invite2, *cancel, *response, *ack;
38
Benny Prijono0c2bc612006-01-10 13:31:40 +000039 PJ_LOG(3,(THIS_FILE, " core transmit data test"));
40
Benny Prijono0ca04b62005-12-30 23:50:15 +000041 /* Create INVITE request. */
42 target = pj_str("tel:+1");
43 from = pj_str("tel:+0");
44 to = pj_str("tel:+1");
45 contact = pj_str("Bob <sip:+0@example.com;user=phone>");
46 body = pj_str("Hello world!");
47
48 status = pjsip_endpt_create_request( endpt, &pjsip_invite_method, &target,
49 &from, &to, &contact, NULL, 10, &body,
50 &invite);
51 if (status != PJ_SUCCESS) {
52 app_perror(" error: unable to create request", status);
53 return -10;
54 }
55
56 /* Buffer must be invalid. */
57 if (pjsip_tx_data_is_valid(invite) != 0) {
Benny Prijono85598d92006-01-07 18:44:25 +000058 PJ_LOG(3,(THIS_FILE, " error: buffer must be invalid"));
Benny Prijono0ca04b62005-12-30 23:50:15 +000059 return -14;
60 }
61 /* Reference counter must be set to 1. */
62 if (pj_atomic_get(invite->ref_cnt) != 1) {
Benny Prijono85598d92006-01-07 18:44:25 +000063 PJ_LOG(3,(THIS_FILE, " error: invalid reference counter"));
Benny Prijono0ca04b62005-12-30 23:50:15 +000064 return -15;
65 }
66 /* Check message type. */
67 if (invite->msg->type != PJSIP_REQUEST_MSG)
68 return -16;
69 /* Check method. */
70 if (invite->msg->line.req.method.id != PJSIP_INVITE_METHOD)
71 return -17;
72
73 /* Check that mandatory headers are present. */
74 if (HFIND(invite->msg, from, FROM) == 0)
75 return -20;
76 if (HFIND(invite->msg, to, TO) == 0)
77 return -21;
78 if (HFIND(invite->msg, contact, CONTACT) == 0)
79 return -22;
80 if (HFIND(invite->msg, cid, CALL_ID) == 0)
81 return -23;
82 if (HFIND(invite->msg, cseq, CSEQ) == 0)
83 return -24;
84 do {
85 pjsip_via_hdr *via = HFIND(invite->msg, via, VIA);
86 if (via == NULL)
87 return -25;
88 /* Branch param must be empty. */
89 if (via->branch_param.slen != 0)
90 return -26;
91 } while (0);
92 if (invite->msg->body == NULL)
93 return -28;
94
95 /* Create another INVITE request from first request. */
96 status = pjsip_endpt_create_request_from_hdr( endpt, &pjsip_invite_method,
97 invite->msg->line.req.uri,
98 HFIND(invite->msg,from,FROM),
99 HFIND(invite->msg,to,TO),
100 HFIND(invite->msg,contact,CONTACT),
101 HFIND(invite->msg,cid,CALL_ID),
102 10, &body, &invite2);
103 if (status != PJ_SUCCESS) {
104 app_perror(" error: create second request failed", status);
105 return -30;
106 }
107
108 /* Buffer must be invalid. */
109 if (pjsip_tx_data_is_valid(invite2) != 0) {
Benny Prijono85598d92006-01-07 18:44:25 +0000110 PJ_LOG(3,(THIS_FILE, " error: buffer must be invalid"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000111 return -34;
112 }
113 /* Reference counter must be set to 1. */
114 if (pj_atomic_get(invite2->ref_cnt) != 1) {
Benny Prijono85598d92006-01-07 18:44:25 +0000115 PJ_LOG(3,(THIS_FILE, " error: invalid reference counter"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000116 return -35;
117 }
118 /* Check message type. */
119 if (invite2->msg->type != PJSIP_REQUEST_MSG)
120 return -36;
121 /* Check method. */
122 if (invite2->msg->line.req.method.id != PJSIP_INVITE_METHOD)
123 return -37;
124
125 /* Check that mandatory headers are again present. */
126 if (HFIND(invite2->msg, from, FROM) == 0)
127 return -40;
128 if (HFIND(invite2->msg, to, TO) == 0)
129 return -41;
130 if (HFIND(invite2->msg, contact, CONTACT) == 0)
131 return -42;
132 if (HFIND(invite2->msg, cid, CALL_ID) == 0)
133 return -43;
134 if (HFIND(invite2->msg, cseq, CSEQ) == 0)
135 return -44;
136 if (HFIND(invite2->msg, via, VIA) == 0)
137 return -45;
138 /*
139 if (HFIND(invite2->msg, ctype, CONTENT_TYPE) == 0)
140 return -46;
141 if (HFIND(invite2->msg, clen, CONTENT_LENGTH) == 0)
142 return -47;
143 */
144 if (invite2->msg->body == NULL)
145 return -48;
146
147 /* Done checking invite2. We can delete this. */
148 if (pjsip_tx_data_dec_ref(invite2) != PJSIP_EBUFDESTROYED) {
Benny Prijono85598d92006-01-07 18:44:25 +0000149 PJ_LOG(3,(THIS_FILE, " error: request buffer not destroyed!"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000150 return -49;
151 }
152
153 /* Initialize dummy rdata (to simulate receiving a request)
154 * We should never do this in real application, as there are many
155 * many more fields need to be initialized!!
156 */
157 dummy_rdata.msg_info.call_id = (HFIND(invite->msg, cid, CALL_ID))->id;
158 dummy_rdata.msg_info.clen = NULL;
159 dummy_rdata.msg_info.cseq = HFIND(invite->msg, cseq, CSEQ);
160 dummy_rdata.msg_info.ctype = NULL;
161 dummy_rdata.msg_info.from = HFIND(invite->msg, from, FROM);
162 dummy_rdata.msg_info.max_fwd = NULL;
163 dummy_rdata.msg_info.msg = invite->msg;
164 dummy_rdata.msg_info.record_route = NULL;
165 dummy_rdata.msg_info.require = NULL;
166 dummy_rdata.msg_info.route = NULL;
167 dummy_rdata.msg_info.to = HFIND(invite->msg, to, TO);
168 dummy_rdata.msg_info.via = HFIND(invite->msg, via, VIA);
169
170 /* Create a response message for the request. */
171 status = pjsip_endpt_create_response( endpt, &dummy_rdata, 301, NULL,
172 &response);
173 if (status != PJ_SUCCESS) {
174 app_perror(" error: unable to create response", status);
175 return -50;
176 }
177
178 /* Buffer must be invalid. */
179 if (pjsip_tx_data_is_valid(response) != 0) {
Benny Prijono85598d92006-01-07 18:44:25 +0000180 PJ_LOG(3,(THIS_FILE, " error: buffer must be invalid"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000181 return -54;
182 }
183 /* Check reference counter. */
184 if (pj_atomic_get(response->ref_cnt) != 1) {
Benny Prijono85598d92006-01-07 18:44:25 +0000185 PJ_LOG(3,(THIS_FILE, " error: invalid ref count in response"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000186 return -55;
187 }
188 /* Check message type. */
189 if (response->msg->type != PJSIP_RESPONSE_MSG)
190 return -56;
191 /* Check correct status is set. */
192 if (response->msg->line.status.code != 301)
193 return -57;
194
195 /* Check that mandatory headers are again present. */
196 if (HFIND(response->msg, from, FROM) == 0)
197 return -60;
198 if (HFIND(response->msg, to, TO) == 0)
199 return -61;
200 /*
201 if (HFIND(response->msg, contact, CONTACT) == 0)
202 return -62;
203 */
204 if (HFIND(response->msg, cid, CALL_ID) == 0)
205 return -63;
206 if (HFIND(response->msg, cseq, CSEQ) == 0)
207 return -64;
208 if (HFIND(response->msg, via, VIA) == 0)
209 return -65;
210
211 /* This response message will be used later when creating ACK */
212
213 /* Create CANCEL request for the original request. */
214 status = pjsip_endpt_create_cancel( endpt, invite, &cancel);
215 if (status != PJ_SUCCESS) {
216 app_perror(" error: unable to create CANCEL request", status);
217 return -80;
218 }
219
220 /* Buffer must be invalid. */
221 if (pjsip_tx_data_is_valid(cancel) != 0) {
Benny Prijono85598d92006-01-07 18:44:25 +0000222 PJ_LOG(3,(THIS_FILE, " error: buffer must be invalid"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000223 return -84;
224 }
225 /* Check reference counter. */
226 if (pj_atomic_get(cancel->ref_cnt) != 1) {
Benny Prijono85598d92006-01-07 18:44:25 +0000227 PJ_LOG(3,(THIS_FILE, " error: invalid ref count in CANCEL request"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000228 return -85;
229 }
230 /* Check message type. */
231 if (cancel->msg->type != PJSIP_REQUEST_MSG)
232 return -86;
233 /* Check method. */
234 if (cancel->msg->line.req.method.id != PJSIP_CANCEL_METHOD)
235 return -87;
236
237 /* Check that mandatory headers are again present. */
238 if (HFIND(cancel->msg, from, FROM) == 0)
239 return -90;
240 if (HFIND(cancel->msg, to, TO) == 0)
241 return -91;
242 /*
243 if (HFIND(cancel->msg, contact, CONTACT) == 0)
244 return -92;
245 */
246 if (HFIND(cancel->msg, cid, CALL_ID) == 0)
247 return -93;
248 if (HFIND(cancel->msg, cseq, CSEQ) == 0)
249 return -94;
250 if (HFIND(cancel->msg, via, VIA) == 0)
251 return -95;
252
253 /* Done checking CANCEL request. */
254 if (pjsip_tx_data_dec_ref(cancel) != PJSIP_EBUFDESTROYED) {
Benny Prijono85598d92006-01-07 18:44:25 +0000255 PJ_LOG(3,(THIS_FILE, " error: response buffer not destroyed!"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000256 return -99;
257 }
258
259 /* Modify dummy_rdata to simulate receiving response. */
260 pj_memset(&dummy_rdata, 0, sizeof(dummy_rdata));
261 dummy_rdata.msg_info.msg = response->msg;
262 dummy_rdata.msg_info.to = HFIND(response->msg, to, TO);
263
264 /* Create ACK request */
265 status = pjsip_endpt_create_ack( endpt, invite, &dummy_rdata, &ack );
266 if (status != PJ_SUCCESS) {
Benny Prijono85598d92006-01-07 18:44:25 +0000267 PJ_LOG(3,(THIS_FILE, " error: unable to create ACK"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000268 return -100;
269 }
270 /* Buffer must be invalid. */
271 if (pjsip_tx_data_is_valid(ack) != 0) {
Benny Prijono85598d92006-01-07 18:44:25 +0000272 PJ_LOG(3,(THIS_FILE, " error: buffer must be invalid"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000273 return -104;
274 }
275 /* Check reference counter. */
276 if (pj_atomic_get(ack->ref_cnt) != 1) {
Benny Prijono85598d92006-01-07 18:44:25 +0000277 PJ_LOG(3,(THIS_FILE, " error: invalid ref count in ACK request"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000278 return -105;
279 }
280 /* Check message type. */
281 if (ack->msg->type != PJSIP_REQUEST_MSG)
282 return -106;
283 /* Check method. */
284 if (ack->msg->line.req.method.id != PJSIP_ACK_METHOD)
285 return -107;
286 /* Check Request-URI is present. */
287 if (ack->msg->line.req.uri == NULL)
288 return -108;
289
290 /* Check that mandatory headers are again present. */
291 if (HFIND(ack->msg, from, FROM) == 0)
292 return -110;
293 if (HFIND(ack->msg, to, TO) == 0)
294 return -111;
295 if (HFIND(ack->msg, cid, CALL_ID) == 0)
296 return -112;
297 if (HFIND(ack->msg, cseq, CSEQ) == 0)
298 return -113;
299 if (HFIND(ack->msg, via, VIA) == 0)
300 return -114;
301 if (ack->msg->body != NULL)
302 return -115;
303
304 /* Done checking invite message. */
305 if (pjsip_tx_data_dec_ref(invite) != PJSIP_EBUFDESTROYED) {
Benny Prijono85598d92006-01-07 18:44:25 +0000306 PJ_LOG(3,(THIS_FILE, " error: response buffer not destroyed!"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000307 return -120;
308 }
309
310 /* Done checking response message. */
311 if (pjsip_tx_data_dec_ref(response) != PJSIP_EBUFDESTROYED) {
Benny Prijono85598d92006-01-07 18:44:25 +0000312 PJ_LOG(3,(THIS_FILE, " error: response buffer not destroyed!"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000313 return -130;
314 }
315
316 /* Done checking ack message. */
317 if (pjsip_tx_data_dec_ref(ack) != PJSIP_EBUFDESTROYED) {
Benny Prijono85598d92006-01-07 18:44:25 +0000318 PJ_LOG(3,(THIS_FILE, " error: response buffer not destroyed!"));
Benny Prijono0ca04b62005-12-30 23:50:15 +0000319 return -140;
320 }
321
322 /* Done. */
323 return 0;
324}
325
Benny Prijono0c2bc612006-01-10 13:31:40 +0000326/* This tests the request creating functions against the following
327 * requirements:
328 * - header params in URI creates header in the request.
329 * - method and headers params are correctly shown or hidden in
330 * request URI, From, To, and Contact header.
331 */
332static int txdata_test_uri_params(void)
333{
334 char msgbuf[512];
335 pj_str_t target = pj_str("sip:alice@wonderland:5061;x-param=param%201"
336 "?X-Hdr-1=Header%201"
337 "&X-Empty-Hdr=");
338 pj_str_t pname = pj_str("x-param");
339 pj_str_t hname = pj_str("X-Hdr-1");
340 pj_str_t hemptyname = pj_str("X-Empty-Hdr");
341 pjsip_from_hdr *from_hdr;
342 pjsip_to_hdr *to_hdr;
343 pjsip_contact_hdr *contact_hdr;
344 pjsip_generic_string_hdr *hdr;
345 pjsip_tx_data *tdata;
346 pjsip_sip_uri *uri;
347 pjsip_param *param;
348 pjsip_msg *msg;
349 int len;
350 pj_status_t status;
351
352 PJ_LOG(3,(THIS_FILE, " header param in URI to create request"));
353
354 /* Create request with header param in target URI. */
355 status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, &target,
356 &target, &target, &target, NULL, -1,
357 NULL, &tdata);
358 if (status != 0) {
359 app_perror(" error: Unable to create request", status);
360 return -200;
361 }
362
363 /* Print and parse the request.
364 * We'll check that header params are not present in
365 */
366 len = pjsip_msg_print(tdata->msg, msgbuf, sizeof(msgbuf));
367 if (len < 1) {
368 PJ_LOG(3,(THIS_FILE, " error: printing message"));
369 pjsip_tx_data_dec_ref(tdata);
370 return -250;
371 }
372 msgbuf[len] = '\0';
373
374 PJ_LOG(5,(THIS_FILE, "%d bytes request created:--begin-msg--\n"
375 "%s\n"
376 "--end-msg--", len, msgbuf));
377
378 /* Now parse the message. */
379 msg = pjsip_parse_msg( tdata->pool, msgbuf, len, NULL);
380 if (msg == NULL) {
381 app_perror(" error: parsing message message", status);
382 pjsip_tx_data_dec_ref(tdata);
383 return -250;
384 }
385
386 /* Check the existence of port, other_param, and header param.
387 * Port is now allowed in To and From header.
388 */
389 /* Port in request URI. */
390 uri = (pjsip_sip_uri*) pjsip_uri_get_uri(msg->line.req.uri);
391 if (uri->port != 5061) {
392 PJ_LOG(3,(THIS_FILE, " error: port not present in request URI"));
393 pjsip_tx_data_dec_ref(tdata);
394 return -260;
395 }
396 /* other_param in request_uri */
397 param = pjsip_param_find(&uri->other_param, &pname);
398 if (param == NULL || pj_strcmp2(&param->value, "param 1") != 0) {
399 PJ_LOG(3,(THIS_FILE, " error: x-param not present in request URI"));
400 pjsip_tx_data_dec_ref(tdata);
401 return -261;
402 }
403 /* header param in request uri. */
404 if (!pj_list_empty(&uri->header_param)) {
405 PJ_LOG(3,(THIS_FILE, " error: hparam in request URI"));
406 pjsip_tx_data_dec_ref(tdata);
407 return -262;
408 }
409
410 /* Port in From header. */
411 from_hdr = (pjsip_from_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_FROM, NULL);
412 uri = (pjsip_sip_uri*) pjsip_uri_get_uri(from_hdr->uri);
413 if (uri->port != 0) {
414 PJ_LOG(3,(THIS_FILE, " error: port most not exist in From header"));
415 pjsip_tx_data_dec_ref(tdata);
416 return -270;
417 }
418 /* other_param in From header */
419 param = pjsip_param_find(&uri->other_param, &pname);
420 if (param == NULL || pj_strcmp2(&param->value, "param 1") != 0) {
421 PJ_LOG(3,(THIS_FILE, " error: x-param not present in From header"));
422 pjsip_tx_data_dec_ref(tdata);
423 return -271;
424 }
425 /* header param in From header. */
426 if (!pj_list_empty(&uri->header_param)) {
427 PJ_LOG(3,(THIS_FILE, " error: hparam in From header"));
428 pjsip_tx_data_dec_ref(tdata);
429 return -272;
430 }
431
432
433 /* Port in To header. */
434 to_hdr = (pjsip_to_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_TO, NULL);
435 uri = (pjsip_sip_uri*) pjsip_uri_get_uri(to_hdr->uri);
436 if (uri->port != 0) {
437 PJ_LOG(3,(THIS_FILE, " error: port most not exist in To header"));
438 pjsip_tx_data_dec_ref(tdata);
439 return -280;
440 }
441 /* other_param in To header */
442 param = pjsip_param_find(&uri->other_param, &pname);
443 if (param == NULL || pj_strcmp2(&param->value, "param 1") != 0) {
444 PJ_LOG(3,(THIS_FILE, " error: x-param not present in To header"));
445 pjsip_tx_data_dec_ref(tdata);
446 return -281;
447 }
448 /* header param in From header. */
449 if (!pj_list_empty(&uri->header_param)) {
450 PJ_LOG(3,(THIS_FILE, " error: hparam in To header"));
451 pjsip_tx_data_dec_ref(tdata);
452 return -282;
453 }
454
455
456
457 /* Port in Contact header. */
458 contact_hdr = (pjsip_contact_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, NULL);
459 uri = (pjsip_sip_uri*) pjsip_uri_get_uri(contact_hdr->uri);
460 if (uri->port != 5061) {
461 PJ_LOG(3,(THIS_FILE, " error: port not present in Contact header"));
462 pjsip_tx_data_dec_ref(tdata);
463 return -290;
464 }
465 /* other_param in Contact header */
466 param = pjsip_param_find(&uri->other_param, &pname);
467 if (param == NULL || pj_strcmp2(&param->value, "param 1") != 0) {
468 PJ_LOG(3,(THIS_FILE, " error: x-param not present in Contact header"));
469 pjsip_tx_data_dec_ref(tdata);
470 return -291;
471 }
472 /* header param in Contact header. */
473 if (pj_list_empty(&uri->header_param)) {
474 PJ_LOG(3,(THIS_FILE, " error: hparam is missing in Contact header"));
475 pjsip_tx_data_dec_ref(tdata);
476 return -292;
477 }
478 /* Check for X-Hdr-1 */
479 param = pjsip_param_find(&uri->header_param, &hname);
480 if (param == NULL || pj_strcmp2(&param->value, "Header 1")!=0) {
481 PJ_LOG(3,(THIS_FILE, " error: hparam is missing in Contact header"));
482 pjsip_tx_data_dec_ref(tdata);
483 return -293;
484 }
485 /* Check for X-Empty-Hdr */
486 param = pjsip_param_find(&uri->header_param, &hemptyname);
487 if (param == NULL || pj_strcmp2(&param->value, "")!=0) {
488 PJ_LOG(3,(THIS_FILE, " error: hparam is missing in Contact header"));
489 pjsip_tx_data_dec_ref(tdata);
490 return -294;
491 }
492
493
494 /* Check that headers are present in the request. */
495 hdr = (pjsip_generic_string_hdr*)
496 pjsip_msg_find_hdr_by_name(msg, &hname, NULL);
497 if (hdr == NULL || pj_strcmp2(&hdr->hvalue, "Header 1")!=0) {
498 PJ_LOG(3,(THIS_FILE, " error: header X-Hdr-1 not created"));
499 pjsip_tx_data_dec_ref(tdata);
500 return -300;
501 }
502
503 hdr = (pjsip_generic_string_hdr*)
504 pjsip_msg_find_hdr_by_name(msg, &hemptyname, NULL);
505 if (hdr == NULL || pj_strcmp2(&param->value, "")!=0) {
506 PJ_LOG(3,(THIS_FILE, " error: header X-Empty-Hdr not created"));
507 pjsip_tx_data_dec_ref(tdata);
508 return -330;
509 }
510
511 pjsip_tx_data_dec_ref(tdata);
512 return 0;
513}
514
515int txdata_test(void)
516{
517 int status;
518
519 status = core_txdata_test();
520 if (status != 0)
521 return status;
522
523
524 status = txdata_test_uri_params();
525 if (status != 0)
526 return status;
527
528 return 0;
529}