~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjsip/src/test/regc_test.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: regc_test.c 4094 2012-04-26 09:31:00Z bennylp $ */
 
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 "test.h"
 
21
#include <pjsip_ua.h>
 
22
#include <pjsip.h>
 
23
#include <pjlib.h>
 
24
 
 
25
#define THIS_FILE   "regc_test.c"
 
26
 
 
27
 
 
28
/************************************************************************/
 
29
/* A module to inject error into outgoing sending operation */
 
30
static pj_status_t mod_send_on_tx_request(pjsip_tx_data *tdata);
 
31
 
 
32
static struct 
 
33
{
 
34
    pjsip_module mod;
 
35
    unsigned     count;
 
36
    unsigned     count_before_reject;
 
37
} send_mod = 
 
38
{
 
39
    {
 
40
        NULL, NULL,                         /* prev, next.              */
 
41
        { "mod-send", 8 },                  /* Name.                    */
 
42
        -1,                                 /* Id                       */
 
43
        PJSIP_MOD_PRIORITY_TRANSPORT_LAYER,         /* Priority                 */
 
44
        NULL,                               /* load()                   */
 
45
        NULL,                               /* start()                  */
 
46
        NULL,                               /* stop()                   */
 
47
        NULL,                               /* unload()                 */
 
48
        NULL,                               /* on_rx_request()          */
 
49
        NULL,                               /* on_rx_response()         */
 
50
        &mod_send_on_tx_request,                    /* on_tx_request.           */
 
51
        NULL,                               /* on_tx_response()         */
 
52
        NULL,                               /* on_tsx_state()           */
 
53
    },
 
54
    0,
 
55
    0xFFFF
 
56
};
 
57
 
 
58
 
 
59
static pj_status_t mod_send_on_tx_request(pjsip_tx_data *tdata)
 
60
{
 
61
    PJ_UNUSED_ARG(tdata);
 
62
 
 
63
    if (++send_mod.count > send_mod.count_before_reject)
 
64
        return PJ_ECANCELLED;
 
65
    else
 
66
        return PJ_SUCCESS;
 
67
};
 
68
 
 
69
 
 
70
/************************************************************************/
 
71
/* Registrar for testing */
 
72
static pj_bool_t regs_rx_request(pjsip_rx_data *rdata);
 
73
 
 
74
enum contact_op
 
75
{
 
76
    NONE,       /* don't put Contact header         */
 
77
    EXACT,      /* return exact contact             */
 
78
    MODIFIED,   /* return modified Contact header   */
 
79
};
 
80
 
 
81
struct registrar_cfg
 
82
{
 
83
    pj_bool_t       respond;        /* should it respond at all         */
 
84
    unsigned        status_code;    /* final response status code       */
 
85
    pj_bool_t       authenticate;   /* should we authenticate?          */
 
86
    enum contact_op contact_op;     /* What should we do with Contact   */
 
87
    unsigned        expires_param;  /* non-zero to put in expires param */
 
88
    unsigned        expires;        /* non-zero to put in Expires header*/
 
89
 
 
90
    pj_str_t        more_contacts;  /* Additional Contact headers to put*/
 
91
};
 
92
 
 
93
static struct registrar
 
94
{
 
95
    pjsip_module            mod;
 
96
    struct registrar_cfg    cfg;
 
97
    unsigned                response_cnt;
 
98
} registrar = 
 
99
{
 
100
    {
 
101
        NULL, NULL,                         /* prev, next.              */
 
102
        { "registrar", 9 },                 /* Name.                    */
 
103
        -1,                                 /* Id                       */
 
104
        PJSIP_MOD_PRIORITY_APPLICATION,     /* Priority                 */
 
105
        NULL,                               /* load()                   */
 
106
        NULL,                               /* start()                  */
 
107
        NULL,                               /* stop()                   */
 
108
        NULL,                               /* unload()                 */
 
109
        &regs_rx_request,                   /* on_rx_request()          */
 
110
        NULL,                               /* on_rx_response()         */
 
111
        NULL,                               /* on_tx_request.           */
 
112
        NULL,                               /* on_tx_response()         */
 
113
        NULL,                               /* on_tsx_state()           */
 
114
    }
 
115
};
 
116
 
 
117
static pj_bool_t regs_rx_request(pjsip_rx_data *rdata)
 
118
{
 
119
    pjsip_msg *msg = rdata->msg_info.msg;
 
120
    pjsip_hdr hdr_list;
 
121
    int code;
 
122
    pj_status_t status;
 
123
 
 
124
    if (msg->line.req.method.id != PJSIP_REGISTER_METHOD)
 
125
        return PJ_FALSE;
 
126
 
 
127
    if (!registrar.cfg.respond)
 
128
        return PJ_TRUE;
 
129
 
 
130
    pj_list_init(&hdr_list);
 
131
 
 
132
    if (registrar.cfg.authenticate && 
 
133
        pjsip_msg_find_hdr(msg, PJSIP_H_AUTHORIZATION, NULL)==NULL) 
 
134
    {
 
135
        pjsip_generic_string_hdr *hwww;
 
136
        const pj_str_t hname = pj_str("WWW-Authenticate");
 
137
        const pj_str_t hvalue = pj_str("Digest realm=\"test\"");
 
138
 
 
139
        hwww = pjsip_generic_string_hdr_create(rdata->tp_info.pool, &hname, 
 
140
                                               &hvalue);
 
141
        pj_list_push_back(&hdr_list, hwww);
 
142
 
 
143
        code = 401;
 
144
 
 
145
    } else {
 
146
        if (registrar.cfg.contact_op == EXACT ||
 
147
            registrar.cfg.contact_op == MODIFIED) 
 
148
        {
 
149
            pjsip_hdr *hsrc;
 
150
 
 
151
            for (hsrc=msg->hdr.next; hsrc!=&msg->hdr; hsrc=hsrc->next) {
 
152
                pjsip_contact_hdr *hdst;
 
153
 
 
154
                if (hsrc->type != PJSIP_H_CONTACT)
 
155
                    continue;
 
156
 
 
157
                hdst = (pjsip_contact_hdr*)
 
158
                       pjsip_hdr_clone(rdata->tp_info.pool, hsrc);
 
159
 
 
160
                if (hdst->expires==0)
 
161
                    continue;
 
162
 
 
163
                if (registrar.cfg.contact_op == MODIFIED) {
 
164
                    if (PJSIP_URI_SCHEME_IS_SIP(hdst->uri) ||
 
165
                        PJSIP_URI_SCHEME_IS_SIPS(hdst->uri))
 
166
                    {
 
167
                        pjsip_sip_uri *sip_uri = (pjsip_sip_uri*)
 
168
                                                 pjsip_uri_get_uri(hdst->uri);
 
169
                        sip_uri->host = pj_str("x-modified-host");
 
170
                        sip_uri->port = 1;
 
171
                    }
 
172
                }
 
173
 
 
174
                if (registrar.cfg.expires_param)
 
175
                    hdst->expires = registrar.cfg.expires_param;
 
176
 
 
177
                pj_list_push_back(&hdr_list, hdst);
 
178
            }
 
179
        }
 
180
 
 
181
        if (registrar.cfg.more_contacts.slen) {
 
182
            pjsip_generic_string_hdr *hcontact;
 
183
            const pj_str_t hname = pj_str("Contact");
 
184
 
 
185
            hcontact = pjsip_generic_string_hdr_create(rdata->tp_info.pool, &hname, 
 
186
                                                       &registrar.cfg.more_contacts);
 
187
            pj_list_push_back(&hdr_list, hcontact);
 
188
        }
 
189
 
 
190
        if (registrar.cfg.expires) {
 
191
            pjsip_expires_hdr *hexp;
 
192
 
 
193
            hexp = pjsip_expires_hdr_create(rdata->tp_info.pool, 
 
194
                                            registrar.cfg.expires);
 
195
            pj_list_push_back(&hdr_list, hexp);
 
196
        }
 
197
 
 
198
        registrar.response_cnt++;
 
199
 
 
200
        code = registrar.cfg.status_code;
 
201
    }
 
202
 
 
203
    status = pjsip_endpt_respond(endpt, NULL, rdata, code, NULL,
 
204
                                 &hdr_list, NULL, NULL);
 
205
    pj_assert(status == PJ_SUCCESS);
 
206
 
 
207
    return PJ_TRUE;
 
208
}
 
