Coverage Report

Created: 2025-12-31 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/resip/stack/BranchParameter.cxx
Line
Count
Source
1
#if defined(HAVE_CONFIG_H)
2
#include "config.h"
3
#endif
4
5
#include "rutil/ResipAssert.h"
6
#include "resip/stack/BranchParameter.hxx"
7
#include "resip/stack/Symbols.hxx"
8
#include "rutil/ParseBuffer.hxx"
9
#include "rutil/Random.hxx"
10
#include "rutil/Coders.hxx"
11
#include "rutil/ParseException.hxx"
12
13
#include "rutil/Logger.hxx"
14
#include "rutil/WinLeakCheck.hxx"
15
16
using namespace resip;
17
using namespace std;
18
19
#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
20
21
BranchParameter::BranchParameter(ParameterTypes::Type type,
22
                                 ParseBuffer& pb, 
23
                                 const std::bitset<256>& terminators)
24
0
   : Parameter(type), 
25
0
     mHasMagicCookie(false),
26
0
     mIsMyBranch(false),
27
0
     mTransactionId(),
28
0
     mTransportSeq(1),
29
0
     mClientData(),
30
0
     mInteropMagicCookie(0),
31
0
     mSigcompCompartment()
32
0
{
33
0
   try
34
0
   {
35
0
      pb.skipWhitespace();
36
0
      pb.skipChar(Symbols::EQUALS[0]);
37
0
      pb.skipWhitespace();
38
0
      if (pb.lengthRemaining() >= 7)
39
0
      {
40
0
         if(memcmp(pb.position(), Symbols::MagicCookie, 7) == 0)
41
0
         {
42
0
            mHasMagicCookie=true;
43
0
            pb.skipN(7);
44
0
         }
45
         // !bwc! This no-case comparison is expensive; only do it if the case-
46
         // sensitive comparison fails.
47
0
         else if(strncasecmp(pb.position(), Symbols::MagicCookie, 7) == 0)
48
0
         {
49
0
            mHasMagicCookie=true;
50
0
            mInteropMagicCookie = new Data(pb.position(), 7);
51
0
            pb.skipN(7);
52
0
         }
53
0
      }
54
      
55
0
      const char* start = pb.position();
56
0
      static std::bitset<256> delimiter=Data::toBitset("\r\n\t ;=?>");
57
58
0
      if (mHasMagicCookie &&
59
0
          (pb.end() - start > 8) &&
60
          // look for prefix cookie (maybe make this bigger?)
61
0
          memcmp(start, Symbols::resipCookie, 8) == 0)
62
0
      {
63
         // ?bwc? Wrap this stuff in try/catch, just in case of false positives?
64
0
         const char* curr=start;
65
0
         mIsMyBranch = true;
66
0
         pb.skipN(8);
67
68
0
         mTransportSeq=pb.uInt32();
69
70
0
         curr=pb.skipChar('-');
71
0
         pb.skipToChar('-');
72
0
         Data encoded;
73
0
         pb.data(encoded, curr);
74
0
         if(!encoded.empty())
75
0
         {
76
            // !bwc! Expensive! Also, Base64 isn't case-insensitive.
77
0
            mClientData = encoded.base64decode();
78
0
         }
79
80
0
         curr=pb.skipChar('-');
81
0
         pb.skipToChar('-');
82
0
         pb.data(encoded,curr);
83
0
         if(!encoded.empty())
84
0
         {
85
            // !bwc! Expensive! Also, Base64 isn't case-insensitive.
86
0
            mSigcompCompartment = encoded.base64decode();
87
0
         }
88
89
0
         start=pb.skipChar('-');
90
0
      }
91
0
      pb.skipToOneOf(delimiter);
92
0
      pb.data(mTransactionId, start);
93
0
   }
94
0
   catch(resip::ParseException& e)
95
0
   {
96
0
      mTransactionId=Random::getRandomHex(8);
97
0
      throw e;
98
0
   }
99
0
}
100
101
BranchParameter::BranchParameter(ParameterTypes::Type type)
102
0
   : Parameter(type),
