Coverage Report

Created: 2023-09-25 06:23

/src/resiprocate/resip/stack/Transport.cxx
Line
Count
Source (jump to first uncovered line)
1
#if defined(HAVE_CONFIG_H)
2
#include "config.h"
3
#endif
4
5
#include <iostream>
6
7
#if defined(HAVE_SYS_SOCKIO_H)
8
#include <sys/sockio.h>
9
#endif
10
11
#include "rutil/Socket.hxx"
12
#include "rutil/DnsUtil.hxx"
13
#include "rutil/Logger.hxx"
14
#include "rutil/ParseBuffer.hxx"
15
16
#include "resip/stack/ConnectionTerminated.hxx"
17
#include "resip/stack/KeepAlivePong.hxx"
18
#include "resip/stack/Transport.hxx"
19
#include "resip/stack/SipMessage.hxx"
20
#include "resip/stack/TransportFailure.hxx"
21
#include "resip/stack/Helper.hxx"
22
#include "resip/stack/SendData.hxx"
23
#include "rutil/WinLeakCheck.hxx"
24
25
using namespace resip;
26
using namespace std;
27
28
#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
29
30
Transport::Exception::Exception(const Data& msg, const Data& file, const int line) :
31
   BaseException(msg,file,line)
32
0
{
33
0
}
34
35
Transport::Transport(Fifo<TransactionMessage>& rxFifo,
36
                     const GenericIPAddress& address,
37
                     const Data& tlsDomain,
38
                     AfterSocketCreationFuncPtr socketFunc,
39
                     Compression &compression) :
40
   mTuple(address),
41
   mCongestionManager(nullptr),
42
   mStateMachineFifo(rxFifo, 8),
43
   mShuttingDown(false),
44
   mTlsDomain(tlsDomain),
45
   mSocketFunc(socketFunc),
46
   mCompression(compression),
47
   mTransportFlags(0)
48
0
{
49
#ifdef USE_NETNS
50
   // Needs to be implemented for NETNS
51
   resip_assert(0);
52
#endif
53
0
   mInterface = Tuple::inet_ntop(mTuple);
54
0
}
55
56
Transport::Transport(Fifo<TransactionMessage>& rxFifo,
57
                     int portNum,
58
                     IpVersion version,
59
                     const Data& intfc,
60
                     const Data& tlsDomain,
61
                     AfterSocketCreationFuncPtr socketFunc,
62
                     Compression &compression,
63
                     unsigned transportFlags,
64
                     const Data& netNs) :
65
   mInterface(intfc),
66
   mTuple(intfc, portNum, version, UNKNOWN_TRANSPORT, Data::Empty, netNs),
67
   mCongestionManager(nullptr),
68
   mStateMachineFifo(rxFifo,8),
69
   mShuttingDown(false),
70
   mTlsDomain(tlsDomain),
71
   mSocketFunc(socketFunc),
72
   mCompression(compression),
73
   mTransportFlags(transportFlags)
