~ubuntu-branches/ubuntu/maverick/sflphone/maverick

« back to all changes in this revision

Viewing changes to sflphone-common/libs/pjproject/pjsip/src/test/txdata_test.c

  • Committer: Bazaar Package Importer
  • Author(s): Francois Marier
  • Date: 2010-06-03 15:59:46 UTC
  • Revision ID: james.westby@ubuntu.com-20100603155946-ybe8d8o8zx8lp0m8
Tags: upstream-0.9.8.3
ImportĀ upstreamĀ versionĀ 0.9.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: txdata_test.c 2883 2009-08-15 11:00:26Z bennylp $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2009 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
 *  Additional permission under GNU GPL version 3 section 7:
 
21
 *
 
22
 *  If you modify this program, or any covered work, by linking or
 
23
 *  combining it with the OpenSSL project's OpenSSL library (or a
 
24
 *  modified version of that library), containing parts covered by the
 
25
 *  terms of the OpenSSL or SSLeay licenses, Teluu Inc. (http://www.teluu.com)
 
26
 *  grants you additional permission to convey the resulting work.
 
27
 *  Corresponding Source for a non-source form of such a combination
 
28
 *  shall include the source code for the parts of OpenSSL used as well
 
29
 *  as that of the covered work.
 
30
 */
 
31
 
 
32
#include "test.h"
 
33
#include <pjsip.h>
 
34
#include <pjlib.h>
 
35
 
 
36
 
 
37
#define THIS_FILE   "txdata_test.c"
 
38
 
 
39
 
 
40
#define HFIND(msg,h,H) ((pjsip_##h##_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_##H, NULL))
 
41
 
 
42
#if defined(PJ_DEBUG) && PJ_DEBUG!=0
 
43
#   define LOOP     10000
 
44
#else
 
45
#   define LOOP     100000
 
46
#endif
 
47
 
 
48
 
 
49
/*
 
50
 * This tests various core message creation functions. 
 
51
 */
 
52
static int core_txdata_test(void)
 
53
{
 
54
    pj_status_t status;
 
55
    pj_str_t target, from, to, contact, body;
 
56
    pjsip_rx_data dummy_rdata;
 
57
    pjsip_tx_data *invite, *invite2, *cancel, *response, *ack;
 
58
 
 
59
    PJ_LOG(3,(THIS_FILE, "   core transmit data test"));
 
60
 
 
61
    /* Create INVITE request. */
 
62
    target = pj_str("tel:+1");
 
63
    from = pj_str("tel:+0");
 
64
    to = pj_str("tel:+1");
 
65
    contact = pj_str("Bob <sip:+0@example.com;user=phone>");
 
66
    body = pj_str("Hello world!");
 
67
 
 
68
    status = pjsip_endpt_create_request( endpt, &pjsip_invite_method, &target,
 
69
                                         &from, &to, &contact, NULL, 10, &body,
 
70
                                         &invite);
 
71
    if (status != PJ_SUCCESS) {
 
72
        app_perror("   error: unable to create request", status);
 
73
        return -10;
 
74
    }
 
75
 
 
76
    /* Buffer must be invalid. */
 
77
    if (pjsip_tx_data_is_valid(invite) != 0) {
 
78
        PJ_LOG(3,(THIS_FILE, "   error: buffer must be invalid"));
 
79
        return -14;
 
80
    }
 
81
    /* Reference counter must be set to 1. */
 
82
    if (pj_atomic_get(invite->ref_cnt) != 1) {
 
83
        PJ_LOG(3,(THIS_FILE, "   error: invalid reference counter"));
 
84
        return -15;
 
85
    }
 
86
    /* Check message type. */
 
87
    if (invite->msg->type != PJSIP_REQUEST_MSG)
 
88
        return -16;
 
89
    /* Check method. */
 
90
    if (invite->msg->line.req.method.id != PJSIP_INVITE_METHOD)
 
91
        return -17;
 
92
 
 
93
    /* Check that mandatory headers are present. */
 
94
    if (HFIND(invite->msg, from, FROM) == 0)
 
95
        return -20;
 
96
    if (HFIND(invite->msg, to, TO) == 0)
 
97
        return -21;
 
98
    if (HFIND(invite->msg, contact, CONTACT) == 0)
 
99
        return -22;
 
100
    if (HFIND(invite->msg, cid, CALL_ID) == 0)
 
101
        return -23;
 
102
    if (HFIND(invite->msg, cseq, CSEQ) == 0)
 
103
        return -24;
 
104
    do {
 
105
        pjsip_via_hdr *via = HFIND(invite->msg, via, VIA);
 
106
        if (via == NULL)
 
107
            return -25;
 
108
        /* Branch param must be empty. */
 
109
        if (via->branch_param.slen != 0)
 
110
            return -26;
 
111
    } while (0);
 
112
    if (invite->msg->body == NULL)
 
113
        return -28;
 
114
 
 
115
    /* Create another INVITE request from first request. */
 
116
    status = pjsip_endpt_create_request_from_hdr( endpt, &pjsip_invite_method,
 
117
                                                  invite->msg->line.req.uri,
 
118
                                                  HFIND(invite->msg,from,FROM),
 
119
                                                  HFIND(invite->msg,to,TO),
 
120
                                                  HFIND(invite->msg,contact,CONTACT),
 
121
                                                  HFIND(invite->msg,cid,CALL_ID),
 
122
                                                  10, &body, &invite2);
 
123
    if (status != PJ_SUCCESS) {
 
124
        app_perror("   error: create second request failed", status);
 
125
        return -30;
 
126
    }
 
127
    
 
128
    /* Buffer must be invalid. */
 
129
    if (pjsip_tx_data_is_valid(invite2) != 0) {
 
130
        PJ_LOG(3,(THIS_FILE, "   error: buffer must be invalid"));
 
131
        return -34;
 
132
    }
 
133
    /* Reference counter must be set to 1. */
 
134
    if (pj_atomic_get(invite2->ref_cnt) != 1) {
 
135
        PJ_LOG(3,(THIS_FILE, "   error: invalid reference counter"));
 
136
        return -35;
 
137
    }
 
138
    /* Check message type. */
 
139
    if (invite2->msg->type != PJSIP_REQUEST_MSG)
 
140
        return -36;
 
141
    /* Check method. */
 
142
    if (invite2->msg->line.req.method.id != PJSIP_INVITE_METHOD)
 
143
        return -37;
 
144
 
 
145
    /* Check that mandatory headers are again present. */
 
146
    if (HFIND(invite2->msg, from, FROM) == 0)
 
147
        return -40;
 
148
    if (HFIND(invite2->msg, to, TO) == 0)
 
149
        return -41;
 
150
    if (HFIND(invite2->msg, contact, CONTACT) == 0)
 
151
        return -42;
 
152
    if (HFIND(invite2->msg, cid, CALL_ID) == 0)
 
153
        return -43;
 
154
    if (HFIND(invite2->msg, cseq, CSEQ) == 0)
 
155
        return -44;
 
156
    if (HFIND(invite2->msg, via, VIA) == 0)
 
157
        return -45;
 
158
    /*
 
159
    if (HFIND(invite2->msg, ctype, CONTENT_TYPE) == 0)
 
160
        return -46;
 
161
    if (HFIND(invite2->msg, clen, CONTENT_LENGTH) == 0)
 
162
        return -47;
 
163
    */
 
164
    if (invite2->msg->body == NULL)
 
165
        return -48;
 
166
 
 
167
    /* Done checking invite2. We can delete this. */
 
168
    if (pjsip_tx_data_dec_ref(invite2) != PJSIP_EBUFDESTROYED) {
 
169
        PJ_LOG(3,(THIS_FILE, "   error: request buffer not destroyed!"));
 
170
        return -49;
 
171
    }
 
172
 
 
173
    /* Initialize dummy rdata (to simulate receiving a request) 
 
174
     * We should never do this in real application, as there are many
 
175
     * many more fields need to be initialized!!
 
176
     */
 
177
    dummy_rdata.msg_info.cid = HFIND(invite->msg, cid, CALL_ID);
 
178
    dummy_rdata.msg_info.clen = NULL;
 
179
    dummy_rdata.msg_info.cseq = HFIND(invite->msg, cseq, CSEQ);
 
180
    dummy_rdata.msg_info.ctype = NULL;
 
181
    dummy_rdata.msg_info.from = HFIND(invite->msg, from, FROM);
 
182
    dummy_rdata.msg_info.max_fwd = NULL;
 
183
    dummy_rdata.msg_info.msg = invite->msg;
 
184
    dummy_rdata.msg_info.record_route = NULL;
 
185
    dummy_rdata.msg_info.require = NULL;
 
186
    dummy_rdata.msg_info.route = NULL;
 
187
    dummy_rdata.msg_info.to = HFIND(invite->msg, to, TO);
 
188
    dummy_rdata.msg_info.via = HFIND(invite->msg, via, VIA);
 
189
 
 
190
    /* Create a response message for the request. */
 
191
    status = pjsip_endpt_create_response( endpt, &dummy_rdata, 301, NULL, 
 
192
                                          &response);
 
193
    if (status != PJ_SUCCESS) {
 
194
        app_perror("   error: unable to create response", status);
 
195
        return -50;
 
196
    }
 
197
    
 
198
    /* Buffer must be invalid. */
 
199
    if (pjsip_tx_data_is_valid(response) != 0) {
 
200
        PJ_LOG(3,(THIS_FILE, "   error: buffer must be invalid"));
 
201
        return -54;
 
202
    }
 
203
    /* Check reference counter. */
 
204
    if (pj_atomic_get(response->ref_cnt) != 1) {
 
205
        PJ_LOG(3,(THIS_FILE, "   error: invalid ref count in response"));
 
206
        return -55;
 
207
    }
 
208
    /* Check message type. */
 
209
    if (response->msg->type != PJSIP_RESPONSE_MSG)
 
210
        return -56;
 
211
    /* Check correct status is set. */
 
212
    if (response->msg->line.status.code != 301)
 
213
        return -57;
 
214
 
 
215
    /* Check that mandatory headers are again present. */
 
216
    if (HFIND(response->msg, from, FROM) == 0)
 
217
        return -60;
 
218
    if (HFIND(response->msg, to, TO) == 0)
 
219
        return -61;
 
220
    /*
 
221
    if (HFIND(response->msg, contact, CONTACT) == 0)
 
222
        return -62;
 
223
     */
 
224
    if (HFIND(response->msg, cid, CALL_ID) == 0)
 
225
        return -63;
 
226
    if (HFIND(response->msg, cseq, CSEQ) == 0)
 
227
        return -64;
 
228
    if (HFIND(response->msg, via, VIA) == 0)
 
229
        return -65;
 
230
 
 
231
    /* This response message will be used later when creating ACK */
 
232
 
 
233
    /* Create CANCEL request for the original request. */
 
234
    status = pjsip_endpt_create_cancel( endpt, invite, &cancel);
 
235
    if (status != PJ_SUCCESS) {
 
236
        app_perror("   error: unable to create CANCEL request", status);
 
237
        return -80;
 
238
    }
 
239
 
 
240
    /* Buffer must be invalid. */
 
241
    if (pjsip_tx_data_is_valid(cancel) != 0) {
 
242
        PJ_LOG(3,(THIS_FILE, "   error: buffer must be invalid"));
 
243
        return -84;
 
244
    }
 
245
    /* Check reference counter. */
 
246
    if (pj_atomic_get(cancel->ref_cnt) != 1) {
 
247
        PJ_LOG(3,(THIS_FILE, "   error: invalid ref count in CANCEL request"));
 
248
        return -85;
 
249
    }
 
250
    /* Check message type. */
 
251
    if (cancel->msg->type != PJSIP_REQUEST_MSG)
 
252
        return -86;
 
253
    /* Check method. */
 
254
    if (cancel->msg->line.req.method.id != PJSIP_CANCEL_METHOD)
 
255
        return -87;
 
256
 
 
257
    /* Check that mandatory headers are again present. */
 
258
    if (HFIND(cancel->msg, from, FROM) == 0)
 
259
        return -90;
 
260
    if (HFIND(cancel->msg, to, TO) == 0)
 
261
        return -91;
 
262
    /*
 
263
    if (HFIND(cancel->msg, contact, CONTACT) == 0)
 
264
        return -92;
 
265
    */
 
266
    if (HFIND(cancel->msg, cid, CALL_ID) == 0)
 
267
        return -93;
 
268
    if (HFIND(cancel->msg, cseq, CSEQ) == 0)
 
269
        return -94;
 
270
    if (HFIND(cancel->msg, via, VIA) == 0)
 
271
        return -95;
 
272
 
 
273
    /* Done checking CANCEL request. */
 
274
    if (pjsip_tx_data_dec_ref(cancel) != PJSIP_EBUFDESTROYED) {
 
275
        PJ_LOG(3,(THIS_FILE, "   error: response buffer not destroyed!"));
 
276
        return -99;
 
277
    }
 
278
 
 
279
    /* Modify dummy_rdata to simulate receiving response. */
 
280
    pj_bzero(&dummy_rdata, sizeof(dummy_rdata));
 
281
    dummy_rdata.msg_info.msg = response->msg;
 
282
    dummy_rdata.msg_info.to = HFIND(response->msg, to, TO);
 
283
 
 
284
    /* Create ACK request */
 
285
    status = pjsip_endpt_create_ack( endpt, invite, &dummy_rdata, &ack );
 
286
    if (status != PJ_SUCCESS) {
 
287
        PJ_LOG(3,(THIS_FILE, "   error: unable to create ACK"));
 
288
        return -100;
 
289
    }
 
290
    /* Buffer must be invalid. */
 
291
    if (pjsip_tx_data_is_valid(ack) != 0) {
 
292
        PJ_LOG(3,(THIS_FILE, "   error: buffer must be invalid"));
 
293
        return -104;
 
294
    }
 
295
    /* Check reference counter. */
 
296
    if (pj_atomic_get(ack->ref_cnt) != 1) {
 
297
        PJ_LOG(3,(THIS_FILE, "   error: invalid ref count in ACK request"));
 
298
        return -105;
 
299
    }
 
300
    /* Check message type. */
 
301
    if (ack->msg->type != PJSIP_REQUEST_MSG)
 
302
        return -106;
 
303
    /* Check method. */
 
304
    if (ack->msg->line.req.method.id != PJSIP_ACK_METHOD)
 
305
        return -107;
 
306
    /* Check Request-URI is present. */
 
307
    if (ack->msg->line.req.uri == NULL)
 
308
        return -108;
 
309
 
 
310
    /* Check that mandatory headers are again present. */
 
311
    if (HFIND(ack->msg, from, FROM) == 0)
 
312
        return -110;
 
313
    if (HFIND(ack->msg, to, TO) == 0)
 
314
        return -111;
 
315
    if (HFIND(ack->msg, cid, CALL_ID) == 0)
 
316
        return -112;
 
317
    if (HFIND(ack->msg, cseq, CSEQ) == 0)
 
318
        return -113;
 
319
    if (HFIND(ack->msg, via, VIA) == 0)
 
320
        return -114;
 
321
    if (ack->msg->body != NULL)
 
322
        return -115;
 
323
 
 
324
    /* Done checking invite message. */
 
325
    if (pjsip_tx_data_dec_ref(invite) != PJSIP_EBUFDESTROYED) {
 
326
        PJ_LOG(3,(THIS_FILE, "   error: response buffer not destroyed!"));
 
327
        return -120;
 
328
    }
 
329
 
 
330
    /* Done checking response message. */
 
331
    if (pjsip_tx_data_dec_ref(response) != PJSIP_EBUFDESTROYED) {
 
332
        PJ_LOG(3,(THIS_FILE, "   error: response buffer not destroyed!"));
 
333
        return -130;
 
334
    }
 
335
 
 
336
    /* Done checking ack message. */
 
337
    if (pjsip_tx_data_dec_ref(ack) != PJSIP_EBUFDESTROYED) {
 
338
        PJ_LOG(3,(THIS_FILE, "   error: response buffer not destroyed!"));
 
339
        return -140;
 
340
    }
 
341
 
 
342
    /* Done. */
 
343
    return 0;
 
344
}
 
345
 
 
346
 
 
347
 
 
348
/* 
 
349
 * This test demonstrate the bug as reported in:
 
350
 *  http://bugzilla.pjproject.net/show_bug.cgi?id=49
 
351
 */
 
352
#if INCLUDE_GCC_TEST
 
353
static int gcc_test()
 
354
{
 
355
    char msgbuf[512];
 
356
    pj_str_t target = pj_str("sip:alice@wonderland:5061;x-param=param%201"
 
357
                             "?X-Hdr-1=Header%201"
 
358
                             "&X-Empty-Hdr=");
 
359
    pjsip_tx_data *tdata;
 
360
    pjsip_parser_err_report err_list;
 
361
    pjsip_msg *msg;
 
362
    int len;
 
363
    pj_status_t status;
 
364
 
 
365
    PJ_LOG(3,(THIS_FILE, "   header param in URI to create request"));
 
366
 
 
367
    /* Create request with header param in target URI. */
 
368
    status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, &target,
 
369
                                        &target, &target, &target, NULL, -1,
 
370
                                        NULL, &tdata);
 
371
    if (status != 0) {
 
372
        app_perror("   error: Unable to create request", status);
 
373
        return -200;
 
374
    }
 
375
 
 
376
    /* Print and parse the request.
 
377
     * We'll check that header params are not present in
 
378
     */
 
379
    len = pjsip_msg_print(tdata->msg, msgbuf, sizeof(msgbuf));
 
380
    if (len < 1) {
 
381
        PJ_LOG(3,(THIS_FILE, "   error: printing message"));
 
382
        pjsip_tx_data_dec_ref(tdata);
 
383
        return -250;
 
384
    }
 
385
    msgbuf[len] = '\0';
 
386
 
 
387
    PJ_LOG(5,(THIS_FILE, "%d bytes request created:--begin-msg--\n"
 
388
                         "%s\n"
 
389
                         "--end-msg--", len, msgbuf));
 
390
 
 
391
    /* Now parse the message. */
 
392
    pj_list_init(&err_list);
 
393
    msg = pjsip_parse_msg( tdata->pool, msgbuf, len, &err_list);
 
394
    if (msg == NULL) {
 
395
        pjsip_parser_err_report *e;
 
396
 
 
397
        PJ_LOG(3,(THIS_FILE, "   error: parsing message message"));
 
398
 
 
399
        e = err_list.next;
 
400
        while (e != &err_list) {
 
401
            PJ_LOG(3,(THIS_FILE, "     %s in line %d col %d hname=%.*s",
 
402
                                 pj_exception_id_name(e->except_code), 
 
403
                                 e->line, e->col+1,
 
404
                                 (int)e->hname.slen,
 
405
                                 e->hname.ptr));
 
406
            e = e->next;
 
407
        }
 
408
 
 
409
        pjsip_tx_data_dec_ref(tdata);
 
410
        return -255;
 
411
    }
 
412
 
 
413
    pjsip_tx_data_dec_ref(tdata);
 
414
    return 0;
 
415
}
 