209
 
 
210
 
 
211
/************************************************************************/
 
212
/* Client registration test session */
 
213
struct client
 
214
{
 
215
    /* Result/expected result */
 
216
    int         error;
 
217
    int         code;
 
218
    pj_bool_t   have_reg;
 
219
    int         expiration;
 
220
    unsigned    contact_cnt;
 
221
    pj_bool_t   auth;
 
222
 
 
223
    /* Commands */
 
224
    pj_bool_t   destroy_on_cb;
 
225
 
 
226
    /* Status */
 
227
    pj_bool_t   done;
 
228
 
 
229
    /* Additional results */
 
230
    int         interval;
 
231
    int         next_reg;
 
232
};
 
233
 
 
234
/* regc callback */
 
235
static void client_cb(struct pjsip_regc_cbparam *param)
 
236
{
 
237
    struct client *client = (struct client*) param->token;
 
238
    pjsip_regc_info info;
 
239
    pj_status_t status;
 
240
 
 
241
    client->done = PJ_TRUE;
 
242
 
 
243
    status = pjsip_regc_get_info(param->regc, &info);
 
244
    pj_assert(status == PJ_SUCCESS);
 
245
 
 
246
    client->error = (param->status != PJ_SUCCESS);
 
247
    client->code = param->code;
 
248
 
 
249
    if (client->error)
 
250
        return;
 
251
 
 
252
    client->have_reg = info.auto_reg && info.interval>0 &&
 
253
                       param->expiration>0;
 
254
    client->expiration = param->expiration;
 
255
    client->contact_cnt = param->contact_cnt;
 
256
    client->interval = info.interval;
 
257
    client->next_reg = info.next_reg;
 
258
 
 
259
    if (client->destroy_on_cb)
 
260
        pjsip_regc_destroy(param->regc);
 
261
}
 
262
 
 
263
 
 
264
/* Generic client test session */
 
265
static struct client client_result;
 
266
static int do_test(const char *title,
 
267
                   const struct registrar_cfg *srv_cfg, 
 
268
                   const struct client *client_cfg,
 
269
                   const pj_str_t *registrar_uri,
 
270
                   unsigned contact_cnt,
 
271
                   const pj_str_t contacts[],
 
272
                   unsigned expires,
 
273
                   pj_bool_t leave_session,
 
274
                   pjsip_regc **p_regc)
 
