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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9367 - (show annotations) (download)
Wed Feb 1 16:12:20 2012 UTC (7 years, 9 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 #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 #include "resip/stack/ExtensionParameter.hxx"
9 #include "resip/stack/ParserCategories.hxx"
10 #include "resip/stack/ParameterTypes.hxx"
11 #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 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 tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="INVITE");
144 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 tassert(msg->header(resip::h_CSeq).unknownMethodName()=="INVITE");
213 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 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
333
334
335
336 }
337
338
339 void
340 intmeth()
341 {
342 #if 0
343 /*
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 #endif
403
404 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 tassert(msg->header(resip::h_RequestLine).method()==resip::UNKNOWN);
442 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 tassert(msg->header(resip::h_CSeq).method()==resip::UNKNOWN);
541 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 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
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 tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="INVITE");
689 tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
690 // ?bwc? Is it appropriate to use a one-size-fits-all approach to unescaping
691 // 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 tassert(msg->header(resip::h_RequestLine).uri().user()=="sips%3Auser%40example.com");
697 tassert_reset();
698 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 tassert(msg->header(resip::h_To).uri().user()=="user");
712 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 // ?bwc? ' ' is not legal in a userpart, but the internal
727 // representation contains it. Is this appropriate?
728 tassert(msg->header(resip::h_From).uri().user()=="I%20have%20spaces");
729 tassert_reset();
730 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 tassert(msg->header(resip::h_CSeq).unknownMethodName()=="INVITE");
763 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 tassert(i->param(resip::p_branch).hasMagicCookie());
783 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 tassert(msg->header(resip::h_Contacts).begin()->uri().user()=="caller");
802 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 // ?bwc? These params have escaped stuff in them; is it mandatory that we
811 // 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 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
831
832
833
834 }
835
836
837 void
838 escnull()
839 {
840 /*
841 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
848 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 Max-Forwards: 70
852 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
859
860 */
861 FILE* fid= fopen("escnull.dat","r");
862 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 fclose(fid);
872 resip::SipMessage* msg = resip::SipMessage::make(txt);
873 tassert_reset();
874 tassert(msg);
875 tassert_reset();
876 if(!msg)
877 {
878 return;
879 }
880
881 std::auto_ptr<resip::SipMessage> message(msg);
882 msg->parseAllHeaders();
883
884 resip::SipMessage copy(*msg);
885
886 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
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
911 //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
943 //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
1001 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 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
1030
1031
1032
1033 }
1034
1035
1036 void
1037 esc02()
1038 {
1039 /*
1040 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
1044 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 l: 0
1068
1069
1070 */
1071 FILE* fid= fopen("esc02.dat","r");
1072 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 fclose(fid);
1082 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 resip::SipMessage copy(*msg);
1095
1096 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
1107 //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 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
1242
1243
1244
1245 }
1246
1247
1248 void
1249 lwsdisp()
1250 {
1251 /*
1252 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
1258 OPTIONS sip:user@example.com SIP/2.0
1259 To: sip:user@example.com
1260 From: caller<sip:caller@example.com>;tag=323
1261 Max-Forwards: 70
1262 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
1267
1268 */
1269 FILE* fid= fopen("lwsdisp.dat","r");
1270 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 fclose(fid);
1280 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 resip::SipMessage copy(*msg);
1293
1294 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
1305 //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 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
1400
1401
1402
1403 }
1404
1405
1406 void
1407 longreq()
1408 {
1409 /*
1410 This well-formed request contains header fields with many values and
1411 values that are very long. Features include the following:
1412
1413 o The To header field has a long display name, and long uri
1414 parameter names and values.
1415
1416 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 */
1476 FILE* fid= fopen("longreq.dat","r");
1477 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 fclose(fid);
1487 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 resip::SipMessage copy(*msg);
1500
1501 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
1512 //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 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
1720
1721
1722
1723 }
1724
1725
1726 void
1727 dblreq()
1728 {
1729 /*
1730 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
1737 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 To: sip:j.user@example.com
1746 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 CSeq: 8 INVITE
1761 Via: SIP/2.0/UDP 192.0.2.15;branch=z9hG4bKkdjuw380234
1762 Content-Type: application/sdp
1763 Content-Length: 150
1764
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 m =video 3227 RTP/AVP 31
1772 a=rtpmap:31 LPC
1773
1774
1775 */
1776 FILE* fid= fopen("dblreq.dat","r");
1777 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 fclose(fid);
1787 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 resip::SipMessage copy(*msg);
1800
1801 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
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
1826 //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 // .bwc. We configured SipMessage to take the Content-Length seriously
1917 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 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
1928
1929
1930
1931 }
1932
1933
1934 void
1935 semiuri()
1936 {
1937 /*
1938 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
1944 OPTIONS sip:user;par=u%40example.net@example.com SIP/2.0
1945 To: sip:j_user@example.com
1946 From: sip:caller@example.org;tag=33242
1947 Max-Forwards: 3
1948 Call-ID: semiuri.0ha0isndaksdj
1949 CSeq: 8 OPTIONS
1950 Accept: application/sdp, application/pkcs7-mime,
1951 multipart/mixed, multipart/signed,
1952 message/sip, message/sipfrag
1953 Via: SIP/2.0/UDP 192.0.2.1;branch=z9hG4bKkdjuw
1954 l: 0
1955
1956
1957 */
1958 FILE* fid= fopen("semiuri.dat","r");
1959 tassert(fid);
1960 resip::Data txt;
1961 char mBuf[1024];
1962 int result;
1963 while(!feof(fid))
1964 {
1965 result = fread(&mBuf,1,1024,fid);
1966 txt += resip::Data(mBuf,result);
1967 }
1968 fclose(fid);
1969 resip::SipMessage* msg = resip::SipMessage::make(txt);
1970 tassert_reset();
1971 tassert(msg);
1972 tassert_reset();
1973 if(!msg)
1974 {
1975 return;
1976 }
1977
1978 std::auto_ptr<resip::SipMessage> message(msg);
1979 msg->parseAllHeaders();
1980
1981 resip::SipMessage copy(*msg);
1982
1983 resip::Data encoded;
1984 {
1985 resip::oDataStream str(encoded);
1986 msg->encode(str);
1987 }
1988 resip::Data copyEncoded;
1989 {
1990 resip::oDataStream str(copyEncoded);
1991 copy.encode(str);
1992 }
1993
1994 //Request Line
1995 //OPTIONS sip:user;par=u%40example.net@example.com SIP/2.0
1996 tassert(msg->header(resip::h_RequestLine).method()==resip::OPTIONS);
1997 tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="OPTIONS");
1998 tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
1999 // ?bwc? Need to determine how escaped stuff should be represented internally
2000 tassert(msg->header(resip::h_RequestLine).uri().user()=="user;par=u%40example.net");
2001 tassert_reset();
2002 tassert(msg->header(resip::h_RequestLine).uri().password().empty());
2003 tassert(msg->header(resip::h_RequestLine).uri().host()=="example.com");
2004 tassert(msg->header(resip::h_RequestLine).uri().port()==0);
2005 tassert(!(msg->header(resip::h_RequestLine).uri().hasEmbedded()));
2006 tassert(msg->header(resip::h_RequestLine).uri().numKnownParams()==0);
2007 tassert(msg->header(resip::h_RequestLine).uri().numUnknownParams()==0);
2008 tassert(msg->header(resip::h_RequestLine).getSipVersion()=="SIP/2.0");
2009
2010 //To: sip:j_user@example.com
2011 tassert(msg->exists(resip::h_To));
2012 tassert(msg->header(resip::h_To).displayName()=="");
2013 tassert(msg->header(resip::h_To).numKnownParams()==0);
2014 tassert(msg->header(resip::h_To).numUnknownParams()==0);
2015 tassert(!(msg->header(resip::h_To).isAllContacts()));
2016 tassert(msg->header(resip::h_To).uri().scheme()=="sip");
2017 tassert(msg->header(resip::h_To).uri().user()=="j_user");
2018 tassert(msg->header(resip::h_To).uri().password().empty());
2019 tassert(msg->header(resip::h_To).uri().host()=="example.com");
2020 tassert(msg->header(resip::h_To).uri().port()==0);
2021 tassert(!(msg->header(resip::h_To).uri().hasEmbedded()));
2022 tassert(msg->header(resip::h_To).uri().numKnownParams()==0);
2023 tassert(msg->header(resip::h_To).uri().numUnknownParams()==0);
2024
2025 //From: sip:caller@example.org;tag=33242
2026 tassert(msg->exists(resip::h_From));
2027 tassert(msg->header(resip::h_From).displayName()=="");
2028 tassert(msg->header(resip::h_From).numKnownParams()==1);
2029 tassert(msg->header(resip::h_From).numUnknownParams()==0);
2030 tassert(msg->header(resip::h_From).exists(resip::p_tag));
2031 tassert(msg->header(resip::h_From).param(resip::p_tag)=="33242");
2032 tassert(!(msg->header(resip::h_From).isAllContacts()));
2033 tassert(msg->header(resip::h_From).uri().scheme()=="sip");
2034 tassert(msg->header(resip::h_From).uri().user()=="caller");
2035 tassert(msg->header(resip::h_From).uri().password().empty());
2036 tassert(msg->header(resip::h_From).uri().host()=="example.org");
2037 tassert(msg->header(resip::h_From).uri().port()==0);
2038 tassert(!(msg->header(resip::h_From).uri().hasEmbedded()));
2039 tassert(msg->header(resip::h_From).uri().numKnownParams()==0);
2040 tassert(msg->header(resip::h_From).uri().numUnknownParams()==0);
2041
2042 //Max-Forwards: 3
2043 tassert(msg->exists(resip::h_MaxForwards));
2044 tassert(msg->header(resip::h_MaxForwards).value()==3);
2045 tassert(msg->header(resip::h_MaxForwards).numKnownParams()==0);
2046 tassert(msg->header(resip::h_MaxForwards).numUnknownParams()==0);
2047
2048 //Call-ID: semiuri.0ha0isndaksdj
2049 tassert(msg->exists(resip::h_CallID));
2050 tassert(msg->header(resip::h_CallID).value()=="semiuri.0ha0isndaksdj");
2051 tassert(msg->header(resip::h_CallID).numKnownParams()==0);
2052 tassert(msg->header(resip::h_CallID).numUnknownParams()==0);
2053
2054 //CSeq: 8 OPTIONS
2055 tassert(msg->exists(resip::h_CSeq));
2056 tassert(msg->header(resip::h_CSeq).method()==resip::OPTIONS);
2057 tassert(msg->header(resip::h_CSeq).unknownMethodName()=="OPTIONS");
2058 tassert(msg->header(resip::h_CSeq).sequence()==8);
2059 tassert(msg->header(resip::h_CSeq).numKnownParams()==0);
2060 tassert(msg->header(resip::h_CSeq).numUnknownParams()==0);
2061
2062 //Accept: application/sdp, application/pkcs7-mime,
2063 // multipart/mixed, multipart/signed,
2064 // message/sip, message/sipfrag
2065 tassert(msg->exists(resip::h_Accepts));
2066 tassert(msg->header(resip::h_Accepts).size()==6);
2067
2068 resip::Mimes::iterator a=msg->header(resip::h_Accepts).begin();
2069
2070 tassert(a->type()=="application");
2071 tassert(a->subType()=="sdp");
2072 tassert(a->numKnownParams()==0);
2073 tassert(a->numUnknownParams()==0);
2074 a++;
2075
2076 tassert(a->type()=="application");
2077 tassert(a->subType()=="pkcs7-mime");
2078 tassert(a->numKnownParams()==0);
2079 tassert(a->numUnknownParams()==0);
2080 a++;
2081
2082 tassert(a->type()=="multipart");
2083 tassert(a->subType()=="mixed");
2084 tassert(a->numKnownParams()==0);
2085 tassert(a->numUnknownParams()==0);
2086 a++;
2087
2088 tassert(a->type()=="multipart");
2089 tassert(a->subType()=="signed");
2090 tassert(a->numKnownParams()==0);
2091 tassert(a->numUnknownParams()==0);
2092 a++;
2093
2094 tassert(a->type()=="message");
2095 tassert(a->subType()=="sip");
2096 tassert(a->numKnownParams()==0);
2097 tassert(a->numUnknownParams()==0);
2098 a++;
2099
2100 tassert(a->type()=="message");
2101 tassert(a->subType()=="sipfrag");
2102 tassert(a->numKnownParams()==0);
2103 tassert(a->numUnknownParams()==0);
2104
2105 //Via: SIP/2.0/UDP 192.0.2.1;branch=z9hG4bKkdjuw
2106 tassert(msg->exists(resip::h_Vias));
2107 tassert(msg->header(resip::h_Vias).size()==1);
2108 resip::ParserContainer<resip::Via>::iterator i=msg->header(resip::h_Vias).begin();
2109
2110 tassert(i->numKnownParams()==1);
2111 tassert(i->numUnknownParams()==0);
2112 tassert(i->protocolName()=="SIP");
2113 tassert(i->protocolVersion()=="2.0");
2114 tassert(i->transport()=="UDP");
2115 tassert(i->sentHost()=="192.0.2.1");
2116 tassert(i->sentPort()==0);
2117
2118 tassert(i->exists(resip::p_branch));
2119 tassert(i->param(resip::p_branch).hasMagicCookie());
2120 tassert(i->param(resip::p_branch).getTransactionId()=="kdjuw");
2121 tassert(i->param(resip::p_branch).clientData().empty());
2122
2123 //l: 0
2124 tassert(msg->exists(resip::h_ContentLength));
2125 tassert(msg->header(resip::h_ContentLength).value()==0);
2126 tassert(msg->header(resip::h_ContentLength).numKnownParams()==0);
2127 tassert(msg->header(resip::h_ContentLength).numUnknownParams()==0);
2128
2129
2130
2131 InfoLog(<< "In case semiuri:" );
2132 InfoLog(<< "Original text:" << std::endl << txt );
2133 InfoLog(<< "Encoded form:" << std::endl << encoded );
2134 InfoLog(<< "Encoded form of copy:" << std::endl << copyEncoded );
2135
2136
2137
2138
2139 }
2140
2141
2142 void
2143 transports()
2144 {
2145 /*
2146 This request contains Via header field values with all known
2147 transport types and exercises the transport extension mechanism.
2148 Parsers must accept this message as well formed. Elements receiving
2149 this message would process it exactly as if the 2nd and subsequent
2150 header field values specified UDP (or other transport).
2151
2152 OPTIONS sip:user@example.com SIP/2.0
2153 To: sip:user@example.com
2154 From: <sip:caller@example.com>;tag=323
2155 Max-Forwards: 70
2156 Call-ID: transports.kijh4akdnaqjkwendsasfdj
2157 Accept: application/sdp
2158 CSeq: 60 OPTIONS
2159 Via: SIP/2.0/UDP t1.example.com;branch=z9hG4bKkdjuw
2160 Via: SIP/2.0/SCTP t2.example.com;branch=z9hG4bKklasjdhf
2161 Via: SIP/2.0/TLS t3.example.com;branch=z9hG4bK2980unddj
2162 Via: SIP/2.0/UNKNOWN t4.example.com;branch=z9hG4bKasd0f3en
2163 Via: SIP/2.0/TCP t5.example.com;branch=z9hG4bK0a9idfnee
2164 l: 0
2165
2166
2167 */
2168 FILE* fid= fopen("transports.dat","r");
2169 tassert(fid);
2170 resip::Data txt;
2171 char mBuf[1024];
2172 int result;
2173 while(!feof(fid))
2174 {
2175 result = fread(&mBuf,1,1024,fid);
2176 txt += resip::Data(mBuf,result);
2177 }
2178 fclose(fid);
2179 resip::SipMessage* msg = resip::SipMessage::make(txt);
2180 tassert_reset();
2181 tassert(msg);
2182 tassert_reset();
2183 if(!msg)
2184 {
2185 return;
2186 }
2187
2188 std::auto_ptr<resip::SipMessage> message(msg);
2189 msg->parseAllHeaders();
2190
2191 resip::SipMessage copy(*msg);
2192
2193 resip::Data encoded;
2194 {
2195 resip::oDataStream str(encoded);
2196 msg->encode(str);
2197 }
2198 resip::Data copyEncoded;
2199 {
2200 resip::oDataStream str(copyEncoded);
2201 copy.encode(str);
2202 }
2203
2204 //Request Line
2205 //OPTIONS sip:user@example.com SIP/2.0
2206 tassert(msg->header(resip::h_RequestLine).method()==resip::OPTIONS);
2207 tassert(msg->header(resip::h_RequestLine).unknownMethodName()=="OPTIONS");
2208 tassert(msg->header(resip::h_RequestLine).uri().scheme()=="sip");
2209 tassert(msg->header(resip::h_RequestLine).uri().user()=="user");
2210 tassert_reset();
2211 tassert(msg->header(resip::h_RequestLine).uri().password().empty());
2212 tassert(msg->header(resip::h_RequestLine).uri().host()=="example.com");
2213 tassert(msg->header(resip::h_RequestLine).uri().port()==0);
2214 tassert(!(msg->header(resip::h_RequestLine).uri().hasEmbedded()));
2215 tassert(msg->header(resip::h_RequestLine).uri().numKnownParams()==0);
2216 tassert(msg->header(resip::h_RequestLine).uri().numUnknownParams()==0);
2217 tassert(msg->header(resip::h_RequestLine).getSipVersion()=="SIP/2.0");
2218
2219 //To: sip:user@example.com
2220 tassert(msg->exists(resip::h_To));
2221 tassert(msg->header(resip::h_To).displayName()=="");
2222 tassert(msg->header(resip::h_To).numKnownParams()==0);
2223 tassert(msg->header(resip::h_To).numUnknownParams()==0);
2224 tassert(!(msg->header(resip::h_To).isAllContacts()));
2225 tassert(msg->header(resip::h_To).uri().scheme()=="sip");
2226 tassert(msg->header(resip::h_To).uri().user()=="user");
2227 tassert(msg->header(resip::h_To).uri().password().empty());
2228 tassert(msg->header(resip::h_To).uri().host()=="example.com");
2229 tassert(msg->header(resip::h_To).uri().port()==0);
2230 tassert(!(msg->header(resip::h_To).uri().hasEmbedded()));
2231 tassert(msg->header(resip::h_To).uri().numKnownParams()==0);
2232 tassert(msg->header(resip::h_To).uri().numUnknownParams()==0);
2233
2234 //From: <sip:caller@example.com>;tag=323
2235 tassert(msg->exists(resip::h_From));
2236 tassert(msg->header(resip::h_From).displayName()=="");
2237 tassert(msg->header(resip::h_From).numKnownParams()==1);
2238 tassert(msg->header(resip::h_From).numUnknownParams()==0);
2239 tassert(msg->header(resip::h_From).exists(resip::p_tag));
2240 tassert(msg->header(resip::h_From).param(resip::p_tag)=="323");
2241 tassert(!(msg->header(resip::h_From).isAllContacts()));
2242 tassert(msg->header(resip::h_From).uri().scheme()=="sip");
2243 tassert(msg->header(resip::h_From).uri().user()=="caller");
2244 tassert(msg->header(resip::h_From).uri().password().empty());
2245 tassert(msg->header(resip::h_From).uri().host()=="example.com");
2246 tassert(msg->header(resip::h_From).uri().port()==0);
2247 tassert(!(msg->header(resip::h_From).uri().hasEmbedded()));
2248 tassert(msg->header(resip::h_From).uri().numKnownParams()==0);
2249 tassert(msg->header(resip::h_From).uri().numUnknownParams()==0);
2250
2251 //Max-Forwards: 70
2252 tassert(msg->exists(resip::h_MaxForwards));
2253 tassert(msg->header(resip::h_MaxForwards).value()==70);
2254 tassert(msg->header(resip::h_MaxForwards).numKnownParams()==0);
2255 tassert(msg->header(resip::h_MaxForwards).numUnknownParams()==0);
2256
2257 //Call-ID: transports.kijh4akdnaqjkwendsasfdj
2258 tassert(msg->exists(resip::h_CallID));
2259 tassert(msg->header(resip::h_CallID).value()=="transports.kijh4akdnaqjkwendsasfdj");
2260 tassert(msg->header(resip::h_CallID).numKnownParams()==0);
2261 tassert(msg->header(resip::h_CallID).numUnknownParams()==0);
2262
2263 //Accept: application/sdp
2264 tassert(msg->exists(resip::h_Accepts));
2265 tassert(msg->header(resip::h_Accepts).size()==1);
2266
2267 resip::Mimes::iterator a=msg->header(resip::h_Accepts).begin();
2268
2269 tassert(a->type()=="application");
2270 tassert(a->subType()=="sdp");
2271 tassert(a->numKnownParams()==0);
2272 tassert(a->numUnknownParams()==0);
2273
2274 //CSeq: 60 OPTIONS
2275 tassert(msg->exists(resip::h_CSeq));
2276 tassert(msg->header(resip::h_CSeq).method()==resip::OPTIONS);
2277 tassert(msg->header(resip::h_CSeq).unknownMethodName()=="OPTIONS");
2278 tassert(msg->header(resip::h_CSeq).sequence()==60);
2279 tassert(msg->header(resip::h_CSeq).numKnownParams()==0);
2280 tassert(msg->header(resip::h_CSeq).numUnknownParams()==0);
2281
2282 //Vias
2283 tassert(msg->exists(resip::h_Vias));
2284 tassert(msg->header(resip::h_Vias).size()==5);
2285 resip::ParserContainer<resip::Via>::iterator v=msg->header(resip::h_Vias).begin();
2286
2287 //Via: SIP/2.0/UDP t1.example.com;branch=z9hG4bKkdjuw
2288 tassert(v->numKnownParams()==1);
2289 tassert(v->numUnknownParams()==0);
2290 tassert(v->protocolName()=="SIP");
2291 tassert(v->protocolVersion()=="2.0");
2292 tassert(v->transport()=="UDP");
2293 tassert(v->sentHost()=="t1.example.com");
2294 tassert(v->sentPort()==0);
2295
2296 tassert(v->exists(resip::p_branch));
2297 tassert(v->param(resip::p_branch).hasMagicCookie());
2298 tassert(v->param(resip::p_branch).getTransactionId()=="kdjuw");
2299 tassert(v->param(resip::p_branch).clientData().empty());
2300
2301 v++;
2302 //Via: SIP/2.0/SCTP t2.example.com;branch=z9hG4bKklasjdhf
2303 tassert(v->numKnownParams()==1);
2304 tassert(v->numUnknownParams()==0);
2305 tassert(v->protocolName()=="SIP");
2306 tassert(v->protocolVersion()=="2.0");
2307 tassert(v->transport()=="SCTP");
2308 tassert(v->sentHost()=="t2.example.com");
2309 tassert(v->sentPort()==0);
2310
2311 tassert(v->exists(resip::p_branch));
2312 tassert(v->param(resip::p_branch).hasMagicCookie());
2313 tassert(v->param(resip::p_branch).getTransactionId()=="klasjdhf");
2314 tassert(v->param(resip::p_branch).clientData().empty());
2315
2316 v++;
2317 //Via: SIP/2.0/TLS t3.example.com;branch=z9hG4bK2980unddj
2318 tassert(v->numKnownParams()==1);
2319 tassert(v->numUnknownParams()==0);
2320 tassert(v->protocolName()=="SIP");
2321 tassert(v->protocolVersion()=="2.0");
2322 tassert(v->transport()=="TLS");
2323 tassert(v->sentHost()=="t3.example.com");
2324 tassert(v->sentPort()==0);
2325
2326 tassert(v->exists(resip::p_branch));
2327 tassert(v->param(resip::p_branch).hasMagicCookie());
2328 tassert(v->param(resip::p_branch).getTransactionId()=="2980unddj");
2329 tassert(v->param(resip::p_branch).clientData().empty());
2330