|
reSIProcate/stack
9694
|
#include <assert.h>#include <iostream>#include <sstream>#include <string.h>#include <string>#include "resip/stack/HeaderFieldValue.hxx"#include "resip/stack/HeaderTypes.hxx"#include "resip/stack/Headers.hxx"#include "resip/stack/ParserCategories.hxx"#include "resip/stack/ExtensionHeader.hxx"#include "resip/stack/UnknownParameterType.hxx"#include "resip/stack/ApiCheckList.hxx"#include "resip/stack/Uri.hxx"#include "rutil/DataStream.hxx"#include "rutil/ParseBuffer.hxx"#include "rutil/Logger.hxx"
Go to the source code of this file.
Classes | |
| class | TR |
Defines | |
| #define | RESIPROCATE_SUBSYSTEM Subsystem::TEST |
| #define | RESIP_COOKIE "-524287-" |
| #define | checkHeaderName(_name) resipCerr << Headers::_name << " " << Headers::getHeaderName(Headers::_name) << " = " << #_name << endl |
| #define | checkParameterName(_name) resipCerr << ParameterTypes::_name << " " << ParameterTypes::ParameterNames[ParameterTypes::_name] << " = " << #_name << endl |
Functions | |
| int | main (int arc, char **argv) |
| #define checkHeaderName | ( | _name | ) | resipCerr << Headers::_name << " " << Headers::getHeaderName(Headers::_name) << " = " << #_name << endl |
Referenced by main().
| #define checkParameterName | ( | _name | ) | resipCerr << ParameterTypes::_name << " " << ParameterTypes::ParameterNames[ParameterTypes::_name] << " = " << #_name << endl |
Referenced by main().
| #define RESIP_COOKIE "-524287-" |
Definition at line 26 of file testParserCategories.cxx.
Referenced by main().
| #define RESIPROCATE_SUBSYSTEM Subsystem::TEST |
Definition at line 25 of file testParserCategories.cxx.
| int main | ( | int | arc, |
| char ** | argv | ||
| ) |
Definition at line 58 of file testParserCategories.cxx.
References resip::ParserContainer< T >::begin(), resip::Data::c_str(), resip::Data::charEncoded(), checkHeaderName, checkParameterName, resip::LazyParser::checkParsed(), resip::Data::clear(), resip::Data::data(), resip::DateCategory::dayOfMonth(), resip::DateCategory::dayOfWeek(), resip::NameAddr::displayName(), resip::Data::empty(), resip::BranchParameter::encode(), resip::LazyParser::encode(), resip::ParserContainer< T >::erase(), resip::Auth::exists(), resip::Via::exists(), resip::Token::exists(), resip::NameAddr::exists(), resip::Uri::exists(), resip::Data::find(), resip::ParserContainer< T >::find(), resip::Data::from(), resip::Uri::getAor(), resip::Uri::getAorAsUri(), resip::ParserCategory::getParameterByEnum(), resip::BranchParameter::getTransactionId(), resip::BranchParameter::hasMagicCookie(), resip::Uri::host(), resip::DateCategory::hour(), resip::LazyParser::isWellFormed(), resip::DateCategory::minute(), resip::DateCategory::month(), resip::ParserCategory::param(), resip::NameAddr::parse(), resip::Uri::password(), resip::Uri::port(), resip::ParserContainer< T >::push_back(), received, resip::Uri::remove(), resip::oDataStream::reset(), RESIP_COOKIE, resipCerr, resip::Auth::scheme(), resip::Uri::scheme(), resip::DateCategory::second(), resip::Via::sentHost(), resip::Via::sentPort(), server, resip::ParserCategory::setParameter(), resip::Data::size(), resip::ParserContainerBase::size(), resip::Mime::subType(), type, resip::Mime::type(), resip::NameAddr::uri(), resip::Uri::user(), resip::StringCategory::value(), resip::Token::value(), and resip::DateCategory::year().
{
Log::initialize(Log::Cout, Log::Debug, argv[0]);
static ExtensionParameter p_mobility_ext("mobility");
static ExtensionParameter p_lr_ext("lr");
static ExtensionParameter p_tag_ext("tag");
static ExtensionParameter p_ttl_ext("ttl");
{
TR _tr("Test poorly formed NameAddr by construction");
try
{
NameAddr test("<jason_AT_example.com@10.0.0.1;transport=TCP>");
assert(false);
}
catch (ParseException& e)
{
resipCerr << e << endl;
}
}
{
TR _tr("Test copy transport param");
NameAddr test("<sip:jason_AT_example.com@10.0.0.1:5060;transport=TCP>");
resipCerr << test << endl;
NameAddr copy = test;
resipCerr << copy << endl;
assert(test.uri().exists(p_transport));
assert(copy.uri().exists(p_transport));
assert(test.uri().param(p_transport) == copy.uri().param(p_transport));
}
{
TR _tr("Test iterator erase in ParserContainer");
NameAddrs nameAddrs;
nameAddrs.push_back(NameAddr(Uri("sip:first@first.com")));
nameAddrs.push_back(NameAddr(Uri("sip:second@second.com")));
nameAddrs.push_back(NameAddr(Uri("sip:third@third.com")));
nameAddrs.push_back(NameAddr(Uri("sip:fourth@fourth.com")));
assert(nameAddrs.size() == 4);
NameAddrs::iterator i = nameAddrs.begin();
++i;
nameAddrs.erase(i);
assert(nameAddrs.size() == 3);
nameAddrs.erase(nameAddrs.begin());
assert(nameAddrs.size() == 2);
assert(nameAddrs.begin()->uri().user() == "third");
}
{
TR _tr("Test NameAddr encode from underlying after read-only parse");
resip::Data raw("<sip:jason_AT_example.com@10.0.0.1:5060;opaque=blah>");
HeaderFieldValue hfv(raw.data(), raw.size());
NameAddr test(hfv, Headers::UNKNOWN);
const NameAddr& c_test(test);
// We should be calling the const version of uri() here, since we don't
// need to modify anything.
static ExtensionParameter p_opaque_ext("opaque");
resip::Data opaque(c_test.uri().param(p_opaque_ext));
resipCerr << test << endl;
NameAddr copy = test;
resipCerr << copy << endl;
assert(resip::Data::from(test)==raw);
assert(resip::Data::from(copy)==raw);
}
{
TR _tr("Test find in ParserContainer");
Tokens tokens;
tokens.push_back(Token("Foo"));
tokens.push_back(Token("Bar"));
tokens.push_back(Token("Baz"));
tokens.push_back(Token("Quux"));
assert(tokens.find(Token("Foo")));
assert(tokens.find(Token("Bar")));
assert(tokens.find(Token("Baz")));
assert(tokens.find(Token("Quux")));
assert(!tokens.find(Token("Zab")));
}
{
TR _tr("Test remove parameters that appear multiple times");
Uri uri1("sip:a@b;xtype=1;maddr=local;xtype=2;maddr=remote;xtype=3;maddr=other");
Uri uri2(uri1);
uri1.remove(p_maddr);
Data res1;
{
DataStream str(res1);
str << uri1;
}
assert(res1 == "sip:a@b;xtype=1;xtype=2;xtype=3");
UnknownParameterType p_xtype("xtype");
uri2.remove(p_xtype);
Data res2;
{
DataStream str(res2);
str << uri2;
}
assert(res2 == "sip:a@b;maddr=local;maddr=remote;maddr=other");
}
{
{
TR _tr("Test remove parameters that appear multiple times");
Uri uri1("sips:bob@foo.com;transport=udp");
Uri aor = uri1.getAorAsUri();
Data res;
{
DataStream str(res);
str << aor;
}
resipCerr << res << endl;
assert(res == "sips:bob@foo.com");
}
}
{
TR _tr("Test remove parameters that appear multiple times; mixed predefined and extensions");
Uri uri1("sip:a@b;xtype=1;maddr=local;foo=bar;ttl=17;xtype=2;maddr=remote;foo=baz;ttl=42;xtype=3;maddr=other;foo=foo;ttl=111");
Uri uri2(uri1);
uri1.remove(p_maddr);
Data res1;
{
DataStream str(res1);
str << uri1;
}
assert(res1 == "sip:a@b;ttl=17;ttl=42;ttl=111;xtype=1;foo=bar;xtype=2;foo=baz;xtype=3;foo=foo");
UnknownParameterType p_xtype("xtype");
uri2.remove(p_xtype);
Data res2;
{
DataStream str(res2);
str << uri2;
}
assert(res2 == "sip:a@b;maddr=local;ttl=17;maddr=remote;ttl=42;maddr=other;ttl=111;foo=bar;foo=baz;foo=foo");
}
{
TR _tr("Test exists unknown parameter");
Uri uri1("sip:a@b;xaudio");
assert(uri1.exists(UnknownParameterType("xaudio")));
assert(uri1.param(UnknownParameterType("xaudio")) == Data::Empty);
Uri uri2("sip:a@b;a=b;xaudio");
resipCerr << uri2.param(UnknownParameterType("a")) << endl;
assert(uri2.exists(UnknownParameterType("xaudio")));
assert(uri2.param(UnknownParameterType("xaudio")) == Data::Empty);
Uri uri3("sip:a@b;xaudio;a=b");
assert(uri3.exists(UnknownParameterType("xaudio")));
assert(uri3.param(UnknownParameterType("xaudio")) == Data::Empty);
}
{
TR _tr("Test non-quoted tokens displayname in NameAddr (torture test: 2.39)");
Data data("A. Bell <sip:a.g.bell@bell-tel.com>;tag=459843");
NameAddr legal(data);
assert(legal.uri().host() == "bell-tel.com");
resipCerr << "!!" << legal << endl;
assert(legal.displayName() == "A. Bell");
}
{
TR _tr("Test quoted displayname in NameAddr (torture test: 2.39)");
Data data("\"A. Bell\" <sip:a.g.bell@bell-tel.com>;tag=459843");
NameAddr legal(data);
assert(legal.uri().host() == "bell-tel.com");
resipCerr << "!!" << legal.displayName() << endl;
assert(legal.displayName() == "A. Bell");
}
{
TR _tr("Test NameAddr parameter handling");
Data data("sip:foo@bar.com;user=phone");
NameAddr original(data);
assert(original.uri().exists(p_user));
resipCerr << "!!" << original << endl;
}
{
TR _tr("Test tel aor canonicalization");
Data data("tel:+14156268178;pOstd=pP2;isUb=1411");
Uri original(data);
resipCerr << original.getAor() << endl;
assert(original.getAor() == "+14156268178");
}
{
TR _tr("Test aor canonicalization");
Data data("sip:User@kElOwNa.GlOo.NeT:5666");
Data data1("sip:User@KeLoWnA.gLoO.nEt:5666");
Uri original(data);
Uri original1(data1);
resipCerr << "!! " << original.getAor() << " " << original1.getAor() << endl;
assert(original.getAor() == original1.getAor());
}
{
TR _tr("Test tel NameAddr");
NameAddr n1("<tel:98267168>");
resipCerr << n1.uri().user() << endl;
}
#ifdef USE_IPV6
{
TR _tr("Test cleverly malformed V6 addr in Uri");
const char* buf="sip:foo@[:x]";
HeaderFieldValue hfv(buf, strlen(buf));
NameAddr nameaddr(hfv, Headers::UNKNOWN);
assert(!nameaddr.isWellFormed());
}
#endif
{
TR _tr("Test empty NameAddr");
NameAddr n1;
NameAddr n2;
assert (!(n1 < n2));
assert (!(n2 < n1));
assert (n1.uri().getAor() == n2.uri().getAor());
}
{
TR _tr("Test NameAddr q value");
NameAddr w("<sip:wombat@192.168.2.221:5062;transport=Udp>;expires=63;q=1");
#ifndef RESIP_FIXED_POINT
assert(w.param(p_q) == 1.0);
#endif
assert(w.param(p_q) == 1000);
w.param(p_q) = 843;
assert(w.param(p_q) <= 843);
#ifndef RESIP_FIXED_POINT
assert(w.param(p_q) == 0.843);
w.param(p_q) = 0.843;
assert(w.param(p_q) == 843);
assert(w.param(p_q) == 0.843);
w.param(p_q) = 0.65;
assert(w.param(p_q) == 650);
#endif
w.param(p_q) = 0;
assert(w.param(p_q) == 0);
}
{
TR _tr("Test NameAddr comparison");
NameAddr w1("<sip:wombat@192.168.2.221:5062;transport=Udp>;expires=63");
NameAddr w2("<sip:wombat@192.168.2.221:5063;transport=Udp>;expires=66");
assert(w1 < w2);
assert (!(w2 < w1));
}
{
TR _tr("Test parameter with spaces");
Data txt("Digest username=\"Alice\", realm = \"atlanta.com\", nonce=\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\", reponse=\"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\"\r\n");
HeaderFieldValue hfv(txt.data(), txt.size());
Auth auth(hfv, Headers::Authorization);
assert(auth.scheme() == "Digest");
assert(auth.exists(p_realm));
}
{
TR _tr("Test uri with no user");
Data data("sip:kelowna.gloo.net");
Uri original(data);
resipCerr << original << endl;
assert(Data::from(original) == data);
}
{
TR _tr("Test uri with empty transport param");
Data data("sip:kelowna.gloo.net;transport=;udp");
try
{
Uri original(data);
assert(0);
}
catch(...)
{}
}
{
TR _tr("Test uri with empty transport param");
Data data("sip:kelowna.gloo.net;transport=;udp");
try
{
Uri original(data);
assert(0);
}
catch(...)
{}
}
{
TR _tr("Test assignment for NameAddr");
NameAddr original(Data("\"Original\"<sip:orig@example.com>;tag=original"));
(void)original.exists(p_tag);
// force parse
NameAddr newna(Data("\"new\"<sip:new@example.com>;tag=new"));
(void)newna.exists(p_tag);
cout << "original NameAddr: ->" << original << "<-"<< endl;
cout << "new NameAddr : ->" << newna << "<-" << endl;
original = newna;
cout << "original : ->" << original << "<-"<< endl;
assert(Data::from(original) == Data::from(newna));
}
{
TR _tr("Test @ in params for Uri");
Uri uri(Data("sip:example.com;lr;foo=\"@haha\""));
assert(uri.user().empty());
assert(uri.host()=="example.com");
assert(uri.port()==0);
}
{
TR _tr("Test unquoted @ in params for Uri");
// This is actually not an ambiguous case; '@' is not valid in either a
// param name or value, and ';' is legal in a userpart
Uri uri(Data("sip:example.com;lr;foo=fooba@haha"));
assert(uri.user()=="example.com;lr;foo=fooba");
assert(uri.host()=="haha");
assert(uri.port()==0);
}
{
TR _tr("Test : in params for Uri");
Uri uri(Data("sip:example.com;lr;foo=\":lol\""));
assert(uri.user().empty());
assert(uri.host()=="example.com");
assert(uri.port()==0);
}
{
TR _tr("Test unquoted : in params for Uri");
Uri uri(Data("sip:example.com;lr;foo=:lol"));
assert(uri.user().empty());
assert(uri.host()=="example.com");
assert(uri.port()==0);
}
{
TR _tr("Test unquoted : in params for Uri (2)");
Uri uri(Data("sip:example.com;lr;:foo=:lol"));
assert(uri.user().empty());
assert(uri.host()=="example.com");
assert(uri.port()==0);
}
{
TR _tr("Test @ in headers for Uri");
Uri uri(Data("sip:example.com?foo=\"@haha\""));
assert(uri.user().empty());
assert(uri.host()=="example.com");
assert(uri.port()==0);
}
{
TR _tr("Test unquoted @ in headers for Uri");
// This is actually not an ambiguous case; '@' is not valid in either an
// embedded header name or value, and '?' is legal in a userpart
Uri uri(Data("sip:example.com?foo=fooba@haha"));
assert(uri.user()=="example.com?foo=fooba");
assert(uri.host()=="haha");
assert(uri.port()==0);
}
{
TR _tr("Test : in headers for Uri");
Uri uri(Data("sip:example.com?foo=\":lol\""));
assert(uri.user().empty());
assert(uri.host()=="example.com");
assert(uri.port()==0);
}
{
TR _tr("Test unquoted : in headers for Uri");
Uri uri(Data("sip:example.com?foo=:lol"));
assert(uri.user().empty());
assert(uri.host()=="example.com");
assert(uri.port()==0);
}
{
TR _tr("Test unquoted : in headers for Uri (2)");
Uri uri(Data("sip:example.com?:foo=:lol"));
assert(uri.user().empty());
assert(uri.host()=="example.com");
assert(uri.port()==0);
}
{
TR _tr("Test typeless parameter copy");
Token s = Token("jason");
s.value() = "value";
s.param(p_expires) = 17;
s.param(p_lr_ext);
s.param(UnknownParameterType("foobie")) = "quux";
Token s1;
s1.value() = "other";
s1.param(p_retryAfter) = 21;
s.setParameter(s1.getParameterByEnum(ParameterTypes::retryAfter));
assert(s.value() == "value");
assert(s.param(p_retryAfter) == 21);
assert(s.exists(p_lr_ext));
assert(s.param(UnknownParameterType("foobie")) == "quux");
}
{
TR a("Test typeless parameter overwrite" );
Token s;
s.value() = "value";
s.param(p_expires) = 17;
s.param(p_retryAfter) = 12;
s.param(p_lr_ext);
s.param(UnknownParameterType("foobie")) = "quux";
Token s1;
s1.value() = "other";
s1.param(p_retryAfter) = 21;
s.setParameter(s1.getParameterByEnum(ParameterTypes::retryAfter));
assert(s.value() == "value");
assert(s.param(p_retryAfter) == 21);
assert(s.exists(p_lr_ext));
assert(s.param(UnknownParameterType("foobie")) == "quux");
s.encode(resipCerr);
resipCerr << endl;
}
{
TR _tr( "Test StringCategory");
Data stringString("Lame Agent");
HeaderFieldValue hfv(stringString.data(), stringString.size());
StringCategory str(hfv, Headers::UNKNOWN);
assert(str.value() == stringString);
Data buff;
{
DataStream s(buff);
str.encode(s);
}
resipCerr << buff << endl;
assert(buff == stringString);
StringCategory copy(str);
assert(copy.value() == stringString);
str.value() = "foo";
assert(str.value() == "foo");
}
{
TR _tr( "Test Token parameters");
Token state;
state.value() = Data("active");
state.param(p_expires) = 666;
resipCerr << state << endl;
}
{
TR _tr( "StatusLine, with reason code");
Data statusLineString("SIP/2.0 180 Ringing");
HeaderFieldValue hfv(statusLineString.data(), statusLineString.size());
StatusLine statusLine(hfv);
assert(statusLine.responseCode() == 180);
resipCerr << statusLine.reason() << endl;
assert(statusLine.reason() == "Ringing");
assert(statusLine.getSipVersion() == "SIP/2.0");
StatusLine copy(statusLine);
assert(copy.responseCode() == 180);
assert(copy.reason() == "Ringing");
assert(copy.getSipVersion() == "SIP/2.0");
}
{
Uri foo;
// valgrind complains, but the problem moves when closely observed
assert(foo.getAor().empty());
}
#define checkHeaderName(_name) resipCerr << Headers::_name << " " << Headers::getHeaderName(Headers::_name) << " = " << #_name << endl /*;assert(isEqualNoCase(Headers::getHeaderName(Headers::_name), #_name))*/
{
// test header hash
for (int i = Headers::CSeq; i < Headers::MAX_HEADERS; i++)
{
if (i == Headers::RESIP_DO_NOT_USE)
{
continue;
}
Data hdr = Headers::getHeaderName(i);
if (!hdr.size()) continue;
Data msg("Checking hash of: ");
msg += hdr;
TR _tr(msg);
assert(Headers::getType(Headers::getHeaderName(i).c_str(), Headers::getHeaderName(i).size()) == i);
}
checkHeaderName(To);
checkHeaderName(From);
checkHeaderName(Via);
checkHeaderName(CallID);
checkHeaderName(CSeq);
checkHeaderName(Route);
checkHeaderName(RecordRoute);
checkHeaderName(Contact);
checkHeaderName(Subject);
checkHeaderName(Expires);
checkHeaderName(MaxForwards);
checkHeaderName(Accept);
checkHeaderName(AcceptEncoding);
checkHeaderName(AcceptLanguage);
checkHeaderName(AlertInfo);
checkHeaderName(Allow);
checkHeaderName(AuthenticationInfo);
checkHeaderName(CallInfo);
checkHeaderName(ContentDisposition);
checkHeaderName(ContentEncoding);
checkHeaderName(ContentLanguage);
checkHeaderName(ContentTransferEncoding);
checkHeaderName(ContentType);
checkHeaderName(Date);
checkHeaderName(InReplyTo);
checkHeaderName(MinExpires);
checkHeaderName(MIMEVersion);
checkHeaderName(Organization);
checkHeaderName(Priority);
checkHeaderName(ProxyAuthenticate);
checkHeaderName(ProxyAuthorization);
checkHeaderName(ProxyRequire);
checkHeaderName(ReplyTo);
checkHeaderName(Require);
checkHeaderName(RetryAfter);
checkHeaderName(Server);
checkHeaderName(SIPETag);
checkHeaderName(SIPIfMatch);
checkHeaderName(Supported);
checkHeaderName(Timestamp);
checkHeaderName(Unsupported);
checkHeaderName(UserAgent);
checkHeaderName(Warning);
checkHeaderName(WWWAuthenticate);
checkHeaderName(SubscriptionState);
checkHeaderName(ReferTo);
checkHeaderName(ReferredBy);
checkHeaderName(Authorization);
checkHeaderName(Replaces);
checkHeaderName(Event);
checkHeaderName(AllowEvents);
checkHeaderName(SecurityClient);
checkHeaderName(SecurityServer);
checkHeaderName(SecurityVerify);
checkHeaderName(ContentLength);
checkHeaderName(ContentId);
}
#define checkParameterName(_name) resipCerr << ParameterTypes::_name << " " << ParameterTypes::ParameterNames[ParameterTypes::_name] << " = " << #_name << endl/*;assert(isEqualNoCase(ParameterTypes::ParameterNames[ParameterTypes::_name], #_name))*/
{
checkParameterName(data);
checkParameterName(control);
checkParameterName(mobility);
checkParameterName(description);
checkParameterName(events);
checkParameterName(priority);
checkParameterName(methods);
checkParameterName(schemes);
checkParameterName(application);
checkParameterName(video);
checkParameterName(language);
checkParameterName(type);
checkParameterName(isFocus);
checkParameterName(actor);
checkParameterName(text);
checkParameterName(extensions);
checkParameterName(Instance);
checkParameterName(gr);
checkParameterName(transport);
checkParameterName(user);
checkParameterName(method);
checkParameterName(ttl);
checkParameterName(maddr);
checkParameterName(lr);
checkParameterName(q);
checkParameterName(purpose);
checkParameterName(expires);
checkParameterName(handling);
checkParameterName(tag);
checkParameterName(toTag);
checkParameterName(fromTag);
checkParameterName(duration);
checkParameterName(branch);
checkParameterName(received);
checkParameterName(comp);
checkParameterName(rport);
checkParameterName(algorithm);
checkParameterName(cnonce);
checkParameterName(domain);
checkParameterName(id);
checkParameterName(nonce);
checkParameterName(nc);
checkParameterName(opaque);
checkParameterName(realm);
checkParameterName(response);
checkParameterName(stale);
checkParameterName(username);
checkParameterName(qop);
checkParameterName(uri);
checkParameterName(retryAfter);
checkParameterName(reason);
checkParameterName(dAlg);
checkParameterName(dQop);
checkParameterName(dVer);
checkParameterName(smimeType);
checkParameterName(name);
checkParameterName(filename);
checkParameterName(protocol);
checkParameterName(micalg);
checkParameterName(boundary);
checkParameterName(expiration);
checkParameterName(size);
checkParameterName(permission);
checkParameterName(site);
checkParameterName(directory);
checkParameterName(mode);
checkParameterName(server);
checkParameterName(charset);
checkParameterName(accessType);
checkParameterName(profileType);
checkParameterName(vendor);
checkParameterName(model);
checkParameterName(version);
checkParameterName(effectiveBy);
checkParameterName(document);
checkParameterName(appId);
checkParameterName(networkUser);
checkParameterName(url);
// test parameter hash
for (int i = 0; i < ParameterTypes::MAX_PARAMETER; i++)
{
if (i != ParameterTypes::qopOptions &&
i != ParameterTypes::qop )
{
TR _tr( Data("Checking hash of: ") + Data(ParameterTypes::ParameterNames[i]));
assert(ParameterTypes::getType(ParameterTypes::ParameterNames[i].c_str(),
ParameterTypes::ParameterNames[i].size()) == i);
}
}
assert(ParameterTypes::ParameterNames[ParameterTypes::qop] == "qop");
assert(ParameterTypes::ParameterNames[ParameterTypes::qopOptions] == "qop");
}
{
TR _tr( "simple Token parse test");
const char *org = "WuggaWuggaFoo";
HeaderFieldValue hfv(org, strlen(org));
Token tok(hfv, Headers::UNKNOWN);
assert(tok.value() == org);
}
{
TR _tr( "Token + parameters parse test");
const char *org = "WuggaWuggaFoo;ttl=2;retry-after=3";
HeaderFieldValue hfv(org, strlen(org));
Token tok(hfv, Headers::UNKNOWN);
assert(tok.value() == "WuggaWuggaFoo");
assert(tok.param(p_ttl_ext) == "2");
assert(tok.param(p_retryAfter) == 3);
}
{
TR _tr( "Test NameAddr(Data) constructor");
Data nad("bob<sips:bob@foo.com>;tag=wd834f");
NameAddr na(nad);
assert(na.uri().user() == "bob");
}
{
TR _tr( "full on via parse");
const char *viaString = /* Via: */ " SIP/2.0/UDP a.b.c.com:5000;ttl=3;maddr=1.2.3.4;received=foo.com";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert(via.sentPort() == 5000);
assert(via.sentHost() == "a.b.c.com");
assert(via.param(p_maddr) == "1.2.3.4");
}
#ifdef USE_IPV6
{
TR _tr( "Via assert bug with malformed IPV6 addr [boom]" );
const char* viaString = "SIP/2.0/UDP [boom]:5060;branch=z9hG4bKblah";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert(!via.isWellFormed());
}
{
TR _tr( "Via assert bug with malformed IPV6 addr [:z]" );
const char* viaString = "SIP/2.0/UDP [:z]:5060;branch=z9hG4bKblah";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert(!via.isWellFormed());
}
#endif
{
TR _tr("Test poorly formed DataParameter by construction");
const char *viaString = /* Via: */ " SIP/2.0/UDP example.com:5000;;tag=";
HeaderFieldValue hfv(viaString, strlen(viaString));
try
{
Via via(hfv, Headers::UNKNOWN);
via.sentPort();
assert(false);
}
catch (ParseException& e)
{
resipCerr << "Caught parse exception for Via" << endl;
}
}
{
TR _tr("Test poorly formed UnknownParameter by construction");
const char *viaString = /* Via: */ " SIP/2.0/UDP example.com:5000;;foobar=";
HeaderFieldValue hfv(viaString, strlen(viaString));
try
{
Via via(hfv, Headers::UNKNOWN);
via.sentPort();
UnknownParameterType p_foobar("foobar");
via.exists(p_foobar);
assert(false);
}
catch (ParseException& e)
{
resipCerr << "Caught parse exception for Via" << endl;
}
}
{
TR _tr("Test poorly formed UInt32Parameter by construction");
const char *viaString = /* Via: */ " SIP/2.0/UDP example.com:5000;;duration=";
HeaderFieldValue hfv(viaString, strlen(viaString));
try
{
Via via(hfv, Headers::UNKNOWN);
via.sentPort();
assert(false);
}
catch (ParseException& e)
{
resipCerr << "Caught parse exception for Via " << endl;
}
}
{
TR _tr("Test poorly formed QuotedDataParameter by construction");
const char *viaString = /* Via: */ " SIP/2.0/UDP example.com:5000;;domain=\"";
HeaderFieldValue hfv(viaString, strlen(viaString));
try
{
Via via(hfv, Headers::UNKNOWN);
via.sentPort();
assert(false);
}
catch (ParseException& e)
{
resipCerr << "Caught parse exception for Via " << endl;
}
}
#ifdef USE_IPV6
{
TR _tr( "full on via parse, IPV6");
// !dlb! deal with maddr=[5f1b:df00:ce3e:e200:20:800:2b37:6426]
const char *viaString = /* Via: */ " SIP/2.0/UDP [5f1b:df00:ce3e:e200:20:800:2b37:6426]:5000;ttl=3;maddr=1.2.3.4;received=foo.com";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert(via.sentPort() == 5000);
assert(via.sentHost() == "5f1b:df00:ce3e:e200:20:800:2b37:6426");
assert(via.param(p_maddr) == "1.2.3.4");
}
#endif
{
TR _tr( "URI parse");
Data uriString = "sip:bob@foo.com";
ParseBuffer pb(uriString.data(), uriString.size());
NameAddr to;
to.parse(pb);
Uri& uri = to.uri();
resipCerr << "!! " << to << endl;
assert(uri.scheme() == "sip");
assert(uri.user() == "bob");
assert(uri.host() == "foo.com");
assert(uri.port() == 0);
}
{
TR _tr( "URI parse, no displayName");
Data uriString = "sips:foo.com";
ParseBuffer pb(uriString.data(), uriString.size());
NameAddr to;
to.parse(pb);
Uri& uri = to.uri();
assert(uri.scheme() == "sips");
assert(uri.user() == "");
assert(uri.host() == "foo.com");
assert(uri.port() == 0);
}
{
TR _tr( "URI parse, parameters");
Data uriString = "sips:bob;param=gargle:password@foo.com";
ParseBuffer pb(uriString.data(), uriString.size());
NameAddr to;
to.parse(pb);
Uri& uri = to.uri();
assert(uri.scheme() == "sips");
assert(uri.user() == "bob;param=gargle");
assert(uri.password() == "password");
assert(uri.host() == "foo.com");
}
{
TR _tr( "URI parse, parameters, port");
Data uriString = "sips:bob;param=gargle:password@foo.com:6000";
ParseBuffer pb(uriString.data(), uriString.size());
NameAddr to;
to.parse(pb);
Uri& uri = to.uri();
assert(uri.scheme() == "sips");
assert(uri.user() == "bob;param=gargle");
assert(uri.password() == "password");
assert(uri.host() == "foo.com");
assert(uri.port() == 6000);
}
{
TR _tr( "URI parse, parameters, correct termination check");
Data uriString = "sips:bob;param=gargle:password@foo.com notHost";
ParseBuffer pb(uriString.data(), uriString.size());
NameAddr to;
to.parse(pb);
Uri& uri = to.uri();
assert(uri.scheme() == "sips");
assert(uri.user() == "bob;param=gargle");
assert(uri.password() == "password");
resipCerr << "Uri:" << uri.host() << endl;
assert(uri.host() == "foo.com");
}
{
TR _tr( "URI parse, transport parameter");
Data uriString = "sip:bob@biloxi.com;transport=udp";
ParseBuffer pb(uriString.data(), uriString.size());
NameAddr to;
to.parse(pb);
Uri& uri = to.uri();
assert(uri.param(p_transport) == "udp");
}
resipCerr << "URI comparison tests" << endl;
{
Data uriStringA("sip:carol@chicago.com");
Data uriStringB("sip:carol@chicago.com;newparam=5");
Data uriStringC("sip:carol@chicago.com;security=on");
ParseBuffer pa(uriStringA.data(), uriStringA.size());
ParseBuffer pb(uriStringB.data(), uriStringB.size());
ParseBuffer pc(uriStringC.data(), uriStringC.size());
NameAddr nA, nB, nC;
nA.parse(pa);
nB.parse(pb);
nC.parse(pc);
Uri& uA = nA.uri();
Uri& uB = nB.uri();
Uri& uC = nC.uri();
assert(uA == uB);
assert(uB == uC);
assert(uA == uC);
}
{
Data uriStringA = "sip:biloxi.com;transport=tcp;method=REGISTER";
Data uriStringB = "sip:biloxi.com;method=REGISTER;transport=tcp";
ParseBuffer pa(uriStringA.data(), uriStringA.size());
ParseBuffer pb(uriStringB.data(), uriStringB.size());
NameAddr nA, nB;
nA.parse(pa);
nB.parse(pb);
Uri& uA = nA.uri();
Uri& uB = nB.uri();
assert(uA == uB);
}
{
Data uriStringA = "sip:alice@atlanta.com";
Data uriStringB = "sip:alice@atlanta.com";
ParseBuffer pa(uriStringA.data(), uriStringA.size());
ParseBuffer pb(uriStringB.data(), uriStringB.size());
NameAddr nA, nB;
nA.parse(pa);
nB.parse(pb);
Uri& uA = nA.uri();
Uri& uB = nB.uri();
assert(uA == uB);
}
{
Data uriStringA = "sip:alice@AtLanTa.CoM;Transport=UDP";
Data uriStringB = "SIP:ALICE@AtLanTa.CoM;Transport=udp";
ParseBuffer pa(uriStringA.data(), uriStringA.size());
ParseBuffer pb(uriStringB.data(), uriStringB.size());
NameAddr nA, nB;
nA.parse(pa);
nB.parse(pb);
Uri& uA = nA.uri();
Uri& uB = nB.uri();
assert(uA != uB);
}
{
Data uriStringA = "sip:bob@192.0.2.4";
Data uriStringB = "sip:bob@phone21.boxesbybob.com";
ParseBuffer pa(uriStringA.data(), uriStringA.size());
ParseBuffer pb(uriStringB.data(), uriStringB.size());
NameAddr nA, nB;
nA.parse(pa);
nB.parse(pb);
Uri& uA = nA.uri();
Uri& uB = nB.uri();
assert(uA != uB);
}
{
Data uriStringA = "sip:bob@biloxi.com:6000;transport=tcp";
Data uriStringB = "sip:bob@biloxi.com";
ParseBuffer pa(uriStringA.data(), uriStringA.size());
ParseBuffer pb(uriStringB.data(), uriStringB.size());
NameAddr nA, nB;
nA.parse(pa);
nB.parse(pb);
Uri& uA = nA.uri();
Uri& uB = nB.uri();
assert(uA != uB);
}
{
Data uriStringA = "sip:bob@biloxi.com;transport=udp";
Data uriStringB = "sip:bob@biloxi.com";
ParseBuffer pa(uriStringA.data(), uriStringA.size());
ParseBuffer pb(uriStringB.data(), uriStringB.size());
NameAddr nA, nB;
nA.parse(pa);
nB.parse(pb);
Uri& uA = nA.uri();
Uri& uB = nB.uri();
resipCerr << "A: " << uA << endl;
resipCerr << "B: " << uB << endl;
resipCerr << "A:exists(transport) " << uA.exists(p_transport) << endl;
assert(uA != uB);
}
{ //embedded header comparison, not supported yet
// char *uriStringA = "sip:carol@chicago.com?Subject=next%20meeting";
// char *uriStringB = "sip:carol@chicago.com";
// ParseBuffer pa(uriStringA, strlen(uriStringA));
// ParseBuffer pb(uriStringB, strlen(uriStringB));
// Uri uA, uB;
// uA.parse(uriStringA);
// uB.parse(uriStringB);
// assert(uA != uB);
}
{
TR _tr( "Request Line parse");
Data requestLineString("INVITE sips:bob@foo.com SIP/2.0");
HeaderFieldValue hfv(requestLineString.data(), requestLineString.size());
RequestLine requestLine(hfv);
assert(requestLine.uri().scheme() == "sips");
assert(requestLine.uri().user() == "bob");
resipCerr << requestLine.uri().host() << endl;
assert(requestLine.uri().host() == "foo.com");
assert(requestLine.getMethod() == INVITE);
assert(requestLine.getSipVersion() == "SIP/2.0");
}
{
TR _tr( "Request Line parse tel");
Data requestLineString("INVITE tel:4153331212 SIP/2.0");
HeaderFieldValue hfv(requestLineString.data(), requestLineString.size());
RequestLine requestLine(hfv);
assert(requestLine.uri().scheme() == "tel");
assert(requestLine.uri().user() == "4153331212");
assert(requestLine.getMethod() == INVITE);
assert(requestLine.getSipVersion() == "SIP/2.0");
}
{
TR _tr( "Request Line parse, parameters");
Data requestLineString("INVITE sips:bob@foo.com;maddr=1.2.3.4 SIP/2.0");
HeaderFieldValue hfv(requestLineString.data(), requestLineString.size());
RequestLine requestLine(hfv);
assert(requestLine.uri().scheme() == "sips");
assert(requestLine.uri().user() == "bob");
resipCerr << requestLine.uri().host() << endl;
assert(requestLine.uri().host() == "foo.com");
assert(requestLine.getMethod() == INVITE);
assert(requestLine.uri().param(p_maddr) == "1.2.3.4");
resipCerr << requestLine.getSipVersion() << endl;
assert(requestLine.getSipVersion() == "SIP/2.0");
}
{
TR _tr( "NameAddr parse");
Data nameAddrString("sips:bob@foo.com");
HeaderFieldValue hfv(nameAddrString.data(), nameAddrString.size());
NameAddr nameAddr(hfv, Headers::UNKNOWN);
assert(nameAddr.uri().scheme() == "sips");
assert(nameAddr.uri().user() == "bob");
assert(nameAddr.uri().host() == "foo.com");
}
{
TR _tr( "NameAddr parse, displayName");
Data nameAddrString("Bob<sips:bob@foo.com>");
HeaderFieldValue hfv(nameAddrString.data(), nameAddrString.size());
NameAddr nameAddr(hfv, Headers::UNKNOWN);
assert(nameAddr.displayName() == "Bob");
assert(nameAddr.uri().scheme() == "sips");
assert(nameAddr.uri().user() == "bob");
assert(nameAddr.uri().host() == "foo.com");
}
{
TR _tr( "NameAddr parse, quoted displayname");
Data nameAddrString = "\"Bob\"<sips:bob@foo.com>";
HeaderFieldValue hfv(nameAddrString.data(), nameAddrString.size());
NameAddr nameAddr(hfv, Headers::UNKNOWN);
assert(nameAddr.displayName() == "Bob");
assert(nameAddr.uri().scheme() == "sips");
assert(nameAddr.uri().user() == "bob");
assert(nameAddr.uri().host() == "foo.com");
}
{
TR _tr( "NameAddr parse, quoted displayname, embedded quotes");
Data nameAddrString("\"Bob \\\" asd \"<sips:bob@foo.com>");
HeaderFieldValue hfv(nameAddrString.data(), nameAddrString.size());
NameAddr nameAddr(hfv, Headers::UNKNOWN);
assert(nameAddr.displayName() == "Bob \\\" asd ");
assert(nameAddr.uri().scheme() == "sips");
assert(nameAddr.uri().user() == "bob");
assert(nameAddr.uri().host() == "foo.com");
}
{
TR _tr( "NameAddr parse, unquoted displayname, paramterMove");
Data nameAddrString("Bob<sips:bob@foo.com>;tag=456248;mobility=\"hobble\"");
HeaderFieldValue hfv(nameAddrString.data(), nameAddrString.size());
NameAddr nameAddr(hfv, Headers::UNKNOWN);
assert(nameAddr.displayName() == "Bob");
assert(nameAddr.uri().scheme() == "sips");
assert(nameAddr.uri().user() == "bob");
assert(nameAddr.uri().host() == "foo.com");
resipCerr << "Uri params: ";
nameAddr.uri().encodeParameters(resipCerr) << endl;
resipCerr << "Header params: ";
nameAddr.encodeParameters(resipCerr) << endl;
assert(nameAddr.param(p_tag) == "456248");
assert(nameAddr.param(p_mobility) == "hobble");
assert(nameAddr.uri().exists(p_tag_ext) == false);
assert(nameAddr.uri().exists(p_mobility_ext) == false);
}
{
TR _tr( "NameAddr parse, quoted displayname, parameterMove");
Data nameAddrString("\"Bob\"<sips:bob@foo.com>;tag=456248;mobility=\"hobble\"");
HeaderFieldValue hfv(nameAddrString.data(), nameAddrString.size());
NameAddr nameAddr(hfv, Headers::UNKNOWN);
assert(nameAddr.displayName() == "Bob");
assert(nameAddr.uri().scheme() == "sips");
assert(nameAddr.uri().user() == "bob");
assert(nameAddr.uri().host() == "foo.com");
resipCerr << "Uri params: ";
nameAddr.uri().encodeParameters(resipCerr) << endl;
resipCerr << "Header params: ";
nameAddr.encodeParameters(resipCerr) << endl;
assert(nameAddr.param(p_tag) == "456248");
assert(nameAddr.param(p_mobility) == "hobble");
assert(nameAddr.uri().exists(p_tag_ext) == false);
assert(nameAddr.uri().exists(p_mobility_ext) == false);
}
{
TR _tr( "NameAddr parse, unquoted displayname, paramterMove");
Data nameAddrString("Bob<sips:bob@foo.com;tag=456248;mobility=\"hobble\">");
HeaderFieldValue hfv(nameAddrString.data(), nameAddrString.size());
NameAddr nameAddr(hfv, Headers::UNKNOWN);
assert(nameAddr.displayName() == "Bob");
assert(nameAddr.uri().scheme() == "sips");
assert(nameAddr.uri().user() == "bob");
assert(nameAddr.uri().host() == "foo.com");
resipCerr << "Uri params: ";
nameAddr.uri().encodeParameters(resipCerr) << endl;
resipCerr << "Header params: ";
nameAddr.encodeParameters(resipCerr) << endl;
assert(nameAddr.uri().param(p_tag_ext) == "456248");
assert(nameAddr.uri().param(p_mobility_ext) == "hobble");
assert(nameAddr.exists(p_tag) == false);
assert(nameAddr.exists(p_mobility) == false);
}
{
TR _tr( "NameAddr parse, unquoted displayname, paramterMove");
Data nameAddrString("Bob<sips:bob@foo.com;mobility=\"hobb;le\";tag=\"true;false\">");
HeaderFieldValue hfv(nameAddrString.data(), nameAddrString.size());
NameAddr nameAddr(hfv, Headers::UNKNOWN);
assert(nameAddr.displayName() == "Bob");
assert(nameAddr.uri().scheme() == "sips");
assert(nameAddr.uri().user() == "bob");
assert(nameAddr.uri().host() == "foo.com");
resipCerr << "Uri params: ";
nameAddr.uri().encodeParameters(resipCerr) << endl;
resipCerr << "Header params: ";
nameAddr.encodeParameters(resipCerr) << endl;
assert(nameAddr.uri().param(p_mobility_ext) == "hobb;le");
assert(nameAddr.uri().param(p_tag_ext) == "true;false");
// assert("true;false" == nameAddr.uri().param(Data("useless")));
assert(nameAddr.exists(p_mobility) == false);
}
{
TR _tr( "NameAddr parse");
Data nameAddrString("sip:101@localhost:5080;transport=UDP");
HeaderFieldValue hfv(nameAddrString.data(), nameAddrString.size());
NameAddr nameAddr(hfv, Headers::UNKNOWN);
assert(nameAddr.displayName() == "");
assert(nameAddr.uri().scheme() == "sip");
assert(nameAddr.uri().user() == "101");
}
{
TR _tr( "NameAddr parse, no user in uri");
Data nameAddrString("sip:localhost:5070");
HeaderFieldValue hfv(nameAddrString.data(), nameAddrString.size());
NameAddr nameAddr(hfv, Headers::UNKNOWN);
assert(nameAddr.displayName() == "");
assert(nameAddr.uri().scheme() == "sip");
assert(nameAddr.uri().host() == "localhost");
assert(nameAddr.uri().user() == "");
assert(nameAddr.uri().port() == 5070);
}
{
TR _tr( "StatusLine, no reason code");
Data statusLineString("SIP/2.0 100 ");
HeaderFieldValue hfv(statusLineString.data(), statusLineString.size());
StatusLine statusLine(hfv);
assert(statusLine.responseCode() == 100);
assert(statusLine.reason() == "");
assert(statusLine.getSipVersion() == "SIP/2.0");
}
{
TR _tr( "StatusLine, no reason code");
Data statusLineString("SIP/2.0 100");
HeaderFieldValue hfv(statusLineString.data(), statusLineString.size());
StatusLine statusLine(hfv);
assert(statusLine.responseCode() == 100);
assert(statusLine.reason() == "");
assert(statusLine.getSipVersion() == "SIP/2.0");
}
{
TR _tr("Auth Schemes");
const char* authorizationString = "Digest realm=\"66.100.107.120\", username=\"1234\", nonce=\"1011235448\" , uri=\"sip:66.100.107.120\" , algorithm=MD5, response=\"8a5165b024fda362ed9c1e29a7af0ef2\"";
HeaderFieldValue hfv(authorizationString, strlen(authorizationString));
Auth auth(hfv, Headers::UNKNOWN);
resipCerr << "Auth scheme: " << auth.scheme() << endl;
assert(auth.scheme() == "Digest");
resipCerr << " realm: " << auth.param(p_realm) << endl;
assert(auth.param(p_realm) == "66.100.107.120");
assert(auth.param(p_username) == "1234");
assert(auth.param(p_nonce) == "1011235448");
assert(auth.param(p_uri) == "sip:66.100.107.120");
assert(auth.param(p_algorithm) == "MD5");
assert(auth.param(p_response) == "8a5165b024fda362ed9c1e29a7af0ef2");
Data dsData;
{
DataStream s(dsData);
auth.encode(s);
}
resipCerr << dsData.c_str() << endl;
assert(dsData == "Digest realm=\"66.100.107.120\",username=\"1234\",nonce=\"1011235448\",uri=\"sip:66.100.107.120\",algorithm=MD5,response=\"8a5165b024fda362ed9c1e29a7af0ef2\"");
}
{
TR _tr("More Auth");
const char* authorizationString = "realm=\"66.100.107.120\", username=\"1234\", nonce=\"1011235448\" , uri=\"sip:66.100.107.120\" , algorithm=MD5, response=\"8a5165b024fda362ed9c1e29a7af0ef2\"";
HeaderFieldValue hfv(authorizationString, strlen(authorizationString));
Auth auth(hfv, Headers::UNKNOWN);
resipCerr << "Auth scheme: " << auth.scheme() << endl;
assert(auth.scheme() == "");
resipCerr << " realm: " << auth.param(p_realm) << endl;
assert(auth.param(p_realm) == "66.100.107.120");
assert(auth.param(p_username) == "1234");
assert(auth.param(p_nonce) == "1011235448");
assert(auth.param(p_uri) == "sip:66.100.107.120");
assert(auth.param(p_algorithm) == "MD5");
assert(auth.param(p_response) == "8a5165b024fda362ed9c1e29a7af0ef2");
Data dsData;
{
DataStream s(dsData);
auth.encode(s);
}
resipCerr << dsData.c_str() << endl;
assert(dsData == "realm=\"66.100.107.120\",username=\"1234\",nonce=\"1011235448\",uri=\"sip:66.100.107.120\",algorithm=MD5,response=\"8a5165b024fda362ed9c1e29a7af0ef2\"");
}
{
TR _tr("Testing qop stuff");
const char* authenticationString = "realm=\"66.100.107.120\", username=\"1234\", nonce=\"1011235448\" , uri=\"sip:66.100.107.120\" , algorithm=MD5, qop=\"auth,auth-int\"";
const char* authorizationString = "realm=\"66.100.107.120\", username=\"1234\", nonce=\"1011235448\" , uri=\"sip:66.100.107.120\" , algorithm=MD5, response=\"8a5165b024fda362ed9c1e29a7af0ef2\", qop=auth";
HeaderFieldValue authenHfv(authenticationString, strlen(authenticationString));
HeaderFieldValue authorHfv(authorizationString, strlen(authorizationString));
Auth wwwAuthen(authenHfv, Headers::WWWAuthenticate);
Auth pAuthen(authenHfv, Headers::ProxyAuthenticate);
Auth authInfo(authorHfv, Headers::AuthenticationInfo);
Auth pAuthor(authorHfv, Headers::ProxyAuthorization);
Auth author(authorHfv, Headers::Authorization);
assert(wwwAuthen.exists(p_qopOptions));
assert(!wwwAuthen.exists(p_qop));
assert(wwwAuthen.param(p_qopOptions)=="auth,auth-int");
assert(pAuthen.exists(p_qopOptions));
assert(!pAuthen.exists(p_qop));
assert(pAuthen.param(p_qopOptions)=="auth,auth-int");
assert(!authInfo.exists(p_qopOptions));
assert(authInfo.exists(p_qop));
assert(authInfo.param(p_qop)=="auth");
assert(!pAuthor.exists(p_qopOptions));
assert(pAuthor.exists(p_qop));
assert(pAuthor.param(p_qop)=="auth");
assert(!author.exists(p_qopOptions));
assert(author.exists(p_qop));
assert(author.param(p_qop)=="auth");
{
Data encoded;
{
oDataStream str(encoded);
wwwAuthen.encode(str);
}
assert(encoded.find("qop=auth")==Data::npos);
assert(encoded.find("qop=\"auth,auth-int\"")!=Data::npos);
assert(encoded.find("qop=\"auth\"")==Data::npos);
assert(encoded.find("qop=auth,auth-int")==Data::npos);
}
{
Data encoded;
{
oDataStream str(encoded);
pAuthen.encode(str);
}
assert(encoded.find("qop=auth")==Data::npos);
assert(encoded.find("qop=\"auth,auth-int\"")!=Data::npos);
assert(encoded.find("qop=\"auth\"")==Data::npos);
assert(encoded.find("qop=auth,auth-int")==Data::npos);
}
{
Data encoded;
{
oDataStream str(encoded);
authInfo.encode(str);
}
assert(encoded.find("qop=auth")!=Data::npos);
assert(encoded.find("qop=\"auth,auth-int\"")==Data::npos);
assert(encoded.find("qop=\"auth\"")==Data::npos);
assert(encoded.find("qop=auth,auth-int")==Data::npos);
}
{
Data encoded;
{
oDataStream str(encoded);
pAuthor.encode(str);
}
assert(encoded.find("qop=auth")!=Data::npos);
assert(encoded.find("qop=\"auth,auth-int\"")==Data::npos);
assert(encoded.find("qop=\"auth\"")==Data::npos);
assert(encoded.find("qop=auth,auth-int")==Data::npos);
}
{
Data encoded;
{
oDataStream str(encoded);
author.encode(str);
}
assert(encoded.find("qop=auth")!=Data::npos);
assert(encoded.find("qop=\"auth,auth-int\"")==Data::npos);
assert(encoded.find("qop=\"auth\"")==Data::npos);
assert(encoded.find("qop=auth,auth-int")==Data::npos);
}
Auth emptyAuthor;
Auth emptyAuthen;
emptyAuthor.param(p_qop)="auth";
emptyAuthen.param(p_qopOptions)="auth";
{
Data encoded;
{
oDataStream str(encoded);
emptyAuthor.encode(str);
}
assert(encoded.find("qop=auth")!=Data::npos);
assert(encoded.find("qop=\"auth\"")==Data::npos);
}
{
Data encoded;
{
oDataStream str(encoded);
emptyAuthen.encode(str);
}
assert(encoded.find("qop=auth")==Data::npos);
assert(encoded.find("qop=\"auth\"")!=Data::npos);
}
}
{
TR _tr("More Auth Encoding");
Auth auth;
Auth auth2;
auth.scheme() = "Digest";
auth.param(p_username) = "bob";
auth2 = auth;
Auth auth3(auth2);
Data a;
Data a1;
Data a2;
{
DataStream s(a);
s << auth;
}
{
DataStream s(a1);
s << auth;
}
{
DataStream s(a2);
s << auth;
}
assert(a == a1);
assert(a1 == a2);
}
{
TR _tr("Generic URI stuff");
const char* genericString = "<http://www.google.com>;purpose=icon;fake=true";
HeaderFieldValue hfv(genericString, strlen(genericString));
GenericUri generic(hfv, Headers::UNKNOWN);
assert(generic.uri() == "http://www.google.com");
resipCerr << generic.param(p_purpose) << endl;
assert(generic.param(p_purpose) == "icon");
assert(generic.param(UnknownParameterType("fake")) == "true");
Data dsData;
{
DataStream s(dsData);
generic.encode(s);
}
resipCerr << dsData.c_str() << endl;
assert(dsData == "<http://www.google.com>;purpose=icon;fake=true");
}
{
TR _tr("Date testing 1");
const char *dateString = "Mon, 04 Nov 2002 17:34:15 GMT";
HeaderFieldValue hfv(dateString, strlen(dateString));
DateCategory date(hfv, Headers::UNKNOWN);
assert(date.dayOfWeek() == Mon);
assert(date.dayOfMonth() == 04);
assert(date.month() == Nov);
assert(date.year() == 2002);
assert(date.hour() == 17);
assert(date.minute() == 34);
assert(date.second() == 15);
Data dsData;
{
DataStream s(dsData);
date.encode(s);
}
resipCerr << dsData.c_str() << endl;
assert(dsData == dateString);
// copy ctor not working in v1.94 ParserCategories.cxx
dsData.clear();
DateCategory otherDate(date);
{
DataStream s2(dsData);
otherDate.encode(s2);
}
resipCerr << "!! original date : " << date << endl;
resipCerr << "!! original string : " << dateString << endl;
resipCerr << "!! otherDate : " << otherDate << endl;
resipCerr << "!! encoded otherDate : " << dsData.c_str() << endl;
assert (dsData == dateString);
}
{
TR _tr("Date testing 2");
const char *dateString = " Sun , 14 Jan 2222 07:04:05 GMT ";
HeaderFieldValue hfv(dateString, strlen(dateString));
DateCategory date(hfv, Headers::UNKNOWN);
assert(date.dayOfWeek() == Sun);
assert(date.dayOfMonth() == 14);
assert(date.month() == Jan);
assert(date.year() == 2222);
assert(date.hour() == 07);
assert(date.minute() == 04);
assert(date.second() == 05);
Data dsData;
{
DataStream s(dsData);
date.encode(s);
}
assert(dsData == "Sun, 14 Jan 2222 07:04:05 GMT");
}
{
TR _tr("Mime types 1");
const char* mimeString = "application/sdp";
HeaderFieldValue hfv(mimeString, strlen(mimeString));
Mime mime(hfv, Headers::UNKNOWN);
assert(mime.type() == "application");
assert(mime.subType() == "sdp");
Data dsData;
{
DataStream s(dsData);
mime.encode(s);
}
assert(dsData == mimeString);
}
{
TR _tr("Mime types 2");
const char* mimeString = "text/html ; charset=ISO-8859-4";
HeaderFieldValue hfv(mimeString, strlen(mimeString));
Mime mime(hfv, Headers::UNKNOWN);
assert(mime.type() == "text");
assert(mime.subType() == "html");
assert(mime.param(p_charset) == "ISO-8859-4");
Data dsData;
{
DataStream s(dsData);
mime.encode(s);
}
assert(dsData == "text/html;charset=ISO-8859-4");
}
{
TR _tr("Mime types 3");
const char* mimeString = " text / html ; charset=ISO-8859-4";
HeaderFieldValue hfv(mimeString, strlen(mimeString));
Mime mime(hfv, Headers::UNKNOWN);
assert(mime.type() == "text");
assert(mime.subType() == "html");
assert(mime.param(p_charset) == "ISO-8859-4");
Data dsData;
{
DataStream s(dsData);
mime.encode(s);
}
assert(dsData == "text/html;charset=ISO-8859-4");
}
{
TR _tr("Via 1");
Via via;
via.encode(resipCerr);
resipCerr << endl;
assert (via.param(p_branch).hasMagicCookie());
}
{
TR _tr("Via 2");
const char* viaString = "SIP/2.0/UDP ;branch=z9hG4bKwkl3lkjsdfjklsdjklfdsjlkdklj";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert (via.param(p_branch).hasMagicCookie());
Data dsData;
{
DataStream s0(dsData);
via.encode(s0);
}
resipCerr << dsData.c_str() << endl;
assert(dsData == "SIP/2.0/UDP ;branch=z9hG4bKwkl3lkjsdfjklsdjklfdsjlkdklj");
assert (via.param(p_branch).getTransactionId() == "wkl3lkjsdfjklsdjklfdsjlkdklj");
dsData.clear();
{
DataStream s1(dsData);
via.encode(s1);
}
assert(dsData == "SIP/2.0/UDP ;branch=z9hG4bKwkl3lkjsdfjklsdjklfdsjlkdklj");
via.param(p_branch).reset("jason");
dsData.clear();
{
DataStream s2(dsData);
via.encode(s2);
}
resipCerr << "!! " << dsData.c_str() << endl;
assert(dsData == "SIP/2.0/UDP ;branch=z9hG4bK" RESIP_COOKIE "1---jason");
assert(via.param(p_branch).getTransactionId() == "jason");
}
{
TR _tr("Via 3");
const char* viaString = "SIP/2.0/UDP ;branch=z9hG4bKwkl3lkjsdfjklsdjklfdsjlkdklj ;ttl=70";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert (via.param(p_branch).hasMagicCookie());
assert (via.param(p_branch).getTransactionId() == "wkl3lkjsdfjklsdjklfdsjlkdklj");
assert (via.param(p_ttl) == 70);
}
{
TR _tr("Via 4");
const char* viaString = "SIP/2.0/UDP ;branch=oldassbranch";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert (!via.param(p_branch).hasMagicCookie());
assert (via.param(p_branch).getTransactionId() == "oldassbranch");
Data dsData;
DataStream s(dsData);
via.encode(s);
s.flush();
assert(dsData == "SIP/2.0/UDP ;branch=oldassbranch");
via.param(p_branch).reset("jason");
dsData.clear();
via.encode(s);
s.flush();
assert(dsData == "SIP/2.0/UDP ;branch=z9hG4bK" RESIP_COOKIE "1---jason");
assert(via.param(p_branch).getTransactionId() == "jason");
}
{
TR _tr("Via 5 assignment with unknown parameter");
const char* viaString = "SIP/2.0/UDP ;branch=z9hG4bKwkl3lkjsdfjklsdjklfdsjlkdklj ;ttl=70;stid=abcd.2";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert (via.param(p_branch).hasMagicCookie());
assert (via.param(p_branch).getTransactionId() == "wkl3lkjsdfjklsdjklfdsjlkdklj");
assert (via.param(p_ttl) == 70);
Via via1;
via1 = via;
resipCerr << "!! "; via1.encode(resipCerr); resipCerr << endl;
assert(via1.param(UnknownParameterType("stid")) == "abcd.2");
}
{
TR _tr("Via 6 parse with known parameter");
const char* viaString = "SIP/2.0/UDP whistler.gloo.net:5061;branch=z9hG4bK" RESIP_COOKIE "1---ec1e.0;ttl=4\r\n";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert (via.param(p_branch).hasMagicCookie());
assert (via.param(p_branch).getTransactionId() == "ec1e.0");
resipCerr << "!! "; via.encode(resipCerr); resipCerr << endl;
assert(via.param(p_ttl) == 4);
}
{
TR _tr("Via 7 parse with unknown parameter");
const char* viaString = "SIP/2.0/UDP whistler.gloo.net:5061;branch=z9hG4bK" RESIP_COOKIE "1---ec1e.0;stid=489573115\r\n";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert (via.param(p_branch).hasMagicCookie());
assert (via.param(p_branch).getTransactionId() == "ec1e.0");
resipCerr << "!! "; via.encode(resipCerr); resipCerr << endl;
assert(via.param(UnknownParameterType("stid")) == "489573115");
}
{
TR _tr("Branch parameter 1");
Data txt("=z9hG4bK" RESIP_COOKIE "1---jason");
ParseBuffer pb(txt.data(), txt.size());
BranchParameter bp(ParameterTypes::branch, pb, Data::toBitset(";"));
assert(bp.hasMagicCookie());
assert(bp.getTransactionId() == "jason");
bp.reset(bp.getTransactionId() + ".10");
bp.encode(resipCerr); resipCerr << endl;
assert(bp.getTransactionId() == "jason.10");
Data o;
{
DataStream s(o);
bp.encode(s);
}
resipCerr << "!! " << o << endl;
assert(o == "branch=z9hG4bK" RESIP_COOKIE "1---jason.10");
}
{
TR _tr("Branch parameter 2");
Data txt("=z9hG4bK" RESIP_COOKIE "14---jason.1.2.3");
ParseBuffer pb(txt.data(), txt.size());
BranchParameter bpc(ParameterTypes::branch, pb, Data::toBitset(";"));
assert(bpc.hasMagicCookie());
assert(bpc.getTransactionId() == "jason.1.2.3");
Data o;
{
DataStream s(o);
bpc.encode(s);
}
resipCerr << "!! " << o << endl;
assert(o == "branch=z9hG4bK" RESIP_COOKIE "14---jason.1.2.3");
}
{
TR _tr("Branch parameter 3");
Data txt("=z9hG4bK" RESIP_COOKIE "14---3e565-ef7w-17.1.2.3foobie");
ParseBuffer pb(txt.data(), txt.size());
BranchParameter bpcc(ParameterTypes::branch, pb, Data::toBitset(";"));
assert(bpcc.hasMagicCookie());
assert(bpcc.getTransactionId() == "3e565-ef7w-17.1.2.3foobie");
Data o;
{
DataStream s(o);
bpcc.encode(s);
}
resipCerr << "!! " << o << endl;
assert(o == "branch=z9hG4bK" RESIP_COOKIE "14---3e565-ef7w-17.1.2.3foobie");
bpcc.reset("foobie");
o.clear();
{
DataStream s(o);
bpcc.encode(s);
}
resipCerr << "!! " << o << endl;
assert(o == "branch=z9hG4bK" RESIP_COOKIE "1---foobie");
}
{
TR _tr("Branch parameter 4");
Data txt("=z9hG4bK" RESIP_COOKIE "14---3e565-ef7w-17.1.2.3");
ParseBuffer pb(txt.data(), txt.size());
BranchParameter bpcc(ParameterTypes::branch, pb, Data::toBitset(";"));
assert(bpcc.hasMagicCookie());
assert(bpcc.getTransactionId() == "3e565-ef7w-17.1.2.3");
Data o;
{
DataStream s(o);
bpcc.encode(s);
}
resipCerr << "!! " << o << endl;
assert(o == "branch=z9hG4bK" RESIP_COOKIE "14---3e565-ef7w-17.1.2.3");
}
{
TR _tr("Branch parameter 7 empty ours");
Data txt("=z9hG4bK" RESIP_COOKIE "1---");
ParseBuffer pb(txt.data(), txt.size());
BranchParameter bpcc(ParameterTypes::branch, pb, Data::toBitset(";"));
assert(bpcc.hasMagicCookie());
assert(bpcc.getTransactionId() == "");
Data o;
{
DataStream s(o);
bpcc.encode(s);
}
resipCerr << "!! " << o << endl;
assert(o == "branch=z9hG4bK" RESIP_COOKIE "1---");
}
{
TR _tr("Branch parameter 8 badly formed ours");
Data txt("=z9hG4bK" RESIP_COOKIE "------");
ParseBuffer pb(txt.data(), txt.size());
try
{
BranchParameter bpcc(ParameterTypes::branch, pb, Data::toBitset(";"));
assert(bpcc.hasMagicCookie());
bpcc.getTransactionId();
assert(false);
}
catch (ParseException &e)
{
}
}
{
TR _tr("Branch parameter 9");
Data txt("=z9hG4bK" RESIP_COOKIE "1-UEEzMjc2OA..--5b42cb698e8c6827790212ac5bdade1a;rport;received=64.124.66.32");
ParseBuffer pb(txt.data(), txt.size());
BranchParameter bp(ParameterTypes::branch, pb, Data::toBitset(";"));
assert(bp.hasMagicCookie());
assert(bp.getTransactionId() == "5b42cb698e8c6827790212ac5bdade1a");
resipCerr << "!! " << bp.clientData() << endl;
assert(bp.clientData() == "PA32768");
bp.encode(resipCerr); resipCerr << endl;
}
{
TR _tr("Branch parameter 10; magic cookie case mismatch");
Data txt("=z9hG4bk15775865934415"); //little k
ParseBuffer pb(txt.data(), txt.size());
BranchParameter bp(ParameterTypes::branch, pb, Data::toBitset(";"));
assert(bp.hasMagicCookie());
assert(bp.getTransactionId() == "15775865934415");
Data enc;
{
DataStream ds(enc);
bp.encode(ds);
}
cout << "!! " << enc << endl;
assert(enc == "branch=z9hG4bk15775865934415");
BranchParameter bpCopyCons(bp);
Data encCopyCons;
{
DataStream ds(encCopyCons);
bpCopyCons.encode(ds);
}
cout << "!! " << encCopyCons << endl;
assert(bp == bpCopyCons);
assert(encCopyCons == "branch=z9hG4bk15775865934415");
Data txt2("=z9hG4bk1577234fhg8df");
ParseBuffer pb2(txt2.data(), txt2.size());
BranchParameter bpAssignOp(ParameterTypes::branch, pb2, Data::toBitset(";"));
bpAssignOp = bp;
Data encAssignOp;
{
DataStream ds(encAssignOp);
bpAssignOp.encode(ds);
}
cout << "!! " << encAssignOp << endl;
assert(bp == bpAssignOp);
assert(encAssignOp == "branch=z9hG4bk15775865934415");
}
{
TR _tr("Branch testing 1");
const char* viaString = "SIP/2.0/UDP ;branch=z9hG4bKwkl3lkjsdfjklsdjklfdsjlkdklj ;ttl=70";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert (via.param(p_branch).hasMagicCookie());
assert (via.param(p_branch).getTransactionId() == "wkl3lkjsdfjklsdjklfdsjlkdklj");
assert (via.param(p_ttl) == 70);
assert (!via.exists(p_rport));
via.param(p_rport);
assert (via.exists(p_rport));
assert (via.exists(p_rport));
assert (!via.param(p_rport).hasValue());
}
{
TR _tr("Branch testing 2");
const char* viaString = "SIP/2.0/UDP ;branch=z9hG4bKwkl3lkjsdfjklsdjklfdsjlkdklj ;ttl=70;rport";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert (via.param(p_branch).hasMagicCookie());
assert (via.param(p_branch).getTransactionId() == "wkl3lkjsdfjklsdjklfdsjlkdklj");
assert (via.param(p_ttl) == 70);
assert (via.exists(p_rport));
assert (!via.param(p_rport).hasValue());
}
{
TR _tr("Branch testing 3");
const char* viaString = "SIP/2.0/UDP ;branch=z9hG4bKwkl3lkjsdfjklsdjklfdsjlkdklj ;ttl=70;rport=100";
HeaderFieldValue hfv(viaString, strlen(viaString));
Via via(hfv, Headers::UNKNOWN);
assert (via.param(p_branch).hasMagicCookie());
assert (via.param(p_branch).getTransactionId() == "wkl3lkjsdfjklsdjklfdsjlkdklj");
assert (via.param(p_ttl) == 70);
assert (via.exists(p_rport));
assert (via.param(p_rport).hasValue());
assert (via.param(p_rport).port() == 100);
}
{
TR _tr("Branch testing 4 with clientData");
Data txt("=z9hG4bK" RESIP_COOKIE "314-Q2xpZW50RGF0YQ..--T-i-D");
ParseBuffer pb(txt.data(), txt.size());
BranchParameter bpcc(ParameterTypes::branch, pb, Data::toBitset(";"));
assert (bpcc.getTransactionId() == "T-i-D");
assert (bpcc.clientData() == "ClientData");
Data o;
{
DataStream s(o);
bpcc.encode(s);
}
// resipCerr << "!! " << o << endl;
assert(o == "branch=z9hG4bK" RESIP_COOKIE "314-Q2xpZW50RGF0YQ..--T-i-D");
}
{
TR _tr("Branch testing 5 with sigcomp ID");
Data txt("=z9hG4bK" RESIP_COOKIE "314--PHVybjp1dWlkOmZhMzNjNzJkLTEyMWYtNDdlOC00MmUyLTFlYjZlMjRhYmE2ND4.-T-i-D");
ParseBuffer pb(txt.data(), txt.size());
BranchParameter bpcc(ParameterTypes::branch, pb, Data::toBitset(";"));
assert (bpcc.getTransactionId() == "T-i-D");
assert (bpcc.clientData() == "");
assert (bpcc.getSigcompCompartment() == "<urn:uuid:fa33c72d-121f-47e8-42e2-1eb6e24aba64>");
bpcc.setSigcompCompartment("<urn:uuid:fa33c72d-121f-47e8-42e2-1eb6e24aba64>");
Data o;
{
DataStream s(o);
bpcc.encode(s);
}
// resipCerr << "!! " << o << endl;
assert(o == "branch=z9hG4bK" RESIP_COOKIE "314--PHVybjp1dWlkOmZhMzNjNzJkLTEyMWYtNDdlOC00MmUyLTFlYjZlMjRhYmE2ND4.-T-i-D");
}
{
TR _tr("Branch testing 6 with sigcomp ID and Client Data");
Data txt("=z9hG4bK" RESIP_COOKIE "314-Q2xpZW50RGF0YQ..-PHVybjp1dWlkOmZhMzNjNzJkLTEyMWYtNDdlOC00MmUyLTFlYjZlMjRhYmE2ND4.-T-i-D");
ParseBuffer pb(txt.data(), txt.size());
BranchParameter bpcc(ParameterTypes::branch, pb, Data::toBitset(";"));
assert (bpcc.getTransactionId() == "T-i-D");
assert (bpcc.clientData() == "ClientData");
assert (bpcc.getSigcompCompartment() == "<urn:uuid:fa33c72d-121f-47e8-42e2-1eb6e24aba64>");
bpcc.setSigcompCompartment("<urn:uuid:fa33c72d-121f-47e8-42e2-1eb6e24aba64>");
Data o;
{
DataStream s(o);
bpcc.encode(s);
}
// resipCerr << "!! " << o << endl;
assert(o == "branch=z9hG4bK" RESIP_COOKIE "314-Q2xpZW50RGF0YQ..-PHVybjp1dWlkOmZhMzNjNzJkLTEyMWYtNDdlOC00MmUyLTFlYjZlMjRhYmE2ND4.-T-i-D");
}
//3329 tests
{
TR _tr( "Token + parameters parse test 3329 ");
const char *org = "digest;d-alg=md5";
HeaderFieldValue hfv(org, strlen(org));
Token tok(hfv, Headers::UNKNOWN);
assert(tok.value() == "digest");
assert(tok.param(p_dAlg) == "md5");
}
{
TR _tr( "Token + parameters parse test");
const char *org = "digest;d-qop=verify";
HeaderFieldValue hfv(org, strlen(org));
Token tok(hfv, Headers::UNKNOWN);
assert(tok.value() == "digest");
assert(tok.param(p_dQop) == "verify");
}
{
TR _tr( "Token + parameters parse test");
const char *org = "digest;d-ver=\"0000000000000000000000000000abcd\"";
HeaderFieldValue hfv(org, strlen(org));
Token tok(hfv, Headers::UNKNOWN);
assert(tok.value() == "digest");
assert(tok.param(p_dVer) == "0000000000000000000000000000abcd");
}
{
TR _tr( "Test CSeqCategory 1");
Data cseqString("1 INVITE");
HeaderFieldValue hfv(cseqString.data(), cseqString.size());
CSeqCategory str(hfv, Headers::UNKNOWN);
assert(str.sequence() == 1);
assert(str.method() == INVITE);
assert(Data::from(str) == cseqString);
}
{
TR _tr( "Test CSeqCategory 2");
Data cseqString("4294967295 INVITE");
HeaderFieldValue hfv(cseqString.data(), cseqString.size());
CSeqCategory str(hfv, Headers::UNKNOWN);
assert(str.sequence() == 4294967295U);
assert(str.method() == INVITE);
assert(Data::from(str) == cseqString);
}
{
TR _tr( "Test RAckCategory 1");
Data rackString("1 2 INVITE");
HeaderFieldValue hfv(rackString.data(), rackString.size());
RAckCategory str(hfv, Headers::UNKNOWN);
assert(str.rSequence() == 1);
assert(str.cSequence() == 2);
assert(str.method() == INVITE);
assert(Data::from(str) == rackString);
}
{
TR _tr( "Test RAckCategory 2");
Data rackString("4294967294 4294967295 INVITE");
HeaderFieldValue hfv(rackString.data(), rackString.size());
RAckCategory str(hfv, Headers::UNKNOWN);
assert(str.rSequence() == 4294967294U);
assert(str.cSequence() == 4294967295U);
assert(str.method() == INVITE);
assert(Data::from(str) == rackString);
}
{
TR _tr( "Test Privacy Category 1");
Data privacy("user;session;critical");
HeaderFieldValue hfv(privacy.data(), privacy.size());
PrivacyCategory test(hfv, Headers::UNKNOWN);
assert(test.value().size()==3);
assert(test.value().back()=="critical");
test.value().pop_back();
assert(test.value().back()=="session");
test.value().pop_back();
assert(test.value().back()=="user");
test.value().pop_back();
}
{
TR _tr( "Test Privacy Category 2");
Data privacy("user; session; critical ");
HeaderFieldValue hfv(privacy.data(), privacy.size());
PrivacyCategory test(hfv, Headers::UNKNOWN);
assert(test.value().size()==3);
assert(test.value().back()=="critical");
test.value().pop_back();
assert(test.value().back()=="session");
test.value().pop_back();
assert(test.value().back()=="user");
test.value().pop_back();
}
{
TR _tr( "Test Privacy Category 3");
Data privacy("user");
HeaderFieldValue hfv(privacy.data(), privacy.size());
PrivacyCategory test(hfv, Headers::UNKNOWN);
assert(test.value().size()==1);
assert(test.value().back()=="user");
test.value().pop_back();
}
// Performance tests
{
resip::Data test("Raw header-field-value creation/deletion");
cout << endl << test << endl;
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
HeaderFieldValue hfv(test.data(), test.size());
// (hfv, Headers::UNKNOWN);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
// Auth
{
resip::Data test("Auth creation/deletion");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
Auth auth(hfv, Headers::UNKNOWN);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("Digest nonce=\"1305231689:fed475e952ee1d3ecaf60b17bce12218\",algorithm=MD5,realm=\"localhost\",qop=\"auth,auth-int\"");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
Auth auth(hfv, Headers::UNKNOWN);
auth.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
Auth pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("Digest username=\"derek\",realm=\"localhost\",nonce=\"1305231689:fed475e952ee1d3ecaf60b17bce12218\",uri=\"sip:jason@localhost\",response=\"88f519f04c2a09c500af88ff7bccdf52\",cnonce=\"foo\",nc=0000005D,qop=auth-int,algorithm=MD5");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
Auth auth(hfv, Headers::UNKNOWN);
auth.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
Auth pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
// CSeq
{
resip::Data test("CSeq creation/deletion");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
CSeqCategory cseq(hfv, Headers::UNKNOWN);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("9872643 INVITE");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
CSeqCategory cseq(hfv, Headers::UNKNOWN);
cseq.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
CSeqCategory pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("1 INVITE");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
CSeqCategory cseq(hfv, Headers::UNKNOWN);
cseq.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
CSeqCategory pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
// CallId
{
resip::Data test("CallId creation/deletion");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
CallId callid(hfv, Headers::UNKNOWN);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("NOIUYCEOGoIUBaocuwyVCopiuVAbcs");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
CallId callid(hfv, Headers::UNKNOWN);
callid.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
CallId pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
// Date
{
resip::Data test("Date creation/deletion");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
DateCategory date(hfv, Headers::UNKNOWN);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("Thu, 21 Feb 2002 13:02:03 GMT");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
DateCategory date(hfv, Headers::UNKNOWN);
date.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
DateCategory pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
// Expires
{
resip::Data test("Expires creation/deletion");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
ExpiresCategory pc(hfv, Headers::UNKNOWN);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("3600");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
ExpiresCategory pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
ExpiresCategory pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
// Mime
{
resip::Data test("Mime creation/deletion");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
Mime pc(hfv, Headers::UNKNOWN);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("application/rlmi+xml");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
Mime pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
Mime pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("application/sdp");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
Mime pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
Mime pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
// NameAddr
{
resip::Data test("NameAddr creation/deletion");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
NameAddr pc(hfv, Headers::UNKNOWN);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("<sip:rls.example.com>");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("<sip:rls.example.com;lr>");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("<sipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsipsip:rls.example.com;lr>");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data strangeUser("работающий");
strangeUser=strangeUser.charEncoded();
resip::Data test("<sip:" + strangeUser+ "@example.com;lr>");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test(" \"Derek\" <sip:derek@localhost>;tag=16d1246e");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("<sip:line1@192.0.2.2;transport=tcp>; reg-id=1;+sip.instance=\"<urn:uuid:00000000-0000-1000-8000-000A95A0E128>\"");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("<sip:line1@192.0.2.2:5060;transport=tcp>; reg-id=1;+sip.instance=\"<urn:uuid:00000000-0000-1000-8000-000A95A0E128>\"");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
NameAddr pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
// RequestLine
{
resip::Data test("RequestLine creation/deletion");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
RequestLine pc(hfv);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("INVITE sip:bob@example.com SIP/2.0");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
RequestLine pc(hfv);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
RequestLine pc(hfv);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("UNKNOWN sip:bob@example.com SIP/2.0");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
RequestLine pc(hfv);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
RequestLine pc(hfv);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
// StatusLine
{
resip::Data test("StatusLine creation/deletion");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
StatusLine pc(hfv);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("SIP/2.0 200 OK");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
StatusLine pc(hfv);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
StatusLine pc(hfv);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("SIP/2.0 200 OKokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokok");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
StatusLine pc(hfv);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
StatusLine pc(hfv);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("NOTSIP/2.0 200 OK");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
StatusLine pc(hfv);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
StatusLine pc(hfv);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
// Via
{
resip::Data test("Via creation/deletion");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
Via pc(hfv, Headers::UNKNOWN);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("SIP/2.0/TCP 127.0.0.1:5060;branch=z9hG4bK-524287-1---307cd5596615cb2e;rport");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
Via pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
Via pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
Token pc(hfv, Headers::UNKNOWN);
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
{
resip::Data test("");
cout << endl << test << endl;
HeaderFieldValue hfv(test.data(), test.size());
UInt64 now(Timer::getTimeMicroSec());
for(int i=0; i<10000000; ++i)
{
Token pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
cout << "encodes:" << endl;
Token pc(hfv, Headers::UNKNOWN);
pc.checkParsed();
Data buffer;
oDataStream str(buffer);
now=Timer::getTimeMicroSec();
for(int i=0; i<10000000; ++i)
{
pc.encode(str);
str.flush();
str.reset();
}
cout << Timer::getTimeMicroSec() - now << " microseconds" << endl;
}
resipCerr << "\nTEST OK" << endl;
return 0;
}
1.7.5.1