reSIProcate/stack  9694
SipTortureTests.cxx
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <memory>
00003 
00004 #include "TestSupport.hxx"
00005 #include "resip/stack/Contents.hxx"
00006 #include "resip/stack/SdpContents.hxx"
00007 #include "resip/stack/SipMessage.hxx"
00008 #include "resip/stack/ExtensionHeader.hxx"
00009 #include "resip/stack/Uri.hxx"
00010 #include "rutil/Logger.hxx"
00011 #include "tassert.h"
00012 
00013 using namespace resip;
00014 using namespace std;
00015 
00016 #define RESIPROCATE_SUBSYSTEM Subsystem::TEST
00017 
00018 #define BUGTRAILINGSPACE " "
00019 
00020 void 
00021 test1()
00022 {
00023   CritLog(<< "2.1 INVITE Parser Torture Test Message" );
00024       
00025       const char *txt = ("INVITE sip:called@called-company.com SIP/2.0\r\n"
00026                    "TO :\r\n"
00027                    " sip:called@called-company.com ;       tag      = 1918181833n\r\n"
00028                    "From     : \"Caller Name \\\\\\\"\" <sip:caller@caller-company.com>\r\n"
00029                    "  ;\r\n"
00030                    "  tag = 98asjd8\r\n"
00031                    "Max-Forwards: 8\r\n"
00032                    "Call-ID: 0ha0isndaksdj@10.0.0.1\r\n"
00033                    "Date: Mon, 02 Jun 1982 08:21:11 GMT\r\n"
00034                    "CSeq: 8\r\n"
00035                    "   INVITE\r\n"
00036                    "Via  : SIP  /   2.0\r\n" 
00037                    " /UDP\r\n" 
00038                    "    135.180.130.133;branch=z9hG4bKkdjuw\r\n" 
00039                    "Subject : \r\n"
00040                    "NewFangledHeader:   newfangled value\r\n" 
00041                    " more newfangled value \r\n" 
00042                    "Content-Type: application/sdp \r\n" 
00043                    "v:  SIP  / 2.0  / TCP     1192.168.156.222   ;\r\n" 
00044                    "  branch  =   9ikj8  , \r\n"
00045                    " SIP  /    2.0   / UDP  192.168.255.111   ; hidden\r\n" 
00046                    "m:\"Quoted string\\\"\\\"\"<sip:caller@caller-company.com>; newparam =\r\n" 
00047                    " newvalue ;\r\n" 
00048                    "  secondparam = secondvalue  ; q = 0.33,\r\n" 
00049                    " tel:4443322 \r\n"
00050                    "\r\n"
00051                    "v=0\r\n" 
00052                    "o=mhandley 29739 7272939 IN IP4 126.5.4.3 \r\n"
00053                    "s=-\r\n" 
00054                    "c=IN IP4 135.180.130.88 \r\n"
00055                    "t=0 0 \r\n"
00056                    "m=audio 492170 RTP/AVP 0 12 \r\n"
00057                    "m=video 3227 RTP/AVP 31 \r\n"
00058                    "a=rtpmap:31 LPC \r\n\r\n");
00059 
00060 
00061 
00062       SipMessage* msg = TestSupport::makeMessage(txt);
00063       
00064 
00065       tassert_reset();
00066       tassert(msg);
00067 
00068       auto_ptr<SipMessage> message(msg);
00069 
00070       tassert(message->isRequest());
00071       tassert(message->isResponse() == false);
00072 
00073       tassert(message->exists(h_To));
00074       tassert(message->header(h_To).uri().user() == "called");
00075       tassert(message->header(h_To).uri().host() == "called-company.com");
00076       tassert(message->header(h_To).param(p_tag) == "1918181833n");
00077 
00078       tassert(message->exists(h_From));
00079       tassert(message->header(h_From).uri().user() == "caller");
00080       tassert(message->header(h_From).uri().host() == "caller-company.com");
00081 
00082       tassert(message->header(h_From).param(p_tag) == "98asjd8");
00083 
00084       tassert(message->exists(h_MaxForwards));
00085       tassert(message->header(h_MaxForwards).value() == 8);
00086       tassert(message->header(h_MaxForwards).exists(p_tag) == false);
00087 
00088       // !ah! compact headers not working.
00089       // skip if ''not present'' -- actually check by unknown hdr... :-)
00090       if (message->exists(h_Contacts))
00091       {
00092         
00093         tassert(message->exists(h_Contacts) == true);
00094         tassert(message->header(h_Contacts).empty() == false);
00095         tassert(message->header(h_Contacts).front().uri().user() == "caller");
00096         tassert(message->header(h_Contacts).front().uri().host() == "caller-company.com");
00097         tassert(message->header(h_Contacts).front().uri().port() == 0);
00098         
00099       }
00100       else
00101       {
00102          CritLog(<<"TODO: Compact headers .. doing by unknown interface!!");
00103          tassert(message->exists(h_Contacts) == false);
00104          tassert(message->exists(ExtensionHeader("m")) == true);
00105          tassert(message->header(ExtensionHeader("m")).empty() == false);
00107          tassert(message->header(ExtensionHeader("m")).front().value() == 
00108                  "\"Quoted string\\\"\\\"\"<sip:caller@caller-company.com>;"
00109                  " newparam =   newvalue ;    secondparam = secondvalue  ; q"
00110                  " = 0.33,   tel:4443322 ");
00111       }
00112 
00113       tassert(message->exists(h_CallId));
00114       tassert(message->header(h_CallId).value() == "0ha0isndaksdj@10.0.0.1");
00115 
00116       tassert(message->exists(h_CSeq));
00117       tassert(message->header(h_CSeq).sequence() == 8);
00118       tassert(message->header(h_CSeq).method() == INVITE);
00119 
00120       tassert(message->exists(h_Vias));
00121       tassert(message->header(h_Vias).empty() == false);
00122       tassert(message->header(h_Vias).front().protocolName() == "SIP");
00123       tassert(message->header(h_Vias).front().protocolVersion() == "2.0");
00124       tassert(message->header(h_Vias).front().transport() == "UDP");
00125       tassert(message->header(h_Vias).front().sentHost() == "135.180.130.133");
00126       tassert(message->header(h_Vias).front().sentPort() == 0);
00127       tassert(message->header(h_Vias).front().exists(p_branch));
00128       tassert(message->header(h_Vias).front().param(p_branch).hasMagicCookie());
00129       tassert(message->header(h_Vias).front().param(p_branch).getTransactionId() == "kdjuw");
00130       tassert(message->exists(h_Subject));
00131       tassert(message->header(h_Subject).value().empty());
00132 
00133       tassert(message->exists(ExtensionHeader("NewFangledHeader")));
00134       tassert(message->header(ExtensionHeader("NewFangledHeader")).front().value() == "newfangled value   more newfangled value"BUGTRAILINGSPACE);
00135       //TODO: Need to check the ContentType header value
00136       tassert(message->exists(h_ContentType));
00137       CritLog(<<"TODO:Check content type"); // << *message);
00138       tassert_verify(1);
00139    }
00140 
00141    void 
00142            test2()
00143    {
00144       CritLog( << "2.2 INVITE with Proxy-Require and Require");
00145        
00146       const char *txt = ("INVITE sip:called@called-company.com SIP/2.0\r\n"
00147                    "To: sip:called@called-company.com\r\n"
00148                    "From: sip:caller@caller-company.com;tag=242etr\r\n"
00149                    "Max-Forwards: 6\r\n"
00150                    "Call-ID: 0ha0isndaksdj@10.0.0.1\r\n"
00151                    "Require: newfeature1, newfeature2\r\n"
00152                    "Proxy-Require: newfeature3, newfeature4\r\n" 
00153                    "CSeq: 8 INVITE\r\n"
00154                    "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw\r\n\r\n");
00155 
00156       auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00157 
00158       tassert_reset();
00159       
00160       tassert(message->isRequest());
00161       tassert(message->isResponse() == false);
00162 
00163       tassert(message->exists(h_To));
00164       tassert(message->header(h_To).uri().user() == "called");
00165       tassert(message->header(h_To).uri().host() == "called-company.com");
00166       tassert(!message->header(h_To).exists(p_tag));
00167 
00168       tassert(message->exists(h_From));
00169       tassert(message->header(h_From).uri().user() == "caller");
00170       tassert(message->header(h_From).uri().host() == "caller-company.com");
00171       tassert(message->header(h_From).exists(p_tag));
00172       tassert(message->header(h_From).param(p_tag) == "242etr");
00173 
00174       tassert(message->exists(h_MaxForwards));
00175       tassert(message->header(h_MaxForwards).value() == 6);
00176       tassert(message->header(h_MaxForwards).exists(p_tag) == false);
00177 
00178       tassert(message->exists(h_Contacts) == false);
00179 
00180       tassert(message->exists(h_CallId));
00181       tassert(message->header(h_CallId).value() == "0ha0isndaksdj@10.0.0.1");
00182 
00183       //TODO: Check Values
00184       CritLog(<<"TODO: Check values h_Requires");
00185       tassert(message->exists(h_Requires));
00186 
00187       //TODO: Check values
00188       CritLog(<<"TODO: Check values h_ProxyRequires");
00189       tassert(message->exists(h_ProxyRequires));
00190 
00191       tassert(message->exists(h_CSeq));
00192       tassert(message->header(h_CSeq).sequence() == 8);
00193       tassert(message->header(h_CSeq).method() == INVITE);
00194 
00195       tassert(message->exists(h_Vias));
00196       tassert(message->header(h_Vias).empty() == false);
00197       tassert(message->header(h_Vias).front().protocolName() == "SIP");
00198       tassert(message->header(h_Vias).front().protocolVersion() == "2.0");
00199       tassert(message->header(h_Vias).front().transport() == "UDP");
00200       tassert(message->header(h_Vias).front().sentHost() == "135.180.130.133");
00201       tassert(message->header(h_Vias).front().sentPort() == 0);
00202       tassert(message->header(h_Vias).front().exists(p_branch));
00203 
00204       // !ah! -- transaction id DOES NOT include the magic cookie
00205       // (removed z9hG4bK)
00206 
00207       tassert(message->header(h_Vias).front().param(p_branch).getTransactionId() == "kdjuw");
00208       tassert_verify(2);
00209 
00210    }
00211 
00212 void 
00213 test3()
00214 {
00215        CritLog( << "2.3 INVITE with Unknown Schemes in URIs");
00216        
00217       
00218       const char *txt = ("INVITE name:John_Smith SIP/2.0\r\n"
00219                    "To: isbn:2983792873\r\n"
00220                    "From: <sip:www.cs.columbia.edu>;tag=3234233\r\n" // was http//
00221                    "Call-ID: 0ha0isndaksdj@10.0.0.1\r\n"
00222                    "CSeq: 8 INVITE\r\n"
00223                    "Max-Forwards: 7\r\n"
00224                    "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw\r\n"
00225                    "Content-Type: application/sdp\r\n" 
00226                    "\r\n"
00227                    "v=0\r\n" 
00228                    "o=mhandley 29739 7272939 IN IP4 126.5.4.3 \r\n"
00229                    "s=- \r\n"
00230                    "c=IN IP4 135.180.130.88 \r\n"
00231                    "t=0 0\r\n"
00232                    "m=audio 492170 RTP/AVP 0 12 \r\n"
00233                    "m=video 3227 RTP/AVP 31 \r\n"
00234                    "a=rtpmap:31 LPC \r\n\r\n");
00235 
00236       auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00237 
00238       
00239       tassert(message->isRequest());
00240       tassert(message->isResponse() == false);
00241 
00242 
00243       // !ah! this will assert(0) in Uri.cxx -- so let's skip this for now
00244       CritLog(<<"TODO: fix generic Uri handling.");
00245       tassert_push();
00246       tassert(message->header(h_RequestLine).getSipVersion() == "SIP/2.0");
00247       tassert_pop();
00248 
00249       
00250       tassert(message->exists(h_To));
00251       tassert(!message->header(h_To).exists(p_tag));
00252 
00253       tassert(message->exists(h_From));
00254 
00255       tassert(message->header(h_From).param(p_tag) == "3234233");
00256 
00257 
00258       tassert(message->exists(h_CallId));
00259       tassert(message->header(h_CallId).value() == "0ha0isndaksdj@10.0.0.1");
00260 
00261       tassert(message->exists(h_CSeq));
00262       tassert(message->header(h_CSeq).sequence() == 8);
00263       tassert(message->header(h_CSeq).method() == INVITE);
00264 
00265       tassert(message->exists(h_MaxForwards));
00266       tassert(message->header(h_MaxForwards).value() == 7);
00267       tassert(message->header(h_MaxForwards).exists(p_tag) == false);
00268 
00269       tassert(message->exists(h_Contacts) == false);
00270 
00271       tassert(message->exists(h_Vias));
00272       tassert(message->header(h_Vias).empty() == false);
00273       tassert(message->header(h_Vias).front().protocolName() == "SIP");
00274       tassert(message->header(h_Vias).front().protocolVersion() == "2.0");
00275       tassert(message->header(h_Vias).front().transport() == "UDP");
00276       tassert(message->header(h_Vias).front().sentHost() == "135.180.130.133");
00277       tassert(message->header(h_Vias).front().sentPort() == 0);
00278       tassert(message->header(h_Vias).front().exists(p_branch));
00279       tassert(message->header(h_Vias).front().param(p_branch).getTransactionId() == "kdjuw");
00280 
00281       //TODO: Check value 
00282       CritLog(<<"TODO: Check value of ContentType");
00283       tassert(message->exists(h_ContentType));
00284       tassert_verify(3);
00285       
00286    }
00287 
00288 void 
00289 test4()
00290 {
00291       CritLog( << "2.4 REGISTER with Y2038 Test (This tests for Absolute Time in Expires)");
00292        
00293       const char *txt = ("REGISTER sip:company.com SIP/2.0\r\n"
00294                    "To: sip:user@company.com\r\n"
00295                    "From: sip:user@company.com;tag=3411345\r\n"
00296                    "Max-Forwards: 8\r\n"
00297                    "Contact: sip:user@host.company.com\r\n"
00298                    "Call-ID: 0ha0isndaksdj@10.0.0.1\r\n"
00299                    "CSeq: 8 REGISTER\r\n"
00300                    "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw\r\n"
00301                    "Expires: Sat, 01 Dec 2040 16:00:00 GMT\r\n\r\n");
00302 
00303       auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00304 
00305       tassert_reset();
00306       
00307       tassert(message->isRequest());
00308       tassert(message->isResponse() == false);
00309 
00310       tassert(message->header(h_RequestLine).getSipVersion() == "SIP/2.0");
00311 
00312       tassert(message->exists(h_To));
00313       tassert(message->header(h_To).uri().user() == "user");
00314       tassert(message->header(h_To).uri().host() == "company.com");
00315       tassert(!message->header(h_To).exists(p_tag));
00316 
00317       tassert(message->exists(h_From));
00318       tassert(message->header(h_From).uri().user() == "user");
00319       tassert(message->header(h_From).uri().host() == "company.com");
00320       tassert(message->header(h_From).exists(p_tag));
00321       tassert(message->header(h_From).param(p_tag) == "3411345");
00322 
00323       tassert(message->exists(h_MaxForwards));
00324       tassert(message->header(h_MaxForwards).value() == 8);
00325       tassert(message->header(h_MaxForwards).exists(p_tag) == false);
00326 
00327       tassert(message->exists(h_Contacts));
00328       tassert(message->header(h_Contacts).empty() == false);
00329       tassert(message->header(h_Contacts).front().uri().user() == "user");
00330       tassert(message->header(h_Contacts).front().uri().host() == "host.company.com");
00331       tassert(message->header(h_Contacts).front().uri().port() == 0);
00332 
00333       tassert(message->exists(h_CallId));
00334       tassert(message->header(h_CallId).value() == "0ha0isndaksdj@10.0.0.1");
00335 
00336       tassert(message->exists(h_CSeq));
00337       tassert(message->header(h_CSeq).sequence() == 8);
00338       tassert(message->header(h_CSeq).method() == REGISTER);
00339 
00340       tassert(message->exists(h_Vias));
00341       tassert(message->header(h_Vias).empty() == false);
00342       tassert(message->header(h_Vias).front().protocolName() == "SIP");
00343       tassert(message->header(h_Vias).front().protocolVersion() == "2.0");
00344       tassert(message->header(h_Vias).front().transport() == "UDP");
00345       tassert(message->header(h_Vias).front().sentHost() == "135.180.130.133");
00346       tassert(message->header(h_Vias).front().sentPort() == 0);
00347       tassert(message->header(h_Vias).front().exists(p_branch));
00348       tassert(message->header(h_Vias).front().param(p_branch).getTransactionId() == "kdjuw");
00349 
00350       tassert(message->exists(h_Expires));
00351       /* 
00352        * Quoted from RFC 3261 
00353        * The "expires" parameter of a Contact header field value indicates how
00354        * long the URI is valid.  The value of the parameter is a number
00355        * indicating seconds.  If this parameter is not provided, the value of
00356        * the Expires header field determines how long the URI is valid.
00357        * Malformed values SHOULD be treated as equivalent to 3600.
00358        * This provides a modest level of backwards compatibility with RFC
00359        * 2543, which allowed absolute times in this header field.  If an
00360        * absolute time is received, it will be treated as malformed, and
00361        * then default to 3600.
00362        */
00363 
00364       tassert(message->header(h_Expires).value() == 3600);
00365       // Asking for something when it doesnt exist
00366       tassert(message->exists(h_ContentLength) == false);
00367       
00368       message->header(h_ContentLength).value();
00369 
00370       tassert_verify(4);
00371    }
00372 
00373 void 
00374 test5()
00375    {
00376       CritLog( << "2.5    INVITE with inconsistent Accept and message body");
00377       
00378       const char *txt = ("INVITE sip:user@company.com SIP/2.0 \r\n"
00379                    "To: sip:j_user@company.com \r\n"
00380                    "From: sip:caller@university.edu;tag=234 \r\n"
00381                    "Max-Forwards: 5 \r\n"
00382                    "Call-ID: 0ha0isndaksdj@10.0.0.1 \r\n"
00383                    "Accept: text/newformat \r\n"
00384                    "CSeq: 8 INVITE \r\n"
00385                    "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw \r\n"
00386                    "Content-Type: application/sdp \r\n"
00387                    "\r\n"
00388                    "v=0 \r\n"
00389                    "c=IN IP4 135.180.130.88 \r\n"
00390                    "m=audio 492170 RTP/AVP 0 12 \r\n"
00391                    "m=video 3227 RTP/AVP 31 \r\n"
00392                    "a=rtpmap:31 LPC "
00393                    "\r\n");
00394 
00395       auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00396 
00397       tassert_reset();
00398 
00399       tassert(message->isRequest());
00400       tassert(!message->isResponse());
00401 
00402       tassert(message->header(h_RequestLine).getMethod() == INVITE);
00403       tassert(message->header(h_RequestLine).getSipVersion() == "SIP/2.0");
00404 
00405       tassert(message->header(h_RequestLine).uri().host() == "company.com");
00406       tassert(message->header(h_RequestLine).uri().user() == "user");
00407       tassert(message->header(h_RequestLine).uri().scheme() == "sip");
00408       tassert(message->header(h_RequestLine).uri().port() == 0);
00409       tassert(message->header(h_RequestLine).uri().password() == "");
00410 
00411       tassert(message->header(h_To).uri().host() == "company.com");
00412       tassert(message->header(h_To).uri().user() == "j_user");
00413       tassert(message->header(h_To).uri().scheme() == "sip");
00414       tassert(message->header(h_To).uri().port() == 0);
00415       tassert(message->header(h_To).uri().password() == "");
00416 
00417       tassert(message->header(h_From).uri().host() == "university.edu");
00418       tassert(message->header(h_From).uri().user() == "caller");
00419       tassert(message->header(h_From).uri().scheme() == "sip");
00420       tassert(message->header(h_From).uri().port() == 0);
00421       tassert(message->header(h_From).uri().password() == "");
00422       // The tag is a tag on From: not the uri...
00423       tassert(message->header(h_From).param(p_tag) == "234");
00424 
00425       tassert(message->header(h_MaxForwards).value() == 5);
00426 
00427       tassert(message->header(h_CallId).value() == "0ha0isndaksdj@10.0.0.1");
00428 
00429       tassert(message->header(h_Accepts).size() == 1);
00430       tassert(message->header(h_Accepts).front().type() == "text");
00431       tassert(message->header(h_Accepts).front().subType() == "newformat");
00432 
00433       tassert(message->header(h_CSeq).sequence() == 8);
00434       tassert(message->header(h_CSeq).method() == INVITE);
00435 
00436       tassert(message->header(h_Vias).size() == 1);
00437       tassert(message->header(h_Vias).front().protocolName() == "SIP");
00438       tassert(message->header(h_Vias).front().protocolVersion() == "2.0");
00439       tassert(message->header(h_Vias).front().transport() == "UDP");
00440       tassert(message->header(h_Vias).front().sentHost() == "135.180.130.133");
00441       tassert(message->header(h_Vias).front().sentPort() == 0);
00442       tassert(message->header(h_Vias).front().param(p_branch).hasMagicCookie());
00443       // !ah! this should go away when parser fixed.
00444       tassert(message->header(h_Vias).front().param(p_branch).getTransactionId() == "kdjuw");
00445 
00446       tassert(message->header(h_ContentType).type() == "application");
00447       tassert(message->header(h_ContentType).subType() == "sdp");
00448 
00449       tassert_verify(5);
00450       // .dlb. someday the body will gack on parse
00451    }
00452 
00453 void test6()
00454 {
00455       CritLog( << "2.6    INVITE with non-SDP message body ");
00456       
00457       const char *txt = ("INVITE sip:user@company.com SIP/2.0\r\n"
00458                    "To: sip:j.user@company.com\r\n"
00459                    "From: sip:caller@university.edu;tag=8\r\n"
00460                    "Max-Forwards: 70 \r\n"
00461                    "Call-ID: 0ha0isndaksdj@10.0.0.1 \r\n"
00462                    "CSeq: 8 INVITE \r\n"
00463                    "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw \r\n"
00464                    "Content-Type: application/newformat \r\n"
00465                    "\r\n"
00466                    "<audio> <pcmu port=\"443\"/> </audio> \r\n"
00467                    "\r\n");
00468 
00469       auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00470 
00471       tassert_reset();
00472 
00473       tassert(message->isRequest());
00474       tassert(!message->isResponse());
00475 
00476       tassert(message->header(h_RequestLine).getMethod() == INVITE);
00477       tassert(message->header(h_RequestLine).getSipVersion() == "SIP/2.0");
00478 
00479       tassert(message->header(h_RequestLine).uri().host() == "company.com");
00480       tassert(message->header(h_RequestLine).uri().user() == "user");
00481       tassert(message->header(h_RequestLine).uri().scheme() == "sip");
00482       tassert(message->header(h_RequestLine).uri().port() == 0);
00483       tassert(message->header(h_RequestLine).uri().password() == "");
00484 
00485       tassert(message->header(h_To).uri().host() == "company.com");
00486       tassert(message->header(h_To).uri().user() == "j.user");
00487       tassert(message->header(h_To).uri().scheme() == "sip");
00488       tassert(message->header(h_To).uri().port() == 0);
00489 
00490       tassert(message->header(h_From).uri().host() == "university.edu");
00491       tassert(message->header(h_From).uri().user() == "caller");
00492       tassert(message->header(h_From).uri().scheme() == "sip");
00493       tassert(message->header(h_From).uri().port() == 0);
00494 
00495       tassert(message->header(h_ContentType).type() == "application");
00496       tassert(message->header(h_ContentType).subType() == "newformat");
00497 
00498       // !jf! should send this to a UAS and it should be rejected (don't
00499       // understand why) - says because it is not SDP
00500 
00501       tassert_verify(6);
00502 }
00503 
00504 
00505 void test7()
00506 {
00507       CritLog( << "2.7    Unknown Method Message");
00508       
00509       const char *txt = ("NEWMETHOD sip:user@company.com SIP/2.0 \r\n"
00510                    "To: sip:j.user@company.com \r\n"
00511                    "From: sip:caller@university.edu;tag=34525 \r\n"
00512                    "Max-Forwards: 6 \r\n"
00513                    "Call-ID: 0ha0isndaksdj@10.0.0.1 \r\n"
00514                    "CSeq: 8 NEWMETHOD \r\n"
00515                    "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw \r\n"
00516                    "Content-Type: application/sdp \r\n"
00517                    "\r\n"
00518                    "v=0\r\n"
00519                    "o=mhandley 29739 7272939 IN IP4 126.5.4.3 \r\n"
00520                    "s=-\r\n"
00521                    "c=IN IP4 135.180.130.88\r\n"
00522                    "m=audio 492170 RTP/AVP 0 12\r\n"
00523                    "m=video 3227 RTP/AVP 31\r\n"
00524                    "a=rtpmap:31 LPC \r\n"
00525                    "\r\n");
00526 
00527       auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00528 
00529       tassert_reset();
00530 
00531       tassert(message->isRequest());
00532       tassert(!message->isResponse());
00533 
00534       tassert(message->header(h_RequestLine).getMethod() == UNKNOWN);
00535       tassert(message->header(h_RequestLine).unknownMethodName() == "NEWMETHOD");
00536       tassert(message->header(h_RequestLine).getSipVersion() == "SIP/2.0");
00537 
00538       tassert(message->header(h_RequestLine).uri().host() == "company.com");
00539       tassert(message->header(h_RequestLine).uri().user() == "user");
00540       tassert(message->header(h_RequestLine).uri().scheme() == "sip");
00541       tassert(message->header(h_RequestLine).uri().port() == 0);
00542       tassert(message->header(h_RequestLine).uri().password() == "");
00543 
00544       tassert(message->header(h_To).uri().host() == "company.com");
00545       tassert(message->header(h_To).uri().user() == "j.user");
00546       tassert(message->header(h_To).uri().scheme() == "sip");
00547       tassert(message->header(h_To).uri().port() == 0);
00548 
00549       tassert(message->header(h_From).uri().host() == "university.edu");
00550       tassert(message->header(h_From).uri().user() == "caller");
00551       tassert(message->header(h_From).uri().scheme() == "sip");
00552       tassert(message->header(h_From).uri().port() == 0);
00553 
00554       tassert(message->header(h_ContentType).type() == "application");
00555       tassert(message->header(h_ContentType).subType() == "sdp");
00556       
00557       DebugLog( << "start map dump" );
00558       HashMap<Mime, ContentsFactoryBase*>& m = ContentsFactoryBase::getFactoryMap();
00559       HashMap<Mime, ContentsFactoryBase*>::iterator i;
00560       i = m.begin();
00561       while ( i != m.end() )
00562       {
00563          DebugLog( << "first=" << i->first );
00564          i++;
00565       }
00566       DebugLog( << "done map dump" );
00567 
00568       Contents* c = message->getContents();
00569         
00570       SdpContents* sdp = dynamic_cast<SdpContents*>(c);
00571       
00572       sdp->session();
00573       
00574       DebugLog( << "got contents of type" << c->getType() );
00575       
00576       // A proxy should forward this using the same retransmission rules as 
00577       // BYE. A UAS should reject it with an error, and list the available 
00578       // methods in the response. 
00579 
00580       tassert_verify(7);
00581 }
00582 
00583 
00584 void test8()
00585 {
00586    CritLog( << "2.8   Unknown Method with CSeq Error ");
00587    
00588    const char *txt = ("NEWMETHOD sip:user@comapny.com SIP/2.0\r\n"
00589                 "To: sip:j.user@company.com\r\n"
00590                 "From: sip:caller@university.edu;tag=23411413\r\n"
00591                 "Max-Forwards: 3\r\n"
00592                 "Call-ID: 0ha0isndaksdj@10.0.1.1\r\n"
00593                 "CSeq: 8 INVITE\r\n"
00594                 "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw\r\n"
00595                 "Content-Type: application/sdp\r\n"
00596                 "\r\n"
00597                 "v=0\r\n"
00598                 "o=mhandley 29739 7272939 IN IP4 126.5.4.3\r\n"
00599                 "s=-\r\n"
00600                 "c=IN IP4 135.180.130.88\r\n"
00601                 "t=0 0\r\n"
00602                 "m=audio 492170 RTP/AVP 0 12\r\n"
00603                 "m=video 3227 RTP/AVP 31\r\n"
00604                 "a=rtpmap:31 LPC\r\n");
00605 
00606    auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00607    tassert_reset();
00608    tassert(message->isRequest());
00609    tassert(!message->isResponse());
00610 
00611    tassert(message->header(h_RequestLine).getMethod() == UNKNOWN);
00612    tassert(message->header(h_RequestLine).unknownMethodName() == "NEWMETHOD");
00613    tassert(message->header(h_CSeq).method() == INVITE);
00614    tassert(message->header(h_CSeq).method() != message->header(h_RequestLine).getMethod());
00615    tassert_verify(8);
00616 }
00617 
00618 void test9()
00619 {
00620    CritLog( << "2.9    REGISTER with Unknown Authorization Scheme" );
00621    
00622    const char* txt = ("REGISTER sip:company.com SIP/2.0\r\n"
00623                 "To: sip:j.user@company.com\r\n"
00624                 "From: sip:j.user@company.com;tag=87321hj23128\r\n"
00625                 "Max-Forwards: 8\r\n"
00626                 "Call-ID: 0ha0isndaksdj@10.0.1.1\r\n"
00627                 "CSeq: 8 REGISTER\r\n"
00628                 "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw\r\n"
00629                 "Authorization: Super-PGP foo=ajsohdaosdh0asyhdaind08yasdknasd09asidhas0d8\r\n\r\n");
00630    auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00631    tassert_reset();
00632    tassert(message->isRequest());
00633    tassert(!message->isResponse());
00634    
00635    tassert(message->header(h_RequestLine).getMethod() == REGISTER);
00636    tassert(message->header(h_Authorizations).front().scheme() == "Super-PGP");
00637    tassert_verify(9);
00638 }
00639 
00640 
00641 void test10()
00642 {
00643    CritLog( << "2.10 Multiple SIP Request in a Single Message");
00644    
00645    const char* txt = ("REGISTER sip:company.com SIP/2.0\r\n"
00646                 "To: sip:j.user@company.com\r\n"
00647                 "From: sip:j.user@company.com;tag=43251j3j324\r\n"
00648                 "Max-Forwards: 8\r\n"
00649                 "Call-ID: 0ha0isndaksdj@10.0.2.2\r\n"
00650                 "Contact: sip:j.user@host.company.com\r\n"
00651                 "CSeq: 8 REGISTER\r\n"
00652                 "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw\r\n"
00653                 "Content-Length: 0\r\n\r\n"
00654                 "INVITE sip:joe@company.com SIP/2.0\r\n"
00655                 "To: sip:joe@company.com\r\n"
00656                 "From: sip:caller@university.edu;tag=141334\r\n"
00657                 "Max-Forwards: 8\r\n"
00658                 "Call-ID: 0ha0isnda977644900765@10.0.0.1\r\n"
00659                 "CSeq: 8 INVITE\r\n"
00660                 "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw\r\n"
00661                 "Content-Type: application/sdp\r\n"
00662                 "\r\n"
00663                 "v=0\r\n"
00664                 "o=mhandley 29739 7272939 IN IP4 126.5.4.3\r\n"
00665                 "s=-\r\n"
00666                 "c=IN IP4 135.180.130.88\r\n"
00667                 "t=0 0\r\n"
00668                 "m=audio 492170 RTP/AVP 0 12\r\n"
00669                 "m =video 3227 RTP/AVP 31\r\n"
00670                 "a=rtpmap:31 LPC\r\n"
00671                 "\r\n");
00672    tassert_reset();
00673    try
00674    {
00675       auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00676       tassert(0);
00677    }
00678    catch (ParseException& e)
00679    {
00680    }
00681    
00682    tassert_verify(10);
00683 }
00684 
00685 void test11()
00686 {
00687    CritLog( << "2.11 INVITE missing Required Headers");
00688 
00689    const char* txt = ("INVITE sip:user@company.com SIP/2.0\r\n"
00690                 "CSeq: 0 INVITE\r\n"
00691                 "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw\r\n"
00692                 "Content-Type: application/sdp\r\n"
00693                 "\r\n"
00694                 "v=0\r\n"
00695                 "o=mhandley 29739 7272939 IN IP4 126.5.4.3\r\n"
00696                 "s=-\r\n"
00697                 "c=IN IP4 135.180.130.88\r\n"
00698                 "t=0 0\r\n"
00699                 "m=audio 492170 RTP/AVP 0 12\r\n"
00700                 "m=video 3227 RTP/AVP 31\r\n"
00701                 "a=rtpmap:31 LPC\r\n"
00702                 "\r\n");
00703    auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00704    tassert_reset();
00705    tassert(message->isRequest());
00706    tassert(!message->isResponse());
00707 
00708    tassert(!message->exists(h_CallId));
00709    tassert(!message->exists(h_From));
00710    tassert(!message->exists(h_To));
00711    tassert_verify(11);
00712 }
00713 
00714 void test12()
00715 {
00716    CritLog( << "2.12 INVITE with Duplicate Required Headers");
00717    //with duplicate headers that are not multi, the first header is kept
00718    
00719    const char* txt = ("INVITE sip:user@company.com SIP/2.0\r\n"
00720                 "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw\r\n"
00721                 "Max-Forwards: 70\r\n"
00722                 "CSeq: 0 INVITE\r\n"
00723                 "Call-ID: 98asdh@10.1.1.1\r\n"
00724                 "Call-ID: 98asdh@10.1.1.2\r\n"
00725                 "From: sip:caller@university.edu;tag=3413415\r\n"
00726                 "From: sip:caller@organization.org\r\n"
00727                 "To: sip:user@company.com\r\n"
00728                 "Content-Type: application/sdp\r\n"
00729                 "\r\n"
00730                 "v=0\r\n"
00731                 "o=mhandley 29739 7272939 IN IP4 126.5.4.3\r\n"
00732                 "s=-\r\n"
00733                 "c=IN IP4 135.180.130.88\r\n"
00734                 "t=0 0\r\n"
00735                 "m=audio 492170 RTP/AVP 0 12\r\n"
00736                 "m=video 3227 RTP/AVP 31\r\n"
00737                 "a=rtpmap:31 LPC\r\n"
00738                 "\r\n");
00739    
00740    tassert_reset();
00741    try
00742    {
00743       auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00744    }
00745    catch (ParseException& e)
00746    {
00747       tassert(0);
00748    }
00749    tassert_verify(12);
00750 }
00751 
00752 
00753 void test13()
00754 {
00755    CritLog( << "2.13 INVITE with lots of header types");
00756    //with duplicate headers that are not multi, the first header is kept
00757    
00758    const char* txt = ("INVITE sip:user@company.com SIP/2.0\r\n"
00759                 "User-Agent: Lame Agent\r\n"
00760                 "Via: SIP/2.0/UDP 135.180.130.133;branch=z9hG4bKkdjuw\r\n"
00761                 "Max-Forwards: 70\r\n"
00762                 "CSeq: 0 INVITE\r\n"
00763                 "Call-ID: 98asdh@10.1.1.2\r\n"
00764                 "From: sip:caller@university.edu;tag=3413415\r\n"
00765                 "From: sip:caller@organization.org\r\n"
00766                 "To: sip:user@company.com\r\n"
00767                 "Content-Type: application/sdp\r\n"
00768                 "\r\n"
00769                 "v=0\r\n"
00770                 "o=mhandley 29739 7272939 IN IP4 126.5.4.3\r\n"
00771                 "s=-\r\n"
00772                 "c=IN IP4 135.180.130.88\r\n"
00773                 "t=0 0\r\n"
00774                 "m=audio 492170 RTP/AVP 0 12\r\n"
00775                 "m=video 3227 RTP/AVP 31\r\n"
00776                 "a=rtpmap:31 LPC\r\n"
00777                 "\r\n");
00778    
00779    tassert_reset();
00780    try
00781    {
00782       auto_ptr<SipMessage> message(TestSupport::makeMessage(txt));
00783 
00784        tassert(message->header(h_UserAgent).value() == "Lame Agent"); 
00785        message->header(h_UserAgent).value() = "Foo";
00786        tassert(message->header(h_UserAgent).value() == "Foo"); 
00787    }
00788    catch (ParseException& e)
00789    {
00790       tassert(0);
00791    }
00792    tassert_verify(13);
00793 }
00794 
00795 
00796 void test14()
00797 {
00798    CritLog( << "2.14 Response with lots of headers");
00799    
00800    const char* txt = ("SIP/2.0 200 OK\r\n"
00801                 "To: <sip:fluffy@example.org>;tag=fb86ad2694115d75c77dce61523c9f07.ca6e\r\n"
00802                 "From: <sip:fluffy@example.org>;tag=a1fd\r\n"
00803                 "Via: SIP/2.0/UDP cj14:5002;branch=z9hG4bK-c87542-472987176-1;received=1.2.3.4\r\n"
00804                 "Call-ID: 048cec32\r\n"
00805                 "CSeq: 2 REGISTER\r\n"
00806                 "Contact: <sip:fluffy@1.2.3.4:5002>;q=1.00;expires=1951\r\n"
00807                 "Contact: <sip:fluffy@example.com:5002>;q=0.50;expires=10\r\n"
00808                 "Contact: <sip:floppy@example.com:5002>;q=0.00;expires=100\r\n"
00809                 "Server: The Server\r\n"
00810                 "Content-Length: 0\r\n"
00811                 "Warning: junk junk junk \r\n"
00812                 "\r\n");
00813    
00814    tassert_reset();
00815    try
00816    {
00817       auto_ptr<SipMessage> msg(TestSupport::makeMessage(txt));
00818       
00819       tassert(  msg->header(h_Contacts).size() == 3 );
00820       
00821       resip::ParserContainer<resip::NameAddr>::iterator i =  msg->header(h_Contacts).begin();
00822       while ( i != msg->header(h_Contacts).end() )
00823       {
00824          DebugLog(<< "i=" << *i  );
00825          i++;
00826       }
00827    }
00828    catch (ParseException& e)
00829    {
00830    }
00831    tassert_verify(14);
00832 }
00833 
00834 
00835 void test15()
00836 {
00837    CritLog( << "2.15 Interesting bodies");
00838    
00839    const char* txt = (
00840     "NOTIFY sip:fluffy@212.157.205.40 SIP/2.0\r\n"
00841     "Via: SIP/2.0/TCP 212.157.205.198:5060;branch=z9hG4bK2367411811584019109\r\n"
00842     "To: sip:fluffy@212.157.205.40\r\n"
00843     "From: sip:ntt2@h1.ntt2.sipit.net;tag=727823805122397238\r\n"
00844     "Max-Forwards: 70\r\n"
00845     "CSeq: 1 NOTIFY\r\n"
00846     "Call-ID: 28067261571992032320\r\n"
00847     "Contact: sip:ntt2@212.157.205.198:5060\r\n"
00848     "Content-Length: 1929\r\n"
00849     "Content-Type: multipart/signed;\r\n"
00850     " protocol=\"application/pkcs7-signature\";\r\n"
00851     " micalg=sha1; boundary=\"----YvhIjyjTU8lfNqGe8Fyvxcmb4mleF6quxsMFpT2hOhrDfS3LLs1MyYBdLNgBLsSC\"\r\n"
00852     "\r\n"
00853     "------YvhIjyjTU8lfNqGe8Fyvxcmb4mleF6quxsMFpT2hOhrDfS3LLs1MyYBdLNgBLsSC\r\n"
00854     "Content-Type: multipart/mixed;boundary=\"----lRIGMC8E2Px6I2IODfk2rISgfWIirrOJwS3tY52HuxDP3pdTiFjsghJJWhvyRCEY\"\r\n"
00855     "Content-Length: 870\r\n"
00856     "Content-Disposition: attachment;handling=required\r\n"
00857     "\r\n"
00858     "------lRIGMC8E2Px6I2IODfk2rISgfWIirrOJwS3tY52HuxDP3pdTiFjsghJJWhvyRCEY\r\n"
00859     "Content-Type: application/sipfrag\r\n"
00860     "Content-Length: 320\r\n"
00861     "\r\n"
00862     "To: sip:fluffy@212.157.205.40\r\n"
00863     "From: sip:ntt2@h1.ntt2.sipit.net;tag=727823805122397238\r\n"
00864     "CSeq: 1 NOTIFY\r\n"
00865     "Call-ID: 28067261571992032320\r\n"
00866     "Contact: sip:ntt2@212.157.205.198:5060\r\n"
00867     "Event: presence\r\n"
00868     "Content-Length: 210\r\n"
00869     "Content-Type: application/xpidf+xml\r\n"
00870     "Subscription-State: active\r\n"
00871     "User-Agent: NTT SecureSession User-Agent\r\n"
00872     "\r\n"
00873     "------lRIGMC8E2Px6I2IODfk2rISgfWIirrOJwS3tY52HuxDP3pdTiFjsghJJWhvyRCEY\r\n"
00874     "Content-Type: application/xpidf+xml\r\n"
00875     "Content-Length: 210\r\n"
00876     "\r\n"
00877     "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
00878     "<presence xmlns:impp=\"urn:ietf:params:xml:ns:pidf\" entity=\"pres:someone@example.com\">\r\n"
00879     "<tuple id=\"765\">\r\n"
00880     "<status>\r\n"
00881     "<basic>open</basic>\r\n"
00882     "</status>\r\n"
00883     "</tuple>\r\n"
00884     "</presence>\r\n"
00885     "\r\n"
00886     "------lRIGMC8E2Px6I2IODfk2rISgfWIirrOJwS3tY52HuxDP3pdTiFjsghJJWhvyRCEY--\r\n"
00887     "\r\n"
00888     "------YvhIjyjTU8lfNqGe8Fyvxcmb4mleF6quxsMFpT2hOhrDfS3LLs1MyYBdLNgBLsSC\r\n"
00889     "Content-Type: application/pkcs7-signature; name=\"smime.p7s\"\r\n"
00890     "Content-Transfer-Encoding: base64\r\n"
00891     "Content-Disposition: attachment; filename=\"smime.p7s\"; handling=required\r\n"
00892     "\r\n"
00893     "MIIBVgYJKoZIhvcNAQcCoIIBRzCCAUMCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3\r\n"
00894     "DQEHATGCASIwggEeAgEBMHwwcDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlm\r\n"
00895     "b3JuaWExETAPBgNVBAcTCFNhbiBKb3NlMQ4wDAYDVQQKEwVzaXBpdDEpMCcGA1UE\r\n"
00896     "CxMgU2lwaXQgVGVzdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkCCAIWABUCBgIVMAkG\r\n"
00897     "BSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYAer8TPSMtA3ZqweGnXLUYKR51bp52N\r\n"
00898     "oGBEqHZz7xR0Nhs6DsAOXiSFv19vTR//33u6Se3zpNNHP/zj7NRr+olimI2PeBNB\r\n"
00899     "tczNdqexoN0pjRW7l7mHZ0e39pqZmI5bhFl+z9CJJu5xW0aSarw84CZxbh5RQaYr\r\n"
00900     "zhSvTYdki20aiQ==\r\n"
00901     "\r\n"
00902     "------YvhIjyjTU8lfNqGe8Fyvxcmb4mleF6quxsMFpT2hOhrDfS3LLs1MyYBdLNgBLsSC--\r\n"
00903       );
00904    
00905    tassert_reset();
00906    try
00907    {
00908       auto_ptr<SipMessage> msg(TestSupport::makeMessage(txt));
00909       
00910    }
00911    catch (ParseException& e)
00912    {
00913    }
00914    tassert_verify(15);
00915 }
00916 
00917 
00918 int
00919 main(int argc, const char*argv[])
00920 {
00921     Log::Level l = Log::Debug;
00922     
00923     if (argc > 1)
00924     {
00925         switch(*argv[1])
00926         {
00927             case 'd': l = Log::Debug;
00928                 break;
00929             case 'i': l = Log::Info;
00930                 break;
00931             case 's': l = Log::Stack;
00932                 break;
00933             case 'c': l = Log::Crit;
00934                 break;
00935         }
00936     }
00937     
00938     Log::initialize(Log::Cout, l, argv[0]);
00939     CritLog(<<"Test Driver Starting");
00940     tassert_init(14);
00941     test1();
00942     test2();
00943     test3();
00944     test4();
00945     test5();
00946     test6();
00947     test7();
00948     test8();
00949     test9();
00950     test10();//this should fail as written
00951     test11();
00952     test12();
00953     test13();
00954     test14();
00955 
00956 
00957     tassert_report();
00958 
00959  CritLog(<<"Test Driver Done");
00960 }
00961 
00962 /* ====================================================================
00963  * The Vovida Software License, Version 1.0 
00964  * 
00965  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00966  * 
00967  * Redistribution and use in source and binary forms, with or without
00968  * modification, are permitted provided that the following conditions
00969  * are met:
00970  * 
00971  * 1. Redistributions of source code must retain the above copyright
00972  *    notice, this list of conditions and the following disclaimer.
00973  * 
00974  * 2. Redistributions in binary form must reproduce the above copyright
00975  *    notice, this list of conditions and the following disclaimer in
00976  *    the documentation and/or other materials provided with the
00977  *    distribution.
00978  * 
00979  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00980  *    and "Vovida Open Communication Application Library (VOCAL)" must
00981  *    not be used to endorse or promote products derived from this
00982  *    software without prior written permission. For written
00983  *    permission, please contact vocal@vovida.org.
00984  *
00985  * 4. Products derived from this software may not be called "VOCAL", nor
00986  *    may "VOCAL" appear in their name, without prior written
00987  *    permission of Vovida Networks, Inc.
00988  * 
00989  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00990  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00991  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00992  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00993  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00994  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00995  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00996  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00997  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00998  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00999  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
01000  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
01001  * DAMAGE.
01002  * 
01003  * ====================================================================
01004  * 
01005  * This software consists of voluntary contributions made by Vovida
01006  * Networks, Inc. and many individuals on behalf of Vovida Networks,
01007  * Inc.  For more information on Vovida Networks, Inc., please see
01008  * <http://www.vovida.org/>.
01009  *
01010  */