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