reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
BranchParameter.cxx
Go to the documentation of this file.
1#if defined(HAVE_CONFIG_H)
2#include "config.h"
3#endif
4
5#include "rutil/ResipAssert.h"
9#include "rutil/Random.hxx"
10#include "rutil/Time.hxx"
11#include "rutil/DataStream.hxx"
12#include "rutil/Coders.hxx"
14
15#include "rutil/Logger.hxx"
17
18using namespace resip;
19using namespace std;
20
21#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
22
23namespace {
24
25inline Data generateTransactionId()
26{
27 Data d;
28 {
29 DataStream s(d);
31 }
32 return d;
33}
34
35}
36
38 ParseBuffer& pb,
39 const std::bitset<256>& terminators)
40 : Parameter(type),
41 mHasMagicCookie(false),
42 mIsMyBranch(false),
43 mTransactionId(),
44 mTransportSeq(1),
45 mClientData(),
46 mInteropMagicCookie(0),
47 mSigcompCompartment()
48{
49 try
50 {
51 pb.skipWhitespace();
53 pb.skipWhitespace();
54 if (pb.lengthRemaining() >= 7)
55 {
56 if(memcmp(pb.position(), Symbols::MagicCookie, 7) == 0)
57 {
58 mHasMagicCookie=true;
59 pb.skipN(7);
60 }
61 // !bwc! This no-case comparison is expensive; only do it if the case-
62 // sensitive comparison fails.
63 else if(strncasecmp(pb.position(), Symbols::MagicCookie, 7) == 0)
64 {
65 mHasMagicCookie=true;
66 mInteropMagicCookie = new Data(pb.position(), 7);
67 pb.skipN(7);
68 }
69 }
70
71 const char* start = pb.position();
72 static std::bitset<256> delimiter=Data::toBitset("\r\n\t ;=?>");
73
74 if (mHasMagicCookie &&
75 (pb.end() - start > 8) &&
76 // look for prefix cookie (maybe make this bigger?)
77 memcmp(start, Symbols::resipCookie, 8) == 0)
78 {
79 // ?bwc? Wrap this stuff in try/catch, just in case of false positives?
80 const char* curr=start;
81 mIsMyBranch = true;
82 pb.skipN(8);
83
84 mTransportSeq=pb.uInt32();
85
86 curr=pb.skipChar('-');
87 pb.skipToChar('-');
88 Data encoded;
89 pb.data(encoded, curr);
90 if(!encoded.empty())
91 {
92 // !bwc! Expensive! Also, Base64 isn't case-insensitive.
93 mClientData = encoded.base64decode();
94 }
95
96 curr=pb.skipChar('-');
97 pb.skipToChar('-');
98 pb.data(encoded,curr);
99 if(!encoded.empty())
100 {
101 // !bwc! Expensive! Also, Base64 isn't case-insensitive.
102 mSigcompCompartment = encoded.base64decode();
103 }
104
105 start=pb.skipChar('-');
106 }
107 pb.skipToOneOf(delimiter);
108 pb.data(mTransactionId, start);
109 }
110 catch(resip::ParseException& e)
111 {
112 mTransactionId=generateTransactionId();
113 throw e;
114 }
115}
116
118 : Parameter(type),
119 mHasMagicCookie(true),
120 mIsMyBranch(true),
121 mTransactionId(generateTransactionId()),
122 mTransportSeq(1),
123 mInteropMagicCookie(0),
124 mSigcompCompartment()
125{
126}
127
129 : Parameter(other),
130 mHasMagicCookie(other.mHasMagicCookie),
131 mIsMyBranch(other.mIsMyBranch),
132 mTransactionId(other.mTransactionId),
133 mTransportSeq(other.mTransportSeq),
134 mClientData(other.mClientData),
135 mSigcompCompartment(other.mSigcompCompartment)
136{
137 if (other.mInteropMagicCookie)
138 {
139 mInteropMagicCookie = new Data(*other.mInteropMagicCookie);
140 }
141 else
142 {
143 mInteropMagicCookie = 0;
144 }
145}
146
148{
149 delete mInteropMagicCookie;
150}
151
154{
155 if (this != &other)
156 {
157 mHasMagicCookie = other.mHasMagicCookie;
158 mIsMyBranch = other.mIsMyBranch;
159 mTransactionId = other.mTransactionId;
160 mTransportSeq = other.mTransportSeq;
161 mClientData = other.mClientData;
162 mSigcompCompartment = other.mSigcompCompartment;
163 if (other.mInteropMagicCookie)
164 {
165 delete mInteropMagicCookie;
166 mInteropMagicCookie = new Data(*other.mInteropMagicCookie);
167 }
168 else
169 {
170 delete mInteropMagicCookie;
171 mInteropMagicCookie = 0;
172 }
173 }
174 return *this;
175}
176
177bool
179{
180 if (mIsMyBranch != other.mIsMyBranch ||
181 mHasMagicCookie != other.mHasMagicCookie ||
182 mTransportSeq != other.mTransportSeq ||
183 mTransactionId != other.mTransactionId ||
184 mClientData != other.mClientData ||
185 mSigcompCompartment != other.mSigcompCompartment)
186 {
187 return false;
188 }
189 return true;
190}
191
192bool
194{
195 return mHasMagicCookie;
196}
197
198const Data&
200{
201 return mTransactionId;
202}
203
204void
206{
207 resip_assert(mIsMyBranch);
208 mTransportSeq++;
209}
210
211Data&
213{
214 return mClientData;
215}
216
217const Data&
219{
220 return mClientData;
221}
222
226void
228{
229 if (id.size() == 0)
230 {
231 mSigcompCompartment = Data::Empty;
232 }
233
234 // These will often (but not always) be UUID URNs in angle brackets;
235 // e.g.: <urn:uuid:fa33c72d-121f-47e8-42e2-1eb6e24aba64>
236
237 // Ideally, we would detect this, strip out everything that isn't
238 // hex, and convert the hex to raw data.
239
240 mSigcompCompartment = id;
241}
242
243Data
245{
246 return mSigcompCompartment;
247}
248
249void
250BranchParameter::reset(const Data& transactionId)
251{
252 mHasMagicCookie = true;
253 mIsMyBranch = true;
254 delete mInteropMagicCookie;
255 mInteropMagicCookie = 0;
256
257 mSigcompCompartment = Data::Empty;
258
259 mTransportSeq = 1;
260 if (!transactionId.empty())
261 {
262 mTransactionId = transactionId;
263 }
264 else
265 {
266 mTransactionId = generateTransactionId();
267 }
268}
269
270Parameter*
272{
273 return new BranchParameter(*this);
274}
275
277BranchParameter::encode(EncodeStream& stream) const
278{
279 stream << getName() << Symbols::EQUALS;
280 if (mHasMagicCookie)
281 {
282 if (mInteropMagicCookie)
283 {
284 stream << *mInteropMagicCookie;
285 }
286 else
287 {
288 stream << Symbols::MagicCookie;
289 }
290 }
291 if (mIsMyBranch)
292 {
293 stream << Symbols::resipCookie;
294 stream << mTransportSeq;
295 stream << Symbols::DASH;
296 if(!mClientData.empty()) // base64encode() makes copies
297 {
298 // !bwc! We should be using hex encoding; branch params are supposed to
299 // be case-insensitive.
300 stream << mClientData.base64encode(true/*safe URL*/);
301 }
302 stream << Symbols::DASH;
303 if(!mSigcompCompartment.empty()) // base64encode() makes copies
304 {
305 // !bwc! We should be using hex encoding; branch params are supposed to
306 // be case-insensitive.
307 stream << mSigcompCompartment.base64encode(true);
308 }
309 stream << Symbols::DASH;
310 }
311 stream << mTransactionId;
312
313 return stream;
314}
315
316
317/* ====================================================================
318 * The Vovida Software License, Version 1.0
319 *
320 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
321 *
322 * Redistribution and use in source and binary forms, with or without
323 * modification, are permitted provided that the following conditions
324 * are met:
325 *
326 * 1. Redistributions of source code must retain the above copyright
327 * notice, this list of conditions and the following disclaimer.
328 *
329 * 2. Redistributions in binary form must reproduce the above copyright
330 * notice, this list of conditions and the following disclaimer in
331 * the documentation and/or other materials provided with the
332 * distribution.
333 *
334 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
335 * and "Vovida Open Communication Application Library (VOCAL)" must
336 * not be used to endorse or promote products derived from this
337 * software without prior written permission. For written
338 * permission, please contact vocal@vovida.org.
339 *
340 * 4. Products derived from this software may not be called "VOCAL", nor
341 * may "VOCAL" appear in their name, without prior written
342 * permission of Vovida Networks, Inc.
343 *
344 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
345 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
346 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
347 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
348 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
349 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
350 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
351 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
352 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
353 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
354 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
355 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
356 * DAMAGE.
357 *
358 * ====================================================================
359 *
360 * This software consists of voluntary contributions made by Vovida
361 * Networks, Inc. and many individuals on behalf of Vovida Networks,
362 * Inc. For more information on Vovida Networks, Inc., please see
363 * <http://www.vovida.org/>.
364 *
365 */
#define resip_assert(x)
This file needs to work for both C and C++ code.
Represents the "via-branch" parameter of the RFC 3261 grammar.
BranchParameter & operator=(const BranchParameter &other)
bool operator==(const BranchParameter &other) const
virtual EncodeStream & encode(EncodeStream &stream) const
void setSigcompCompartment(const Data &)
void reset(const Data &transactionId=Data::Empty)
BranchParameter(ParameterTypes::Type, ParseBuffer &pb, const std::bitset< 256 > &terminators)
const Data & getTransactionId() const
virtual Parameter * clone() const
An iostream that operates on an existing Data.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
Data base64decode() const
Performs RFC 3548 Base 64 decoding of the contents of this data.
Definition Data.cxx:2607
static const Data Empty
Constant that represents a zero-length data.
Definition Data.hxx:882
Data base64encode(bool useUrlSafe=false) const
Performs RFC 3548 Base 64 encoding of the contents of this data.
Definition Data.cxx:2682
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
static std::bitset< 256 > toBitset(const resip::Data &chars)
Creates a bitset reflecting the contents of this data (as a set) ie.
Definition Data.cxx:2477
virtual const Data & getName() const
Definition Parameter.cxx:23
Provides string-parsing functionality with protection from buffer overflow.
uint32_t uInt32()
dcm! – merge these, ask about length checks
Pointer end() const
CurrentPosition skipWhitespace()
CurrentPosition skipToChar(char c)
CurrentPosition position() const
CurrentPosition skipToOneOf(const char *cs)
CurrentPosition skipN(size_t count)
CurrentPosition skipChar()
void data(Data &data, const char *start) const
make the passed in data share memory with the buffer (uses Data::Share)
BaseException used to indicate parse failures.
static Data getCryptoRandomHex(unsigned int numBytes)
Definition Random.cxx:394
static uint64_t getTimeMicroSec()
Returns the current clock time in microseconds.
Definition Time.hxx:61
static const char * DASH
Definition Symbols.hxx:17
static const char * EQUALS
Definition Symbols.hxx:29
static const char *const resipCookie
Definition Symbols.hxx:78
static const char *const MagicCookie
Definition Symbols.hxx:77
dcm! – add UnusedChecking(_enum) below;
#define EncodeStream