416
#endif
 
417
 
 
418
 
 
419
/* This tests the request creating functions against the following
 
420
 * requirements:
 
421
 *  - header params in URI creates header in the request.
 
422
 *  - method and headers params are correctly shown or hidden in
 
423
 *    request URI, From, To, and Contact header.
 
424
 */
 
425
static int txdata_test_uri_params(void)
 
426
{
 
427
    char msgbuf[512];
 
428
    pj_str_t target = pj_str("sip:alice@wonderland:5061;x-param=param%201"
 
429
                             "?X-Hdr-1=Header%201"
 
430
                             "&X-Empty-Hdr=");
 
431
    pj_str_t contact;
 
432
    pj_str_t pname = pj_str("x-param");
 
433
    pj_str_t hname = pj_str("X-Hdr-1");
 
434
    pj_str_t hemptyname = pj_str("X-Empty-Hdr");
 
435
    pjsip_from_hdr *from_hdr;
 
436
    pjsip_to_hdr *to_hdr;
 
437
    pjsip_contact_hdr *contact_hdr;
 
438
    pjsip_generic_string_hdr *hdr;
 
439
    pjsip_tx_data *tdata;
 
440
    pjsip_sip_uri *uri;
 
441
    pjsip_param *param;
 
442
    pjsip_via_hdr *via;
 
443
    pjsip_parser_err_report err_list;
 
444
    pjsip_msg *msg;
 
445
    int len;
 
446
    pj_status_t status;
 
447
 
 
448
    PJ_LOG(3,(THIS_FILE, "   header param in URI to create request"));
 
449
 
 
450
    /* Due to #930, contact argument is now parsed as Contact header, so
 
451
     * must enclose it with <> to make it be parsed as URI.
 
452
     */
 
453
    pj_ansi_snprintf(msgbuf, sizeof(msgbuf), "<%.*s>",
 
454
                     (int)target.slen, target.ptr);
 
455
    contact.ptr = msgbuf;
 
456
    contact.slen = strlen(msgbuf);
 
457
 
 
458
    /* Create request with header param in target URI. */
 
459
    status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, &target,
 
460
                                        &target, &target, &contact, NULL, -1,
 
461
                                        NULL, &tdata);
 