103
0
     mHasMagicCookie(true),
104
0
     mIsMyBranch(true),
105
0
     mTransactionId(Random::getRandomHex(8)),
106
0
     mTransportSeq(1),
107
0
     mInteropMagicCookie(0),
108
0
     mSigcompCompartment()
109
0
{
110
0
}
111
112
BranchParameter::BranchParameter(const BranchParameter& other)
113
0
   : Parameter(other), 
114
0
     mHasMagicCookie(other.mHasMagicCookie),
115
0
     mIsMyBranch(other.mIsMyBranch),
116
0
     mTransactionId(other.mTransactionId),
117
0
     mTransportSeq(other.mTransportSeq),
118
0
     mClientData(other.mClientData),
119
0
     mSigcompCompartment(other.mSigcompCompartment)
120
0
{
121
0
   if (other.mInteropMagicCookie)
122
0
   {
123
0
      mInteropMagicCookie = new Data(*other.mInteropMagicCookie);
124
0
   }
125
0
   else
126
0
   {
127
0
      mInteropMagicCookie = 0;
128
0
   }
129
0
}
130
131
BranchParameter::~BranchParameter()
132
0
{
133
0
   delete mInteropMagicCookie;
134
0
}
135
136
BranchParameter& 
137
BranchParameter::operator=(const BranchParameter& other)
138
0
{
139
0
   if (this != &other)
140
0
   {
141
0
      mHasMagicCookie = other.mHasMagicCookie;
142
0
      mIsMyBranch = other.mIsMyBranch;
143
0
      mTransactionId = other.mTransactionId;
144
0
      mTransportSeq = other.mTransportSeq;
145
0
      mClientData = other.mClientData;
146
0
      mSigcompCompartment = other.mSigcompCompartment;
147
0
      if (other.mInteropMagicCookie)
148
0
      {
149
0
         delete mInteropMagicCookie;         
150
0
         mInteropMagicCookie = new Data(*other.mInteropMagicCookie);
151
0
      }
152
0
      else
153
0
      {
154
0
         delete mInteropMagicCookie;
155
0
         mInteropMagicCookie = 0;
156
0
      }
157
0
   }
158
0
   return *this;
159
0
}
160
161
bool
162
BranchParameter::operator==(const BranchParameter& other) const
163
0
{
164
0
   if (mIsMyBranch != other.mIsMyBranch ||
165
0
       mHasMagicCookie != other.mHasMagicCookie ||
166
0
       mTransportSeq != other.mTransportSeq ||
167
0
       mTransactionId != other.mTransactionId ||
168
0
       mClientData != other.mClientData ||
169
0
       mSigcompCompartment != other.mSigcompCompartment)
170
0
   {
171
0
      return false;
172
0
   }
173
0
   return true;
174
0
}
175
176
bool
177
BranchParameter::hasMagicCookie() const
178
0
{
179
0
   return mHasMagicCookie;
180
0
}
181
182
const Data& 
183
BranchParameter::getTransactionId() const
184
0
{
185
0
   return mTransactionId;
186
0
}
187
188
void
189
BranchParameter::incrementTransportSequence()
190
0
{
191
0
   resip_assert(mIsMyBranch);
192
0
   mTransportSeq++;
193
0
}
194
195
Data&
196
BranchParameter::clientData()
197
0
{
198
0
    return mClientData;
199
0
}
200
201
const Data&
202
BranchParameter::clientData() const
203
0
{
204
0
    return mClientData;
205
0
}
206
207
/**
208
  @todo The encoding here could be more efficient.
209
*/
210
void
211
BranchParameter::setSigcompCompartment(const Data &id)
212
0
{
213
0
  if (id.size() == 0)
214
0
  {
215
0
    mSigcompCompartment = Data::Empty;
216
0
  }
217
218
  // These will often (but not always) be UUID URNs in angle brackets;
219
  // e.g.: <urn:uuid:fa33c72d-121f-47e8-42e2-1eb6e24aba64>
220
221
  // Ideally, we would detect this, strip out everything that isn't
222
  // hex, and convert the hex to raw data.
223
224
0
  mSigcompCompartment = id;
225
0
}
226
227
Data
228
BranchParameter::getSigcompCompartment() const
229
0
{
230
0
  return mSigcompCompartment;
231
0
}
232
233
void
234
BranchParameter::reset(const Data& transactionId)
235
0
{
236
0
   mHasMagicCookie = true;
237
0
   mIsMyBranch = true;
238
0
   delete mInteropMagicCookie;
239
0
   mInteropMagicCookie = 0;   
240
241
0
   mSigcompCompartment = Data::Empty;
242
243
0
   mTransportSeq = 1;
244
0
   if (!transactionId.empty())
245
0
   {
246
0
      mTransactionId = transactionId;
247
0
   }
248
0
   else
249
0
   {
250
0
      mTransactionId = Random::getRandomHex(8);
251
0
   }
252
0
}
253
254
Parameter* 
255
BranchParameter::clone() const
256
0
{
257
0
   return new BranchParameter(*this);
258
0
}
259
260
EncodeStream& 
261
BranchParameter::encode(EncodeStream& stream) const
262
0
{
263
0
   stream << getName() << Symbols::EQUALS;
264
0
   if (mHasMagicCookie)
265
0
   {
266
0
      if (mInteropMagicCookie)
267
0
      {
268
0
         stream << *mInteropMagicCookie;         
269
0
      }
270
0
      else
271
0
      {
272
0
         stream << Symbols::MagicCookie;
273
0
      }
274
0
   }
275
0
   if (mIsMyBranch)
276
0
   {
277
0
      stream << Symbols::resipCookie;
278
0
      stream << mTransportSeq;
279
0
      stream << Symbols::DASH;
280
0
      if(!mClientData.empty()) // base64encode() makes copies
281
0
      {
282
         // !bwc! We should be using hex encoding; branch params are supposed to
283
         // be case-insensitive.
284
0
         stream << mClientData.base64encode(true/*safe URL*/);
285
0
      }
286
0
      stream << Symbols::DASH;
287
0
      if(!mSigcompCompartment.empty()) // base64encode() makes copies
288
0
      {
289
         // !bwc! We should be using hex encoding; branch params are supposed to
290
         // be case-insensitive.
291
0
         stream << mSigcompCompartment.base64encode(true);
292
0
      }
293
0
      stream << Symbols::DASH;
294
0
   }
295
0
   stream << mTransactionId;
296
      
297
0
   return stream;
298
0
}
299
300
301
/* ====================================================================
302
 * The Vovida Software License, Version 1.0 
303
 * 
304
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
305
 * 
306
 * Redistribution and use in source and binary forms, with or without
307
 * modification, are permitted provided that the following conditions
308
 * are met:
309
 * 
310
 * 1. Redistributions of source code must retain the above copyright
311
 *    notice, this list of conditions and the following disclaimer.
312
 * 
313
 * 2. Redistributions in binary form must reproduce the above copyright
314
 *    notice, this list of conditions and the following disclaimer in
315
 *    the documentation and/or other materials provided with the
316
 *    distribution.
317
 * 
318
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
319
 *    and "Vovida Open Communication Application Library (VOCAL)" must
320
 *    not be used to endorse or promote products derived from this
321
 *    software without prior written permission. For written
322
 *    permission, please contact vocal@vovida.org.
323
 *
324
 * 4. Products derived from this software may not be called "VOCAL", nor
325
 *    may "VOCAL" appear in their name, without prior written
326
 *    permission of Vovida Networks, Inc.
327
 * 
328
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
329
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
330
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
331
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
332
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
333
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
334
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
335
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
336
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
337
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
338
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
339
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
340
 * DAMAGE.
341
 * 
342
 * ====================================================================
343
 * 
344
 * This software consists of voluntary contributions made by Vovida
345
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
346
 * Inc.  For more information on Vovida Networks, Inc., please see
347
 * <http://www.vovida.org/>.
348
 *
349
 */