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