1
/* $Id: regc_test.c 4094 2012-04-26 09:31:00Z bennylp $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
25
#define THIS_FILE "regc_test.c"
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);
36
unsigned count_before_reject;
40
NULL, NULL, /* prev, next. */
41
{ "mod-send", 8 }, /* Name. */
43
PJSIP_MOD_PRIORITY_TRANSPORT_LAYER, /* Priority */
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() */
59
static pj_status_t mod_send_on_tx_request(pjsip_tx_data *tdata)
63
if (++send_mod.count > send_mod.count_before_reject)
70
/************************************************************************/
71
/* Registrar for testing */
72
static pj_bool_t regs_rx_request(pjsip_rx_data *rdata);
76
NONE, /* don't put Contact header */
77
EXACT, /* return exact contact */
78
MODIFIED, /* return modified Contact header */
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*/
90
pj_str_t more_contacts; /* Additional Contact headers to put*/
93
static struct registrar
96
struct registrar_cfg cfg;
97
unsigned response_cnt;
101
NULL, NULL, /* prev, next. */
102
{ "registrar", 9 }, /* Name. */
104
PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
109
®s_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() */
117
static pj_bool_t regs_rx_request(pjsip_rx_data *rdata)
119
pjsip_msg *msg = rdata->msg_info.msg;
124
if (msg->line.req.method.id != PJSIP_REGISTER_METHOD)
127
if (!registrar.cfg.respond)
130
pj_list_init(&hdr_list);
132
if (registrar.cfg.authenticate &&
133
pjsip_msg_find_hdr(msg, PJSIP_H_AUTHORIZATION, NULL)==NULL)
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\"");
139
hwww = pjsip_generic_string_hdr_create(rdata->tp_info.pool, &hname,
141
pj_list_push_back(&hdr_list, hwww);
146
if (registrar.cfg.contact_op == EXACT ||
147
registrar.cfg.contact_op == MODIFIED)
151
for (hsrc=msg->hdr.next; hsrc!=&msg->hdr; hsrc=hsrc->next) {
152
pjsip_contact_hdr *hdst;
154
if (hsrc->type != PJSIP_H_CONTACT)
157
hdst = (pjsip_contact_hdr*)
158
pjsip_hdr_clone(rdata->tp_info.pool, hsrc);
160
if (hdst->expires==0)
163
if (registrar.cfg.contact_op == MODIFIED) {
164
if (PJSIP_URI_SCHEME_IS_SIP(hdst->uri) ||
165
PJSIP_URI_SCHEME_IS_SIPS(hdst->uri))
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");
174
if (registrar.cfg.expires_param)
175
hdst->expires = registrar.cfg.expires_param;
177
pj_list_push_back(&hdr_list, hdst);
181
if (registrar.cfg.more_contacts.slen) {
182
pjsip_generic_string_hdr *hcontact;
183
const pj_str_t hname = pj_str("Contact");
185
hcontact = pjsip_generic_string_hdr_create(rdata->tp_info.pool, &hname,
186
®istrar.cfg.more_contacts);
187
pj_list_push_back(&hdr_list, hcontact);
190
if (registrar.cfg.expires) {
191
pjsip_expires_hdr *hexp;
193
hexp = pjsip_expires_hdr_create(rdata->tp_info.pool,
194
registrar.cfg.expires);
195
pj_list_push_back(&hdr_list, hexp);
198
registrar.response_cnt++;
200
code = registrar.cfg.status_code;
203
status = pjsip_endpt_respond(endpt, NULL, rdata, code, NULL,
204
&hdr_list, NULL, NULL);
205
pj_assert(status == PJ_SUCCESS);
211
/************************************************************************/
212
/* Client registration test session */
215
/* Result/expected result */
220
unsigned contact_cnt;
224
pj_bool_t destroy_on_cb;
229
/* Additional results */
235
static void client_cb(struct pjsip_regc_cbparam *param)
237
struct client *client = (struct client*) param->token;
238
pjsip_regc_info info;
241
client->done = PJ_TRUE;
243
status = pjsip_regc_get_info(param->regc, &info);
244
pj_assert(status == PJ_SUCCESS);
246
client->error = (param->status != PJ_SUCCESS);
247
client->code = param->code;
252
client->have_reg = info.auto_reg && info.interval>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;
259
if (client->destroy_on_cb)
260
pjsip_regc_destroy(param->regc);
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[],
273
pj_bool_t leave_session,
278
const pj_str_t aor = pj_str("<sip:regc-test@pjsip.org>");
279
pjsip_tx_data *tdata;
282
PJ_LOG(3,(THIS_FILE, " %s", title));
284
/* Modify registrar settings */
285
pj_memcpy(®istrar.cfg, srv_cfg, sizeof(*srv_cfg));
287
pj_bzero(&client_result, sizeof(client_result));
288
client_result.destroy_on_cb = client_cfg->destroy_on_cb;
290
status = pjsip_regc_create(endpt, &client_result, &client_cb, ®c);
291
if (status != PJ_SUCCESS)
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);
301
if (client_cfg->auth) {
302
pjsip_cred_info cred;
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");
311
status = pjsip_regc_set_credentials(regc, 1, &cred);
312
if (status != PJ_SUCCESS) {
313
pjsip_regc_destroy(regc);
319
status = pjsip_regc_register(regc, PJ_TRUE, &tdata);
320
if (status != PJ_SUCCESS) {
321
pjsip_regc_destroy(regc);
324
status = pjsip_regc_send(regc, tdata);
326
/* That's it, wait until the callback is sent */
327
for (i=0; i<600 && !client_result.done; ++i) {
331
if (!client_result.done) {
332
PJ_LOG(3,(THIS_FILE, " error: test has timed out"));
333
pjsip_regc_destroy(regc);
337
/* Destroy the regc, we're done with the test, unless we're
338
* instructed to leave the session open.
340
if (!leave_session && !client_cfg->destroy_on_cb)
341
pjsip_regc_destroy(regc);
343
/* Compare results with expected results */
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));
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));
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));
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));
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));
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));
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));
381
/* Looks like everything is okay. */
390
/************************************************************************/
391
/* Customized tests */
393
/* Check that client is sending register refresh */
394
static int keep_alive_test(const pj_str_t *registrar_uri)
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>");
410
ret = do_test("register refresh (takes ~40 secs)", &server_cfg, &client_cfg, registrar_uri,
411
1, &contact, TIMEOUT, PJ_TRUE, ®c);
415
/* Reset server response_cnt */
416
registrar.response_cnt = 0;
418
/* Wait until keep-alive/refresh is done */
419
for (i=0; i<(TIMEOUT-1)*10 && registrar.response_cnt==0; ++i) {
423
if (registrar.response_cnt==0) {
424
PJ_LOG(3,(THIS_FILE, " error: no refresh is received"));
428
if (client_result.error) {
429
PJ_LOG(3,(THIS_FILE, " error: got error"));
432
if (client_result.code != 200) {
433
PJ_LOG(3,(THIS_FILE, " error: expecting code=%d, got code=%d",
434
200, client_result.code));
437
if (client_result.expiration != TIMEOUT) {
438
PJ_LOG(3,(THIS_FILE, " error: expecting expiration=%d, got expiration=%d",
439
TIMEOUT, client_result.expiration));
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));
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));
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));
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));
464
pjsip_regc_destroy(regc);
469
/* Send error on refresh */
470
static int refresh_error(const pj_str_t *registrar_uri,
471
pj_bool_t destroy_on_cb)
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>");
486
ret = do_test("refresh error (takes ~40 secs)", &server_cfg, &client_cfg, registrar_uri,
487
1, &contact, TIMEOUT, PJ_TRUE, ®c);
491
/* Reset server response_cnt */
492
registrar.response_cnt = 0;
494
/* inject error for transmission */
496
send_mod.count_before_reject = 0;
498
/* reconfigure client */
499
client_result.done = PJ_FALSE;
500
client_result.destroy_on_cb = destroy_on_cb;
502
/* Wait until keep-alive/refresh is done */
503
for (i=0; i<TIMEOUT*10 && !client_result.done; ++i) {
507
send_mod.count_before_reject = 0xFFFF;
510
pjsip_regc_destroy(regc);
512
if (!client_result.done) {
513
PJ_LOG(3,(THIS_FILE, " error: test has timed out"));
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"));
527
/* Send error on refresh */
528
static int update_test(const pj_str_t *registrar_uri)
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[] = {
544
pjsip_contact_hdr *h1, *h2;
545
pjsip_sip_uri *u1, *u2;
548
pjsip_tx_data *tdata = NULL;
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, ®c);
559
* replace the contact with new one
561
PJ_LOG(3,(THIS_FILE, " replacing contact"));
562
status = pjsip_regc_update_contact(regc, 1, &contacts[1]);
563
if (status != PJ_SUCCESS) {
568
status = pjsip_regc_register(regc, PJ_TRUE, &tdata);
569
if (status != PJ_SUCCESS) {
574
/* Check that the REGISTER contains two Contacts:
575
* - <sip:a>;expires=0,
578
h1 = (pjsip_contact_hdr*)
579
pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
584
if ((void*)h1->next == (void*)&tdata->msg->hdr)
587
h2 = (pjsip_contact_hdr*)
588
pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, h1->next);
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)
601
u1 = (pjsip_sip_uri*) pjsip_uri_get_uri(h1->uri);
602
u2 = (pjsip_sip_uri*) pjsip_uri_get_uri(h2->uri);
604
if (*u1->host.ptr == 'a') {
605
if (h1->expires != 0) {
609
if (h2->expires == 0) {
615
pj_assert(*u1->host.ptr == 'b');
616
if (h1->expires == 0) {
620
if (h2->expires != 0) {
627
pjsip_tx_data_dec_ref(tdata);
633
* First loop, it will update with more contacts. Second loop
636
for (i=0; i<2; ++i) {
638
PJ_LOG(3,(THIS_FILE, " replacing with more contacts"));
640
PJ_LOG(3,(THIS_FILE, " updating contacts with same contacts"));
642
status = pjsip_regc_update_contact(regc, 2, &contacts[1]);
643
if (status != PJ_SUCCESS) {
648
status = pjsip_regc_register(regc, PJ_TRUE, &tdata);
649
if (status != PJ_SUCCESS) {
654
/* Check that the REGISTER contains two Contacts:
658
h1 = (pjsip_contact_hdr*)
659
pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
664
if ((void*)h1->next == (void*)&tdata->msg->hdr)
667
h2 = (pjsip_contact_hdr*)
668
pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, h1->next);
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)
681
/* both contacts must not have expires=0 parameter */
682
if (h1->expires == 0) {
686
if (h2->expires == 0) {
692
pjsip_tx_data_dec_ref(tdata);
697
if (tdata) pjsip_tx_data_dec_ref(tdata);
698
pjsip_regc_destroy(regc);
703
/* send error on authentication */
704
static int auth_send_error(const pj_str_t *registrar_uri,
705
pj_bool_t destroy_on_cb)
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>");
719
client_cfg.destroy_on_cb = destroy_on_cb;
721
/* inject error for second request retry */
723
send_mod.count_before_reject = 1;
725
ret = do_test("auth send error", &server_cfg, &client_cfg, registrar_uri,
726
1, &contact, TIMEOUT, PJ_TRUE, ®c);
728
send_mod.count_before_reject = 0xFFFF;
736
/************************************************************************/
747
unsigned check_contact;
748
unsigned add_xuid_param;
752
unsigned contact_cnt;
755
struct registrar_cfg server_cfg;
756
struct client client_cfg;
759
/* immediate error */
761
OFF, /* check_contact */
762
OFF, /* add_xuid_param */
763
"immediate error", /* title */
764
"sip:unresolved-host-xyy", /* alt_registrar */
766
{ "sip:user@127.0.0.1:5060" }, /* contacts[] */
769
/* registrar config: */
770
/* respond code auth contact exp_prm expires more_contacts */
771
{ PJ_FALSE, 200, PJ_FALSE, NONE, 0, 0, {NULL, 0}},
773
/* client expected results: */
774
/* error code have_reg expiration contact_cnt auth?*/
775
{ PJ_FALSE, 502, PJ_FALSE, -1, 0, PJ_FALSE}
780
OFF, /* check_contact */
781
OFF, /* add_xuid_param */
782
"timeout test (takes ~32 secs)",/* title */
783
NULL, /* alt_registrar */
785
{ "sip:user@127.0.0.1:5060" }, /* contacts[] */
788
/* registrar config: */
789
/* respond code auth contact exp_prm expires more_contacts */
790
{ PJ_FALSE, 200, PJ_FALSE, NONE, 0, 0, {NULL, 0}},
792
/* client expected results: */
793
/* error code have_reg expiration contact_cnt auth? */
794
{ PJ_FALSE, 408, PJ_FALSE, -1, 0, PJ_FALSE}
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
803
ON_OFF, /* check_contact */
804
ON_OFF, /* add_xuid_param */
806
NULL, /* alt_registrar */
808
{ "<sip:user@127.0.0.1:5060;transport=udp;x-param=1234>" }, /* contacts[] */
811
/* registrar config: */
812
/* respond code auth contact exp_prm expires more_contacts */
813
{ PJ_TRUE, 200, PJ_FALSE, EXACT, 75, 65, {NULL, 0}},
815
/* client expected results: */
816
/* error code have_reg expiration contact_cnt auth?*/
817
{ PJ_FALSE, 200, PJ_TRUE, 75, 1, PJ_FALSE}
820
/* Basic successful registration scenario with authentication
823
ON_OFF, /* check_contact */
824
ON_OFF, /* add_xuid_param */
825
"authentication", /* title */
826
NULL, /* alt_registrar */
828
{ "<sip:user@127.0.0.1:5060;transport=udp;x-param=1234>" }, /* contacts[] */
831
/* registrar config: */
832
/* respond code auth contact exp_prm expires more_contacts */
833
{ PJ_TRUE, 200, PJ_TRUE, EXACT, 75, 65, {NULL, 0}},
835
/* client expected results: */
836
/* error code have_reg expiration contact_cnt auth?*/
837
{ PJ_FALSE, 200, PJ_TRUE, 75, 1, PJ_TRUE}
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.
845
ON_OFF, /* check_contact */
846
ON, /* add_xuid_param */
847
"more bindings in response", /* title */
848
NULL, /* alt_registrar */
850
{ "<sip:user@127.0.0.1:5060;transport=udp>" }, /* contacts[] */
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}},
857
/* client expected results: */
858
/* error code have_reg expiration contact_cnt auth?*/
859
{ PJ_FALSE, 200, PJ_TRUE, 75, 2, PJ_FALSE}
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.
870
ON_OFF, /* check_contact */
871
ON_OFF, /* add_xuid_param */
872
"registrar modifies Contact header", /* title */
873
NULL, /* alt_registrar */
875
{ "<sip:user@127.0.0.1:5060>" }, /* contacts[] */
878
/* registrar config: */
879
/* respond code auth contact exp_prm expires more_contacts */
880
{ PJ_TRUE, 200, PJ_FALSE, MODIFIED, 75, 65, {NULL, 0}},
882
/* client expected results: */
883
/* error code have_reg expiration contact_cnt auth?*/
884
{ PJ_FALSE, 200, PJ_TRUE, 75, 1, PJ_FALSE}
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.
892
* In this case the expiration is taken from the expires param
893
* because add_xuid_param is enabled.
896
ON_OFF, /* check_contact */
897
ON, /* add_xuid_param */
898
"registrar modifies Contact header and add bindings", /* title */
899
NULL, /* alt_registrar */
901
{ "<sip:user@127.0.0.1:5060>" }, /* contacts[] */
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}},
908
/* client expected results: */
909
/* error code have_reg expiration contact_cnt auth?*/
910
{ PJ_FALSE, 200, PJ_TRUE, 75, 2, PJ_FALSE}
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
920
ON_OFF, /* check_contact */
921
ON_OFF, /* add_xuid_param */
922
"registrar replaces Contact header", /* title */
923
NULL, /* alt_registrar */
925
{ "<sip:user@127.0.0.1:5060>" }, /* contacts[] */
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}},
932
/* client expected results: */
933
/* error code have_reg expiration contact_cnt auth?*/
934
{ PJ_FALSE, 202, PJ_TRUE, 75, 1, PJ_FALSE}
938
/* a bad registrar returns completely different Contact (and
939
* all parameters are gone) and it also includes bindings from
941
* In this case the expiration is taken from the Expires header.
944
ON_OFF, /* check_contact */
945
ON_OFF, /* add_xuid_param */
946
" as above with additional bindings", /* title */
947
NULL, /* alt_registrar */
949
{ "<sip:user@127.0.0.1:5060>" }, /* contacts[] */
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}},
956
/* client expected results: */
957
/* error code have_reg expiration contact_cnt auth?*/
958
{ PJ_FALSE, 200, PJ_TRUE, 65, 2, PJ_FALSE}
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.
966
ON_OFF, /* check_contact */
967
ON_OFF, /* add_xuid_param */
968
"no Contact but with Expires", /* title */
969
NULL, /* alt_registrar */
971
{ "<sip:user@127.0.0.1:5060>" }, /* contacts[] */
974
/* registrar config: */
975
/* respond code auth contact exp_prm expires more_contacts */
976
{ PJ_TRUE, 200, PJ_FALSE, NONE, 0, 65, {NULL, 0}},
978
/* client expected results: */
979
/* error code have_reg expiration contact_cnt auth?*/
980
{ PJ_FALSE, 200, PJ_TRUE, 65, 0, PJ_FALSE}
983
/* Neither Contact header nor Expires header are present.
984
* In this case the expiration is taken from the request.
987
ON_OFF, /* check_contact */
988
ON_OFF, /* add_xuid_param */
989
"no Contact and no Expires", /* title */
990
NULL, /* alt_registrar */
992
{ "<sip:user@127.0.0.1:5060>" },/* contacts[] */
995
/* registrar config: */
996
/* respond code auth contact exp_prm expires more_contacts */
997
{ PJ_TRUE, 200, PJ_FALSE, NONE, 0, 0, {NULL, 0}},
999
/* client expected results: */
1000
/* error code have_reg expiration contact_cnt auth?*/
1001
{ PJ_FALSE, 200, PJ_TRUE, 600, 0, PJ_FALSE}
1006
pj_sockaddr_in addr;
1007
pjsip_transport *udp = NULL;
1009
char registrar_uri_buf[80];
1010
pj_str_t registrar_uri;
1013
pj_sockaddr_in_init(&addr, 0, 0);
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);
1022
rc = pjsip_udp_transport_start(endpt, NULL, NULL, 1, &udp);
1023
if (rc != PJ_SUCCESS) {
1024
app_perror(" error creating UDP transport", rc);
1029
port = pj_sockaddr_get_port(&udp->local_addr);
1032
/* Register registrar module */
1033
rc = pjsip_endpt_register_module(endpt, ®istrar.mod);
1034
if (rc != PJ_SUCCESS) {
1035
app_perror(" error registering module", rc);
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);
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);
1052
for (i=0; i<PJ_ARRAY_SIZE(test_rec); ++i) {
1053
struct test_rec *t = &test_rec[i];
1056
pj_str_t contacts[8];
1058
/* Fill in the registrar address if it's not specified */
1059
if (t->alt_registrar == NULL) {
1060
reg_uri = registrar_uri;
1062
reg_uri = pj_str(t->alt_registrar);
1065
/* Build contact pj_str_t's */
1066
for (j=0; j<t->contact_cnt; ++j) {
1067
contacts[j] = pj_str(t->contacts[j]);
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);
1074
/* Do tests with three combinations:
1075
* - check_contact on/off
1076
* - add_xuid_param on/off
1077
* - destroy_on_callback on/off
1079
for (x=1; x<=2; ++x) {
1082
if ((t->check_contact & x) == 0)
1085
pjsip_cfg()->regc.check_contact = (x-1);
1087
for (y=1; y<=2; ++y) {
1090
if ((t->add_xuid_param & y) == 0)
1093
pjsip_cfg()->regc.add_xuid_param = (y-1);
1095
for (z=0; z<=1; ++z) {
1096
char new_title[200];
1098
t->client_cfg.destroy_on_cb = z;
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
®_uri, t->contact_cnt, contacts,
1105
t->expires, PJ_FALSE, NULL);
1113
/* Sleep between test groups to avoid using up too many
1114
* active transactions.
1116
pj_thread_sleep(1000);
1119
/* keep-alive test */
1120
rc = keep_alive_test(®istrar_uri);
1124
/* Send error on refresh without destroy on callback */
1125
rc = refresh_error(®istrar_uri, PJ_FALSE);
1129
/* Send error on refresh, destroy on callback */
1130
rc = refresh_error(®istrar_uri, PJ_TRUE);
1134
/* Updating contact */
1135
rc = update_test(®istrar_uri);
1139
/* Send error during auth, don't destroy on callback */
1140
rc = auth_send_error(®istrar_uri, PJ_FALSE);
1144
/* Send error during auth, destroy on callback */
1145
rc = auth_send_error(®istrar_uri, PJ_FALSE);
1150
if (registrar.mod.id != -1) {
1151
pjsip_endpt_unregister_module(endpt, ®istrar.mod);
1153
if (send_mod.mod.id != -1) {
1154
pjsip_endpt_unregister_module(endpt, &send_mod.mod);
1157
pjsip_transport_dec_ref(udp);