462
    if (status != 0) {
 
463
        app_perror("   error: Unable to create request", status);
 
464
        return -200;
 
465
    }
 
466
 
 
467
    /* Fill up the Via header to prevent syntax error on parsing */
 
468
    via = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
 
469
    via->transport = pj_str("TCP");
 
470
    via->sent_by.host = pj_str("127.0.0.1");
 
471
 
 
472
    /* Print and parse the request.
 
473
     * We'll check that header params are not present in
 
474
     */
 
475
    len = pjsip_msg_print(tdata->msg, msgbuf, sizeof(msgbuf));
 
476
    if (len < 1) {
 
477
        PJ_LOG(3,(THIS_FILE, "   error: printing message"));
 
478
        pjsip_tx_data_dec_ref(tdata);
 
479
        return -250;
 
480
    }
 
481
    msgbuf[len] = '\0';
 
482
 
 
483
    PJ_LOG(5,(THIS_FILE, "%d bytes request created:--begin-msg--\n"
 
484
                         "%s\n"
 
485
                         "--end-msg--", len, msgbuf));
 
486
 
 
487
    /* Now parse the message. */
 
488
    pj_list_init(&err_list);
 
489
    msg = pjsip_parse_msg( tdata->pool, msgbuf, len, &err_list);
 
490
    if (msg == NULL) {
 
491
        pjsip_parser_err_report *e;
 
492
 
 
493
        PJ_LOG(3,(THIS_FILE, "   error: parsing message message"));
 
494
 
 
495
        e = err_list.next;
 
496
        while (e != &err_list) {
 
497
            PJ_LOG(3,(THIS_FILE, "     %s in line %d col %d hname=%.*s",
 
498
                                 pj_exception_id_name(e->except_code), 
 
499
                                 e->line, e->col+1,
 
500
                                 (int)e->hname.slen,
 
501
                                 e->hname.ptr));
 
502
            e = e->next;
 
503
        }
 
504
 
 
505
        pjsip_tx_data_dec_ref(tdata);
 
506
        return -256;
 
507
    }
 
