summaryrefslogtreecommitdiff
path: root/channels/sip/reqresp_parser.c
diff options
context:
space:
mode:
authorDavid Vossel <dvossel@digium.com>2010-07-26 20:00:52 +0000
committerDavid Vossel <dvossel@digium.com>2010-07-26 20:00:52 +0000
commit4a98994542bb56bc7252cf70a3394311fd01e968 (patch)
tree5f612d10ca48c649bb42845e9402e2e9aa80e4e0 /channels/sip/reqresp_parser.c
parent4bd366a92660f8b650c7c640d76659326dc90751 (diff)
Merged revisions 279568 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r279568 | dvossel | 2010-07-26 14:59:03 -0500 (Mon, 26 Jul 2010) | 21 lines transaction matching using top most Via header This patch modifies the way chan_sip.c does transaction to dialog matching. Asterisk now stores information in the top most Via header of the initial incoming request and compares that against other Requests that have the same call-id. This results in Asterisk being able to detect a forked call in which it has received multiple legs of the fork. I completely stripped out the previous matching code and made the comparisons a little more explicit and easier to understand. My comments in the code should offer all the details involving this patch. This patch also fixes a bug with the usage of the OBJ-MULTIPLE flag to find multiple dialogs with the same call-id. Since the callback function was returning (CMP_MATCH | CMP_STOP) only the first item found was being returned. I fixed this by making a new callback function for finding multiple dialogs that only returns (CMP_MATCH) on a match allowing for multiple items to be returned. Review: https://reviewboard.asterisk.org/r/776/ ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@279569 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/sip/reqresp_parser.c')
-rw-r--r--channels/sip/reqresp_parser.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/channels/sip/reqresp_parser.c b/channels/sip/reqresp_parser.c
index ac9aeaba9..b219bf039 100644
--- a/channels/sip/reqresp_parser.c
+++ b/channels/sip/reqresp_parser.c
@@ -2243,6 +2243,151 @@ AST_TEST_DEFINE(sip_uri_cmp_test)
return test_res;
}
+void get_viabranch(char *via, char **sent_by, char **branch)
+{
+ char *tmp;
+
+ if (sent_by) {
+ *sent_by = NULL;
+ }
+ if (branch) {
+ *branch = NULL;
+ }
+ if (ast_strlen_zero(via)) {
+ return;
+ }
+ via = ast_skip_blanks(via);
+ /*
+ * VIA syntax. RFC 3261 section 6.40.5
+ * Via = ( "Via" | "v") ":" 1#( sent-protocol sent-by *( ";" via-params ) [ comment ] )
+ * via-params = via-hidden | via-ttl | via-maddr | via-received | via-branch
+ * via-hidden = "hidden"
+ * via-ttl = "ttl" "=" ttl
+ * via-maddr = "maddr" "=" maddr
+ * via-received = "received" "=" host
+ * via-branch = "branch" "=" token
+ * sent-protocol = protocol-name "/" protocol-version "/" transport
+ * protocol-name = "SIP" | token
+ * protocol-version = token
+ * transport = "UDP" | "TCP" | token
+ * sent-by = ( host [ ":" port ] ) | ( concealed-host )
+ * concealed-host = token
+ * ttl = 1*3DIGIT ; 0 to 255
+ */
+
+ /* chop off ("Via:" | "v:") if present */
+ if (!strncasecmp(via, "Via:", 4)) {
+ via += 4;
+ } else if (!strncasecmp(via, "v:", 2)) {
+ via += 2;
+ }
+ if (ast_strlen_zero(via)) {
+ return;
+ }
+
+ /* chop off sent-protocol */
+ via = ast_skip_blanks(via);
+ strsep(&via, " \t\r\n");
+ if (ast_strlen_zero(via)) {
+ return;
+ }
+
+ /* chop off sent-by */
+ via = ast_skip_blanks(via);
+ *sent_by = strsep(&via, "; \t\r\n");
+ if (ast_strlen_zero(via)) {
+ return;
+ }
+
+ /* now see if there is a branch parameter in there */
+ if (!ast_strlen_zero(via) && (tmp = strstr(via, "branch="))) {
+ /* find the branch ID */
+ via = ast_skip_blanks(tmp + 7);
+
+ /* chop off the branch parameter */
+ *branch = strsep(&via, "; \t\r\n");
+ }
+}
+
+AST_TEST_DEFINE(get_viabranch_test)
+{
+ int res = AST_TEST_PASS;
+ int i = 1;
+ char *sent_by, *branch;
+ struct testdata {
+ char *in;
+ char *expected_branch;
+ char *expected_sent_by;
+ AST_LIST_ENTRY(testdata) list;
+ };
+ struct testdata *testdataptr;
+ static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
+ struct testdata t1 = {
+ .in = "Via: SIP/2.0/UDP host:port;branch=thebranch",
+ .expected_branch = "thebranch",
+ .expected_sent_by = "host:port"
+ };
+ struct testdata t2 = {
+ .in = "SIP/2.0/UDP host:port;branch=thebranch",
+ .expected_branch = "thebranch",
+ .expected_sent_by = "host:port"
+ };
+ struct testdata t3 = {
+ .in = "SIP/2.0/UDP host:port",
+ .expected_branch = "",
+ .expected_sent_by = "host:port"
+ };
+ struct testdata t4 = {
+ .in = "BLAH/BLAH/BLAH host:port ; branch= thebranch ;;;;;;;",
+ .expected_branch = "thebranch",
+ .expected_sent_by = "host:port"
+ };
+ struct testdata t5 = {
+ .in = "v: BLAH/BLAH/BLAH",
+ .expected_branch = "",
+ .expected_sent_by = ""
+ };
+ struct testdata t6 = {
+ .in = "BLAH/BLAH/BLAH host:port;branch=",
+ .expected_branch = "",
+ .expected_sent_by = "host:port"
+ };
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "get_viabranch_test";
+ info->category = "channels/chan_sip/";
+ info->summary = "Tests getting sent-by and branch parameter from via";
+ info->description =
+ "Runs through various test situations in which a sent-by and"
+ " branch parameter must be extracted from a VIA header";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ AST_LIST_HEAD_SET_NOLOCK(&testdatalist, &t1);
+ AST_LIST_INSERT_TAIL(&testdatalist, &t2, list);
+ AST_LIST_INSERT_TAIL(&testdatalist, &t3, list);
+ AST_LIST_INSERT_TAIL(&testdatalist, &t4, list);
+ AST_LIST_INSERT_TAIL(&testdatalist, &t5, list);
+ AST_LIST_INSERT_TAIL(&testdatalist, &t6, list);
+
+
+ AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
+ get_viabranch(ast_strdupa(testdataptr->in), &sent_by, &branch);
+ if ((ast_strlen_zero(sent_by) && !ast_strlen_zero(testdataptr->expected_sent_by)) ||
+ (ast_strlen_zero(branch) && !ast_strlen_zero(testdataptr->expected_branch)) ||
+ (!ast_strlen_zero(sent_by) && strcmp(sent_by, testdataptr->expected_sent_by)) ||
+ (!ast_strlen_zero(branch) && strcmp(branch, testdataptr->expected_branch))) {
+ ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\" parsed sent-by = \"%s\" parsed branch = \"%s\"\n",
+ i, testdataptr->in, sent_by, branch);
+ res = AST_TEST_FAIL;
+ }
+ i++;
+ }
+ return res;
+}
+
void sip_request_parser_register_tests(void)
{
AST_TEST_REGISTER(get_calleridname_test);
@@ -2254,6 +2399,7 @@ void sip_request_parser_register_tests(void)
AST_TEST_REGISTER(parse_contact_header_test);
AST_TEST_REGISTER(sip_parse_options_test);
AST_TEST_REGISTER(sip_uri_cmp_test);
+ AST_TEST_REGISTER(get_viabranch_test);
}
void sip_request_parser_unregister_tests(void)
{
@@ -2266,6 +2412,7 @@ void sip_request_parser_unregister_tests(void)
AST_TEST_UNREGISTER(parse_contact_header_test);
AST_TEST_UNREGISTER(sip_parse_options_test);
AST_TEST_UNREGISTER(sip_uri_cmp_test);
+ AST_TEST_UNREGISTER(get_viabranch_test);
}
int sip_reqresp_parser_init(void)