/[resiprocate]/main/resip/stack/test/RFC4475TortureTests.cxx
ViewVC logotype

Annotation of /main/resip/stack/test/RFC4475TortureTests.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9367 - (hide annotations) (download)
Wed Feb 1 16:12:20 2012 UTC (7 years, 10 months ago) by sgodin
File size: 194120 byte(s)
-merge work from resip-b-TKLC-perf_work branch

Merge Notes:

Various optimizations of Data
=============================

Made Data smaller, without sacrificing functionality. Data is 20 (56 vs 36) 
bytes smaller on 64-bit libs, and 4 (36 vs 32) bytes smaller on 32-bit libs. 
This was accomplished by making mSize, mCapacity, and mShareEnum 4-bytes on 
64-bit platforms (mShareEnum could be one byte, but it turns out this imposes a 
detectable performance penalty), and by having mShareEnum do double-duty as a 
null-terminator for mPreBuffer (Borrow==0), instead of requiring an extra byte 
at the end of mPreBuffer.

Several very simple functions have been inlined.

Functionality enhancements to a couple of functions:

- Data::md5() has been changed to Data::md5(Data::EncodingType type=HEX); this 
allows the output of md5() to be encoded as hex or Base64, or not encoded at all 
(binary).

- Data::replace(const Data& match, const Data& target) has been updated to 
Data::replace(const Data& match, const Data& target, int max=INT_MAX); this 
allows the maximum number of replacements to be specified.

Lastly, a few specialized hashing and comparison functions have been added:

- Data::caseInsensitiveTokenHash(); this is a case-insensitive hash that assumes 
that the Data is an RFC 3261 token (eg; branch params). This character set has 
the property that no character is equal to any other character when bit 6 is 
masked out, except for the alphabetical characters. (For alphabetical 
characters, bit 6 specifies whether the character is upper/lower case) This 
means that we can mask out bit 6, and then use a case-sensitive hash algorithm 
on the resulting characters, without hurting the collision properties of the 
hash, and get a case-insensitive hash as a result. This hash function is based 
on the Hsieh hash.

- bool Data::caseInsensitiveTokenCompare(const Data& rhs); this is an equality 
comparison that assumes that both Datas are RFC 3261 tokens (eg; branch 
parameters). This function takes advantage of the same properties of the RFC 
3261 token character set as caseInsensitiveTokenHash(), by using a bitmask 
instead of a true lowercase() operation. This ends up being faster than 
strncasecmp().

- Data& schemeLowercase(); this is a variant of lowercase() that assumes the 
Data is an RFC 3261 scheme. This character set has the property that setting bit 
6 is a no-op, except for alphabetical characters (0-9, '+', '-', and '.' all 
already have bit 6 set). Setting bit 6 on a alphabetical character is equivalent 
to lower-casing the character. Note: There is no corresponding schemeUppercase() 
function, because clearing bit 6 will convert 0-9, '+', '-', and '.' into 
unprintable characters (well, '-' is turned into a CR, but you get the point).



Performance improvements to ParseBuffer
=======================================

- Most functions that returned a Pointer now return a much more lightweight
   CurrentPosition object.
- Allow some of the simpler functions to be inlined
- Integer parsing code is more efficient, and overflow detection is better


Performance enhancements to DnsUtil
===================================

- DnsUtil::inet_ntop(): For some reason, the stock system inet_ntop 
  is dreadfully inefficient on OS X. A dirt-simple hand-rolled 
  implementation was 5-6 times as fast. This is shocking. The Linux 
  implementation is plenty efficient, though, so we're using 
  preprocessor to activate the hand-rolled code.

- DnsUtil::isIpV4Address(): The implementation uses 
  sscanf(), which is pretty expensive. Hand-rolled some code that 
  is much faster.


Reduced the memory footprint associated with storing URIs
=========================================================
- Removed the AOR cacheing stuff from Uri; it was horrifically inefficient. Checking
  for staleness of the cache was nearly as expensive as regenerating the AOR from 
  scratch. Not to mention that the AOR cacheing stuff took up a whopping 148 bytes
  of space on 64-bit platforms (4 Datas, and an int).

- Reworked the host canonicalization cache to take up less space, and be faster.
  Previously, the canonicalized host was put in a separate Data. We now canonicalize
  in-place, and use a bool to denote whether canonicalization has been performed yet.
  This saves us 32 bytes.

- Changed Data Uri::mEmbeddedHeadersText to an auto_ptr<>, since in most cases Uris don't
  use it. Also use auto_ptr for mEmbeddedHeaders (was already a pointer, for consistency).


Change how branch parameters are encoded.
=========================================

Old format: z9hG4bK-d8754z-<branch>-<transportseq>-<clientData>-<sigcompCompartment>-d8754z-

New Format: z9hG4bK-524287-<transportseq>-<clientData>-<sigcompComprtment>-<branch>

This format encodes faster, parses faster (with _much_ simpler code), and takes up
less space on the wire. We may decide to tweak the new resip cookie; I chose 
something that we can use memcmp instead of strncasecmp with, but the token character
set has a bunch of characters that aren't alphanumeric we could use.

Also, some other small optimizations; avoid copies associated with calling
Data::base64encode()/base64decode() on empty Datas, and reorder the SIP cookie
comparisons to be more efficient.


State shedding modifications to TransactionState
================================================
In a number of cases, we were preserving state (in the form of SipMessages
and DnsResults) in cases where we did not really need them any more. For
example, once we have transmitted a response, there is no need
to preserve the full SipMessage for this response (the raw retransmit buffer
is sufficient). Also, INVITE requests do not need to be maintained once
a final response comes in (since there is no possibility that we'll need to
send a simulated 408 or 503 to the TU, nor will we need to construct a CANCEL
request using the INVITE, nor will we need to retransmit). Similarly, once we
have received a final response for a NIT transaction, we no longer need to
maintain the original request or the retransmit buffer. Lastly, if we are
using a reliable transport, we do not need to maintain retransmit buffers
(although we may need to maintain full original requests for simulated
responses and such).

This change has basically no impact on reliable NIT performance, but a huge
impact on non-reliable and INVITE performance. Prior to this change, either
NIT UDP or INVITE TCP testStack would exhaust main memory on my laptop (with
4GB of main memory), bringing progress to a complete halt on runs longer than
15 seconds or so. I did not bother trying INVITE UDP, but that works now too.


Reduction in buffer reallocations while encoding a SipMessage
=============================================================
TransportSelector now keeps a moving average of the outgoing message size,
which is used to preallocate the buffers into which SipMessages are encoded.

This ends up making a small difference in testStack when linked against google
malloc, but a larger difference when linked against OS X's (horrible) standard
malloc.


Multiple Threads in the Stack
=============================
Allow transaction processing, transport processing, and DNS processing to be 
broken off into separate threads.

- SipStack::run() causes the creation and run of three threads; a 
TransactionControllerThread, and TransportSelectorThread, and a DnsThread. You 
continue to use stuff like StackThread and EventStackThread to give cycles to 
the rest of the stack (mainly processing app timers and statistics logging); the 
SipStack is smart enough to unhook these three things from the normal event loop 
API when they have their own threads. In other words, to use the new 
multi-threaded mode, all you have to do is throw in a call to SipStack::run() 
before you fire up your normal SipStack processing, and a 
SipStack::shutdownAndJoinThreads() when you're done.

- In the Connection read/write code, process reads/writes until EAGAIN, or we 
run out of stuff to send. Gives a healthy performance boost on connection-based 
transports.

- In TransactionController, put transaction timers in their own fifo. This 
prevents timers from firing late when the state machine fifo gets congested. 
Also, process at most 16 TransactionMessages from the state machine fifo at a 
time, to prevent starving other parts of the system.

- Unhook the TransactionController's processing loop from that of the 
TransportSelector. This simplifies this API considerably, but required the 
addition of a new feature to Fifo. Fifo can now take an (optional) 
AsyncProcessHandler* that will be notified when the fifo goes from empty to 
non-empty. Actually pretty useful.

- Allow setPollGrp() to be called multiple times on the various classes that 
have this function. This allows the FdPollGrp to be re-set when the SipStack 
enters multithreaded mode.

- Added a "multithreadedstack" --thread-type option to testStack. Exercise this 
option in testStackStd.sh

- Added the ability to run any of the existing Transport objects in their own 
thread, by a combination of a new transport flag 
(RESIP_TRANSPORT_FLAG_OWNTHREAD), and a new TransportThread class. Added support 
for this mode to testStack using the --tf option. Also exercised this feature in 
testStackStd.sh.

- Installed SelectInterruptors at the TransportSelector, each Transport object, 
and the DnsStub (this last one required moving SelectInterruptor to rutil). This 
is critical to making multithreaded mode work in a performant manner, and 
imposes almost no performance penalty due to the way they are invoked.

- SipStack now creates its own SelectInterruptor if one is not supplied 
externally. This is because it is critical to be able to wake the 
TransactionController up when new work comes down from the TU, or from the 
transports.


New congestion-management framework
===================================
Notable features include:
* Allow testStack, tfm/repro/sanityTests, and repro to be run with a congestion 
   manager with the --use-congestion-manager flag.

* Efficient wait-time estimation in AbstractFifo; keeps track of how rapidly
   messages are consumed, allowing good estimates of how long a new message will
   take to be serviced. More efficient than the time-depth logic in 
   TimeLimitFifo, and a better predictor too.

* The ability to shed load at the transport level when the TransactionController
   is congested, in a very efficient manner, using new functionality in Helper
   and SipMessage (Helper::makeRawResponse() and 
   SipMessage::encodeSingleHeader())

* The ability to shed load coming from the TU when the TransactionController is 
   congested. This is crucial when congestion is being caused by a TU trying to 
   do too much.

* Changed the way load-shedding is handled for TransactionUsers to use the new
   API

* A flexible congestion-management API, allowing load-shedding decisions to be
   made in an arbitrary fashion.

* A generalized CongestionManager implementation that is powerful enough to be
   useful.

* The TransactionController will now defer retransmissions of requests if 
   sufficiently congested (ie; the response is probably stuck in mStateMacFifo)

* The TransactionController now determines its hostname with a single call to 
   DnsUtil::getLocalHostName() on construction, for use in 503s. Previously, it 
   would make this call every time a 503 was sent; this call blocks sometimes!

* Don't call DnsResult::blacklistLast() on a Retry-After: 0

* Several fixes the the processing loop in testStack that were causing 
   starvation of one type of work or another when congestion occurred.


Other Misc Enhancements
=======================
-Small efficiency improvement in Random::getCryptoRandom(int)
 Random::getCryptoRandom(unsigned int len) was implemented by calling 
 Random::getCryptoRandom() repeatedly, and collecting the return values 
 in a buffer. In the openssl case, we now use a single call to RAND_bytes().
-Use a priority_queue instead of a multiset for storing timers.
-Slight refactoring of Timer so that transaction timers and payload timers (ie; 
 timers that carry a Message*) are separate classes. Transaction timers no longer 
 have an unused Message* member, and payload timers no longer have the unused 
 transaction-id, Timer::Type, and duration. This saves a _lot_ of memory for apps 
 that use lots of app timers with long lifetimes.
-Less wasteful population of Call-IDs: 
 When generating Call-IDs, Helper was computing an md5 hash of the hostname and 
 some salt, hex-encoding it, and then Base64 encoding the hex data. We now Base64 
 encode the md5 hash directly. This is less computationally expensive, requires 
 less memory because the resulting string is half the size, and requires fewer 
 bytes on the wire.
-Make TransactionMap case-insensitive; Data::caseInsensitiveTokenHash() is fast
 enough that performance actually increases a little.
-std::bitset-based parsing in a number of places.
-Don't check whether the encoding tables are initted for every single
 character; check once before the encode operation begins. Also, checking
 the value of a static bool to determine whether an init has been carried
 out is pointless; that bool might not be initted yet, and it could have
 any value. The static init code now copes with both accesses to the encoding
 tables during static initialization, and from multiple threads during runtime.
-Don't bother generating a transaction identifier unless the parse fails
 to extract one.
-Some refactoring of the FdPollGrp stuff. Now is compatible with cares, using
 a bit of a hack. Also compatible with being driven with the old buildFdSet()/
 select()/process(FdSet&) call sequence, although this is now deprecated.
 Fixing these compatibility problems allowed us to switch over to using FdPollGrp
 in all cases, instead of having dual mode everywhere.
-Buffer classes for Fifo to reduce lock contention. Using them in a few places, will
 use them in more once we phase out TimeLimitFifo with the new congestion management
 code.
-Use the --ignore-case option for generation of ParameterHash.cxx, instead of the
 nasty sed rewriting we are using now. Should also be slightly faster, since gperf
 handles case-insensitive hashing more efficiently than our hack was.
-Adding a local memory pool to SipMessage, to cut down (dramatically) on
 heap allocation overhead. Some minor refactoring to free up wasted space
 in SipMessage as well (makes more room for the pool). Changing the way
 the start-line is stored to no longer use a full-blown ParserContainer+
 HeaderFieldValueList. Lots of opportunistic doxygen merging.
 Up to 20K NIT transactions per second on my machine, roughly a doubling
 in performance.


Bug Fixes
=========
-Use getaddrinfo() instead of the non-threadsafe gethostbyname().
-Remove unused (and non-threadsafe) Timer::mTimerCount/Timer::mId.
 Previously, all timers were assigned a "unique" (not really, more on that in a 
 moment) integer identifier. There is no place in the resip codebase that 
 actually uses this identifier in any way. For transaction timers, this 
 identifier is in principle unnecessary, since there is more than sufficient 
 identifier information present already (the transaction id and timer type). When 
 passing a Message* into the timer queue, a unique identifier already exists; the 
 Message* itself (if potential use of this Message* bugs you, you can always turn 
 it into a handle by applying some sort of transformation to it). This identifier 
 is unnecessary in every case I can think of. In addition, the values are 
 assigned simply by incrementing a global variable (Timer::mTimerCount), with no 
 threadsafety measures whatsoever, so it is not even guaranteed to be unique. 
 Because of all this, it has been removed. As a bonus, this saves some memory; 8 
 bytes per timer on 64-bit platforms, which adds up to around 3MB when testStack 
 steady state has close to 400000 timers in the timer queues at any given point. 
 This could be an even larger amount for TUs that schedule lots of long-lifetime 
 timers (Timer C, for instance).
