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