74
0
{
75
0
}
76
77
Transport::~Transport()
78
0
{
79
0
}
80
81
void
82
Transport::onReload()
83
0
{
84
0
}
85
86
void
87
Transport::error(int e)
88
0
{
89
0
   switch (e)
90
0
   {
91
0
      case EAGAIN:
92
         //InfoLog (<< "No data ready to read" << strerror(e));
93
0
         break;
94
0
      case EINTR:
95
0
         InfoLog (<< "The call was interrupted by a signal before any data was read : " << strerror(e));
96
0
         break;
97
0
      case EIO:
98
0
         InfoLog (<< "I/O error : " << strerror(e));
99
0
         break;
100
0
      case EBADF:
101
0
         InfoLog (<< "fd is not a valid file descriptor or is not open for reading : " << strerror(e));
102
0
         break;
103
0
      case EINVAL:
104
0
         InfoLog (<< "fd is attached to an object which is unsuitable for reading : " << strerror(e));
105
0
         break;
106
0
      case EFAULT:
107
0
         InfoLog (<< "buf is outside your accessible address space : " << strerror(e));
108
0
         break;
109
110
#if defined(WIN32)
111
      case WSAENETDOWN:
112
         InfoLog (<<" The network subsystem has failed.  ");
113
         break;
114
      case WSAEFAULT:
115
         InfoLog (<<" The buf or from parameters are not part of the user address space, "
116
                   "or the fromlen parameter is too small to accommodate the peer address.  ");
117
         break;
118
      case WSAEINTR:
119
         InfoLog (<<" The (blocking) call was canceled through WSACancelBlockingCall.  ");
120
         break;
121
      case WSAEINPROGRESS:
122
         InfoLog (<<" A blocking Windows Sockets 1.1 call is in progress, or the "
123
                   "service provider is still processing a callback function.  ");
124
         break;
125
      case WSAEINVAL:
126
         InfoLog (<<" The socket has not been bound with bind, or an unknown flag was specified, "
127
                   "or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, "
128
                   "or (for byte stream-style sockets only) len was zero or negative.  ");
129
         break;
130
      case WSAEISCONN :
131
         InfoLog (<<"The socket is connected. This function is not permitted with a connected socket, "
132
                  "whether the socket is connection-oriented or connectionless.  ");
133
         break;
134
      case WSAENETRESET:
135
         InfoLog (<<" The connection has been broken due to the keep-alive activity "
136
                  "detecting a failure while the operation was in progress.  ");
137
         break;
138
      case WSAENOTSOCK :
139
         InfoLog (<<"The descriptor is not a socket.  ");
140
         break;
141
      case WSAEOPNOTSUPP:
142
         InfoLog (<<" MSG_OOB was specified, but the socket is not stream-style such as type "
143
                   "SOCK_STREAM, OOB data is not supported in the communication domain associated with this socket, "
144
                   "or the socket is unidirectional and supports only send operations.  ");
145
         break;
146
      case WSAESHUTDOWN:
147
         InfoLog (<<"The socket has been shut down; it is not possible to recvfrom on a socket after "
148
                  "shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH.  ");
149
         break;
150
      case WSAEMSGSIZE:
151
         InfoLog (<<" The message was too large to fit into the specified buffer and was truncated.  ");
152
         break;
153
      case WSAETIMEDOUT:
154
         InfoLog (<<" The connection has been dropped, because of a network failure or because the "
155
                  "system on the other end went down without notice.  ");
156
         break;
157
      case WSAECONNRESET :
158
         InfoLog (<<"Connection reset ");
159
         break;
160
161
      case WSAEWOULDBLOCK:
162
         DebugLog (<<"Would Block ");
163
         break;
164
165
      case WSAEHOSTUNREACH:
166
         InfoLog (<<"A socket operation was attempted to an unreachable host ");
167
         break;
168
      case WSANOTINITIALISED:
169
         InfoLog (<<"Either the application has not called WSAStartup or WSAStartup failed. "
170
                  "The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks),"
171
                  "or WSACleanup has been called too many times.  ");
172
         break;
173
      case WSAEACCES:
174
         InfoLog (<<"An attempt was made to access a socket in a way forbidden by its access permissions ");
175
         break;
176
      case WSAENOBUFS:
177
         InfoLog (<<"An operation on a socket could not be performed because the system lacked sufficient "
178
                  "buffer space or because a queue was full");
179
         break;
180
      case WSAENOTCONN:
181
         InfoLog (<<"A request to send or receive data was disallowed because the socket is not connected "
182
                  "and (when sending on a datagram socket using sendto) no address was supplied");
183
         break;
184
      case WSAECONNABORTED:
185
         InfoLog (<<"An established connection was aborted by the software in your host computer, possibly "
186
                  "due to a data transmission time-out or protocol error");
187
         break;
188
      case WSAEADDRNOTAVAIL:
189
         InfoLog (<<"The requested address is not valid in its context. This normally results from an attempt to "
190
                  "bind to an address that is not valid for the local computer");
191
         break;
192
      case WSAEAFNOSUPPORT:
193
         InfoLog (<<"An address incompatible with the requested protocol was used");
194
         break;
195
      case WSAEDESTADDRREQ:
196
         InfoLog (<<"A required address was omitted from an operation on a socket");
197
         break;
198
      case WSAENETUNREACH:
199
         InfoLog (<<"A socket operation was attempted to an unreachable network");
200
         break;
201
202
#endif
203
204
0
      default:
205
0
         InfoLog (<< "Some other error (" << e << "): " << strerror(e));
206
0
         break;
207
0
   }
208
0
}
209
210
void
211
Transport::flowTerminated(const Tuple& flow)
212
0
{
213
0
   mStateMachineFifo.add(new ConnectionTerminated(flow));
214
0
}
215
216
void
217
Transport::keepAlivePong(const Tuple& flow)
218
0
{
219
0
   mStateMachineFifo.add(new KeepAlivePong(flow));
220
0
}
221
222
void
223
Transport::fail(const Data& tid, TransportFailure::FailureReason reason, int subCode)
224
0
{
225
0
   if (!tid.empty())
226
0
   {
227
0
      mStateMachineFifo.add(new TransportFailure(tid, reason, subCode));
228
0
   }
229
0
}
230
231
void 
232
Transport::setTcpConnectState(const Data& tid, TcpConnectState::State state)
233
0
{
234
0
    if (!tid.empty())
235
0
    {
236
0
        mStateMachineFifo.add(new TcpConnectState(tid, state));
237
0
    }
238
0
}
239
240
std::unique_ptr<SendData>
241
Transport::makeSendData( const Tuple& dest, const Data& d, const Data& tid, const Data &sigcompId)
242
0
{
243
0
   resip_assert(dest.getPort() != -1);
244
0
   std::unique_ptr<SendData> data(new SendData(dest, d, tid, sigcompId));
245
0
   return data;
246
0
}
247
248
void
249
Transport::makeFailedResponse(const SipMessage& msg,
250
                              int responseCode,
251
                              const char * warning)