508
 
 
509
    /* Check the existence of port, other_param, and header param.
 
510
     * Port is now allowed in To and From header.
 
511
     */
 
512
    /* Port in request URI. */
 
513
    uri = (pjsip_sip_uri*) pjsip_uri_get_uri(msg->line.req.uri);
 
514
    if (uri->port != 5061) {
 
515
        PJ_LOG(3,(THIS_FILE, "   error: port not present in request URI"));
 
516
        pjsip_tx_data_dec_ref(tdata);
 
517
        return -260;
 
518
    }
 
519
    /* other_param in request_uri */
 
520
    param = pjsip_param_find(&uri->other_param, &pname);
 
521
    if (param == NULL || pj_strcmp2(&param->value, "param 1") != 0) {
 
522
        PJ_LOG(3,(THIS_FILE, "   error: x-param not present in request URI"));
 
523
        pjsip_tx_data_dec_ref(tdata);
 
524
        return -261;
 
525
    }
 
526
    /* header param in request uri. */
 
527
    if (!pj_list_empty(&uri->header_param)) {
 
528
        PJ_LOG(3,(THIS_FILE, "   error: hparam in request URI"));
 
529
        pjsip_tx_data_dec_ref(tdata);
 
530
        return -262;
 
531
    }
 
532
 
 
533
    /* Port in From header. */
 