275
{
 
276
    pjsip_regc *regc;
 
277
    unsigned i;
 
278
    const pj_str_t aor = pj_str("<sip:regc-test@pjsip.org>");
 
279
    pjsip_tx_data *tdata;
 
280
    pj_status_t status;
 
281
 
 
282
    PJ_LOG(3,(THIS_FILE, "  %s", title));
 
283
 
 
284
    /* Modify registrar settings */
 
285
    pj_memcpy(&registrar.cfg, srv_cfg, sizeof(*srv_cfg));
 
286
 
 
287
    pj_bzero(&client_result, sizeof(client_result));
 
288
    client_result.destroy_on_cb = client_cfg->destroy_on_cb;
 
289
 
 
290
    status = pjsip_regc_create(endpt, &client_result, &client_cb, &regc);
 
291
    if (status != PJ_SUCCESS)
 
292
        return -100;
 
293
 
 
294
    status = pjsip_regc_init(regc, registrar_uri, &aor, &aor, contact_cnt,
 
295
                             contacts, expires ? expires : 60);
 
296
    if (status != PJ_SUCCESS) {
 
297
        pjsip_regc_destroy(regc);
 
298
        return -110;
 
299
    }
 
300
 
 
301
    if (client_cfg->auth) {
 
302
        pjsip_cred_info cred;
 
303
 
 
304
        pj_bzero(&cred, sizeof(cred));
 
305
        cred.realm = pj_str("*");
 
306
        cred.scheme = pj_str("digest");
 
307
        cred.username = pj_str("user");
 
308
        cred.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
 
309
        cred.data = pj_str("password");
 
310
 
 
311
        status = pjsip_regc_set_credentials(regc, 1, &cred);
 
312
        if (status != PJ_SUCCESS) {
 
313
            pjsip_regc_destroy(regc);
 
314
            return -115;
 
315
        }
 
316
    }
 
317
 
 
318
    /* Register */
 
319
    status = pjsip_regc_register(regc, PJ_TRUE, &tdata);
 
320
    if (status != PJ_SUCCESS) {
 
321
        pjsip_regc_destroy(regc);
 
322
        return -120;
 
323
    }
 
324
    status = pjsip_regc_send(regc, tdata);
 
325
 
 
326
    /* That's it, wait until the callback is sent */
 
327
    for (i=0; i<600 && !client_result.done; ++i) {
 
328
        flush_events(100);
 
329
    }
 
330
 
 
331
    if (!client_result.done) {
 
332
        PJ_LOG(3,(THIS_FILE, "    error: test has timed out"));
 
333
        pjsip_regc_destroy(regc);
 
334
        return -200;
 
335
    }
 
336
 
 
337
    /* Destroy the regc, we're done with the test, unless we're
 
338
     * instructed to leave the session open.
 
339
     */
 
340
    if (!leave_session && !client_cfg->destroy_on_cb)
 
341
        pjsip_regc_destroy(regc);
 
342
 
 
343
    /* Compare results with expected results */
 
344
 
 
345
    if (client_result.error != client_cfg->error) {
 
346
        PJ_LOG(3,(THIS_FILE, "    error: expecting err=%d, got err=%d",
 
347
                  client_cfg->error, client_result.error));
 
348
        return -210;
 
349
    }
 
350
    if (client_result.code != client_cfg->code) {
 
351
        PJ_LOG(3,(THIS_FILE, "    error: expecting code=%d, got code=%d",
 
352
                  client_cfg->code, client_result.code));
 
353
        return -220;
 
354
    }
 
355
    if (client_result.expiration != client_cfg->expiration) {
 
356
        PJ_LOG(3,(THIS_FILE, "    error: expecting expiration=%d, got expiration=%d",
 
357
                  client_cfg->expiration, client_result.expiration));
 
358
        return -240;
 
359
    }
 
360
    if (client_result.contact_cnt != client_cfg->contact_cnt) {
 
361
        PJ_LOG(3,(THIS_FILE, "    error: expecting contact_cnt=%d, got contact_cnt=%d",
 
362
                  client_cfg->contact_cnt, client_result.contact_cnt));
 
363
        return -250;
 
364
    }
 
365
    if (client_result.have_reg != client_cfg->have_reg) {
 
366
        PJ_LOG(3,(THIS_FILE, "    error: expecting have_reg=%d, got have_reg=%d",
 
367
                  client_cfg->have_reg, client_result.have_reg));
 
368
        return -260;
 
369
    }
 
370
    if (client_result.interval != client_result.expiration) {
 
371
        PJ_LOG(3,(THIS_FILE, "    error: interval (%d) is different than expiration (%d)",
 
372
                  client_result.interval, client_result.expiration));
 
373
        return -270;
 
374
    }
 
375
    if (client_result.expiration > 0 && client_result.next_reg < 1) {
 
376
        PJ_LOG(3,(THIS_FILE, "    error: next_reg=%d, expecting positive number because expiration is %d",
 
377
                  client_result.next_reg, client_result.expiration));
 
378
        return -280;
 
379
    }
 
380
 
 
381
    /* Looks like everything is okay. */
 
382
    if (leave_session) {
 
383
        *p_regc = regc;
 
384
    }
 
385
 
 
386
    return 0;
 
387
}
 
388
 
 
389
 
 
390
/************************************************************************/
 
391
/* Customized tests */
 
392
 
 
393
/* Check that client is sending register refresh */
 
394
static int keep_alive_test(const pj_str_t *registrar_uri)
 
395
{
 
396
    enum { TIMEOUT = 40 };
 
397
    struct registrar_cfg server_cfg = 
 
398
        /* respond      code    auth      contact  exp_prm expires more_contacts */
 
399
        { PJ_TRUE,      200,    PJ_FALSE, EXACT,   TIMEOUT, 0,      {NULL, 0}};
 
400
    struct client client_cfg = 
 
401
        /* error        code    have_reg    expiration  contact_cnt auth?    destroy*/
 
402
        { PJ_FALSE,     200,    PJ_TRUE,   TIMEOUT,     1,          PJ_FALSE,PJ_FALSE};
 
403
    pj_str_t contact = pj_str("<sip:c@C>");
 
404
 
 
405
 
 
406
    pjsip_regc *regc;
 
407
    unsigned i;
 
408
    int ret;
 
409
 
 
410
    ret = do_test("register refresh (takes ~40 secs)", &server_cfg, &client_cfg, registrar_uri,
 
411
                  1, &contact, TIMEOUT, PJ_TRUE, &regc);
 
412
    if (ret != 0)
 
413
        return ret;
 
414
 
 
415
    /* Reset server response_cnt */
 
416
    registrar.response_cnt = 0;
 
417
 
 
418
    /* Wait until keep-alive/refresh is done */
 
419
    for (i=0; i<(TIMEOUT-1)*10 && registrar.response_cnt==0; ++i) {
 
420
        flush_events(100);
 
421
    }
 
422
 
 
423
    if (registrar.response_cnt==0) {
 
424
        PJ_LOG(3,(THIS_FILE, "    error: no refresh is received"));
 
425
        return -400;
 
426
    }
 
427
 
 
428
    if (client_result.error) {
 
429
        PJ_LOG(3,(THIS_FILE, "    error: got error"));
 
430
        return -410;
 
431
    }
 
432
    if (client_result.code != 200) {
 
433
        PJ_LOG(3,(THIS_FILE, "    error: expecting code=%d, got code=%d",
 
434
                  200, client_result.code));
 
435
        return -420;
 
436
    }
 
437
    if (client_result.expiration != TIMEOUT) {
 
438
        PJ_LOG(3,(THIS_FILE, "    error: expecting expiration=%d, got expiration=%d",
 
439
                  TIMEOUT, client_result.expiration));
 
440
        return -440;
 
441
    }
 
442
    if (client_result.contact_cnt != 1) {
 
443
        PJ_LOG(3,(THIS_FILE, "    error: expecting contact_cnt=%d, got contact_cnt=%d",
 
444
                  TIMEOUT, client_result.contact_cnt));
 
445
        return -450;
 
446
    }
 
447
    if (client_result.have_reg == 0) {
 
448
        PJ_LOG(3,(THIS_FILE, "    error: expecting have_reg=%d, got have_reg=%d",
 
449
                  1, client_result.have_reg));
 
450
        return -460;
 
451
    }
 
452
    if (client_result.interval != TIMEOUT) {
 
453
        PJ_LOG(3,(THIS_FILE, "    error: interval (%d) is different than expiration (%d)",
 
454
                  client_result.interval, TIMEOUT));
 
455
        return -470;
 
456
    }
 
457
    if (client_result.expiration > 0 && client_result.next_reg < 1) {
 
458
        PJ_LOG(3,(THIS_FILE, "    error: next_reg=%d, expecting positive number because expiration is %d",
 
459
                  client_result.next_reg, client_result.expiration));
 
460
        return -480;
 
461
    }
 
462
 
 
463
    /* Success */
 
464
    pjsip_regc_destroy(regc);
 
465
    return 0;
 
466
}
 