252
0
{
253
0
  if (msg.isResponse()) return;
254
255
0
  const Tuple& dest = msg.getSource();
256
257
0
  std::unique_ptr<SipMessage> errMsg(Helper::makeResponse(msg,
258
0
                                                        responseCode,
259
0
                                                        warning ? warning : "Original request had no Vias"));
260
261
  // make send data here w/ blank tid and blast it out.
262
  // encode message
263
0
  Data encoded;
264
0
  encoded.clear();
265
0
  DataStream encodeStream(encoded);
266
0
  errMsg->encode(encodeStream);
267
0
  encodeStream.flush();
268
0
  resip_assert(!encoded.empty());
269
270
0
  InfoLog(<<"Sending response directly to " << dest << " : " << errMsg->brief() );
271
272
  // Calculate compartment ID for outbound message
273
0
  Data remoteSigcompId;
274
0
   setRemoteSigcompId(*errMsg,remoteSigcompId);
275
0
  send(makeSendData(dest, encoded, Data::Empty, remoteSigcompId));
276
0
}
277
278
std::unique_ptr<SendData>
279
Transport::make503(SipMessage& msg, uint16_t retryAfter)
280
0
{
281
0
  std::unique_ptr<SendData> result;
282
0
  if (msg.isResponse()) return result;
283
284
0
   try
285
0
   {
286
0
      if(msg.method()==ACK)
287
0
      {
288
0
         return result;
289
0
      }
290
0
   }
291
0
   catch(BaseException&)
292
0
   {
293
      // .bwc. Parse failed on the start-line. Stop.
294
0
      return result;
295
0
   }
296
   
297
0
  const Tuple& dest = msg.getSource();
298
299
   // Calculate compartment ID for outbound message
300
0
   Data remoteSigcompId;
301
0
   setRemoteSigcompId(msg,remoteSigcompId);
302
303
   // .bwc. msg is completely unverified. Handle with caution.
304
0
   result=makeSendData(dest, Data::Empty, Data::Empty, remoteSigcompId);
305
0
   static const Data retryAfterHeader("Retry-After: ");
306
0
   Data value(retryAfter);
307
0
   Helper::makeRawResponse(result->data, msg, 503, retryAfterHeader+value+"\r\n");
308
309
0
  return result;
310
0
}
311
312
std::unique_ptr<SendData>
313
Transport::make100(SipMessage& msg)
314
0
{
315
0
  std::unique_ptr<SendData> result;
316
0
  if (msg.isResponse()) return result;
317
318
0
   try
319
0
   {
320
0
      if(msg.method()==ACK)
321
0
      {
322
0
         return result;
323
0
      }
324
0
   }
325
0
   catch(BaseException&)
326
0
   {
327
      // .bwc. Parse failed on the start-line. Stop.
328
0
      return result;
329
0
   }
330
   
331
0
  const Tuple& dest = msg.getSource();
332
333
   // Calculate compartment ID for outbound message
334
0
   Data remoteSigcompId;
335
0
   setRemoteSigcompId(msg,remoteSigcompId);
336
337
   // .bwc. msg is completely unverified. Handle with caution.
338
0
   result=makeSendData(dest, Data::Empty, Data::Empty, remoteSigcompId);
339
0
   Helper::makeRawResponse(result->data, msg, 100);
340
341
0
   return result;
342
0
}
343
344
void
345
Transport::setRemoteSigcompId(SipMessage& msg, Data& remoteSigcompId)
346
0
{
347
0
   if (mCompression.isEnabled())
348
0
   {
349
0
      try
350
0
      {
351
0
         const Via &topVia(msg.const_header(h_Vias).front());
352
         
353
0
         if(topVia.exists(p_comp) && topVia.param(p_comp) == "sigcomp")
354
0
         {
355
0
            if (topVia.exists(p_sigcompId))
356
0
            {
357
0
               remoteSigcompId = topVia.param(p_sigcompId);
358
0
            }
359
0
            else
360
0
            {
361
               // XXX rohc-sigcomp-sip-03 says "sent-by",
362
               // but this should probably be "received" if present,
363
               // and "sent-by" otherwise.
364
               // XXX Also, the spec is ambiguous about whether
365
               // to include the port in this identifier.
366
0
               remoteSigcompId = topVia.sentHost();
367
0
            }
368
0
         }
369
0
      }
370
0
      catch(BaseException&)
371
0
      {
372
         // ?bwc? Couldn't grab sigcomp compartment id. We don't even know if
373
         // the initial request was using sigcomp or not. 
374
         // What should we do here?
375
0
      }
376
0
   }
377
0
}
378
379
void
380
Transport::stampReceived(SipMessage* message)
381
0
{
382
   // set the received= and rport= parameters in the message if necessary !jf!
383
0
   if (message->isRequest() && message->exists(h_Vias) && !message->const_header(h_Vias).empty())
384
0
   {
385
0
      const Tuple& tuple = message->getSource();
386
0
      Data received = Tuple::inet_ntop(tuple);
387
0
      if(message->const_header(h_Vias).front().sentHost() != received)  // only add if received address is different from sent-by in Via
388
0
      {
389
0
         message->header(h_Vias).front().param(p_received) = received;
390
0
      }
391
      //message->header(h_Vias).front().param(p_received) = Tuple::inet_ntop(tuple);
392
0
      if (message->const_header(h_Vias).front().exists(p_rport))
393
0
      {
394
0
         message->header(h_Vias).front().param(p_rport).port() = tuple.getPort();
395
0
      }
396
0
   }
397
0
   DebugLog (<< "incoming from: " << message->getSource());
398
0
   StackLog (<< endl << endl << *message);
399
0
}
400
401
bool
402
Transport::basicCheck(const SipMessage& msg)
403
0
{
404
0
   resip::Data reason;
405
0
   if (msg.isExternal())
406
0
   {
407
0
      try
408
0
      {
409
0
         if (!Helper::validateMessage(msg,&reason))
410
0
         {
411
0
            InfoLog(<<"Message Failed basicCheck :" << msg.brief());
412
0
            if (msg.isRequest() && msg.method()!=ACK )
413
0
            {
414
               // this is VERY low-level b/c we don't have a transaction...
415
               // here we make a response to warn the offending party.
416
0
               makeFailedResponse(msg,400,reason.c_str());
417
0
            }
418
0
            return false;
419
0
         }
420
0
         else if (mShuttingDown && msg.isRequest() && msg.method() != ACK)
421
0
         {
422
0
            InfoLog (<< "Server has been shutdown, reject message with 503");
423
            // this is VERY low-level b/c we don't have a transaction...
424
            // here we make a response to warn the offending party.
425
0
            makeFailedResponse(msg, 503, "Server has been shutdown");
426
0
            return false;
427
0
         }
428
0
      }
429
0
      catch (BaseException& e)
430
0
      {
431
0
         InfoLog (<< "Cannot make failure response to badly constructed message: " << e);
432
0
         return false;
433
0
      }
434
0
   }
435
0
   return true;
436
0
}
437
438
void
439
Transport::callSocketFunc(Socket sock)
440
0
{
441
0
   if (mSocketFunc)
442
0
   {
443
0
      mSocketFunc(sock, transport(), __FILE__, __LINE__);
444
0
   }
445
0
}
446
447
void
448
Transport::pushRxMsgUp(SipMessage* message)
449
0
{
450
0
   for(auto& handler : getSipMessageLoggingHandlers())
451
0
   {
452
0
       handler->inboundMessage(message->getSource(), message->getReceivedTransportTuple(), *message);
453
0
   }
454
455
0
   mStateMachineFifo.add(message);
456
0
}
457
458
bool
459
Transport::operator==(const Transport& rhs) const
460
0
{
461
0
   return ( ( mTuple.isV4() == rhs.isV4()) &&
462
0
            ( port() == rhs.port()) &&
463
0
            ( memcmp(&boundInterface(),&rhs.boundInterface(),mTuple.length()) == 0) );
464
0
}
465
466
EncodeStream&
467
resip::operator<<(EncodeStream& strm, const resip::Transport& rhs)
468
0
{
469
0
   strm << "Transport: " << rhs.mTuple;
470
0
   if (!rhs.mInterface.empty()) strm << " on " << rhs.mInterface;
471
0
   return strm;
472
0
}
473
474
/* ====================================================================
475
 * The Vovida Software License, Version 1.0
476
 *
477
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
478
 *
479
 * Redistribution and use in source and binary forms, with or without
480
 * modification, are permitted provided that the following conditions
481
 * are met:
482
 *
483
 * 1. Redistributions of source code must retain the above copyright
484
 *    notice, this list of conditions and the following disclaimer.
485
 *
486
 * 2. Redistributions in binary form must reproduce the above copyright
487
 *    notice, this list of conditions and the following disclaimer in
488
 *    the documentation and/or other materials provided with the
489
 *    distribution.
490
 *
491
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
492
 *    and "Vovida Open Communication Application Library (VOCAL)" must
493
 *    not be used to endorse or promote products derived from this
494
 *    software without prior written permission. For written
495
 *    permission, please contact vocal@vovida.org.
496
 *
497
 * 4. Products derived from this software may not be called "VOCAL", nor
498
 *    may "VOCAL" appear in their name, without prior written
499
 *    permission of Vovida Networks, Inc.
500
 *
501
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
502
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
503
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
504
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
505
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
506
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
507
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
508
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
509
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
510
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
511
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
512
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
513
 * DAMAGE.
514
 *
515
 * ====================================================================
516
 *
517
 * This software consists of voluntary contributions made by Vovida
518
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
519
 * Inc.  For more information on Vovida Networks, Inc., please see
520
 * <http://www.vovida.org/>.
521
 *
522
 * vi: set shiftwidth=3 expandtab:
523
 */