534
    from_hdr = (pjsip_from_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_FROM, NULL);
 
535
    uri = (pjsip_sip_uri*) pjsip_uri_get_uri(from_hdr->uri);
 
536
    if (uri->port != 0) {
 
537
        PJ_LOG(3,(THIS_FILE, "   error: port most not exist in From header"));
 
538
        pjsip_tx_data_dec_ref(tdata);
 
539
        return -270;
 
540
    }
 
541
    /* other_param in From header */
 
542
    param = pjsip_param_find(&uri->other_param, &pname);
 
543
    if (param == NULL || pj_strcmp2(&param->value, "param 1") != 0) {
 
544
        PJ_LOG(3,(THIS_FILE, "   error: x-param not present in From header"));
 
545
        pjsip_tx_data_dec_ref(tdata);
 
546
        return -271;
 
547
    }
 
548
    /* header param in From header. */
 
549
    if (!pj_list_empty(&uri->header_param)) {
 
550
        PJ_LOG(3,(THIS_FILE, "   error: hparam in From header"));
 
551
        pjsip_tx_data_dec_ref(tdata);
 
552
        return -272;
 
553
    }
 
554
 
 
555
 
 
556
    /* Port in To header. */
 
557
    to_hdr = (pjsip_to_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_TO, NULL);
 
