00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 379392 $")
00029
00030 #include "include/sip.h"
00031 #include "include/sip_utils.h"
00032 #include "include/reqresp_parser.h"
00033
00034 #ifdef HAVE_XLOCALE_H
00035 locale_t c_locale;
00036 #endif
00037
00038
00039 int parse_uri_full(char *uri, const char *scheme, char **user, char **pass,
00040 char **hostport, struct uriparams *params, char **headers,
00041 char **residue)
00042 {
00043 char *userinfo = NULL;
00044 char *parameters = NULL;
00045 char *endparams = NULL;
00046 char *c = NULL;
00047 int error = 0;
00048
00049
00050
00051
00052
00053
00054 if (user) {
00055 *user = "";
00056 }
00057 if (pass) {
00058 *pass = "";
00059 }
00060 if (hostport) {
00061 *hostport = "";
00062 }
00063 if (headers) {
00064 *headers = "";
00065 }
00066 if (residue) {
00067 *residue = "";
00068 }
00069
00070
00071 if (ast_strlen_zero(uri)) {
00072 return -1;
00073 }
00074
00075 if (scheme) {
00076 int l;
00077 char *scheme2 = ast_strdupa(scheme);
00078 char *cur = strsep(&scheme2, ",");
00079 for (; !ast_strlen_zero(cur); cur = strsep(&scheme2, ",")) {
00080 l = strlen(cur);
00081 if (!strncasecmp(uri, cur, l)) {
00082 uri += l;
00083 break;
00084 }
00085 }
00086 if (ast_strlen_zero(cur)) {
00087 ast_debug(1, "No supported scheme found in '%s' using the scheme[s] %s\n", uri, scheme);
00088 error = -1;
00089 }
00090 }
00091
00092 if (!hostport) {
00093
00094
00095 userinfo = uri;
00096 } else {
00097 char *dom = "";
00098 if ((c = strchr(uri, '@'))) {
00099 *c++ = '\0';
00100 dom = c;
00101 userinfo = uri;
00102 uri = c;
00103 } else {
00104
00105 dom = uri;
00106 userinfo = "";
00107 }
00108
00109 *hostport = dom;
00110 }
00111
00112 if (pass && (c = strchr(userinfo, ':'))) {
00113 *c++ = '\0';
00114 *pass = c;
00115 } else if (pass) {
00116 *pass = "";
00117 }
00118
00119 if (user) {
00120 *user = userinfo;
00121 }
00122
00123 parameters = uri;
00124
00125 if ((c = strrchr(uri, '?'))) {
00126 *c++ = '\0';
00127 uri = c;
00128 if (headers) {
00129 *headers = c;
00130 }
00131 if ((c = strrchr(uri, ';'))) {
00132 *c++ = '\0';
00133 } else {
00134 c = strrchr(uri, '\0');
00135 }
00136 uri = c;
00137
00138
00139 } else if (headers) {
00140 *headers = "";
00141 }
00142
00143
00144 endparams = strchr(parameters,'\0');
00145 if ((c = strchr(parameters, ';'))) {
00146 *c++ = '\0';
00147 parameters = c;
00148 } else {
00149 parameters = endparams;
00150 }
00151
00152 if (params) {
00153 char *rem = parameters;
00154 char *label;
00155 char *value;
00156 int lr = 0;
00157
00158 params->transport = "";
00159 params->user = "";
00160 params->method = "";
00161 params->ttl = "";
00162 params->maddr = "";
00163 params->lr = 0;
00164
00165 rem = parameters;
00166
00167 while ((value = strchr(parameters, '=')) || (lr = !strncmp(parameters, "lr", 2))) {
00168
00169 if (lr) {
00170 value = parameters;
00171 } else {
00172 *value++ = '\0';
00173 }
00174 label = parameters;
00175 if ((c = strchr(value, ';'))) {
00176 *c++ = '\0';
00177 parameters = c;
00178 } else {
00179 parameters = endparams;
00180 }
00181
00182 if (!strcmp(label, "transport")) {
00183 params->transport = value;
00184 rem = parameters;
00185 } else if (!strcmp(label, "user")) {
00186 params->user = value;
00187 rem = parameters;
00188 } else if (!strcmp(label, "method")) {
00189 params->method = value;
00190 rem = parameters;
00191 } else if (!strcmp(label, "ttl")) {
00192 params->ttl = value;
00193 rem = parameters;
00194 } else if (!strcmp(label, "maddr")) {
00195 params->maddr = value;
00196 rem = parameters;
00197
00198 } else if ((!strcmp(label, "lr") && strcmp(value, "no") && strcmp(value, "off") && strcmp(value, "0") && strcmp(value, "")) || ((lr) && strcmp(value, "lr"))) {
00199 params->lr = 1;
00200 rem = parameters;
00201 } else {
00202 value--;
00203 *value = '=';
00204 if (c) {
00205 c--;
00206 *c = ';';
00207 }
00208 }
00209 }
00210 if (rem > uri) {
00211 uri = rem;
00212 }
00213
00214 }
00215
00216 if (residue) {
00217 *residue = uri;
00218 }
00219
00220 return error;
00221 }
00222
00223
00224 AST_TEST_DEFINE(sip_parse_uri_full_test)
00225 {
00226 int res = AST_TEST_PASS;
00227 char uri[1024];
00228 char *user, *pass, *hostport, *headers, *residue;
00229 struct uriparams params;
00230
00231 struct testdata {
00232 char *desc;
00233 char *uri;
00234 char *user;
00235 char *pass;
00236 char *hostport;
00237 char *headers;
00238 char *residue;
00239 struct uriparams params;
00240 AST_LIST_ENTRY(testdata) list;
00241 };
00242
00243
00244 struct testdata *testdataptr;
00245
00246 static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
00247
00248 struct testdata td1 = {
00249 .desc = "no headers",
00250 .uri = "sip:user:secret@host:5060;param=discard;transport=tcp;param2=residue",
00251 .user = "user",
00252 .pass = "secret",
00253 .hostport = "host:5060",
00254 .headers = "",
00255 .residue = "param2=residue",
00256 .params.transport = "tcp",
00257 .params.lr = 0,
00258 .params.user = ""
00259 };
00260
00261 struct testdata td2 = {
00262 .desc = "with headers",
00263 .uri = "sip:user:secret@host:5060;param=discard;transport=tcp;param2=discard2?header=blah&header2=blah2;param3=residue",
00264 .user = "user",
00265 .pass = "secret",
00266 .hostport = "host:5060",
00267 .headers = "header=blah&header2=blah2",
00268 .residue = "param3=residue",
00269 .params.transport = "tcp",
00270 .params.lr = 0,
00271 .params.user = ""
00272 };
00273
00274 struct testdata td3 = {
00275 .desc = "difficult user",
00276 .uri = "sip:-_.!~*'()&=+$,;?/:secret@host:5060;transport=tcp",
00277 .user = "-_.!~*'()&=+$,;?/",
00278 .pass = "secret",
00279 .hostport = "host:5060",
00280 .headers = "",
00281 .residue = "",
00282 .params.transport = "tcp",
00283 .params.lr = 0,
00284 .params.user = ""
00285 };
00286
00287 struct testdata td4 = {
00288 .desc = "difficult pass",
00289 .uri = "sip:user:-_.!~*'()&=+$,@host:5060;transport=tcp",
00290 .user = "user",
00291 .pass = "-_.!~*'()&=+$,",
00292 .hostport = "host:5060",
00293 .headers = "",
00294 .residue = "",
00295 .params.transport = "tcp",
00296 .params.lr = 0,
00297 .params.user = ""
00298 };
00299
00300 struct testdata td5 = {
00301 .desc = "difficult host",
00302 .uri = "sip:user:secret@1-1.a-1.:5060;transport=tcp",
00303 .user = "user",
00304 .pass = "secret",
00305 .hostport = "1-1.a-1.:5060",
00306 .headers = "",
00307 .residue = "",
00308 .params.transport = "tcp",
00309 .params.lr = 0,
00310 .params.user = ""
00311 };
00312
00313 struct testdata td6 = {
00314 .desc = "difficult params near transport",
00315 .uri = "sip:user:secret@host:5060;-_.!~*'()[]/:&+$=-_.!~*'()[]/:&+$;transport=tcp",
00316 .user = "user",
00317 .pass = "secret",
00318 .hostport = "host:5060",
00319 .headers = "",
00320 .residue = "",
00321 .params.transport = "tcp",
00322 .params.lr = 0,
00323 .params.user = ""
00324 };
00325
00326 struct testdata td7 = {
00327 .desc = "difficult params near headers",
00328 .uri = "sip:user:secret@host:5060;-_.!~*'()[]/:&+$=-_.!~*'()[]/:&+$?header=blah&header2=blah2;-_.!~*'()[]/:&+$=residue",
00329 .user = "user",
00330 .pass = "secret",
00331 .hostport = "host:5060",
00332 .headers = "header=blah&header2=blah2",
00333 .residue = "-_.!~*'()[]/:&+$=residue",
00334 .params.transport = "",
00335 .params.lr = 0,
00336 .params.user = ""
00337 };
00338
00339 struct testdata td8 = {
00340 .desc = "lr parameter",
00341 .uri = "sip:user:secret@host:5060;param=discard;lr?header=blah",
00342 .user = "user",
00343 .pass = "secret",
00344 .hostport = "host:5060",
00345 .headers = "header=blah",
00346 .residue = "",
00347 .params.transport = "",
00348 .params.lr = 1,
00349 .params.user = ""
00350 };
00351
00352 struct testdata td9 = {
00353 .desc = "alternative lr parameter",
00354 .uri = "sip:user:secret@host:5060;param=discard;lr=yes?header=blah",
00355 .user = "user",
00356 .pass = "secret",
00357 .hostport = "host:5060",
00358 .headers = "header=blah",
00359 .residue = "",
00360 .params.transport = "",
00361 .params.lr = 1,
00362 .params.user = ""
00363 };
00364
00365 struct testdata td10 = {
00366 .desc = "no lr parameter",
00367 .uri = "sip:user:secret@host:5060;paramlr=lr;lr=no;lr=off;lr=0;lr=;=lr;lrextra;lrparam2=lr?header=blah",
00368 .user = "user",
00369 .pass = "secret",
00370 .hostport = "host:5060",
00371 .headers = "header=blah",
00372 .residue = "",
00373 .params.transport = "",
00374 .params.lr = 0,
00375 .params.user = ""
00376 };
00377
00378
00379 AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &td1);
00380 AST_LIST_INSERT_TAIL(&testdatalist, &td2, list);
00381 AST_LIST_INSERT_TAIL(&testdatalist, &td3, list);
00382 AST_LIST_INSERT_TAIL(&testdatalist, &td4, list);
00383 AST_LIST_INSERT_TAIL(&testdatalist, &td5, list);
00384 AST_LIST_INSERT_TAIL(&testdatalist, &td6, list);
00385 AST_LIST_INSERT_TAIL(&testdatalist, &td7, list);
00386 AST_LIST_INSERT_TAIL(&testdatalist, &td8, list);
00387 AST_LIST_INSERT_TAIL(&testdatalist, &td9, list);
00388 AST_LIST_INSERT_TAIL(&testdatalist, &td10, list);
00389
00390
00391 switch (cmd) {
00392 case TEST_INIT:
00393 info->name = "sip_uri_full_parse_test";
00394 info->category = "/channels/chan_sip/";
00395 info->summary = "tests sip full uri parsing";
00396 info->description =
00397 "Tests full parsing of various URIs "
00398 "Verifies output matches expected behavior.";
00399 return AST_TEST_NOT_RUN;
00400 case TEST_EXECUTE:
00401 break;
00402 }
00403
00404 AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
00405 user = pass = hostport = headers = residue = NULL;
00406 params.transport = params.user = params.method = params.ttl = params.maddr = NULL;
00407 params.lr = 0;
00408
00409 ast_copy_string(uri,testdataptr->uri,sizeof(uri));
00410 if (parse_uri_full(uri, "sip:,sips:", &user,
00411 &pass, &hostport,
00412 ¶ms,
00413 &headers,
00414 &residue) ||
00415 (user && strcmp(testdataptr->user, user)) ||
00416 (pass && strcmp(testdataptr->pass, pass)) ||
00417 (hostport && strcmp(testdataptr->hostport, hostport)) ||
00418 (headers && strcmp(testdataptr->headers, headers)) ||
00419 (residue && strcmp(testdataptr->residue, residue)) ||
00420 (strcmp(testdataptr->params.transport,params.transport)) ||
00421 (testdataptr->params.lr != params.lr) ||
00422 (strcmp(testdataptr->params.user,params.user))
00423 ) {
00424 ast_test_status_update(test, "Sub-Test: %s, failed.\n", testdataptr->desc);
00425 res = AST_TEST_FAIL;
00426 }
00427 }
00428
00429
00430 return res;
00431 }
00432
00433
00434 int parse_uri(char *uri, const char *scheme, char **user, char **pass,
00435 char **hostport, char **transport) {
00436 int ret;
00437 char *headers;
00438 struct uriparams params;
00439
00440 headers = NULL;
00441 ret = parse_uri_full(uri, scheme, user, pass, hostport, ¶ms, &headers, NULL);
00442 if (transport) {
00443 *transport=params.transport;
00444 }
00445 return ret;
00446 }
00447
00448 AST_TEST_DEFINE(sip_parse_uri_test)
00449 {
00450 int res = AST_TEST_PASS;
00451 char *name, *pass, *hostport, *transport;
00452 char uri1[] = "sip:name@host";
00453 char uri2[] = "sip:name@host;transport=tcp";
00454 char uri3[] = "sip:name:secret@host;transport=tcp";
00455 char uri4[] = "sip:name:secret@host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
00456
00457 char uri6[] = "sip:name:secret@host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
00458 char uri7[] = "sip:name:secret@host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
00459 char uri8[] = "sip:host";
00460 char uri9[] = "sip:host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
00461 char uri10[] = "host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
00462 char uri11[] = "host";
00463
00464 switch (cmd) {
00465 case TEST_INIT:
00466 info->name = "sip_uri_parse_test";
00467 info->category = "/channels/chan_sip/";
00468 info->summary = "tests sip uri parsing";
00469 info->description =
00470 "Tests parsing of various URIs "
00471 "Verifies output matches expected behavior.";
00472 return AST_TEST_NOT_RUN;
00473 case TEST_EXECUTE:
00474 break;
00475 }
00476
00477
00478 name = pass = hostport = transport = NULL;
00479 if (parse_uri(uri1, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00480 strcmp(name, "name") ||
00481 !ast_strlen_zero(pass) ||
00482 strcmp(hostport, "host") ||
00483 !ast_strlen_zero(transport)) {
00484 ast_test_status_update(test, "Test 1: simple uri failed. \n");
00485 res = AST_TEST_FAIL;
00486 }
00487
00488
00489 name = pass = hostport = transport = NULL;
00490 if (parse_uri(uri2, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00491 strcmp(name, "name") ||
00492 !ast_strlen_zero(pass) ||
00493 strcmp(hostport, "host") ||
00494 strcmp(transport, "tcp")) {
00495 ast_test_status_update(test, "Test 2: uri with addtion of tcp transport failed. \n");
00496 res = AST_TEST_FAIL;
00497 }
00498
00499
00500 name = pass = hostport = transport = NULL;
00501 if (parse_uri(uri3, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00502 strcmp(name, "name") ||
00503 strcmp(pass, "secret") ||
00504 strcmp(hostport, "host") ||
00505 strcmp(transport, "tcp")) {
00506 ast_test_status_update(test, "Test 3: uri with addition of secret failed.\n");
00507 res = AST_TEST_FAIL;
00508 }
00509
00510
00511 name = pass = hostport = transport = NULL;
00512 if (parse_uri(uri4, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00513 strcmp(name, "name") ||
00514 strcmp(pass, "secret") ||
00515 strcmp(hostport, "host:port") ||
00516 strcmp(transport, "tcp")) {
00517 ast_test_status_update(test, "Test 4: add port and unparsed header field failed.\n");
00518 res = AST_TEST_FAIL;
00519 }
00520
00521
00522 name = pass = hostport = transport = NULL;
00523 if (!parse_uri(NULL, "sip:,sips:", &name, &pass, &hostport, &transport)) {
00524 ast_test_status_update(test, "Test 5: passing a NULL uri failed.\n");
00525 res = AST_TEST_FAIL;
00526 }
00527
00528
00529 name = pass = hostport = transport = NULL;
00530 if (parse_uri(uri6, "sip:,sips:", NULL, NULL, NULL, NULL)) {
00531 ast_test_status_update(test, "Test 6: passing NULL output parameters failed.\n");
00532 res = AST_TEST_FAIL;
00533 }
00534
00535
00536 name = pass = hostport = transport = NULL;
00537 if (parse_uri(uri7, "sip:,sips:", &name, NULL, &hostport, NULL) ||
00538 strcmp(name, "name:secret") ||
00539 strcmp(hostport, "host:port")) {
00540
00541 ast_test_status_update(test, "Test 7: providing no port and secret output parameters failed.\n");
00542 res = AST_TEST_FAIL;
00543 }
00544
00545
00546 name = pass = hostport = transport = NULL;
00547 if (parse_uri(uri8, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00548 strcmp(hostport, "host") ||
00549 !ast_strlen_zero(name)) {
00550 ast_test_status_update(test, "Test 8: add port and unparsed header field failed.\n");
00551 res = AST_TEST_FAIL;
00552 }
00553
00554
00555 name = pass = hostport = transport = NULL;
00556 if (parse_uri(uri9, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00557 !ast_strlen_zero(name) ||
00558 !ast_strlen_zero(pass) ||
00559 strcmp(hostport, "host:port") ||
00560 strcmp(transport, "tcp")) {
00561 ast_test_status_update(test, "Test 9: hostport only uri failed \n");
00562 res = AST_TEST_FAIL;
00563 }
00564
00565
00566
00567
00568 name = pass = hostport = transport = NULL;
00569 if (!parse_uri(uri10, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00570 !ast_strlen_zero(name) ||
00571 !ast_strlen_zero(pass) ||
00572 strcmp(hostport, "host:port") ||
00573 strcmp(transport, "tcp")) {
00574 ast_test_status_update(test, "Test 10: missing \"sip:sips:\" scheme failed\n");
00575 res = AST_TEST_FAIL;
00576 }
00577
00578
00579
00580
00581 name = pass = hostport = transport = NULL;
00582 if (!parse_uri(uri11, "sip:,sips:", &name, &pass, &hostport, &transport) ||
00583 !ast_strlen_zero(name) ||
00584 !ast_strlen_zero(pass) ||
00585 strcmp(hostport, "host") ||
00586 !ast_strlen_zero(transport)) {
00587 ast_test_status_update(test, "Test 11: simple uri with missing scheme failed. \n");
00588 res = AST_TEST_FAIL;
00589 }
00590
00591 return res;
00592 }
00593
00594
00595
00596
00597
00598 const char *get_calleridname(const char *input, char *output, size_t outputsize)
00599 {
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 char *orig_output = output;
00624 const char *orig_input = input;
00625
00626 if (!output || !outputsize) {
00627
00628 return input;
00629 }
00630
00631
00632 input = ast_skip_blanks(input);
00633
00634
00635 *orig_output = '\0';
00636
00637
00638 --outputsize;
00639
00640
00641 if (!input || *input == '<') {
00642 return input;
00643 }
00644
00645
00646 if (input[0] == '"') {
00647 input++;
00648
00649 for (; *input; ++input) {
00650 if (*input == '"') {
00651 break;
00652 } else if (*input == 0x5c) {
00653 ++input;
00654 if (!*input) {
00655 break;
00656 }
00657 if ((unsigned char) *input > 0x7f || *input == 0xa || *input == 0xd) {
00658 continue;
00659 }
00660 } else if ((*input != 0x9 && (unsigned char) *input < 0x20)
00661 || *input == 0x7f) {
00662 continue;
00663 }
00664
00665 if (0 < outputsize) {
00666
00667 *output++ = *input;
00668 --outputsize;
00669 }
00670 }
00671
00672
00673 if (*input != '"') {
00674 ast_log(LOG_WARNING, "No ending quote for display-name was found\n");
00675 *orig_output = '\0';
00676 return orig_input;
00677 }
00678
00679
00680 ++input;
00681
00682
00683 *output = '\0';
00684 } else {
00685 for (; *input; ++input) {
00686
00687 if ((*input >= '0' && *input <= '9') || (*input >= 'A' && *input <= 'Z')
00688 || (*input >= 'a' && *input <= 'z') || *input == '-' || *input == '.'
00689 || *input == '!' || *input == '%' || *input == '*' || *input == '_'
00690 || *input == '+' || *input == '`' || *input == '\'' || *input == '~'
00691 || *input == 0x9 || *input == ' ') {
00692 if (0 < outputsize) {
00693
00694 *output++ = *input;
00695 --outputsize;
00696 }
00697 } else if (*input == '<') {
00698
00699 break;
00700 } else if (*input == ':') {
00701
00702 *orig_output = '\0';
00703 return orig_input;
00704 } else {
00705 continue;
00706 }
00707 }
00708
00709 if (*input != '<') {
00710 *orig_output = '\0';
00711 return orig_input;
00712 }
00713
00714
00715 do {
00716 *output-- = '\0';
00717 } while (orig_output <= output && (*output == 0x9 || *output == ' '));
00718 }
00719
00720 return input;
00721 }
00722
00723 AST_TEST_DEFINE(get_calleridname_test)
00724 {
00725 int res = AST_TEST_PASS;
00726 const char *in1 = " \" quoted-text internal \\\" quote \"<stuff>";
00727 const char *in2 = " token text with no quotes <stuff>";
00728 const char *overflow1 = " \"quoted-text overflow 1234567890123456789012345678901234567890\" <stuff>";
00729 const char *overflow2 = " non-quoted text overflow 1234567890123456789012345678901234567890 <stuff>";
00730 const char *noendquote = " \"quoted-text no end <stuff>";
00731 const char *addrspec = " sip:blah@blah";
00732 const char *no_quotes_no_brackets = "blah@blah";
00733 const char *after_dname;
00734 char dname[40];
00735
00736 switch (cmd) {
00737 case TEST_INIT:
00738 info->name = "sip_get_calleridname_test";
00739 info->category = "/channels/chan_sip/";
00740 info->summary = "decodes callerid name from sip header";
00741 info->description = "Decodes display-name field of sip header. Checks for valid output and expected failure cases.";
00742 return AST_TEST_NOT_RUN;
00743 case TEST_EXECUTE:
00744 break;
00745 }
00746
00747
00748 after_dname = get_calleridname(in1, dname, sizeof(dname));
00749 ast_test_status_update(test, "display-name1: %s\nafter: %s\n", dname, after_dname);
00750 if (strcmp(dname, " quoted-text internal \" quote ")) {
00751 ast_test_status_update(test, "display-name1 test failed\n");
00752 res = AST_TEST_FAIL;
00753 }
00754
00755
00756 after_dname = get_calleridname(in2, dname, sizeof(dname));
00757 ast_test_status_update(test, "display-name2: %s\nafter: %s\n", dname, after_dname);
00758 if (strcmp(dname, "token text with no quotes")) {
00759 ast_test_status_update(test, "display-name2 test failed\n");
00760 res = AST_TEST_FAIL;
00761 }
00762
00763
00764 after_dname = get_calleridname(overflow1, dname, sizeof(dname));
00765 ast_test_status_update(test, "overflow display-name1: %s\nafter: %s\n", dname, after_dname);
00766 if (strcmp(dname, "quoted-text overflow 123456789012345678")) {
00767 ast_test_status_update(test, "overflow display-name1 test failed\n");
00768 res = AST_TEST_FAIL;
00769 }
00770
00771
00772 after_dname = get_calleridname(overflow2, dname, sizeof(dname));
00773 ast_test_status_update(test, "overflow display-name2: %s\nafter: %s\n", dname, after_dname);
00774 if (strcmp(dname, "non-quoted text overflow 12345678901234")) {
00775 ast_test_status_update(test, "overflow display-name2 test failed\n");
00776 res = AST_TEST_FAIL;
00777 }
00778
00779
00780 after_dname = get_calleridname(noendquote, dname, sizeof(dname));
00781 ast_test_status_update(test, "noendquote display-name1: %s\nafter: %s\n", dname, after_dname);
00782 if (*dname != '\0' && after_dname != noendquote) {
00783 ast_test_status_update(test, "no end quote for quoted-text display-name failed\n");
00784 res = AST_TEST_FAIL;
00785 }
00786
00787
00788 after_dname = get_calleridname(addrspec, dname, sizeof(dname));
00789 ast_test_status_update(test, "addr-spec display-name1: %s\nafter: %s\n", dname, after_dname);
00790 if (*dname != '\0' && after_dname != addrspec) {
00791 ast_test_status_update(test, "detection of addr-spec failed\n");
00792 res = AST_TEST_FAIL;
00793 }
00794
00795
00796 after_dname = get_calleridname(no_quotes_no_brackets, dname, sizeof(dname));
00797 ast_test_status_update(test, "no_quotes_no_brackets display-name1: %s\nafter: %s\n", dname, after_dname);
00798 if (*dname != '\0' && after_dname != no_quotes_no_brackets) {
00799 ast_test_status_update(test, "detection of addr-spec failed\n");
00800 res = AST_TEST_FAIL;
00801 }
00802
00803 return res;
00804 }
00805
00806 int get_name_and_number(const char *hdr, char **name, char **number)
00807 {
00808 char header[256];
00809 char tmp_name[50];
00810 char *tmp_number = NULL;
00811 char *hostport = NULL;
00812 char *dummy = NULL;
00813
00814 if (!name || !number || ast_strlen_zero(hdr)) {
00815 return -1;
00816 }
00817
00818 *number = NULL;
00819 *name = NULL;
00820 ast_copy_string(header, hdr, sizeof(header));
00821
00822
00823 get_calleridname(header, tmp_name, sizeof(tmp_name));
00824
00825
00826 tmp_number = get_in_brackets(header);
00827
00828
00829 if (parse_uri(tmp_number, "sip:,sips:", &tmp_number, &dummy, &hostport, NULL) || ast_strlen_zero(tmp_number)) {
00830 ast_log(LOG_ERROR, "can not parse name and number from sip header.\n");
00831 return -1;
00832 }
00833
00834
00835 *number = ast_strdup(tmp_number);
00836 ast_uri_decode(*number);
00837
00838
00839 if (!ast_strlen_zero(tmp_name)) {
00840 *name = ast_strdup(tmp_name);
00841 }
00842
00843 return 0;
00844 }
00845
00846 AST_TEST_DEFINE(get_name_and_number_test)
00847 {
00848 int res = AST_TEST_PASS;
00849 char *name = NULL;
00850 char *number = NULL;
00851 const char *in1 = "NAME <sip:NUMBER@place>";
00852 const char *in2 = "\"NA><ME\" <sip:NUMBER@place>";
00853 const char *in3 = "NAME";
00854 const char *in4 = "<sip:NUMBER@place>";
00855 const char *in5 = "This is a screwed up string <sip:LOLCLOWNS<sip:>@place>";
00856
00857 switch (cmd) {
00858 case TEST_INIT:
00859 info->name = "sip_get_name_and_number_test";
00860 info->category = "/channels/chan_sip/";
00861 info->summary = "Tests getting name and number from sip header";
00862 info->description =
00863 "Runs through various test situations in which a name and "
00864 "and number can be retrieved from a sip header.";
00865 return AST_TEST_NOT_RUN;
00866 case TEST_EXECUTE:
00867 break;
00868 }
00869
00870
00871 number = name = NULL;
00872 if ((get_name_and_number(in1, &name, &number)) ||
00873 strcmp(name, "NAME") ||
00874 strcmp(number, "NUMBER")) {
00875
00876 ast_test_status_update(test, "Test 1, simple get name and number failed.\n");
00877 res = AST_TEST_FAIL;
00878 }
00879 ast_free(name);
00880 ast_free(number);
00881
00882
00883 number = name = NULL;
00884 if ((get_name_and_number(in2, &name, &number)) ||
00885 strcmp(name, "NA><ME") ||
00886 strcmp(number, "NUMBER")) {
00887
00888 ast_test_status_update(test, "Test 2, get quoted name and number failed.\n");
00889 res = AST_TEST_FAIL;
00890 }
00891 ast_free(name);
00892 ast_free(number);
00893
00894
00895 number = name = NULL;
00896 if (!(get_name_and_number(in3, &name, &number))) {
00897
00898 ast_test_status_update(test, "Test 3, get name only was expected to fail but did not.\n");
00899 res = AST_TEST_FAIL;
00900 }
00901 ast_free(name);
00902 ast_free(number);
00903
00904
00905 number = name = NULL;
00906 if ((get_name_and_number(in4, &name, &number)) ||
00907 !ast_strlen_zero(name) ||
00908 strcmp(number, "NUMBER")) {
00909
00910 ast_test_status_update(test, "Test 4, get number with no name present failed.\n");
00911 res = AST_TEST_FAIL;
00912 }
00913 ast_free(name);
00914 ast_free(number);
00915
00916
00917 number = name = NULL;
00918 if (!(get_name_and_number(in5, &name, &number)) ||
00919 !ast_strlen_zero(name) ||
00920 !ast_strlen_zero(number)) {
00921
00922 ast_test_status_update(test, "Test 5, processing malformed string failed.\n");
00923 res = AST_TEST_FAIL;
00924 }
00925 ast_free(name);
00926 ast_free(number);
00927
00928
00929 number = name = NULL;
00930 if (!(get_name_and_number(in5, NULL, NULL))) {
00931
00932 ast_test_status_update(test, "Test 6, NULL output parameters failed.\n");
00933 res = AST_TEST_FAIL;
00934 }
00935
00936
00937 number = name = NULL;
00938 if (!(get_name_and_number(NULL, &name, &number)) ||
00939 !ast_strlen_zero(name) ||
00940 !ast_strlen_zero(number)) {
00941
00942 ast_test_status_update(test, "Test 7, NULL input parameter failed.\n");
00943 res = AST_TEST_FAIL;
00944 }
00945 ast_free(name);
00946 ast_free(number);
00947
00948 return res;
00949 }
00950
00951 int get_in_brackets_const(const char *src,const char **start,int *length)
00952 {
00953 const char *parse = src;
00954 const char *first_bracket;
00955 const char *second_bracket;
00956
00957 if (start == NULL) {
00958 return -1;
00959 }
00960 if (length == NULL) {
00961 return -1;
00962 }
00963 *start = NULL;
00964 *length = -1;
00965 if (ast_strlen_zero(src)) {
00966 return 1;
00967 }
00968
00969
00970
00971
00972
00973 while ( (first_bracket = strchr(parse, '<')) ) {
00974 const char *first_quote = strchr(parse, '"');
00975 first_bracket++;
00976 if (!first_quote || first_quote >= first_bracket) {
00977 break;
00978 }
00979
00980 parse = find_closing_quote(first_quote + 1, NULL);
00981 if (!*parse) {
00982 ast_log(LOG_WARNING, "No closing quote found in '%s'\n", src);
00983 return -1;
00984 }
00985 parse++;
00986 }
00987
00988
00989
00990 if (!first_bracket) {
00991 ast_log(LOG_WARNING, "No opening bracket found in '%s'\n", src);
00992 return 1;
00993 }
00994
00995 if ((second_bracket = strchr(first_bracket, '>'))) {
00996 *start = first_bracket;
00997 *length = second_bracket - first_bracket;
00998 return 0;
00999 }
01000 ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", src);
01001 return -1;
01002 }
01003
01004 int get_in_brackets_full(char *tmp,char **out,char **residue)
01005 {
01006 const char *parse = tmp;
01007 char *first_bracket;
01008 char *second_bracket;
01009
01010 if (out) {
01011 *out = "";
01012 }
01013 if (residue) {
01014 *residue = "";
01015 }
01016
01017 if (ast_strlen_zero(tmp)) {
01018 return 1;
01019 }
01020
01021
01022
01023
01024
01025 while ( (first_bracket = strchr(parse, '<')) ) {
01026 char *first_quote = strchr(parse, '"');
01027 first_bracket++;
01028 if (!first_quote || first_quote >= first_bracket) {
01029 break;
01030 }
01031
01032 parse = find_closing_quote(first_quote + 1, NULL);
01033 if (!*parse) {
01034 ast_log(LOG_WARNING, "No closing quote found in '%s'\n", tmp);
01035 return -1;
01036 }
01037 parse++;
01038 }
01039
01040
01041
01042
01043 if (first_bracket) {
01044 parse = first_bracket;
01045 } else {
01046 parse = tmp;
01047 }
01048
01049 if ((second_bracket = strchr(parse, '>'))) {
01050 *second_bracket++ = '\0';
01051 if (out) {
01052 *out = (char *) parse;
01053 }
01054 if (residue) {
01055 *residue = second_bracket;
01056 }
01057 return 0;
01058 }
01059
01060 if ((first_bracket)) {
01061 ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", tmp);
01062 return -1;
01063 }
01064
01065 if (out) {
01066 *out = tmp;
01067 }
01068
01069 return 1;
01070 }
01071
01072 char *get_in_brackets(char *tmp)
01073 {
01074 char *out;
01075
01076 if ((get_in_brackets_full(tmp, &out, NULL))) {
01077 return tmp;
01078 }
01079 return out;
01080 }
01081
01082 AST_TEST_DEFINE(get_in_brackets_test)
01083 {
01084 int res = AST_TEST_PASS;
01085 char in_brackets[] = "sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah";
01086 char no_name[] = "<sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
01087 char quoted_string[] = "\"I'm a quote stri><ng\" <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
01088 char missing_end_quote[] = "\"I'm a quote string <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
01089 char name_no_quotes[] = "name not in quotes <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
01090 char no_end_bracket[] = "name not in quotes <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah";
01091 char no_name_no_brackets[] = "sip:name@host";
01092 char missing_start_bracket[] = "sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
01093 char *uri = NULL;
01094
01095 switch (cmd) {
01096 case TEST_INIT:
01097 info->name = "sip_get_in_brackets_test";
01098 info->category = "/channels/chan_sip/";
01099 info->summary = "Tests getting a sip uri in <> brackets within a sip header.";
01100 info->description =
01101 "Runs through various test situations in which a sip uri "
01102 "in angle brackets needs to be retrieved";
01103 return AST_TEST_NOT_RUN;
01104 case TEST_EXECUTE:
01105 break;
01106 }
01107
01108
01109 if (!(uri = get_in_brackets(no_name)) || strcmp(uri, in_brackets)) {
01110 ast_test_status_update(test, "Test 1, simple get in brackets failed. %s\n", uri);
01111 res = AST_TEST_FAIL;
01112 }
01113
01114
01115 if (!(uri = get_in_brackets(quoted_string)) || strcmp(uri, in_brackets)) {
01116 ast_test_status_update(test, "Test 2, get in brackets with quoted string in front failed. %s\n", uri);
01117 res = AST_TEST_FAIL;
01118 }
01119
01120
01121 if (!(uri = get_in_brackets(missing_end_quote)) || !strcmp(uri, in_brackets)) {
01122 ast_test_status_update(test, "Test 3, missing end quote failed. %s\n", uri);
01123 res = AST_TEST_FAIL;
01124 }
01125
01126
01127 if (!(uri = get_in_brackets(name_no_quotes)) || strcmp(uri, in_brackets)) {
01128 ast_test_status_update(test, "Test 4, passing name not in quotes failed. %s\n", uri);
01129 res = AST_TEST_FAIL;
01130 }
01131
01132
01133 if (!(uri = get_in_brackets(no_end_bracket)) || !strcmp(uri, in_brackets)) {
01134 ast_test_status_update(test, "Test 5, no end bracket failed. %s\n", uri);
01135 res = AST_TEST_FAIL;
01136 }
01137
01138
01139 if (get_in_brackets(NULL)) {
01140 ast_test_status_update(test, "Test 6, NULL input failed.\n");
01141 res = AST_TEST_FAIL;
01142 }
01143
01144
01145 if (!(uri = get_in_brackets(no_name_no_brackets)) || strcmp(uri, "sip:name@host")) {
01146 ast_test_status_update(test, "Test 7 failed. %s\n", uri);
01147 res = AST_TEST_FAIL;
01148 }
01149
01150
01151 if (!(uri = get_in_brackets(missing_start_bracket)) || strcmp(uri, in_brackets)) {
01152 ast_test_status_update(test, "Test 8 failed. %s\n", uri);
01153 res = AST_TEST_FAIL;
01154 }
01155
01156 return res;
01157 }
01158
01159
01160 int parse_name_andor_addr(char *uri, const char *scheme, char **name,
01161 char **user, char **pass, char **hostport,
01162 struct uriparams *params, char **headers,
01163 char **residue)
01164 {
01165 char buf[1024];
01166 char **residue2 = residue;
01167 char *orig_uri = uri;
01168 int ret;
01169
01170 buf[0] = '\0';
01171 if (name) {
01172 uri = (char *) get_calleridname(uri, buf, sizeof(buf));
01173 }
01174 ret = get_in_brackets_full(uri, &uri, residue);
01175 if (ret == 0) {
01176
01177
01178
01179
01180 if (residue && **residue) {
01181
01182 *residue = *residue + 1;
01183 }
01184 residue2 = NULL;
01185 }
01186
01187 if (name) {
01188 if (buf[0]) {
01189
01190
01191
01192
01193
01194 strcpy(orig_uri, buf);
01195 *name = orig_uri;
01196 } else {
01197 *name = "";
01198 }
01199 }
01200
01201 return parse_uri_full(uri, scheme, user, pass, hostport, params, headers, residue2);
01202 }
01203
01204 AST_TEST_DEFINE(parse_name_andor_addr_test)
01205 {
01206 int res = AST_TEST_PASS;
01207 char uri[1024];
01208 char *name, *user, *pass, *hostport, *headers, *residue;
01209 struct uriparams params;
01210
01211 struct testdata {
01212 char *desc;
01213 char *uri;
01214 char *name;
01215 char *user;
01216 char *pass;
01217 char *hostport;
01218 char *headers;
01219 char *residue;
01220 struct uriparams params;
01221 AST_LIST_ENTRY(testdata) list;
01222 };
01223
01224 struct testdata *testdataptr;
01225
01226 static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
01227
01228 struct testdata td1 = {
01229 .desc = "quotes and brackets",
01230 .uri = "\"name :@ \" <sip:user:secret@host:5060;param=discard;transport=tcp>;tag=tag",
01231 .name = "name :@ ",
01232 .user = "user",
01233 .pass = "secret",
01234 .hostport = "host:5060",
01235 .headers = "",
01236 .residue = "tag=tag",
01237 .params.transport = "tcp",
01238 .params.lr = 0,
01239 .params.user = ""
01240 };
01241
01242 struct testdata td2 = {
01243 .desc = "no quotes",
01244 .uri = "givenname familyname <sip:user:secret@host:5060;param=discard;transport=tcp>;expires=3600",
01245 .name = "givenname familyname",
01246 .user = "user",
01247 .pass = "secret",
01248 .hostport = "host:5060",
01249 .headers = "",
01250 .residue = "expires=3600",
01251 .params.transport = "tcp",
01252 .params.lr = 0,
01253 .params.user = ""
01254 };
01255
01256 struct testdata td3 = {
01257 .desc = "no brackets",
01258 .uri = "sip:user:secret@host:5060;param=discard;transport=tcp;q=1",
01259 .name = "",
01260 .user = "user",
01261 .pass = "secret",
01262 .hostport = "host:5060",
01263 .headers = "",
01264 .residue = "q=1",
01265 .params.transport = "tcp",
01266 .params.lr = 0,
01267 .params.user = ""
01268 };
01269
01270 struct testdata td4 = {
01271 .desc = "just host",
01272 .uri = "sips:host",
01273 .name = "",
01274 .user = "",
01275 .pass = "",
01276 .hostport = "host",
01277 .headers = "",
01278 .residue = "",
01279 .params.transport = "",
01280 .params.lr = 0,
01281 .params.user = ""
01282 };
01283
01284
01285 AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &td1);
01286 AST_LIST_INSERT_TAIL(&testdatalist, &td2, list);
01287 AST_LIST_INSERT_TAIL(&testdatalist, &td3, list);
01288 AST_LIST_INSERT_TAIL(&testdatalist, &td4, list);
01289
01290
01291 switch (cmd) {
01292 case TEST_INIT:
01293 info->name = "parse_name_andor_addr_test";
01294 info->category = "/channels/chan_sip/";
01295 info->summary = "tests parsing of name_andor_addr abnf structure";
01296 info->description =
01297 "Tests parsing of abnf name-andor-addr = name-addr / addr-spec "
01298 "Verifies output matches expected behavior.";
01299 return AST_TEST_NOT_RUN;
01300 case TEST_EXECUTE:
01301 break;
01302 }
01303
01304 AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
01305 name = user = pass = hostport = headers = residue = NULL;
01306 params.transport = params.user = params.method = params.ttl = params.maddr = NULL;
01307 params.lr = 0;
01308 ast_copy_string(uri,testdataptr->uri,sizeof(uri));
01309 if (parse_name_andor_addr(uri, "sip:,sips:",
01310 &name,
01311 &user,
01312 &pass,
01313 &hostport,
01314 ¶ms,
01315 &headers,
01316 &residue) ||
01317 (name && strcmp(testdataptr->name, name)) ||
01318 (user && strcmp(testdataptr->user, user)) ||
01319 (pass && strcmp(testdataptr->pass, pass)) ||
01320 (hostport && strcmp(testdataptr->hostport, hostport)) ||
01321 (headers && strcmp(testdataptr->headers, headers)) ||
01322 (residue && strcmp(testdataptr->residue, residue)) ||
01323 (strcmp(testdataptr->params.transport,params.transport)) ||
01324 (strcmp(testdataptr->params.user,params.user))
01325 ) {
01326 ast_test_status_update(test, "Sub-Test: %s,failed.\n", testdataptr->desc);
01327 res = AST_TEST_FAIL;
01328 }
01329 }
01330
01331 return res;
01332 }
01333
01334 int get_comma(char *in, char **out)
01335 {
01336 char *c;
01337 char *parse = in;
01338 if (out) {
01339 *out = in;
01340 }
01341
01342
01343 while (*parse) {
01344 if ((c = strchr(parse, '"'))) {
01345 in = (char *)find_closing_quote((const char *)c + 1, NULL);
01346 if (!*in) {
01347 ast_log(LOG_WARNING, "No closing quote found in '%s'\n", c);
01348 return -1;
01349 } else {
01350 break;
01351 }
01352 } else {
01353 break;
01354 }
01355 parse++;
01356 }
01357 parse = in;
01358
01359
01360 if ((c = strchr(parse,'@'))) {
01361 parse = c+1;
01362 }
01363 if ((out) && (c = strchr(parse,','))) {
01364 *c++ = '\0';
01365 *out = c;
01366 return 0;
01367 }
01368 return 1;
01369 }
01370
01371 int parse_contact_header(char *contactheader, struct contactliststruct *contactlist)
01372 {
01373 int res;
01374 int last;
01375 char *comma;
01376 char *residue;
01377 char *param;
01378 char *value;
01379 struct contact *split_contact = NULL;
01380
01381 if (*contactheader == '*') {
01382 return 1;
01383 }
01384
01385 split_contact = ast_calloc(1, sizeof(*split_contact));
01386
01387 AST_LIST_HEAD_SET_NOLOCK(contactlist, split_contact);
01388 while ((last = get_comma(contactheader, &comma)) != -1) {
01389 res = parse_name_andor_addr(contactheader, "sip:,sips:",
01390 &split_contact->name, &split_contact->user,
01391 &split_contact->pass, &split_contact->hostport,
01392 &split_contact->params, &split_contact->headers,
01393 &residue);
01394 if (res == -1) {
01395 return res;
01396 }
01397
01398
01399 split_contact->expires = split_contact->q = "";
01400
01401 while ((value = strchr(residue,'='))) {
01402 *value++ = '\0';
01403
01404 param = residue;
01405 if ((residue = strchr(value,';'))) {
01406 *residue++ = '\0';
01407 } else {
01408 residue = "";
01409 }
01410
01411 if (!strcmp(param,"expires")) {
01412 split_contact->expires = value;
01413 } else if (!strcmp(param,"q")) {
01414 split_contact->q = value;
01415 }
01416 }
01417
01418 if (last) {
01419 return 0;
01420 }
01421 contactheader = comma;
01422
01423 split_contact = ast_calloc(1, sizeof(*split_contact));
01424 AST_LIST_INSERT_TAIL(contactlist, split_contact, list);
01425 }
01426 return last;
01427 }
01428
01429 AST_TEST_DEFINE(parse_contact_header_test)
01430 {
01431 int res = AST_TEST_PASS;
01432 char contactheader[1024];
01433 int star;
01434 struct contactliststruct contactlist;
01435 struct contactliststruct *contactlistptr=&contactlist;
01436
01437 struct testdata {
01438 char *desc;
01439 char *contactheader;
01440 int star;
01441 struct contactliststruct *contactlist;
01442
01443 AST_LIST_ENTRY(testdata) list;
01444 };
01445
01446 struct testdata *testdataptr;
01447 struct contact *tdcontactptr;
01448 struct contact *contactptr;
01449
01450 static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
01451 struct contactliststruct contactlist1, contactlist2;
01452
01453 struct testdata td1 = {
01454 .desc = "single contact",
01455 .contactheader = "\"name :@;?&,\" <sip:user:secret@host:5082;param=discard;transport=tcp>;expires=3600",
01456 .contactlist = &contactlist1,
01457 .star = 0
01458 };
01459 struct contact contact11 = {
01460 .name = "name :@;?&,",
01461 .user = "user",
01462 .pass = "secret",
01463 .hostport = "host:5082",
01464 .params.transport = "tcp",
01465 .params.ttl = "",
01466 .params.lr = 0,
01467 .headers = "",
01468 .expires = "3600",
01469 .q = ""
01470 };
01471
01472 struct testdata td2 = {
01473 .desc = "multiple contacts",
01474 .contactheader = "sip:,user1,:,secret1,@host1;ttl=7;q=1;expires=3600,sips:host2",
01475 .contactlist = &contactlist2,
01476 .star = 0,
01477 };
01478 struct contact contact21 = {
01479 .name = "",
01480 .user = ",user1,",
01481 .pass = ",secret1,",
01482 .hostport = "host1",
01483 .params.transport = "",
01484 .params.ttl = "7",
01485 .params.lr = 0,
01486 .headers = "",
01487 .expires = "3600",
01488 .q = "1"
01489 };
01490 struct contact contact22 = {
01491 .name = "",
01492 .user = "",
01493 .pass = "",
01494 .hostport = "host2",
01495 .params.transport = "",
01496 .params.ttl = "",
01497 .params.lr = 0,
01498 .headers = "",
01499 .expires = "",
01500 .q = ""
01501 };
01502
01503 struct testdata td3 = {
01504 .desc = "star - all contacts",
01505 .contactheader = "*",
01506 .star = 1,
01507 .contactlist = NULL
01508 };
01509
01510 AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &td1);
01511 AST_LIST_INSERT_TAIL(&testdatalist, &td2, list);
01512 AST_LIST_INSERT_TAIL(&testdatalist, &td3, list);
01513
01514 AST_LIST_HEAD_SET_NOLOCK(&contactlist1, &contact11);
01515
01516 AST_LIST_HEAD_SET_NOLOCK(&contactlist2, &contact21);
01517 AST_LIST_INSERT_TAIL(&contactlist2, &contact22, list);
01518
01519
01520 switch (cmd) {
01521 case TEST_INIT:
01522 info->name = "parse_contact_header_test";
01523 info->category = "/channels/chan_sip/";
01524 info->summary = "tests parsing of sip contact header";
01525 info->description =
01526 "Tests parsing of a contact header including those with multiple contacts "
01527 "Verifies output matches expected behavior.";
01528 return AST_TEST_NOT_RUN;
01529 case TEST_EXECUTE:
01530 break;
01531 }
01532
01533 AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
01534 ast_copy_string(contactheader,testdataptr->contactheader,sizeof(contactheader));
01535 star = parse_contact_header(contactheader,contactlistptr);
01536 if (testdataptr->star) {
01537
01538 if (!star) {
01539 ast_test_status_update(test, "Sub-Test: %s,failed.\n", testdataptr->desc);
01540 res = AST_TEST_FAIL;
01541 break;
01542 }
01543 } else {
01544 contactptr = AST_LIST_FIRST(contactlistptr);
01545 AST_LIST_TRAVERSE(testdataptr->contactlist, tdcontactptr, list) {
01546 if (!contactptr ||
01547 strcmp(tdcontactptr->name, contactptr->name) ||
01548 strcmp(tdcontactptr->user, contactptr->user) ||
01549 strcmp(tdcontactptr->pass, contactptr->pass) ||
01550 strcmp(tdcontactptr->hostport, contactptr->hostport) ||
01551 strcmp(tdcontactptr->headers, contactptr->headers) ||
01552 strcmp(tdcontactptr->expires, contactptr->expires) ||
01553 strcmp(tdcontactptr->q, contactptr->q) ||
01554 strcmp(tdcontactptr->params.transport, contactptr->params.transport) ||
01555 strcmp(tdcontactptr->params.ttl, contactptr->params.ttl) ||
01556 (tdcontactptr->params.lr != contactptr->params.lr)
01557 ) {
01558 ast_test_status_update(test, "Sub-Test: %s,failed.\n", testdataptr->desc);
01559 res = AST_TEST_FAIL;
01560 break;
01561 }
01562
01563 contactptr = AST_LIST_NEXT(contactptr,list);
01564 }
01565 }
01566 }
01567
01568 return res;
01569 }
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583 unsigned int parse_sip_options(const char *options, char *unsupported, size_t unsupported_len)
01584 {
01585 char *next, *sep;
01586 char *temp;
01587 int i, found, supported;
01588 unsigned int profile = 0;
01589
01590 char *out = unsupported;
01591 size_t outlen = unsupported_len;
01592 char *cur_out = out;
01593
01594 if (out && (outlen > 0)) {
01595 memset(out, 0, outlen);
01596 }
01597
01598 if (ast_strlen_zero(options) )
01599 return 0;
01600
01601 temp = ast_strdupa(options);
01602
01603 ast_debug(3, "Begin: parsing SIP \"Supported: %s\"\n", options);
01604
01605 for (next = temp; next; next = sep) {
01606 found = FALSE;
01607 supported = FALSE;
01608 if ((sep = strchr(next, ',')) != NULL) {
01609 *sep++ = '\0';
01610 }
01611
01612
01613 next = ast_strip(next);
01614
01615 if (ast_strlen_zero(next)) {
01616 continue;
01617 }
01618
01619 ast_debug(3, "Found SIP option: -%s-\n", next);
01620 for (i = 0; i < ARRAY_LEN(sip_options); i++) {
01621 if (!strcasecmp(next, sip_options[i].text)) {
01622 profile |= sip_options[i].id;
01623 if (sip_options[i].supported == SUPPORTED) {
01624 supported = TRUE;
01625 }
01626 found = TRUE;
01627 ast_debug(3, "Matched SIP option: %s\n", next);
01628 break;
01629 }
01630 }
01631
01632
01633 if (!supported && out && outlen) {
01634 size_t copylen = strlen(next);
01635 size_t cur_outlen = strlen(out);
01636
01637
01638 if ((cur_outlen + copylen + 2) < outlen) {
01639
01640 if (cur_outlen) {
01641 *cur_out = ',';
01642 cur_out++;
01643 cur_outlen++;
01644 }
01645 ast_copy_string(cur_out, next, (outlen - cur_outlen));
01646 cur_out += copylen;
01647 }
01648 }
01649
01650 if (!found) {
01651 profile |= SIP_OPT_UNKNOWN;
01652 if (!strncasecmp(next, "x-", 2))
01653 ast_debug(3, "Found private SIP option, not supported: %s\n", next);
01654 else
01655 ast_debug(3, "Found no match for SIP option: %s (Please file bug report!)\n", next);
01656 }
01657 }
01658
01659 return profile;
01660 }
01661
01662 AST_TEST_DEFINE(sip_parse_options_test)
01663 {
01664 int res = AST_TEST_PASS;
01665 char unsupported[64];
01666 unsigned int option_profile = 0;
01667 struct testdata {
01668 char *name;
01669 char *input_options;
01670 char *expected_unsupported;
01671 unsigned int expected_profile;
01672 AST_LIST_ENTRY(testdata) list;
01673 };
01674
01675 struct testdata *testdataptr;
01676 static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
01677
01678 struct testdata test1 = {
01679 .name = "test_all_unsupported",
01680 .input_options = "unsupported1,,, ,unsupported2,unsupported3,unsupported4",
01681 .expected_unsupported = "unsupported1,unsupported2,unsupported3,unsupported4",
01682 .expected_profile = SIP_OPT_UNKNOWN,
01683 };
01684 struct testdata test2 = {
01685 .name = "test_all_unsupported_one_supported",
01686 .input_options = " unsupported1, replaces, unsupported3 , , , ,unsupported4",
01687 .expected_unsupported = "unsupported1,unsupported3,unsupported4",
01688 .expected_profile = SIP_OPT_UNKNOWN | SIP_OPT_REPLACES
01689 };
01690 struct testdata test3 = {
01691 .name = "test_two_supported_two_unsupported",
01692 .input_options = ",, timer ,replaces ,unsupported3,unsupported4",
01693 .expected_unsupported = "unsupported3,unsupported4",
01694 .expected_profile = SIP_OPT_UNKNOWN | SIP_OPT_REPLACES | SIP_OPT_TIMER,
01695 };
01696
01697 struct testdata test4 = {
01698 .name = "test_all_supported",
01699 .input_options = "timer,replaces",
01700 .expected_unsupported = "",
01701 .expected_profile = SIP_OPT_REPLACES | SIP_OPT_TIMER,
01702 };
01703
01704 struct testdata test5 = {
01705 .name = "test_all_supported_redundant",
01706 .input_options = "timer,replaces,timer,replace,timer,replaces",
01707 .expected_unsupported = "",
01708 .expected_profile = SIP_OPT_REPLACES | SIP_OPT_TIMER,
01709 };
01710 struct testdata test6 = {
01711 .name = "test_buffer_overflow",
01712 .input_options = "unsupported1,replaces,timer,unsupported4,unsupported_huge____"
01713 "____________________________________,__________________________________________"
01714 "________________________________________________",
01715 .expected_unsupported = "unsupported1,unsupported4",
01716 .expected_profile = SIP_OPT_UNKNOWN | SIP_OPT_REPLACES | SIP_OPT_TIMER,
01717 };
01718 struct testdata test7 = {
01719 .name = "test_null_input",
01720 .input_options = NULL,
01721 .expected_unsupported = "",
01722 .expected_profile = 0,
01723 };
01724 struct testdata test8 = {
01725 .name = "test_whitespace_input",
01726 .input_options = " ",
01727 .expected_unsupported = "",
01728 .expected_profile = 0,
01729 };
01730 struct testdata test9 = {
01731 .name = "test_whitespace_plus_option_input",
01732 .input_options = " , , ,timer , , , , , ",
01733 .expected_unsupported = "",
01734 .expected_profile = SIP_OPT_TIMER,
01735 };
01736
01737 switch (cmd) {
01738 case TEST_INIT:
01739 info->name = "sip_parse_options_test";
01740 info->category = "/channels/chan_sip/";
01741 info->summary = "Tests parsing of sip options";
01742 info->description =
01743 "Tests parsing of SIP options from supported and required "
01744 "header fields. Verifies when unsupported options are encountered "
01745 "that they are appended to the unsupported out buffer and that the "
01746 "correct bit field representnig the option profile is returned.";
01747 return AST_TEST_NOT_RUN;
01748 case TEST_EXECUTE:
01749 break;
01750 }
01751
01752 AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &test1);
01753 AST_LIST_INSERT_TAIL(&testdatalist, &test2, list);
01754 AST_LIST_INSERT_TAIL(&testdatalist, &test3, list);
01755 AST_LIST_INSERT_TAIL(&testdatalist, &test4, list);
01756 AST_LIST_INSERT_TAIL(&testdatalist, &test5, list);
01757 AST_LIST_INSERT_TAIL(&testdatalist, &test6, list);
01758 AST_LIST_INSERT_TAIL(&testdatalist, &test7, list);
01759 AST_LIST_INSERT_TAIL(&testdatalist, &test8, list);
01760 AST_LIST_INSERT_TAIL(&testdatalist, &test9, list);
01761
01762
01763 AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
01764 option_profile = parse_sip_options(testdataptr->input_options, unsupported, ARRAY_LEN(unsupported));
01765 if (option_profile != testdataptr->expected_profile ||
01766 strcmp(unsupported, testdataptr->expected_unsupported)) {
01767 ast_test_status_update(test, "Test with output buffer \"%s\", expected unsupported: %s actual unsupported:"
01768 "%s expected bit profile: %x actual bit profile: %x\n",
01769 testdataptr->name,
01770 testdataptr->expected_unsupported,
01771 unsupported,
01772 testdataptr->expected_profile,
01773 option_profile);
01774 res = AST_TEST_FAIL;
01775 } else {
01776 ast_test_status_update(test, "\"%s\" passed got expected unsupported: %s and bit profile: %x\n",
01777 testdataptr->name,
01778 unsupported,
01779 option_profile);
01780 }
01781
01782 option_profile = parse_sip_options(testdataptr->input_options, NULL, 0);
01783 if (option_profile != testdataptr->expected_profile) {
01784 ast_test_status_update(test, "NULL output test \"%s\", expected bit profile: %x actual bit profile: %x\n",
01785 testdataptr->name,
01786 testdataptr->expected_profile,
01787 option_profile);
01788 res = AST_TEST_FAIL;
01789 } else {
01790 ast_test_status_update(test, "\"%s\" with NULL output buf passed, bit profile: %x\n",
01791 testdataptr->name,
01792 option_profile);
01793 }
01794 }
01795
01796 return res;
01797 }
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816 static int sip_uri_params_cmp(const char *input1, const char *input2)
01817 {
01818 char *params1 = NULL;
01819 char *params2 = NULL;
01820 char *pos1;
01821 char *pos2;
01822 int zerolength1 = 0;
01823 int zerolength2 = 0;
01824 int maddrmatch = 0;
01825 int ttlmatch = 0;
01826 int usermatch = 0;
01827 int methodmatch = 0;
01828
01829 if (ast_strlen_zero(input1)) {
01830 zerolength1 = 1;
01831 } else {
01832 params1 = ast_strdupa(input1);
01833 }
01834 if (ast_strlen_zero(input2)) {
01835 zerolength2 = 1;
01836 } else {
01837 params2 = ast_strdupa(input2);
01838 }
01839
01840
01841
01842
01843 if (zerolength1 && zerolength2) {
01844 return 0;
01845 }
01846
01847 for (pos1 = strsep(¶ms1, ";"); pos1; pos1 = strsep(¶ms1, ";")) {
01848 char *value1 = pos1;
01849 char *name1 = strsep(&value1, "=");
01850 char *params2dup = NULL;
01851 int matched = 0;
01852 if (!value1) {
01853 value1 = "";
01854 }
01855
01856
01857
01858
01859 if (!zerolength2) {
01860 params2dup = ast_strdupa(params2);
01861 }
01862 for (pos2 = strsep(¶ms2dup, ";"); pos2; pos2 = strsep(¶ms2dup, ";")) {
01863 char *name2 = pos2;
01864 char *value2 = strchr(pos2, '=');
01865 if (!value2) {
01866 value2 = "";
01867 } else {
01868 *value2++ = '\0';
01869 }
01870 if (!strcasecmp(name1, name2)) {
01871 if (strcasecmp(value1, value2)) {
01872 goto fail;
01873 } else {
01874 matched = 1;
01875 break;
01876 }
01877 }
01878 }
01879
01880 if (!strcasecmp(name1, "maddr")) {
01881 if (matched) {
01882 maddrmatch = 1;
01883 } else {
01884 goto fail;
01885 }
01886 } else if (!strcasecmp(name1, "ttl")) {
01887 if (matched) {
01888 ttlmatch = 1;
01889 } else {
01890 goto fail;
01891 }
01892 } else if (!strcasecmp(name1, "user")) {
01893 if (matched) {
01894 usermatch = 1;
01895 } else {
01896 goto fail;
01897 }
01898 } else if (!strcasecmp(name1, "method")) {
01899 if (matched) {
01900 methodmatch = 1;
01901 } else {
01902 goto fail;
01903 }
01904 }
01905 }
01906
01907
01908
01909
01910
01911 for (pos2 = strsep(¶ms2, ";"); pos2; pos2 = strsep(¶ms2, ";")) {
01912 char *value2 = pos2;
01913 char *name2 = strsep(&value2, "=");
01914 if (!value2) {
01915 value2 = "";
01916 }
01917 if ((!strcasecmp(name2, "maddr") && !maddrmatch) ||
01918 (!strcasecmp(name2, "ttl") && !ttlmatch) ||
01919 (!strcasecmp(name2, "user") && !usermatch) ||
01920 (!strcasecmp(name2, "method") && !methodmatch)) {
01921 goto fail;
01922 }
01923 }
01924 return 0;
01925
01926 fail:
01927 return 1;
01928 }
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942 static int sip_uri_headers_cmp(const char *input1, const char *input2)
01943 {
01944 char *headers1 = NULL;
01945 char *headers2 = NULL;
01946 int zerolength1 = 0;
01947 int zerolength2 = 0;
01948 int different = 0;
01949 char *header1;
01950
01951 if (ast_strlen_zero(input1)) {
01952 zerolength1 = 1;
01953 } else {
01954 headers1 = ast_strdupa(input1);
01955 }
01956
01957 if (ast_strlen_zero(input2)) {
01958 zerolength2 = 1;
01959 } else {
01960 headers2 = ast_strdupa(input2);
01961 }
01962
01963
01964
01965
01966 if (zerolength1 != zerolength2) {
01967 return 1;
01968 }
01969
01970 if (zerolength1 && zerolength2)
01971 return 0;
01972
01973
01974
01975
01976
01977 if (strlen(headers1) != strlen(headers2)) {
01978 return 1;
01979 }
01980
01981 for (header1 = strsep(&headers1, "&"); header1; header1 = strsep(&headers1, "&")) {
01982 if (!strcasestr(headers2, header1)) {
01983 different = 1;
01984 break;
01985 }
01986 }
01987
01988 return different;
01989 }
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007 static int sip_uri_domain_cmp(const char *host1, const char *host2)
02008 {
02009 struct ast_sockaddr addr1;
02010 struct ast_sockaddr addr2;
02011 int addr1_parsed;
02012 int addr2_parsed;
02013
02014 addr1_parsed = ast_sockaddr_parse(&addr1, host1, 0);
02015 addr2_parsed = ast_sockaddr_parse(&addr2, host2, 0);
02016
02017 if (addr1_parsed != addr2_parsed) {
02018
02019
02020
02021 return 1;
02022 }
02023
02024
02025
02026
02027
02028
02029 if (!addr1_parsed) {
02030 #ifdef HAVE_XLOCALE_H
02031 if(!c_locale) {
02032 return strcasecmp(host1, host2);
02033 } else {
02034 return strcasecmp_l(host1, host2, c_locale);
02035 }
02036 #else
02037 return strcasecmp(host1, host2);
02038 #endif
02039 }
02040
02041
02042 return ast_sockaddr_cmp(&addr1, &addr2);
02043 }
02044
02045 int sip_uri_cmp(const char *input1, const char *input2)
02046 {
02047 char *uri1;
02048 char *uri2;
02049 char *uri_scheme1;
02050 char *uri_scheme2;
02051 char *host1;
02052 char *host2;
02053 char *params1;
02054 char *params2;
02055 char *headers1;
02056 char *headers2;
02057
02058
02059
02060
02061
02062
02063 if (!input1 || !input2) {
02064 return 1;
02065 }
02066
02067 uri1 = ast_strdupa(input1);
02068 uri2 = ast_strdupa(input2);
02069
02070 ast_uri_decode(uri1);
02071 ast_uri_decode(uri2);
02072
02073 uri_scheme1 = strsep(&uri1, ":");
02074 uri_scheme2 = strsep(&uri2, ":");
02075
02076 if (strcmp(uri_scheme1, uri_scheme2)) {
02077 return 1;
02078 }
02079
02080
02081
02082
02083
02084 if (strcmp(uri_scheme1, "sip") && strcmp(uri_scheme1, "sips")) {
02085 return 1;
02086 }
02087
02088 if (ast_strlen_zero(uri1) || ast_strlen_zero(uri2)) {
02089 return 1;
02090 }
02091
02092 if ((host1 = strchr(uri1, '@'))) {
02093 *host1++ = '\0';
02094 }
02095 if ((host2 = strchr(uri2, '@'))) {
02096 *host2++ = '\0';
02097 }
02098
02099
02100
02101
02102 if ((host1 && !host2) ||
02103 (host2 && !host1) ||
02104 (host1 && host2 && strcmp(uri1, uri2))) {
02105 return 1;
02106 }
02107
02108 if (!host1) {
02109 host1 = uri1;
02110 }
02111 if (!host2) {
02112 host2 = uri2;
02113 }
02114
02115
02116
02117
02118
02119 if ((params1 = strchr(host1, ';'))) {
02120 *params1++ = '\0';
02121 }
02122 if ((params2 = strchr(host2, ';'))) {
02123 *params2++ = '\0';
02124 }
02125
02126
02127
02128
02129 if ((headers1 = strchr(S_OR(params1, host1), '?'))) {
02130 *headers1++ = '\0';
02131 }
02132 if ((headers2 = strchr(S_OR(params2, host2), '?'))) {
02133 *headers2++ = '\0';
02134 }
02135
02136 if (sip_uri_domain_cmp(host1, host2)) {
02137 return 1;
02138 }
02139
02140
02141 if (sip_uri_headers_cmp(headers1, headers2)) {
02142 return 1;
02143 }
02144
02145
02146 return sip_uri_params_cmp(params1, params2);
02147 }
02148
02149 #define URI_CMP_MATCH 0
02150 #define URI_CMP_NOMATCH 1
02151
02152 AST_TEST_DEFINE(sip_uri_cmp_test)
02153 {
02154 static const struct {
02155 const char *uri1;
02156 const char *uri2;
02157 int expected_result;
02158 } uri_cmp_tests [] = {
02159
02160 { "sip:bob@example.com", "sip:bob@example.com", URI_CMP_MATCH },
02161
02162 { "sip:alice@example.com", "sip:bob@example.com", URI_CMP_NOMATCH },
02163
02164 { "sip:bob@example.com", "sip:bob@examplez.com", URI_CMP_NOMATCH },
02165
02166 { "sip:bob@1.2.3.4", "sip:bob@1.2.3.4", URI_CMP_MATCH },
02167
02168 { "sip:bob@1.2.3.4", "sip:bob@001.002.003.004", URI_CMP_MATCH },
02169
02170 { "sip:bob@127.0.0.1", "sip:bob@localhost", URI_CMP_NOMATCH },
02171
02172 { "sip:bob@[::1]", "sip:bob@localhost", URI_CMP_NOMATCH },
02173
02174 { "sip:bob@[2001:db8::1234]", "sip:bob@[2001:db8::1234]", URI_CMP_MATCH },
02175
02176 { "sip:bob@[2001:db8::1234]", "sip:bob@[2001:0db8::1234]", URI_CMP_MATCH },
02177
02178 { "sip:bob@1.2.3.4:5060", "sip:bob@1.2.3.4:5061", URI_CMP_NOMATCH },
02179
02180 { "sip:bob@1.2.3.4:5060", "sip:bob@1.2.3.4", URI_CMP_NOMATCH },
02181
02182 { "sip:bob@[2001:db8:1234]:5060", "sip:bob@[2001:db8:1234]", URI_CMP_NOMATCH },
02183
02184 { "sip:bob@example.com", "sip:BOB@example.com", URI_CMP_NOMATCH },
02185
02186 { "sip:bob@example.com", "sip:bob@EXAMPLE.COM", URI_CMP_MATCH },
02187
02188 { "sip:bob@example.com?header1=value1&header2=value2", "sip:bob@example.com?header1=value1&header2=value2", URI_CMP_MATCH },
02189
02190 { "sip:bob@example.com?header1=value1&header2=value2", "sip:bob@example.com", URI_CMP_NOMATCH },
02191
02192 { "sip:bob@example.com?header1=value1&header2=value2", "sip:bob@example.com?header1=value1&header2=value3", URI_CMP_NOMATCH },
02193
02194 { "sip:bob@example.com;param1=value1;param2=value2", "sip:bob@example.com;param1=value1;param2=value2", URI_CMP_MATCH },
02195
02196 { "sip:bob@example.com;param2=value2;param1=value1", "sip:bob@example.com;param1=value1;param2=value2", URI_CMP_MATCH },
02197
02198 { "sip:bob@example.com;param1=value1;param2=value2", "sip:bob@example.com", URI_CMP_MATCH },
02199
02200 { "sip:bob@example.com;param1=value1;param2=value2", "sip:bob@example.com;param1=value1;param2=value3", URI_CMP_NOMATCH },
02201
02202 { "sip:bob@example.com;param1=value1;maddr=192.168.0.1", "sip:bob@example.com;param1=value1", URI_CMP_NOMATCH },
02203
02204 { "sip:bob@example.com;param1=value1;maddr=192.168.0.1", "sip:bob@example.com;param1=value1;maddr=192.168.0.1", URI_CMP_MATCH },
02205
02206 { "sips:bob@example.com", "sip:bob@example.com", URI_CMP_NOMATCH },
02207
02208 { "bob@example.com", "bob@example.com", URI_CMP_NOMATCH },
02209
02210 { "sip", "sips", URI_CMP_NOMATCH },
02211
02212 { "sip", "sip", URI_CMP_NOMATCH },
02213
02214 { "", "", URI_CMP_NOMATCH },
02215
02216 { "", NULL, URI_CMP_NOMATCH },
02217 };
02218 int i;
02219 int test_res = AST_TEST_PASS;
02220 switch (cmd) {
02221 case TEST_INIT:
02222 info->name = "sip_uri_cmp_test";
02223 info->category = "/channels/chan_sip/";
02224 info->summary = "Tests comparison of SIP URIs";
02225 info->description = "Several would-be tricky URI comparisons are performed";
02226 return AST_TEST_NOT_RUN;
02227 case TEST_EXECUTE:
02228 break;
02229 }
02230
02231 for (i = 0; i < ARRAY_LEN(uri_cmp_tests); ++i) {
02232 int cmp_res1;
02233 int cmp_res2;
02234 if ((cmp_res1 = sip_uri_cmp(uri_cmp_tests[i].uri1, uri_cmp_tests[i].uri2))) {
02235
02236
02237
02238 cmp_res1 = URI_CMP_NOMATCH;
02239 }
02240 if (cmp_res1 != uri_cmp_tests[i].expected_result) {
02241 ast_test_status_update(test, "Unexpected comparison result for URIs %s and %s. "
02242 "Expected %s but got %s\n", uri_cmp_tests[i].uri1, uri_cmp_tests[i].uri2,
02243 uri_cmp_tests[i].expected_result == URI_CMP_MATCH ? "Match" : "No Match",
02244 cmp_res1 == URI_CMP_MATCH ? "Match" : "No Match");
02245 test_res = AST_TEST_FAIL;
02246 }
02247
02248
02249
02250
02251 if ((cmp_res2 = sip_uri_cmp(uri_cmp_tests[i].uri2, uri_cmp_tests[i].uri1))) {
02252
02253
02254
02255 cmp_res2 = URI_CMP_NOMATCH;
02256 }
02257 if (cmp_res2 != uri_cmp_tests[i].expected_result) {
02258 ast_test_status_update(test, "Unexpected comparison result for URIs %s and %s. "
02259 "Expected %s but got %s\n", uri_cmp_tests[i].uri2, uri_cmp_tests[i].uri1,
02260 uri_cmp_tests[i].expected_result == URI_CMP_MATCH ? "Match" : "No Match",
02261 cmp_res2 == URI_CMP_MATCH ? "Match" : "No Match");
02262 test_res = AST_TEST_FAIL;
02263 }
02264 }
02265
02266 return test_res;
02267 }
02268
02269 void free_via(struct sip_via *v)
02270 {
02271 if (!v) {
02272 return;
02273 }
02274
02275 ast_free(v->via);
02276 ast_free(v);
02277 }
02278
02279 struct sip_via *parse_via(const char *header)
02280 {
02281 struct sip_via *v = ast_calloc(1, sizeof(*v));
02282 char *via, *parm;
02283
02284 if (!v) {
02285 return NULL;
02286 }
02287
02288 v->via = ast_strdup(header);
02289 v->ttl = 1;
02290
02291 via = v->via;
02292
02293 if (ast_strlen_zero(via)) {
02294 ast_log(LOG_ERROR, "received request without a Via header\n");
02295 free_via(v);
02296 return NULL;
02297 }
02298
02299
02300 via = strsep(&via, ",");
02301
02302
02303 v->protocol = strsep(&via, " \t\r\n");
02304 if (ast_strlen_zero(v->protocol)) {
02305 ast_log(LOG_ERROR, "missing sent-protocol in Via header\n");
02306 free_via(v);
02307 return NULL;
02308 }
02309 v->protocol = ast_skip_blanks(v->protocol);
02310
02311 if (via) {
02312 via = ast_skip_blanks(via);
02313 }
02314
02315
02316 v->sent_by = strsep(&via, "; \t\r\n");
02317 if (ast_strlen_zero(v->sent_by)) {
02318 ast_log(LOG_ERROR, "missing sent-by in Via header\n");
02319 free_via(v);
02320 return NULL;
02321 }
02322 v->sent_by = ast_skip_blanks(v->sent_by);
02323
02324
02325
02326 if (((parm = strchr(v->sent_by, ']')) && *(++parm) == ':') || (parm = strchr(v->sent_by, ':'))) {
02327 char *endptr;
02328
02329 v->port = strtol(++parm, &endptr, 10);
02330 }
02331
02332
02333 while ((parm = strsep(&via, "; \t\r\n"))) {
02334 char *c;
02335 if ((c = strstr(parm, "maddr="))) {
02336 v->maddr = ast_skip_blanks(c + sizeof("maddr=") - 1);
02337 } else if ((c = strstr(parm, "branch="))) {
02338 v->branch = ast_skip_blanks(c + sizeof("branch=") - 1);
02339 } else if ((c = strstr(parm, "ttl="))) {
02340 char *endptr;
02341 c = ast_skip_blanks(c + sizeof("ttl=") - 1);
02342 v->ttl = strtol(c, &endptr, 10);
02343
02344
02345 if (c == endptr) {
02346 v->ttl = 1;
02347 }
02348 }
02349 }
02350
02351 return v;
02352 }
02353
02354 AST_TEST_DEFINE(parse_via_test)
02355 {
02356 int res = AST_TEST_PASS;
02357 int i = 1;
02358 struct sip_via *via;
02359 struct testdata {
02360 char *in;
02361 char *expected_protocol;
02362 char *expected_branch;
02363 char *expected_sent_by;
02364 char *expected_maddr;
02365 unsigned int expected_port;
02366 unsigned char expected_ttl;
02367 int expected_null;
02368 AST_LIST_ENTRY(testdata) list;
02369 };
02370 struct testdata *testdataptr;
02371 static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
02372 struct testdata t1 = {
02373 .in = "SIP/2.0/UDP host:port;branch=thebranch",
02374 .expected_protocol = "SIP/2.0/UDP",
02375 .expected_sent_by = "host:port",
02376 .expected_branch = "thebranch",
02377 };
02378 struct testdata t2 = {
02379 .in = "SIP/2.0/UDP host:port",
02380 .expected_protocol = "SIP/2.0/UDP",
02381 .expected_sent_by = "host:port",
02382 .expected_branch = "",
02383 };
02384 struct testdata t3 = {
02385 .in = "SIP/2.0/UDP",
02386 .expected_null = 1,
02387 };
02388 struct testdata t4 = {
02389 .in = "BLAH/BLAH/BLAH host:port;branch=",
02390 .expected_protocol = "BLAH/BLAH/BLAH",
02391 .expected_sent_by = "host:port",
02392 .expected_branch = "",
02393 };
02394 struct testdata t5 = {
02395 .in = "SIP/2.0/UDP host:5060;branch=thebranch;maddr=224.0.0.1;ttl=1",
02396 .expected_protocol = "SIP/2.0/UDP",
02397 .expected_sent_by = "host:5060",
02398 .expected_port = 5060,
02399 .expected_branch = "thebranch",
02400 .expected_maddr = "224.0.0.1",
02401 .expected_ttl = 1,
02402 };
02403 struct testdata t6 = {
02404 .in = "SIP/2.0/UDP host:5060;\n branch=thebranch;\r\n maddr=224.0.0.1; ttl=1",
02405 .expected_protocol = "SIP/2.0/UDP",
02406 .expected_sent_by = "host:5060",
02407 .expected_port = 5060,
02408 .expected_branch = "thebranch",
02409 .expected_maddr = "224.0.0.1",
02410 .expected_ttl = 1,
02411 };
02412 struct testdata t7 = {
02413 .in = "SIP/2.0/UDP [::1]:5060",
02414 .expected_protocol = "SIP/2.0/UDP",
02415 .expected_sent_by = "[::1]:5060",
02416 .expected_port = 5060,
02417 .expected_branch = "",
02418 };
02419 switch (cmd) {
02420 case TEST_INIT:
02421 info->name = "parse_via_test";
02422 info->category = "/channels/chan_sip/";
02423 info->summary = "Tests parsing the Via header";
02424 info->description =
02425 "Runs through various test situations in which various "
02426 " parameters parameter must be extracted from a VIA header";
02427 return AST_TEST_NOT_RUN;
02428 case TEST_EXECUTE:
02429 break;
02430 }
02431
02432 AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &t1);
02433 AST_LIST_INSERT_TAIL(&testdatalist, &t2, list);
02434 AST_LIST_INSERT_TAIL(&testdatalist, &t3, list);
02435 AST_LIST_INSERT_TAIL(&testdatalist, &t4, list);
02436 AST_LIST_INSERT_TAIL(&testdatalist, &t5, list);
02437 AST_LIST_INSERT_TAIL(&testdatalist, &t6, list);
02438 AST_LIST_INSERT_TAIL(&testdatalist, &t7, list);
02439
02440
02441 AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
02442 via = parse_via(testdataptr->in);
02443 if (!via) {
02444 if (!testdataptr->expected_null) {
02445 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02446 "failed to parse header\n",
02447 i, testdataptr->in);
02448 res = AST_TEST_FAIL;
02449 }
02450 i++;
02451 continue;
02452 }
02453
02454 if (testdataptr->expected_null) {
02455 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02456 "successfully parased invalid via header\n",
02457 i, testdataptr->in);
02458 res = AST_TEST_FAIL;
02459 free_via(via);
02460 i++;
02461 continue;
02462 }
02463
02464 if ((ast_strlen_zero(via->protocol) && !ast_strlen_zero(testdataptr->expected_protocol))
02465 || (!ast_strlen_zero(via->protocol) && strcmp(via->protocol, testdataptr->expected_protocol))) {
02466
02467 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02468 "parsed protocol = \"%s\"\n"
02469 "expected = \"%s\"\n"
02470 "failed to parse protocol\n",
02471 i, testdataptr->in, via->protocol, testdataptr->expected_protocol);
02472 res = AST_TEST_FAIL;
02473 }
02474
02475 if ((ast_strlen_zero(via->sent_by) && !ast_strlen_zero(testdataptr->expected_sent_by))
02476 || (!ast_strlen_zero(via->sent_by) && strcmp(via->sent_by, testdataptr->expected_sent_by))) {
02477
02478 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02479 "parsed sent_by = \"%s\"\n"
02480 "expected = \"%s\"\n"
02481 "failed to parse sent-by\n",
02482 i, testdataptr->in, via->sent_by, testdataptr->expected_sent_by);
02483 res = AST_TEST_FAIL;
02484 }
02485
02486 if (testdataptr->expected_port && testdataptr->expected_port != via->port) {
02487 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02488 "parsed port = \"%d\"\n"
02489 "expected = \"%d\"\n"
02490 "failed to parse port\n",
02491 i, testdataptr->in, via->port, testdataptr->expected_port);
02492 res = AST_TEST_FAIL;
02493 }
02494
02495 if ((ast_strlen_zero(via->branch) && !ast_strlen_zero(testdataptr->expected_branch))
02496 || (!ast_strlen_zero(via->branch) && strcmp(via->branch, testdataptr->expected_branch))) {
02497
02498 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02499 "parsed branch = \"%s\"\n"
02500 "expected = \"%s\"\n"
02501 "failed to parse branch\n",
02502 i, testdataptr->in, via->branch, testdataptr->expected_branch);
02503 res = AST_TEST_FAIL;
02504 }
02505
02506 if ((ast_strlen_zero(via->maddr) && !ast_strlen_zero(testdataptr->expected_maddr))
02507 || (!ast_strlen_zero(via->maddr) && strcmp(via->maddr, testdataptr->expected_maddr))) {
02508
02509 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02510 "parsed maddr = \"%s\"\n"
02511 "expected = \"%s\"\n"
02512 "failed to parse maddr\n",
02513 i, testdataptr->in, via->maddr, testdataptr->expected_maddr);
02514 res = AST_TEST_FAIL;
02515 }
02516
02517 if (testdataptr->expected_ttl && testdataptr->expected_ttl != via->ttl) {
02518 ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
02519 "parsed ttl = \"%d\"\n"
02520 "expected = \"%d\"\n"
02521 "failed to parse ttl\n",
02522 i, testdataptr->in, via->ttl, testdataptr->expected_ttl);
02523 res = AST_TEST_FAIL;
02524 }
02525
02526 free_via(via);
02527 i++;
02528 }
02529 return res;
02530 }
02531
02532 void sip_request_parser_register_tests(void)
02533 {
02534 AST_TEST_REGISTER(get_calleridname_test);
02535 AST_TEST_REGISTER(sip_parse_uri_test);
02536 AST_TEST_REGISTER(get_in_brackets_test);
02537 AST_TEST_REGISTER(get_name_and_number_test);
02538 AST_TEST_REGISTER(sip_parse_uri_full_test);
02539 AST_TEST_REGISTER(parse_name_andor_addr_test);
02540 AST_TEST_REGISTER(parse_contact_header_test);
02541 AST_TEST_REGISTER(sip_parse_options_test);
02542 AST_TEST_REGISTER(sip_uri_cmp_test);
02543 AST_TEST_REGISTER(parse_via_test);
02544 }
02545 void sip_request_parser_unregister_tests(void)
02546 {
02547 AST_TEST_UNREGISTER(sip_parse_uri_test);
02548 AST_TEST_UNREGISTER(get_calleridname_test);
02549 AST_TEST_UNREGISTER(get_in_brackets_test);
02550 AST_TEST_UNREGISTER(get_name_and_number_test);
02551 AST_TEST_UNREGISTER(sip_parse_uri_full_test);
02552 AST_TEST_UNREGISTER(parse_name_andor_addr_test);
02553 AST_TEST_UNREGISTER(parse_contact_header_test);
02554 AST_TEST_UNREGISTER(sip_parse_options_test);
02555 AST_TEST_UNREGISTER(sip_uri_cmp_test);
02556 AST_TEST_UNREGISTER(parse_via_test);
02557 }
02558
02559 int sip_reqresp_parser_init(void)
02560 {
02561 #ifdef HAVE_XLOCALE_H
02562 c_locale = newlocale(LC_CTYPE_MASK, "C", NULL);
02563 if (!c_locale) {
02564 return -1;
02565 }
02566 #endif
02567 return 0;
02568 }
02569
02570 void sip_reqresp_parser_exit(void)
02571 {
02572 #ifdef HAVE_XLOCALE_H
02573 if (c_locale) {
02574 freelocale(c_locale);
02575 c_locale = NULL;
02576 }
02577 #endif
02578 }