-Get rid of a wasteful double-encode, in Message.cxx
-minor windows build fixes to avoid file in use errors when building dum test projects
-fix testDigestAuthentiation for recent lowercase nonce change
-fixed a nasty bug in NameAddr - where unknown parameters uri parameters on a 
 NameAddr/Uri with no angle brackets are treated as NameAddr parameters.  When this is
 done, the memory for these parameters was only a temporary Data object.
-fix bug in Data.  If Data is wrapping memory allocated externally (ie. Share mode = BORROW)
 and you start appending to it.  It is possible that the append method will write a NULL
 character off the end of the buffer.  Changed the resize condition to make the buffer
 larger 1 character sooner, to accommodate for this.
1 bcampen 6448 #include <iostream>
2     #include <memory>
3    
4     #include "resip/stack/Contents.hxx"
5     #include "resip/stack/SdpContents.hxx"
6     #include "resip/stack/SipMessage.hxx"
7     #include "resip/stack/ExtensionHeader.hxx"
8 bcampen 6512 #include "resip/stack/ExtensionParameter.hxx"
9     #include "resip/stack/ParserCategories.hxx"
10     #include "resip/stack/ParameterTypes.hxx"
11 bcampen 6448 #include "resip/stack/Uri.hxx"
12     #include "rutil/Logger.hxx"
13     #include "tassert.h"
14    
15     #define RESIPROCATE_SUBSYSTEM resip::Subsystem::TEST
16    
17     void
18 bcampen 6512 wsinv()
19     {
20     /*
21     This short, relatively human-readable message contains:
22    
23     o line folding all over.
24    
25     o escaped characters within quotes.
26    
27     o an empty subject.
28    
29     o LWS between colons, semicolons, header field values, and other
30     fields.
31    
32     o both comma separated and separately listed header field values.
33    
34     o a mix of short and long form for the same header field name.
35    
36     o unknown Request-URI parameter.
37    
38     o unknown header fields.
39    
40     o an unknown header field with a value that would be syntactically
41     invalid if it were defined in terms of generic-param.
42    
43     o unusual header field ordering.
44    
45     o unusual header field name character case.
46    
47     o unknown parameters of a known header field.
48    
49     o a uri parameter with no value.
50    
51     o a header parameter with no value.
52    
53     o integer fields (Max-Forwards and CSeq) with leading zeros.
54    
55     All elements should treat this as a well-formed request.
56    
57     The UnknownHeaderWithUnusualValue header field deserves special
58     attention. If this header field were defined in terms of comma-
59     separated values with semicolon-separated parameters (as would many
60     of the existing defined header fields), this would be invalid.
61     However, since the receiving element does not know the definition of
62     the syntax for this field, it must parse it as a header value.
63     Proxies would forward this header field unchanged. Endpoints would
64     ignore the header field.
65    
66     INVITE sip:vivekg@chair-dnrc.example.com;unknownparam SIP/2.0
67     TO :
68     sip:vivekg@chair-dnrc.example.com ; tag = 1918181833n
69     from : "J Rosenberg \\\"" <sip:jdrosen@example.com>
70     ;
71     tag = 98asjd8
72     MaX-fOrWaRdS: 0068
73     Call-ID: wsinv.ndaksdj@192.0.2.1
74     Content-Length : 150
75     cseq: 0009
76     INVITE
77     Via : SIP / 2.0
78     /UDP
79     192.0.2.2;branch=390skdjuw
80     s :
81     NewFangledHeader: newfangled value
82     continued newfangled value
83     UnknownHeaderWithUnusualValue: ;;,,;;,;
84     Content-Type: application/sdp
85     Route:
86     <sip:services.example.com;lr;unknownwith=value;unknown-no-value>
87     v: SIP / 2.0 / TCP spindle.example.com ;
88     branch = z9hG4bK9ikj8 ,
89     SIP / 2.0 / UDP 192.168.255.111 ; branch=
90     z9hG4bK30239
91     m:"Quoted string \"\"" <sip:jdrosen@example.com> ; newparam =
92     newvalue ;
93     secondparam ; q = 0.33
94    
95     v=0
96     o=mhandley 29739 7272939 IN IP4 192.0.2.3
97     s=-
98     c=IN IP4 192.0.2.4
99     t=0 0
100     m=audio 49217 RTP/AVP 0 12
101     m=video 3227 RTP/AVP 31
102     a=rtpmap:31 LPC
103    
104     */
105     FILE* fid= fopen("wsinv.dat","r");
106     tassert(fid);
107     resip::Data txt;
108     char mBuf[1024];
109     int result;
110     while(!feof(fid))
111     {
112     result = fread(&mBuf,1,1024,fid);
113     txt += resip::Data(mBuf,result);
114     }
115     fclose(fid);
116     resip::SipMessage* msg = resip::SipMessage::make(txt);
117     tassert_reset();
118     tassert(msg);
119     tassert_reset();
120     if(!msg)
121     {
122     return;
123     }
124    
125     std::auto_ptr<resip::SipMessage> message(msg);
126     msg->parseAllHeaders();
127    
128     resip::SipMessage copy(*msg);
129    
130     resip::Data encoded;
131     {
132     resip::oDataStream str(encoded);
133     msg->encode(str);
134     }
135     resip::Data copyEncoded;
136     {
137     resip::oDataStream str(copyEncoded);
138     copy.encode(str);
139     }
140    
141     // Request Line
142     tassert(msg->header(resip::h_RequestLine).method()==resip::INVITE);
143 bcampen 6524 tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="INVITE");
144 bcampen 6512 tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
145     tassert(msg->header(resip::h_RequestLine).uri().user()=="vivekg");
146     tassert(msg->header(resip::h_RequestLine).uri().host()=="chair-dnrc.example.com");
147     tassert(msg->header(resip::h_RequestLine).uri().port()==0);
148     tassert(msg->header(resip::h_RequestLine).uri().password().empty());
149     tassert(!(msg->header(resip::h_RequestLine).uri().hasEmbedded()));
150     tassert(msg->header(resip::h_RequestLine).uri().numKnownParams()==0);
151     tassert(msg->header(resip::h_RequestLine).uri().numUnknownParams()==1);
152     resip::ExtensionParameter p_unknownparam("unknownparam");
153     tassert(msg->header(resip::h_RequestLine).uri().exists(p_unknownparam));
154     tassert(msg->header(resip::h_RequestLine).getSipVersion()=="SIP/2.0");
155    
156     //To
157     tassert(msg->exists(resip::h_To));
158     tassert(msg->header(resip::h_To).displayName().empty());
159     tassert(msg->header(resip::h_To).numKnownParams()==1);
160     tassert(msg->header(resip::h_To).numUnknownParams()==0);
161     tassert(msg->header(resip::h_To).exists(resip::p_tag));
162     tassert(msg->header(resip::h_To).param(resip::p_tag)=="1918181833n");
163     tassert(!(msg->header(resip::h_To).isAllContacts()));
164     tassert(msg->header(resip::h_To).uri().scheme()=="sip");
165     tassert(msg->header(resip::h_To).uri().user()=="vivekg");
166     tassert(msg->header(resip::h_To).uri().host()=="chair-dnrc.example.com");
167     tassert(msg->header(resip::h_To).uri().port()==0);
168     tassert(msg->header(resip::h_To).uri().password().empty());
169     tassert(!(msg->header(resip::h_To).uri().hasEmbedded()));
170     tassert(msg->header(resip::h_To).uri().numKnownParams()==0);
171     tassert(msg->header(resip::h_To).uri().numUnknownParams()==0);
172    
173     //From
174     tassert(msg->exists(resip::h_From));
175     tassert(msg->header(resip::h_From).displayName()=="J Rosenberg \\\\\\\"");
176     tassert(msg->header(resip::h_From).numKnownParams()==1);
177     tassert(msg->header(resip::h_From).numUnknownParams()==0);
178     tassert(msg->header(resip::h_From).exists(resip::p_tag));
179     tassert(msg->header(resip::h_From).param(resip::p_tag)=="98asjd8");
180     tassert(!(msg->header(resip::h_From).isAllContacts()));
181     tassert(msg->header(resip::h_From).uri().scheme()=="sip");
182     tassert(msg->header(resip::h_From).uri().user()=="jdrosen");
183     tassert(msg->header(resip::h_From).uri().host()=="example.com");
184     tassert(msg->header(resip::h_From).uri().port()==0);
185     tassert(msg->header(resip::h_From).uri().password().empty());
186     tassert(!(msg->header(resip::h_From).uri().hasEmbedded()));
187     tassert(msg->header(resip::h_From).uri().numKnownParams()==0);
188     tassert(msg->header(resip::h_From).uri().numUnknownParams()==0);
189    
190     //Max-Forwards
191     tassert(msg->exists(resip::h_MaxForwards));
192     tassert(msg->header(resip::h_MaxForwards).value()==68);
193     tassert(msg->header(resip::h_MaxForwards).numKnownParams()==0);
194     tassert(msg->header(resip::h_MaxForwards).numUnknownParams()==0);
195    
196    
197     //Call-ID
198     tassert(msg->exists(resip::h_CallID));
199     tassert(msg->header(resip::h_CallID).value()=="wsinv.ndaksdj@192.0.2.1");
200     tassert(msg->header(resip::h_CallID).numKnownParams()==0);
201     tassert(msg->header(resip::h_CallID).numUnknownParams()==0);
202    
203     //Content-Length
204     tassert(msg->exists(resip::h_ContentLength));
205     tassert(msg->header(resip::h_ContentLength).value()==150);
206     tassert(msg->header(resip::h_ContentLength).numKnownParams()==0);
207     tassert(msg->header(resip::h_ContentLength).numUnknownParams()==0);
208    
209     //CSeq
210     tassert(msg->exists(resip::h_CSeq));
211     tassert(msg->header(resip::h_CSeq).method()==resip::INVITE);
212 bcampen 6524 tassert(msg->header(resip::h_CSeq).unknownMethodName()=="INVITE");
213 bcampen 6512 tassert(msg->header(resip::h_CSeq).sequence()==9);
214     tassert(msg->header(resip::h_CSeq).numKnownParams()==0);
215     tassert(msg->header(resip::h_CSeq).numUnknownParams()==0);
216    
217     //Vias
218     tassert(msg->exists(resip::h_Vias));
219     tassert(msg->header(resip::h_Vias).size()==3);
220     resip::ParserContainer<resip::Via>::iterator i=msg->header(resip::h_Vias).begin();
221    
222     tassert(i->numKnownParams()==1);
223     tassert(i->numUnknownParams()==0);
224     tassert(i->protocolName()=="SIP");
225     tassert(i->protocolVersion()=="2.0");
226     tassert(i->transport()=="UDP");
227     tassert(i->sentHost()=="192.0.2.2");
228     tassert(i->sentPort()==0);
229    
230     tassert(i->exists(resip::p_branch));
231     tassert(!(i->param(resip::p_branch).hasMagicCookie()));
232     tassert(i->param(resip::p_branch).getTransactionId()=="390skdjuw");
233     tassert(i->param(resip::p_branch).clientData().empty());
234    
235     i++;
236    
237     tassert(i->numKnownParams()==1);
238     tassert(i->numUnknownParams()==0);
239     tassert(i->protocolName()=="SIP");
240     tassert(i->protocolVersion()=="2.0");
241     tassert(i->transport()=="TCP");
242     tassert(i->sentHost()=="spindle.example.com");
243     tassert(i->sentPort()==0);
244    
245     tassert(i->exists(resip::p_branch));
246     tassert(i->param(resip::p_branch).hasMagicCookie());
247     tassert(i->param(resip::p_branch).getTransactionId()=="9ikj8");
248     tassert(i->param(resip::p_branch).clientData().empty());
249    
250     i++;
251    
252     tassert(i->numKnownParams()==1);
253     tassert(i->numUnknownParams()==0);
254     tassert(i->protocolName()=="SIP");
255     tassert(i->protocolVersion()=="2.0");
256     tassert(i->transport()=="UDP");
257     tassert(i->sentHost()=="192.168.255.111");
258     tassert(i->sentPort()==0);
259    
260     tassert(i->exists(resip::p_branch));
261     tassert(i->param(resip::p_branch).hasMagicCookie());
262     tassert(i->param(resip::p_branch).getTransactionId()=="30239");
263     tassert(i->param(resip::p_branch).clientData().empty());
264    
265    
266     //Subject
267     tassert(msg->exists(resip::h_Subject));
268     tassert(msg->header(resip::h_Subject).value()=="");
269     tassert(msg->header(resip::h_Subject).numKnownParams()==0);
270     tassert(msg->header(resip::h_Subject).numUnknownParams()==0);
271    
272    
273     // Unknown headers
274     resip::ExtensionHeader h_NewFangledHeader("NewFangledHeader");
275    
276     tassert(msg->exists(h_NewFangledHeader));
277     tassert(msg->header(h_NewFangledHeader).size()==1);
278     tassert(msg->header(h_NewFangledHeader).begin()->value()=="newfangled value\r\n continued newfangled value");
279     tassert(msg->header(h_NewFangledHeader).begin()->numKnownParams()==0);
280     tassert(msg->header(h_NewFangledHeader).begin()->numUnknownParams()==0);
281    
282     resip::ExtensionHeader h_UnknownHeaderWithUnusualValue("UnknownHeaderWithUnusualValue");
283    
284     tassert(msg->exists(h_UnknownHeaderWithUnusualValue));
285     tassert(msg->header(h_UnknownHeaderWithUnusualValue).size()==1);
286     tassert(msg->header(h_UnknownHeaderWithUnusualValue).begin()->value()==";;,,;;,;");
287     tassert(msg->header(h_UnknownHeaderWithUnusualValue).begin()->numKnownParams()==0);
288     tassert(msg->header(h_UnknownHeaderWithUnusualValue).begin()->numUnknownParams()==0);
289    
290     //Content-Type
291     tassert(msg->exists(resip::h_ContentType));
292     tassert(msg->header(resip::h_ContentType).type()=="application");
293     tassert(msg->header(resip::h_ContentType).subType()=="sdp");
294     tassert(msg->header(resip::h_ContentType).numKnownParams()==0);
295     tassert(msg->header(resip::h_ContentType).numUnknownParams()==0);
296    
297     //Contact
298     tassert(msg->exists(resip::h_Contacts));
299     tassert(msg->header(resip::h_Contacts).size()==1);
300     tassert(msg->header(resip::h_Contacts).begin()->displayName()=="Quoted string \\\"\\\"");
301     tassert(msg->header(resip::h_Contacts).begin()->numKnownParams()==1);
302     tassert(msg->header(resip::h_Contacts).begin()->numUnknownParams()==2);
303     tassert(!(msg->header(resip::h_Contacts).begin()->isAllContacts()));
304     tassert(msg->header(resip::h_Contacts).begin()->uri().numKnownParams()==0);
305     tassert(msg->header(resip::h_Contacts).begin()->uri().numUnknownParams()==0);
306     tassert(msg->header(resip::h_Contacts).begin()->uri().scheme()=="sip");
307     tassert(msg->header(resip::h_Contacts).begin()->uri().user()=="jdrosen");
308     tassert(msg->header(resip::h_Contacts).begin()->uri().host()=="example.com");
309     tassert(msg->header(resip::h_Contacts).begin()->uri().port()==0);
310     tassert(msg->header(resip::h_Contacts).begin()->uri().password().empty());
311     tassert(!(msg->header(resip::h_Contacts).begin()->uri().hasEmbedded()));
312    
313     resip::ExtensionParameter p_newparam("newparam");
314     tassert(msg->header(resip::h_Contacts).begin()->exists(p_newparam));
315     tassert(msg->header(resip::h_Contacts).begin()->param(p_newparam)=="newvalue");
316    
317     resip::ExtensionParameter p_secondparam("secondparam");
318     tassert(msg->header(resip::h_Contacts).begin()->exists(p_secondparam));
319     tassert(msg->header(resip::h_Contacts).begin()->param(p_secondparam)=="");
320    
321     tassert(msg->header(resip::h_Contacts).begin()->exists(resip::p_q));
322     tassert(msg->header(resip::h_Contacts).begin()->param(resip::p_q)==330);
323    
324    
325    
326    
327    
328 bcampen 6532 InfoLog(<< "In case wsinv:" );
329     InfoLog(<< "Original text:" << std::endl << txt );
330     InfoLog(<< "Encoded form:" << std::endl << encoded );
331     InfoLog(<< "Encoded form of copy:" << std::endl << copyEncoded );
332 bcampen 6512
333    
334    
335    
336     }
337    
338    
339     void
340     intmeth()
341     {
342 adam 8425 #if 0
343 bcampen 6512 /*
344     This message exercises a wider range of characters in several key
345     syntactic elements than implementations usually see. In particular,
346     note the following:
347    
348     o The Method contains non-alpha characters from token. Note that %
349     is not an escape character for this field. A method of IN%56ITE
350     is an unknown method. It is not the same as a method of INVITE.
351    
352     o The Request-URI contains unusual, but legal, characters.
353    
354     o A branch parameter contains all non-alphanum characters from
355     token.
356    
357     o The To header field value's quoted string contains quoted-pair
358     expansions, including a quoted NULL character.
359    
360     o The name part of name-addr in the From header field value contains
361     multiple tokens (instead of a quoted string) with all non-alphanum
362     characters from the token production rule. That value also has an
363     unknown header parameter whose name contains the non-alphanum
364     token characters and whose value is a non-ascii range UTF-8
365     encoded string. The tag parameter on this value contains the
366     non-alphanum token characters.
367    
368     o The Call-ID header field value contains the non-alphanum
369     characters from word. Notice that in this production:
370    
371     * % is not an escape character. It is only an escape character
372     in productions matching the rule "escaped".
373    
374     * " does not start a quoted string. None of ',` or " imply that
375     there will be a matching symbol later in the string.
376    
377     * The characters []{}()<> do not have any grouping semantics.
378     They are not required to appear in balanced pairs.
379    
380     o There is an unknown header field (matching extension-header) with
381     non-alphanum token characters in its name and a UTF8-NONASCII
382     value.
383    
384     If this unusual URI has been defined at a proxy, the proxy will
385     forward this request normally. Otherwise, a proxy will generate a
386     404. Endpoints will generate a 501 listing the methods they
387     understand in an Allow header field.
388    
389    
390     !interesting-Method0123456789_*+`.%indeed'~ sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*:&it+has=1,weird!*pas$wo~d_too.(doesn't-it)@example.com SIP/2.0
391     Via: SIP/2.0/TCP host1.example.com;branch=z9hG4bK-.!%66*_+`'~
392     To: "BEL:\ NUL:\ DEL:\" <sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*@example.com>
393     From: token1~` token2'+_ token3*%!.- <sip:mundane@example.com>;fromParam''~+*_!.-%="работающий";tag=_token~1'+`*%!-.
394     Call-ID: intmeth.word%ZK-!.*_+'@word`~)(><:\/"][?}{
395     CSeq: 139122385 !interesting-Method0123456789_*+`.%indeed'~
396     Max-Forwards: 255
397     extensionHeader-!.%*+_`'~:大停電
398     Content-Length: 0
399    
400    
401     */
402 adam 8425 #endif
403    
404 bcampen 6512 FILE* fid= fopen("intmeth.dat","r");
405     tassert(fid);
406     resip::Data txt;
407     char mBuf[1024];
408     int result;
409     while(!feof(fid))
410     {
411     result = fread(&mBuf,1,1024,fid);
412     txt += resip::Data(mBuf,result);
413     }
414     fclose(fid);
415     resip::SipMessage* msg = resip::SipMessage::make(txt);
416     tassert_reset();
417     tassert(msg);
418     tassert_reset();
419     if(!msg)
420     {
421     return;
422     }
423    
424     std::auto_ptr<resip::SipMessage> message(msg);
425     msg->parseAllHeaders();
426    
427     resip::SipMessage copy(*msg);
428    
429     resip::Data encoded;
430     {
431     resip::oDataStream str(encoded);
432     msg->encode(str);
433     }
434     resip::Data copyEncoded;
435     {
436     resip::oDataStream str(copyEncoded);
437     copy.encode(str);
438     }
439    
440     // Request Line
441 bcampen 6524 tassert(msg->header(resip::h_RequestLine).method()==resip::UNKNOWN);
442 bcampen 6512 tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="!interesting-Method0123456789_*+`.%indeed'~");
443     tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
444     tassert(msg->header(resip::h_RequestLine).uri().user()=="1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*");
445     tassert(msg->header(resip::h_RequestLine).uri().password()=="&it+has=1,weird!*pas$wo~d_too.(doesn't-it)");
446     tassert(msg->header(resip::h_RequestLine).uri().host()=="example.com");
447     tassert(msg->header(resip::h_RequestLine).uri().port()==0);
448     tassert(!(msg->header(resip::h_RequestLine).uri().hasEmbedded()));
449     tassert(msg->header(resip::h_RequestLine).uri().numKnownParams()==0);
450     tassert(msg->header(resip::h_RequestLine).uri().numUnknownParams()==0);
451     tassert(msg->header(resip::h_RequestLine).getSipVersion()=="SIP/2.0");
452    
453     //To
454     tassert(msg->exists(resip::h_To));
455     tassert(msg->header(resip::h_To).numKnownParams()==0);
456     tassert(msg->header(resip::h_To).numUnknownParams()==0);
457     resip::Data dispName;
458     dispName+="BEL:\\";
459     dispName+=(char)0x07;
460     dispName+=" NUL:\\";
461     dispName+=(char)0x00;
462     dispName+=" DEL:\\";
463     dispName+=(char)0x7F;
464     tassert(msg->header(resip::h_To).displayName()==dispName);
465     tassert(!(msg->header(resip::h_To).isAllContacts()));
466    
467     tassert(msg->header(resip::h_To).uri().scheme()=="sip");
468     tassert(msg->header(resip::h_To).uri().user()=="1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*");
469     tassert(msg->header(resip::h_To).uri().password().empty());
470     tassert(msg->header(resip::h_To).uri().host()=="example.com");
471     tassert(msg->header(resip::h_To).uri().port()==0);
472     tassert(!(msg->header(resip::h_To).uri().hasEmbedded()));
473     tassert(msg->header(resip::h_To).uri().numKnownParams()==0);
474     tassert(msg->header(resip::h_To).uri().numUnknownParams()==0);
475    
476     //From
477     tassert(msg->exists(resip::h_From));
478     tassert(msg->header(resip::h_From).numKnownParams()==1);
479     tassert(msg->header(resip::h_From).numUnknownParams()==1);
480     tassert(msg->header(resip::h_From).exists(resip::p_tag));
481     tassert(msg->header(resip::h_From).param(resip::p_tag)=="_token~1'+`*%!-.");
482    
483     resip::ExtensionParameter p_oddball("fromParam''~+*_!.-%");
484     tassert(msg->header(resip::h_From).exists(p_oddball));
485     resip::Data binaryParamVal;
486     binaryParamVal+=(char)0xD1;
487     binaryParamVal+=(char)0x80;
488     binaryParamVal+=(char)0xD0;
489     binaryParamVal+=(char)0xB0;
490     binaryParamVal+=(char)0xD0;
491     binaryParamVal+=(char)0xB1;
492     binaryParamVal+=(char)0xD0;
493     binaryParamVal+=(char)0xBE;
494     binaryParamVal+=(char)0xD1;
495     binaryParamVal+=(char)0x82;
496     binaryParamVal+=(char)0xD0;
497     binaryParamVal+=(char)0xB0;
498     binaryParamVal+=(char)0xD1;
499     binaryParamVal+=(char)0x8E;
500     binaryParamVal+=(char)0xD1;
501     binaryParamVal+=(char)0x89;
502     binaryParamVal+=(char)0xD0;
503     binaryParamVal+=(char)0xB8;
504     binaryParamVal+=(char)0xD0;
505     binaryParamVal+=(char)0xB9;
506     tassert(msg->header(resip::h_From).param(p_oddball)==binaryParamVal);
507     tassert(msg->header(resip::h_From).displayName()=="token1~` token2'+_ token3*%!.-");
508     tassert(!(msg->header(resip::h_From).isAllContacts()));
509    
510     tassert(msg->header(resip::h_From).uri().scheme()=="sip");
511     tassert(msg->header(resip::h_From).uri().user()=="mundane");
512     tassert(msg->header(resip::h_From).uri().password().empty());
513     tassert(msg->header(resip::h_From).uri().host()=="example.com");
514     tassert(msg->header(resip::h_From).uri().port()==0);
515     tassert(!(msg->header(resip::h_From).uri().hasEmbedded()));
516     tassert(msg->header(resip::h_From).uri().numKnownParams()==0);
517     tassert(msg->header(resip::h_From).uri().numUnknownParams()==0);
518    
519    
520     //Max-Forwards
521     tassert(msg->exists(resip::h_MaxForwards));
522     tassert(msg->header(resip::h_MaxForwards).value()==255);
523     tassert(msg->header(resip::h_MaxForwards).numKnownParams()==0);
524     tassert(msg->header(resip::h_MaxForwards).numUnknownParams()==0);
525    
526     //Call-ID
527     tassert(msg->exists(resip::h_CallID));
528     tassert(msg->header(resip::h_CallID).value()=="intmeth.word%ZK-!.*_+'@word`~)(><:\\/\"][?}{");
529     tassert(msg->header(resip::h_CallID).numKnownParams()==0);
530     tassert(msg->header(resip::h_CallID).numUnknownParams()==0);
531    
532     //Content-Length
533     tassert(msg->exists(resip::h_ContentLength));
534     tassert(msg->header(resip::h_ContentLength).value()==0);
535     tassert(msg->header(resip::h_ContentLength).numKnownParams()==0);
536     tassert(msg->header(resip::h_ContentLength).numUnknownParams()==0);
537    
538     //CSeq
539     tassert(msg->exists(resip::h_CSeq));
540 bcampen 6524 tassert(msg->header(resip::h_CSeq).method()==resip::UNKNOWN);
541 bcampen 6512 tassert(msg->header(resip::h_CSeq).unknownMethodName()=="!interesting-Method0123456789_*+`.%indeed'~");
542     tassert(msg->header(resip::h_CSeq).sequence()==139122385);
543     tassert(msg->header(resip::h_CSeq).numKnownParams()==0);
544     tassert(msg->header(resip::h_CSeq).numUnknownParams()==0);
545    
546     //Vias
547     tassert(msg->exists(resip::h_Vias));
548     tassert(msg->header(resip::h_Vias).size()==1);
549     resip::ParserContainer<resip::Via>::iterator i=msg->header(resip::h_Vias).begin();
550    
551     tassert(i->protocolName()=="SIP");
552     tassert(i->protocolVersion()=="2.0");
553     tassert(i->transport()=="TCP");
554     tassert(i->sentHost()=="host1.example.com");
555     tassert(i->sentPort()==0);
556    
557     tassert(i->numKnownParams()==1);
558     tassert(i->numUnknownParams()==0);
559     tassert(i->exists(resip::p_branch));
560     tassert(i->param(resip::p_branch).hasMagicCookie());
561     tassert(i->param(resip::p_branch).getTransactionId()=="-.!%66*_+`'~");
562     tassert(i->param(resip::p_branch).clientData().empty());
563    
564    
565    
566     // Unknown headers
567     resip::ExtensionHeader h_extensionHeader("extensionHeader-!.%*+_`'~");
568    
569     tassert(msg->exists(h_extensionHeader));
570     tassert(msg->header(h_extensionHeader).size()==1);
571     resip::Data binaryHfv;
572     binaryHfv+=(char)0xEF;
573     binaryHfv+=(char)0xBB;
574     binaryHfv+=(char)0xBF;
575     binaryHfv+=(char)0xE5;
576     binaryHfv+=(char)0xA4;
577     binaryHfv+=(char)0xA7;
578     binaryHfv+=(char)0xE5;
579     binaryHfv+=(char)0x81;
580     binaryHfv+=(char)0x9C;
581     binaryHfv+=(char)0xE9;
582     binaryHfv+=(char)0x9B;
583     binaryHfv+=(char)0xBB;
584     tassert(msg->header(h_extensionHeader).begin()->value()==binaryHfv);
585     tassert(msg->header(h_extensionHeader).begin()->numKnownParams()==0);
586     tassert(msg->header(h_extensionHeader).begin()->numUnknownParams()==0);
587    
588    
589 bcampen 6532 InfoLog(<< "In case intmeth:" );
590     InfoLog(<< "Original text:" << std::endl << txt );
591     InfoLog(<< "Encoded form:" << std::endl << encoded );
592     InfoLog(<< "Encoded form of copy:" << std::endl << copyEncoded );
593 bcampen 6512
594    
595    
596    
597     }
598    
599    
600     void
601     esc01()
602     {
603     /*
604     This INVITE exercises the % HEX HEX escaping mechanism in several
605     places. The request is syntactically valid. Interesting features
606     include the following:
607    
608     o The request-URI has sips:user@example.com embedded in its
609     userpart. What that might mean to example.net is beyond the scope
610     of this document.
611    
612     o The From and To URIs have escaped characters in their userparts.
613    
614     o The Contact URI has escaped characters in the URI parameters.
615     Note that the "name" uri-parameter has a value of "value%41",
616     which is NOT equivalent to "valueA". Per [RFC3986], unescaping
617     URI components is never performed recursively.
618    
619     A parser must accept this as a well-formed message. The application
620     using the message must treat the % HEX HEX expansions as equivalent
621     to the character being encoded. The application must not try to
622     interpret % as an escape character in those places where % HEX HEX
623     ("escaped" in the grammar) is not a valid part of the construction.
624     In [RFC3261], "escaped" only occurs in the expansions of SIP-URI,
625     SIPS-URI, and Reason-Phrase.
626    
627    
628     INVITE sip:sips%3Auser%40example.com@example.net SIP/2.0
629     To: sip:%75se%72@example.com
630     From: <sip:I%20have%20spaces@example.net>;tag=938
631     Max-Forwards: 87
632     i: esc01.239409asdfakjkn23onasd0-3234
633     CSeq: 234234 INVITE
634     Via: SIP/2.0/UDP host5.example.net;branch=z9hG4bKkdjuw
635     C: application/sdp
636     Contact:
637     <sip:cal%6Cer@host5.example.net;%6C%72;n%61me=v%61lue%25%34%31>
638     Content-Length: 150
639    
640     v=0
641     o=mhandley 29739 7272939 IN IP4 192.0.2.1
642     s=-
643     c=IN IP4 192.0.2.1
644     t=0 0
645     m=audio 49217 RTP/AVP 0 12
646     m=video 3227 RTP/AVP 31
647     a=rtpmap:31 LPC
648    
649     */
650     FILE* fid= fopen("esc01.dat","r");
651     tassert(fid);
652     resip::Data txt;
653     char mBuf[1024];
654     int result;
655     while(!feof(fid))
656     {
657     result = fread(&mBuf,1,1024,fid);
658     txt += resip::Data(mBuf,result);
659     }
660     fclose(fid);
661     resip::SipMessage* msg = resip::SipMessage::make(txt);
662     tassert_reset();
663     tassert(msg);
664     tassert_reset();
665     if(!msg)
666     {
667     return;
668     }
669    
670     std::auto_ptr<resip::SipMessage> message(msg);
671     msg->parseAllHeaders();
672    
673     resip::SipMessage copy(*msg);
674    
675     resip::Data encoded;
676     {
677     resip::oDataStream str(encoded);
678     msg->encode(str);
679     }
680     resip::Data copyEncoded;
681     {
682     resip::oDataStream str(copyEncoded);
683     copy.encode(str);
684     }
685    
686     // Request Line
687     tassert(msg->header(resip::h_RequestLine).method()==resip::INVITE);
688 bcampen 6524 tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="INVITE");
689 bcampen 6512 tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
690 bcampen 6989 // ?bwc? Is it appropriate to use a one-size-fits-all approach to unescaping
691 bcampen 6524 // parsed components? ('@' is not legal in a userpart, but the internal
692     // representation contains it)
693     // What is the best approach: all (unescape everything that is printable),
694     // none (leave escaping exactly as found), or context sensitive (escape
695     // everything that is legal for a given field)?
696 bcampen 6512 tassert(msg->header(resip::h_RequestLine).uri().user()=="sips%3Auser%40example.com");
697 bcampen 6524 tassert_reset();
698 bcampen 6512 tassert(msg->header(resip::h_RequestLine).uri().password().empty());
699     tassert(msg->header(resip::h_RequestLine).uri().host()=="example.net");
700     tassert(msg->header(resip::h_RequestLine).uri().port()==0);
701     tassert(msg->header(resip::h_RequestLine).uri().numKnownParams()==0);
702     tassert(msg->header(resip::h_RequestLine).uri().numUnknownParams()==0);
703     tassert(!(msg->header(resip::h_RequestLine).uri().hasEmbedded()));
704     tassert(msg->header(resip::h_RequestLine).getSipVersion()=="SIP/2.0");
705    
706     //To
707     tassert(msg->exists(resip::h_To));
708     tassert(msg->header(resip::h_To).displayName().empty());
709     tassert(!(msg->header(resip::h_To).isAllContacts()));
710     tassert(msg->header(resip::h_To).uri().scheme()=="sip");
711 bcampen 6524 tassert(msg->header(resip::h_To).uri().user()=="user");
712 bcampen 6512 tassert(msg->header(resip::h_To).uri().password().empty());
713     tassert(msg->header(resip::h_To).uri().host()=="example.com");
714     tassert(msg->header(resip::h_To).uri().port()==0);
715     tassert(!(msg->header(resip::h_To).uri().hasEmbedded()));
716     tassert(msg->header(resip::h_To).uri().numKnownParams()==0);
717     tassert(msg->header(resip::h_To).uri().numUnknownParams()==0);
718     tassert(msg->header(resip::h_To).numKnownParams()==0);
719     tassert(msg->header(resip::h_To).numUnknownParams()==0);
720    
721     //From
722     tassert(msg->exists(resip::h_From));
723     tassert(msg->header(resip::h_From).displayName().empty());
724     tassert(!(msg->header(resip::h_From).isAllContacts()));
725     tassert(msg->header(resip::h_From).uri().scheme()=="sip");
726 bcampen 6989 // ?bwc? ' ' is not legal in a userpart, but the internal
727 bcampen 6524 // representation contains it. Is this appropriate?
728 bcampen 6512 tassert(msg->header(resip::h_From).uri().user()=="I%20have%20spaces");
729 bcampen 6524 tassert_reset();
730 bcampen 6512 tassert(msg->header(resip::h_From).uri().password().empty());
731     tassert(msg->header(resip::h_From).uri().host()=="example.net");
732     tassert(msg->header(resip::h_From).uri().port()==0);
733     tassert(!(msg->header(resip::h_From).uri().hasEmbedded()));
734     tassert(msg->header(resip::h_From).uri().numKnownParams()==0);
735     tassert(msg->header(resip::h_From).uri().numUnknownParams()==0);
736     tassert(msg->header(resip::h_From).numKnownParams()==1);
737     tassert(msg->header(resip::h_From).numUnknownParams()==0);
738     tassert(msg->header(resip::h_From).exists(resip::p_tag));
739     tassert(msg->header(resip::h_From).param(resip::p_tag)=="938");
740    
741     //Max-Forwards
742     tassert(msg->exists(resip::h_MaxForwards));
743     tassert(msg->header(resip::h_MaxForwards).value()==87);
744     tassert(msg->header(resip::h_MaxForwards).numKnownParams()==0);
745     tassert(msg->header(resip::h_MaxForwards).numUnknownParams()==0);
746    
747     //Call-ID
748     tassert(msg->exists(resip::h_CallID));
749     tassert(msg->header(resip::h_CallID).value()=="esc01.239409asdfakjkn23onasd0-3234");
750     tassert(msg->header(resip::h_CallID).numKnownParams()==0);
751     tassert(msg->header(resip::h_CallID).numUnknownParams()==0);
752    
753     //Content-Length
754     tassert(msg->exists(resip::h_ContentLength));
755     tassert(msg->header(resip::h_ContentLength).value()==150);
756     tassert(msg->header(resip::h_ContentLength).numKnownParams()==0);
757     tassert(msg->header(resip::h_ContentLength).numUnknownParams()==0);
758    
759     //CSeq
760     tassert(msg->exists(resip::h_CSeq));
761     tassert(msg->header(resip::h_CSeq).method()==resip::INVITE);
762 bcampen 6524 tassert(msg->header(resip::h_CSeq).unknownMethodName()=="INVITE");
763 bcampen 6512 tassert(msg->header(resip::h_CSeq).sequence()==234234);
764     tassert(msg->header(resip::h_CSeq).numKnownParams()==0);
765     tassert(msg->header(resip::h_CSeq).numUnknownParams()==0);
766    
767     //Vias
768     tassert(msg->exists(resip::h_Vias));
769     tassert(msg->header(resip::h_Vias).size()==1);
770     resip::ParserContainer<resip::Via>::iterator i=msg->header(resip::h_Vias).begin();
771    
772     tassert(i->protocolName()=="SIP");
773     tassert(i->protocolVersion()=="2.0");
774     tassert(i->transport()=="UDP");
775     tassert(i->sentHost()=="host5.example.net");
776     tassert(i->sentPort()==0);
777    
778     tassert(i->numKnownParams()==1);
779     tassert(i->numUnknownParams()==0);
780    
781     tassert(i->exists(resip::p_branch));
782 bcampen 6524 tassert(i->param(resip::p_branch).hasMagicCookie());
783 bcampen 6512 tassert(i->param(resip::p_branch).getTransactionId()=="kdjuw");
784     tassert(i->param(resip::p_branch).clientData().empty());
785    
786    
787    
788     //Content-Type
789     tassert(msg->exists(resip::h_ContentType));
790     tassert(msg->header(resip::h_ContentType).type()=="application");
791     tassert(msg->header(resip::h_ContentType).subType()=="sdp");
792     tassert(msg->header(resip::h_ContentType).numKnownParams()==0);
793     tassert(msg->header(resip::h_ContentType).numUnknownParams()==0);
794    
795     //Contact
796     tassert(msg->exists(resip::h_Contacts));
797     tassert(msg->header(resip::h_Contacts).size()==1);
798     tassert(msg->header(resip::h_Contacts).begin()->displayName().empty());
799     tassert(!(msg->header(resip::h_Contacts).begin()->isAllContacts()));
800     tassert(msg->header(resip::h_Contacts).begin()->uri().scheme()=="sip");
801 bcampen 6524 tassert(msg->header(resip::h_Contacts).begin()->uri().user()=="caller");
802 bcampen 6512 tassert(msg->header(resip::h_Contacts).begin()->uri().password().empty());
803     tassert(msg->header(resip::h_Contacts).begin()->uri().host()=="host5.example.net");
804     tassert(msg->header(resip::h_Contacts).begin()->uri().port()==0);
805     tassert(!(msg->header(resip::h_Contacts).begin()->uri().hasEmbedded()));
806    
807     tassert(msg->header(resip::h_Contacts).begin()->uri().numKnownParams()==0);
808     tassert(msg->header(resip::h_Contacts).begin()->uri().numUnknownParams()==2);
809    
810 bcampen 6989 // ?bwc? These params have escaped stuff in them; is it mandatory that we
811 bcampen 6512 // treat escaped and unescaped versions of the same parameter as identical?
812    
813     resip::ExtensionParameter p_wonky1("%6C%72");
814     resip::ExtensionParameter p_wonky2("n%61me");
815     tassert(msg->header(resip::h_Contacts).begin()->uri().exists(p_wonky1));
816     tassert(msg->header(resip::h_Contacts).begin()->uri().param(p_wonky1)=="");
817     tassert(msg->header(resip::h_Contacts).begin()->uri().exists(p_wonky2));
818     tassert(msg->header(resip::h_Contacts).begin()->uri().param(p_wonky2)=="v%61lue%25%34%31");
819    
820    
821     tassert(msg->header(resip::h_Contacts).begin()->numKnownParams()==0);
822     tassert(msg->header(resip::h_Contacts).begin()->numUnknownParams()==0);
823    
824     tassert_reset();
825    
826 bcampen 6532 InfoLog(<< "In case esc01:" );
827     InfoLog(<< "Original text:" << std::endl << txt );
828     InfoLog(<< "Encoded form:" << std::endl << encoded );
829     InfoLog(<< "Encoded form of copy:" << std::endl << copyEncoded );
830 bcampen 6512
831    
832    
833    
834     }
835    
836    
837     void
838 bcampen 6524 escnull()
839 bcampen 6448 {
840     /*
841 bcampen 6524 This register request contains several URIs with nulls in the
842     userpart. The message is well formed - parsers must accept this
843     message. Implementations must take special care when unescaping the
844     Address-of-Record (AOR) in this request so as to not prematurely
845     shorten the username. This request registers two distinct contact
846     URIs.
847 bcampen 6448
848 bcampen 6524 REGISTER sip:example.com SIP/2.0
849     To: sip:null-%00-null@example.com
850     From: sip:null-%00-null@example.com;tag=839923423
851 bcampen 6448 Max-Forwards: 70
852 bcampen 6524 Call-ID: escnull.39203ndfvkjdasfkq3w4otrq0adsfdfnavd
853     CSeq: 14398234 REGISTER
854     Via: SIP/2.0/UDP host5.example.com;branch=z9hG4bKkdjuw
855     Contact: <sip:%00@host5.example.com>
856     Contact: <sip:%00%00@host5.example.com>
857     L:0
858 bcampen 6448
859    
860     */
861 bcampen 6524 FILE* fid= fopen("escnull.dat","r");
862 bcampen 6448 tassert(fid);
863     resip::Data txt;
864     char mBuf[1024];
865     int result;
866     while(!feof(fid))
867     {
868     result = fread(&mBuf,1,1024,fid);
869     txt += resip::Data(mBuf,result);
870     }
871 bcampen 6450 fclose(fid);
872 bcampen 6448 resip::SipMessage* msg = resip::SipMessage::make(txt);
873     tassert_reset();
874 bcampen 6524 tassert(msg);
875     tassert_reset();
876 bcampen 6448 if(!msg)
877     {
878     return;
879     }
880    
881     std::auto_ptr<resip::SipMessage> message(msg);
882     msg->parseAllHeaders();
883    
884 bcampen 6453 resip::SipMessage copy(*msg);
885 bcampen 6448
886 bcampen 6453 resip::Data encoded;
887     {
888     resip::oDataStream str(encoded);
889     msg->encode(str);
890     }
891     resip::Data copyEncoded;
892     {
893     resip::oDataStream str(copyEncoded);
894     copy.encode(str);
895     }
896 bcampen 6524
897     // Request Line
898     //REGISTER sip:example.com SIP/2.0
899     tassert(msg->header(resip::h_RequestLine).method()==resip::REGISTER);
900     tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="REGISTER");
901     tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
902     tassert(msg->header(resip::h_RequestLine).uri().user()=="");
903     tassert(msg->header(resip::h_RequestLine).uri().password().empty());
904     tassert(msg->header(resip::h_RequestLine).uri().host()=="example.com");
905     tassert(msg->header(resip::h_RequestLine).uri().port()==0);
906     tassert(!(msg->header(resip::h_RequestLine).uri().hasEmbedded()));
907     tassert(msg->header(resip::h_RequestLine).uri().numKnownParams()==0);
908     tassert(msg->header(resip::h_RequestLine).uri().numUnknownParams()==0);
909     tassert(msg->header(resip::h_RequestLine).getSipVersion()=="SIP/2.0");
910 bcampen 6512
911 bcampen 6524 //To: sip:null-%00-null@example.com
912     tassert(msg->exists(resip::h_To));
913     tassert(msg->header(resip::h_To).displayName().empty());
914     tassert(msg->header(resip::h_To).numKnownParams()==0);
915     tassert(msg->header(resip::h_To).numUnknownParams()==0);
916     tassert(!(msg->header(resip::h_To).isAllContacts()));
917     tassert(msg->header(resip::h_To).uri().scheme()=="sip");
918     tassert(msg->header(resip::h_To).uri().user()=="null-%00-null");
919     tassert(msg->header(resip::h_To).uri().password().empty());
920     tassert(msg->header(resip::h_To).uri().host()=="example.com");
921     tassert(msg->header(resip::h_To).uri().port()==0);
922     tassert(!(msg->header(resip::h_To).uri().hasEmbedded()));
923     tassert(msg->header(resip::h_To).uri().numKnownParams()==0);
924     tassert(msg->header(resip::h_To).uri().numUnknownParams()==0);
925    
926     //From: sip:null-%00-null@example.com;tag=839923423
927     tassert(msg->exists(resip::h_From));
928     tassert(msg->header(resip::h_From).displayName()=="");
929     tassert(msg->header(resip::h_From).numKnownParams()==1);
930     tassert(msg->header(resip::h_From).numUnknownParams()==0);
931     tassert(msg->header(resip::h_From).exists(resip::p_tag));
932     tassert(msg->header(resip::h_From).param(resip::p_tag)=="839923423");
933     tassert(!(msg->header(resip::h_From).isAllContacts()));
934     tassert(msg->header(resip::h_From).uri().scheme()=="sip");
935     tassert(msg->header(resip::h_From).uri().user()=="null-%00-null");
936     tassert(msg->header(resip::h_From).uri().password().empty());
937     tassert(msg->header(resip::h_From).uri().host()=="example.com");
938     tassert(msg->header(resip::h_From).uri().port()==0);
939     tassert(!(msg->header(resip::h_From).uri().hasEmbedded()));
940     tassert(msg->header(resip::h_From).uri().numKnownParams()==0);
941     tassert(msg->header(resip::h_From).uri().numUnknownParams()==0);
942 bcampen 6512
943 bcampen 6524 //Max-Forwards: 70
944     tassert(msg->exists(resip::h_MaxForwards));
945     tassert(msg->header(resip::h_MaxForwards).value()==70);
946     tassert(msg->header(resip::h_MaxForwards).numKnownParams()==0);
947     tassert(msg->header(resip::h_MaxForwards).numUnknownParams()==0);
948    
949    
950     //Call-ID: escnull.39203ndfvkjdasfkq3w4otrq0adsfdfnavd
951     tassert(msg->exists(resip::h_CallID));
952     tassert(msg->header(resip::h_CallID).value()=="escnull.39203ndfvkjdasfkq3w4otrq0adsfdfnavd");
953     tassert(msg->header(resip::h_CallID).numKnownParams()==0);
954     tassert(msg->header(resip::h_CallID).numUnknownParams()==0);
955    
956     //CSeq: 14398234 REGISTER
957     tassert(msg->exists(resip::h_CSeq));
958     tassert(msg->header(resip::h_CSeq).method()==resip::REGISTER);
959     tassert(msg->header(resip::h_CSeq).unknownMethodName()=="REGISTER");
960     tassert(msg->header(resip::h_CSeq).sequence()==14398234);
961     tassert(msg->header(resip::h_CSeq).numKnownParams()==0);
962     tassert(msg->header(resip::h_CSeq).numUnknownParams()==0);
963    
964     //Via: SIP/2.0/UDP host5.example.com;branch=z9hG4bKkdjuw
965     tassert(msg->exists(resip::h_Vias));
966     tassert(msg->header(resip::h_Vias).size()==1);
967     resip::ParserContainer<resip::Via>::iterator i=msg->header(resip::h_Vias).begin();
968    
969     tassert(i->numKnownParams()==1);
970     tassert(i->numUnknownParams()==0);
971     tassert(i->protocolName()=="SIP");
972     tassert(i->protocolVersion()=="2.0");
973     tassert(i->transport()=="UDP");
974     tassert(i->sentHost()=="host5.example.com");
975     tassert(i->sentPort()==0);
976    
977     tassert(i->exists(resip::p_branch));
978     tassert(i->param(resip::p_branch).hasMagicCookie());
979     tassert(i->param(resip::p_branch).getTransactionId()=="kdjuw");
980     tassert(i->param(resip::p_branch).clientData().empty());
981    
982     //Contact: <sip:%00@host5.example.com>
983     //Contact: <sip:%00%00@host5.example.com>
984     tassert(msg->exists(resip::h_Contacts));
985     tassert(msg->header(resip::h_Contacts).size()==2);
986     resip::ParserContainer<resip::NameAddr>::iterator j=msg->header(resip::h_Contacts).begin();
987    
988     tassert(j->displayName()=="");
989     tassert(j->numKnownParams()==0);
990     tassert(j->numUnknownParams()==0);
991     tassert(!(j->isAllContacts()));
992     tassert(j->uri().numKnownParams()==0);
993     tassert(j->uri().numUnknownParams()==0);
994     tassert(j->uri().scheme()=="sip");
995     tassert(j->uri().user()=="%00");
996     tassert(j->uri().password().empty());
997     tassert(j->uri().host()=="host5.example.com");
998     tassert(j->uri().port()==0);
999     tassert(!(j->uri().hasEmbedded()));
1000 bcampen 6448
1001 bcampen 6524 j++;
1002    
1003     tassert(j->displayName()=="");
1004     tassert(j->numKnownParams()==0);
1005     tassert(j->numUnknownParams()==0);
1006     tassert(!(j->isAllContacts()));
1007     tassert(j->uri().numKnownParams()==0);
1008     tassert(j->uri().numUnknownParams()==0);
1009     tassert(j->uri().scheme()=="sip");
1010     tassert(j->uri().user()=="%00%00");
1011     tassert(j->uri().password().empty());
1012     tassert(j->uri().host()=="host5.example.com");
1013     tassert(j->uri().port()==0);
1014     tassert(!(j->uri().hasEmbedded()));
1015    
1016     //L:0
1017     tassert(msg->exists(resip::h_ContentLength));
1018     tassert(msg->header(resip::h_ContentLength).value()==0);
1019     tassert(msg->header(resip::h_ContentLength).numKnownParams()==0);
1020     tassert(msg->header(resip::h_ContentLength).numUnknownParams()==0);
1021    
1022    
1023    
1024    
1025 bcampen 6532 InfoLog(<< "In case escnull:" );
1026     InfoLog(<< "Original text:" << std::endl << txt );
1027     InfoLog(<< "Encoded form:" << std::endl << encoded );
1028     InfoLog(<< "Encoded form of copy:" << std::endl << copyEncoded );
1029 bcampen 6453
1030    
1031    
1032    
1033 bcampen 6448 }
1034    
1035    
1036     void
1037 bcampen 6524 esc02()
1038 bcampen 6448 {
1039     /*
1040 bcampen 6524 In most of the places % can appear in a SIP message, it is not an
1041     escape character. This can surprise the unwary implementor. The
1042     following well-formed request has these properties:
1043 bcampen 6448
1044 bcampen 6524 o The request method is unknown. It is NOT equivalent to REGISTER.
1045    
1046     o The display name portion of the To and From header fields is
1047     "%Z%45". Note that this is not the same as %ZE.
1048    
1049     o This message has two Contact header field values, not three.
1050     <sip:alias2@host2.example.com> is a C%6Fntact header field value.
1051    
1052     A parser should accept this message as well formed. A proxy would
1053     forward or reject the message depending on what the Request-URI meant
1054     to it. An endpoint would reject this message with a 501.
1055    
1056    
1057     RE%47IST%45R sip:registrar.example.com SIP/2.0
1058     To: "%Z%45" <sip:resource@example.com>
1059     From: "%Z%45" <sip:resource@example.com>;tag=f232jadfj23
1060     Call-ID: esc02.asdfnqwo34rq23i34jrjasdcnl23nrlknsdf
1061     Via: SIP/2.0/TCP host.example.com;branch=z9hG4bK209%fzsnel234
1062     CSeq: 29344 RE%47IST%45R
1063     Max-Forwards: 70
1064     Contact: <sip:alias1@host1.example.com>
1065     C%6Fntact: <sip:alias2@host2.example.com>
1066     Contact: <sip:alias3@host3.example.com>
1067 bcampen 6448 l: 0
1068    
1069    
1070     */
1071 bcampen 6524 FILE* fid= fopen("esc02.dat","r");
1072 bcampen 6448 tassert(fid);
1073     resip::Data txt;
1074     char mBuf[1024];
1075     int result;
1076     while(!feof(fid))
1077     {
1078     result = fread(&mBuf,1,1024,fid);
1079     txt += resip::Data(mBuf,result);
1080     }
1081 bcampen 6450 fclose(fid);
1082 bcampen 6448 resip::SipMessage* msg = resip::SipMessage::make(txt);
1083     tassert_reset();
1084     tassert(msg);
1085     tassert_reset();
1086     if(!msg)
1087     {
1088     return;
1089     }
1090    
1091     std::auto_ptr<resip::SipMessage> message(msg);
1092     msg->parseAllHeaders();
1093    
1094 bcampen 6453 resip::SipMessage copy(*msg);
1095 bcampen 6448
1096 bcampen 6453 resip::Data encoded;
1097     {
1098     resip::oDataStream str(encoded);
1099     msg->encode(str);
1100     }
1101     resip::Data copyEncoded;
1102     {
1103     resip::oDataStream str(copyEncoded);
1104     copy.encode(str);
1105     }
1106 bcampen 6448
1107 bcampen 6524 //RE%47IST%45R sip:registrar.example.com SIP/2.0
1108     tassert(msg->header(resip::h_RequestLine).method()==resip::UNKNOWN);
1109     tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="RE%47IST%45R");
1110     tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
1111     tassert(msg->header(resip::h_RequestLine).uri().user()=="");
1112     tassert(msg->header(resip::h_RequestLine).uri().password().empty());
1113     tassert(msg->header(resip::h_RequestLine).uri().host()=="registrar.example.com");
1114     tassert(msg->header(resip::h_RequestLine).uri().port()==0);
1115     tassert(!(msg->header(resip::h_RequestLine).uri().hasEmbedded()));
1116     tassert(msg->header(resip::h_RequestLine).uri().numKnownParams()==0);
1117     tassert(msg->header(resip::h_RequestLine).uri().numUnknownParams()==0);
1118     tassert(msg->header(resip::h_RequestLine).getSipVersion()=="SIP/2.0");
1119    
1120     //To: "%Z%45" <sip:resource@example.com>
1121     tassert(msg->exists(resip::h_To));
1122     tassert(msg->header(resip::h_To).displayName()=="%Z%45");
1123     tassert(msg->header(resip::h_To).numKnownParams()==0);
1124     tassert(msg->header(resip::h_To).numUnknownParams()==0);
1125     tassert(!(msg->header(resip::h_To).isAllContacts()));
1126     tassert(msg->header(resip::h_To).uri().scheme()=="sip");
1127     tassert(msg->header(resip::h_To).uri().user()=="resource");
1128     tassert(msg->header(resip::h_To).uri().password().empty());
1129     tassert(msg->header(resip::h_To).uri().host()=="example.com");
1130     tassert(msg->header(resip::h_To).uri().port()==0);
1131     tassert(!(msg->header(resip::h_To).uri().hasEmbedded()));
1132     tassert(msg->header(resip::h_To).uri().numKnownParams()==0);
1133     tassert(msg->header(resip::h_To).uri().numUnknownParams()==0);
1134    
1135     //From: "%Z%45" <sip:resource@example.com>;tag=f232jadfj23
1136     tassert(msg->exists(resip::h_From));
1137     tassert(msg->header(resip::h_From).displayName()=="%Z%45");
1138     tassert(msg->header(resip::h_From).numKnownParams()==1);
1139     tassert(msg->header(resip::h_From).numUnknownParams()==0);
1140     tassert(msg->header(resip::h_From).exists(resip::p_tag));
1141     tassert(msg->header(resip::h_From).param(resip::p_tag)=="f232jadfj23");
1142     tassert(!(msg->header(resip::h_From).isAllContacts()));
1143     tassert(msg->header(resip::h_From).uri().scheme()=="sip");
1144     tassert(msg->header(resip::h_From).uri().user()=="resource");
1145     tassert(msg->header(resip::h_From).uri().password().empty());
1146     tassert(msg->header(resip::h_From).uri().host()=="example.com");
1147     tassert(msg->header(resip::h_From).uri().port()==0);
1148     tassert(!(msg->header(resip::h_From).uri().hasEmbedded()));
1149     tassert(msg->header(resip::h_From).uri().numKnownParams()==0);
1150     tassert(msg->header(resip::h_From).uri().numUnknownParams()==0);
1151    
1152     //Call-ID: esc02.asdfnqwo34rq23i34jrjasdcnl23nrlknsdf
1153     tassert(msg->exists(resip::h_CallID));
1154     tassert(msg->header(resip::h_CallID).value()=="esc02.asdfnqwo34rq23i34jrjasdcnl23nrlknsdf");
1155     tassert(msg->header(resip::h_CallID).numKnownParams()==0);
1156     tassert(msg->header(resip::h_CallID).numUnknownParams()==0);
1157    
1158     //Via: SIP/2.0/TCP host.example.com;branch=z9hG4bK209%fzsnel234
1159     tassert(msg->exists(resip::h_Vias));
1160     tassert(msg->header(resip::h_Vias).size()==1);
1161     resip::ParserContainer<resip::Via>::iterator i=msg->header(resip::h_Vias).begin();
1162    
1163     tassert(i->numKnownParams()==1);
1164     tassert(i->numUnknownParams()==0);
1165     tassert(i->protocolName()=="SIP");
1166     tassert(i->protocolVersion()=="2.0");
1167     tassert(i->transport()=="TCP");
1168     tassert(i->sentHost()=="host.example.com");
1169     tassert(i->sentPort()==0);
1170    
1171     tassert(i->exists(resip::p_branch));
1172     tassert(i->param(resip::p_branch).hasMagicCookie());
1173     tassert(i->param(resip::p_branch).getTransactionId()=="209%fzsnel234");
1174     tassert(i->param(resip::p_branch).clientData().empty());
1175    
1176     //CSeq: 29344 RE%47IST%45R
1177     tassert(msg->exists(resip::h_CSeq));
1178     tassert(msg->header(resip::h_CSeq).method()==resip::UNKNOWN);
1179     tassert(msg->header(resip::h_CSeq).unknownMethodName()=="RE%47IST%45R");
1180     tassert(msg->header(resip::h_CSeq).sequence()==29344);
1181     tassert(msg->header(resip::h_CSeq).numKnownParams()==0);
1182     tassert(msg->header(resip::h_CSeq).numUnknownParams()==0);
1183    
1184     //Max-Forwards: 70
1185     tassert(msg->exists(resip::h_MaxForwards));
1186     tassert(msg->header(resip::h_MaxForwards).value()==70);
1187     tassert(msg->header(resip::h_MaxForwards).numKnownParams()==0);
1188     tassert(msg->header(resip::h_MaxForwards).numUnknownParams()==0);
1189    
1190     //Contact: <sip:alias1@host1.example.com>
1191     //Contact: <sip:alias3@host3.example.com>
1192     tassert(msg->exists(resip::h_Contacts));
1193     tassert(msg->header(resip::h_Contacts).size()==2);
1194     resip::ParserContainer<resip::NameAddr>::iterator j=msg->header(resip::h_Contacts).begin();
1195    
1196     tassert(j->displayName()=="");
1197     tassert(j->numKnownParams()==0);
1198     tassert(j->numUnknownParams()==0);
1199     tassert(!(j->isAllContacts()));
1200     tassert(j->uri().numKnownParams()==0);
1201     tassert(j->uri().numUnknownParams()==0);
1202     tassert(j->uri().scheme()=="sip");
1203     tassert(j->uri().user()=="alias1");
1204     tassert(j->uri().password().empty());
1205     tassert(j->uri().host()=="host1.example.com");
1206     tassert(j->uri().port()==0);
1207     tassert(!(j->uri().hasEmbedded()));
1208    
1209     j++;
1210    
1211     tassert(j->displayName()=="");
1212     tassert(j->numKnownParams()==0);
1213     tassert(j->numUnknownParams()==0);
1214     tassert(!(j->isAllContacts()));
1215     tassert(j->uri().numKnownParams()==0);
1216     tassert(j->uri().numUnknownParams()==0);
1217     tassert(j->uri().scheme()=="sip");
1218     tassert(j->uri().user()=="alias3");
1219     tassert(j->uri().password().empty());
1220     tassert(j->uri().host()=="host3.example.com");
1221     tassert(j->uri().port()==0);
1222     tassert(!(j->uri().hasEmbedded()));
1223    
1224     //C%6Fntact: <sip:alias2@host2.example.com>
1225     resip::ExtensionHeader p_fakeContact("C%6Fntact");
1226     tassert(msg->exists(p_fakeContact));
1227     tassert(msg->header(p_fakeContact).size()==1);
1228     tassert(msg->header(p_fakeContact).begin()->value()=="<sip:alias2@host2.example.com>");
1229    
1230     //l: 0
1231     tassert(msg->exists(resip::h_ContentLength));
1232     tassert(msg->header(resip::h_ContentLength).value()==0);
1233     tassert(msg->header(resip::h_ContentLength).numKnownParams()==0);
1234     tassert(msg->header(resip::h_ContentLength).numUnknownParams()==0);
1235    
1236    
1237 bcampen 6532 InfoLog(<< "In case esc02:" );
1238     InfoLog(<< "Original text:" << std::endl << txt );
1239     InfoLog(<< "Encoded form:" << std::endl << encoded );
1240     InfoLog(<< "Encoded form of copy:" << std::endl << copyEncoded );
1241 bcampen 6453
1242    
1243    
1244    
1245 bcampen 6448 }
1246    
1247    
1248     void
1249 bcampen 6524 lwsdisp()
1250 bcampen 6448 {
1251     /*
1252 bcampen 6524 This OPTIONS request is not valid per the grammar in RFC 3261 since
1253     there is no LWS between the token in the display name and < in the
1254     From header field value. This has been identified as a specification
1255     bug that will be removed when RFC 3261 is revised. Elements should
1256     accept this request as well formed.
1257 bcampen 6448
1258 bcampen 6524 OPTIONS sip:user@example.com SIP/2.0
1259 bcampen 6448 To: sip:user@example.com
1260 bcampen 6524 From: caller<sip:caller@example.com>;tag=323
1261 bcampen 6448 Max-Forwards: 70
1262 bcampen 6524 Call-ID: lwsdisp.1234abcd@funky.example.com
1263     CSeq: 60 OPTIONS
1264     Via: SIP/2.0/UDP funky.example.com;branch=z9hG4bKkdjuw
1265     l: 0
1266 bcampen 6448
1267    
1268     */
1269 bcampen 6524 FILE* fid= fopen("lwsdisp.dat","r");
1270 bcampen 6448 tassert(fid);
1271     resip::Data txt;
1272     char mBuf[1024];
1273     int result;
1274     while(!feof(fid))
1275     {
1276     result = fread(&mBuf,1,1024,fid);
1277     txt += resip::Data(mBuf,result);
1278     }
1279 bcampen 6450 fclose(fid);
1280 bcampen 6448 resip::SipMessage* msg = resip::SipMessage::make(txt);
1281     tassert_reset();
1282     tassert(msg);
1283     tassert_reset();
1284     if(!msg)
1285     {
1286     return;
1287     }
1288    
1289     std::auto_ptr<resip::SipMessage> message(msg);
1290     msg->parseAllHeaders();
1291    
1292 bcampen 6453 resip::SipMessage copy(*msg);
1293 bcampen 6448
1294 bcampen 6453 resip::Data encoded;
1295     {
1296     resip::oDataStream str(encoded);
1297     msg->encode(str);
1298     }
1299     resip::Data copyEncoded;
1300     {
1301     resip::oDataStream str(copyEncoded);
1302     copy.encode(str);
1303     }
1304 bcampen 6448
1305 bcampen 6524 //Request-Line
1306     //OPTIONS sip:user@example.com SIP/2.0
1307     tassert(msg->header(resip::h_RequestLine).method()==resip::OPTIONS);
1308     tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="OPTIONS");
1309     tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
1310     tassert(msg->header(resip::h_RequestLine).uri().user()=="user");
1311     tassert(msg->header(resip::h_RequestLine).uri().password().empty());
1312     tassert(msg->header(resip::h_RequestLine).uri().host()=="example.com");
1313     tassert(msg->header(resip::h_RequestLine).uri().port()==0);
1314     tassert(!(msg->header(resip::h_RequestLine).uri().hasEmbedded()));
1315     tassert(msg->header(resip::h_RequestLine).uri().numKnownParams()==0);
1316     tassert(msg->header(resip::h_RequestLine).uri().numUnknownParams()==0);
1317     tassert(msg->header(resip::h_RequestLine).getSipVersion()=="SIP/2.0");
1318    
1319     //To: sip:user@example.com
1320     tassert(msg->exists(resip::h_To));
1321     tassert(msg->header(resip::h_To).displayName()=="");
1322     tassert(msg->header(resip::h_To).numKnownParams()==0);
1323     tassert(msg->header(resip::h_To).numUnknownParams()==0);
1324     tassert(!(msg->header(resip::h_To).isAllContacts()));
1325     tassert(msg->header(resip::h_To).uri().scheme()=="sip");
1326     tassert(msg->header(resip::h_To).uri().user()=="user");
1327     tassert(msg->header(resip::h_To).uri().password().empty());
1328     tassert(msg->header(resip::h_To).uri().host()=="example.com");
1329     tassert(msg->header(resip::h_To).uri().port()==0);
1330     tassert(!(msg->header(resip::h_To).uri().hasEmbedded()));
1331     tassert(msg->header(resip::h_To).uri().numKnownParams()==0);
1332     tassert(msg->header(resip::h_To).uri().numUnknownParams()==0);
1333    
1334     //From: caller<sip:caller@example.com>;tag=323
1335     tassert(msg->exists(resip::h_From));
1336     tassert(msg->header(resip::h_From).displayName()=="caller");
1337     tassert(msg->header(resip::h_From).numKnownParams()==1);
1338     tassert(msg->header(resip::h_From).numUnknownParams()==0);
1339     tassert(msg->header(resip::h_From).exists(resip::p_tag));
1340     tassert(msg->header(resip::h_From).param(resip::p_tag)=="323");
1341     tassert(!(msg->header(resip::h_From).isAllContacts()));
1342     tassert(msg->header(resip::h_From).uri().scheme()=="sip");
1343     tassert(msg->header(resip::h_From).uri().user()=="caller");
1344     tassert(msg->header(resip::h_From).uri().password().empty());
1345     tassert(msg->header(resip::h_From).uri().host()=="example.com");
1346     tassert(msg->header(resip::h_From).uri().port()==0);
1347     tassert(!(msg->header(resip::h_From).uri().hasEmbedded()));
1348     tassert(msg->header(resip::h_From).uri().numKnownParams()==0);
1349     tassert(msg->header(resip::h_From).uri().numUnknownParams()==0);
1350    
1351     //Max-Forwards: 70
1352     tassert(msg->exists(resip::h_MaxForwards));
1353     tassert(msg->header(resip::h_MaxForwards).value()==70);
1354     tassert(msg->header(resip::h_MaxForwards).numKnownParams()==0);
1355     tassert(msg->header(resip::h_MaxForwards).numUnknownParams()==0);
1356    
1357     //Call-ID: lwsdisp.1234abcd@funky.example.com
1358     tassert(msg->exists(resip::h_CallID));
1359     tassert(msg->header(resip::h_CallID).value()=="lwsdisp.1234abcd@funky.example.com");
1360     tassert(msg->header(resip::h_CallID).numKnownParams()==0);
1361     tassert(msg->header(resip::h_CallID).numUnknownParams()==0);
1362    
1363     //CSeq: 60 OPTIONS
1364     tassert(msg->exists(resip::h_CSeq));
1365     tassert(msg->header(resip::h_CSeq).method()==resip::OPTIONS);
1366     tassert(msg->header(resip::h_CSeq).unknownMethodName()=="OPTIONS");
1367     tassert(msg->header(resip::h_CSeq).sequence()==60);
1368     tassert(msg->header(resip::h_CSeq).numKnownParams()==0);
1369     tassert(msg->header(resip::h_CSeq).numUnknownParams()==0);
1370    
1371     //Via: SIP/2.0/UDP funky.example.com;branch=z9hG4bKkdjuw
1372     tassert(msg->exists(resip::h_Vias));
1373     tassert(msg->header(resip::h_Vias).size()==1);
1374     resip::ParserContainer<resip::Via>::iterator i=msg->header(resip::h_Vias).begin();
1375    
1376     tassert(i->numKnownParams()==1);
1377     tassert(i->numUnknownParams()==0);
1378     tassert(i->protocolName()=="SIP");
1379     tassert(i->protocolVersion()=="2.0");
1380     tassert(i->transport()=="UDP");
1381     tassert(i->sentHost()=="funky.example.com");
1382     tassert(i->sentPort()==0);
1383    
1384     tassert(i->exists(resip::p_branch));
1385     tassert(i->param(resip::p_branch).hasMagicCookie());
1386     tassert(i->param(resip::p_branch).getTransactionId()=="kdjuw");
1387     tassert(i->param(resip::p_branch).clientData().empty());
1388    
1389     //l: 0
1390     tassert(msg->exists(resip::h_ContentLength));
1391     tassert(msg->header(resip::h_ContentLength).value()==0);
1392     tassert(msg->header(resip::h_ContentLength).numKnownParams()==0);
1393     tassert(msg->header(resip::h_ContentLength).numUnknownParams()==0);
1394    
1395 bcampen 6532 InfoLog(<< "In case lwsdisp:" );
1396     InfoLog(<< "Original text:" << std::endl << txt );
1397     InfoLog(<< "Encoded form:" << std::endl << encoded );
1398     InfoLog(<< "Encoded form of copy:" << std::endl << copyEncoded );
1399 bcampen 6453
1400    
1401    
1402    
1403 bcampen 6448 }
1404    
1405    
1406     void
1407 bcampen 6524 longreq()
1408 bcampen 6448 {
1409     /*
1410 bcampen 6524 This well-formed request contains header fields with many values and
1411     values that are very long. Features include the following:
1412 bcampen 6448
1413 bcampen 6524 o The To header field has a long display name, and long uri
1414     parameter names and values.
1415 bcampen 6448
1416 bcampen 6524 o The From header field has long header parameter names and values,
1417     in particular, a very long tag.
1418    
1419     o The Call-ID is one long token.
1420    
1421     INVITE sip:user@example.com SIP/2.0
1422     To: "I have a user name of extremeextremeextremeextremeextremeextremeextremeextremeextremeextreme proportion"<sip:user@example.com:6000;unknownparam1=verylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongvalue;longparamnamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename=shortvalue;verylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongParameterNameWithNoValue>
1423     F: sip:amazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallername@example.net;tag=12982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982424;unknownheaderparamnamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename=unknowheaderparamvaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevalue;unknownValuelessparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamname
1424     Call-ID: longreq.onereallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongcallid
1425     CSeq: 3882340 INVITE
1426     Unknown-LongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLong-Name: unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-value; unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-parameter-name = unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-parameter-value
1427     Via: SIP/2.0/TCP sip33.example.com
1428     v: SIP/2.0/TCP sip32.example.com
1429     V: SIP/2.0/TCP sip31.example.com
1430     Via: SIP/2.0/TCP sip30.example.com
1431     ViA: SIP/2.0/TCP sip29.example.com
1432     VIa: SIP/2.0/TCP sip28.example.com
1433     VIA: SIP/2.0/TCP sip27.example.com
1434     via: SIP/2.0/TCP sip26.example.com
1435     viA: SIP/2.0/TCP sip25.example.com
1436     vIa: SIP/2.0/TCP sip24.example.com
1437     vIA: SIP/2.0/TCP sip23.example.com
1438     V : SIP/2.0/TCP sip22.example.com
1439     v : SIP/2.0/TCP sip21.example.com
1440     V : SIP/2.0/TCP sip20.example.com
1441     v : SIP/2.0/TCP sip19.example.com
1442     Via : SIP/2.0/TCP sip18.example.com
1443     Via : SIP/2.0/TCP sip17.example.com
1444     Via: SIP/2.0/TCP sip16.example.com
1445     Via: SIP/2.0/TCP sip15.example.com
1446     Via: SIP/2.0/TCP sip14.example.com
1447     Via: SIP/2.0/TCP sip13.example.com
1448     Via: SIP/2.0/TCP sip12.example.com
1449     Via: SIP/2.0/TCP sip11.example.com
1450     Via: SIP/2.0/TCP sip10.example.com
1451     Via: SIP/2.0/TCP sip9.example.com
1452     Via: SIP/2.0/TCP sip8.example.com
1453     Via: SIP/2.0/TCP sip7.example.com
1454     Via: SIP/2.0/TCP sip6.example.com
1455     Via: SIP/2.0/TCP sip5.example.com
1456     Via: SIP/2.0/TCP sip4.example.com
1457     Via: SIP/2.0/TCP sip3.example.com
1458     Via: SIP/2.0/TCP sip2.example.com
1459     Via: SIP/2.0/TCP sip1.example.com
1460     Via: SIP/2.0/TCP host.example.com;received=192.0.2.5;branch=verylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongbranchvalue
1461     Max-Forwards: 70
1462     Contact: <sip:amazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallername@host5.example.net>
1463     Content-Type: application/sdp
1464     l: 150
1465    
1466     v=0
1467     o=mhandley 29739 7272939 IN IP4 192.0.2.1
1468     s=-
1469     c=IN IP4 192.0.2.1
1470     t=0 0
1471     m=audio 49217 RTP/AVP 0 12
1472     m=video 3227 RTP/AVP 31
1473     a=rtpmap:31 LPC
1474    
1475 bcampen 6448 */
1476 bcampen 6524 FILE* fid= fopen("longreq.dat","r");
1477 bcampen 6448 tassert(fid);
1478     resip::Data txt;
1479     char mBuf[1024];
1480     int result;
1481     while(!feof(fid))
1482     {
1483     result = fread(&mBuf,1,1024,fid);
1484     txt += resip::Data(mBuf,result);
1485     }
1486 bcampen 6450 fclose(fid);
1487 bcampen 6448 resip::SipMessage* msg = resip::SipMessage::make(txt);
1488     tassert_reset();
1489     tassert(msg);
1490     tassert_reset();
1491     if(!msg)
1492     {
1493     return;
1494     }
1495    
1496     std::auto_ptr<resip::SipMessage> message(msg);
1497     msg->parseAllHeaders();
1498    
1499 bcampen 6453 resip::SipMessage copy(*msg);
1500 bcampen 6448
1501 bcampen 6453 resip::Data encoded;
1502     {
1503     resip::oDataStream str(encoded);
1504     msg->encode(str);
1505     }
1506     resip::Data copyEncoded;
1507     {
1508     resip::oDataStream str(copyEncoded);
1509     copy.encode(str);
1510     }
1511 bcampen 6448
1512 bcampen 6524 //Request Line
1513     //INVITE sip:user@example.com SIP/2.0
1514     tassert(msg->header(resip::h_RequestLine).method()==resip::INVITE);
1515     tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="INVITE");
1516     tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
1517     tassert(msg->header(resip::h_RequestLine).uri().user()=="user");
1518     tassert(msg->header(resip::h_RequestLine).uri().password().empty());
1519     tassert(msg->header(resip::h_RequestLine).uri().host()=="example.com");
1520     tassert(msg->header(resip::h_RequestLine).uri().port()==0);
1521     tassert(!(msg->header(resip::h_RequestLine).uri().hasEmbedded()));
1522     tassert(msg->header(resip::h_RequestLine).uri().numKnownParams()==0);
1523     tassert(msg->header(resip::h_RequestLine).uri().numUnknownParams()==0);
1524     tassert(msg->header(resip::h_RequestLine).getSipVersion()=="SIP/2.0");
1525    
1526     //To: "I have a user name of extremeextremeextremeextremeextremeextremeextremeextremeextremeextreme proportion"<sip:user@example.com:6000;unknownparam1=verylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongvalue;longparamnamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename=shortvalue;verylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongParameterNameWithNoValue>
1527     tassert(msg->exists(resip::h_To));
1528     tassert(msg->header(resip::h_To).displayName()=="I have a user name of extremeextremeextremeextremeextremeextremeextremeextremeextremeextreme proportion");
1529     tassert(msg->header(resip::h_To).numKnownParams()==0);
1530     tassert(msg->header(resip::h_To).numUnknownParams()==0);
1531     tassert(!(msg->header(resip::h_To).isAllContacts()));
1532     tassert(msg->header(resip::h_To).uri().scheme()=="sip");
1533     tassert(msg->header(resip::h_To).uri().user()=="user");
1534     tassert(msg->header(resip::h_To).uri().password().empty());
1535     tassert(msg->header(resip::h_To).uri().host()=="example.com");
1536     tassert(msg->header(resip::h_To).uri().port()==6000);
1537     tassert(!(msg->header(resip::h_To).uri().hasEmbedded()));
1538     tassert(msg->header(resip::h_To).uri().numKnownParams()==0);
1539     tassert(msg->header(resip::h_To).uri().numUnknownParams()==3);
1540    
1541     resip::ExtensionParameter p_unknownparam1("unknownparam1");
1542     tassert(msg->header(resip::h_To).uri().exists(p_unknownparam1));
1543     tassert(msg->header(resip::h_To).uri().param(p_unknownparam1)=="verylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongvalue");
1544    
1545     resip::ExtensionParameter p_long("longparamnamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename");
1546     tassert(msg->header(resip::h_To).uri().exists(p_long));
1547     tassert(msg->header(resip::h_To).uri().param(p_long)=="shortvalue");
1548    
1549     resip::ExtensionParameter p_verylong("verylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongParameterNameWithNoValue");
1550     tassert(msg->header(resip::h_To).uri().exists(p_verylong));
1551     tassert(msg->header(resip::h_To).uri().param(p_verylong)=="");
1552    
1553     //F: sip:amazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallername@example.net;tag=12982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982424;unknownheaderparamnamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename=unknowheaderparamvaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevalue;unknownValuelessparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamname
1554     tassert(msg->exists(resip::h_From));
1555     tassert(msg->header(resip::h_From).displayName()=="");
1556     tassert(msg->header(resip::h_From).numKnownParams()==1);
1557     tassert(msg->header(resip::h_From).numUnknownParams()==2);
1558     tassert(msg->header(resip::h_From).exists(resip::p_tag));
1559     tassert(msg->header(resip::h_From).param(resip::p_tag)=="12982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982982424");
1560    
1561     resip::ExtensionParameter p_unknownheaderparameternameXalot("unknownheaderparamnamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename");
1562     tassert(msg->header(resip::h_From).exists(p_unknownheaderparameternameXalot));
1563     tassert(msg->header(resip::h_From).param(p_unknownheaderparameternameXalot)=="unknowheaderparamvaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevaluevalue");
1564    
1565     resip::ExtensionParameter p_unknownvalueless("unknownValuelessparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamnameparamname");
1566     tassert(msg->header(resip::h_From).exists(p_unknownvalueless));
1567     tassert(msg->header(resip::h_From).param(p_unknownvalueless)=="");
1568    
1569     tassert(!(msg->header(resip::h_From).isAllContacts()));
1570     tassert(msg->header(resip::h_From).uri().scheme()=="sip");
1571     tassert(msg->header(resip::h_From).uri().user()=="amazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallername");
1572     tassert(msg->header(resip::h_From).uri().password().empty());
1573     tassert(msg->header(resip::h_From).uri().host()=="example.net");
1574     tassert(msg->header(resip::h_From).uri().port()==0);
1575     tassert(!(msg->header(resip::h_From).uri().hasEmbedded()));
1576     tassert(msg->header(resip::h_From).uri().numKnownParams()==0);
1577     tassert(msg->header(resip::h_From).uri().numUnknownParams()==0);
1578    
1579     //Call-ID: longreq.onereallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongcallid
1580     tassert(msg->exists(resip::h_CallID));
1581     tassert(msg->header(resip::h_CallID).value()=="longreq.onereallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongcallid");
1582     tassert(msg->header(resip::h_CallID).numKnownParams()==0);
1583     tassert(msg->header(resip::h_CallID).numUnknownParams()==0);
1584    
1585     //CSeq: 3882340 INVITE
1586     tassert(msg->exists(resip::h_CSeq));
1587     tassert(msg->header(resip::h_CSeq).method()==resip::INVITE);
1588     tassert(msg->header(resip::h_CSeq).unknownMethodName()=="INVITE");
1589     tassert(msg->header(resip::h_CSeq).sequence()==3882340);
1590     tassert(msg->header(resip::h_CSeq).numKnownParams()==0);
1591     tassert(msg->header(resip::h_CSeq).numUnknownParams()==0);
1592    
1593     //Unknown headers
1594     //Unknown-LongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLong-Name: unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-value; unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-parameter-name = unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-parameter-value
1595     resip::ExtensionHeader h_UnknownLong("Unknown-LongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLong-Name");
1596    
1597     tassert(msg->exists(h_UnknownLong));
1598     tassert(msg->header(h_UnknownLong).size()==1);
1599     tassert(msg->header(h_UnknownLong).begin()->value()=="unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-value; unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-parameter-name = unknown-longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong-parameter-value");
1600     tassert(msg->header(h_UnknownLong).begin()->numKnownParams()==0);
1601     tassert(msg->header(h_UnknownLong).begin()->numUnknownParams()==0);
1602    
1603     //Vias
1604    
1605     //Via: SIP/2.0/TCP sip33.example.com
1606     //v: SIP/2.0/TCP sip32.example.com
1607     //V: SIP/2.0/TCP sip31.example.com
1608     //Via: SIP/2.0/TCP sip30.example.com
1609     //ViA: SIP/2.0/TCP sip29.example.com
1610     //VIa: SIP/2.0/TCP sip28.example.com
1611     //VIA: SIP/2.0/TCP sip27.example.com
1612     //via: SIP/2.0/TCP sip26.example.com
1613     //viA: SIP/2.0/TCP sip25.example.com
1614     //vIa: SIP/2.0/TCP sip24.example.com
1615     //vIA: SIP/2.0/TCP sip23.example.com
1616     //V : SIP/2.0/TCP sip22.example.com
1617     //v : SIP/2.0/TCP sip21.example.com
1618     //V : SIP/2.0/TCP sip20.example.com
1619     //v : SIP/2.0/TCP sip19.example.com
1620     //Via : SIP/2.0/TCP sip18.example.com
1621     //Via : SIP/2.0/TCP sip17.example.com
1622     //Via: SIP/2.0/TCP sip16.example.com
1623     //Via: SIP/2.0/TCP sip15.example.com
1624     //Via: SIP/2.0/TCP sip14.example.com
1625     //Via: SIP/2.0/TCP sip13.example.com
1626     //Via: SIP/2.0/TCP sip12.example.com
1627     //Via: SIP/2.0/TCP sip11.example.com
1628     //Via: SIP/2.0/TCP sip10.example.com
1629     //Via: SIP/2.0/TCP sip9.example.com
1630     //Via: SIP/2.0/TCP sip8.example.com
1631     //Via: SIP/2.0/TCP sip7.example.com
1632     //Via: SIP/2.0/TCP sip6.example.com
1633     //Via: SIP/2.0/TCP sip5.example.com
1634     //Via: SIP/2.0/TCP sip4.example.com
1635     //Via: SIP/2.0/TCP sip3.example.com
1636     //Via: SIP/2.0/TCP sip2.example.com
1637     //Via: SIP/2.0/TCP sip1.example.com
1638     //Via: SIP/2.0/TCP host.example.com;received=192.0.2.5;branch=verylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongbranchvalue
1639    
1640     tassert(msg->exists(resip::h_Vias));
1641     tassert(msg->header(resip::h_Vias).size()==34);
1642    
1643     int i=33;
1644     resip::Vias::iterator iter;
1645     for(iter=msg->header(resip::h_Vias).begin();
1646     iter!=msg->header(resip::h_Vias).end(); iter++)
1647     {
1648     if(i==0)
1649     {
1650     break;
1651     }
1652     tassert(iter->numKnownParams()==0);
1653     tassert(iter->numUnknownParams()==0);
1654     tassert(iter->protocolName()=="SIP");
1655     tassert(iter->protocolVersion()=="2.0");
1656     tassert(iter->transport()=="TCP");
1657     tassert(iter->sentHost()==resip::Data("sip")+resip::Data(i)+resip::Data(".example.com"));
1658     tassert(iter->sentPort()==0);
1659     i--;
1660     }
1661    
1662     tassert(iter->numKnownParams()==2);
1663     tassert(iter->numUnknownParams()==0);
1664     tassert(iter->protocolName()=="SIP");
1665     tassert(iter->protocolVersion()=="2.0");
1666     tassert(iter->transport()=="TCP");
1667     tassert(iter->sentHost()=="host.example.com");
1668     tassert(iter->sentPort()==0);
1669    
1670     tassert(iter->exists(resip::p_branch));
1671     tassert(!(iter->param(resip::p_branch).hasMagicCookie()));
1672     tassert(iter->param(resip::p_branch).getTransactionId()=="verylonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglongbranchvalue");
1673     tassert(iter->param(resip::p_branch).clientData().empty());
1674    
1675     tassert(iter->exists(resip::p_received));
1676     tassert(iter->param(resip::p_received)=="192.0.2.5");
1677    
1678     //Max-Forwards: 70
1679     tassert(msg->exists(resip::h_MaxForwards));
1680     tassert(msg->header(resip::h_MaxForwards).value()==70);
1681     tassert(msg->header(resip::h_MaxForwards).numKnownParams()==0);
1682     tassert(msg->header(resip::h_MaxForwards).numUnknownParams()==0);
1683    
1684     //Contact: <sip:amazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallername@host5.example.net>
1685     tassert(msg->exists(resip::h_Contacts));
1686     tassert(msg->header(resip::h_Contacts).size()==1);
1687     resip::ParserContainer<resip::NameAddr>::iterator j=msg->header(resip::h_Contacts).begin();
1688    
1689     tassert(j->displayName()=="");
1690     tassert(j->numKnownParams()==0);
1691     tassert(j->numUnknownParams()==0);
1692     tassert(!(j->isAllContacts()));
1693     tassert(j->uri().numKnownParams()==0);
1694     tassert(j->uri().numUnknownParams()==0);
1695     tassert(j->uri().scheme()=="sip");
1696     tassert(j->uri().user()=="amazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallernameamazinglylongcallername");
1697     tassert(j->uri().password().empty());
1698     tassert(j->uri().host()=="host5.example.net");
1699     tassert(j->uri().port()==0);
1700     tassert(!(j->uri().hasEmbedded()));
1701    
1702     //Content-Type: application/sdp
1703     tassert(msg->exists(resip::h_ContentType));
1704     tassert(msg->header(resip::h_ContentType).type()=="application");
1705     tassert(msg->header(resip::h_ContentType).subType()=="sdp");
1706     tassert(msg->header(resip::h_ContentType).numKnownParams()==0);
1707     tassert(msg->header(resip::h_ContentType).numUnknownParams()==0);
1708    
1709     //l: 150
1710     tassert(msg->exists(resip::h_ContentLength));
1711     tassert(msg->header(resip::h_ContentLength).value()==150);
1712     tassert(msg->header(resip::h_ContentLength).numKnownParams()==0);
1713     tassert(msg->header(resip::h_ContentLength).numUnknownParams()==0);
1714    
1715 bcampen 6532 InfoLog(<< "In case longreq:" );
1716     InfoLog(<< "Original text:" << std::endl << txt );
1717     InfoLog(<< "Encoded form:" << std::endl << encoded );
1718     InfoLog(<< "Encoded form of copy:" << std::endl << copyEncoded );
1719 bcampen 6453
1720    
1721    
1722    
1723 bcampen 6448 }
1724    
1725    
1726     void
1727 bcampen 6524 dblreq()
1728 bcampen 6448 {
1729     /*
1730 bcampen 6524 This message contains a single SIP REGISTER request, which ostensibly
1731     arrived over UDP in a single datagram. The packet contains extra
1732     octets after the body (which in this case has zero length). The
1733     extra octets happen to look like a SIP INVITE request, but (per
1734     section 18.3 of [RFC3261]) they are just spurious noise that must be
1735     ignored.
1736 bcampen 6448
1737 bcampen 6524 A SIP element receiving this datagram would handle the REGISTER
1738     request normally and ignore the extra bits that look like an INVITE
1739     request. If the element is a proxy choosing to forward the REGISTER,
1740     the INVITE octets would not appear in the forwarded request.
1741    
1742    
1743    
1744     REGISTER sip:example.com SIP/2.0
1745 bcampen 6448 To: sip:j.user@example.com
1746 bcampen 6524 From: sip:j.user@example.com;tag=43251j3j324
1747     Max-Forwards: 8
1748     I: dblreq.0ha0isndaksdj99sdfafnl3lk233412
1749     Contact: sip:j.user@host.example.com
1750     CSeq: 8 REGISTER
1751     Via: SIP/2.0/UDP 192.0.2.125;branch=z9hG4bKkdjuw23492
1752     Content-Length: 0
1753    
1754    
1755     INVITE sip:joe@example.com SIP/2.0
1756     t: sip:joe@example.com
1757     From: sip:caller@example.net;tag=141334
1758     Max-Forwards: 8
1759     Call-ID: dblreq.0ha0isnda977644900765@192.0.2.15
1760 bcampen 6448 CSeq: 8 INVITE
1761 bcampen 6524 Via: SIP/2.0/UDP 192.0.2.15;branch=z9hG4bKkdjuw380234
1762 bcampen 6448 Content-Type: application/sdp
1763 bcampen 6524 Content-Length: 150
1764 bcampen 6448
1765     v=0
1766     o=mhandley 29739 7272939 IN IP4 192.0.2.15
1767     s=-
1768     c=IN IP4 192.0.2.15
1769     t=0 0
1770     m=audio 49217 RTP/AVP 0 12
1771 bcampen 6524 m =video 3227 RTP/AVP 31
1772 bcampen 6448 a=rtpmap:31 LPC
1773    
1774 bcampen 6524
1775 bcampen 6448 */
1776 bcampen 6524 FILE* fid= fopen("dblreq.dat","r");
1777 bcampen 6448 tassert(fid);
1778     resip::Data txt;
1779     char mBuf[1024];
1780     int result;
1781     while(!feof(fid))
1782     {
1783     result = fread(&mBuf,1,1024,fid);
1784     txt += resip::Data(mBuf,result);
1785     }
1786 bcampen 6450 fclose(fid);
1787 bcampen 6448 resip::SipMessage* msg = resip::SipMessage::make(txt);
1788     tassert_reset();
1789     tassert(msg);
1790     tassert_reset();
1791     if(!msg)
1792     {
1793     return;
1794     }
1795    
1796     std::auto_ptr<resip::SipMessage> message(msg);
1797     msg->parseAllHeaders();
1798    
1799 bcampen 6453 resip::SipMessage copy(*msg);
1800 bcampen 6448
1801 bcampen 6453 resip::Data encoded;
1802     {
1803     resip::oDataStream str(encoded);
1804     msg->encode(str);
1805     }
1806     resip::Data copyEncoded;
1807     {
1808     resip::oDataStream str(copyEncoded);
1809     copy.encode(str);
1810     }
1811 bcampen 6524
1812     //Request Line
1813     //REGISTER sip:example.com SIP/2.0
1814     tassert(msg->header(resip::h_RequestLine).method()==resip::REGISTER);
1815     tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="REGISTER");
1816     tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
1817     tassert(msg->header(resip::h_RequestLine).uri().user()=="");
1818     tassert(msg->header(resip::h_RequestLine).uri().password().empty());
1819     tassert(msg->header(resip::h_RequestLine).uri().host()=="example.com");
1820     tassert(msg->header(resip::h_RequestLine).uri().port()==0);
1821     tassert(!(msg->header(resip::h_RequestLine).uri().hasEmbedded()));
1822     tassert(msg->header(resip::h_RequestLine).uri().numKnownParams()==0);
1823     tassert(msg->header(resip::h_RequestLine).uri().numUnknownParams()==0);
1824     tassert(msg->header(resip::h_RequestLine).getSipVersion()=="SIP/2.0");
1825 bcampen 6448
1826 bcampen 6524 //To: sip:j.user@example.com
1827     tassert(msg->exists(resip::h_To));
1828     tassert(msg->header(resip::h_To).displayName()=="");
1829     tassert(msg->header(resip::h_To).numKnownParams()==0);
1830     tassert(msg->header(resip::h_To).numUnknownParams()==0);
1831     tassert(!(msg->header(resip::h_To).isAllContacts()));
1832     tassert(msg->header(resip::h_To).uri().scheme()=="sip");
1833     tassert(msg->header(resip::h_To).uri().user()=="j.user");
1834     tassert(msg->header(resip::h_To).uri().password().empty());
1835     tassert(msg->header(resip::h_To).uri().host()=="example.com");
1836     tassert(msg->header(resip::h_To).uri().port()==0);
1837     tassert(!(msg->header(resip::h_To).uri().hasEmbedded()));
1838     tassert(msg->header(resip::h_To).uri().numKnownParams()==0);
1839     tassert(msg->header(resip::h_To).uri().numUnknownParams()==0);
1840    
1841     //From: sip:j.user@example.com;tag=43251j3j324
1842     tassert(msg->exists(resip::h_From));
1843     tassert(msg->header(resip::h_From).displayName()=="");
1844     tassert(msg->header(resip::h_From).numKnownParams()==1);
1845     tassert(msg->header(resip::h_From).numUnknownParams()==0);
1846     tassert(msg->header(resip::h_From).exists(resip::p_tag));
1847     tassert(msg->header(resip::h_From).param(resip::p_tag)=="43251j3j324");
1848     tassert(!(msg->header(resip::h_From).isAllContacts()));
1849     tassert(msg->header(resip::h_From).uri().scheme()=="sip");
1850     tassert(msg->header(resip::h_From).uri().user()=="j.user");
1851     tassert(msg->header(resip::h_From).uri().password().empty());
1852     tassert(msg->header(resip::h_From).uri().host()=="example.com");
1853     tassert(msg->header(resip::h_From).uri().port()==0);
1854     tassert(!(msg->header(resip::h_From).uri().hasEmbedded()));
1855     tassert(msg->header(resip::h_From).uri().numKnownParams()==0);
1856     tassert(msg->header(resip::h_From).uri().numUnknownParams()==0);
1857    
1858     //Max-Forwards: 8
1859     tassert(msg->exists(resip::h_MaxForwards));
1860     tassert(msg->header(resip::h_MaxForwards).value()==8);
1861     tassert(msg->header(resip::h_MaxForwards).numKnownParams()==0);
1862     tassert(msg->header(resip::h_MaxForwards).numUnknownParams()==0);
1863    
1864     //I: dblreq.0ha0isndaksdj99sdfafnl3lk233412
1865     tassert(msg->exists(resip::h_CallID));
1866     tassert(msg->header(resip::h_CallID).value()=="dblreq.0ha0isndaksdj99sdfafnl3lk233412");
1867     tassert(msg->header(resip::h_CallID).numKnownParams()==0);
1868     tassert(msg->header(resip::h_CallID).numUnknownParams()==0);
1869    
1870     //Contact: sip:j.user@host.example.com
1871     tassert(msg->exists(resip::h_Contacts));
1872     tassert(msg->header(resip::h_Contacts).size()==1);
1873     resip::ParserContainer<resip::NameAddr>::iterator j=msg->header(resip::h_Contacts).begin();
1874    
1875     tassert(j->displayName()=="");
1876     tassert(j->numKnownParams()==0);
1877     tassert(j->numUnknownParams()==0);
1878     tassert(!(j->isAllContacts()));
1879     tassert(j->uri().numKnownParams()==0);
1880     tassert(j->uri().numUnknownParams()==0);
1881     tassert(j->uri().scheme()=="sip");
1882     tassert(j->uri().user()=="j.user");
1883     tassert(j->uri().password().empty());
1884     tassert(j->uri().host()=="host.example.com");
1885     tassert(j->uri().port()==0);
1886     tassert(!(j->uri().hasEmbedded()));
1887    
1888     //CSeq: 8 REGISTER
1889     tassert(msg->exists(resip::h_CSeq));
1890     tassert(msg->header(resip::h_CSeq).method()==resip::REGISTER);
1891     tassert(msg->header(resip::h_CSeq).unknownMethodName()=="REGISTER");
1892     tassert(msg->header(resip::h_CSeq).sequence()==8);
1893     tassert(msg->header(resip::h_CSeq).numKnownParams()==0);
1894     tassert(msg->header(resip::h_CSeq).numUnknownParams()==0);
1895    
1896     //Via: SIP/2.0/UDP 192.0.2.125;branch=z9hG4bKkdjuw23492
1897     tassert(msg->exists(resip::h_Vias));
1898     tassert(msg->header(resip::h_Vias).size()==1);
1899     resip::ParserContainer<resip::Via>::iterator i=msg->header(resip::h_Vias).begin();
1900    
1901     tassert(i->numKnownParams()==1);
1902     tassert(i->numUnknownParams()==0);
1903     tassert(i->protocolName()=="SIP");
1904     tassert(i->protocolVersion()=="2.0");
1905     tassert(i->transport()=="UDP");
1906     tassert(i->sentHost()=="192.0.2.125");
1907     tassert(i->sentPort()==0);
1908    
1909     tassert(i->exists(resip::p_branch));
1910     tassert(i->param(resip::p_branch).hasMagicCookie());
1911     tassert(i->param(resip::p_branch).getTransactionId()=="kdjuw23492");
1912     tassert(i->param(resip::p_branch).clientData().empty());
1913    
1914     //Content-Length: 0
1915     tassert(msg->exists(resip::h_ContentLength));
1916 bcampen 6989 // .bwc. We configured SipMessage to take the Content-Length seriously
1917 bcampen 6524 tassert(msg->header(resip::h_ContentLength).value()==0);
1918     tassert(msg->header(resip::h_ContentLength).numKnownParams()==0);
1919     tassert(msg->header(resip::h_ContentLength).numUnknownParams()==0);
1920    
1921    
1922    
1923 bcampen 6532 InfoLog(<< "In case dblreq:" );
1924     InfoLog(<< "Original text:" << std::endl << txt );
1925     InfoLog(<< "Encoded form:" << std::endl << encoded );
1926     InfoLog(<< "Encoded form of copy:" << std::endl << copyEncoded );
1927 bcampen 6453
1928    
1929    
1930    
1931 bcampen 6448 }
1932    
1933    
1934     void
1935 bcampen 6524 semiuri()
1936 bcampen 6448 {
1937     /*
1938 bcampen 6524 This request has a semicolon-separated parameter contained in the
1939     "user" part of the Request-URI (whose value contains an escaped @
1940     symbol). Receiving elements will accept this as a well-formed
1941     message. The Request-URI will parse so that the user part is
1942     "user;par=u@example.net".
1943 bcampen 6448
1944 bcampen 6524 OPTIONS sip:user;par=u%40example.net@example.com SIP/2.0
1945     To: sip:j_user@example.com
1946    </