558
    uri = (pjsip_sip_uri*) pjsip_uri_get_uri(to_hdr->uri);
 
559
    if (uri->port != 0) {
 
560
        PJ_LOG(3,(THIS_FILE, "   error: port most not exist in To header"));
 
561
        pjsip_tx_data_dec_ref(tdata);
 
562
        return -280;
 
563
    }
 
564
    /* other_param in To header */
 
565
    param = pjsip_param_find(&uri->other_param, &pname);
 
566
    if (param == NULL || pj_strcmp2(&param->value, "param 1") != 0) {
 
567
        PJ_LOG(3,(THIS_FILE, "   error: x-param not present in To header"));
 
568
        pjsip_tx_data_dec_ref(tdata);
 
569
        return -281;
 
570
    }
 
571
    /* header param in From header. */
 
572
    if (!pj_list_empty(&uri->header_param)) {
 
573
        PJ_LOG(3,(THIS_FILE, "   error: hparam in To header"));
 
574
        pjsip_tx_data_dec_ref(tdata);
 
575
        return -282;
 
576
    }
 
577
 
 
578
 
 
579
 
 
580
    /* Port in Contact header. */
 
581
    contact_hdr = (pjsip_contact_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, NULL);
 
582
    uri = (pjsip_sip_uri*) pjsip_uri_get_uri(contact_hdr->uri);
 
583
    if (uri->port != 5061) {
 
584
        PJ_LOG(3,(THIS_FILE, "   error: port not present in Contact header"));
 
585
        pjsip_tx_data_dec_ref(tdata);
 
586
        return -290;
 
587
    }
 
588
    /* other_param in Contact header */
 
589
    param = pjsip_param_find(&uri->other_param, &pname);
 
590
    if (param == NULL || pj_strcmp2(&param->value, "param 1") != 0) {
 
591
        PJ_LOG(3,(THIS_FILE, "   error: x-param not present in Contact header"));
 
592
        pjsip_tx_data_dec_ref(tdata);
 
593
        return -291;
 
594
    }
 
595
    /* header param in Contact header. */
 
596
    if (pj_list_empty(&uri->header_param)) {
 
597
        PJ_LOG(3,(THIS_FILE, "   error: hparam is missing in Contact header"));
 
598
        pjsip_tx_data_dec_ref(tdata);
 
599
        return -292;
 
600
    }
 
601
    /* Check for X-Hdr-1 */
 
602
    param = pjsip_param_find(&uri->header_param, &hname);
 
603
    if (param == NULL || pj_strcmp2(&param->value, "Header 1")!=0) {
 
604
        PJ_LOG(3,(THIS_FILE, "   error: hparam is missing in Contact header"));
 
605
        pjsip_tx_data_dec_ref(tdata);
 
606
        return -293;
 
607
    }
 
608
    /* Check for X-Empty-Hdr */
 
609
    param = pjsip_param_find(&uri->header_param, &hemptyname);
 
610
    if (param == NULL || pj_strcmp2(&param->value, "")!=0) {
 
611
        PJ_LOG(3,(THIS_FILE, "   error: hparam is missing in Contact header"));
 
612
        pjsip_tx_data_dec_ref(tdata);
 
613
        return -294;
 
614
    }
 
615
 
 
616
 
 
617
    /* Check that headers are present in the request. */
 
618
    hdr = (pjsip_generic_string_hdr*) 
 
619
        pjsip_msg_find_hdr_by_name(msg, &hname, NULL);
 
620
    if (hdr == NULL || pj_strcmp2(&hdr->hvalue, "Header 1")!=0) {
 
621
        PJ_LOG(3,(THIS_FILE, "   error: header X-Hdr-1 not created"));
 
622
        pjsip_tx_data_dec_ref(tdata);
 
623
        return -300;
 
624
    }
 
625
 
 
626
    hdr = (pjsip_generic_string_hdr*) 
 
627
        pjsip_msg_find_hdr_by_name(msg, &hemptyname, NULL);
 
628
    if (hdr == NULL || pj_strcmp2(&param->value, "")!=0) {
 
629
        PJ_LOG(3,(THIS_FILE, "   error: header X-Empty-Hdr not created"));
 
630
        pjsip_tx_data_dec_ref(tdata);
 
631
        return -330;
 
632
    }
 
633
 
 
634
    pjsip_tx_data_dec_ref(tdata);
 
635
    return 0;
 
636
}
 
