38 char **hostport,
struct uriparams *params,
char **headers,
41 char *userinfo =
NULL;
42 char *parameters =
NULL;
43 char *endparams =
NULL;
46 int teluri_scheme = 0;
77 char *cur =
strsep(&scheme2,
",");
80 if (!strncasecmp(uri, cur, l)) {
81 teluri_scheme = !strncasecmp(uri,
"tel:", 4);
87 ast_debug(1,
"No supported scheme found in '%s' using the scheme[s] %s\n", uri, scheme);
96 }
else if (teluri_scheme) {
110 if ((c = strstr(uri,
";phone-context="))) {
122 }
else if (
'+' == uri[0]) {
128 ast_debug(1,
"No RFC 3966 global number or context found in '%s'; returning local number anyway\n", uri);
134 if ((c = strchr(uri,
'@'))) {
148 if (pass && (c = strchr(userinfo,
':'))) {
161 if ((c = strrchr(uri,
'?'))) {
167 if ((c = strrchr(uri,
';'))) {
170 c = strrchr(uri,
'\0');
175 }
else if (headers) {
180 endparams = strchr(parameters,
'\0');
181 if ((c = strchr(parameters,
';'))) {
185 parameters = endparams;
189 char *rem = parameters;
203 while ((value = strchr(parameters,
'=')) || (lr = !strncmp(parameters,
"lr", 2))) {
211 if ((c = strchr(value,
';'))) {
215 parameters = endparams;
218 if (!strcmp(label,
"transport")) {
221 }
else if (!strcmp(label,
"user")) {
224 }
else if (!strcmp(label,
"method")) {
227 }
else if (!strcmp(label,
"ttl")) {
230 }
else if (!strcmp(label,
"maddr")) {
234 }
else if ((!strcmp(label,
"lr") && strcmp(value,
"no") && strcmp(value,
"off") && strcmp(value,
"0") && strcmp(value,
"")) || ((lr) && strcmp(value,
"lr"))) {
259 #ifdef TEST_FRAMEWORK 264 char *
user, *
pass, *hostport, *headers, *residue;
280 struct testdata *testdataptr;
284 struct testdata td1 = {
285 .desc =
"no headers",
286 .uri =
"sip:user:secret@host:5060;param=discard;transport=tcp;param2=residue",
289 .hostport =
"host:5060",
291 .residue =
"param2=residue",
292 .params.transport =
"tcp",
297 struct testdata td2 = {
298 .desc =
"with headers",
299 .uri =
"sip:user:secret@host:5060;param=discard;transport=tcp;param2=discard2?header=blah&header2=blah2;param3=residue",
302 .hostport =
"host:5060",
303 .headers =
"header=blah&header2=blah2",
304 .residue =
"param3=residue",
305 .params.transport =
"tcp",
310 struct testdata td3 = {
311 .desc =
"difficult user",
312 .uri =
"sip:-_.!~*'()&=+$,;?/:secret@host:5060;transport=tcp",
313 .user =
"-_.!~*'()&=+$,;?/",
315 .hostport =
"host:5060",
318 .params.transport =
"tcp",
323 struct testdata td4 = {
324 .desc =
"difficult pass",
325 .uri =
"sip:user:-_.!~*'()&=+$,@host:5060;transport=tcp",
327 .pass =
"-_.!~*'()&=+$,",
328 .hostport =
"host:5060",
331 .params.transport =
"tcp",
336 struct testdata td5 = {
337 .desc =
"difficult host",
341 .hostport =
"1-1.a-1.:5060",
344 .params.transport =
"tcp",
349 struct testdata td6 = {
350 .desc =
"difficult params near transport",
351 .uri =
"sip:user:secret@host:5060;-_.!~*'()[]/:&+$=-_.!~*'()[]/:&+$;transport=tcp",
354 .hostport =
"host:5060",
357 .params.transport =
"tcp",
362 struct testdata td7 = {
363 .desc =
"difficult params near headers",
364 .uri =
"sip:user:secret@host:5060;-_.!~*'()[]/:&+$=-_.!~*'()[]/:&+$?header=blah&header2=blah2;-_.!~*'()[]/:&+$=residue",
367 .hostport =
"host:5060",
368 .headers =
"header=blah&header2=blah2",
369 .residue =
"-_.!~*'()[]/:&+$=residue",
370 .params.transport =
"",
375 struct testdata td8 = {
376 .desc =
"lr parameter",
377 .uri =
"sip:user:secret@host:5060;param=discard;lr?header=blah",
380 .hostport =
"host:5060",
381 .headers =
"header=blah",
383 .params.transport =
"",
388 struct testdata td9 = {
389 .desc =
"alternative lr parameter",
390 .uri =
"sip:user:secret@host:5060;param=discard;lr=yes?header=blah",
393 .hostport =
"host:5060",
394 .headers =
"header=blah",
396 .params.transport =
"",
401 struct testdata td10 = {
402 .desc =
"no lr parameter",
403 .uri =
"sip:user:secret@host:5060;paramlr=lr;lr=no;lr=off;lr=0;lr=;=lr;lrextra;lrparam2=lr?header=blah",
406 .hostport =
"host:5060",
407 .headers =
"header=blah",
409 .params.transport =
"",
415 struct testdata td11 = {
416 .desc =
"tel local number",
417 .uri =
"tel:0987654321;phone-context=+32987654321",
418 .user =
"0987654321",
420 .hostport =
"+32987654321",
423 .params.transport =
"",
428 struct testdata td12 = {
429 .desc =
"tel global number",
430 .uri =
"tel:+32987654321",
431 .user =
"+32987654321",
433 .hostport =
"+32987654321",
436 .params.transport =
"",
447 struct testdata td13 = {
448 .desc =
"tel local number",
449 .uri =
"tel:0987654321;ext=1234;param=discard;phone-context=+32987654321;transport=udp;param2=discard2?header=blah&header2=blah2;param3=residue",
450 .user =
"0987654321;ext=1234;param=discard",
452 .hostport =
"+32987654321",
453 .headers =
"header=blah&header2=blah2",
454 .residue =
"param3=residue",
455 .params.transport =
"udp",
476 info->name =
"sip_uri_full_parse_test";
477 info->category =
"/channels/chan_sip/";
478 info->summary =
"tests sip full uri parsing";
480 "Tests full parsing of various URIs " 481 "Verifies output matches expected behavior.";
488 user = pass = hostport = headers = residue =
NULL;
498 (user && strcmp(testdataptr->user, user)) ||
499 (pass && strcmp(testdataptr->pass, pass)) ||
500 (hostport && strcmp(testdataptr->hostport, hostport)) ||
501 (headers && strcmp(testdataptr->headers, headers)) ||
502 (residue && strcmp(testdataptr->residue, residue)) ||
503 (strcmp(testdataptr->params.transport,params.
transport)) ||
504 (testdataptr->params.lr != params.
lr) ||
505 (strcmp(testdataptr->params.user,params.
user))
518 char **hostport,
char **transport) {
531 #ifdef TEST_FRAMEWORK 536 char uri1[] =
"sip:name@host";
537 char uri2[] =
"sip:name@host;transport=tcp";
538 char uri3[] =
"sip:name:secret@host;transport=tcp";
539 char uri4[] =
"sip:name:secret@host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
541 char uri6[] =
"sip:name:secret@host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
542 char uri7[] =
"sip:name:secret@host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
543 char uri8[] =
"sip:host";
544 char uri9[] =
"sip:host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
545 char uri10[] =
"host:port;transport=tcp?headers=%40%40testblah&headers2=blah%20blah";
546 char uri11[] =
"host";
547 char uri12[] =
"tel:911";
551 info->name =
"sip_uri_parse_test";
552 info->category =
"/channels/chan_sip/";
553 info->summary =
"tests sip uri parsing";
555 "Tests parsing of various URIs " 556 "Verifies output matches expected behavior.";
563 name = pass = hostport = transport =
NULL;
564 if (
parse_uri(uri1,
"sip:,sips:", &name, &pass, &hostport, &transport) ||
565 strcmp(name,
"name") ||
567 strcmp(hostport,
"host") ||
574 name = pass = hostport = transport =
NULL;
575 if (
parse_uri(uri2,
"sip:,sips:", &name, &pass, &hostport, &transport) ||
576 strcmp(name,
"name") ||
578 strcmp(hostport,
"host") ||
579 strcmp(transport,
"tcp")) {
585 name = pass = hostport = transport =
NULL;
586 if (
parse_uri(uri3,
"sip:,sips:", &name, &pass, &hostport, &transport) ||
587 strcmp(name,
"name") ||
588 strcmp(pass,
"secret") ||
589 strcmp(hostport,
"host") ||
590 strcmp(transport,
"tcp")) {
596 name = pass = hostport = transport =
NULL;
597 if (
parse_uri(uri4,
"sip:,sips:", &name, &pass, &hostport, &transport) ||
598 strcmp(name,
"name") ||
599 strcmp(pass,
"secret") ||
600 strcmp(hostport,
"host:port") ||
601 strcmp(transport,
"tcp")) {
607 name = pass = hostport = transport =
NULL;
608 if (!
parse_uri(
NULL,
"sip:,sips:", &name, &pass, &hostport, &transport)) {
614 name = pass = hostport = transport =
NULL;
621 name = pass = hostport = transport =
NULL;
623 strcmp(name,
"name:secret") ||
624 strcmp(hostport,
"host:port")) {
631 name = pass = hostport = transport =
NULL;
632 if (
parse_uri(uri8,
"sip:,sips:", &name, &pass, &hostport, &transport) ||
633 strcmp(hostport,
"host") ||
640 name = pass = hostport = transport =
NULL;
641 if (
parse_uri(uri9,
"sip:,sips:", &name, &pass, &hostport, &transport) ||
644 strcmp(hostport,
"host:port") ||
645 strcmp(transport,
"tcp")) {
653 name = pass = hostport = transport =
NULL;
654 if (!
parse_uri(uri10,
"sip:,sips:", &name, &pass, &hostport, &transport) ||
657 strcmp(hostport,
"host:port") ||
658 strcmp(transport,
"tcp")) {
666 name = pass = hostport = transport =
NULL;
667 if (!
parse_uri(uri11,
"sip:,sips:", &name, &pass, &hostport, &transport) ||
670 strcmp(hostport,
"host") ||
677 name = pass = hostport = transport =
NULL;
678 if (!
parse_uri(uri12,
"sip:,sips:,tel:", &name, &pass, &hostport, &transport) ||
679 strcmp(name,
"911") ||
720 char *orig_output = output;
721 const char *orig_input =
input;
723 if (!output || !outputsize) {
738 if (!input || *input ==
'<') {
743 if (input[0] ==
'"') {
749 }
else if (*input == 0x5c) {
754 if ((
unsigned char) *input > 0x7f || *input == 0xa || *input == 0xd) {
757 }
else if ((*input != 0x9 && (
unsigned char) *input < 0x20)
762 if (0 < outputsize) {
784 if ((*input >=
'0' && *input <=
'9') || (*input >=
'A' && *input <=
'Z')
785 || (*input >=
'a' && *input <=
'z') || *input ==
'-' || *input ==
'.' 786 || *input ==
'!' || *input ==
'%' || *input ==
'*' || *input ==
'_' 787 || *input ==
'+' || *input ==
'`' || *input ==
'\'' || *input ==
'~' 788 || *input == 0x9 || *input ==
' ') {
789 if (0 < outputsize) {
794 }
else if (*input ==
'<') {
797 }
else if (*input ==
':') {
814 }
while (orig_output <= output && (*output == 0x9 || *output ==
' '));
820 #ifdef TEST_FRAMEWORK 824 const char *in1 =
" \" quoted-text internal \\\" quote \"<stuff>";
825 const char *in2 =
" token text with no quotes <stuff>";
826 const char *overflow1 =
" \"quoted-text overflow 1234567890123456789012345678901234567890\" <stuff>";
827 const char *overflow2 =
" non-quoted text overflow 1234567890123456789012345678901234567890 <stuff>";
828 const char *noendquote =
" \"quoted-text no end <stuff>";
829 const char *addrspec =
" sip:blah@blah";
830 const char *no_quotes_no_brackets =
"blah@blah";
831 const char *after_dname;
836 info->name =
"sip_get_calleridname_test";
837 info->category =
"/channels/chan_sip/";
838 info->summary =
"decodes callerid name from sip header";
839 info->description =
"Decodes display-name field of sip header. Checks for valid output and expected failure cases.";
848 if (strcmp(dname,
" quoted-text internal \" quote ")) {
856 if (strcmp(dname,
"token text with no quotes")) {
864 if (strcmp(dname,
"quoted-text overflow 123456789012345678")) {
872 if (strcmp(dname,
"non-quoted text overflow 12345678901234")) {
880 if (*dname !=
'\0' && after_dname != noendquote) {
888 if (*dname !=
'\0' && after_dname != addrspec) {
894 after_dname =
get_calleridname(no_quotes_no_brackets, dname,
sizeof(dname));
896 if (*dname !=
'\0' && after_dname != no_quotes_no_brackets) {
909 char *tmp_number =
NULL;
910 char *hostport =
NULL;
945 #ifdef TEST_FRAMEWORK 951 const char *in1 =
"NAME <sip:NUMBER@place>";
952 const char *in2 =
"\"NA><ME\" <sip:NUMBER@place>";
953 const char *in3 =
"NAME";
954 const char *in4 =
"<sip:NUMBER@place>";
955 const char *in5 =
"This is a screwed up string <sip:LOLCLOWNS<sip:>@place>";
959 info->name =
"sip_get_name_and_number_test";
960 info->category =
"/channels/chan_sip/";
961 info->summary =
"Tests getting name and number from sip header";
963 "Runs through various test situations in which a name and " 964 "and number can be retrieved from a sip header.";
971 number = name =
NULL;
973 strcmp(name,
"NAME") ||
974 strcmp(number,
"NUMBER")) {
983 number = name =
NULL;
985 strcmp(name,
"NA><ME") ||
986 strcmp(number,
"NUMBER")) {
995 number = name =
NULL;
1005 number = name =
NULL;
1008 strcmp(number,
"NUMBER")) {
1017 number = name =
NULL;
1029 number = name =
NULL;
1037 number = name =
NULL;
1054 const char *
parse = src;
1055 const char *first_bracket;
1056 const char *second_bracket;
1058 if (start ==
NULL) {
1061 if (length ==
NULL) {
1074 while ( (first_bracket = strchr(parse,
'<')) ) {
1075 const char *first_quote = strchr(parse,
'"');
1077 if (!first_quote || first_quote >= first_bracket) {
1091 if (!first_bracket) {
1096 if ((second_bracket = strchr(first_bracket,
'>'))) {
1097 *start = first_bracket;
1098 *length = second_bracket - first_bracket;
1108 char *first_bracket;
1109 char *second_bracket;
1126 while ( (first_bracket = strchr(parse,
'<')) ) {
1127 char *first_quote = strchr(parse,
'"');
1129 if (!first_quote || first_quote >= first_bracket) {
1144 if (first_bracket) {
1145 parse = first_bracket;
1150 if ((second_bracket = strchr(parse,
'>'))) {
1151 *second_bracket++ =
'\0';
1153 *out = (
char *) parse;
1156 *residue = second_bracket;
1161 if ((first_bracket)) {
1183 #ifdef TEST_FRAMEWORK 1187 char in_brackets[] =
"sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah";
1188 char no_name[] =
"<sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
1189 char quoted_string[] =
"\"I'm a quote stri><ng\" <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
1190 char missing_end_quote[] =
"\"I'm a quote string <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
1191 char name_no_quotes[] =
"name not in quotes <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
1192 char no_end_bracket[] =
"name not in quotes <sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah";
1193 char no_name_no_brackets[] =
"sip:name@host";
1194 char missing_start_bracket[] =
"sip:name:secret@host:port;transport=tcp?headers=testblah&headers2=blahblah>";
1199 info->name =
"sip_get_in_brackets_test";
1200 info->category =
"/channels/chan_sip/";
1201 info->summary =
"Tests getting a sip uri in <> brackets within a sip header.";
1203 "Runs through various test situations in which a sip uri " 1204 "in angle brackets needs to be retrieved";
1217 if (!(uri =
get_in_brackets(quoted_string)) || strcmp(uri, in_brackets)) {
1223 if (!(uri =
get_in_brackets(missing_end_quote)) || !strcmp(uri, in_brackets)) {
1229 if (!(uri =
get_in_brackets(name_no_quotes)) || strcmp(uri, in_brackets)) {
1235 if (!(uri =
get_in_brackets(no_end_bracket)) || !strcmp(uri, in_brackets)) {
1247 if (!(uri =
get_in_brackets(no_name_no_brackets)) || strcmp(uri,
"sip:name@host")) {
1253 if (!(uri =
get_in_brackets(missing_start_bracket)) || strcmp(uri, in_brackets)) {
1263 char **
user,
char **
pass,
char **hostport,
1264 struct uriparams *params,
char **headers,
1268 char **residue2 = residue;
1269 char *orig_uri = uri;
1282 if (residue && **residue) {
1284 *residue = *residue + 1;
1296 strcpy(orig_uri, buf);
1303 return parse_uri_full(uri, scheme, user, pass, hostport, params, headers, residue2);
1306 #ifdef TEST_FRAMEWORK 1311 char *
name, *
user, *
pass, *hostport, *headers, *residue;
1327 struct testdata *testdataptr;
1331 struct testdata td1 = {
1332 .desc =
"quotes and brackets",
1333 .uri =
"\"name :@ \" <sip:user:secret@host:5060;param=discard;transport=tcp>;tag=tag",
1337 .hostport =
"host:5060",
1339 .residue =
"tag=tag",
1340 .params.transport =
"tcp",
1345 struct testdata td2 = {
1346 .desc =
"no quotes",
1347 .uri =
"givenname familyname <sip:user:secret@host:5060;param=discard;transport=tcp>;expires=3600",
1348 .name =
"givenname familyname",
1351 .hostport =
"host:5060",
1353 .residue =
"expires=3600",
1354 .params.transport =
"tcp",
1359 struct testdata td3 = {
1360 .desc =
"no brackets",
1361 .uri =
"sip:user:secret@host:5060;param=discard;transport=tcp;q=1",
1365 .hostport =
"host:5060",
1368 .params.transport =
"tcp",
1373 struct testdata td4 = {
1374 .desc =
"just host",
1382 .params.transport =
"",
1396 info->name =
"parse_name_andor_addr_test";
1397 info->category =
"/channels/chan_sip/";
1398 info->summary =
"tests parsing of name_andor_addr abnf structure";
1400 "Tests parsing of abnf name-andor-addr = name-addr / addr-spec " 1401 "Verifies output matches expected behavior.";
1408 name = user = pass = hostport = headers = residue =
NULL;
1420 (name && strcmp(testdataptr->name, name)) ||
1421 (user && strcmp(testdataptr->user, user)) ||
1422 (pass && strcmp(testdataptr->pass, pass)) ||
1423 (hostport && strcmp(testdataptr->hostport, hostport)) ||
1424 (headers && strcmp(testdataptr->headers, headers)) ||
1425 (residue && strcmp(testdataptr->residue, residue)) ||
1426 (strcmp(testdataptr->params.transport,params.
transport)) ||
1427 (strcmp(testdataptr->params.user,params.
user))
1448 if ((c = strchr(parse,
'"'))) {
1464 if ((c = strchr(parse,
'@'))) {
1467 if ((out) && (c = strchr(parse,
','))) {
1485 if (*contactheader ==
'*') {
1489 split_contact =
ast_calloc(1,
sizeof(*split_contact));
1492 while ((last =
get_comma(contactheader, &comma)) != -1) {
1494 &split_contact->
name, &split_contact->
user,
1503 split_contact->
expires = split_contact->
q =
"";
1505 while ((value = strchr(residue,
'='))) {
1509 if ((residue = strchr(value,
';'))) {
1515 if (!strcmp(param,
"expires")) {
1517 }
else if (!strcmp(param,
"q")) {
1518 split_contact->
q =
value;
1525 contactheader = comma;
1527 split_contact =
ast_calloc(1,
sizeof(*split_contact));
1533 #ifdef TEST_FRAMEWORK 1537 char contactheader[1024];
1539 struct contactliststruct contactlist;
1540 struct contactliststruct *contactlistptr=&contactlist;
1544 char *contactheader;
1546 struct contactliststruct *contactlist;
1551 struct testdata *testdataptr;
1556 struct contactliststruct contactlist1, contactlist2;
1558 struct testdata td1 = {
1559 .desc =
"single contact",
1560 .contactheader =
"\"name :@;?&,\" <sip:user:secret@host:5082;param=discard;transport=tcp>;expires=3600",
1561 .contactlist = &contactlist1,
1565 .
name =
"name :@;?&,",
1568 .hostport =
"host:5082",
1569 .params.transport =
"tcp",
1577 struct testdata td2 = {
1578 .desc =
"multiple contacts",
1579 .contactheader =
"sip:,user1,:,secret1,@host1;ttl=7;q=1;expires=3600,sips:host2",
1580 .contactlist = &contactlist2,
1586 .pass =
",secret1,",
1587 .hostport =
"host1",
1588 .params.transport =
"",
1599 .hostport =
"host2",
1600 .params.transport =
"",
1608 struct testdata td3 = {
1609 .desc =
"star - all contacts",
1610 .contactheader =
"*",
1627 info->name =
"parse_contact_header_test";
1628 info->category =
"/channels/chan_sip/";
1629 info->summary =
"tests parsing of sip contact header";
1631 "Tests parsing of a contact header including those with multiple contacts " 1632 "Verifies output matches expected behavior.";
1639 ast_copy_string(contactheader,testdataptr->contactheader,
sizeof(contactheader));
1641 if (testdataptr->star) {
1652 strcmp(tdcontactptr->
name, contactptr->
name) ||
1653 strcmp(tdcontactptr->
user, contactptr->
user) ||
1654 strcmp(tdcontactptr->
pass, contactptr->
pass) ||
1658 strcmp(tdcontactptr->
q, contactptr->
q) ||
1697 int i, found, supported;
1698 unsigned int profile = 0;
1700 char *
out = unsupported;
1701 size_t outlen = unsupported_len;
1702 char *cur_out =
out;
1709 ast_debug(3,
"Begin: parsing SIP \"Supported: %s\"\n", options);
1710 for (next = temp; next; next = sep) {
1713 if ((sep = strchr(next,
',')) !=
NULL) {
1724 ast_debug(3,
"Found SIP option: -%s-\n", next);
1732 ast_debug(3,
"Matched SIP option: %s\n", next);
1738 if (!supported && out && outlen) {
1739 size_t copylen = strlen(next);
1740 size_t cur_outlen = strlen(out);
1743 if ((cur_outlen + copylen + 2) < outlen) {
1757 if (!strncasecmp(next,
"x-", 2))
1758 ast_debug(3,
"Found private SIP option, not supported: %s\n", next);
1760 ast_debug(3,
"Found no match for SIP option: %s (Please file bug report!)\n", next);
1767 #ifdef TEST_FRAMEWORK 1771 char unsupported[64];
1772 unsigned int option_profile = 0;
1775 char *input_options;
1776 char *expected_unsupported;
1777 unsigned int expected_profile;
1781 struct testdata *testdataptr;
1784 struct testdata test1 = {
1785 .name =
"test_all_unsupported",
1786 .input_options =
"unsupported1,,, ,unsupported2,unsupported3,unsupported4",
1787 .expected_unsupported =
"unsupported1,unsupported2,unsupported3,unsupported4",
1790 struct testdata test2 = {
1791 .name =
"test_all_unsupported_one_supported",
1792 .input_options =
" unsupported1, replaces, unsupported3 , , , ,unsupported4",
1793 .expected_unsupported =
"unsupported1,unsupported3,unsupported4",
1796 struct testdata test3 = {
1797 .name =
"test_two_supported_two_unsupported",
1798 .input_options =
",, timer ,replaces ,unsupported3,unsupported4",
1799 .expected_unsupported =
"unsupported3,unsupported4",
1803 struct testdata test4 = {
1804 .name =
"test_all_supported",
1805 .input_options =
"timer,replaces",
1806 .expected_unsupported =
"",
1810 struct testdata test5 = {
1811 .name =
"test_all_supported_redundant",
1812 .input_options =
"timer,replaces,timer,replace,timer,replaces",
1813 .expected_unsupported =
"",
1816 struct testdata test6 = {
1817 .name =
"test_buffer_overflow",
1818 .input_options =
"unsupported1,replaces,timer,unsupported4,unsupported_huge____" 1819 "____________________________________,__________________________________________" 1820 "________________________________________________",
1821 .expected_unsupported =
"unsupported1,unsupported4",
1824 struct testdata test7 = {
1825 .name =
"test_null_input",
1826 .input_options =
NULL,
1827 .expected_unsupported =
"",
1828 .expected_profile = 0,
1830 struct testdata test8 = {
1831 .name =
"test_whitespace_input",
1832 .input_options =
" ",
1833 .expected_unsupported =
"",
1834 .expected_profile = 0,
1836 struct testdata test9 = {
1837 .name =
"test_whitespace_plus_option_input",
1838 .input_options =
" , , ,timer , , , , , ",
1839 .expected_unsupported =
"",
1845 info->name =
"sip_parse_options_test";
1846 info->category =
"/channels/chan_sip/";
1847 info->summary =
"Tests parsing of sip options";
1849 "Tests parsing of SIP options from supported and required " 1850 "header fields. Verifies when unsupported options are encountered " 1851 "that they are appended to the unsupported out buffer and that the " 1852 "correct bit field representnig the option profile is returned.";
1870 memset(unsupported, 0,
sizeof(unsupported));
1872 if (option_profile != testdataptr->expected_profile ||
1873 strcmp(unsupported, testdataptr->expected_unsupported)) {
1875 "%s expected bit profile: %x actual bit profile: %x\n",
1877 testdataptr->expected_unsupported,
1879 testdataptr->expected_profile,
1890 if (option_profile != testdataptr->expected_profile) {
1893 testdataptr->expected_profile,
1926 char *params1 =
NULL;
1927 char *params2 =
NULL;
1930 int zerolength1 = 0;
1931 int zerolength2 = 0;
1935 int methodmatch = 0;
1951 if (zerolength1 && zerolength2) {
1955 for (pos1 =
strsep(¶ms1,
";"); pos1; pos1 =
strsep(¶ms1,
";")) {
1956 char *value1 = pos1;
1957 char *name1 =
strsep(&value1,
"=");
1958 char *params2dup =
NULL;
1970 for (pos2 =
strsep(¶ms2dup,
";"); pos2; pos2 =
strsep(¶ms2dup,
";")) {
1972 char *value2 = strchr(pos2,
'=');
1978 if (!strcasecmp(name1, name2)) {
1979 if (strcasecmp(value1, value2)) {
1988 if (!strcasecmp(name1,
"maddr")) {
1994 }
else if (!strcasecmp(name1,
"ttl")) {
2000 }
else if (!strcasecmp(name1,
"user")) {
2006 }
else if (!strcasecmp(name1,
"method")) {
2019 for (pos2 =
strsep(¶ms2,
";"); pos2; pos2 =
strsep(¶ms2,
";")) {
2020 char *value2 = pos2;
2021 char *name2 =
strsep(&value2,
"=");
2025 if ((!strcasecmp(name2,
"maddr") && !maddrmatch) ||
2026 (!strcasecmp(name2,
"ttl") && !ttlmatch) ||
2027 (!strcasecmp(name2,
"user") && !usermatch) ||
2028 (!strcasecmp(name2,
"method") && !methodmatch)) {
2052 char *headers1 =
NULL;
2053 char *headers2 =
NULL;
2054 int zerolength1 = 0;
2055 int zerolength2 = 0;
2074 if (zerolength1 != zerolength2) {
2078 if (zerolength1 && zerolength2)
2085 if (strlen(headers1) != strlen(headers2)) {
2089 for (header1 =
strsep(&headers1,
"&"); header1; header1 =
strsep(&headers1,
"&")) {
2125 if (addr1_parsed != addr2_parsed) {
2137 if (!addr1_parsed) {
2138 #ifdef HAVE_XLOCALE_H 2140 return strcasecmp(host1, host2);
2142 return strcasecmp_l(host1, host2,
c_locale);
2145 return strcasecmp(host1, host2);
2171 if (!input1 || !input2) {
2181 uri_scheme1 =
strsep(&uri1,
":");
2182 uri_scheme2 =
strsep(&uri2,
":");
2184 if (strcmp(uri_scheme1, uri_scheme2)) {
2192 if (strcmp(uri_scheme1,
"sip") && strcmp(uri_scheme1,
"sips")) {
2200 if ((host1 = strchr(uri1,
'@'))) {
2203 if ((host2 = strchr(uri2,
'@'))) {
2210 if ((host1 && !host2) ||
2211 (host2 && !host1) ||
2212 (host1 && host2 && strcmp(uri1, uri2))) {
2227 if ((params1 = strchr(host1,
';'))) {
2230 if ((params2 = strchr(host2,
';'))) {
2237 if ((headers1 = strchr(
S_OR(params1, host1),
'?'))) {
2240 if ((headers2 = strchr(
S_OR(params2, host2),
'?'))) {
2257 #define URI_CMP_MATCH 0 2258 #define URI_CMP_NOMATCH 1 2260 #ifdef TEST_FRAMEWORK 2263 static const struct {
2266 int expected_result;
2267 } uri_cmp_tests [] = {
2283 {
"sip:bob@[2001:db8::1234]",
"sip:bob@[2001:db8::1234]",
URI_CMP_MATCH },
2285 {
"sip:bob@[2001:db8::1234]",
"sip:bob@[2001:0db8::1234]",
URI_CMP_MATCH },
2291 {
"sip:bob@[2001:db8:1234]:5060",
"sip:bob@[2001:db8:1234]",
URI_CMP_NOMATCH },
2331 info->name =
"sip_uri_cmp_test";
2332 info->category =
"/channels/chan_sip/";
2333 info->summary =
"Tests comparison of SIP URIs";
2334 info->description =
"Several would-be tricky URI comparisons are performed";
2340 for (i = 0; i <
ARRAY_LEN(uri_cmp_tests); ++i) {
2343 if ((cmp_res1 =
sip_uri_cmp(uri_cmp_tests[i].uri1, uri_cmp_tests[i].uri2))) {
2349 if (cmp_res1 != uri_cmp_tests[i].expected_result) {
2351 "Expected %s but got %s\n", uri_cmp_tests[i].uri1, uri_cmp_tests[i].uri2,
2352 uri_cmp_tests[i].expected_result ==
URI_CMP_MATCH ?
"Match" :
"No Match",
2360 if ((cmp_res2 =
sip_uri_cmp(uri_cmp_tests[i].uri2, uri_cmp_tests[i].uri1))) {
2366 if (cmp_res2 != uri_cmp_tests[i].expected_result) {
2368 "Expected %s but got %s\n", uri_cmp_tests[i].uri2, uri_cmp_tests[i].uri1,
2369 uri_cmp_tests[i].expected_result ==
URI_CMP_MATCH ?
"Match" :
"No Match",
2436 if (((parm = strchr(v->
sent_by,
']')) && *(++parm) ==
':') || (!(parm = strchr(v->
sent_by,
']')) && (parm = strchr(v->
sent_by,
':')))) {
2439 v->
port = strtol(++parm, &endptr, 10);
2443 while ((parm =
strsep(&via,
"; \t\r\n"))) {
2445 if ((c = strstr(parm,
"maddr="))) {
2447 }
else if ((c = strstr(parm,
"branch="))) {
2449 }
else if ((c = strstr(parm,
"ttl="))) {
2452 v->
ttl = strtol(c, &endptr, 10);
2464 #ifdef TEST_FRAMEWORK 2472 char *expected_protocol;
2473 char *expected_branch;
2474 char *expected_sent_by;
2475 char *expected_maddr;
2476 unsigned int expected_port;
2477 unsigned char expected_ttl;
2481 struct testdata *testdataptr;
2483 struct testdata t1 = {
2484 .in =
"SIP/2.0/UDP host:port;branch=thebranch",
2485 .expected_protocol =
"SIP/2.0/UDP",
2486 .expected_sent_by =
"host:port",
2487 .expected_branch =
"thebranch",
2489 struct testdata t2 = {
2490 .in =
"SIP/2.0/UDP host:port",
2491 .expected_protocol =
"SIP/2.0/UDP",
2492 .expected_sent_by =
"host:port",
2493 .expected_branch =
"",
2495 struct testdata t3 = {
2496 .in =
"SIP/2.0/UDP",
2499 struct testdata t4 = {
2500 .in =
"BLAH/BLAH/BLAH host:port;branch=",
2501 .expected_protocol =
"BLAH/BLAH/BLAH",
2502 .expected_sent_by =
"host:port",
2503 .expected_branch =
"",
2505 struct testdata t5 = {
2506 .in =
"SIP/2.0/UDP host:5060;branch=thebranch;maddr=224.0.0.1;ttl=1",
2507 .expected_protocol =
"SIP/2.0/UDP",
2508 .expected_sent_by =
"host:5060",
2509 .expected_port = 5060,
2510 .expected_branch =
"thebranch",
2511 .expected_maddr =
"224.0.0.1",
2514 struct testdata t6 = {
2515 .in =
"SIP/2.0/UDP host:5060;\n branch=thebranch;\r\n maddr=224.0.0.1; ttl=1",
2516 .expected_protocol =
"SIP/2.0/UDP",
2517 .expected_sent_by =
"host:5060",
2518 .expected_port = 5060,
2519 .expected_branch =
"thebranch",
2520 .expected_maddr =
"224.0.0.1",
2523 struct testdata t7 = {
2524 .in =
"SIP/2.0/UDP [::1]:5060",
2525 .expected_protocol =
"SIP/2.0/UDP",
2526 .expected_sent_by =
"[::1]:5060",
2527 .expected_port = 5060,
2528 .expected_branch =
"",
2532 info->name =
"parse_via_test";
2533 info->category =
"/channels/chan_sip/";
2534 info->summary =
"Tests parsing the Via header";
2536 "Runs through various test situations in which various " 2537 " parameters parameter must be extracted from a VIA header";
2555 if (!testdataptr->expected_null) {
2557 "failed to parse header\n",
2558 i, testdataptr->in);
2565 if (testdataptr->expected_null) {
2567 "successfully parased invalid via header\n",
2568 i, testdataptr->in);
2579 "parsed protocol = \"%s\"\n" 2580 "expected = \"%s\"\n" 2581 "failed to parse protocol\n",
2582 i, testdataptr->in, via->
protocol, testdataptr->expected_protocol);
2590 "parsed sent_by = \"%s\"\n" 2591 "expected = \"%s\"\n" 2592 "failed to parse sent-by\n",
2593 i, testdataptr->in, via->
sent_by, testdataptr->expected_sent_by);
2597 if (testdataptr->expected_port && testdataptr->expected_port != via->
port) {
2599 "parsed port = \"%u\"\n" 2600 "expected = \"%u\"\n" 2601 "failed to parse port\n",
2602 i, testdataptr->in, via->
port, testdataptr->expected_port);
2610 "parsed branch = \"%s\"\n" 2611 "expected = \"%s\"\n" 2612 "failed to parse branch\n",
2613 i, testdataptr->in, via->
branch, testdataptr->expected_branch);
2621 "parsed maddr = \"%s\"\n" 2622 "expected = \"%s\"\n" 2623 "failed to parse maddr\n",
2624 i, testdataptr->in, via->
maddr, testdataptr->expected_maddr);
2628 if (testdataptr->expected_ttl && testdataptr->expected_ttl != via->
ttl) {
2630 "parsed ttl = \"%d\"\n" 2631 "expected = \"%d\"\n" 2632 "failed to parse ttl\n",
2633 i, testdataptr->in, via->
ttl, testdataptr->expected_ttl);
2673 #ifdef HAVE_XLOCALE_H 2684 #ifdef HAVE_XLOCALE_H
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
AST_TEST_DEFINE(sip_parse_uri_full_test)
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
unsigned int parse_sip_options(const char *options, char *unsupported, size_t unsupported_len)
Parse supported header in incoming packet.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
int get_in_brackets_const(const char *src, const char **start, int *length)
Get text in brackets on a const without copy.
static void dummy(char *unused,...)
int get_in_brackets_full(char *tmp, char **out, char **residue)
Get text in brackets and any trailing residue.
static int sip_uri_domain_cmp(const char *host1, const char *host2)
Compare domain sections of SIP URIs.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
#define AST_TEST_REGISTER(cb)
int sip_uri_cmp(const char *input1, const char *input2)
Compare two URIs as described in RFC 3261 Section 19.1.4.
#define ast_strdup(str)
A wrapper for strdup()
const char * find_closing_quote(const char *start, const char *lim)
Locate closing quote in a string, skipping escaped quotes. optionally with a limit on the search...
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
int parse_uri_full(char *uri, const char *scheme, char **user, char **pass, char **hostport, struct uriparams *params, char **headers, char **residue)
parses a URI in its components.
static int input(yyscan_t yyscanner)
Socket address structure.
#define ast_strlen_zero(foo)
Structure to store Via information.
int parse_uri(char *uri, const char *scheme, char **user, char **pass, char **hostport, char **transport)
parses a URI in its components.
#define ast_debug(level,...)
Log a DEBUG message.
int get_name_and_number(const char *hdr, char **name, char **number)
Get name and number from sip header.
void sip_request_parser_register_tests(void)
register request parsing tests
#define ast_test_status_update(a, b, c...)
struct sla_ringing_trunk * last
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
char * get_in_brackets(char *tmp)
Pick out text in brackets from character string.
const char * get_calleridname(const char *input, char *output, size_t outputsize)
Get caller id name from SIP headers, copy into output buffer.
void free_via(struct sip_via *v)
#define ast_strdupa(s)
duplicate a string in memory from the stack
void sip_reqresp_parser_exit(void)
Free resources used by request and response parser.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
AST_LIST_HEAD_NOLOCK(contactliststruct, contact)
sip request response parser header file
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
int parse_contact_header(char *contactheader, struct contactliststruct *contactlist)
static int sip_uri_headers_cmp(const char *input1, const char *input2)
helper routine for sip_uri_cmp to compare URI headers
#define AST_TEST_UNREGISTER(cb)
static enum ast_test_result_state test_res
int parse_name_andor_addr(char *uri, const char *scheme, char **name, char **user, char **pass, char **hostport, struct uriparams *params, char **headers, char **residue)
Parse the ABNF structure name-andor-addr = name-addr / addr-spec into its components and return any t...
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
int get_comma(char *in, char **out)
Parse all contact header contacts.
char * strcasestr(const char *, const char *)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
static void parse(struct mgcp_request *req)
#define AST_LIST_HEAD_SET_NOLOCK(head, entry)
Initializes a list head structure with a specified first entry.
static const struct cfsip_options sip_options[]
#define ast_calloc(num, len)
A wrapper for calloc()
structure to hold users read from users.conf
char * strsep(char **str, const char *delims)
void sip_request_parser_unregister_tests(void)
unregister request parsing tests
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int sip_reqresp_parser_init(void)
initialize request and response parser data
const struct ast_flags ast_uri_sip_user
int error(const char *format,...)
struct sip_via * parse_via(const char *header)
Parse a Via header.
static int sip_uri_params_cmp(const char *input1, const char *input2)
helper routine for sip_uri_cmp to compare URI parameters