467
 
 
468
 
 
469
/* Send error on refresh */
 
470
static int refresh_error(const pj_str_t *registrar_uri,
 
471
                         pj_bool_t destroy_on_cb)
 
472
{
 
473
    enum { TIMEOUT = 40 };
 
474
    struct registrar_cfg server_cfg = 
 
475
        /* respond      code    auth      contact  exp_prm expires more_contacts */
 
476
        { PJ_TRUE,      200,    PJ_FALSE, EXACT,   TIMEOUT, 0,      {NULL, 0}};
 
477
    struct client client_cfg = 
 
478
        /* error        code    have_reg    expiration  contact_cnt auth?    destroy*/
 
479
        { PJ_FALSE,     200,    PJ_TRUE,   TIMEOUT,     1,          PJ_FALSE,PJ_FALSE};
 
480
    pj_str_t contact = pj_str("<sip:c@C>");
 
481
 
 
482
    pjsip_regc *regc;
 
483
    unsigned i;
 
484
    int ret;
 
485
 
 
486
    ret = do_test("refresh error (takes ~40 secs)", &server_cfg, &client_cfg, registrar_uri,
 
487
                  1, &contact, TIMEOUT, PJ_TRUE, &regc);
 
488
    if (ret != 0)
 
489
        return ret;
 
490
 
 
491
    /* Reset server response_cnt */
 
492
    registrar.response_cnt = 0;
 
493
 
 
494
    /* inject error for transmission */
 
495
    send_mod.count = 0;
 
496
    send_mod.count_before_reject = 0;
 
497
 
 
498
    /* reconfigure client */
 
499
    client_result.done = PJ_FALSE;
 
500
    client_result.destroy_on_cb = destroy_on_cb;
 
501
 
 
502
    /* Wait until keep-alive/refresh is done */
 
503
    for (i=0; i<TIMEOUT*10 && !client_result.done; ++i) {
 
504
        flush_events(100);
 
505
    }
 
506
 
 
507
    send_mod.count_before_reject = 0xFFFF;
 
508
 
 
509
    if (!destroy_on_cb)
 
510
        pjsip_regc_destroy(regc);
 
511
 
 
512
    if (!client_result.done) {
 
513
        PJ_LOG(3,(THIS_FILE, "    error: test has timed out"));
 
514
        return -500;
 
515
    }
 
516
 
 
517
    /* Expecting error */
 
518
    if (client_result.error==PJ_FALSE && client_result.code/100==2) {
 
519
        PJ_LOG(3,(THIS_FILE, "    error: expecting error got successfull result"));
 
520
        return -510;
 
521
    }
 
522
 
 
523
    return PJ_SUCCESS;
 
524
};
 
525
 
 
526
 
 
527
/* Send error on refresh */
 
528
static int update_test(const pj_str_t *registrar_uri)
 
529
{
 
530
    enum { TIMEOUT = 40 };
 
531
    struct registrar_cfg server_cfg = 
 
532
        /* respond      code    auth      contact  exp_prm expires more_contacts */
 
533
        { PJ_TRUE,      200,    PJ_FALSE, EXACT,   TIMEOUT, 0,      {NULL, 0}};
 
534
    struct client client_cfg = 
 
535
        /* error        code    have_reg    expiration  contact_cnt auth?    destroy*/
 
536
        { PJ_FALSE,     200,    PJ_TRUE,   TIMEOUT,     1,          PJ_FALSE,PJ_FALSE};
 
537
    pj_str_t contacts[] = {
 
538
        { "<sip:a>", 7 },
 
539
        { "<sip:b>", 7 },
 
540
        { "<sip:c>", 7 }
 
541
    };
 
542
 
 
543
    pjsip_regc *regc;
 
544
    pjsip_contact_hdr *h1, *h2;
 
545
    pjsip_sip_uri *u1, *u2;
 
546
    unsigned i;
 
547
    pj_status_t status;
 
548
    pjsip_tx_data *tdata = NULL;
 
549
    int ret = 0;
 
550
 
 
551
    /* initially only has 1 contact */
 
552
    ret = do_test("update test", &server_cfg, &client_cfg, registrar_uri,
 
553
                  1, &contacts[0], TIMEOUT, PJ_TRUE, &regc);
 
554
    if (ret != 0) {
 
555
        return -600;
 
556
    }
 
557
 
 
558
    /*****
 
559
     * replace the contact with new one 
 
560
     */
 
561
    PJ_LOG(3,(THIS_FILE, "   replacing contact"));
 
562
    status = pjsip_regc_update_contact(regc, 1, &contacts[1]);
 
563
    if (status != PJ_SUCCESS) {
 
564
        ret = -610;
 
565
        goto on_return;
 
566
    }
 
567
 
 
568
    status = pjsip_regc_register(regc, PJ_TRUE, &tdata);
 
569
    if (status != PJ_SUCCESS) {
 
570
        ret = -620;
 
571
        goto on_return;
 
572
    }
 
573
 
 
574
    /* Check that the REGISTER contains two Contacts:
 
575
     *  - <sip:a>;expires=0,
 
576
     *  - <sip:b>
 
577
     */
 
578
    h1 = (pjsip_contact_hdr*) 
 
579
          pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
 
580
    if (!h1) {
 
581
        ret = -630;
 
582
        goto on_return;
 
583
    }
 
584
    if ((void*)h1->next == (void*)&tdata->msg->hdr)
 
585
        h2 = NULL;
 
586
    else
 
587
        h2 = (pjsip_contact_hdr*) 
 
588
              pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, h1->next);
 
589
    if (!h2) {
 
590
        ret = -640;
 
591
        goto on_return;
 
592
    }
 
593
    /* must not have other Contact header */
 
594
    if ((void*)h2->next != (void*)&tdata->msg->hdr &&
 
595
        pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, h2->next) != NULL)
 
596
    {
 
597
        ret = -645;
 
598
        goto on_return;
 
599
    }
 