637
 
 
638
 
 
639
/*
 
640
 * create request benchmark
 
641
 */
 
642
static int create_request_bench(pj_timestamp *p_elapsed)
 
643
{
 
644
    enum { COUNT = 100 };
 
645
    unsigned i, j;
 
646
    pjsip_tx_data *tdata[COUNT];
 
647
    pj_timestamp t1, t2, elapsed;
 
648
    pj_status_t status;
 
649
 
 
650
    pj_str_t str_target = pj_str("sip:someuser@someprovider.com");
 
651
    pj_str_t str_from = pj_str("\"Local User\" <sip:localuser@serviceprovider.com>");
 
652
    pj_str_t str_to = pj_str("\"Remote User\" <sip:remoteuser@serviceprovider.com>");
 
653
    pj_str_t str_contact = str_from;
 
654
 
 
655
    elapsed.u64 = 0;
 
656
 
 
657
    for (i=0; i<LOOP; i+=COUNT) {
 
658
        pj_bzero(tdata, sizeof(tdata));
 
659
 
 
660
        pj_get_timestamp(&t1);
 
661
 
 
662
        for (j=0; j<COUNT; ++j) {
 
663
            status = pjsip_endpt_create_request(endpt, &pjsip_invite_method,
 
664
                                                &str_target, &str_from, &str_to,
 
665
                                                &str_contact, NULL, -1, NULL,
 
666
                                                &tdata[j]);
 
667
            if (status != PJ_SUCCESS) {
 
668
                app_perror("    error: unable to create request", status);
 
669
                goto on_error;
 
670
            }
 
671
        }
 
672
 
 
673
        pj_get_timestamp(&t2);
 
674
        pj_sub_timestamp(&t2, &t1);
 
675
        pj_add_timestamp(&elapsed, &t2);
 
676
        
 
677
        for (j=0; j<COUNT; ++j)
 
678
            pjsip_tx_data_dec_ref(tdata[j]);
 
679
    }
 
680
 
 
681
    p_elapsed->u64 = elapsed.u64;
 
682
    return PJ_SUCCESS;
 
683
 
 
684
on_error:
 
685
    for (i=0; i<COUNT; ++i) {
 
686
        if (tdata[i])
 
687
            pjsip_tx_data_dec_ref(tdata[i]);
 
688
    }
 
689
    return -400;
 
690
}
 
691
 
 
692
 
 
693
 
 
694
/*
 
695
 * create response benchmark
 
696
 */
 
697
static int create_response_bench(pj_timestamp *p_elapsed)
 
698
{
 
699
    enum { COUNT = 100 };
 
700
    unsigned i, j;
 
701
    pjsip_via_hdr *via;
 
702
    pjsip_rx_data rdata;
 
703
    pjsip_tx_data *request;
 
704
    pjsip_tx_data *tdata[COUNT];
 
705
    pj_timestamp t1, t2, elapsed;
 
706
    pj_status_t status;
 
707
 
 
708
    /* Create the request first. */
 
709
    pj_str_t str_target = pj_str("sip:someuser@someprovider.com");
 
710
    pj_str_t str_from = pj_str("\"Local User\" <sip:localuser@serviceprovider.com>");
 
711
    pj_str_t str_to = pj_str("\"Remote User\" <sip:remoteuser@serviceprovider.com>");
 
712
    pj_str_t str_contact = str_from;
 
713
 
 
714
    status = pjsip_endpt_create_request(endpt, &pjsip_invite_method,
 
715
                                        &str_target, &str_from, &str_to,
 
716
                                        &str_contact, NULL, -1, NULL,
 
717
                                        &request);
 
718
    if (status != PJ_SUCCESS) {
 
719
        app_perror("    error: unable to create request", status);
 
720
        return status;
 
721
    }
 
722
 
 
723
    /* Create several Via headers */
 
724
    via = pjsip_via_hdr_create(request->pool);
 
725
    via->sent_by.host = pj_str("192.168.0.7");
 
726
    via->sent_by.port = 5061;
 
727
    via->transport = pj_str("udp");
 
728
    via->rport_param = 0;
 
729
    via->branch_param = pj_str("012345678901234567890123456789");
 
730
    via->recvd_param = pj_str("192.168.0.7");
 
731
    pjsip_msg_insert_first_hdr(request->msg, (pjsip_hdr*) pjsip_hdr_clone(request->pool, via));
 
732
    pjsip_msg_insert_first_hdr(request->msg, (pjsip_hdr*) pjsip_hdr_clone(request->pool, via));
 
733
    pjsip_msg_insert_first_hdr(request->msg, (pjsip_hdr*)via);
 
734
    
 
735
 
 
736
    /* Create "dummy" rdata from the tdata */
 
737
    pj_bzero(&rdata, sizeof(pjsip_rx_data));
 
738
    rdata.tp_info.pool = request->pool;
 
739
    rdata.msg_info.msg = request->msg;
 
740
    rdata.msg_info.from = (pjsip_from_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL);
 
741
    rdata.msg_info.to = (pjsip_to_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_TO, NULL);
 
742
    rdata.msg_info.cseq = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_CSEQ, NULL);
 
