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