600
 
 
601
    u1 = (pjsip_sip_uri*) pjsip_uri_get_uri(h1->uri);
 
602
    u2 = (pjsip_sip_uri*) pjsip_uri_get_uri(h2->uri);
 
603
 
 
604
    if (*u1->host.ptr == 'a') {
 
605
        if (h1->expires != 0) {
 
606
            ret = -650;
 
607
            goto on_return;
 
608
        }
 
609
        if (h2->expires == 0) {
 
610
            ret = -660;
 
611
            goto on_return;
 
612
        }
 
613
 
 
614
    } else {
 
615
        pj_assert(*u1->host.ptr == 'b');
 
616
        if (h1->expires == 0) {
 
617
            ret = -670;
 
618
            goto on_return;
 
619
        }
 
620
        if (h2->expires != 0) {
 
621
            ret = -680;
 
622
            goto on_return;
 
623
        }
 
624
    }
 
625
 
 
626
    /* Destroy tdata */
 
627
    pjsip_tx_data_dec_ref(tdata);
 
628
    tdata = NULL;
 
629
 
 
630
 
 
631
 
 
632
    /** 
 
633
     * First loop, it will update with more contacts. Second loop
 
634
     * should do nothing.
 
635
     */
 
636
    for (i=0; i<2; ++i) {
 
637
        if (i==0)
 
638
            PJ_LOG(3,(THIS_FILE, "   replacing with more contacts"));
 
639
        else
 
640
            PJ_LOG(3,(THIS_FILE, "   updating contacts with same contacts"));
 
641
 
 
642
        status = pjsip_regc_update_contact(regc, 2, &contacts[1]);
 
643
        if (status != PJ_SUCCESS) {
 
644
            ret = -710;
 
645
            goto on_return;
 
646
        }
 
647
 
 
648
        status = pjsip_regc_register(regc, PJ_TRUE, &tdata);
 
649
        if (status != PJ_SUCCESS) {
 
650
            ret = -720;
 
651
            goto on_return;
 
652
        }
 
653
 
 
654
        /* Check that the REGISTER contains two Contacts:
 
655
         *  - <sip:b>
 
656
         *  - <sip:c>
 
657
         */
 
658
        h1 = (pjsip_contact_hdr*) 
 
659
              pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
 
660
        if (!h1) {
 
661
            ret = -730;
 
662
            goto on_return;
 
663
        }
 
664
        if ((void*)h1->next == (void*)&tdata->msg->hdr)
 
665
            h2 = NULL;
 
666
        else
 
667
            h2 = (pjsip_contact_hdr*) 
 
668
                  pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, h1->next);
 
669
        if (!h2) {
 
670
            ret = -740;
 
671
            goto on_return;
 
672
        }
 
673
        /* must not have other Contact header */
 
674
        if ((void*)h2->next != (void*)&tdata->msg->hdr &&
 
675
            pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, h2->next) != NULL)
 
676
        {
 
677
            ret = -745;
 
678
            goto on_return;
 
679
        }
 
680
 
 
681
        /* both contacts must not have expires=0 parameter */
 
682
        if (h1->expires == 0) {
 
683
            ret = -750;
 
684
            goto on_return;
 
685
        }
 
686
        if (h2->expires == 0) {
 
687
            ret = -760;
 
688
            goto on_return;
 
689
        }
 
690
 
 
691
        /* Destroy tdata */
 
692
        pjsip_tx_data_dec_ref(tdata);
 
693
        tdata = NULL;
 
694
    }
 
695
 
 
696
on_return:
 
697
    if (tdata) pjsip_tx_data_dec_ref(tdata);
 
698
    pjsip_regc_destroy(regc);
 
699
    return ret;
 
700
};
 
701
 
 
702
 
 
703
/* send error on authentication */
 
704
static int auth_send_error(const pj_str_t *registrar_uri,
 
705
                           pj_bool_t destroy_on_cb)
 
706
{
 
707
    enum { TIMEOUT = 40 };
 
708
    struct registrar_cfg server_cfg = 
 
709
        /* respond      code    auth      contact  exp_prm expires more_contacts */
 
710
        { PJ_TRUE,      200,    PJ_TRUE,  EXACT,   75,      0,      {NULL, 0}};
 
711
    struct client client_cfg = 
 
712
        /* error        code    have_reg    expiration  contact_cnt auth?    destroy*/
 
713
        { PJ_TRUE,      401,    PJ_FALSE, -1,           0,          PJ_TRUE, PJ_TRUE};
 
714
    pj_str_t contact = pj_str("<sip:c@C>");
 
715
 
 
716
    pjsip_regc *regc;
 
717
    int ret;
 
718
 
 
719
    client_cfg.destroy_on_cb = destroy_on_cb;
 
720
 
 
721
    /* inject error for second request retry */
 
722
    send_mod.count = 0;
 
723
    send_mod.count_before_reject = 1;
 
724
 
 
725
    ret = do_test("auth send error", &server_cfg, &client_cfg, registrar_uri,
 
726
                  1, &contact, TIMEOUT, PJ_TRUE, &regc);
 
727
 
 
728
    send_mod.count_before_reject = 0xFFFF;
 
729
 
 
730
    return ret;
 
731
};
 
732
 
 
733
 
 
734
 
 
735
 
 
736
/************************************************************************/
 
737
enum
 
738
{
 
739
    OFF     = 1,
 
740
    ON      = 2,
 
741
    ON_OFF  = 3,
 
742
};
 
743
 
 
744
int regc_test(void)
 
