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