/src/resiprocate/resip/stack/SipMessage.cxx
Line | Count | Source (jump to first uncovered line) |
1 | | #if defined(HAVE_CONFIG_H) |
2 | | #include "config.h" |
3 | | #endif |
4 | | |
5 | | #include "resip/stack/Contents.hxx" |
6 | | #include "resip/stack/Embedded.hxx" |
7 | | #include "resip/stack/OctetContents.hxx" |
8 | | #include "resip/stack/HeaderFieldValueList.hxx" |
9 | | #include "resip/stack/SipMessage.hxx" |
10 | | #include "resip/stack/ExtensionHeader.hxx" |
11 | | #include "rutil/Coders.hxx" |
12 | | #include "rutil/CountStream.hxx" |
13 | | #include "rutil/Logger.hxx" |
14 | | #include "rutil/MD5Stream.hxx" |
15 | | #include "rutil/compat.hxx" |
16 | | #include "rutil/vmd5.hxx" |
17 | | #include "rutil/Coders.hxx" |
18 | | #include "rutil/Random.hxx" |
19 | | #include "rutil/ParseBuffer.hxx" |
20 | | #include "resip/stack/MsgHeaderScanner.hxx" |
21 | | //#include "rutil/WinLeakCheck.hxx" // not compatible with placement new used below |
22 | | #include <utility> |
23 | | |
24 | | using namespace resip; |
25 | | using namespace std; |
26 | | |
27 | | #define RESIPROCATE_SUBSYSTEM Subsystem::SIP |
28 | | |
29 | | bool SipMessage::checkContentLength=true; |
30 | | |
31 | | SipMessage::SipMessage(const Tuple *receivedTransportTuple) |
32 | 9.62k | : mIsDecorated(false), |
33 | 9.62k | mIsBadAck200(false), |
34 | 9.62k | mIsExternal(receivedTransportTuple != 0), // may be modified later by setFromTU or setFromExternal |
35 | 9.62k | mHeaders(StlPoolAllocator<HeaderFieldValueList*, PoolBase >(&mPool)), |
36 | | #ifndef __SUNPRO_CC |
37 | 9.62k | mUnknownHeaders(StlPoolAllocator<std::pair<Data, HeaderFieldValueList*>, PoolBase >(&mPool)), |
38 | | #else |
39 | | mUnknownHeaders(), |
40 | | #endif |
41 | 9.62k | mRequest(false), |
42 | 9.62k | mResponse(false), |
43 | 9.62k | mInvalid(false), |
44 | 9.62k | mCreatedTime(Timer::getTimeMicroSec()), |
45 | 9.62k | mTlsDomain(Data::Empty) |
46 | 9.62k | { |
47 | 9.62k | if(receivedTransportTuple) |
48 | 0 | { |
49 | 0 | mReceivedTransportTuple = *receivedTransportTuple; |
50 | 0 | } |
51 | | // !bwc! TODO make this tunable |
52 | 9.62k | mHeaders.reserve(16); |
53 | 9.62k | clear(); |
54 | 9.62k | } |
55 | | |
56 | | SipMessage::SipMessage(const SipMessage& from) |
57 | 0 | : mHeaders(StlPoolAllocator<HeaderFieldValueList*, PoolBase >(&mPool)), |
58 | | #ifndef __SUNPRO_CC |
59 | 0 | mUnknownHeaders(StlPoolAllocator<std::pair<Data, HeaderFieldValueList*>, PoolBase >(&mPool)), |
60 | | #else |
61 | | mUnknownHeaders(), |
62 | | #endif |
63 | 0 | mCreatedTime(Timer::getTimeMicroSec()) |
64 | 0 | { |
65 | 0 | init(from); |
66 | 0 | } |
67 | | |
68 | | Message* |
69 | | SipMessage::clone() const |
70 | 0 | { |
71 | 0 | return new SipMessage(*this); |
72 | 0 | } |
73 | | |
74 | | SipMessage& |
75 | | SipMessage::operator=(const SipMessage& rhs) |
76 | 0 | { |
77 | 0 | if (this != &rhs) |
78 | 0 | { |
79 | 0 | freeMem(); |
80 | 0 | init(rhs); |
81 | 0 | } |
82 | 0 | return *this; |
83 | 0 | } |
84 | | |
85 | | SipMessage::~SipMessage() |
86 | 9.62k | { |
87 | | //#define DINKYPOOL_PROFILING |
88 | | #ifdef DINKYPOOL_PROFILING |
89 | | if (mPool.getHeapBytes() > 0) |
90 | | { |
91 | | InfoLog(<< "SipMessage mPool filled up and used " << mPool.getHeapBytes() << " bytes on the heap, consider increasing the mPool size (sizeof SipMessage is " << sizeof(SipMessage) << " bytes): msg=" |
92 | | << std::endl << *this); |
93 | | } |
94 | | else |
95 | | { |
96 | | InfoLog(<< "SipMessage mPool used " << mPool.getPoolBytes() << " bytes of a total " << mPool.getPoolSizeBytes() << " bytes (sizeof SipMessage is " << sizeof(SipMessage) << " bytes): msg=" |
97 | | << std::endl << *this); |
98 | | } |
99 | | #endif |
100 | 9.62k | freeMem(); |
101 | 9.62k | } |
102 | | |
103 | | void |
104 | | SipMessage::clear(bool leaveResponseStuff) |
105 | 9.62k | { |
106 | 9.62k | if(!leaveResponseStuff) |
107 | 9.62k | { |
108 | 9.62k | memset(mHeaderIndices,0,sizeof(mHeaderIndices)); |
109 | 9.62k | clearHeaders(); |
110 | | |
111 | | // !bwc! The "invalid" 0 index. |
112 | 9.62k | mHeaders.push_back(getEmptyHfvl()); |
113 | 9.62k | mBufferList.clear(); |
114 | 9.62k | } |
115 | | |
116 | 9.62k | mUnknownHeaders.clear(); |
117 | | |
118 | 9.62k | mStartLine = 0; |
119 | 9.62k | mContents = 0; |
120 | 9.62k | mContentsHfv.clear(); |
121 | 9.62k | mForceTarget = 0; |
122 | 9.62k | mReason=0; |
123 | 9.62k | mOutboundDecorators.clear(); |
124 | 9.62k | } |
125 | | |
126 | | void |
127 | | SipMessage::init(const SipMessage& rhs) |
128 | 0 | { |
129 | 0 | clear(); |
130 | 0 | mIsDecorated = rhs.mIsDecorated; |
131 | 0 | mIsBadAck200 = rhs.mIsBadAck200; |
132 | 0 | mIsExternal = rhs.mIsExternal; |
133 | 0 | mReceivedTransportTuple = rhs.mReceivedTransportTuple; |
134 | 0 | mSource = rhs.mSource; |
135 | 0 | mDestination = rhs.mDestination; |
136 | 0 | mRFC2543TransactionId = rhs.mRFC2543TransactionId; |
137 | 0 | mRequest = rhs.mRequest; |
138 | 0 | mResponse = rhs.mResponse; |
139 | 0 | mInvalid = rhs.mInvalid; |
140 | 0 | if(!rhs.mReason) |
141 | 0 | { |
142 | 0 | mReason=0; |
143 | 0 | } |
144 | 0 | else |
145 | 0 | { |
146 | 0 | mReason = new Data(*rhs.mReason); |
147 | 0 | } |
148 | 0 | mTlsDomain = rhs.mTlsDomain; |
149 | |
|
150 | 0 | memcpy(&mHeaderIndices,&rhs.mHeaderIndices,sizeof(mHeaderIndices)); |
151 | | |
152 | | // .bwc. Clear out the pesky invalid 0 index. |
153 | 0 | clearHeaders(); |
154 | 0 | mHeaders.reserve(rhs.mHeaders.size()); |
155 | 0 | for (TypedHeaders::const_iterator i = rhs.mHeaders.begin(); |
156 | 0 | i != rhs.mHeaders.end(); i++) |
157 | 0 | { |
158 | 0 | mHeaders.push_back(getCopyHfvl(**i)); |
159 | 0 | } |
160 | |
|
161 | 0 | for (UnknownHeaders::const_iterator i = rhs.mUnknownHeaders.begin(); |
162 | 0 | i != rhs.mUnknownHeaders.end(); i++) |
163 | 0 | { |
164 | 0 | mUnknownHeaders.push_back(pair<Data, HeaderFieldValueList*>( |
165 | 0 | i->first, |
166 | 0 | getCopyHfvl(*i->second))); |
167 | 0 | } |
168 | 0 | if (rhs.mStartLine != 0) |
169 | 0 | { |
170 | 0 | mStartLine = rhs.mStartLine->clone(mStartLineMem); |
171 | 0 | } |
172 | 0 | if (rhs.mContents != 0) |
173 | 0 | { |
174 | 0 | mContents = rhs.mContents->clone(); |
175 | 0 | } |
176 | 0 | else if (rhs.mContentsHfv.getBuffer() != 0) |
177 | 0 | { |
178 | 0 | mContentsHfv.copyWithPadding(rhs.mContentsHfv); |
179 | 0 | } |
180 | 0 | else |
181 | 0 | { |
182 | | // no body to copy |
183 | 0 | } |
184 | 0 | if (rhs.mForceTarget != 0) |
185 | 0 | { |
186 | 0 | mForceTarget = new Uri(*rhs.mForceTarget); |
187 | 0 | } |
188 | |
|
189 | 0 | if (rhs.mSecurityAttributes.get()) |
190 | 0 | { |
191 | |
|
192 | 0 | if (!mSecurityAttributes.get()) |
193 | 0 | { |
194 | 0 | SecurityAttributes* attr = new SecurityAttributes(); |
195 | 0 | mSecurityAttributes.reset(attr); |
196 | 0 | } |
197 | |
|
198 | 0 | if (rhs.mSecurityAttributes->isEncrypted()) |
199 | 0 | { |
200 | 0 | mSecurityAttributes->setEncrypted(); |
201 | 0 | } |
202 | 0 | mSecurityAttributes->setSignatureStatus(rhs.mSecurityAttributes->getSignatureStatus()); |
203 | 0 | mSecurityAttributes->setIdentity(rhs.mSecurityAttributes->getIdentity()); |
204 | 0 | mSecurityAttributes->setIdentityStrength(rhs.mSecurityAttributes->getIdentityStrength()); |
205 | 0 | mSecurityAttributes->setSigner(rhs.mSecurityAttributes->getSigner()); |
206 | 0 | mSecurityAttributes->setOutgoingEncryptionLevel(rhs.mSecurityAttributes->getOutgoingEncryptionLevel()); |
207 | 0 | mSecurityAttributes->setEncryptionPerformed(rhs.mSecurityAttributes->encryptionPerformed()); |
208 | 0 | } |
209 | 0 | else |
210 | 0 | { |
211 | 0 | if (mSecurityAttributes.get()) |
212 | 0 | { |
213 | 0 | mSecurityAttributes.reset(); |
214 | 0 | } |
215 | 0 | } |
216 | |
|
217 | 0 | for(std::vector<MessageDecorator*>::const_iterator i=rhs.mOutboundDecorators.begin(); i!=rhs.mOutboundDecorators.end();++i) |
218 | 0 | { |
219 | 0 | mOutboundDecorators.push_back((*i)->clone()); |
220 | 0 | } |
221 | 0 | } |
222 | | |
223 | | void |
224 | | SipMessage::freeMem(bool leaveResponseStuff) |
225 | 9.62k | { |
226 | 9.62k | for (UnknownHeaders::iterator i = mUnknownHeaders.begin(); |
227 | 23.7k | i != mUnknownHeaders.end(); i++) |
228 | 14.0k | { |
229 | 14.0k | freeHfvl(i->second); |
230 | 14.0k | } |
231 | | |
232 | 9.62k | if(!leaveResponseStuff) |
233 | 9.62k | { |
234 | 9.62k | clearHeaders(); |
235 | | |
236 | 9.62k | for (vector<char*>::iterator i = mBufferList.begin(); |
237 | 1.30M | i != mBufferList.end(); i++) |
238 | 1.29M | { |
239 | 1.29M | delete [] *i; |
240 | 1.29M | } |
241 | 9.62k | } |
242 | | |
243 | 9.62k | if(mStartLine) |
244 | 562 | { |
245 | 562 | mStartLine->~StartLine(); |
246 | 562 | mStartLine=0; |
247 | 562 | } |
248 | | |
249 | 9.62k | delete mContents; |
250 | 9.62k | delete mForceTarget; |
251 | 9.62k | delete mReason; |
252 | | |
253 | 9.62k | for(std::vector<MessageDecorator*>::iterator i=mOutboundDecorators.begin(); |
254 | 9.62k | i!=mOutboundDecorators.end();++i) |
255 | 0 | { |
256 | 0 | delete *i; |
257 | 0 | } |
258 | 9.62k | } |
259 | | |
260 | | void |
261 | | SipMessage::clearHeaders() |
262 | 19.2k | { |
263 | 30.4k | for (TypedHeaders::iterator i = mHeaders.begin(); i != mHeaders.end(); i++) |
264 | 11.2k | { |
265 | 11.2k | freeHfvl(*i); |
266 | 11.2k | } |
267 | 19.2k | mHeaders.clear(); |
268 | 19.2k | } |
269 | | |
270 | | SipMessage* |
271 | | SipMessage::make(const Data& data, bool isExternal) |
272 | 6.36k | { |
273 | 6.36k | Tuple fakeWireTuple; |
274 | 6.36k | fakeWireTuple.setType(UDP); |
275 | 6.36k | SipMessage* msg = new SipMessage(isExternal ? &fakeWireTuple : 0); |
276 | | |
277 | 6.36k | size_t len = data.size(); |
278 | 6.36k | char *buffer = new char[len + 5]; |
279 | | |
280 | 6.36k | msg->addBuffer(buffer); |
281 | 6.36k | memcpy(buffer,data.data(), len); |
282 | 6.36k | MsgHeaderScanner msgHeaderScanner; |
283 | 6.36k | msgHeaderScanner.prepareForMessage(msg); |
284 | | |
285 | 6.36k | char *unprocessedCharPtr; |
286 | 6.36k | if (msgHeaderScanner.scanChunk(buffer, (unsigned int)len, &unprocessedCharPtr) != MsgHeaderScanner::scrEnd) |
287 | 6.21k | { |
288 | 6.21k | DebugLog(<<"Scanner rejecting buffer as unparsable / fragmented."); |
289 | 6.21k | DebugLog(<< data); |
290 | 6.21k | delete msg; |
291 | 6.21k | msg = 0; |
292 | 6.21k | return 0; |
293 | 6.21k | } |
294 | | |
295 | | // no pp error |
296 | 155 | unsigned int used = (unsigned int)(unprocessedCharPtr - buffer); |
297 | | |
298 | 155 | if (used < len) |
299 | 153 | { |
300 | | // body is present .. add it up. |
301 | | // NB. The Sip Message uses an overlay (again) |
302 | | // for the body. It ALSO expects that the body |
303 | | // will be contiguous (of course). |
304 | | // it doesn't need a new buffer in UDP b/c there |
305 | | // will only be one datagram per buffer. (1:1 strict) |
306 | | |
307 | 153 | msg->setBody(buffer+used,uint32_t(len-used)); |
308 | | //DebugLog(<<"added " << len-used << " byte body"); |
309 | 153 | } |
310 | | |
311 | 155 | return msg; |
312 | 6.36k | } |
313 | | |
314 | | void |
315 | | SipMessage::parseAllHeaders() |
316 | 0 | { |
317 | 0 | for (int i = 0; i < Headers::MAX_HEADERS; i++) |
318 | 0 | { |
319 | 0 | ParserContainerBase* pc=0; |
320 | 0 | if(mHeaderIndices[i]>0) |
321 | 0 | { |
322 | 0 | HeaderFieldValueList* hfvl = ensureHeaders((Headers::Type)i); |
323 | 0 | if(!Headers::isMulti((Headers::Type)i) && hfvl->parsedEmpty()) |
324 | 0 | { |
325 | 0 | hfvl->push_back(0,0,false); |
326 | 0 | } |
327 | |
|
328 | 0 | if(!(pc=hfvl->getParserContainer())) |
329 | 0 | { |
330 | 0 | pc = HeaderBase::getInstance((Headers::Type)i)->makeContainer(hfvl); |
331 | 0 | hfvl->setParserContainer(pc); |
332 | 0 | } |
333 | | |
334 | 0 | pc->parseAll(); |
335 | 0 | } |
336 | 0 | } |
337 | |
|
338 | 0 | for (UnknownHeaders::iterator i = mUnknownHeaders.begin(); |
339 | 0 | i != mUnknownHeaders.end(); i++) |
340 | 0 | { |
341 | 0 | ParserContainerBase* scs=0; |
342 | 0 | if(!(scs=i->second->getParserContainer())) |
343 | 0 | { |
344 | 0 | scs=makeParserContainer<StringCategory>(i->second,Headers::RESIP_DO_NOT_USE); |
345 | 0 | i->second->setParserContainer(scs); |
346 | 0 | } |
347 | | |
348 | 0 | scs->parseAll(); |
349 | 0 | } |
350 | | |
351 | 0 | resip_assert(mStartLine); |
352 | |
|
353 | 0 | mStartLine->checkParsed(); |
354 | | |
355 | 0 | getContents(); |
356 | 0 | } |
357 | | |
358 | | const Data& |
359 | | SipMessage::getTransactionId() const |
360 | 0 | { |
361 | 0 | if (empty(h_Vias)) |
362 | 0 | { |
363 | 0 | InfoLog (<< "Bad message with no Vias: " << *this); |
364 | 0 | throw Exception("No Via in message", __FILE__,__LINE__); |
365 | 0 | } |
366 | | |
367 | 0 | resip_assert(exists(h_Vias) && !header(h_Vias).empty()); |
368 | 0 | if( exists(h_Vias) && header(h_Vias).front().exists(p_branch) |
369 | 0 | && header(h_Vias).front().param(p_branch).hasMagicCookie() |
370 | 0 | && (!header(h_Vias).front().param(p_branch).getTransactionId().empty()) |
371 | 0 | ) |
372 | 0 | { |
373 | 0 | return header(h_Vias).front().param(p_branch).getTransactionId(); |
374 | 0 | } |
375 | 0 | else |
376 | 0 | { |
377 | 0 | if (mRFC2543TransactionId.empty()) |
378 | 0 | { |
379 | 0 | compute2543TransactionHash(); |
380 | 0 | } |
381 | 0 | return mRFC2543TransactionId; |
382 | 0 | } |
383 | 0 | } |
384 | | |
385 | | void |
386 | | SipMessage::compute2543TransactionHash() const |
387 | 0 | { |
388 | 0 | resip_assert (mRFC2543TransactionId.empty()); |
389 | | |
390 | | /* From rfc3261, 17.2.3 |
391 | | The INVITE request matches a transaction if the Request-URI, To tag, |
392 | | From tag, Call-ID, CSeq, and top Via header field match those of the |
393 | | INVITE request which created the transaction. In this case, the |
394 | | INVITE is a retransmission of the original one that created the |
395 | | transaction. |
396 | | |
397 | | The ACK request matches a transaction if the Request-URI, From tag, |
398 | | Call-ID, CSeq number (not the method), and top Via header field match |
399 | | those of the INVITE request which created the transaction, and the To |
400 | | tag of the ACK matches the To tag of the response sent by the server |
401 | | transaction. |
402 | | |
403 | | Matching is done based on the matching rules defined for each of those |
404 | | header fields. Inclusion of the tag in the To header field in the ACK |
405 | | matching process helps disambiguate ACK for 2xx from ACK for other |
406 | | responses at a proxy, which may have forwarded both responses (This |
407 | | can occur in unusual conditions. Specifically, when a proxy forked a |
408 | | request, and then crashes, the responses may be delivered to another |
409 | | proxy, which might end up forwarding multiple responses upstream). An |
410 | | ACK request that matches an INVITE transaction matched by a previous |
411 | | ACK is considered a retransmission of that previous ACK. |
412 | | |
413 | | For all other request methods, a request is matched to a transaction |
414 | | if the Request-URI, To tag, From tag, Call-ID, CSeq (including the |
415 | | method), and top Via header field match those of the request that |
416 | | created the transaction. Matching is done based on the matching |
417 | | */ |
418 | | |
419 | | // If it is here and isn't a request, leave the transactionId empty, this |
420 | | // will cause the Transaction to send it statelessly |
421 | |
|
422 | 0 | if (isRequest()) |
423 | 0 | { |
424 | 0 | MD5Stream strm; |
425 | | // See section 17.2.3 Matching Requests to Server Transactions in rfc 3261 |
426 | | |
427 | | //#define VONAGE_FIX |
428 | 0 | #ifndef VONAGE_FIX |
429 | 0 | strm << header(h_RequestLine).uri().scheme(); |
430 | 0 | strm << header(h_RequestLine).uri().user(); |
431 | 0 | strm << header(h_RequestLine).uri().host(); |
432 | 0 | strm << header(h_RequestLine).uri().port(); |
433 | 0 | strm << header(h_RequestLine).uri().password(); |
434 | 0 | strm << header(h_RequestLine).uri().commutativeParameterHash(); |
435 | 0 | #endif |
436 | 0 | if (!empty(h_Vias)) |
437 | 0 | { |
438 | 0 | strm << header(h_Vias).front().protocolName(); |
439 | 0 | strm << header(h_Vias).front().protocolVersion(); |
440 | 0 | strm << header(h_Vias).front().transport(); |
441 | 0 | strm << header(h_Vias).front().sentHost(); |
442 | 0 | strm << header(h_Vias).front().sentPort(); |
443 | 0 | strm << header(h_Vias).front().commutativeParameterHash(); |
444 | 0 | } |
445 | | |
446 | 0 | if (header(h_From).exists(p_tag)) |
447 | 0 | { |
448 | 0 | strm << header(h_From).param(p_tag); |
449 | 0 | } |
450 | | |
451 | | // Only include the totag for non-invite requests |
452 | 0 | if (header(h_RequestLine).getMethod() != INVITE && |
453 | 0 | header(h_RequestLine).getMethod() != ACK && |
454 | 0 | header(h_RequestLine).getMethod() != CANCEL && |
455 | 0 | header(h_To).exists(p_tag)) |
456 | 0 | { |
457 | 0 | strm << header(h_To).param(p_tag); |
458 | 0 | } |
459 | |
|
460 | 0 | strm << header(h_CallID).value(); |
461 | |
|
462 | 0 | if (header(h_RequestLine).getMethod() == ACK || |
463 | 0 | header(h_RequestLine).getMethod() == CANCEL) |
464 | 0 | { |
465 | 0 | strm << INVITE; |
466 | 0 | strm << header(h_CSeq).sequence(); |
467 | 0 | } |
468 | 0 | else |
469 | 0 | { |
470 | 0 | strm << header(h_CSeq).method(); |
471 | 0 | strm << header(h_CSeq).sequence(); |
472 | 0 | } |
473 | | |
474 | 0 | mRFC2543TransactionId = strm.getHex(); |
475 | 0 | } |
476 | 0 | else |
477 | 0 | { |
478 | 0 | InfoLog (<< "Trying to compute a transaction id on a 2543 response. Drop the response"); |
479 | 0 | DebugLog (<< *this); |
480 | 0 | throw Exception("Drop invalid 2543 response", __FILE__, __LINE__); |
481 | 0 | } |
482 | 0 | } |
483 | | |
484 | | const Data& |
485 | | SipMessage::getRFC2543TransactionId() const |
486 | 0 | { |
487 | 0 | if(empty(h_Vias) || |
488 | 0 | !header(h_Vias).front().exists(p_branch) || |
489 | 0 | !header(h_Vias).front().param(p_branch).hasMagicCookie() || |
490 | 0 | header(h_Vias).front().param(p_branch).getTransactionId().empty()) |
491 | 0 | { |
492 | 0 | if (mRFC2543TransactionId.empty()) |
493 | 0 | { |
494 | 0 | compute2543TransactionHash(); |
495 | 0 | } |
496 | 0 | } |
497 | 0 | return mRFC2543TransactionId; |
498 | 0 | } |
499 | | |
500 | | |
501 | | Data |
502 | | SipMessage::getCanonicalIdentityString() const |
503 | 0 | { |
504 | 0 | Data result; |
505 | 0 | DataStream strm(result); |
506 | | |
507 | | // digest-string = addr-spec ":" addr-spec ":" callid ":" 1*DIGIT SP method ":" |
508 | | // SIP-Date ":" [ addr-spec ] ":" message-body |
509 | | |
510 | 0 | strm << header(h_From).uri(); |
511 | 0 | strm << Symbols::BAR; |
512 | | |
513 | 0 | strm << header(h_To).uri(); |
514 | 0 | strm << Symbols::BAR; |
515 | | |
516 | 0 | strm << header(h_CallId).value(); |
517 | 0 | strm << Symbols::BAR; |
518 | | |
519 | 0 | header(h_CSeq).sequence(); // force parsed |
520 | 0 | header(h_CSeq).encodeParsed( strm ); |
521 | 0 | strm << Symbols::BAR; |
522 | | |
523 | | // if there is no date, it will throw |
524 | 0 | if ( empty(h_Date) ) |
525 | 0 | { |
526 | 0 | WarningLog( << "Computing Identity on message with no Date header" ); |
527 | | // TODO FIX - should it have a throw here ???? Help ??? |
528 | 0 | } |
529 | 0 | header(h_Date).dayOfMonth(); // force it to be parsed |
530 | 0 | header(h_Date).encodeParsed( strm ); |
531 | 0 | strm << Symbols::BAR; |
532 | | |
533 | 0 | if ( !empty(h_Contacts) ) |
534 | 0 | { |
535 | 0 | if ( header(h_Contacts).front().isAllContacts() ) |
536 | 0 | { |
537 | 0 | strm << Symbols::STAR; |
538 | 0 | } |
539 | 0 | else |
540 | 0 | { |
541 | 0 | strm << header(h_Contacts).front().uri(); |
542 | 0 | } |
543 | 0 | } |
544 | 0 | strm << Symbols::BAR; |
545 | | |
546 | | // bodies |
547 | 0 | if (mContents != 0) |
548 | 0 | { |
549 | 0 | mContents->encode(strm); |
550 | 0 | } |
551 | 0 | else if (mContentsHfv.getBuffer() != 0) |
552 | 0 | { |
553 | 0 | mContentsHfv.encode(strm); |
554 | 0 | } |
555 | |
|
556 | 0 | strm.flush(); |
557 | |
|
558 | 0 | DebugLog( << "Indentity Canonical String is: " << result ); |
559 | | |
560 | 0 | return result; |
561 | 0 | } |
562 | | |
563 | | |
564 | | void |
565 | | SipMessage::setRFC2543TransactionId(const Data& tid) |
566 | 0 | { |
567 | 0 | mRFC2543TransactionId = tid; |
568 | 0 | } |
569 | | |
570 | | resip::MethodTypes |
571 | | SipMessage::method() const |
572 | 0 | { |
573 | 0 | resip::MethodTypes res=UNKNOWN; |
574 | 0 | try |
575 | 0 | { |
576 | 0 | if(isRequest()) |
577 | 0 | { |
578 | 0 | res=header(h_RequestLine).getMethod(); |
579 | 0 | } |
580 | 0 | else if(isResponse()) |
581 | 0 | { |
582 | 0 | res=header(h_CSeq).method(); |
583 | 0 | } |
584 | 0 | else |
585 | 0 | { |
586 | 0 | resip_assert(0); |
587 | 0 | } |
588 | 0 | } |
589 | 0 | catch(resip::ParseException&) |
590 | 0 | { |
591 | 0 | } |
592 | | |
593 | 0 | return res; |
594 | 0 | } |
595 | | |
596 | | const Data& |
597 | | SipMessage::methodStr() const |
598 | 0 | { |
599 | 0 | if(method()!=UNKNOWN) |
600 | 0 | { |
601 | 0 | return getMethodName(method()); |
602 | 0 | } |
603 | 0 | else |
604 | 0 | { |
605 | 0 | try |
606 | 0 | { |
607 | 0 | if(isRequest()) |
608 | 0 | { |
609 | 0 | return header(h_RequestLine).unknownMethodName(); |
610 | 0 | } |
611 | 0 | else if(isResponse()) |
612 | 0 | { |
613 | 0 | return header(h_CSeq).unknownMethodName(); |
614 | 0 | } |
615 | 0 | else |
616 | 0 | { |
617 | 0 | resip_assert(0); |
618 | 0 | } |
619 | 0 | } |
620 | 0 | catch(resip::ParseException&) |
621 | 0 | { |
622 | 0 | } |
623 | 0 | } |
624 | 0 | return Data::Empty; |
625 | 0 | } |
626 | | |
627 | | static const Data requestEB("SipReq: "); |
628 | | static const Data responseEB("SipResp: "); |
629 | | static const Data tidEB(" tid="); |
630 | | static const Data contactEB(" contact="); |
631 | | static const Data cseqEB(" cseq="); |
632 | | static const Data slashEB(" / "); |
633 | | static const Data wireEB(" from(wire)"); |
634 | | static const Data ftuEB(" from(tu)"); |
635 | | static const Data tlsdEB(" tlsd="); |
636 | | EncodeStream& |
637 | | SipMessage::encodeBrief(EncodeStream& str) const |
638 | 0 | { |
639 | 0 | if (isRequest()) |
640 | 0 | { |
641 | 0 | str << requestEB; |
642 | 0 | MethodTypes meth = header(h_RequestLine).getMethod(); |
643 | 0 | if (meth != UNKNOWN) |
644 | 0 | { |
645 | 0 | str << getMethodName(meth); |
646 | 0 | } |
647 | 0 | else |
648 | 0 | { |
649 | 0 | str << header(h_RequestLine).unknownMethodName(); |
650 | 0 | } |
651 | | |
652 | 0 | str << Symbols::SPACE; |
653 | 0 | str << header(h_RequestLine).uri().getAor(); |
654 | 0 | } |
655 | 0 | else if (isResponse()) |
656 | 0 | { |
657 | 0 | str << responseEB; |
658 | 0 | str << header(h_StatusLine).responseCode(); |
659 | 0 | } |
660 | 0 | if (!empty(h_Vias)) |
661 | 0 | { |
662 | 0 | str << tidEB; |
663 | 0 | try |
664 | 0 | { |
665 | 0 | str << getTransactionId(); |
666 | 0 | } |
667 | 0 | catch(BaseException&) // Could be SipMessage::Exception or ParseException |
668 | 0 | { |
669 | 0 | str << "BAD-VIA"; |
670 | 0 | } |
671 | 0 | } |
672 | 0 | else |
673 | 0 | { |
674 | 0 | str << " NO-VIAS "; |
675 | 0 | } |
676 | |
|
677 | 0 | str << cseqEB; |
678 | 0 | str << header(h_CSeq); |
679 | |
|
680 | 0 | try |
681 | 0 | { |
682 | 0 | if (!empty(h_Contacts)) |
683 | 0 | { |
684 | 0 | str << contactEB; |
685 | 0 | str << header(h_Contacts).front().uri().getAor(); |
686 | 0 | } |
687 | 0 | } |
688 | 0 | catch(resip::ParseException&) |
689 | 0 | { |
690 | 0 | str << " MALFORMED CONTACT "; |
691 | 0 | } |
692 | | |
693 | 0 | str << slashEB; |
694 | 0 | str << header(h_CSeq).sequence(); |
695 | 0 | str << (mIsExternal ? wireEB : ftuEB); |
696 | 0 | if (!mTlsDomain.empty()) |
697 | 0 | { |
698 | 0 | str << tlsdEB << mTlsDomain; |
699 | 0 | } |
700 | | |
701 | 0 | return str; |
702 | 0 | } |
703 | | |
704 | | bool |
705 | | SipMessage::isClientTransaction() const |
706 | 0 | { |
707 | 0 | resip_assert(mRequest || mResponse); |
708 | 0 | return ((mIsExternal && mResponse) || (!mIsExternal && mRequest)); |
709 | 0 | } |
710 | | |
711 | | EncodeStream& |
712 | | SipMessage::encode(EncodeStream& str) const |
713 | 0 | { |
714 | 0 | return encode(str, false); |
715 | 0 | } |
716 | | |
717 | | EncodeStream& |
718 | | SipMessage::encodeSipFrag(EncodeStream& str) const |
719 | 0 | { |
720 | 0 | return encode(str, true); |
721 | 0 | } |
722 | | |
723 | | // dynamic_cast &str to DataStream* to avoid CountStream? |
724 | | |
725 | | EncodeStream& |
726 | | SipMessage::encode(EncodeStream& str, bool isSipFrag) const |
727 | 0 | { |
728 | 0 | if (mStartLine != 0) |
729 | 0 | { |
730 | 0 | mStartLine->encode(str); |
731 | 0 | str << "\r\n"; |
732 | 0 | } |
733 | |
|
734 | 0 | Data contents; |
735 | 0 | if (mContents != 0) |
736 | 0 | { |
737 | 0 | oDataStream temp(contents); |
738 | 0 | mContents->encode(temp); |
739 | 0 | } |
740 | 0 | else if (mContentsHfv.getBuffer() != 0) |
741 | 0 | { |
742 | | #if 0 |
743 | | // !bwc! This causes an additional copy; sure would be nice to have a way |
744 | | // to get a data to take on a buffer with Data::Share _after_ construction |
745 | | contents.append(mContentsHfv.getBuffer(), mContentsHfv.getLength()); |
746 | | #else |
747 | | // .kw. Your wish is granted |
748 | 0 | mContentsHfv.toShareData(contents); |
749 | 0 | #endif |
750 | 0 | } |
751 | |
|
752 | 0 | for (uint8_t i = 0; i < Headers::MAX_HEADERS; i++) |
753 | 0 | { |
754 | 0 | if (i != Headers::ContentLength) // !dlb! hack... |
755 | 0 | { |
756 | 0 | if (mHeaderIndices[i] > 0) |
757 | 0 | { |
758 | 0 | mHeaders[mHeaderIndices[i]]->encode(i, str); |
759 | 0 | } |
760 | 0 | } |
761 | 0 | } |
762 | |
|
763 | 0 | for (UnknownHeaders::const_iterator i = mUnknownHeaders.begin(); |
764 | 0 | i != mUnknownHeaders.end(); i++) |
765 | 0 | { |
766 | 0 | i->second->encode(i->first, str); |
767 | 0 | } |
768 | |
|
769 | 0 | if(!isSipFrag || !contents.empty()) |
770 | 0 | { |
771 | 0 | str << "Content-Length: " << contents.size() << "\r\n"; |
772 | 0 | } |
773 | |
|
774 | 0 | str << Symbols::CRLF; |
775 | | |
776 | 0 | str << contents; |
777 | 0 | return str; |
778 | 0 | } |
779 | | |
780 | | EncodeStream& |
781 | | SipMessage::encodeSingleHeader(Headers::Type type, EncodeStream& str) const |
782 | 0 | { |
783 | 0 | if (mHeaderIndices[type] > 0) |
784 | 0 | { |
785 | 0 | mHeaders[mHeaderIndices[type]]->encode(type, str); |
786 | 0 | } |
787 | 0 | return str; |
788 | 0 | } |
789 | | |
790 | | EncodeStream& |
791 | | SipMessage::encodeEmbedded(EncodeStream& str) const |
792 | 0 | { |
793 | 0 | bool first = true; |
794 | 0 | for (uint8_t i = 0; i < Headers::MAX_HEADERS; i++) |
795 | 0 | { |
796 | 0 | if (i != Headers::ContentLength) |
797 | 0 | { |
798 | 0 | if (mHeaderIndices[i] > 0) |
799 | 0 | { |
800 | 0 | if (first) |
801 | 0 | { |
802 | 0 | str << Symbols::QUESTION; |
803 | 0 | first = false; |
804 | 0 | } |
805 | 0 | else |
806 | 0 | { |
807 | 0 | str << Symbols::AMPERSAND; |
808 | 0 | } |
809 | 0 | mHeaders[mHeaderIndices[i]]->encodeEmbedded(Headers::getHeaderName(i), str); |
810 | 0 | } |
811 | 0 | } |
812 | 0 | } |
813 | |
|
814 | 0 | for (UnknownHeaders::const_iterator i = mUnknownHeaders.begin(); |
815 | 0 | i != mUnknownHeaders.end(); i++) |
816 | 0 | { |
817 | 0 | if (first) |
818 | 0 | { |
819 | 0 | str << Symbols::QUESTION; |
820 | 0 | first = false; |
821 | 0 | } |
822 | 0 | else |
823 | 0 | { |
824 | 0 | str << Symbols::AMPERSAND; |
825 | 0 | } |
826 | 0 | i->second->encodeEmbedded(i->first, str); |
827 | 0 | } |
828 | |
|
829 | 0 | if (mContents != 0 || mContentsHfv.getBuffer() != 0) |
830 | 0 | { |
831 | 0 | if (first) |
832 | 0 | { |
833 | 0 | str << Symbols::QUESTION; |
834 | 0 | } |
835 | 0 | else |
836 | 0 | { |
837 | 0 | str << Symbols::AMPERSAND; |
838 | 0 | } |
839 | 0 | str << "body="; |
840 | 0 | Data contents; |
841 | | // !dlb! encode escaped for characters |
842 | | // .kw. what does that mean? what needs to be escaped? |
843 | 0 | if(mContents != 0) |
844 | 0 | { |
845 | 0 | DataStream s(contents); |
846 | 0 | mContents->encode(s); |
847 | 0 | } |
848 | 0 | else |
849 | 0 | { |
850 | | // .kw. Early code did: |
851 | | // DataStream s(contents); |
852 | | // mContentsHfv->encode(str); |
853 | | // str << Embedded::encode(contents); |
854 | | // .kw. which I think is buggy b/c Hfv was written directly |
855 | | // to str and skipped the encode step via contents |
856 | 0 | mContentsHfv.toShareData(contents); |
857 | 0 | } |
858 | 0 | str << Embedded::encode(contents); |
859 | 0 | } |
860 | 0 | return str; |
861 | 0 | } |
862 | | |
863 | | void |
864 | | SipMessage::addBuffer(char* buf) |
865 | 1.29M | { |
866 | 1.29M | mBufferList.push_back(buf); |
867 | 1.29M | } |
868 | | |
869 | | void |
870 | | SipMessage::setStartLine(const char* st, int len) |
871 | 562 | { |
872 | 562 | if(len >= 4 && !strncasecmp(st,"SIP/",4)) |
873 | 4 | { |
874 | | // Response |
875 | 4 | mStartLine = new (mStartLineMem) StatusLine(st, len); |
876 | | //!dcm! should invoke the statusline parser here once it does limited validation |
877 | 4 | mResponse = true; |
878 | 4 | } |
879 | 558 | else |
880 | 558 | { |
881 | | // Request |
882 | 558 | mStartLine = new (mStartLineMem) RequestLine(st, len); |
883 | | //!dcm! should invoke the responseline parser here once it does limited validation |
884 | 558 | mRequest = true; |
885 | 558 | } |
886 | | |
887 | | |
888 | | // .bwc. This stuff is so needlessly complicated. Much, much simpler, faster, |
889 | | // and more robust code above. |
890 | | // ParseBuffer pb(st, len); |
891 | | // const char* start; |
892 | | // start = pb.skipWhitespace(); |
893 | | // pb.skipNonWhitespace(); |
894 | | // MethodTypes method = getMethodType(start, pb.position() - start); |
895 | | // if (method == UNKNOWN) //probably a status line |
896 | | // { |
897 | | // start = pb.skipChar(Symbols::SPACE[0]); |
898 | | // pb.skipNonWhitespace(); |
899 | | // if ((pb.position() - start) == 3) |
900 | | // { |
901 | | // mStartLine = new (mStartLineMem) StatusLine(st, len ,Headers::NONE); |
902 | | // //!dcm! should invoke the statusline parser here once it does limited validation |
903 | | // mResponse = true; |
904 | | // } |
905 | | // } |
906 | | // if (!mResponse) |
907 | | // { |
908 | | // mStartLine = new (mStartLineMem) RequestLine(st, len, Headers::NONE); |
909 | | // //!dcm! should invoke the responseline parser here once it does limited validation |
910 | | // mRequest = true; |
911 | | // } |
912 | 562 | } |
913 | | |
914 | | void |
915 | | SipMessage::setBody(const char* start, uint32_t len) |
916 | 27.2k | { |
917 | 27.2k | if(checkContentLength) |
918 | 27.2k | { |
919 | 27.2k | if(exists(h_ContentLength)) |
920 | 4.31k | { |
921 | 4.31k | try |
922 | 4.31k | { |
923 | 4.31k | const_header(h_ContentLength).checkParsed(); |
924 | 4.31k | } |
925 | 4.31k | catch(resip::ParseException& e) |
926 | 4.31k | { |
927 | 102 | if(!mReason) |
928 | 102 | { |
929 | 102 | mReason=new Data; |
930 | 102 | } |
931 | | |
932 | 102 | if(mInvalid) |
933 | 0 | { |
934 | 0 | mReason->append(",",1); |
935 | 0 | } |
936 | | |
937 | 102 | mInvalid=true; |
938 | 102 | mReason->append("Malformed Content-Length",24); |
939 | 102 | InfoLog(<< "Malformed Content-Length. Ignoring. " << e); |
940 | 102 | header(h_ContentLength).value()=len; |
941 | 102 | } |
942 | | |
943 | 4.31k | uint32_t contentLength=const_header(h_ContentLength).value(); |
944 | | |
945 | 4.31k | if(len > contentLength) |
946 | 810 | { |
947 | 810 | InfoLog(<< (len-contentLength) << " extra bytes after body. Ignoring these bytes."); |
948 | 810 | } |
949 | 3.50k | else if(len < contentLength) |
950 | 134 | { |
951 | 134 | InfoLog(<< "Content Length (" << contentLength << ") is " |
952 | 134 | << (contentLength-len) << " bytes larger than body (" << len << ")!" |
953 | 134 | << " (We are supposed to 400 this) "); |
954 | | |
955 | 134 | if(!mReason) |
956 | 85 | { |
957 | 85 | mReason=new Data; |
958 | 85 | } |
959 | | |
960 | 134 | if(mInvalid) |
961 | 49 | { |
962 | 49 | mReason->append(",",1); |
963 | 49 | } |
964 | | |
965 | 134 | mInvalid=true; |
966 | 134 | mReason->append("Bad Content-Length (larger than datagram)",41); |
967 | 134 | header(h_ContentLength).value()=len; |
968 | 134 | contentLength=len; |
969 | | |
970 | 134 | } |
971 | | |
972 | 4.31k | mContentsHfv.init(start,contentLength, false); |
973 | 4.31k | } |
974 | 22.9k | else |
975 | 22.9k | { |
976 | 22.9k | InfoLog(<< "Message has a body, but no Content-Length header."); |
977 | 22.9k | mContentsHfv.init(start,len, false); |
978 | 22.9k | } |
979 | 27.2k | } |
980 | 0 | else |
981 | 0 | { |
982 | 0 | mContentsHfv.init(start,len, false); |
983 | 0 | } |
984 | 27.2k | } |
985 | | |
986 | | void |
987 | | SipMessage::setRawBody(const HeaderFieldValue& body) |
988 | 0 | { |
989 | 0 | setContents(0); |
990 | 0 | mContentsHfv = body; |
991 | 0 | } |
992 | | |
993 | | |
994 | | void |
995 | | SipMessage::setContents(unique_ptr<Contents> contents) |
996 | 0 | { |
997 | 0 | Contents* contentsP = contents.release(); |
998 | |
|
999 | 0 | delete mContents; |
1000 | 0 | mContents = 0; |
1001 | 0 | mContentsHfv.clear(); |
1002 | |
|
1003 | 0 | if (contentsP == 0) |
1004 | 0 | { |
1005 | | // The semantics of setContents(0) are to delete message contents |
1006 | 0 | remove(h_ContentType); |
1007 | 0 | remove(h_ContentDisposition); |
1008 | 0 | remove(h_ContentTransferEncoding); |
1009 | 0 | remove(h_ContentLanguages); |
1010 | 0 | return; |
1011 | 0 | } |
1012 | | |
1013 | 0 | mContents = contentsP; |
1014 | | |
1015 | | // copy contents headers into message |
1016 | 0 | if (mContents->exists(h_ContentDisposition)) |
1017 | 0 | { |
1018 | 0 | header(h_ContentDisposition) = mContents->header(h_ContentDisposition); |
1019 | 0 | } |
1020 | 0 | if (mContents->exists(h_ContentTransferEncoding)) |
1021 | 0 | { |
1022 | 0 | header(h_ContentTransferEncoding) = mContents->header(h_ContentTransferEncoding); |
1023 | 0 | } |
1024 | 0 | if (mContents->exists(h_ContentLanguages)) |
1025 | 0 | { |
1026 | 0 | header(h_ContentLanguages) = mContents->header(h_ContentLanguages); |
1027 | 0 | } |
1028 | 0 | if (mContents->exists(h_ContentType)) |
1029 | 0 | { |
1030 | 0 | header(h_ContentType) = mContents->header(h_ContentType); |
1031 | 0 | resip_assert( header(h_ContentType).type() == mContents->getType().type() ); |
1032 | 0 | resip_assert( header(h_ContentType).subType() == mContents->getType().subType() ); |
1033 | 0 | } |
1034 | 0 | else |
1035 | 0 | { |
1036 | 0 | header(h_ContentType) = mContents->getType(); |
1037 | 0 | } |
1038 | 0 | } |
1039 | | |
1040 | | void |
1041 | | SipMessage::setContents(const Contents* contents) |
1042 | 0 | { |
1043 | 0 | if (contents) |
1044 | 0 | { |
1045 | 0 | setContents(unique_ptr<Contents>(contents->clone())); |
1046 | 0 | } |
1047 | 0 | else |
1048 | 0 | { |
1049 | 0 | setContents(unique_ptr<Contents>()); |
1050 | 0 | } |
1051 | 0 | } |
1052 | | |
1053 | | Contents* |
1054 | | SipMessage::getContents() const |
1055 | 0 | { |
1056 | 0 | if (mContents == 0 && mContentsHfv.getBuffer() != 0) |
1057 | 0 | { |
1058 | 0 | if (empty(h_ContentType) || |
1059 | 0 | !const_header(h_ContentType).isWellFormed()) |
1060 | 0 | { |
1061 | 0 | StackLog(<< "SipMessage::getContents: ContentType header does not exist - implies no contents"); |
1062 | 0 | return 0; |
1063 | 0 | } |
1064 | 0 | DebugLog(<< "SipMessage::getContents: " |
1065 | 0 | << const_header(h_ContentType).type() |
1066 | 0 | << "/" |
1067 | 0 | << const_header(h_ContentType).subType()); |
1068 | |
|
1069 | 0 | if ( ContentsFactoryBase::getFactoryMap().find(const_header(h_ContentType)) == ContentsFactoryBase::getFactoryMap().end() ) |
1070 | 0 | { |
1071 | 0 | InfoLog(<< "SipMessage::getContents: got content type (" |
1072 | 0 | << const_header(h_ContentType).type() |
1073 | 0 | << "/" |
1074 | 0 | << const_header(h_ContentType).subType() |
1075 | 0 | << ") that is not known, " |
1076 | 0 | << "returning as opaque application/octet-stream"); |
1077 | 0 | mContents = ContentsFactoryBase::getFactoryMap()[OctetContents::getStaticType()]->create(mContentsHfv, OctetContents::getStaticType()); |
1078 | 0 | } |
1079 | 0 | else |
1080 | 0 | { |
1081 | 0 | mContents = ContentsFactoryBase::getFactoryMap()[const_header(h_ContentType)]->create(mContentsHfv, const_header(h_ContentType)); |
1082 | 0 | } |
1083 | 0 | resip_assert( mContents ); |
1084 | | |
1085 | | // copy contents headers into the contents |
1086 | 0 | if (!empty(h_ContentDisposition)) |
1087 | 0 | { |
1088 | 0 | mContents->header(h_ContentDisposition) = const_header(h_ContentDisposition); |
1089 | 0 | } |
1090 | 0 | if (!empty(h_ContentTransferEncoding)) |
1091 | 0 | { |
1092 | 0 | mContents->header(h_ContentTransferEncoding) = const_header(h_ContentTransferEncoding); |
1093 | 0 | } |
1094 | 0 | if (!empty(h_ContentLanguages)) |
1095 | 0 | { |
1096 | 0 | mContents->header(h_ContentLanguages) = const_header(h_ContentLanguages); |
1097 | 0 | } |
1098 | 0 | if (!empty(h_ContentType)) |
1099 | 0 | { |
1100 | 0 | mContents->header(h_ContentType) = const_header(h_ContentType); |
1101 | 0 | } |
1102 | | // !dlb! Content-Transfer-Encoding? |
1103 | 0 | } |
1104 | 0 | return mContents; |
1105 | 0 | } |
1106 | | |
1107 | | unique_ptr<Contents> |
1108 | | SipMessage::releaseContents() |
1109 | 0 | { |
1110 | 0 | Contents* c=getContents(); |
1111 | | // .bwc. unique_ptr owns the Contents. No other references allowed! |
1112 | 0 | unique_ptr<Contents> ret(c ? c->clone() : nullptr); |
1113 | 0 | setContents(nullptr); |
1114 | |
|
1115 | 0 | if (ret != nullptr && !ret->isWellFormed()) |
1116 | 0 | { |
1117 | 0 | ret.reset(); |
1118 | 0 | } |
1119 | |
|
1120 | 0 | return ret; |
1121 | 0 | } |
1122 | | |
1123 | | // unknown header interface |
1124 | | const StringCategories& |
1125 | | SipMessage::header(const ExtensionHeader& headerName) const |
1126 | 0 | { |
1127 | 0 | for (UnknownHeaders::const_iterator i = mUnknownHeaders.begin(); |
1128 | 0 | i != mUnknownHeaders.end(); i++) |
1129 | 0 | { |
1130 | 0 | if (isEqualNoCase(i->first, headerName.getName())) |
1131 | 0 | { |
1132 | 0 | HeaderFieldValueList* hfvs = i->second; |
1133 | 0 | if (hfvs->getParserContainer() == 0) |
1134 | 0 | { |
1135 | 0 | SipMessage* nc_this(const_cast<SipMessage*>(this)); |
1136 | 0 | hfvs->setParserContainer(nc_this->makeParserContainer<StringCategory>(hfvs, Headers::RESIP_DO_NOT_USE)); |
1137 | 0 | } |
1138 | 0 | return *dynamic_cast<ParserContainer<StringCategory>*>(hfvs->getParserContainer()); |
1139 | 0 | } |
1140 | 0 | } |
1141 | | // missing extension header |
1142 | 0 | resip_assert(false); |
1143 | |
|
1144 | 0 | return *(StringCategories*)0; |
1145 | 0 | } |
1146 | | |
1147 | | StringCategories& |
1148 | | SipMessage::header(const ExtensionHeader& headerName) |
1149 | 0 | { |
1150 | 0 | for (UnknownHeaders::iterator i = mUnknownHeaders.begin(); |
1151 | 0 | i != mUnknownHeaders.end(); i++) |
1152 | 0 | { |
1153 | 0 | if (isEqualNoCase(i->first, headerName.getName())) |
1154 | 0 | { |
1155 | 0 | HeaderFieldValueList* hfvs = i->second; |
1156 | 0 | if (hfvs->getParserContainer() == 0) |
1157 | 0 | { |
1158 | 0 | hfvs->setParserContainer(makeParserContainer<StringCategory>(hfvs, Headers::RESIP_DO_NOT_USE)); |
1159 | 0 | } |
1160 | 0 | return *dynamic_cast<ParserContainer<StringCategory>*>(hfvs->getParserContainer()); |
1161 | 0 | } |
1162 | 0 | } |
1163 | | |
1164 | | // create the list empty |
1165 | 0 | HeaderFieldValueList* hfvs = getEmptyHfvl(); |
1166 | 0 | hfvs->setParserContainer(makeParserContainer<StringCategory>(hfvs, Headers::RESIP_DO_NOT_USE)); |
1167 | 0 | mUnknownHeaders.push_back(make_pair(headerName.getName(), hfvs)); |
1168 | 0 | return *dynamic_cast<ParserContainer<StringCategory>*>(hfvs->getParserContainer()); |
1169 | 0 | } |
1170 | | |
1171 | | bool |
1172 | | SipMessage::exists(const ExtensionHeader& symbol) const |
1173 | 0 | { |
1174 | 0 | for (UnknownHeaders::const_iterator i = mUnknownHeaders.begin(); |
1175 | 0 | i != mUnknownHeaders.end(); i++) |
1176 | 0 | { |
1177 | 0 | if (isEqualNoCase(i->first, symbol.getName())) |
1178 | 0 | { |
1179 | 0 | return true; |
1180 | 0 | } |
1181 | 0 | } |
1182 | 0 | return false; |
1183 | 0 | } |
1184 | | |
1185 | | void |
1186 | | SipMessage::remove(const ExtensionHeader& headerName) |
1187 | 0 | { |
1188 | 0 | for (UnknownHeaders::iterator i = mUnknownHeaders.begin(); |
1189 | 0 | i != mUnknownHeaders.end(); i++) |
1190 | 0 | { |
1191 | 0 | if (isEqualNoCase(i->first, headerName.getName())) |
1192 | 0 | { |
1193 | 0 | freeHfvl(i->second); |
1194 | 0 | mUnknownHeaders.erase(i); |
1195 | 0 | return; |
1196 | 0 | } |
1197 | 0 | } |
1198 | 0 | } |
1199 | | |
1200 | | void |
1201 | | SipMessage::addHeader(Headers::Type header, const char* headerName, int headerLen, |
1202 | | const char* start, int len) |
1203 | 1.79M | { |
1204 | 1.79M | if (header != Headers::UNKNOWN) |
1205 | 638k | { |
1206 | 638k | resip_assert(header >= Headers::UNKNOWN && header < Headers::MAX_HEADERS); |
1207 | 638k | HeaderFieldValueList* hfvl=0; |
1208 | 638k | if (mHeaderIndices[header] == 0) |
1209 | 1.61k | { |
1210 | 1.61k | mHeaderIndices[header] = (short)mHeaders.size(); |
1211 | 1.61k | mHeaders.push_back(getEmptyHfvl()); |
1212 | 1.61k | hfvl=mHeaders.back(); |
1213 | 1.61k | } |
1214 | 636k | else |
1215 | 636k | { |
1216 | 636k | if(mHeaderIndices[header]<0) |
1217 | 0 | { |
1218 | | // Adding to a previously removed header type; there is already an |
1219 | | // empty HeaderFieldValueList in mHeaders for this type, all we |
1220 | | // need to do is flip the sign to re-enable it. |
1221 | 0 | mHeaderIndices[header] *= -1; |
1222 | 0 | } |
1223 | 636k | hfvl=mHeaders[mHeaderIndices[header]]; |
1224 | 636k | } |
1225 | | |
1226 | 638k | if(Headers::isMulti(header)) |
1227 | 567k | { |
1228 | 567k | if (len) |
1229 | 543k | { |
1230 | 543k | hfvl->push_back(start, len, false); |
1231 | 543k | } |
1232 | 567k | } |
1233 | 71.0k | else |
1234 | 71.0k | { |
1235 | | #ifdef PEDANTIC_STACK |
1236 | | if(hfvl->size()==1) |
1237 | | { |
1238 | | if(!mReason) |
1239 | | { |
1240 | | mReason=new Data; |
1241 | | } |
1242 | | |
1243 | | if(mInvalid) |
1244 | | { |
1245 | | mReason->append(",",1); |
1246 | | } |
1247 | | mInvalid=true; |
1248 | | mReason->append("Multiple values in single-value header ",39); |
1249 | | (*mReason)+=Headers::getHeaderName(header); |
1250 | | return; |
1251 | | } |
1252 | | #endif |
1253 | 71.0k | if (hfvl->empty()) |
1254 | 1.17k | { |
1255 | 1.17k | hfvl->push_back(start ? start : Data::Empty.data(), len, false); |
1256 | 1.17k | } |
1257 | 71.0k | } |
1258 | | |
1259 | 638k | } |
1260 | 1.15M | else |
1261 | 1.15M | { |
1262 | 1.15M | resip_assert(headerLen >= 0); |
1263 | 1.15M | for (UnknownHeaders::iterator i = mUnknownHeaders.begin(); |
1264 | 23.1M | i != mUnknownHeaders.end(); i++) |
1265 | 23.1M | { |
1266 | 23.1M | if (i->first.size() == (unsigned int)headerLen && |
1267 | 23.1M | strncasecmp(i->first.data(), headerName, headerLen) == 0) |
1268 | 1.14M | { |
1269 | | // add to end of list |
1270 | 1.14M | if (len) |
1271 | 302k | { |
1272 | 302k | i->second->push_back(start, len, false); |
1273 | 302k | } |
1274 | 1.14M | return; |
1275 | 1.14M | } |
1276 | 23.1M | } |
1277 | | |
1278 | | // didn't find it, add an entry |
1279 | 14.0k | HeaderFieldValueList *hfvs = getEmptyHfvl(); |
1280 | 14.0k | if (len) |
1281 | 5.71k | { |
1282 | 5.71k | hfvs->push_back(start, len, false); |
1283 | 5.71k | } |
1284 | 14.0k | mUnknownHeaders.push_back(pair<Data, HeaderFieldValueList*>(Data(headerName, headerLen), |
1285 | 14.0k | hfvs)); |
1286 | 14.0k | } |
1287 | 1.79M | } |
1288 | | |
1289 | | RequestLine& |
1290 | | SipMessage::header(const RequestLineType& l) |
1291 | 0 | { |
1292 | 0 | resip_assert (!isResponse()); |
1293 | 0 | if (mStartLine == 0 ) |
1294 | 0 | { |
1295 | 0 | mStartLine = new (mStartLineMem) RequestLine; |
1296 | 0 | mRequest = true; |
1297 | 0 | } |
1298 | 0 | return *static_cast<RequestLine*>(mStartLine); |
1299 | 0 | } |
1300 | | |
1301 | | const RequestLine& |
1302 | | SipMessage::header(const RequestLineType& l) const |
1303 | 0 | { |
1304 | 0 | resip_assert (!isResponse()); |
1305 | 0 | if (mStartLine == 0 ) |
1306 | 0 | { |
1307 | | // request line missing |
1308 | 0 | resip_assert(false); |
1309 | 0 | } |
1310 | 0 | return *static_cast<RequestLine*>(mStartLine); |
1311 | 0 | } |
1312 | | |
1313 | | StatusLine& |
1314 | | SipMessage::header(const StatusLineType& l) |
1315 | 0 | { |
1316 | 0 | resip_assert (!isRequest()); |
1317 | 0 | if (mStartLine == 0 ) |
1318 | 0 | { |
1319 | 0 | mStartLine = new (mStartLineMem) StatusLine; |
1320 | 0 | mResponse = true; |
1321 | 0 | } |
1322 | 0 | return *static_cast<StatusLine*>(mStartLine); |
1323 | 0 | } |
1324 | | |
1325 | | const StatusLine& |
1326 | | SipMessage::header(const StatusLineType& l) const |
1327 | 0 | { |
1328 | 0 | resip_assert (!isRequest()); |
1329 | 0 | if (mStartLine == 0 ) |
1330 | 0 | { |
1331 | | // status line missing |
1332 | 0 | resip_assert(false); |
1333 | 0 | } |
1334 | 0 | return *static_cast<StatusLine*>(mStartLine); |
1335 | 0 | } |
1336 | | |
1337 | | HeaderFieldValueList* |
1338 | | SipMessage::ensureHeaders(Headers::Type type) |
1339 | 0 | { |
1340 | 0 | HeaderFieldValueList* hfvl=0; |
1341 | 0 | if(mHeaderIndices[type]!=0) |
1342 | 0 | { |
1343 | 0 | if(mHeaderIndices[type]<0) |
1344 | 0 | { |
1345 | | // Accessing a previously removed header type; there is already an |
1346 | | // empty HeaderFieldValueList in mHeaders for this type, all we |
1347 | | // need to do is flip the sign to re-enable it. |
1348 | 0 | mHeaderIndices[type] *= -1; |
1349 | 0 | } |
1350 | 0 | hfvl = mHeaders[mHeaderIndices[type]]; |
1351 | 0 | } |
1352 | 0 | else |
1353 | 0 | { |
1354 | | // create the list with a new component |
1355 | 0 | mHeaders.push_back(getEmptyHfvl()); |
1356 | 0 | hfvl=mHeaders.back(); |
1357 | 0 | mHeaderIndices[type]= (short)mHeaders.size()-1; |
1358 | 0 | } |
1359 | |
|
1360 | 0 | return hfvl; |
1361 | 0 | } |
1362 | | |
1363 | | HeaderFieldValueList* |
1364 | | SipMessage::ensureHeader(Headers::Type type) |
1365 | 236 | { |
1366 | 236 | HeaderFieldValueList* hfvl=0; |
1367 | 236 | if(mHeaderIndices[type]!=0) |
1368 | 236 | { |
1369 | 236 | if(mHeaderIndices[type]<0) |
1370 | 0 | { |
1371 | | // Accessing a previously removed header type; there is already an |
1372 | | // empty HeaderFieldValueList in mHeaders for this type, all we |
1373 | | // need to do is flip the sign to re-enable it. |
1374 | 0 | mHeaderIndices[type] *= -1; |
1375 | 0 | hfvl = mHeaders[mHeaderIndices[type]]; |
1376 | 0 | hfvl->push_back(0,0,false); |
1377 | 0 | } |
1378 | 236 | hfvl = mHeaders[mHeaderIndices[type]]; |
1379 | 236 | } |
1380 | 0 | else |
1381 | 0 | { |
1382 | | // create the list with a new component |
1383 | 0 | mHeaders.push_back(getEmptyHfvl()); |
1384 | 0 | hfvl=mHeaders.back(); |
1385 | 0 | mHeaderIndices[type]=(short)mHeaders.size()-1; |
1386 | 0 | mHeaders.back()->push_back(0,0,false); |
1387 | 0 | } |
1388 | | |
1389 | 236 | return hfvl; |
1390 | 236 | } |
1391 | | |
1392 | | void |
1393 | | SipMessage::throwHeaderMissing(Headers::Type type) const |
1394 | 0 | { |
1395 | | // header missing |
1396 | | // assert(false); |
1397 | 0 | InfoLog( << "Missing Header [" << Headers::getHeaderName(type) << "]"); |
1398 | 0 | DebugLog (<< *this); |
1399 | 0 | throw Exception("Missing header " + Headers::getHeaderName(type), __FILE__, __LINE__); |
1400 | 0 | } |
1401 | | |
1402 | | // type safe header accessors |
1403 | | bool |
1404 | | SipMessage::exists(const HeaderBase& headerType) const |
1405 | 27.2k | { |
1406 | 27.2k | return mHeaderIndices[headerType.getTypeNum()] > 0; |
1407 | 27.2k | }; |
1408 | | |
1409 | | bool |
1410 | | SipMessage::empty(const HeaderBase& headerType) const |
1411 | 0 | { |
1412 | 0 | return (mHeaderIndices[headerType.getTypeNum()] <= 0) || mHeaders[mHeaderIndices[headerType.getTypeNum()]]->parsedEmpty(); |
1413 | 0 | } |
1414 | | |
1415 | | void |
1416 | | SipMessage::remove(Headers::Type type) |
1417 | 0 | { |
1418 | 0 | if(mHeaderIndices[type] > 0) |
1419 | 0 | { |
1420 | | // .bwc. The entry in mHeaders still remains after we do this; we retain |
1421 | | // our index (as a negative number, indicating that this header should |
1422 | | // not be encoded), in case this header type needs to be used later. |
1423 | 0 | mHeaders[mHeaderIndices[type]]->clear(); |
1424 | 0 | mHeaderIndices[type] *= -1; |
1425 | 0 | } |
1426 | 0 | }; |
1427 | | |
1428 | | #ifndef PARTIAL_TEMPLATE_SPECIALIZATION |
1429 | | |
1430 | | #undef defineHeader |
1431 | | #define defineHeader(_header, _name, _type, _rfc) \ |
1432 | | const H_##_header::Type& \ |
1433 | 8.62k | SipMessage::header(const H_##_header& headerType) const \ |
1434 | 8.62k | { \ |
1435 | 8.62k | HeaderFieldValueList* hfvs = ensureHeader(headerType.getTypeNum()); \ |
1436 | 8.62k | if (hfvs->getParserContainer() == 0) \ |
1437 | 8.62k | { \ |
1438 | 259 | SipMessage* nc_this(const_cast<SipMessage*>(this)); \ |
1439 | 259 | hfvs->setParserContainer(nc_this->makeParserContainer<H_##_header::Type>(hfvs, headerType.getTypeNum())); \ |
1440 | 259 | } \ |
1441 | 8.62k | return static_cast<ParserContainer<H_##_header::Type>*>(hfvs->getParserContainer())->front(); \ |
1442 | 8.62k | } \ Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentDisposition const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentEncoding const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_MIMEVersion const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Priority const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Event const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SubscriptionState const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SIPETag const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SIPIfMatch const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentId const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ReferSub const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_AnswerMode const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_PrivAnswerMode const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentType const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_IdentityInfo const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_From const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_To const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ReplyTo const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ReferTo const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ReferredBy const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_PCalledPartyId const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentTransferEncoding const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Organization const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SecWebSocketKey const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SecWebSocketKey1 const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SecWebSocketKey2 const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Origin const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Host const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SecWebSocketAccept const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Server const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Subject const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_UserAgent const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Timestamp const&) const resip::SipMessage::header(resip::H_ContentLength const&) const Line | Count | Source | 1433 | 8.62k | SipMessage::header(const H_##_header& headerType) const \ | 1434 | 8.62k | { \ | 1435 | 8.62k | HeaderFieldValueList* hfvs = ensureHeader(headerType.getTypeNum()); \ | 1436 | 8.62k | if (hfvs->getParserContainer() == 0) \ | 1437 | 8.62k | { \ | 1438 | 259 | SipMessage* nc_this(const_cast<SipMessage*>(this)); \ | 1439 | 259 | hfvs->setParserContainer(nc_this->makeParserContainer<H_##_header::Type>(hfvs, headerType.getTypeNum())); \ | 1440 | 259 | } \ | 1441 | 8.62k | return static_cast<ParserContainer<H_##_header::Type>*>(hfvs->getParserContainer())->front(); \ | 1442 | 8.62k | } \ |
Unexecuted instantiation: resip::SipMessage::header(resip::H_MaxForwards const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_MinExpires const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_RSeq const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_RetryAfter const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_FlowTimer const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Expires const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SessionExpires const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_MinSE const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_CallID const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Replaces const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_InReplyTo const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Join const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_TargetDialog const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_AuthenticationInfo const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_CSeq const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Date const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_RAck const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_PChargingVector const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_PChargingFunctionAddresses const&) const |
1443 | | \ |
1444 | | H_##_header::Type& \ |
1445 | 236 | SipMessage::header(const H_##_header& headerType) \ |
1446 | 236 | { \ |
1447 | 236 | HeaderFieldValueList* hfvs = ensureHeader(headerType.getTypeNum()); \ |
1448 | 236 | if (hfvs->getParserContainer() == 0) \ |
1449 | 236 | { \ |
1450 | 0 | hfvs->setParserContainer(makeParserContainer<H_##_header::Type>(hfvs, headerType.getTypeNum())); \ |
1451 | 0 | } \ |
1452 | 236 | return static_cast<ParserContainer<H_##_header::Type>*>(hfvs->getParserContainer())->front(); \ |
1453 | 236 | } Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentDisposition const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentEncoding const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_MIMEVersion const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Priority const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Event const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SubscriptionState const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SIPETag const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SIPIfMatch const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentId const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ReferSub const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_AnswerMode const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_PrivAnswerMode const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentType const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_IdentityInfo const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_From const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_To const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ReplyTo const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ReferTo const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ReferredBy const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_PCalledPartyId const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentTransferEncoding const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Organization const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SecWebSocketKey const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SecWebSocketKey1 const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SecWebSocketKey2 const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Origin const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Host const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SecWebSocketAccept const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Server const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Subject const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_UserAgent const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Timestamp const&) resip::SipMessage::header(resip::H_ContentLength const&) Line | Count | Source | 1445 | 236 | SipMessage::header(const H_##_header& headerType) \ | 1446 | 236 | { \ | 1447 | 236 | HeaderFieldValueList* hfvs = ensureHeader(headerType.getTypeNum()); \ | 1448 | 236 | if (hfvs->getParserContainer() == 0) \ | 1449 | 236 | { \ | 1450 | 0 | hfvs->setParserContainer(makeParserContainer<H_##_header::Type>(hfvs, headerType.getTypeNum())); \ | 1451 | 0 | } \ | 1452 | 236 | return static_cast<ParserContainer<H_##_header::Type>*>(hfvs->getParserContainer())->front(); \ | 1453 | 236 | } |
Unexecuted instantiation: resip::SipMessage::header(resip::H_MaxForwards const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_MinExpires const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_RSeq const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_RetryAfter const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_FlowTimer const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Expires const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SessionExpires const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_MinSE const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_CallID const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Replaces const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_InReplyTo const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Join const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_TargetDialog const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_AuthenticationInfo const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_CSeq const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Date const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_RAck const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_PChargingVector const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_PChargingFunctionAddresses const&) |
1454 | | |
1455 | | #undef defineMultiHeader |
1456 | | #define defineMultiHeader(_header, _name, _type, _rfc) \ |
1457 | | const H_##_header##s::Type& \ |
1458 | 0 | SipMessage::header(const H_##_header##s& headerType) const \ |
1459 | 0 | { \ |
1460 | 0 | HeaderFieldValueList* hfvs = ensureHeaders(headerType.getTypeNum()); \ |
1461 | 0 | if (hfvs->getParserContainer() == 0) \ |
1462 | 0 | { \ |
1463 | 0 | SipMessage* nc_this(const_cast<SipMessage*>(this)); \ |
1464 | 0 | hfvs->setParserContainer(nc_this->makeParserContainer<H_##_header##s::ContainedType>(hfvs, headerType.getTypeNum())); \ |
1465 | 0 | } \ |
1466 | 0 | return *static_cast<H_##_header##s::Type*>(hfvs->getParserContainer()); \ |
1467 | 0 | } \ Unexecuted instantiation: resip::SipMessage::header(resip::H_AllowEventss const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Identitys const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_AcceptEncodings const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_AcceptLanguages const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Allows const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentLanguages const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ProxyRequires const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Requires const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Supporteds const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Unsupporteds const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SecurityClients const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SecurityServers const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_SecurityVerifys const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_RequestDispositions const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Reasons const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Privacys const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_PMediaAuthorizations const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Accepts const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_CallInfos const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_AlertInfos const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ErrorInfos const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_RecordRoutes const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Routes const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Contacts const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Paths const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_AcceptContacts const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_RejectContacts const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_PAssertedIdentitys const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_PPreferredIdentitys const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_PAssociatedUris const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ServiceRoutes const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Cookies const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Authorizations const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ProxyAuthenticates const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_ProxyAuthorizations const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_WWWAuthenticates const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Warnings const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_Vias const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_RemotePartyIds const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_HistoryInfos const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_PAccessNetworkInfos const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_PVisitedNetworkIDs const&) const Unexecuted instantiation: resip::SipMessage::header(resip::H_UserToUsers const&) const |
1468 | | \ |
1469 | | H_##_header##s::Type& \ |
1470 | 0 | SipMessage::header(const H_##_header##s& headerType) \ |
1471 | 0 | { \ |
1472 | 0 | HeaderFieldValueList* hfvs = ensureHeaders(headerType.getTypeNum()); \ |
1473 | 0 | if (hfvs->getParserContainer() == 0) \ |
1474 | 0 | { \ |
1475 | 0 | hfvs->setParserContainer(makeParserContainer<H_##_header##s::ContainedType>(hfvs, headerType.getTypeNum())); \ |
1476 | 0 | } \ |
1477 | 0 | return *static_cast<H_##_header##s::Type*>(hfvs->getParserContainer()); \ |
1478 | 0 | } Unexecuted instantiation: resip::SipMessage::header(resip::H_AllowEventss const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Identitys const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_AcceptEncodings const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_AcceptLanguages const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Allows const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ContentLanguages const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ProxyRequires const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Requires const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Supporteds const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Unsupporteds const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SecurityClients const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SecurityServers const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_SecurityVerifys const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_RequestDispositions const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Reasons const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Privacys const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_PMediaAuthorizations const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Accepts const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_CallInfos const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_AlertInfos const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ErrorInfos const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_RecordRoutes const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Routes const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Contacts const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Paths const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_AcceptContacts const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_RejectContacts const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_PAssertedIdentitys const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_PPreferredIdentitys const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_PAssociatedUris const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ServiceRoutes const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Cookies const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Authorizations const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ProxyAuthenticates const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_ProxyAuthorizations const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_WWWAuthenticates const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Warnings const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_Vias const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_RemotePartyIds const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_HistoryInfos const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_PAccessNetworkInfos const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_PVisitedNetworkIDs const&) Unexecuted instantiation: resip::SipMessage::header(resip::H_UserToUsers const&) |
1479 | | |
1480 | | defineHeader(ContentDisposition, "Content-Disposition", Token, "RFC 3261"); |
1481 | | defineHeader(ContentEncoding, "Content-Encoding", Token, "RFC 3261"); |
1482 | | defineHeader(MIMEVersion, "Mime-Version", Token, "RFC 3261"); |
1483 | | defineHeader(Priority, "Priority", Token, "RFC 3261"); |
1484 | | defineHeader(Event, "Event", Token, "RFC 3265"); |
1485 | | defineHeader(SubscriptionState, "Subscription-State", Token, "RFC 3265"); |
1486 | | defineHeader(SIPETag, "SIP-ETag", Token, "RFC 3903"); |
1487 | | defineHeader(SIPIfMatch, "SIP-If-Match", Token, "RFC 3903"); |
1488 | | defineHeader(ContentId, "Content-ID", Token, "RFC 2045"); |
1489 | | defineMultiHeader(AllowEvents, "Allow-Events", Token, "RFC 3265"); |
1490 | | defineMultiHeader(Identity, "Identity", StringCategory, "RFC 8224"); // Originally defined in RFC 4474 as a single header, but later modified by RFC8224 to be a multiheader |
1491 | | defineMultiHeader(AcceptEncoding, "Accept-Encoding", Token, "RFC 3261"); |
1492 | | defineMultiHeader(AcceptLanguage, "Accept-Language", Token, "RFC 3261"); |
1493 | | defineMultiHeader(Allow, "Allow", Token, "RFC 3261"); |
1494 | | defineMultiHeader(ContentLanguage, "Content-Language", Token, "RFC 3261"); |
1495 | | defineMultiHeader(ProxyRequire, "Proxy-Require", Token, "RFC 3261"); |
1496 | | defineMultiHeader(Require, "Require", Token, "RFC 3261"); |
1497 | | defineMultiHeader(Supported, "Supported", Token, "RFC 3261"); |
1498 | | defineMultiHeader(Unsupported, "Unsupported", Token, "RFC 3261"); |
1499 | | defineMultiHeader(SecurityClient, "Security-Client", Token, "RFC 3329"); |
1500 | | defineMultiHeader(SecurityServer, "Security-Server", Token, "RFC 3329"); |
1501 | | defineMultiHeader(SecurityVerify, "Security-Verify", Token, "RFC 3329"); |
1502 | | defineMultiHeader(RequestDisposition, "Request-Disposition", Token, "RFC 3841"); |
1503 | | defineMultiHeader(Reason, "Reason", Token, "RFC 3326"); |
1504 | | defineMultiHeader(Privacy, "Privacy", PrivacyCategory, "RFC 3323"); |
1505 | | defineMultiHeader(PMediaAuthorization, "P-Media-Authorization", Token, "RFC 3313"); |
1506 | | defineHeader(ReferSub, "Refer-Sub", Token, "RFC 4488"); |
1507 | | defineHeader(AnswerMode, "Answer-Mode", Token, "draft-ietf-answermode-01"); |
1508 | | defineHeader(PrivAnswerMode, "Priv-Answer-Mode", Token, "draft-ietf-answermode-01"); |
1509 | | |
1510 | | defineMultiHeader(Accept, "Accept", Mime, "RFC 3261"); |
1511 | | defineHeader(ContentType, "Content-Type", Mime, "RFC 3261"); |
1512 | | |
1513 | | defineMultiHeader(CallInfo, "Call-Info", GenericUri, "RFC 3261"); |
1514 | | defineMultiHeader(AlertInfo, "Alert-Info", GenericUri, "RFC 3261"); |
1515 | | defineMultiHeader(ErrorInfo, "Error-Info", GenericUri, "RFC 3261"); |
1516 | | defineHeader(IdentityInfo, "Identity-Info", GenericUri, "RFC 4474"); |
1517 | | |
1518 | | defineMultiHeader(RecordRoute, "Record-Route", NameAddr, "RFC 3261"); |
1519 | | defineMultiHeader(Route, "Route", NameAddr, "RFC 3261"); |
1520 | | defineMultiHeader(Contact, "Contact", NameAddr, "RFC 3261"); |
1521 | | defineHeader(From, "From", NameAddr, "RFC 3261"); |
1522 | | defineHeader(To, "To", NameAddr, "RFC 3261"); |
1523 | | defineHeader(ReplyTo, "Reply-To", NameAddr, "RFC 3261"); |
1524 | | defineHeader(ReferTo, "Refer-To", NameAddr, "RFC 3515"); |
1525 | | defineHeader(ReferredBy, "Referred-By", NameAddr, "RFC 3892"); |
1526 | | defineMultiHeader(Path, "Path", NameAddr, "RFC 3327"); |
1527 | | defineMultiHeader(AcceptContact, "Accept-Contact", NameAddr, "RFC 3841"); |
1528 | | defineMultiHeader(RejectContact, "Reject-Contact", NameAddr, "RFC 3841"); |
1529 | | defineMultiHeader(PAssertedIdentity, "P-Asserted-Identity", NameAddr, "RFC 3325"); |
1530 | | defineMultiHeader(PPreferredIdentity, "P-Preferred-Identity", NameAddr, "RFC 3325"); |
1531 | | defineHeader(PCalledPartyId, "P-Called-Party-ID", NameAddr, "RFC 3455"); |
1532 | | defineMultiHeader(PAssociatedUri, "P-Associated-URI", NameAddr, "RFC 3455"); |
1533 | | defineMultiHeader(ServiceRoute, "Service-Route", NameAddr, "RFC 3608"); |
1534 | | |
1535 | | defineHeader(ContentTransferEncoding, "Content-Transfer-Encoding", StringCategory, "RFC ?"); |
1536 | | defineHeader(Organization, "Organization", StringCategory, "RFC 3261"); |
1537 | | defineHeader(SecWebSocketKey, "Sec-WebSocket-Key", StringCategory, "RFC 6455"); |
1538 | | defineHeader(SecWebSocketKey1, "Sec-WebSocket-Key1", StringCategory, "draft-hixie- thewebsocketprotocol-76"); |
1539 | | defineHeader(SecWebSocketKey2, "Sec-WebSocket-Key2", StringCategory, "draft-hixie- thewebsocketprotocol-76"); |
1540 | | defineHeader(Origin, "Origin", StringCategory, "draft-hixie- thewebsocketprotocol-76"); |
1541 | | defineHeader(Host, "Host", StringCategory, "draft-hixie- thewebsocketprotocol-76"); |
1542 | | defineHeader(SecWebSocketAccept, "Sec-WebSocket-Accept", StringCategory, "RFC 6455"); |
1543 | | defineMultiHeader(Cookie, "Cookie", StringCategory, "RFC 6265"); |
1544 | | defineHeader(Server, "Server", StringCategory, "RFC 3261"); |
1545 | | defineHeader(Subject, "Subject", StringCategory, "RFC 3261"); |
1546 | | defineHeader(UserAgent, "User-Agent", StringCategory, "RFC 3261"); |
1547 | | defineHeader(Timestamp, "Timestamp", StringCategory, "RFC 3261"); |
1548 | | |
1549 | | defineHeader(ContentLength, "Content-Length", UInt32Category, "RFC 3261"); |
1550 | | defineHeader(MaxForwards, "Max-Forwards", UInt32Category, "RFC 3261"); |
1551 | | defineHeader(MinExpires, "Min-Expires", Uint32Category, "RFC 3261"); |
1552 | | defineHeader(RSeq, "RSeq", UInt32Category, "RFC 3261"); |
1553 | | |
1554 | | // !dlb! this one is not quite right -- can have (comment) after field value |
1555 | | defineHeader(RetryAfter, "Retry-After", UInt32Category, "RFC 3261"); |
1556 | | defineHeader(FlowTimer, "Flow-Timer", UInt32Category, "RFC 5626"); |
1557 | | |
1558 | | defineHeader(Expires, "Expires", ExpiresCategory, "RFC 3261"); |
1559 | | defineHeader(SessionExpires, "Session-Expires", ExpiresCategory, "RFC 4028"); |
1560 | | defineHeader(MinSE, "Min-SE", ExpiresCategory, "RFC 4028"); |
1561 | | |
1562 | | defineHeader(CallID, "Call-ID", CallID, "RFC 3261"); |
1563 | | defineHeader(Replaces, "Replaces", CallID, "RFC 3891"); |
1564 | | defineHeader(InReplyTo, "In-Reply-To", CallID, "RFC 3261"); |
1565 | | defineHeader(Join, "Join", CallId, "RFC 3911"); |
1566 | | defineHeader(TargetDialog, "Target-Dialog", CallId, "RFC 4538"); |
1567 | | |
1568 | | defineHeader(AuthenticationInfo, "Authentication-Info", Auth, "RFC 3261"); |
1569 | | defineMultiHeader(Authorization, "Authorization", Auth, "RFC 3261"); |
1570 | | defineMultiHeader(ProxyAuthenticate, "Proxy-Authenticate", Auth, "RFC 3261"); |
1571 | | defineMultiHeader(ProxyAuthorization, "Proxy-Authorization", Auth, "RFC 3261"); |
1572 | | defineMultiHeader(WWWAuthenticate, "Www-Authenticate", Auth, "RFC 3261"); |
1573 | | |
1574 | | defineHeader(CSeq, "CSeq", CSeqCategory, "RFC 3261"); |
1575 | | defineHeader(Date, "Date", DateCategory, "RFC 3261"); |
1576 | | defineMultiHeader(Warning, "Warning", WarningCategory, "RFC 3261"); |
1577 | | defineMultiHeader(Via, "Via", Via, "RFC 3261"); |
1578 | | defineHeader(RAck, "RAck", RAckCategory, "RFC 3262"); |
1579 | | defineMultiHeader(RemotePartyId, "Remote-Party-ID", NameAddr, "draft-ietf-sip-privacy-04"); // ?bwc? Not in 3323, should we keep? |
1580 | | defineMultiHeader(HistoryInfo, "History-Info", NameAddr, "RFC 4244"); |
1581 | | |
1582 | | defineMultiHeader(PAccessNetworkInfo, "P-Access-Network-Info", Token, "RFC 7315"); // section 5.4. |
1583 | | defineHeader(PChargingVector, "P-Charging-Vector", Token, "RFC 3455"); |
1584 | | defineHeader(PChargingFunctionAddresses, "P-Charging-Function-Addresses", Token, "RFC 3455"); |
1585 | | defineMultiHeader(PVisitedNetworkID, "P-Visited-Network-ID", TokenOrQuotedStringCategory, "RFC 3455"); |
1586 | | |
1587 | | defineMultiHeader(UserToUser, "User-to-User", TokenOrQuotedStringCategory, "draft-ietf-cuss-sip-uui-17"); |
1588 | | |
1589 | | #endif |
1590 | | |
1591 | | const HeaderFieldValueList* |
1592 | | SipMessage::getRawHeader(Headers::Type headerType) const |
1593 | 0 | { |
1594 | 0 | if(mHeaderIndices[headerType]>0) |
1595 | 0 | { |
1596 | 0 | return mHeaders[mHeaderIndices[headerType]]; |
1597 | 0 | } |
1598 | | |
1599 | 0 | return 0; |
1600 | 0 | } |
1601 | | |
1602 | | void |
1603 | | SipMessage::setRawHeader(const HeaderFieldValueList* hfvs, Headers::Type headerType) |
1604 | 0 | { |
1605 | 0 | HeaderFieldValueList* copy=0; |
1606 | 0 | if (mHeaderIndices[headerType] == 0) |
1607 | 0 | { |
1608 | 0 | mHeaderIndices[headerType]=(short)mHeaders.size(); |
1609 | 0 | copy=getCopyHfvl(*hfvs); |
1610 | 0 | mHeaders.push_back(copy); |
1611 | 0 | } |
1612 | 0 | else |
1613 | 0 | { |
1614 | 0 | if(mHeaderIndices[headerType]<0) |
1615 | 0 | { |
1616 | | // Setting a previously removed header type; there is already an |
1617 | | // empty HeaderFieldValueList in mHeaders for this type, all we |
1618 | | // need to do is flip the sign to re-enable it. |
1619 | 0 | mHeaderIndices[headerType]=-mHeaderIndices[headerType]; |
1620 | 0 | } |
1621 | 0 | copy = mHeaders[mHeaderIndices[headerType]]; |
1622 | 0 | *copy=*hfvs; |
1623 | 0 | } |
1624 | 0 | if(!Headers::isMulti(headerType) && copy->parsedEmpty()) |
1625 | 0 | { |
1626 | 0 | copy->push_back(0,0,false); |
1627 | 0 | } |
1628 | 0 | } |
1629 | | |
1630 | | void |
1631 | | SipMessage::setForceTarget(const Uri& uri) |
1632 | 0 | { |
1633 | 0 | if (mForceTarget) |
1634 | 0 | { |
1635 | 0 | *mForceTarget = uri; |
1636 | 0 | } |
1637 | 0 | else |
1638 | 0 | { |
1639 | 0 | mForceTarget = new Uri(uri); |
1640 | 0 | } |
1641 | 0 | } |
1642 | | |
1643 | | void |
1644 | | SipMessage::clearForceTarget() |
1645 | 0 | { |
1646 | 0 | delete mForceTarget; |
1647 | 0 | mForceTarget = 0; |
1648 | 0 | } |
1649 | | |
1650 | | const Uri& |
1651 | | SipMessage::getForceTarget() const |
1652 | 0 | { |
1653 | 0 | resip_assert(mForceTarget); |
1654 | 0 | return *mForceTarget; |
1655 | 0 | } |
1656 | | |
1657 | | bool |
1658 | | SipMessage::hasForceTarget() const |
1659 | 0 | { |
1660 | 0 | return (mForceTarget != 0); |
1661 | 0 | } |
1662 | | |
1663 | | SipMessage& |
1664 | | SipMessage::mergeUri(const Uri& source) |
1665 | 0 | { |
1666 | 0 | header(h_RequestLine).uri() = source; |
1667 | 0 | header(h_RequestLine).uri().removeEmbedded(); |
1668 | |
|
1669 | 0 | if (source.exists(p_method)) |
1670 | 0 | { |
1671 | 0 | header(h_RequestLine).method() = getMethodType(source.param(p_method)); |
1672 | 0 | header(h_RequestLine).uri().remove(p_method); |
1673 | 0 | } |
1674 | | |
1675 | | //19.1.5 |
1676 | | //dangerous headers not included in merge: |
1677 | | // From, Call-ID, Cseq, Via, Record Route, Route, Accept, Accept-Encoding, |
1678 | | // Accept-Langauge, Allow, Contact, Organization, Supported, User-Agent |
1679 | | |
1680 | | //from the should-verify section, remove for now, some never seem to make |
1681 | | //sense: |
1682 | | // Content-Encoding, Content-Language, Content-Length, Content-Type, Date, |
1683 | | // Mime-Version, and TimeStamp |
1684 | |
|
1685 | 0 | if (source.hasEmbedded()) |
1686 | 0 | { |
1687 | 0 | h_AuthenticationInfo.merge(*this, source.embedded()); |
1688 | 0 | h_ContentTransferEncoding.merge(*this, source.embedded()); |
1689 | 0 | h_Event.merge(*this, source.embedded()); |
1690 | 0 | h_Expires.merge(*this, source.embedded()); |
1691 | 0 | h_SessionExpires.merge(*this, source.embedded()); |
1692 | 0 | h_MinSE.merge(*this, source.embedded()); |
1693 | 0 | h_InReplyTo.merge(*this, source.embedded()); |
1694 | 0 | h_MaxForwards.merge(*this, source.embedded()); |
1695 | 0 | h_MinExpires.merge(*this, source.embedded()); |
1696 | 0 | h_Priority.merge(*this, source.embedded()); |
1697 | 0 | h_ReferTo.merge(*this, source.embedded()); |
1698 | 0 | h_ReferredBy.merge(*this, source.embedded()); |
1699 | 0 | h_Replaces.merge(*this, source.embedded()); |
1700 | 0 | h_ReplyTo.merge(*this, source.embedded()); |
1701 | 0 | h_RetryAfter.merge(*this, source.embedded()); |
1702 | 0 | h_Server.merge(*this, source.embedded()); |
1703 | 0 | h_SIPETag.merge(*this, source.embedded()); |
1704 | 0 | h_SIPIfMatch.merge(*this, source.embedded()); |
1705 | 0 | h_Subject.merge(*this, source.embedded()); |
1706 | 0 | h_SubscriptionState.merge(*this, source.embedded()); |
1707 | 0 | h_To.merge(*this, source.embedded()); |
1708 | 0 | h_Warnings.merge(*this, source.embedded()); |
1709 | |
|
1710 | 0 | h_SecurityClients.merge(*this, source.embedded()); |
1711 | 0 | h_SecurityServers.merge(*this, source.embedded()); |
1712 | 0 | h_SecurityVerifys.merge(*this, source.embedded()); |
1713 | |
|
1714 | 0 | h_Authorizations.merge(*this, source.embedded()); |
1715 | 0 | h_ProxyAuthenticates.merge(*this, source.embedded()); |
1716 | 0 | h_WWWAuthenticates.merge(*this, source.embedded()); |
1717 | 0 | h_ProxyAuthorizations.merge(*this, source.embedded()); |
1718 | |
|
1719 | 0 | h_AlertInfos.merge(*this, source.embedded()); |
1720 | 0 | h_AllowEvents.merge(*this, source.embedded()); |
1721 | 0 | h_CallInfos.merge(*this, source.embedded()); |
1722 | 0 | h_ErrorInfos.merge(*this, source.embedded()); |
1723 | 0 | h_ProxyRequires.merge(*this, source.embedded()); |
1724 | 0 | h_Requires.merge(*this, source.embedded()); |
1725 | 0 | h_Unsupporteds.merge(*this, source.embedded()); |
1726 | 0 | h_AnswerMode.merge(*this, source.embedded()); |
1727 | 0 | h_PrivAnswerMode.merge(*this, source.embedded()); |
1728 | |
|
1729 | 0 | h_RSeq.merge(*this, source.embedded()); |
1730 | 0 | h_RAck.merge(*this, source.embedded()); |
1731 | 0 | } |
1732 | | //unknown header merge |
1733 | 0 | return *this; |
1734 | 0 | } |
1735 | | |
1736 | | void |
1737 | | SipMessage::setSecurityAttributes(std::unique_ptr<SecurityAttributes> sec) noexcept |
1738 | 0 | { |
1739 | 0 | mSecurityAttributes = std::move(sec); |
1740 | 0 | } |
1741 | | |
1742 | | void |
1743 | | SipMessage::callOutboundDecorators(const Tuple &src, |
1744 | | const Tuple &dest, |
1745 | | const Data& sigcompId) |
1746 | 0 | { |
1747 | 0 | if(mIsDecorated) |
1748 | 0 | { |
1749 | 0 | rollbackOutboundDecorators(); |
1750 | 0 | } |
1751 | |
|
1752 | 0 | std::vector<MessageDecorator*>::iterator i; |
1753 | 0 | for (i = mOutboundDecorators.begin(); |
1754 | 0 | i != mOutboundDecorators.end(); i++) |
1755 | 0 | { |
1756 | 0 | (*i)->decorateMessage(*this, src, dest, sigcompId); |
1757 | 0 | } |
1758 | 0 | mIsDecorated = true; |
1759 | 0 | } |
1760 | | |
1761 | | void |
1762 | | SipMessage::clearOutboundDecorators() |
1763 | 0 | { |
1764 | 0 | while(!mOutboundDecorators.empty()) |
1765 | 0 | { |
1766 | 0 | delete mOutboundDecorators.back(); |
1767 | 0 | mOutboundDecorators.pop_back(); |
1768 | 0 | } |
1769 | 0 | } |
1770 | | |
1771 | | void |
1772 | | SipMessage::rollbackOutboundDecorators() |
1773 | 0 | { |
1774 | 0 | std::vector<MessageDecorator*>::reverse_iterator r; |
1775 | 0 | for(r=mOutboundDecorators.rbegin(); r!=mOutboundDecorators.rend(); ++r) |
1776 | 0 | { |
1777 | 0 | (*r)->rollbackMessage(*this); |
1778 | 0 | } |
1779 | 0 | mIsDecorated = false; |
1780 | 0 | } |
1781 | | |
1782 | | void |
1783 | | SipMessage::copyOutboundDecoratorsToStackCancel(SipMessage& cancel) |
1784 | 0 | { |
1785 | 0 | std::vector<MessageDecorator*>::iterator i; |
1786 | 0 | for (i = mOutboundDecorators.begin(); |
1787 | 0 | i != mOutboundDecorators.end(); i++) |
1788 | 0 | { |
1789 | 0 | if((*i)->copyToStackCancels()) |
1790 | 0 | { |
1791 | 0 | cancel.addOutboundDecorator(std::unique_ptr<MessageDecorator>((*i)->clone())); |
1792 | 0 | } |
1793 | 0 | } |
1794 | 0 | } |
1795 | | |
1796 | | void |
1797 | | SipMessage::copyOutboundDecoratorsToStackFailureAck(SipMessage& ack) |
1798 | 0 | { |
1799 | 0 | std::vector<MessageDecorator*>::iterator i; |
1800 | 0 | for (i = mOutboundDecorators.begin(); |
1801 | 0 | i != mOutboundDecorators.end(); i++) |
1802 | 0 | { |
1803 | 0 | if((*i)->copyToStackFailureAcks()) |
1804 | 0 | { |
1805 | 0 | ack.addOutboundDecorator(std::unique_ptr<MessageDecorator>((*i)->clone())); |
1806 | 0 | } |
1807 | 0 | } |
1808 | 0 | } |
1809 | | |
1810 | | /* ==================================================================== |
1811 | | * The Vovida Software License, Version 1.0 |
1812 | | * |
1813 | | * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. |
1814 | | * |
1815 | | * Redistribution and use in source and binary forms, with or without |
1816 | | * modification, are permitted provided that the following conditions |
1817 | | * are met: |
1818 | | * |
1819 | | * 1. Redistributions of source code must retain the above copyright |
1820 | | * notice, this list of conditions and the following disclaimer. |
1821 | | * |
1822 | | * 2. Redistributions in binary form must reproduce the above copyright |
1823 | | * notice, this list of conditions and the following disclaimer in |
1824 | | * the documentation and/or other materials provided with the |
1825 | | * distribution. |
1826 | | * |
1827 | | * 3. The names "VOCAL", "Vovida Open Communication Application Library", |
1828 | | * and "Vovida Open Communication Application Library (VOCAL)" must |
1829 | | * not be used to endorse or promote products derived from this |
1830 | | * software without prior written permission. For written |
1831 | | * permission, please contact vocal@vovida.org. |
1832 | | * |
1833 | | * 4. Products derived from this software may not be called "VOCAL", nor |
1834 | | * may "VOCAL" appear in their name, without prior written |
1835 | | * permission of Vovida Networks, Inc. |
1836 | | * |
1837 | | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
1838 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
1839 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND |
1840 | | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA |
1841 | | * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES |
1842 | | * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, |
1843 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
1844 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
1845 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
1846 | | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
1847 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
1848 | | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
1849 | | * DAMAGE. |
1850 | | * |
1851 | | * ==================================================================== |
1852 | | * |
1853 | | * This software consists of voluntary contributions made by Vovida |
1854 | | * Networks, Inc. and many individuals on behalf of Vovida Networks, |
1855 | | * Inc. For more information on Vovida Networks, Inc., please see |
1856 | | * <http://www.vovida.org/>. |
1857 | | * |
1858 | | * vi: set shiftwidth=3 expandtab: |
1859 | | */ |