745
{
 
746
    struct test_rec {
 
747
        unsigned                 check_contact;
 
748
        unsigned                 add_xuid_param;
 
749
 
 
750
        const char              *title;
 
751
        char                    *alt_registrar;
 
752
        unsigned                 contact_cnt;
 
753
        char                    *contacts[4];
 
754
        unsigned                 expires;
 
755
        struct registrar_cfg     server_cfg;
 
756
        struct client            client_cfg;
 
757
    } test_rec[] = 
 
758
    {
 
759
        /* immediate error */
 
760
        {
 
761
            OFF,                            /* check_contact    */
 
762
            OFF,                            /* add_xuid_param   */
 
763
            "immediate error",              /* title            */
 
764
            "sip:unresolved-host-xyy",      /* alt_registrar    */
 
765
            1,                              /* contact cnt      */
 
766
            { "sip:user@127.0.0.1:5060" },  /* contacts[]       */
 
767
            600,                            /* expires          */
 
768
 
 
769
            /* registrar config: */
 
770
            /* respond  code    auth      contact   exp_prm expires more_contacts */
 
771
            { PJ_FALSE, 200,    PJ_FALSE, NONE,     0,      0,      {NULL, 0}},
 
772
 
 
773
            /* client expected results: */
 
774
            /* error    code    have_reg    expiration  contact_cnt auth?*/
 
775
            { PJ_FALSE, 502,    PJ_FALSE,   -1,         0,          PJ_FALSE}
 
776
        },
 
777
 
 
778
        /* timeout test */
 
779
        {
 
780
            OFF,                            /* check_contact    */
 
781
            OFF,                            /* add_xuid_param   */
 
782
            "timeout test (takes ~32 secs)",/* title            */
 
783
            NULL,                           /* alt_registrar    */
 
784
            1,                              /* contact cnt      */
 
785
            { "sip:user@127.0.0.1:5060" },  /* contacts[]       */
 
786
            600,                            /* expires          */
 
787
 
 
788
            /* registrar config: */
 
789
            /* respond  code    auth      contact   exp_prm expires more_contacts */
 
790
            { PJ_FALSE, 200,    PJ_FALSE, NONE,     0,      0,      {NULL, 0}},
 
791
 
 
792
            /* client expected results: */
 
793
            /* error    code    have_reg    expiration  contact_cnt auth? */
 
794
            { PJ_FALSE, 408,    PJ_FALSE,   -1,         0,          PJ_FALSE}
 
795
        },
 
796
 
 
797
        /* Basic successful registration scenario:
 
798
         * a good registrar returns the Contact header as is and
 
799
         * add expires parameter. In this test no additional bindings
 
800
         * are returned.
 
801
         */
 
802
        {
 
803
            ON_OFF,                         /* check_contact    */
 
804
            ON_OFF,                         /* add_xuid_param   */
 
805
            "basic",                        /* title            */
 
806
            NULL,                           /* alt_registrar    */
 
807
            1,                              /* contact cnt      */
 
808
            { "<sip:user@127.0.0.1:5060;transport=udp;x-param=1234>" },  /* contacts[]  */
 
809
            600,                            /* expires          */
 
810
 
 
811
            /* registrar config: */
 
812
            /* respond  code    auth      contact  exp_prm expires more_contacts */
 
813
            { PJ_TRUE,  200,    PJ_FALSE, EXACT,    75,     65,     {NULL, 0}},
 
814
 
 
815
            /* client expected results: */
 
816
            /* error    code    have_reg    expiration  contact_cnt auth?*/
 
817
            { PJ_FALSE, 200,    PJ_TRUE,   75,          1,          PJ_FALSE}
 
818
        },
 
819
 
 
820
        /* Basic successful registration scenario with authentication
 
821
         */
 
822
        {
 
823
            ON_OFF,                         /* check_contact    */
 
824
            ON_OFF,                         /* add_xuid_param   */
 
825
            "authentication",               /* title            */
 
826
            NULL,                           /* alt_registrar    */
 
827
            1,                              /* contact cnt      */
 
828
            { "<sip:user@127.0.0.1:5060;transport=udp;x-param=1234>" },  /* contacts[]  */
 
829
            600,                            /* expires          */
 
830
 
 
831
            /* registrar config: */
 
832
            /* respond  code    auth      contact  exp_prm expires more_contacts */
 
833
            { PJ_TRUE,  200,    PJ_TRUE,  EXACT,    75,     65,     {NULL, 0}},
 
834
 
 
835
            /* client expected results: */
 
836
            /* error    code    have_reg    expiration  contact_cnt auth?*/
 
837
            { PJ_FALSE, 200,    PJ_TRUE,   75,          1,          PJ_TRUE}
 
838
        },
 
839
 
 
840
        /* a good registrar returns the Contact header as is and
 
841
         * add expires parameter. Also it adds bindings from other
 
842
         * clients in this test.
 
843
         */
 
844
        {
 
845
            ON_OFF,                         /* check_contact    */
 
846
            ON,                             /* add_xuid_param   */
 
847
            "more bindings in response",    /* title            */
 
848
            NULL,                           /* alt_registrar    */
 
849
            1,                              /* contact cnt      */
 
850
            { "<sip:user@127.0.0.1:5060;transport=udp>" },  /* contacts[]       */
 
851
            600,                            /* expires          */
 
852
 
 
853
            /* registrar config: */
 
854
            /* respond  code    auth      contact  exp_prm expires more_contacts */
 
855
            { PJ_TRUE,  200,    PJ_FALSE, EXACT,    75,     65,     {"<sip:a@a>;expires=70", 0}},
 
856
 
 
857
            /* client expected results: */
 
858
            /* error    code    have_reg    expiration  contact_cnt auth?*/
 
859
            { PJ_FALSE, 200,    PJ_TRUE,   75,          2,          PJ_FALSE}
 
860
        },
 
861
 
 
862
 
 
863
        /* a bad registrar returns modified Contact header, but it
 
864
         * still returns all parameters intact. In this case
 
865
         * the expiration is taken from the expires param because
 
866
         * of matching xuid param or because the number of
 
867
         * Contact header matches.
 
868
         */
 
869
        {
 
870
            ON_OFF,                         /* check_contact    */
 
871
            ON_OFF,                         /* add_xuid_param   */
 
872
            "registrar modifies Contact header",    /* title            */
 
873
            NULL,                           /* alt_registrar    */
 
874
            1,                              /* contact cnt      */
 
875
            { "<sip:user@127.0.0.1:5060>" },  /* contacts[]     */
 
876
            600,                            /* expires          */
 
877
 
 
878
            /* registrar config: */
 
879
            /* respond  code    auth      contact   exp_prm expires more_contacts */
 
880
            { PJ_TRUE,  200,    PJ_FALSE, MODIFIED, 75,     65,     {NULL, 0}},
 
881
 
 
882
            /* client expected results: */
 
883
            /* error    code    have_reg    expiration  contact_cnt auth?*/
 
884
            { PJ_FALSE, 200,    PJ_TRUE,   75,          1,          PJ_FALSE}
 
885
        },
 
886
 
 
887
 
 
888
        /* a bad registrar returns modified Contact header, but it
 
889
         * still returns all parameters intact. In addition it returns
 
890
         * bindings from other clients.
 
891
         *
 
892
         * In this case the expiration is taken from the expires param 
 
893
         * because add_xuid_param is enabled.
 
894
         */
 
895
        {
 
896
            ON_OFF,                         /* check_contact    */
 
897
            ON,                             /* add_xuid_param   */
 
898
            "registrar modifies Contact header and add bindings",    /* title           */
 
899
            NULL,                           /* alt_registrar    */
 
900
            1,                              /* contact cnt      */
 
901
            { "<sip:user@127.0.0.1:5060>" },  /* contacts[]     */
 
902
            600,                            /* expires          */
 
903
 
 
904
            /* registrar config: */
 
905
            /* respond  code    auth      contact   exp_prm expires more_contacts */
 
906
            { PJ_TRUE,  200,    PJ_FALSE, MODIFIED, 75,     65,     {"<sip:a@a>;expires=70", 0}},
 
907
 
 
908
            /* client expected results: */
 
909
            /* error    code    have_reg    expiration  contact_cnt auth?*/
 
910
            { PJ_FALSE, 200,    PJ_TRUE,   75,          2,          PJ_FALSE}
 
911
        },
 
912
 
 
913
 
 
914
        /* a bad registrar returns completely different Contact and
 
915
         * all parameters are gone. In this case the expiration is 
 
916
         * also taken from the expires param since the number of 
 
917
         * header matches.
 
918
         */
 
919
        {
 
920
            ON_OFF,                         /* check_contact    */
 
921
            ON_OFF,                         /* add_xuid_param   */
 
922
            "registrar replaces Contact header",    /* title            */
 
923
            NULL,                           /* alt_registrar    */
 
924
            1,                              /* contact cnt      */
 
925
            { "<sip:user@127.0.0.1:5060>" },  /* contacts[]     */
 
926
            600,                            /* expires          */
 
927
 
 
928
            /* registrar config: */
 
929
            /* respond  code    auth      contact   exp_prm expires more_contacts */
 
930
            { PJ_TRUE,  202,    PJ_FALSE, NONE,     0,      65,     {"<sip:a@A>;expires=75", 0}},
 
931
 
 
932
            /* client expected results: */
 
933
            /* error    code    have_reg    expiration  contact_cnt auth?*/
 
934
            { PJ_FALSE, 202,    PJ_TRUE,   75,          1,          PJ_FALSE}
 
935
        },
 
936
 
 
937
 
 
938
        /* a bad registrar returns completely different Contact (and
 
939
         * all parameters are gone) and it also includes bindings from
 
940
         * other clients.
 
941
         * In this case the expiration is taken from the Expires header.
 
942
         */
 
943
        {
 
944
            ON_OFF,                         /* check_contact    */
 
945
            ON_OFF,                         /* add_xuid_param   */
 
946
            " as above with additional bindings",    /* title           */
 
947
            NULL,                           /* alt_registrar    */
 
948
            1,                              /* contact cnt      */
 
949
            { "<sip:user@127.0.0.1:5060>" },  /* contacts[]     */
 
950
            600,                            /* expires          */
 
951
 
 
952
            /* registrar config: */
 
953
            /* respond  code    auth      contact   exp_prm expires more_contacts */
 
954
            { PJ_TRUE,  200,    PJ_FALSE, NONE,     0,      65,     {"<sip:a@A>;expires=75, <sip:b@B;expires=70>", 0}},
 
955
 
 
956
            /* client expected results: */
 
957
            /* error    code    have_reg    expiration  contact_cnt auth?*/
 
958
            { PJ_FALSE, 200,    PJ_TRUE,   65,          2,          PJ_FALSE}
 
959
        },
 
960
 
 
961
        /* the registrar doesn't return any bindings, but for some
 
962
         * reason it includes an Expires header.
 
963
         * In this case the expiration is taken from the Expires header.
 
964
         */
 
965
        {
 
966
            ON_OFF,                         /* check_contact    */
 
967
            ON_OFF,                         /* add_xuid_param   */
 
968
            "no Contact but with Expires",  /* title            */
 
969
            NULL,                           /* alt_registrar    */
 
970
            1,                              /* contact cnt      */
 
971
            { "<sip:user@127.0.0.1:5060>" },  /* contacts[]     */
 
972
            600,                            /* expires          */
 
973
 
 
974
            /* registrar config: */
 
975
            /* respond  code    auth      contact   exp_prm expires more_contacts */
 
976
            { PJ_TRUE,  200,    PJ_FALSE, NONE,     0,      65,     {NULL, 0}},
 
977
 
 
978
            /* client expected results: */
 
979
            /* error    code    have_reg    expiration  contact_cnt auth?*/
 
980
            { PJ_FALSE, 200,    PJ_TRUE,   65,          0,          PJ_FALSE}
 
981
        },
 
982
 
 
983
        /* Neither Contact header nor Expires header are present.
 
984
         * In this case the expiration is taken from the request.
 
985
         */
 
986
        {
 
987
            ON_OFF,                         /* check_contact    */
 
988
            ON_OFF,                         /* add_xuid_param   */
 
989
            "no Contact and no Expires",    /* title            */
 
990
            NULL,                           /* alt_registrar    */
 
991
            1,                              /* contact cnt      */
 
992
            { "<sip:user@127.0.0.1:5060>" },/* contacts[]       */
 
993
            600,                            /* expires          */
 
994
 
 
995
            /* registrar config: */
 
996
            /* respond  code    auth      contact   exp_prm expires more_contacts */
 
997
            { PJ_TRUE,  200,    PJ_FALSE, NONE,     0,      0,      {NULL, 0}},
 
998
 
 
999
            /* client expected results: */
 
1000
            /* error    code    have_reg    expiration  contact_cnt auth?*/
 
1001
            { PJ_FALSE, 200,    PJ_TRUE,   600,         0,          PJ_FALSE}
 
1002
        },
 
1003
    };
 
1004
 
 
1005
    unsigned i;
 
1006
    pj_sockaddr_in addr;
 
1007
    pjsip_transport *udp = NULL;
 
1008
    pj_uint16_t port; 
 
1009
    char registrar_uri_buf[80];
 
1010
    pj_str_t registrar_uri;
 
1011
    int rc = 0;
 
1012
 
 
1013
    pj_sockaddr_in_init(&addr, 0, 0);
 
1014
 
 
1015
    /* Acquire existing transport, if any */
 
1016
    rc = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_UDP, &addr, sizeof(addr), NULL, &udp);
 
