#include "asterisk.h"
#include "include/sip.h"
#include "include/sip_utils.h"
#include "include/reqresp_parser.h"

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