reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
Transport.cxx
Go to the documentation of this file.
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
24
25using namespace resip;
26using namespace std;
27
28#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
29
30void
31Transport::setSipMessageLoggingHandler(std::shared_ptr<SipMessageLoggingHandler> handler)
32{
33 mSipMessageLoggingHandlers.clear();
34
35 if (handler)
36 {
37 mSipMessageLoggingHandlers.push_back(handler);
38 }
39}
40
41void
42Transport::addSipMessageLoggingHandler(std::shared_ptr<SipMessageLoggingHandler> handler)
43{
44 if (handler)
45 {
46 mSipMessageLoggingHandlers.push_back(handler);
47 }
48}
49
50void
52{
53 mSipMessageLoggingHandlers = handlers;
54}
55
56void
58{
59 mSipMessageLoggingHandlers.clear();
60}
61
64{
65 return mSipMessageLoggingHandlers;
66}
67
68Transport::Exception::Exception(const Data& msg, const Data& file, const int line) :
69 BaseException(msg,file,line)
70{
71}
72
74 const GenericIPAddress& address,
75 const Data& tlsDomain,
77 Compression &compression) :
78 mTuple(address),
79 mCongestionManager(nullptr),
80 mStateMachineFifo(rxFifo, 8),
81 mShuttingDown(false),
82 mTlsDomain(tlsDomain),
83 mSocketFunc(socketFunc),
84 mCompression(compression),
86{
87#ifdef USE_NETNS
88 // Needs to be implemented for NETNS
89 resip_assert(0);
90#endif
92}
93
95 int portNum,
96 IpVersion version,
97 const Data& intfc,
98 const Data& tlsDomain,
100 Compression &compression,
101 unsigned transportFlags,
102 const Data& netNs) :
103 mInterface(intfc),
104 mTuple(intfc, portNum, version, UNKNOWN_TRANSPORT, Data::Empty, netNs),
105 mCongestionManager(nullptr),
106 mStateMachineFifo(rxFifo,8),
107 mShuttingDown(false),
108 mTlsDomain(tlsDomain),
109 mSocketFunc(socketFunc),
110 mCompression(compression),
111 mTransportFlags(transportFlags)
112{
113}
114
118
119void
123
124void
126{
127 // Read before the traversal clears the mark state, so a reset still reports
128 // the 0 it wrote.
129 const int handled = effectiveDscp();
130
131 // The refresh first, so the report reads the class this pass wrote.
132 if (mDscpRefreshPending.load())
133 {
135 }
136
137 if (mDscpReportPending.exchange(false))
138 {
139 reportDscp(handled);
140 }
141}
142
143void
145{
146 // Clear the request before reading the value it was raised for. A setDscp()
147 // that lands after this either carries the value this pass is about to
148 // write, or raises the request again for the next cycle.
149 mDscpRefreshPending.store(false);
150
151 const int wanted = mDscp.load();
152
153 // Before the traversal: with nothing to write and nothing to undo, the
154 // user's AfterSocketCreationFunc must not be re-invoked at all.
155 if (effectiveDscp(wanted) < 0)
156 {
157 return;
158 }
159
161
162 // What this pass wrote, not what mDscp says now: a value that changed while
163 // the traversal ran has raised its own request.
164 mWasMarkRequested.store(wanted >= 0);
165}
166
167void
168Transport::reportDscp(int wanted) const
169{
170 if (wanted < 0)
171 {
172 return;
173 }
174
175 const Socket listener = getListenerSocket();
176 if (listener == INVALID_SOCKET)
177 {
178 return;
179 }
180
181 const int carried = getSocketTos(listener, ipVersion());
182 if (carried < 0)
183 {
184 ErrLog(<< *this << " cannot read the signaling DSCP class back from its listener");
185 return;
186 }
187
188 // As a class rather than a byte, so the kernel's own ECN bits do not read
189 // as a mismatch.
190 if ((carried >> 2) != wanted)
191 {
192 ErrLog(<< *this << " asked for signaling DSCP " << wanted
193 << " but its listener carries " << (carried >> 2)
194 << " (ToS byte " << carried << ")");
195 return;
196 }
197
198 InfoLog(<< *this << " signaling DSCP " << (carried >> 2)
199 << " (ToS byte " << carried << ")");
200}
201
202void
204{
205 if (e != EAGAIN)
206 {
207 InfoLog(<< errorToString(e));
208 }
209}
210
211Data
213{
214 Data errorString;
215 DataStream ds(errorString);
216 switch (e)
217 {
218 case 0:
219 ds << "None";
220 break;
221 case EAGAIN:
222 ds << "No data ready to read: " << strError(e);
223 break;
224 case EINTR:
225 ds << "The call was interrupted by a signal before any data was read: " << strError(e);
226 break;
227 case EIO:
228 ds << "I/O error: " << strError(e);
229 break;
230 case EBADF:
231 ds << "fd is not a valid file descriptor or is not open for reading: " << strError(e);
232 break;
233 case EINVAL:
234 ds << "fd is attached to an object which is unsuitable for reading: " << strError(e);
235 break;
236 case EFAULT:
237 ds << "buf is outside your accessible address space: " << strError(e);
238 break;
239
240#if defined(WIN32)
241 case WSAENETDOWN:
242 ds << "The network subsystem has failed.";
243 break;
244 case WSAEFAULT:
245 ds << "The buf or from parameters are not part of the user address space, "
246 "or the fromlen parameter is too small to accommodate the peer address.";
247 break;
248 case WSAEINTR:
249 ds << "The (blocking) call was canceled through WSACancelBlockingCall.";
250 break;
251 case WSAEINPROGRESS:
252 ds << "A blocking Windows Sockets 1.1 call is in progress, or the "
253 "service provider is still processing a callback function.";
254 break;
255 case WSAEINVAL:
256 ds << "The socket has not been bound with bind, or an unknown flag was specified, "
257 "or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, "
258 "or (for byte stream-style sockets only) len was zero or negative.";
259 break;
260 case WSAEISCONN :
261 ds << "The socket is connected. This function is not permitted with a connected socket, "
262 "whether the socket is connection-oriented or connectionless.";
263 break;
264 case WSAENETRESET:
265 ds << "The connection has been broken due to the keep-alive activity "
266 "detecting a failure while the operation was in progress.";
267 break;
268 case WSAENOTSOCK:
269 ds << "The descriptor is not a socket.";
270 break;
271 case WSAEOPNOTSUPP:
272 ds << " MSG_OOB was specified, but the socket is not stream-style such as type "
273 "SOCK_STREAM, OOB data is not supported in the communication domain associated with this socket, "
274 "or the socket is unidirectional and supports only send operations.";
275 break;
276 case WSAESHUTDOWN:
277 ds << "The socket has been shut down; it is not possible to recvfrom on a socket after "
278 "shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH.";
279 break;
280 case WSAEMSGSIZE:
281 ds << "The message was too large to fit into the specified buffer and was truncated.";
282 break;
283 case WSAETIMEDOUT:
284 ds << "The connection has been dropped, because of a network failure or because the "
285 "system on the other end went down without notice.";
286 break;
287 case WSAECONNRESET :
288 ds << "Connection reset.";
289 break;
290 case WSAEWOULDBLOCK:
291 ds << "Would block.";
292 break;
293 case WSAEHOSTUNREACH:
294 ds << "A socket operation was attempted to an unreachable host.";
295 break;
297 ds << "Either the application has not called WSAStartup or WSAStartup failed. "
298 "The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks),"
299 "or WSACleanup has been called too many times.";
300 break;
301 case WSAEACCES:
302 ds << "An attempt was made to access a socket in a way forbidden by its access permissions.";
303 break;
304 case WSAENOBUFS:
305 ds << "An operation on a socket could not be performed because the system lacked sufficient "
306 "buffer space or because a queue was full.";
307 break;
308 case WSAENOTCONN:
309 ds << "A request to send or receive data was disallowed because the socket is not connected "
310 "and (when sending on a datagram socket using sendto) no address was supplied.";
311 break;
312 case WSAECONNABORTED:
313 ds << "An established connection was aborted by the software in your host computer, possibly "
314 "due to a data transmission time-out or protocol error.";
315 break;
316 case WSAEADDRNOTAVAIL:
317 ds << "The requested address is not valid in its context. This normally results from an attempt to "
318 "bind to an address that is not valid for the local computer.";
319 break;
320 case WSAEAFNOSUPPORT:
321 ds << "An address incompatible with the requested protocol was used.";
322 break;
323 case WSAEDESTADDRREQ:
324 ds << "A required address was omitted from an operation on a socket.";
325 break;
326 case WSAENETUNREACH:
327 ds << "A socket operation was attempted to an unreachable network.";
328 break;
329#endif
330
331 default:
332 ds << "Some other error (" << e << "): " << strError(e);
333 break;
334 }
335 ds.flush();
336 return errorString;
337}
338
339void
340Transport::flowTerminated(const Tuple& flow, TransportFailure::FailureReason failureReason, int failureSubCode, const Data& failureString, const std::list<Data> additionalFailureStrings)
341{
342 mStateMachineFifo.add(new ConnectionTerminated(flow, failureReason, failureSubCode, failureString, additionalFailureStrings));
343}
344
345void
347{
348 mStateMachineFifo.add(new KeepAlivePong(flow));
349}
350
351void
353{
354 if (!tid.empty())
355 {
356 mStateMachineFifo.add(new TransportFailure(tid, reason, subCode));
357 }
358}
359
360void
362{
363 if (!tid.empty())
364 {
365 mStateMachineFifo.add(new TcpConnectState(tid, state));
366 }
367}
368
369std::unique_ptr<SendData>
370Transport::makeSendData( const Tuple& dest, const Data& d, const Data& tid, const Data &sigcompId)
371{
372 resip_assert(dest.getPort() != -1);
373 std::unique_ptr<SendData> data(new SendData(dest, d, tid, sigcompId));
374 return data;
375}
376
377void
379 int responseCode,
380 const char * warning)
381{
382 if (msg.isResponse()) return;
383
384 const Tuple& dest = msg.getSource();
385
386 std::unique_ptr<SipMessage> errMsg(Helper::makeResponse(msg,
387 responseCode,
388 warning ? warning : "Original request had no Vias"));
389
390 // make send data here w/ blank tid and blast it out.
391 // encode message
392 Data encoded;
393 encoded.clear();
394 DataStream encodeStream(encoded);
395 errMsg->encode(encodeStream);
396 encodeStream.flush();
397 resip_assert(!encoded.empty());
398
399 InfoLog(<<"Sending response directly to " << dest << " : " << errMsg->brief() );
400
401 // Calculate compartment ID for outbound message
402 Data remoteSigcompId;
403 setRemoteSigcompId(*errMsg,remoteSigcompId);
404 send(makeSendData(dest, encoded, Data::Empty, remoteSigcompId));
405}
406
407std::unique_ptr<SendData>
409{
410 std::unique_ptr<SendData> result;
411 if (msg.isResponse()) return result;
412
413 try
414 {
415 if(msg.method()==ACK)
416 {
417 return result;
418 }
419 }
420 catch(BaseException&)
421 {
422 // .bwc. Parse failed on the start-line. Stop.
423 return result;
424 }
425
426 const Tuple& dest = msg.getSource();
427
428 // Calculate compartment ID for outbound message
429 Data remoteSigcompId;
430 setRemoteSigcompId(msg,remoteSigcompId);
431
432 // .bwc. msg is completely unverified. Handle with caution.
433 result=makeSendData(dest, Data::Empty, Data::Empty, remoteSigcompId);
434 static const Data retryAfterHeader("Retry-After: ");
435 Data value(retryAfter);
436 Helper::makeRawResponse(result->data, msg, 503, retryAfterHeader+value+"\r\n");
437
438 return result;
439}
440
441std::unique_ptr<SendData>
443{
444 std::unique_ptr<SendData> result;
445 if (msg.isResponse()) return result;
446
447 try
448 {
449 if(msg.method()==ACK)
450 {
451 return result;
452 }
453 }
454 catch(BaseException&)
455 {
456 // .bwc. Parse failed on the start-line. Stop.
457 return result;
458 }
459
460 const Tuple& dest = msg.getSource();
461
462 // Calculate compartment ID for outbound message
463 Data remoteSigcompId;
464 setRemoteSigcompId(msg,remoteSigcompId);
465
466 // .bwc. msg is completely unverified. Handle with caution.
467 result=makeSendData(dest, Data::Empty, Data::Empty, remoteSigcompId);
468 Helper::makeRawResponse(result->data, msg, 100);
469
470 return result;
471}
472
473void
475{
477 {
478 try
479 {
480 const Via &topVia(msg.const_header(h_Vias).front());
481
482 if(topVia.exists(p_comp) && topVia.param(p_comp) == "sigcomp")
483 {
484 if (topVia.exists(p_sigcompId))
485 {
486 remoteSigcompId = topVia.param(p_sigcompId);
487 }
488 else
489 {
490 // XXX rohc-sigcomp-sip-03 says "sent-by",
491 // but this should probably be "received" if present,
492 // and "sent-by" otherwise.
493 // XXX Also, the spec is ambiguous about whether
494 // to include the port in this identifier.
495 remoteSigcompId = topVia.sentHost();
496 }
497 }
498 }
499 catch(BaseException&)
500 {
501 // ?bwc? Couldn't grab sigcomp compartment id. We don't even know if
502 // the initial request was using sigcomp or not.
503 // What should we do here?
504 }
505 }
506}
507
508void
510{
511 // set the received= and rport= parameters in the message if necessary !jf!
512 if (message->isRequest() && message->exists(h_Vias) && !message->const_header(h_Vias).empty())
513 {
514 const Tuple& tuple = message->getSource();
515 Data received = Tuple::inet_ntop(tuple);
516 if(message->const_header(h_Vias).front().sentHost() != received) // only add if received address is different from sent-by in Via
517 {
518 message->header(h_Vias).front().param(p_received) = received;
519 }
520 //message->header(h_Vias).front().param(p_received) = Tuple::inet_ntop(tuple);
521 if (message->const_header(h_Vias).front().exists(p_rport))
522 {
523 message->header(h_Vias).front().param(p_rport).port() = tuple.getPort();
524 }
525 }
526 DebugLog (<< "incoming from: " << message->getSource());
527 StackLog (<< endl << endl << *message);
528}
529
530bool
532{
533 resip::Data reason;
534 if (msg.isExternal())
535 {
536 try
537 {
538 if (!Helper::validateMessage(msg,&reason))
539 {
540 InfoLog(<<"Message Failed basicCheck :" << msg.brief());
541 if (msg.isRequest() && msg.method()!=ACK )
542 {
543 // this is VERY low-level b/c we don't have a transaction...
544 // here we make a response to warn the offending party.
545 makeFailedResponse(msg,400,reason.c_str());
546 }
547 return false;
548 }
549 else if (mShuttingDown && msg.isRequest() && msg.method() != ACK)
550 {
551 InfoLog (<< "Server has been shutdown, reject message with 503");
552 // this is VERY low-level b/c we don't have a transaction...
553 // here we make a response to warn the offending party.
554 makeFailedResponse(msg, 503, "Server has been shutdown");
555 return false;
556 }
557 }
558 catch (BaseException& e)
559 {
560 InfoLog (<< "Cannot make failure response to badly constructed message: " << e);
561 return false;
562 }
563 }
564 return true;
565}
566
567bool
569{
570 // Refused once per change, not once per accepted connection.
571 if (dscp < -1 || dscp > 63)
572 {
573 ErrLog(<< *this << " refusing DSCP class " << dscp << ", outside -1..63");
574 return false;
575 }
576
577 if (mDscp.exchange(dscp) != dscp)
578 {
579 mDscpRefreshPending.store(true);
580 }
581
582 // Raised on every call, not only on a change: a marking that failed is then
583 // reported again on the next reload rather than reading as fixed.
584 mDscpReportPending.store(true);
585
586 return true;
587}
588
589int
591{
592 return effectiveDscp(mDscp.load());
593}
594
595int
597{
598 if (wanted >= 0)
599 {
600 return wanted;
601 }
602
603 return mWasMarkRequested.load() ? 0 : -1;
604}
605
606void
608{
609 const int dscp = effectiveDscp();
610 if (dscp >= 0)
611 {
612 // The return is dropped on purpose: the listener read-back reports the
613 // state once, instead of once per socket a refresh touches.
614 setSocketDscp(sock, dscp, ipVersion());
615 mWasMarkRequested.store(true);
616 }
617
618 callSocketFunc(sock);
619}
620
621void
623{
624 if (mSocketFunc)
625 {
626 mSocketFunc(sock, transport(), __FILE__, __LINE__);
627 }
628}
629
630void
632{
633 for(auto& handler : getSipMessageLoggingHandlers())
634 {
635 handler->inboundMessage(message->getSource(), message->getReceivedTransportTuple(), *message);
636 }
637
638 mStateMachineFifo.add(message);
639}
640
641bool
643{
644 return ( ( mTuple.isV4() == rhs.isV4()) &&
645 ( port() == rhs.port()) &&
646 ( memcmp(&boundInterface(),&rhs.boundInterface(),mTuple.length()) == 0) );
647}
648
650resip::operator<<(EncodeStream& strm, const resip::Transport& rhs)
651{
652 strm << "Transport: " << rhs.mTuple;
653 if (rhs.hasSpecificContact() && !rhs.mInterface.empty()) strm << " on " << rhs.mInterface;
654 if (!rhs.mTlsDomain.empty()) strm << " (tlsdomain=" << rhs.mTlsDomain << ")";
655 return strm;
656}
657
658/* ====================================================================
659 * The Vovida Software License, Version 1.0
660 *
661 * Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
662 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
663 *
664 * Redistribution and use in source and binary forms, with or without
665 * modification, are permitted provided that the following conditions
666 * are met:
667 *
668 * 1. Redistributions of source code must retain the above copyright
669 * notice, this list of conditions and the following disclaimer.
670 *
671 * 2. Redistributions in binary form must reproduce the above copyright
672 * notice, this list of conditions and the following disclaimer in
673 * the documentation and/or other materials provided with the
674 * distribution.
675 *
676 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
677 * and "Vovida Open Communication Application Library (VOCAL)" must
678 * not be used to endorse or promote products derived from this
679 * software without prior written permission. For written
680 * permission, please contact vocal@vovida.org.
681 *
682 * 4. Products derived from this software may not be called "VOCAL", nor
683 * may "VOCAL" appear in their name, without prior written
684 * permission of Vovida Networks, Inc.
685 *
686 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
687 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
688 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
689 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
690 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
691 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
692 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
693 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
694 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
695 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
696 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
697 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
698 * DAMAGE.
699 *
700 * ====================================================================
701 *
702 * This software consists of voluntary contributions made by Vovida
703 * Networks, Inc. and many individuals on behalf of Vovida Networks,
704 * Inc. For more information on Vovida Networks, Inc., please see
705 * <http://www.vovida.org/>.
706 *
707 * vi: set shiftwidth=3 expandtab:
708 */
#define DebugLog(args_)
Definition Logger.hxx:128
#define StackLog(args_)
Definition Logger.hxx:125
#define InfoLog(args_)
Definition Logger.hxx:131
#define ErrLog(args_)
Definition Logger.hxx:137
#define resip_assert(x)
This file needs to work for both C and C++ code.
Handles cross-platform sockets compatibility.
#define WSANOTINITIALISED
Definition Socket.hxx:82
#define INVALID_SOCKET
Definition Socket.hxx:95
int Socket
The abstract base-class for all exceptions thrown by resip code.
An iostream that operates on an existing Data.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
static const Data Empty
Constant that represents a zero-length data.
Definition Data.hxx:882
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
Data & clear()
Clears the contents of this Data.
Definition Data.hxx:800
A templated, threadsafe message-queue class.
Definition Fifo.hxx:16
static bool validateMessage(const SipMessage &message, resip::Data *reason=0)
Definition Helper.cxx:1791
static void makeResponse(SipMessage &response, const SipMessage &request, int responseCode, const Data &reason=Data::Empty, const Data &hostname=Data::Empty, const Data &warning=Data::Empty)
Make a response to a provided request.
Definition Helper.cxx:412
static void makeRawResponse(Data &rawBuffer, const SipMessage &request, int responseCode, const Data &additionalHeaders=Data::Empty, const Data &body=Data::Empty)
Definition Helper.cxx:549
virtual Brief brief() const
return a facet for brief encoding of message
Definition Message.cxx:16
Represents a SIP message.
bool isRequest() const
Returns true if message is a request, false otherwise.
const Tuple & getReceivedTransportTuple() const
const RequestLine & header(const RequestLineType &l) const
Returns the RequestLine. This is only valid for request messages.
bool isResponse() const
Returns true if message is a response, false otherwise.
const RequestLine & const_header(const RequestLineType &l) const
bool exists(const HeaderBase &headerType) const
Returns true if the given header field is present, false otherwise.
const Tuple & getSource() const
Returns the source tuple that the message was received from only makes sense for messages received fr...
bool isExternal() const
Check if SipMessage is to be treated as it came off the wire.
resip::MethodTypes method() const
returns the method type of the message
This message is used to indicate to the transaction state that a TCP based transport is trying to TCP...
This message is used to indicate that the TransportSelector has sent a sip message using either relia...
Exception(const Data &msg, const Data &file, int line)
Definition Transport.cxx:68
The base class for Transport classes.
Definition Transport.hxx:83
void drainDscpRefresh()
Serves a pending refresh and a pending report.
virtual bool hasSpecificContact() const
std::unique_ptr< SendData > make503(SipMessage &msg, uint16_t retryAfter)
void setSipMessageLoggingHandlers(const SipMessageLoggingHandlerList &handlers)
Definition Transport.cxx:51
void makeFailedResponse(const SipMessage &msg, int responseCode=400, const char *warning=nullptr)
void unsetSipMessageLoggingHandler() noexcept
Definition Transport.cxx:57
IpVersion ipVersion() const
std::atomic< bool > mWasMarkRequested
Whether this transport has asked a socket to carry a class that a clear would have to undo.
AfterSocketCreationFuncPtr mSocketFunc
int effectiveDscp() const
The class to write to a socket right now, or -1 to leave it alone.
const TransportType transport() const
unsigned mTransportFlags
bool isV4() const
CongestionManager * mCongestionManager
virtual void pushRxMsgUp(SipMessage *msg)
std::unique_ptr< SendData > make100(SipMessage &msg)
Transport(Fifo< TransactionMessage > &rxFifo, const GenericIPAddress &address, const Data &tlsDomain=Data::Empty, AfterSocketCreationFuncPtr socketFunc=nullptr, Compression &compression=Compression::Disabled)
Definition Transport.cxx:73
std::atomic< bool > mDscpReportPending
Set by every setDscp() call, cleared by the owning thread's report, so a reload that changed nothing ...
static void stampReceived(SipMessage *request)
int port() const
static Data errorToString(int e)
SipMessageLoggingHandlerList getSipMessageLoggingHandlers() const noexcept
Definition Transport.cxx:63
void fail(const Data &tid, TransportFailure::FailureReason reason=TransportFailure::Failure, int subCode=0)
Posts a TransportFailure to the TransactionMessage Fifo.
Compression & mCompression
std::atomic< int > mDscp
the class to write, -1 for "do not mark"
bool operator==(const Transport &rhs) const
virtual ~Transport()
void callSocketFunc(Socket sock) const
bool basicCheck(const SipMessage &msg)
Perform basic sanity checks on message.
const sockaddr & boundInterface() const
virtual void invokeAfterSocketCreationFunc() const =0
void setSipMessageLoggingHandler(std::shared_ptr< SipMessageLoggingHandler > handler)
Definition Transport.cxx:31
const Data & tlsDomain() const
bool setDscp(int dscp)
Sets the DSCP class this transport puts on its sockets, and returns whether it was accepted.
void applyDscpToOwnSockets()
Re-runs the per-socket set-up on every socket this transport holds – the listener,...
std::atomic< bool > mDscpRefreshPending
Set by setDscp() when the value changes, cleared by the owning thread's refresh.
void setRemoteSigcompId(SipMessage &msg, Data &id)
void applySocketOptions(Socket sock) const
The one place a socket of this transport is configured.
static void error(int e)
Generates a generic log for the platform specific socket error number.
virtual void onReload()
ProducerFifoBuffer< TransactionMessage > mStateMachineFifo
void keepAlivePong(const Tuple &flow)
std::vector< std::shared_ptr< SipMessageLoggingHandler > > SipMessageLoggingHandlerList
std::unique_ptr< SendData > makeSendData(const Tuple &tuple, const Data &data, const Data &tid, const Data &sigcompId=Data::Empty)
void flowTerminated(const Tuple &flow, TransportFailure::FailureReason failureReason, int failureSubCode, const Data &failureString, const std::list< Data > additionalFailureStrings)
Posts a ConnectionTerminated message to TransactionMessage Fifo.
void addSipMessageLoggingHandler(std::shared_ptr< SipMessageLoggingHandler > handler)
Definition Transport.cxx:42
virtual void send(std::unique_ptr< SendData > data)=0
virtual Socket getListenerSocket() const
The transport's own listening or bound socket, or INVALID_SOCKET for a transport that holds none.
void setTcpConnectState(const Data &tid, TcpConnectState::State state)
Posts a TcpConnectState to the TransactionMessage Fifo.
Represents a network address.
Definition Tuple.hxx:59
socklen_t length() const
Definition Tuple.cxx:655
bool isV4() const
Definition Tuple.cxx:531
int getPort() const
Definition Tuple.cxx:466
static Data inet_ntop(const Tuple &tuple)
Converts the binary socket address to presentation format, via the DnsUtil::inet_ntop() method.
Definition Tuple.cxx:939
Represents the "via-parm" element in the RFC 3261 grammar.
Definition Via.hxx:18
bool exists(const Param< Via > &paramType) const
Definition Via.cxx:266
Data & sentHost()
Definition Via.cxx:135
const Data & param(const ExtensionParameter &param) const
Const accessor for non-natively-supported parameter types.
dcm! – add UnusedChecking(_enum) below;
void(* AfterSocketCreationFuncPtr)(Socket s, int transportType, const char *file, int line)
Definition Socket.hxx:107
unsigned short uint16_t
Definition Stun.hxx:30
int Socket
Definition Socket.hxx:94
@ UNKNOWN_TRANSPORT
int setSocketDscp(Socket fd, int dscp, IpVersion version)
Sets the DSCP class of {fd}, in the IPv4 ToS byte or the IPv6 traffic class, and reads it back.
Definition Socket.cxx:292
std::string strError(int err)
Definition compat.hxx:274
int getSocketTos(Socket fd, IpVersion version)
Reads the IPv4 ToS byte, or the IPv6 traffic class, of {fd}.
Definition Socket.cxx:322
IpVersion
An enumeration of IP versions.
EncodeStream & operator<<(EncodeStream &strm, const BaseException &e)
#define EncodeStream
Represents an IP-address and port (V4 or V6).