1017
    if (rc == PJ_SUCCESS) {
 
1018
        port = pj_sockaddr_get_port(&udp->local_addr);
 
1019
        pjsip_transport_dec_ref(udp);
 
1020
        udp = NULL;
 
1021
    } else {
 
1022
        rc = pjsip_udp_transport_start(endpt, NULL, NULL, 1, &udp);
 
1023
        if (rc != PJ_SUCCESS) {
 
1024
            app_perror("   error creating UDP transport", rc);
 
1025
            rc = -2;
 
1026
            goto on_return;
 
1027
        }
 
1028
 
 
1029
        port = pj_sockaddr_get_port(&udp->local_addr);
 
1030
    }
 
1031
 
 
1032
    /* Register registrar module */
 
1033
    rc = pjsip_endpt_register_module(endpt, &registrar.mod);
 
1034
    if (rc != PJ_SUCCESS) {
 
1035
        app_perror("   error registering module", rc);
 
1036
        rc = -3;
 
1037
        goto on_return;
 
1038
    }
 
1039
 
 
1040
    /* Register send module */
 
1041
    rc = pjsip_endpt_register_module(endpt, &send_mod.mod);
 
1042
    if (rc != PJ_SUCCESS) {
 
1043
        app_perror("   error registering module", rc);
 
1044
        rc = -3;
 
1045
        goto on_return;
 
1046
    }
 