743
    rdata.msg_info.cid = (pjsip_cid_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL);
 
744
    rdata.msg_info.via = via;
 
745
 
 
746
    /*
 
747
     * Now benchmark create_response
 
748
     */
 
749
    elapsed.u64 = 0;
 
750
 
 
751
    for (i=0; i<LOOP; i+=COUNT) {
 
752
        pj_bzero(tdata, sizeof(tdata));
 
753
 
 
754
        pj_get_timestamp(&t1);
 
755
 
 
756
        for (j=0; j<COUNT; ++j) {
 
757
            status = pjsip_endpt_create_response(endpt, &rdata, 200, NULL, &tdata[j]);
 
758
            if (status != PJ_SUCCESS) {
 
759
                app_perror("    error: unable to create request", status);
 
760
                goto on_error;
 
761
            }
 
762
        }
 
763
 
 
764
        pj_get_timestamp(&t2);
 
765
        pj_sub_timestamp(&t2, &t1);
 
766
        pj_add_timestamp(&elapsed, &t2);
 
767
        
 
768
        for (j=0; j<COUNT; ++j)
 
769
            pjsip_tx_data_dec_ref(tdata[j]);
 
770
    }
 
771
 
 
772
    p_elapsed->u64 = elapsed.u64;
 
773
    pjsip_tx_data_dec_ref(request);
 
774
    return PJ_SUCCESS;
 
775
 
 
776
on_error:
 
777
    for (i=0; i<COUNT; ++i) {
 
778
        if (tdata[i])
 
779
            pjsip_tx_data_dec_ref(tdata[i]);
 
780
    }
 
781
    return -400;
 
782
}
 
783
 
 
784
 
 
785
int txdata_test(void)
 
786
{
 
787
    enum { REPEAT = 4 };
 
788
    unsigned i, msgs;
 
789
    pj_timestamp usec[REPEAT], min, freq;
 
790
    int status;
 
791
 
 
792
    status = pj_get_timestamp_freq(&freq);
 
793
    if (status != PJ_SUCCESS)
 
794
        return status;
 
795
 
 
796
    status = core_txdata_test();
 
797
    if (status  != 0)
 
798
        return status;
 
799
 
 
800
#if INCLUDE_GCC_TEST
 
801
    status = gcc_test();
 
802
    if (status != 0)
 
803
        return status;
 
804
#endif
 
805
 
 
806
    status = txdata_test_uri_params();
 
807
    if (status != 0)
 
808
        return status;
 
809
 
 
810
 
 
811
    /*
 
812
     * Benchmark create_request()
 
813
     */
 
814
    PJ_LOG(3,(THIS_FILE, "   benchmarking request creation:"));
 
815
    for (i=0; i<REPEAT; ++i) {
 
816
        PJ_LOG(3,(THIS_FILE, "    test %d of %d..",
 
817
                  i+1, REPEAT));
 
818
        status = create_request_bench(&usec[i]);
 
819
        if (status != PJ_SUCCESS)
 
820
            return status;
 
821
    }
 
822
 
 
823
    min.u64 = PJ_UINT64(0xFFFFFFFFFFFFFFF);
 
824
    for (i=0; i<REPEAT; ++i) {
 
825
        if (usec[i].u64 < min.u64) min.u64 = usec[i].u64;
 
826
    }
 
827
 
 
828
    msgs = (unsigned)(freq.u64 * LOOP / min.u64);
 
829
 
 
830
    PJ_LOG(3,(THIS_FILE, "    Requests created at %d requests/sec", msgs));
 
831
 
 
832
    report_ival("create-request-per-sec", 
 
833
                msgs, "msg/sec",
 
834
                "Number of typical request messages that can be created "
 
835
                "per second with <tt>pjsip_endpt_create_request()</tt>");
 
836
 
 
837
 
 
838
    /*
 
839
     * Benchmark create_response()
 
840
     */
 
841
    PJ_LOG(3,(THIS_FILE, "   benchmarking response creation:"));
 
842
    for (i=0; i<REPEAT; ++i) {
 
843
        PJ_LOG(3,(THIS_FILE, "    test %d of %d..",
 
844
                  i+1, REPEAT));
 
845
        status = create_response_bench(&usec[i]);
 
846
        if (status != PJ_SUCCESS)
 
847
            return status;
 
848
    }
 
849
 
 
850
    min.u64 = PJ_UINT64(0xFFFFFFFFFFFFFFF);
 
851
    for (i=0; i<REPEAT; ++i) {
 
852
        if (usec[i].u64 < min.u64) min.u64 = usec[i].u64;
 
853
    }
 
854
 
 
855
    msgs = (unsigned)(freq.u64 * LOOP / min.u64);
 
856
 
 
857
    PJ_LOG(3,(THIS_FILE, "    Responses created at %d responses/sec", msgs));
 
858
 
 
859
    report_ival("create-response-per-sec", 
 
860
                msgs, "msg/sec",
 
861
                "Number of typical response messages that can be created "
 
862
                "per second with <tt>pjsip_endpt_create_response()</tt>");
 
863
 
 
864
 
 
865
    return 0;
 
866
}
 
867