/* $Id$ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "test.h" #include #include #define POOL_SIZE 8000 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 # define LOOP 10000 #else # define LOOP 100000 #endif #define AVERAGE_MSG_LEN 800 #define THIS_FILE "msg_test.c" static pjsip_msg *create_msg0(pj_pool_t *pool); static pjsip_msg *create_msg1(pj_pool_t *pool); #define STATUS_PARTIAL 1 #define STATUS_SYNTAX_ERROR 2 #define FLAG_DETECT_ONLY 1 #define FLAG_PARSE_ONLY 4 #define FLAG_PRINT_ONLY 8 struct test_msg { char msg[1024]; pjsip_msg *(*creator)(pj_pool_t *pool); pj_size_t len; int expected_status; } test_array[] = { { /* 'Normal' message with all headers. */ "INVITE sip:user@foo SIP/2.0\n" "from: Hi I'm Joe ;tag=123457890123456\r" "To: Fellow User \r\n" "Call-ID: 12345678901234567890@bar\r\n" "Content-Length: 0\r\n" "CSeq: 123456 INVITE\n" "Contact: ; q=0.5;expires=3600,sip:user@host;q=0.500\r" " ,sip:user2@host2\n" "Content-Type: text/html ; charset=ISO-8859-4\r" "Route: ,\r\n" " \r" "Record-Route: ,\r\n" /* multiple routes+folding*/ " \n" "v: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c230\n" "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n" /* folding. */ " ;received=192.0.2.1\r\n" "Via: SIP/2.0/UDP 10.2.1.1, SIP/2.0/TCP 192.168.1.1\n" "Organization: \r" "Max-Forwards: 70\n" "X-Header: \r\n" /* empty header */ "P-Associated-URI:\r\n" /* empty header without space */ "\r\n", &create_msg0, 0, PJ_SUCCESS }, { /* Typical response message. */ "SIP/2.0 200 OK\r\n" "Via: SIP/2.0/SCTP server10.biloxi.com;branch=z9hG4bKnashds8;rport;received=192.0.2.1\r\n" "Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2\r\n" "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds ;received=192.0.2.3\r\n" "Route: \r\n" "Route: \r\n" "Max-Forwards: 70\r\n" "To: Bob ;tag=a6c85cf\r\n" "From: Alice ;tag=1928301774\r\n" "Call-ID: a84b4c76e66710@pc33.atlanta.com\r\n" "CSeq: 314159 INVITE\r\n" "Contact: \r\n" "Content-Type: application/sdp\r\n" "Content-Length: 150\r\n" "\r\n" "v=0\r\n" "o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com\r\n" "s=-\r\n" "t=0 0\r\n" "c=IN IP4 pc33.atlanta.com\r\n" "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 \\\\\\\"\" \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" " \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 \\\"\\\"\" ; 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\" \n" "From: token1~` token2'+_ token3*%!.- ;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: ;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" " \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: \r\n" "Contact: \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\" \r\n" "From: \"%Z%45\" ;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: \r\n" "C%6Fntact: \r\n" "Contact: \r\n" "l: 0\r\n" "\r\n", NULL, 0, PJ_SUCCESS } }; static struct { int flag; pj_highprec_t detect_len, parse_len, print_len; pj_timestamp detect_time, parse_time, print_time; } var; static pj_status_t test_entry( pj_pool_t *pool, struct test_msg *entry ) { pjsip_msg *parsed_msg, *ref_msg = NULL; static pjsip_msg *print_msg; pj_status_t status = PJ_SUCCESS; pj_ssize_t len; pj_str_t str1, str2; pjsip_hdr *hdr1, *hdr2; pj_timestamp t1, t2; pjsip_parser_err_report err_list; pj_size_t msg_size; char msgbuf1[PJSIP_MAX_PKT_LEN]; char msgbuf2[PJSIP_MAX_PKT_LEN]; enum { BUFLEN = 512 }; if (entry->len==0) entry->len = pj_ansi_strlen(entry->msg); if (var.flag & FLAG_PARSE_ONLY) goto parse_msg; if (var.flag & FLAG_PRINT_ONLY) { if (print_msg == NULL) print_msg = entry->creator(pool); goto print_msg; } /* Detect message. */ var.detect_len = var.detect_len + entry->len; pj_get_timestamp(&t1); status = pjsip_find_msg(entry->msg, entry->len, PJ_FALSE, &msg_size); if (status != PJ_SUCCESS) { if (status!=PJSIP_EPARTIALMSG || entry->expected_status!=STATUS_PARTIAL) { app_perror(" error: unable to detect message", status); return -5; } } if (msg_size != entry->len) { PJ_LOG(3,(THIS_FILE, " error: size mismatch")); return -6; } pj_get_timestamp(&t2); pj_sub_timestamp(&t2, &t1); pj_add_timestamp(&var.detect_time, &t2); if (var.flag & FLAG_DETECT_ONLY) return PJ_SUCCESS; /* Parse message. */ parse_msg: var.parse_len = var.parse_len + entry->len; pj_get_timestamp(&t1); pj_list_init(&err_list); parsed_msg = pjsip_parse_msg(pool, entry->msg, entry->len, &err_list); if (parsed_msg == NULL) { if (entry->expected_status != STATUS_SYNTAX_ERROR) { status = -10; if (err_list.next != &err_list) { PJ_LOG(3,(THIS_FILE, " Syntax error in line %d col %d", err_list.next->line, err_list.next->col)); } goto on_return; } } pj_get_timestamp(&t2); pj_sub_timestamp(&t2, &t1); pj_add_timestamp(&var.parse_time, &t2); if ((var.flag & FLAG_PARSE_ONLY) || entry->creator==NULL) return PJ_SUCCESS; /* Create reference message. */ ref_msg = entry->creator(pool); /* Create buffer for comparison. */ str1.ptr = (char*)pj_pool_alloc(pool, BUFLEN); str2.ptr = (char*)pj_pool_alloc(pool, BUFLEN); /* Compare message type. */ if (parsed_msg->type != ref_msg->type) { status = -20; goto on_return; } /* Compare request or status line. */ if (parsed_msg->type == PJSIP_REQUEST_MSG) { pjsip_method *m1 = &parsed_msg->line.req.method; pjsip_method *m2 = &ref_msg->line.req.method; if (pjsip_method_cmp(m1, m2) != 0) { status = -30; goto on_return; } status = pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI, parsed_msg->line.req.uri, ref_msg->line.req.uri); if (status != PJ_SUCCESS) { app_perror(" error: request URI mismatch", status); status = -31; goto on_return; } } else { if (parsed_msg->line.status.code != ref_msg->line.status.code) { PJ_LOG(3,(THIS_FILE, " error: status code mismatch")); status = -32; goto on_return; } if (pj_strcmp(&parsed_msg->line.status.reason, &ref_msg->line.status.reason) != 0) { PJ_LOG(3,(THIS_FILE, " error: status text mismatch")); status = -33; goto on_return; } } /* Compare headers. */ hdr1 = parsed_msg->hdr.next; hdr2 = ref_msg->hdr.next; while (hdr1 != &parsed_msg->hdr && hdr2 != &ref_msg->hdr) { len = pjsip_hdr_print_on(hdr1, str1.ptr, BUFLEN); if (len < 0) { status = -40; goto on_return; } str1.ptr[len] = '\0'; str1.slen = len; len = pjsip_hdr_print_on(hdr2, str2.ptr, BUFLEN); if (len < 0) { status = -50; goto on_return; } str2.ptr[len] = '\0'; str2.slen = len; if (pj_strcmp(&str1, &str2) != 0) { status = -60; PJ_LOG(3,(THIS_FILE, " error: header string mismatch:\n" " h1='%s'\n" " h2='%s'\n", str1.ptr, str2.ptr)); goto on_return; } hdr1 = hdr1->next; hdr2 = hdr2->next; } if (hdr1 != &parsed_msg->hdr || hdr2 != &ref_msg->hdr) { status = -70; goto on_return; } /* Compare body? */ if (parsed_msg->body==NULL && ref_msg->body==NULL) goto print_msg; /* Compare msg body length. */ if (parsed_msg->body->len != ref_msg->body->len) { status = -80; goto on_return; } /* Compare msg body content type. */ if (pj_strcmp(&parsed_msg->body->content_type.type, &ref_msg->body->content_type.type) != 0) { status = -90; goto on_return; } if (pj_strcmp(&parsed_msg->body->content_type.subtype, &ref_msg->body->content_type.subtype) != 0) { status = -100; goto on_return; } /* Compare body content. */ str1.slen = parsed_msg->body->print_body(parsed_msg->body, msgbuf1, sizeof(msgbuf1)); if (str1.slen < 1) { status = -110; goto on_return; } str1.ptr = msgbuf1; str2.slen = ref_msg->body->print_body(ref_msg->body, msgbuf2, sizeof(msgbuf2)); if (str2.slen < 1) { status = -120; goto on_return; } str2.ptr = msgbuf2; if (pj_strcmp(&str1, &str2) != 0) { status = -140; goto on_return; } /* Print message. */ print_msg: var.print_len = var.print_len + entry->len; pj_get_timestamp(&t1); if (var.flag & FLAG_PRINT_ONLY) ref_msg = print_msg; len = pjsip_msg_print(ref_msg, msgbuf1, PJSIP_MAX_PKT_LEN); if (len < 1) { status = -150; goto on_return; } pj_get_timestamp(&t2); pj_sub_timestamp(&t2, &t1); pj_add_timestamp(&var.print_time, &t2); status = PJ_SUCCESS; on_return: return status; } static pjsip_msg *create_msg0(pj_pool_t *pool) { pjsip_msg *msg; pjsip_name_addr *name_addr; pjsip_sip_uri *url; pjsip_fromto_hdr *fromto; pjsip_cid_hdr *cid; pjsip_clen_hdr *clen; pjsip_cseq_hdr *cseq; pjsip_contact_hdr *contact; pjsip_ctype_hdr *ctype; pjsip_routing_hdr *routing; pjsip_via_hdr *via; pjsip_generic_string_hdr *generic; pjsip_param *prm; pj_str_t str; msg = pjsip_msg_create(pool, PJSIP_REQUEST_MSG); /* "INVITE sip:user@foo SIP/2.0\n" */ pjsip_method_set(&msg->line.req.method, PJSIP_INVITE_METHOD); url = pjsip_sip_uri_create(pool, 0); msg->line.req.uri = (pjsip_uri*)url; pj_strdup2(pool, &url->user, "user"); pj_strdup2(pool, &url->host, "foo"); /* "From: Hi I'm Joe ;tag=123457890123456\r" */ fromto = pjsip_from_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)fromto); pj_strdup2(pool, &fromto->tag, "123457890123456"); name_addr = pjsip_name_addr_create(pool); fromto->uri = (pjsip_uri*)name_addr; pj_strdup2(pool, &name_addr->display, "Hi I'm Joe"); url = pjsip_sip_uri_create(pool, 0); name_addr->uri = (pjsip_uri*)url; pj_strdup2(pool, &url->user, "joe.user"); pj_strdup2(pool, &url->host, "bar.otherdomain.com"); /* "To: Fellow User \r\n" */ fromto = pjsip_to_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)fromto); name_addr = pjsip_name_addr_create(pool); fromto->uri = (pjsip_uri*)name_addr; pj_strdup2(pool, &name_addr->display, "Fellow User"); url = pjsip_sip_uri_create(pool, 0); name_addr->uri = (pjsip_uri*)url; pj_strdup2(pool, &url->user, "user"); pj_strdup2(pool, &url->host, "foo.bar.domain.com"); /* "Call-ID: 12345678901234567890@bar\r\n" */ cid = pjsip_cid_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)cid); pj_strdup2(pool, &cid->id, "12345678901234567890@bar"); /* "Content-Length: 0\r\n" */ clen = pjsip_clen_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)clen); clen->len = 0; /* "CSeq: 123456 INVITE\n" */ cseq = pjsip_cseq_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)cseq); cseq->cseq = 123456; pjsip_method_set(&cseq->method, PJSIP_INVITE_METHOD); /* "Contact: ;q=0.5;expires=3600*/ contact = pjsip_contact_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact); contact->q1000 = 500; contact->expires = 3600; name_addr = pjsip_name_addr_create(pool); contact->uri = (pjsip_uri*)name_addr; url = pjsip_sip_uri_create(pool, 0); name_addr->uri = (pjsip_uri*)url; pj_strdup2(pool, &url->user, "joe"); pj_strdup2(pool, &url->host, "bar"); /*, sip:user@host;q=0.500\r" */ contact = pjsip_contact_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact); contact->q1000 = 500; name_addr = pjsip_name_addr_create(pool); contact->uri = (pjsip_uri*)name_addr; url = pjsip_sip_uri_create(pool, 0); name_addr->uri = (pjsip_uri*)url; pj_strdup2(pool, &url->user, "user"); pj_strdup2(pool, &url->host, "host"); /* " ,sip:user2@host2\n" */ contact = pjsip_contact_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact); name_addr = pjsip_name_addr_create(pool); contact->uri = (pjsip_uri*)name_addr; url = pjsip_sip_uri_create(pool, 0); name_addr->uri = (pjsip_uri*)url; pj_strdup2(pool, &url->user, "user2"); pj_strdup2(pool, &url->host, "host2"); /* "Content-Type: text/html; charset=ISO-8859-4\r" */ ctype = pjsip_ctype_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)ctype); pj_strdup2(pool, &ctype->media.type, "text"); pj_strdup2(pool, &ctype->media.subtype, "html"); prm = PJ_POOL_ALLOC_T(pool, pjsip_param); prm->name = pj_str("charset"); prm->value = pj_str("ISO-8859-4"); pj_list_push_back(&ctype->media.param, prm); /* "Route: ,\r\n" */ routing = pjsip_route_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing); url = pjsip_sip_uri_create(pool, 0); routing->name_addr.uri = (pjsip_uri*)url; pj_strdup2(pool, &url->host, "bigbox3.site3.atlanta.com"); url->lr_param = 1; /* " \r" */ routing = pjsip_route_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing); url = pjsip_sip_uri_create(pool, 0); routing->name_addr.uri = (pjsip_uri*)url; pj_strdup2(pool, &url->host, "server10.biloxi.com"); url->lr_param = 1; /* "Record-Route: ,\r\n" */ routing = pjsip_rr_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing); url = pjsip_sip_uri_create(pool, 0); routing->name_addr.uri = (pjsip_uri*)url; pj_strdup2(pool, &url->host, "server10.biloxi.com"); url->lr_param = 0; /* " \n" */ routing = pjsip_rr_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)routing); url = pjsip_sip_uri_create(pool, 0); routing->name_addr.uri = (pjsip_uri*)url; pj_strdup2(pool, &url->host, "bigbox3.site3.atlanta.com"); url->lr_param = 1; /* "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c230\n" */ via = pjsip_via_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)via); pj_strdup2(pool, &via->transport, "SCTP"); pj_strdup2(pool, &via->sent_by.host, "bigbox3.site3.atlanta.com"); pj_strdup2(pool, &via->branch_param, "z9hG4bK77ef4c230"); /* "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n" " ;received=192.0.2.1\r\n" */ via = pjsip_via_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)via); pj_strdup2(pool, &via->transport, "UDP"); pj_strdup2(pool, &via->sent_by.host, "pc33.atlanta.com"); pj_strdup2(pool, &via->branch_param, "z9hG4bKnashds8"); pj_strdup2(pool, &via->recvd_param, "192.0.2.1"); /* "Via: SIP/2.0/UDP 10.2.1.1, */ via = pjsip_via_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)via); pj_strdup2(pool, &via->transport, "UDP"); pj_strdup2(pool, &via->sent_by.host, "10.2.1.1"); /*SIP/2.0/TCP 192.168.1.1\n" */ via = pjsip_via_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)via); pj_strdup2(pool, &via->transport, "TCP"); pj_strdup2(pool, &via->sent_by.host, "192.168.1.1"); /* "Organization: \r" */ str.ptr = "Organization"; str.slen = 12; generic = pjsip_generic_string_hdr_create(pool, &str, NULL); pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic); generic->hvalue.ptr = NULL; generic->hvalue.slen = 0; /* "Max-Forwards: 70\n" */ str.ptr = "Max-Forwards"; str.slen = 12; generic = pjsip_generic_string_hdr_create(pool, &str, NULL); pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic); str.ptr = "70"; str.slen = 2; generic->hvalue = str; /* "X-Header: \r\n" */ str.ptr = "X-Header"; str.slen = 8; generic = pjsip_generic_string_hdr_create(pool, &str, NULL); pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic); str.ptr = NULL; str.slen = 0; generic->hvalue = str; /* P-Associated-URI:\r\n */ str.ptr = "P-Associated-URI"; str.slen = 16; generic = pjsip_generic_string_hdr_create(pool, &str, NULL); pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic); str.ptr = NULL; str.slen = 0; generic->hvalue = str; return msg; } static pjsip_msg *create_msg1(pj_pool_t *pool) { pjsip_via_hdr *via; pjsip_route_hdr *route; pjsip_name_addr *name_addr; pjsip_sip_uri *url; pjsip_max_fwd_hdr *max_fwd; pjsip_to_hdr *to; pjsip_from_hdr *from; pjsip_contact_hdr *contact; pjsip_ctype_hdr *ctype; pjsip_cid_hdr *cid; pjsip_clen_hdr *clen; pjsip_cseq_hdr *cseq; pjsip_msg *msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG); pjsip_msg_body *body; //"SIP/2.0 200 OK\r\n" msg->line.status.code = 200; msg->line.status.reason = pj_str("OK"); //"Via: SIP/2.0/SCTP server10.biloxi.com;branch=z9hG4bKnashds8;rport;received=192.0.2.1\r\n" via = pjsip_via_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)via); via->transport = pj_str("SCTP"); via->sent_by.host = pj_str("server10.biloxi.com"); via->branch_param = pj_str("z9hG4bKnashds8"); via->rport_param = 0; via->recvd_param = pj_str("192.0.2.1"); //"Via: SIP/2.0/UDP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2\r\n" via = pjsip_via_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)via); via->transport = pj_str("UDP"); via->sent_by.host = pj_str("bigbox3.site3.atlanta.com"); via->branch_param = pj_str("z9hG4bK77ef4c2312983.1"); via->recvd_param = pj_str("192.0.2.2"); //"Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds ;received=192.0.2.3\r\n" via = pjsip_via_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)via); via->transport = pj_str("UDP"); via->sent_by.host = pj_str("pc33.atlanta.com"); via->branch_param = pj_str("z9hG4bK776asdhds"); via->recvd_param = pj_str("192.0.2.3"); //"Route: \r\n" route = pjsip_route_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)route); url = pjsip_sip_uri_create(pool, PJ_FALSE); route->name_addr.uri = (pjsip_uri*)url; url->host = pj_str("proxy.sipprovider.com"); //"Route: \r\n" route = pjsip_route_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)route); url = pjsip_sip_uri_create(pool, PJ_FALSE); route->name_addr.uri = (pjsip_uri*)url; url->host = pj_str("proxy.supersip.com"); url->port = 5060; //"Max-Forwards: 70\r\n" max_fwd = pjsip_max_fwd_hdr_create(pool, 70); pjsip_msg_add_hdr(msg, (pjsip_hdr*)max_fwd); //"To: Bob ;tag=a6c85cf\r\n" to = pjsip_to_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)to); name_addr = pjsip_name_addr_create(pool); name_addr->display = pj_str("Bob"); to->uri = (pjsip_uri*)name_addr; url = pjsip_sip_uri_create(pool, PJ_FALSE); name_addr->uri = (pjsip_uri*)url; url->user = pj_str("bob"); url->host = pj_str("biloxi.com"); to->tag = pj_str("a6c85cf"); //"From: Alice ;tag=1928301774\r\n" from = pjsip_from_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)from); name_addr = pjsip_name_addr_create(pool); name_addr->display = pj_str("Alice"); from->uri = (pjsip_uri*)name_addr; url = pjsip_sip_uri_create(pool, PJ_FALSE); name_addr->uri = (pjsip_uri*)url; url->user = pj_str("alice"); url->host = pj_str("atlanta.com"); from->tag = pj_str("1928301774"); //"Call-ID: a84b4c76e66710@pc33.atlanta.com\r\n" cid = pjsip_cid_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)cid); cid->id = pj_str("a84b4c76e66710@pc33.atlanta.com"); //"CSeq: 314159 INVITE\r\n" cseq = pjsip_cseq_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)cseq); cseq->cseq = 314159; pjsip_method_set(&cseq->method, PJSIP_INVITE_METHOD); //"Contact: \r\n" contact = pjsip_contact_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)contact); name_addr = pjsip_name_addr_create(pool); contact->uri = (pjsip_uri*)name_addr; url = pjsip_sip_uri_create(pool, PJ_TRUE); name_addr->uri = (pjsip_uri*)url; url->user = pj_str("bob"); url->host = pj_str("192.0.2.4"); //"Content-Type: application/sdp\r\n" ctype = pjsip_ctype_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)ctype); ctype->media.type = pj_str("application"); ctype->media.subtype = pj_str("sdp"); //"Content-Length: 150\r\n" clen = pjsip_clen_hdr_create(pool); pjsip_msg_add_hdr(msg, (pjsip_hdr*)clen); clen->len = 150; // Body body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body); msg->body = body; body->content_type.type = pj_str("application"); body->content_type.subtype = pj_str("sdp"); body->data = (void*) "v=0\r\n" "o=alice 53655765 2353687637 IN IP4 pc33.atlanta.com\r\n" "s=-\r\n" "t=0 0\r\n" "c=IN IP4 pc33.atlanta.com\r\n" "m=audio 3456 RTP/AVP 0 1 3 99\r\n" "a=rtpmap:0 PCMU/8000\r\n"; body->len = (unsigned)pj_ansi_strlen((const char*) body->data); body->print_body = &pjsip_print_text_body; return msg; } /*****************************************************************************/ static pj_status_t simple_test(void) { char stbuf[] = "SIP/2.0 180 Ringing like it never rings before"; unsigned i; pjsip_status_line st_line; pj_status_t status; PJ_LOG(3,(THIS_FILE, " simple test..")); status = pjsip_parse_status_line(stbuf, pj_ansi_strlen(stbuf), &st_line); if (status != PJ_SUCCESS) return status; for (i=0; i" #define HDR_FLAG_PARSE_FAIL 1 #define HDR_FLAG_DONT_PRINT 2 struct hdr_test_t { char *hname; char *hshort_name; char *hcontent; int (*test)(pjsip_hdr*); unsigned flags; } hdr_test_data[] = { { /* Empty Accept */ "Accept", NULL, "", &hdr_test_accept0 }, { /* Overflowing generic string header */ "Accept", NULL, "a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \ "a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \ "a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \ "a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \ "a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \ "a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \ "a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, " \ "a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a", &hdr_test_success, HDR_FLAG_PARSE_FAIL }, { /* Normal Accept */ "Accept", NULL, "application/*, text/plain", &hdr_test_accept1 }, { /* Accept with params */ "Accept", NULL, "application/*;p1=v1, text/plain", &hdr_test_accept2 }, { /* Empty Allow */ "Allow", NULL, "", &hdr_test_allow0, }, { /* Authorization, testing which params should be quoted */ "Authorization", NULL, "Digest username=\"username\", realm=\"realm\", nonce=\"nonce\", " \ "uri=\"sip:domain\", response=\"RESPONSE\", algorithm=MD5, " \ "cnonce=\"CNONCE\", opaque=\"OPAQUE\", qop=auth, nc=00000001", &hdr_test_authorization }, { /* Call ID */ "Call-ID", "i", "-.!%*_+`'~()<>:\\\"/[]?{}", &hdr_test_cid, }, { /* Parameter belong to hparam */ "Contact", "m", SIMPLE_ADDR_SPEC ";p1=v1", &hdr_test_contact0, HDR_FLAG_DONT_PRINT }, { /* generic-param in Contact header */ "Contact", "m", NAME_ADDR ";" GENERIC_PARAM, &hdr_test_contact1 }, { /* q=0 parameter in Contact header */ "Contact", "m", NAME_ADDR ";q=0", &hdr_test_contact_q0, HDR_FLAG_DONT_PRINT }, { /* q=0.5 parameter in Contact header */ "Contact", "m", NAME_ADDR ";q=0.5", &hdr_test_contact_q1 }, { /* q=1 parameter in Contact header */ "Contact", "m", NAME_ADDR ";q=1", &hdr_test_contact_q2 }, { /* q=1.0 parameter in Contact header */ "Contact", "m", NAME_ADDR ";q=1.0", &hdr_test_contact_q3, HDR_FLAG_DONT_PRINT }, { /* q=1.1 parameter in Contact header */ "Contact", "m", NAME_ADDR ";q=1.15", &hdr_test_contact_q4 }, { /* Content-Length */ "Content-Length", "l", "10", &hdr_test_content_length }, { /* Content-Type, with generic-param */ "Content-Type", "c", "application/sdp" ";" GENERIC_PARAM, &hdr_test_content_type, HDR_FLAG_DONT_PRINT }, { /* From, testing parameters and generic-param */ "From", "f", NAME_ADDR ";" GENERIC_PARAM, &hdr_test_from }, { /* Proxy-Authenticate, testing which params should be quoted */ "Proxy-Authenticate", NULL, "Digest realm=\"realm\",domain=\"sip:domain\",nonce=\"nonce\"," \ "opaque=\"opaque\",stale=true,algorithm=MD5,qop=\"auth\"", &hdr_test_proxy_authenticate }, { /* Record-Route, param belong to header */ "Record-Route", NULL, NAME_ADDR ";" GENERIC_PARAM, &hdr_test_record_route }, { /* Empty Supported */ "Supported", "k", "", &hdr_test_supported, }, { /* To */ "To", "t", NAME_ADDR ";" GENERIC_PARAM, &hdr_test_to }, { /* Via */ "Via", "v", "SIP/2.0/XYZ host" ";" GENERIC_PARAM, &hdr_test_via }, { /* Via with IPv6 */ "Via", "v", "SIP/2.0/UDP [::1]", &hdr_test_via_ipv6_1 }, { /* Via with IPv6 */ "Via", "v", "SIP/2.0/UDP [::1]:5061", &hdr_test_via_ipv6_2 }, { /* Via with IPv6 */ "Via", "v", "SIP/2.0/UDP [::1];rport=5061;received=::2", &hdr_test_via_ipv6_3 }, { /* Retry-After header with comment */ "Retry-After", NULL, "10(Already Pending Register)", &hdr_test_retry_after1 }, { /* Non-ASCII UTF-8 characters in Subject */ "Subject", NULL, "\xC0\x81", &hdr_test_subject_utf } }; static int hdr_test_success(pjsip_hdr *h) { PJ_UNUSED_ARG(h); return 0; } /* "" */ static int hdr_test_accept0(pjsip_hdr *h) { pjsip_accept_hdr *hdr = (pjsip_accept_hdr*)h; if (h->type != PJSIP_H_ACCEPT) return -1010; if (hdr->count != 0) return -1020; return 0; } /* "application/ *, text/plain\r\n" */ static int hdr_test_accept1(pjsip_hdr *h) { pjsip_accept_hdr *hdr = (pjsip_accept_hdr*)h; if (h->type != PJSIP_H_ACCEPT) return -1110; if (hdr->count != 2) return -1120; if (pj_strcmp2(&hdr->values[0], "application/*")) return -1130; if (pj_strcmp2(&hdr->values[1], "text/plain")) return -1140; return 0; } /* "application/ *;p1=v1, text/plain\r\n" */ static int hdr_test_accept2(pjsip_hdr *h) { pjsip_accept_hdr *hdr = (pjsip_accept_hdr*)h; if (h->type != PJSIP_H_ACCEPT) return -1210; if (hdr->count != 2) return -1220; if (pj_strcmp2(&hdr->values[0], "application/*;p1=v1")) return -1230; if (pj_strcmp2(&hdr->values[1], "text/plain")) return -1240; return 0; } /* "" */ static int hdr_test_allow0(pjsip_hdr *h) { pjsip_allow_hdr *hdr = (pjsip_allow_hdr*)h; if (h->type != PJSIP_H_ALLOW) return -1310; if (hdr->count != 0) return -1320; return 0; } /* "Digest username=\"username\", realm=\"realm\", nonce=\"nonce\", " \ "uri=\"sip:domain\", response=\"RESPONSE\", algorithm=MD5, " \ "cnonce=\"CNONCE\", opaque=\"OPAQUE\", qop=auth, nc=00000001", */ static int hdr_test_authorization(pjsip_hdr *h) { pjsip_authorization_hdr *hdr = (pjsip_authorization_hdr*)h; if (h->type != PJSIP_H_AUTHORIZATION) return -1410; if (pj_strcmp2(&hdr->scheme, "Digest")) return -1420; if (pj_strcmp2(&hdr->credential.digest.username, "username")) return -1421; if (pj_strcmp2(&hdr->credential.digest.realm, "realm")) return -1422; if (pj_strcmp2(&hdr->credential.digest.nonce, "nonce")) return -1423; if (pj_strcmp2(&hdr->credential.digest.uri, "sip:domain")) return -1424; if (pj_strcmp2(&hdr->credential.digest.response, "RESPONSE")) return -1425; if (pj_strcmp2(&hdr->credential.digest.algorithm, "MD5")) return -1426; if (pj_strcmp2(&hdr->credential.digest.cnonce, "CNONCE")) return -1427; if (pj_strcmp2(&hdr->credential.digest.opaque, "OPAQUE")) return -1428; if (pj_strcmp2(&hdr->credential.digest.qop, "auth")) return -1429; if (pj_strcmp2(&hdr->credential.digest.nc, "00000001")) return -1430; return 0; } /* "-.!%*_+`'~()<>:\\\"/[]?{}\r\n" */ static int hdr_test_cid(pjsip_hdr *h) { pjsip_cid_hdr *hdr = (pjsip_cid_hdr*)h; if (h->type != PJSIP_H_CALL_ID) return -1510; if (pj_strcmp2(&hdr->id, "-.!%*_+`'~()<>:\\\"/[]?{}")) return -1520; return 0; } /* #define SIMPLE_ADDR_SPEC "sip:host" */ static int test_simple_addr_spec(pjsip_uri *uri) { pjsip_sip_uri *sip_uri = (pjsip_sip_uri *)pjsip_uri_get_uri(uri); if (!PJSIP_URI_SCHEME_IS_SIP(uri)) return -900; if (pj_strcmp2(&sip_uri->host, "host")) return -910; if (sip_uri->port != 0) return -920; return 0; } /* #define PARAM_CHAR "][/:&+$" #define SIMPLE_ADDR_SPEC "sip:host" #define ADDR_SPEC SIMPLE_ADDR_SPEC ";"PARAM_CHAR"="PARAM_CHAR ";p1=\";\"" #define NAME_ADDR "<" ADDR_SPEC ">" */ static int nameaddr_test(void *uri) { pjsip_sip_uri *sip_uri=(pjsip_sip_uri *)pjsip_uri_get_uri((pjsip_uri*)uri); pjsip_param *param; int rc; if (!PJSIP_URI_SCHEME_IS_SIP(uri)) return -930; rc = test_simple_addr_spec((pjsip_uri*)sip_uri); if (rc != 0) return rc; if (pj_list_size(&sip_uri->other_param) != 2) return -940; param = sip_uri->other_param.next; if (pj_strcmp2(¶m->name, PARAM_CHAR)) return -942; if (pj_strcmp2(¶m->value, PARAM_CHAR)) return -943; param = param->next; if (pj_strcmp2(¶m->name, "p1")) return -942; if (pj_strcmp2(¶m->value, "\";\"")) return -943; return 0; } /* #define GENERIC_PARAM "p0=a;p1=\"ab:;cd\";p2=ab%3acd;p3" */ static int generic_param_test(pjsip_param *param_head) { pjsip_param *param; if (pj_list_size(param_head) != 4) return -950; param = param_head->next; if (pj_strcmp2(¶m->name, "p0")) return -952; if (pj_strcmp2(¶m->value, "a")) return -953; param = param->next; if (pj_strcmp2(¶m->name, "p1")) return -954; if (pj_strcmp2(¶m->value, "\"ab:;cd\"")) return -955; param = param->next; if (pj_strcmp2(¶m->name, "p2")) return -956; if (pj_strcmp2(¶m->value, "ab:cd")) return -957; param = param->next; if (pj_strcmp2(¶m->name, "p3")) return -958; if (pj_strcmp2(¶m->value, "")) return -959; return 0; } /* SIMPLE_ADDR_SPEC ";p1=v1\r\n" */ static int hdr_test_contact0(pjsip_hdr *h) { pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h; pjsip_param *param; int rc; if (h->type != PJSIP_H_CONTACT) return -1610; rc = test_simple_addr_spec(hdr->uri); if (rc != 0) return rc; if (pj_list_size(&hdr->other_param) != 1) return -1620; param = hdr->other_param.next; if (pj_strcmp2(¶m->name, "p1")) return -1630; if (pj_strcmp2(¶m->value, "v1")) return -1640; return 0; } /* NAME_ADDR GENERIC_PARAM "\r\n", */ static int hdr_test_contact1(pjsip_hdr *h) { pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h; int rc; if (h->type != PJSIP_H_CONTACT) return -1710; rc = nameaddr_test(hdr->uri); if (rc != 0) return rc; rc = generic_param_test(&hdr->other_param); if (rc != 0) return rc; return 0; } /* NAME_ADDR ";q=0" */ static int hdr_test_contact_q0(pjsip_hdr *h) { pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h; int rc; if (h->type != PJSIP_H_CONTACT) return -1710; rc = nameaddr_test(hdr->uri); if (rc != 0) return rc; if (hdr->q1000 != 0) return -1711; return 0; } /* NAME_ADDR ";q=0.5" */ static int hdr_test_contact_q1(pjsip_hdr *h) { pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h; int rc; if (h->type != PJSIP_H_CONTACT) return -1710; rc = nameaddr_test(hdr->uri); if (rc != 0) return rc; if (hdr->q1000 != 500) return -1712; return 0; } /* NAME_ADDR ";q=1" */ static int hdr_test_contact_q2(pjsip_hdr *h) { pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h; int rc; if (h->type != PJSIP_H_CONTACT) return -1710; rc = nameaddr_test(hdr->uri); if (rc != 0) return rc; if (hdr->q1000 != 1000) return -1713; return 0; } /* NAME_ADDR ";q=1.0" */ static int hdr_test_contact_q3(pjsip_hdr *h) { pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h; int rc; if (h->type != PJSIP_H_CONTACT) return -1710; rc = nameaddr_test(hdr->uri); if (rc != 0) return rc; if (hdr->q1000 != 1000) return -1714; return 0; } /* NAME_ADDR ";q=1.15" */ static int hdr_test_contact_q4(pjsip_hdr *h) { pjsip_contact_hdr *hdr = (pjsip_contact_hdr*)h; int rc; if (h->type != PJSIP_H_CONTACT) return -1710; rc = nameaddr_test(hdr->uri); if (rc != 0) return rc; if (hdr->q1000 != 1150) return -1715; return 0; } /* "10" */ static int hdr_test_content_length(pjsip_hdr *h) { pjsip_clen_hdr *hdr = (pjsip_clen_hdr*)h; if (h->type != PJSIP_H_CONTENT_LENGTH) return -1810; if (hdr->len != 10) return -1820; return 0; } /* "application/sdp" GENERIC_PARAM, */ static int hdr_test_content_type(pjsip_hdr *h) { pjsip_ctype_hdr *hdr = (pjsip_ctype_hdr*)h; const pjsip_param *prm; if (h->type != PJSIP_H_CONTENT_TYPE) return -1910; if (pj_strcmp2(&hdr->media.type, "application")) return -1920; if (pj_strcmp2(&hdr->media.subtype, "sdp")) return -1930; /* Currently, if the media parameter contains escaped characters, * pjsip will print the parameter unescaped. */ prm = hdr->media.param.next; if (prm == &hdr->media.param) return -1940; if (pj_strcmp2(&prm->name, "p0")) return -1941; if (pj_strcmp2(&prm->value, "a")) return -1942; prm = prm->next; if (prm == &hdr->media.param) return -1950; if (pj_strcmp2(&prm->name, "p1")) { PJ_LOG(3,("", "%.*s", (int)prm->name.slen, prm->name.ptr)); return -1951; } if (pj_strcmp2(&prm->value, "\"ab:;cd\"")) { PJ_LOG(3,("", "%.*s", (int)prm->value.slen, prm->value.ptr)); return -1952; } prm = prm->next; if (prm == &hdr->media.param) return -1960; if (pj_strcmp2(&prm->name, "p2")) return -1961; if (pj_strcmp2(&prm->value, "ab:cd")) return -1962; prm = prm->next; if (prm == &hdr->media.param) return -1970; if (pj_strcmp2(&prm->name, "p3")) return -1971; if (pj_strcmp2(&prm->value, "")) return -1972; return 0; } /* NAME_ADDR GENERIC_PARAM, */ static int hdr_test_from(pjsip_hdr *h) { pjsip_from_hdr *hdr = (pjsip_from_hdr*)h; int rc; if (h->type != PJSIP_H_FROM) return -2010; rc = nameaddr_test(hdr->uri); if (rc != 0) return rc; rc = generic_param_test(&hdr->other_param); if (rc != 0) return rc; return 0; } /* "Digest realm=\"realm\", domain=\"sip:domain\", nonce=\"nonce\", " \ "opaque=\"opaque\", stale=true, algorithm=MD5, qop=\"auth\"", */ static int hdr_test_proxy_authenticate(pjsip_hdr *h) { pjsip_proxy_authenticate_hdr *hdr = (pjsip_proxy_authenticate_hdr*)h; if (h->type != PJSIP_H_PROXY_AUTHENTICATE) return -2110; if (pj_strcmp2(&hdr->scheme, "Digest")) return -2120; if (pj_strcmp2(&hdr->challenge.digest.realm, "realm")) return -2130; if (pj_strcmp2(&hdr->challenge.digest.domain, "sip:domain")) return -2140; if (pj_strcmp2(&hdr->challenge.digest.nonce, "nonce")) return -2150; if (pj_strcmp2(&hdr->challenge.digest.opaque, "opaque")) return -2160; if (hdr->challenge.digest.stale != 1) return -2170; if (pj_strcmp2(&hdr->challenge.digest.algorithm, "MD5")) return -2180; if (pj_strcmp2(&hdr->challenge.digest.qop, "auth")) return -2190; return 0; } /* NAME_ADDR GENERIC_PARAM, */ static int hdr_test_record_route(pjsip_hdr *h) { pjsip_rr_hdr *hdr = (pjsip_rr_hdr*)h; int rc; if (h->type != PJSIP_H_RECORD_ROUTE) return -2210; rc = nameaddr_test(&hdr->name_addr); if (rc != 0) return rc; rc = generic_param_test(&hdr->other_param); if (rc != 0) return rc; return 0; } /* " \r\n" */ static int hdr_test_supported(pjsip_hdr *h) { pjsip_supported_hdr *hdr = (pjsip_supported_hdr*)h; if (h->type != PJSIP_H_SUPPORTED) return -2310; if (hdr->count != 0) return -2320; return 0; } /* NAME_ADDR GENERIC_PARAM, */ static int hdr_test_to(pjsip_hdr *h) { pjsip_to_hdr *hdr = (pjsip_to_hdr*)h; int rc; if (h->type != PJSIP_H_TO) return -2410; rc = nameaddr_test(hdr->uri); if (rc != 0) return rc; rc = generic_param_test(&hdr->other_param); if (rc != 0) return rc; return 0; } /* "SIP/2.0 host" GENERIC_PARAM */ static int hdr_test_via(pjsip_hdr *h) { pjsip_via_hdr *hdr = (pjsip_via_hdr*)h; int rc; if (h->type != PJSIP_H_VIA) return -2510; if (pj_strcmp2(&hdr->transport, "XYZ")) return -2515; if (pj_strcmp2(&hdr->sent_by.host, "host")) return -2520; if (hdr->sent_by.port != 0) return -2530; rc = generic_param_test(&hdr->other_param); if (rc != 0) return rc; return 0; } /* "SIP/2.0/UDP [::1]" */ static int hdr_test_via_ipv6_1(pjsip_hdr *h) { pjsip_via_hdr *hdr = (pjsip_via_hdr*)h; if (h->type != PJSIP_H_VIA) return -2610; if (pj_strcmp2(&hdr->transport, "UDP")) return -2615; if (pj_strcmp2(&hdr->sent_by.host, "::1")) return -2620; if (hdr->sent_by.port != 0) return -2630; return 0; } /* "SIP/2.0/UDP [::1]:5061" */ static int hdr_test_via_ipv6_2(pjsip_hdr *h) { pjsip_via_hdr *hdr = (pjsip_via_hdr*)h; if (h->type != PJSIP_H_VIA) return -2710; if (pj_strcmp2(&hdr->transport, "UDP")) return -2715; if (pj_strcmp2(&hdr->sent_by.host, "::1")) return -2720; if (hdr->sent_by.port != 5061) return -2730; return 0; } /* "SIP/2.0/UDP [::1];rport=5061;received=::2" */ static int hdr_test_via_ipv6_3(pjsip_hdr *h) { pjsip_via_hdr *hdr = (pjsip_via_hdr*)h; if (h->type != PJSIP_H_VIA) return -2810; if (pj_strcmp2(&hdr->transport, "UDP")) return -2815; if (pj_strcmp2(&hdr->sent_by.host, "::1")) return -2820; if (hdr->sent_by.port != 0) return -2830; if (pj_strcmp2(&hdr->recvd_param, "::2")) return -2840; if (hdr->rport_param != 5061) return -2850; return 0; } /* "10(Already Pending Register)" */ static int hdr_test_retry_after1(pjsip_hdr *h) { pjsip_retry_after_hdr *hdr = (pjsip_retry_after_hdr*)h; if (h->type != PJSIP_H_RETRY_AFTER) return -2910; if (hdr->ivalue != 10) return -2920; if (pj_strcmp2(&hdr->comment, "Already Pending Register")) return -2930; return 0; } /* Subject: \xC0\x81 */ static int hdr_test_subject_utf(pjsip_hdr *h) { pjsip_subject_hdr *hdr = (pjsip_subject_hdr*)h; if (pj_strcmp2(&h->name, "Subject")) return -2950; if (pj_strcmp2(&hdr->hvalue, "\xC0\x81")) return -2960; return 0; } static int hdr_test(void) { unsigned i; PJ_LOG(3,(THIS_FILE, " testing header parsing..")); for (i=0; ihname); len = strlen(test->hcontent); #if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0 PJ_ASSERT_RETURN(len < sizeof(hcontent), PJSIP_EMSGTOOLONG); strcpy(hcontent, test->hcontent); #else hcontent = test->hcontent; #endif parsed_hdr1 = (pjsip_hdr*) pjsip_parse_hdr(pool, &hname, hcontent, len, &parsed_len); if (parsed_hdr1 == NULL) { if (test->flags & HDR_FLAG_PARSE_FAIL) { pj_pool_release(pool); continue; } PJ_LOG(3,(THIS_FILE, " error parsing header %s: %s", test->hname, test->hcontent)); return -500; } /* Test the parsing result */ if (test->test && (rc=test->test(parsed_hdr1)) != 0) { PJ_LOG(3,(THIS_FILE, " validation failed for header %s: %s", test->hname, test->hcontent)); PJ_LOG(3,(THIS_FILE, " error code is %d", rc)); return -502; } #if 1 /* Parse with hshortname, if present */ if (test->hshort_name) { hname = pj_str(test->hshort_name); len = strlen(test->hcontent); #if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0 PJ_ASSERT_RETURN(len < sizeof(hcontent), PJSIP_EMSGTOOLONG); strcpy(hcontent, test->hcontent); #else hcontent = test->hcontent; #endif parsed_hdr2 = (pjsip_hdr*) pjsip_parse_hdr(pool, &hname, hcontent, len, &parsed_len); if (parsed_hdr2 == NULL) { PJ_LOG(3,(THIS_FILE, " error parsing header %s: %s", test->hshort_name, test->hcontent)); return -510; } } #endif if (test->flags & HDR_FLAG_DONT_PRINT) { pj_pool_release(pool); continue; } /* Print the original header */ input = (char*) pj_pool_alloc(pool, 1024); len = pj_ansi_snprintf(input, 1024, "%s: %s", test->hname, test->hcontent); if (len < 1 || len >= 1024) return -520; /* Print the parsed header*/ output = (char*) pj_pool_alloc(pool, 1024); len = pjsip_hdr_print_on(parsed_hdr1, output, 1024); if (len < 0 || len >= 1024) { PJ_LOG(3,(THIS_FILE, " header too long: %s: %s", test->hname, test->hcontent)); return -530; } output[len] = 0; if (strcmp(input, output) != 0) { PJ_LOG(3,(THIS_FILE, " header character by character comparison failed.")); PJ_LOG(3,(THIS_FILE, " original header=|%s|", input)); PJ_LOG(3,(THIS_FILE, " parsed header =|%s|", output)); return -540; } pj_pool_release(pool); } return 0; } /*****************************************************************************/ int msg_test(void) { enum { COUNT = 1, DETECT=0, PARSE=1, PRINT=2 }; struct { unsigned detect; unsigned parse; unsigned print; } run[COUNT]; unsigned i, max, avg_len; char desc[250]; pj_status_t status; status = hdr_test(); if (status != 0) return status; status = simple_test(); if (status != PJ_SUCCESS) return status; #if INCLUDE_BENCHMARKS for (i=0; i max) max = run[i].detect; PJ_LOG(3,("", " Maximum message detection/sec=%u", max)); pj_ansi_sprintf(desc, "Number of SIP messages " "can be pre-parse by pjsip_find_msg() " "per second (tested with %d message sets with " "average message length of " "%d bytes)", (int)PJ_ARRAY_SIZE(test_array), avg_len); report_ival("msg-detect-per-sec", max, "msg/sec", desc); /* Print maximum parse/sec */ for (i=0, max=0; i max) max = run[i].parse; PJ_LOG(3,("", " Maximum message parsing/sec=%u", max)); pj_ansi_sprintf(desc, "Number of SIP messages " "can be parsed by pjsip_parse_msg() " "per second (tested with %d message sets with " "average message length of " "%d bytes)", (int)PJ_ARRAY_SIZE(test_array), avg_len); report_ival("msg-parse-per-sec", max, "msg/sec", desc); /* Msg parsing bandwidth */ report_ival("msg-parse-bandwidth-mb", avg_len*max/1000000, "MB/sec", "Message parsing bandwidth in megabytes (number of megabytes" " worth of SIP messages that can be parsed per second). " "The value is derived from msg-parse-per-sec above."); /* Print maximum print/sec */ for (i=0, max=0; i max) max = run[i].print; PJ_LOG(3,("", " Maximum message print/sec=%u", max)); pj_ansi_sprintf(desc, "Number of SIP messages " "can be printed by pjsip_msg_print()" " per second (tested with %d message sets with " "average message length of " "%d bytes)", (int)PJ_ARRAY_SIZE(test_array), avg_len); report_ival("msg-print-per-sec", max, "msg/sec", desc); /* Msg print bandwidth */ report_ival("msg-printed-bandwidth-mb", avg_len*max/1000000, "MB/sec", "Message print bandwidth in megabytes (total size of " "SIP messages printed per second). " "The value is derived from msg-print-per-sec above."); #endif /* INCLUDE_BENCHMARKS */ return PJ_SUCCESS; }