summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2009-03-23 13:14:26 +0000
committerBenny Prijono <bennylp@teluu.com>2009-03-23 13:14:26 +0000
commit1a2dc9890d46d3ff996f191498de1f1dbbe830bf (patch)
tree83a0c971eb486a97282079bff3074f6ef066fced
parentf08114796f552fffea47f9de39d58865fe306ca9 (diff)
Ticket #748: backported changes from ticket #747
git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/1.0@2538 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib-util/src/pjlib-util/scanner.c4
-rw-r--r--pjsip-apps/src/pjsua/pjsua_app.c97
-rw-r--r--pjsip/include/pjsip/sip_parser.h3
-rw-r--r--pjsip/src/pjsip/sip_parser.c123
-rw-r--r--pjsip/src/test-pjsip/msg_test.c136
-rw-r--r--tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_1.py52
-rw-r--r--tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_2.py25
-rw-r--r--tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_3.py35
-rw-r--r--tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_4.py25
-rw-r--r--tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_5.py25
10 files changed, 492 insertions, 33 deletions
diff --git a/pjlib-util/src/pjlib-util/scanner.c b/pjlib-util/src/pjlib-util/scanner.c
index a5a56160..6e01ba6f 100644
--- a/pjlib-util/src/pjlib-util/scanner.c
+++ b/pjlib-util/src/pjlib-util/scanner.c
@@ -28,7 +28,7 @@
#define PJ_SCAN_IS_SPACE(c) ((c)==' ' || (c)=='\t')
#define PJ_SCAN_IS_NEWLINE(c) ((c)=='\r' || (c)=='\n')
#define PJ_SCAN_IS_PROBABLY_SPACE(c) ((c) <= 32)
-#define PJ_SCAN_CHECK_EOF(s) (*s)
+#define PJ_SCAN_CHECK_EOF(s) (s != scanner->end)
#if defined(PJ_SCANNER_USE_BITWISE) && PJ_SCANNER_USE_BITWISE != 0
@@ -375,7 +375,7 @@ PJ_DEF(void) pj_scan_get_quotes(pj_scanner *scanner,
*/
do {
/* loop until end_quote is found. */
- while (*s && *s != '\n' && *s != end_quote[qpair]) {
+ while (PJ_SCAN_CHECK_EOF(s) && *s != '\n' && *s != end_quote[qpair]) {
++s;
}
diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c
index 5414b087..63e52ca2 100644
--- a/pjsip-apps/src/pjsua/pjsua_app.c
+++ b/pjsip-apps/src/pjsua/pjsua_app.c
@@ -4015,6 +4015,97 @@ on_exit:
;
}
+/*****************************************************************************
+ * A simple module to handle otherwise unhandled request. We will register
+ * this with the lowest priority.
+ */
+
+/* Notification on incoming request */
+static pj_bool_t default_mod_on_rx_request(pjsip_rx_data *rdata)
+{
+ pjsip_tx_data *tdata;
+ pjsip_status_code status_code;
+ pj_status_t status;
+
+ /* Don't respond to ACK! */
+ if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
+ &pjsip_ack_method) == 0)
+ return PJ_TRUE;
+
+ /* Create basic response. */
+ if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
+ &pjsip_notify_method) == 0)
+ {
+ /* Unsolicited NOTIFY's, send with Bad Request */
+ status_code = PJSIP_SC_BAD_REQUEST;
+ } else {
+ /* Probably unknown method */
+ status_code = PJSIP_SC_METHOD_NOT_ALLOWED;
+ }
+ status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(),
+ rdata, status_code,
+ NULL, &tdata);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Unable to create response", status);
+ return PJ_TRUE;
+ }
+
+ /* Add Allow if we're responding with 405 */
+ if (status_code == PJSIP_SC_METHOD_NOT_ALLOWED) {
+ const pjsip_hdr *cap_hdr;
+ cap_hdr = pjsip_endpt_get_capability(pjsua_get_pjsip_endpt(),
+ PJSIP_H_ALLOW, NULL);
+ if (cap_hdr) {
+ pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_clone(tdata->pool,
+ cap_hdr));
+ }
+ }
+
+ /* Add User-Agent header */
+ {
+ pj_str_t user_agent;
+ char tmp[80];
+ const pj_str_t USER_AGENT = { "User-Agent", 10};
+ pjsip_hdr *h;
+
+ pj_ansi_snprintf(tmp, sizeof(tmp), "PJSUA v%s/%s",
+ pj_get_version(), PJ_OS_NAME);
+ pj_strdup2_with_null(tdata->pool, &user_agent, tmp);
+
+ h = (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool,
+ &USER_AGENT,
+ &user_agent);
+ pjsip_msg_add_hdr(tdata->msg, h);
+ }
+
+ pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(), rdata, tdata,
+ NULL, NULL);
+
+ return PJ_TRUE;
+}
+
+
+/* The module instance. */
+static pjsip_module mod_default_handler =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-default-handler", 19 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION+99, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &default_mod_on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+
+};
+
+
+
/*****************************************************************************
* Public API
@@ -4065,6 +4156,12 @@ pj_status_t app_init(int argc, char *argv[])
if (status != PJ_SUCCESS)
return status;
+ /* Initialize our module to handle otherwise unhandled request */
+ status = pjsip_endpt_register_module(pjsua_get_pjsip_endpt(),
+ &mod_default_handler);
+ if (status != PJ_SUCCESS)
+ return status;
+
#ifdef STEREO_DEMO
stereo_demo();
#endif
diff --git a/pjsip/include/pjsip/sip_parser.h b/pjsip/include/pjsip/sip_parser.h
index b3e6a671..34e049ab 100644
--- a/pjsip/include/pjsip/sip_parser.h
+++ b/pjsip/include/pjsip/sip_parser.h
@@ -336,6 +336,9 @@ typedef struct pjsip_parser_const_t
pj_cis_t pjsip_ALNUM_SPEC; /**< Decimal + Alpha. */
pj_cis_t pjsip_TOKEN_SPEC; /**< Token. */
pj_cis_t pjsip_TOKEN_SPEC_ESC; /**< Token without '%' character */
+ pj_cis_t pjsip_VIA_PARAM_SPEC; /**< Via param is token + ":" for
+ IPv6. */
+ pj_cis_t pjsip_VIA_PARAM_SPEC_ESC; /**< .. as above without '%' */
pj_cis_t pjsip_HEX_SPEC; /**< Hexadecimal digits. */
pj_cis_t pjsip_PARAM_CHAR_SPEC; /**< For scanning pname (or pvalue
when it's not quoted.) in URI */
diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c
index 5a45817f..e86cf601 100644
--- a/pjsip/src/pjsip/sip_parser.c
+++ b/pjsip/src/pjsip/sip_parser.c
@@ -54,8 +54,6 @@
*/
#define GENERIC_URI_CHARS "#?;:@&=+-_.!~*'()%$,/" "%"
-#define PJSIP_VERSION "SIP/2.0"
-
#define UNREACHED(expr)
#define IS_NEWLINE(c) ((c)=='\r' || (c)=='\n')
@@ -327,6 +325,14 @@ static pj_status_t init_parser()
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_del_str(&pconst.pjsip_TOKEN_SPEC_ESC, "%");
+ status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC, &pconst.pjsip_TOKEN_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC, ":");
+
+ status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC_ESC, &pconst.pjsip_TOKEN_SPEC_ESC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC, ":");
+
status = pj_cis_dup(&pconst.pjsip_HOST_SPEC, &pconst.pjsip_ALNUM_SPEC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_add_str( &pconst.pjsip_HOST_SPEC, HOST);
@@ -772,6 +778,8 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size,
const char *pos;
const char *line;
int content_length = -1;
+ pj_str_t cur_msg;
+ const pj_str_t end_hdr = { "\n\r\n", 3};
*msg_size = size;
@@ -781,8 +789,12 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size,
}
- /* Find the end of header area by finding an empty line. */
- pos = pj_ansi_strstr(buf, "\n\r\n");
+ /* Find the end of header area by finding an empty line.
+ * Don't use plain strstr() since we want to be able to handle
+ * NULL character in the message
+ */
+ cur_msg.ptr = (char*)buf; cur_msg.slen = size;
+ pos = pj_strstr(&cur_msg, &end_hdr);
if (pos == NULL) {
return PJSIP_EPARTIALMSG;
}
@@ -791,7 +803,7 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size,
body_start = pos+3;
/* Find "Content-Length" header the hard way. */
- line = pj_ansi_strchr(buf, '\n');
+ line = pj_strchr(&cur_msg, '\n');
while (line && line < hdr_end) {
++line;
if ( ((*line=='C' || *line=='c') &&
@@ -842,7 +854,9 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size,
break;
/* Go to next line. */
- line = pj_ansi_strchr(line, '\n');
+ cur_msg.slen -= (line - cur_msg.ptr);
+ cur_msg.ptr = (char*)line;
+ line = pj_strchr(&cur_msg, '\n');
}
/* Found Content-Length? */
@@ -893,6 +907,36 @@ PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool,
return NULL;
}
+/* SIP version */
+static void parse_sip_version(pj_scanner *scanner)
+{
+ pj_str_t SIP = { "SIP", 3 };
+ pj_str_t V2 = { "2.0", 3 };
+ pj_str_t sip, version;
+
+ pj_scan_get( scanner, &pconst.pjsip_ALPHA_SPEC, &sip);
+ if (pj_scan_get_char(scanner) != '/')
+ on_syntax_error(scanner);
+ pj_scan_get_n( scanner, 3, &version);
+ if (pj_stricmp(&sip, &SIP) || pj_stricmp(&version, &V2))
+ on_syntax_error(scanner);
+}
+
+static pj_bool_t is_next_sip_version(pj_scanner *scanner)
+{
+ pj_str_t SIP = { "SIP", 3 };
+ pj_str_t sip;
+ int c;
+
+ c = pj_scan_peek(scanner, &pconst.pjsip_ALPHA_SPEC, &sip);
+ /* return TRUE if it is "SIP" followed by "/" or space.
+ * we include space since the "/" may be separated by space,
+ * although this would mean it would return TRUE if it is a
+ * request and the method is "SIP"!
+ */
+ return c && (c=='/' || c==' ' || c=='\t') && pj_stricmp(&sip, &SIP)==0;
+}
+
/* Internal function to parse SIP message */
static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx,
pjsip_parser_err_report *err_list)
@@ -926,7 +970,7 @@ retry_parse:
return NULL;
/* Parse request or status line */
- if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) == 0) {
+ if (is_next_sip_version(scanner)) {
msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG);
int_parse_status_line( scanner, &msg->line.status );
} else {
@@ -1125,7 +1169,7 @@ PJ_DEF(void) pjsip_parse_uri_param_imp( pj_scanner *scanner, pj_pool_t *pool,
}
-/* Parse parameter (";" pname ["=" pvalue]) in header. */
+/* Parse parameter (";" pname ["=" pvalue]) in SIP header. */
static void int_parse_param( pj_scanner *scanner, pj_pool_t *pool,
pj_str_t *pname, pj_str_t *pvalue,
unsigned option)
@@ -1513,9 +1557,7 @@ static void int_parse_req_line( pj_scanner *scanner, pj_pool_t *pool,
pjsip_method_init_np( &req_line->method, &token);
req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE);
- if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) != 0)
- PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
- pj_scan_advance_n (scanner, 7, 1);
+ parse_sip_version(scanner);
pj_scan_get_newline( scanner );
}
@@ -1525,10 +1567,7 @@ static void int_parse_status_line( pj_scanner *scanner,
{
pj_str_t token;
- if (pj_scan_stricmp_alnum(scanner, PJSIP_VERSION, 7) != 0)
- PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
- pj_scan_advance_n( scanner, 7, 1);
-
+ parse_sip_version(scanner);
pj_scan_get( scanner, &pconst.pjsip_DIGIT_SPEC, &token);
status_line->code = pj_strtoul(&token);
if (*scanner->curptr != '\r' && *scanner->curptr != '\n')
@@ -1618,12 +1657,32 @@ end:
/* Parse generic string header. */
static void parse_generic_string_hdr( pjsip_generic_string_hdr *hdr,
- pj_scanner *scanner )
+ pjsip_parse_ctx *ctx)
{
- if (pj_cis_match(&pconst.pjsip_NOT_NEWLINE, *scanner->curptr))
+ pj_scanner *scanner = ctx->scanner;
+
+ hdr->hvalue.slen = 0;
+
+ /* header may be mangled hence the loop */
+ while (pj_cis_match(&pconst.pjsip_NOT_NEWLINE, *scanner->curptr)) {
+ pj_str_t next, tmp;
+
pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &hdr->hvalue);
- else
- hdr->hvalue.slen = 0;
+ if (pj_scan_is_eof(scanner) || IS_NEWLINE(*scanner->curptr))
+ break;
+ /* mangled, get next fraction */
+ pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &next);
+ /* concatenate */
+ tmp.ptr = (char*)pj_pool_alloc(ctx->pool,
+ hdr->hvalue.slen + next.slen + 2);
+ tmp.slen = 0;
+ pj_strcpy(&tmp, &hdr->hvalue);
+ pj_strcat2(&tmp, " ");
+ pj_strcat(&tmp, &next);
+ tmp.ptr[tmp.slen] = '\0';
+
+ hdr->hvalue = tmp;
+ }
parse_hdr_end(scanner);
}
@@ -1934,13 +1993,20 @@ static void int_parse_via_param( pjsip_via_hdr *hdr, pj_scanner *scanner,
pj_str_t pname, pvalue;
//Parse with PARAM_CHAR instead, to allow IPv6
+ //No, back to using int_parse_param() for the "`" character!
//int_parse_param( scanner, pool, &pname, &pvalue, 0);
- /* Get ';' character */
+ //parse_param_imp(scanner, pool, &pname, &pvalue,
+ // &pconst.pjsip_TOKEN_SPEC,
+ // &pconst.pjsip_TOKEN_SPEC_ESC, 0);
+ //int_parse_param(scanner, pool, &pname, &pvalue, 0);
+ // This should be the correct one:
+ // added special spec for Via parameter, basically token plus
+ // ":" to allow IPv6 address in the received param.
pj_scan_get_char(scanner);
-
- parse_param_imp(scanner, pool, &pname, &pvalue,
- &pconst.pjsip_PARAM_CHAR_SPEC,
- &pconst.pjsip_PARAM_CHAR_SPEC_ESC, 0);
+ parse_param_imp(scanner, pool, &pname, &pvalue,
+ &pconst.pjsip_VIA_PARAM_SPEC,
+ &pconst.pjsip_VIA_PARAM_SPEC_ESC,
+ 0);
if (!parser_stricmp(pname, pconst.pjsip_BRANCH_STR) && pvalue.slen) {
hdr->branch_param = pvalue;
@@ -2075,10 +2141,9 @@ static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx )
else
pj_list_insert_before(first, hdr);
- if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION "/", 8) != 0)
- PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
-
- pj_scan_advance_n( scanner, 8, 1);
+ parse_sip_version(scanner);
+ if (pj_scan_get_char(scanner) != '/')
+ on_syntax_error(scanner);
pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &hdr->transport);
int_parse_host(scanner, &hdr->sent_by.host);
@@ -2119,7 +2184,7 @@ static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx )
pjsip_generic_string_hdr *hdr;
hdr = pjsip_generic_string_hdr_create(ctx->pool, NULL, NULL);
- parse_generic_string_hdr(hdr, ctx->scanner);
+ parse_generic_string_hdr(hdr, ctx);
return (pjsip_hdr*)hdr;
}
diff --git a/pjsip/src/test-pjsip/msg_test.c b/pjsip/src/test-pjsip/msg_test.c
index ea7af64b..6aad1f8a 100644
--- a/pjsip/src/test-pjsip/msg_test.c
+++ b/pjsip/src/test-pjsip/msg_test.c
@@ -73,6 +73,7 @@ struct test_msg
"P-Associated-URI:\r\n" /* empty header without space */
"\r\n",
&create_msg0,
+ 0,
PJ_SUCCESS
},
{
@@ -100,6 +101,136 @@ struct test_msg
"m=audio 3456 RTP/AVP 0 1 3 99\r\n"
"a=rtpmap:0 PCMU/8000\r\n",
&create_msg1,
+ 0,
+ PJ_SUCCESS
+},
+{
+ /* Torture message from RFC 4475
+ * 3.1.1.1 A short tortuous INVITE
+ */
+ "INVITE sip:vivekg@chair-dnrc.example.com;unknownparam SIP/2.0\n"
+ "TO :\n"
+ " sip:vivekg@chair-dnrc.example.com ; tag = 1918181833n\n"
+ "from : \"J Rosenberg \\\\\\\"\" <sip:jdrosen@example.com>\n"
+ " ;\n"
+ " tag = 98asjd8\n"
+ "MaX-fOrWaRdS: 0068\n"
+ "Call-ID: wsinv.ndaksdj@192.0.2.1\n"
+ "Content-Length : 150\n"
+ "cseq: 0009\n"
+ " INVITE\n"
+ "Via : SIP / 2.0\n"
+ " /UDP\n"
+ " 192.0.2.2;rport;branch=390skdjuw\n"
+ "s :\n"
+ "NewFangledHeader: newfangled value\n"
+ " continued newfangled value\n"
+ "UnknownHeaderWithUnusualValue: ;;,,;;,;\n"
+ "Content-Type: application/sdp\n"
+ "Route:\n"
+ " <sip:services.example.com;lr;unknownwith=value;unknown-no-value>\n"
+ "v: SIP / 2.0 / TCP spindle.example.com ;\n"
+ " branch = z9hG4bK9ikj8 ,\n"
+ " SIP / 2.0 / UDP 192.168.255.111 ; branch=\n"
+ " z9hG4bK30239\n"
+ "m:\"Quoted string \\\"\\\"\" <sip:jdrosen@example.com> ; newparam =\n"
+ " newvalue ;\n"
+ " secondparam ; q = 0.33\r\n"
+ "\r\n"
+ "v=0\r\n"
+ "o=mhandley 29739 7272939 IN IP4 192.0.2.3\r\n"
+ "s=-\r\n"
+ "c=IN IP4 192.0.2.4\r\n"
+ "t=0 0\r\n"
+ "m=audio 49217 RTP/AVP 0 12\r\n"
+ "m=video 3227 RTP/AVP 31\r\n"
+ "a=rtpmap:31 LPC\r\n",
+ NULL,
+ 0,
+ PJ_SUCCESS
+},
+{
+ /* Torture message from RFC 4475
+ * 3.1.1.2 Wide Range of Valid Characters
+ */
+ "!interesting-Method0123456789_*+`.%indeed'~ sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*:&it+has=1,weird!*pas$wo~d_too.(doesn't-it)@example.com SIP/2.0\n"
+ "Via: SIP/2.0/UDP host1.example.com;rport;branch=z9hG4bK-.!%66*_+`'~\n"
+ "To: \"BEL:\\\x07 NUL:\\\x00 DEL:\\\x7F\" <sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*@example.com>\n"
+ "From: token1~` token2'+_ token3*%!.- <sip:mundane@example.com> ;fromParam''~+*_!.-%=\"\xD1\x80\xD0\xB0\xD0\xB1\xD0\xBE\xD1\x82\xD0\xB0\xD1\x8E\xD1\x89\xD0\xB8\xD0\xB9\";tag=_token~1'+`*%!-.\n"
+ "Call-ID: intmeth.word%ZK-!.*_+'@word`~)(><:\\/\"][?}{\n"
+ "CSeq: 139122385 !interesting-Method0123456789_*+`.%indeed'~\n"
+ "Max-Forwards: 255\n"
+ "extensionHeader-!.%*+_`'~: \xEF\xBB\xBF\xE5\xA4\xA7\xE5\x81\x9C\xE9\x9B\xBB\n"
+ "Content-Length: 0\r\n\r\n",
+ NULL,
+ 641,
+ PJ_SUCCESS
+},
+{
+ /* Torture message from RFC 4475
+ * 3.1.1.3 Valid Use of the % Escaping Mechanism
+ */
+ "INVITE sip:sips%3Auser%40example.com@example.net SIP/2.0\n"
+ "To: sip:%75se%72@example.com\n"
+ "From: <sip:I%20have%20spaces@example.net>;tag=1234\n"
+ "Max-Forwards: 87\n"
+ "i: esc01.239409asdfakjkn23onasd0-3234\n"
+ "CSeq: 234234 INVITE\n"
+ "Via: SIP/2.0/UDP host5.example.net;rport;branch=z9hG4bKkdjuw\n"
+ "C: application/sdp\n"
+ "Contact:\n"
+ " <sip:cal%6Cer@192.168.0.2:5060;%6C%72;n%61me=v%61lue%25%34%31>\n"
+ "Content-Length: 150\r\n"
+ "\r\n"
+ "v=0\r\n"
+ "o=mhandley 29739 7272939 IN IP4 192.0.2.1\r\n"
+ "s=-\r\n"
+ "c=IN IP4 192.0.2.1\r\n"
+ "t=0 0\r\n"
+ "m=audio 49217 RTP/AVP 0 12\r\n"
+ "m=video 3227 RTP/AVP 31\r\n"
+ "a=rtpmap:31 LPC\r\n",
+ NULL,
+ 0,
+ PJ_SUCCESS
+},
+{
+ /* Torture message from RFC 4475
+ * 3.1.1.4 Escaped Nulls in URIs
+ */
+ "REGISTER sip:example.com SIP/2.0\r\n"
+ "To: sip:null-%00-null@example.com\r\n"
+ "From: sip:null-%00-null@example.com;tag=839923423\r\n"
+ "Max-Forwards: 70\r\n"
+ "Call-ID: escnull.39203ndfvkjdasfkq3w4otrq0adsfdfnavd\r\n"
+ "CSeq: 14398234 REGISTER\r\n"
+ "Via: SIP/2.0/UDP host5.example.com;rport;branch=z9hG4bKkdjuw\r\n"
+ "Contact: <sip:%00@host5.example.com>\r\n"
+ "Contact: <sip:%00%00@host5.example.com>\r\n"
+ "L:0\r\n"
+ "\r\n",
+ NULL,
+ 0,
+ PJ_SUCCESS
+},
+{
+ /* Torture message from RFC 4475
+ * 3.1.1.5 Use of % When It Is Not an Escape
+ */
+ "RE%47IST%45R sip:registrar.example.com SIP/2.0\r\n"
+ "To: \"%Z%45\" <sip:resource@example.com>\r\n"
+ "From: \"%Z%45\" <sip:resource@example.com>;tag=f232jadfj23\r\n"
+ "Call-ID: esc02.asdfnqwo34rq23i34jrjasdcnl23nrlknsdf\r\n"
+ "Via: SIP/2.0/TCP host.example.com;rport;branch=z9hG4bK209%fzsnel234\r\n"
+ "CSeq: 29344 RE%47IST%45R\r\n"
+ "Max-Forwards: 70\r\n"
+ "Contact: <sip:alias1@host1.example.com>\r\n"
+ "C%6Fntact: <sip:alias2@host2.example.com>\r\n"
+ "Contact: <sip:alias3@host3.example.com>\r\n"
+ "l: 0\r\n"
+ "\r\n",
+ NULL,
+ 0,
PJ_SUCCESS
}
};
@@ -126,7 +257,8 @@ static pj_status_t test_entry( pj_pool_t *pool, struct test_msg *entry )
char msgbuf2[PJSIP_MAX_PKT_LEN];
enum { BUFLEN = 512 };
- entry->len = pj_ansi_strlen(entry->msg);
+ if (entry->len==0)
+ entry->len = pj_ansi_strlen(entry->msg);
if (var.flag & FLAG_PARSE_ONLY)
goto parse_msg;
@@ -180,7 +312,7 @@ parse_msg:
pj_sub_timestamp(&t2, &t1);
pj_add_timestamp(&var.parse_time, &t2);
- if (var.flag & FLAG_PARSE_ONLY)
+ if ((var.flag & FLAG_PARSE_ONLY) || entry->creator==NULL)
return PJ_SUCCESS;
/* Create reference message. */
diff --git a/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_1.py b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_1.py
new file mode 100644
index 00000000..35f803c7
--- /dev/null
+++ b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_1.py
@@ -0,0 +1,52 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+# Torture message from RFC 4475
+# 3.1.1. Valid Messages
+# 3.1.1.1. A Short Tortuous INVITE
+complete_msg = \
+"""INVITE sip:vivekg@chair-dnrc.example.com;unknownparam SIP/2.0
+TO :
+ sip:vivekg@chair-dnrc.example.com ; tag = 1918181833n
+from : "J Rosenberg \\\\\\"" <sip:jdrosen@example.com>
+ ;
+ tag = 98asjd8
+MaX-fOrWaRdS: 0068
+Call-ID: wsinv.ndaksdj@192.0.2.1
+Content-Length : 150
+cseq: 0009
+ INVITE
+Via : SIP / 2.0
+ /UDP
+ 192.0.2.2;rport;branch=390skdjuw
+s :
+NewFangledHeader: newfangled value
+ continued newfangled value
+UnknownHeaderWithUnusualValue: ;;,,;;,;
+Content-Type: application/sdp
+Route:
+ <sip:services.example.com;lr;unknownwith=value;unknown-no-value>
+v: SIP / 2.0 / TCP spindle.example.com ;
+ branch = z9hG4bK9ikj8 ,
+ SIP / 2.0 / UDP 192.168.255.111 ; branch=
+ z9hG4bK30239
+m:"Quoted string \\"\\"" <sip:jdrosen@example.com> ; newparam =
+ newvalue ;
+ secondparam ; q = 0.33
+
+v=0
+o=mhandley 29739 7272939 IN IP4 192.0.2.3
+s=-
+c=IN IP4 192.0.2.4
+t=0 0
+m=audio 49217 RTP/AVP 0 12
+m=video 3227 RTP/AVP 31
+a=rtpmap:31 LPC
+"""
+
+
+sendto_cfg = sip.SendtoCfg( "RFC 4475 3.1.1.1",
+ "--null-audio --auto-answer 200",
+ "", 481, complete_msg=complete_msg)
+
diff --git a/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_2.py b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_2.py
new file mode 100644
index 00000000..88fd249b
--- /dev/null
+++ b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_2.py
@@ -0,0 +1,25 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+# Torture message from RFC 4475
+# 3.1.1. Valid Messages
+# 3.1.1.2. Wide Range of Valid Characters
+complete_msg = \
+"""!interesting-Method0123456789_*+`.%indeed'~ sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*:&it+has=1,weird!*pas$wo~d_too.(doesn't-it)@example.com SIP/2.0
+Via: SIP/2.0/UDP host1.example.com;rport;branch=z9hG4bK-.!%66*_+`'~
+To: "BEL:\\\x07 NUL:\\\x00 DEL:\\\x7F" <sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*@example.com>
+From: token1~` token2'+_ token3*%!.- <sip:mundane@example.com> ;fromParam''~+*_!.-%="\xD1\x80\xD0\xB0\xD0\xB1\xD0\xBE\xD1\x82\xD0\xB0\xD1\x8E\xD1\x89\xD0\xB8\xD0\xB9";tag=_token~1'+`*%!-.
+Call-ID: intmeth.word%ZK-!.*_+'@word`~)(><:\\/"][?}{
+CSeq: 139122385 !interesting-Method0123456789_*+`.%indeed'~
+Max-Forwards: 255
+extensionHeader-!.%*+_`'~: \xEF\xBB\xBF\xE5\xA4\xA7\xE5\x81\x9C\xE9\x9B\xBB
+Content-Length: 0
+
+"""
+
+
+sendto_cfg = sip.SendtoCfg( "RFC 4475 3.1.1.2",
+ "--null-audio --auto-answer 200",
+ "", 405, complete_msg=complete_msg)
+
diff --git a/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_3.py b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_3.py
new file mode 100644
index 00000000..4f32e979
--- /dev/null
+++ b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_3.py
@@ -0,0 +1,35 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+# Torture message from RFC 4475
+# 3.1.1. Valid Messages
+# 3.1.1.3. Valid Use of the % Escaping Mechanism
+complete_msg = \
+"""INVITE sip:sips%3Auser%40example.com@example.net SIP/2.0
+To: sip:%75se%72@example.com
+From: <sip:I%20have%20spaces@example.net>;tag=$FROM_TAG
+Max-Forwards: 87
+i: esc01.239409asdfakjkn23onasd0-3234
+CSeq: 234234 INVITE
+Via: SIP/2.0/UDP host5.example.net;rport;branch=z9hG4bKkdjuw
+C: application/sdp
+Contact:
+ <sip:cal%6Cer@$LOCAL_IP:$LOCAL_PORT;%6C%72;n%61me=v%61lue%25%34%31>
+Content-Length: 150
+
+v=0
+o=mhandley 29739 7272939 IN IP4 192.0.2.1
+s=-
+c=IN IP4 192.0.2.1
+t=0 0
+m=audio 49217 RTP/AVP 0 12
+m=video 3227 RTP/AVP 31
+a=rtpmap:31 LPC
+"""
+
+
+sendto_cfg = sip.SendtoCfg( "RFC 4475 3.1.1.3",
+ "--null-audio --auto-answer 200",
+ "", 200, complete_msg=complete_msg)
+
diff --git a/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_4.py b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_4.py
new file mode 100644
index 00000000..7a05c144
--- /dev/null
+++ b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_4.py
@@ -0,0 +1,25 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+# Torture message from RFC 4475
+# 3.1.1. Valid Messages
+# 3.1.1.4. Escaped Nulls in URIs
+complete_msg = \
+"""REGISTER sip:example.com SIP/2.0
+To: sip:null-%00-null@example.com
+From: sip:null-%00-null@example.com;tag=839923423
+Max-Forwards: 70
+Call-ID: escnull.39203ndfvkjdasfkq3w4otrq0adsfdfnavd
+CSeq: 14398234 REGISTER
+Via: SIP/2.0/UDP host5.example.com;rport;branch=z9hG4bKkdjuw
+Contact: <sip:%00@host5.example.com>
+Contact: <sip:%00%00@host5.example.com>
+L:0
+"""
+
+
+sendto_cfg = sip.SendtoCfg( "RFC 4475 3.1.1.4",
+ "--null-audio --auto-answer 200",
+ "", 405, complete_msg=complete_msg)
+
diff --git a/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_5.py b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_5.py
new file mode 100644
index 00000000..2b449d11
--- /dev/null
+++ b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_5.py
@@ -0,0 +1,25 @@
+# $Id$
+import inc_sip as sip
+import inc_sdp as sdp
+
+# Torture message from RFC 4475
+# 3.1.1. Valid Messages
+# 3.1.1.5. Use of % When It Is Not an Escape
+complete_msg = \
+"""RE%47IST%45R sip:registrar.example.com SIP/2.0
+To: "%Z%45" <sip:resource@example.com>
+From: "%Z%45" <sip:resource@example.com>;tag=f232jadfj23
+Call-ID: esc02.asdfnqwo34rq23i34jrjasdcnl23nrlknsdf
+Via: SIP/2.0/TCP host.example.com;rport;branch=z9hG4bK209%fzsnel234
+CSeq: 29344 RE%47IST%45R
+Max-Forwards: 70
+Contact: <sip:alias1@host1.example.com>
+C%6Fntact: <sip:alias2@host2.example.com>
+Contact: <sip:alias3@host3.example.com>
+l: 0
+"""
+
+sendto_cfg = sip.SendtoCfg( "RFC 4475 3.1.1.5",
+ "--null-audio --auto-answer 200",
+ "", 405, complete_msg=complete_msg)
+