1047
 
 
1048
    pj_ansi_snprintf(registrar_uri_buf, sizeof(registrar_uri_buf),
 
1049
                    "sip:127.0.0.1:%d", (int)port);
 
1050
    registrar_uri = pj_str(registrar_uri_buf);
 
1051
 
 
1052
    for (i=0; i<PJ_ARRAY_SIZE(test_rec); ++i) {
 
1053
        struct test_rec *t = &test_rec[i];
 
1054
        unsigned j, x;
 
1055
        pj_str_t reg_uri;
 
1056
        pj_str_t contacts[8];
 
1057
 
 
1058
        /* Fill in the registrar address if it's not specified */
 
1059
        if (t->alt_registrar == NULL) {
 
1060
            reg_uri = registrar_uri;
 
1061
        } else {
 
1062
            reg_uri = pj_str(t->alt_registrar);
 
1063
        }
 
1064
 
 
1065
        /* Build contact pj_str_t's */
 
1066
        for (j=0; j<t->contact_cnt; ++j) {
 
1067
            contacts[j] = pj_str(t->contacts[j]);
 
1068
        }
 
1069
 
 
1070
        /* Normalize more_contacts field */
 
1071
        if (t->server_cfg.more_contacts.ptr)
 
1072
            t->server_cfg.more_contacts.slen = strlen(t->server_cfg.more_contacts.ptr);
 
1073
 
 
1074
        /* Do tests with three combinations:
 
1075
         *  - check_contact on/off
 
1076
         *  - add_xuid_param on/off
 
1077
         *  - destroy_on_callback on/off
 
1078
         */
 
1079
        for (x=1; x<=2; ++x) {
 
1080
            unsigned y;
 
1081
 
 
1082
            if ((t->check_contact & x) == 0)
 
1083
                continue;
 
1084
 
 
1085
            pjsip_cfg()->regc.check_contact = (x-1);
 
1086
 
 
1087
            for (y=1; y<=2; ++y) {
 
1088
                unsigned z;
 
1089
 
 
1090
                if ((t->add_xuid_param & y) == 0)
 
1091
                    continue;
 
1092
 
 
1093
                pjsip_cfg()->regc.add_xuid_param = (y-1);
 
1094
 
 
1095
                for (z=0; z<=1; ++z) {
 
1096
                    char new_title[200];
 
1097
 
 
1098
                    t->client_cfg.destroy_on_cb = z;
 
1099
 
 
1100
                    sprintf(new_title, "%s [check=%d, xuid=%d, destroy=%d]", 
 
1101
                            t->title, pjsip_cfg()->regc.check_contact,
 
1102
                            pjsip_cfg()->regc.add_xuid_param, z);
 
1103
                    rc = do_test(new_title, &t->server_cfg, &t->client_cfg, 
 
1104
                                 &reg_uri, t->contact_cnt, contacts, 
 
1105
                                 t->expires, PJ_FALSE, NULL);
 
1106
                    if (rc != 0)
 
1107
                        goto on_return;
 
1108
                }
 
1109
 
 
1110
            }
 
1111
        }
 
1112
 
 
1113
        /* Sleep between test groups to avoid using up too many
 
1114
         * active transactions.
 
1115
         */
 
1116
        pj_thread_sleep(1000);
 
1117
    }
 
1118
 
 
1119
    /* keep-alive test */
 
1120
    rc = keep_alive_test(&registrar_uri);
 
1121
    if (rc != 0)
 
1122
        goto on_return;
 
1123
 
 
1124
    /* Send error on refresh without destroy on callback */
 
1125
    rc = refresh_error(&registrar_uri, PJ_FALSE);
 
1126
    if (rc != 0)
 
1127
        goto on_return;
 
1128
 
 
1129
    /* Send error on refresh, destroy on callback */
 
1130
    rc = refresh_error(&registrar_uri, PJ_TRUE);
 
1131
    if (rc != 0)
 
1132
        goto on_return;
 
1133
 
 
1134
    /* Updating contact */
 
1135
    rc = update_test(&registrar_uri);
 
1136
    if (rc != 0)
 
1137
        goto on_return;
 
1138
 
 
1139
    /* Send error during auth, don't destroy on callback */
 
1140
    rc = auth_send_error(&registrar_uri, PJ_FALSE);
 
1141
    if (rc != 0)
 
1142
        goto on_return;
 
1143
 
 
1144
    /* Send error during auth, destroy on callback */
 
1145
    rc = auth_send_error(&registrar_uri, PJ_FALSE);
 
1146
    if (rc != 0)
 
1147
        goto on_return;
 
1148
 
 
1149
on_return:
 
1150
    if (registrar.mod.id != -1) {
 
1151
        pjsip_endpt_unregister_module(endpt, &registrar.mod);
 
1152
    }
 
1153
    if (send_mod.mod.id != -1) {
 
1154
        pjsip_endpt_unregister_module(endpt, &send_mod.mod);
 
1155
    }
 
1156
    if (udp) {
 
1157
        pjsip_transport_dec_ref(udp);
 
1158
    }
 
1159
    return rc;
 
1160
}
 
1161
 
 
1162