reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
InternalTransport.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#include <fcntl.h>
8
9#if defined(HAVE_SYS_SOCKIO_H)
10#include <sys/sockio.h>
11#endif
12
13#if defined(HAVE_SOCK_CLOEXEC)
14#include <sys/socket.h>
15#endif
16
20#include "rutil/DnsUtil.hxx"
21#include "rutil/Logger.hxx"
23
24using namespace resip;
25using namespace std;
26
27#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
28
29
31 int portNum,
32 IpVersion version,
33 const Data& interfaceObj,
35 Compression &compression,
36 unsigned transportFlags,
37 const Data& netNs) :
38 Transport(rxFifo, portNum, version, interfaceObj, Data::Empty,
39 socketFunc, compression, transportFlags, netNs),
40 mFd(INVALID_SOCKET),
41 mInterruptorHandle(0),
42 mTxFifoOutBuffer(mTxFifo),
43 mPollGrp(NULL),
44 mPollItemHandle(NULL)
45{}
46
48{
50 {
52 }
54 {
56 }
57
58 if (mFd != INVALID_SOCKET)
59 {
60 //DebugLog (<< "Closing " << mFd);
62 }
63 mFd = -2;
64 if(!mTxFifo.empty())
65 {
66 WarningLog(<< "TX Fifo non-empty in ~InternalTransport! Has " << mTxFifo.size() << " messages.");
67 }
68 setCongestionManager(0); // Clear out congestion manager
69}
70
71bool
73{
74 return !mTxFifoOutBuffer.messageAvailable();
75}
76
79{
80#if defined(HAVE_SOCK_CLOEXEC)
81 const int sockCloexec = SOCK_CLOEXEC;
82#else
83 const int sockCloexec = 0;
84#endif
85
86 Socket fd;
87 switch (type)
88 {
89 case UDP:
90#ifdef USE_IPV6
91 fd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_DGRAM | sockCloexec, IPPROTO_UDP);
92#else
93 fd = ::socket(PF_INET, SOCK_DGRAM | sockCloexec, IPPROTO_UDP);
94#endif
95 break;
96 case TCP:
97 case TLS:
98#ifdef USE_IPV6
99 fd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_STREAM | sockCloexec, 0);
100#else
101 fd = ::socket(PF_INET, SOCK_STREAM | sockCloexec, 0);
102#endif
103 break;
104 default:
105 InfoLog (<< "Try to create an unsupported socket type: " << Tuple::toData(type));
106 resip_assert(0);
107 throw Transport::Exception("Unsupported transport", __FILE__,__LINE__);
108 }
109
110 if ( fd == INVALID_SOCKET )
111 {
112 int e = getErrno();
113 ErrLog (<< "Failed to create socket: " << strError(e));
114 throw Transport::Exception("Can't create TcpBaseTransport", __FILE__,__LINE__);
115 }
116#if defined(WIN32)
117 if (!SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0))
118 {
119 int e = getErrno();
120 ErrLog(<< "Failed to set handle information: " << strError(e));
121 throw Transport::Exception("Failed SetHandleInformation", __FILE__, __LINE__);
122 }
123#elif !defined(HAVE_SOCK_CLOEXEC)
124 int flags = fcntl(fd, F_GETFD);
125 if (flags == -1)
126 {
127 int e = getErrno();
128 ErrLog (<< "Failed to get socket flags: " << strError(e));
129 throw Transport::Exception("Can't get socket flags", __FILE__,__LINE__);
130 }
131 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
132 {
133 int e = getErrno();
134 ErrLog (<< "Failed to set socket flags: " << strError(e));
135 throw Transport::Exception("Can't set socket flags", __FILE__,__LINE__);
136 }
137#endif
138
139#ifdef USE_IPV6
140#ifdef __linux__
141 int on = 1;
142 if (ipVer == V6)
143 {
144 if ( ::setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) )
145 {
146 int e = getErrno();
147 InfoLog (<< "Couldn't set sockoptions IPV6_V6ONLY: " << strError(e));
148 error(e);
149 throw Exception("Failed setsockopt", __FILE__,__LINE__);
150 }
151 }
152#endif
153#endif
154
155 DebugLog (<< "Creating fd=" << fd << (ipVer == V4 ? " V4/" : " V6/") << (type == UDP ? "UDP" : "TCP"));
156
157 return fd;
158}
159
160void
162{
163#ifdef USE_NETNS
164 DebugLog (<< "Binding to " << Tuple::inet_ntop(mTuple)
165 << " in netns=\"" <<mTuple.getNetNs() << "\"");
166#else
167 DebugLog (<< "Binding to " << Tuple::inet_ntop(mTuple));
168#endif
169
171 {
172 int e = getErrno();
173 if ( e == EADDRINUSE )
174 {
175 error(e);
176 ErrLog (<< mTuple << " already in use ");
177 throw Transport::Exception("port already in use", __FILE__,__LINE__);
178 }
179 else
180 {
181 error(e);
182 ErrLog (<< "Could not bind to " << mTuple);
183 throw Transport::Exception("Could not use port", __FILE__,__LINE__);
184 }
185 }
186
187 // If we bound to port 0, then query OS for assigned port number
188 if (mTuple.getPort() == 0)
189 {
190 socklen_t len = mTuple.length();
191 if (::getsockname(mFd, &mTuple.getMutableSockaddr(), &len) == SOCKET_ERROR)
192 {
193 int e = getErrno();
194 ErrLog (<<"getsockname failed, error=" << e);
195 throw Transport::Exception("Could not query port", __FILE__,__LINE__);
196 }
197 }
198
199 bool ok = makeSocketNonBlocking(mFd);
200 if ( !ok )
201 {
202 ErrLog (<< "Could not make socket non-blocking " << port());
203 throw Transport::Exception("Failed making socket non-blocking", __FILE__,__LINE__);
204 }
205
207}
208
209unsigned int
211{
212 return mTxFifo.size();
213}
214
215bool
217{
218 return mTxFifoOutBuffer.messageAvailable();
219}
220
221void
222InternalTransport::send(std::unique_ptr<SendData> data)
223{
224 mTxFifo.add(data.release());
225}
226
227void
229{
231 {
232 // If this transport does not have its own thread, it does not need to
233 // register its SelectInterruptor because the TransportSelector will take
234 // care of interrupting the select()/epoll() loop when necessary.
236 {
239 }
240
241 if (grp)
242 {
244 }
245 }
246
247 mPollGrp = grp;
248}
249
250void
252{
253 // !bwc! I have tried installing mSelectInterruptor in mTxFifo, but it
254 // hampers performance. This seems to be because we get a significant
255 // performance boost from having multiple messages added to mTxFifo before
256 // mSelectInterruptor is invoked (this is what the TransactionController
257 // does; it processes at most 16 TransactionMessages, and then pokes the
258 // Transports). Once we have buffered producer queues in place, this
259 // performance concern will be rendered moot, and we'll be able to install
260 // the interruptor in mTxFifo.
261 if(mTxFifoOutBuffer.messageAvailable())
262 {
263 // This will interrupt the select statement and cause processing of
264 // this new outgoing message.
266 }
267}
268
269void
274
275
276/* ====================================================================
277 * The Vovida Software License, Version 1.0
278 *
279 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
280 *
281 * Redistribution and use in source and binary forms, with or without
282 * modification, are permitted provided that the following conditions
283 * are met:
284 *
285 * 1. Redistributions of source code must retain the above copyright
286 * notice, this list of conditions and the following disclaimer.
287 *
288 * 2. Redistributions in binary form must reproduce the above copyright
289 * notice, this list of conditions and the following disclaimer in
290 * the documentation and/or other materials provided with the
291 * distribution.
292 *
293 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
294 * and "Vovida Open Communication Application Library (VOCAL)" must
295 * not be used to endorse or promote products derived from this
296 * software without prior written permission. For written
297 * permission, please contact vocal@vovida.org.
298 *
299 * 4. Products derived from this software may not be called "VOCAL", nor
300 * may "VOCAL" appear in their name, without prior written
301 * permission of Vovida Networks, Inc.
302 *
303 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
304 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
305 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
306 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
307 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
308 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
309 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
310 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
312 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
313 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
314 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
315 * DAMAGE.
316 *
317 * ====================================================================
318 *
319 * This software consists of voluntary contributions made by Vovida
320 * Networks, Inc. and many individuals on behalf of Vovida Networks,
321 * Inc. For more information on Vovida Networks, Inc., please see
322 * <http://www.vovida.org/>.
323 *
324 * vi: set shiftwidth=3 expandtab:
325 */
#define FPEM_Read
Definition FdPoll.hxx:29
#define DebugLog(args_)
Definition Logger.hxx:128
#define InfoLog(args_)
Definition Logger.hxx:131
#define WarningLog(args_)
Definition Logger.hxx:134
#define ErrLog(args_)
Definition Logger.hxx:137
#define resip_assert(x)
This file needs to work for both C and C++ code.
#define INVALID_SOCKET
Definition Socket.hxx:95
#define SOCKET_ERROR
Definition Socket.hxx:96
static const struct nv flags[]
Definition adig.c:62
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
virtual FdPollItemHandle addPollItem(Socket sock, FdPollEventMask newMask, FdPollItemIf *item)=0
virtual void delPollItem(FdPollItemHandle handle)=0
A templated, threadsafe message-queue class.
Definition Fifo.hxx:16
virtual bool shareStackProcessAndSelect() const
Returns true if this Transport should be included in the FdSet processing loop, false if the Transpor...
virtual void poke()
Called when a writer is done adding messages to the TxFifo; this is used to interrupt the select call...
static Socket socket(TransportType type, IpVersion ipVer)
virtual void setCongestionManager(CongestionManager *manager)
SelectInterruptor mSelectInterruptor
virtual unsigned int getFifoSize() const
virtual void send(std::unique_ptr< SendData > data)
virtual bool isFinished() const
ConsumerFifoBuffer< SendData > mTxFifoOutBuffer
FdPollItemHandle mInterruptorHandle
InternalTransport(Fifo< TransactionMessage > &rxFifo, int portNum, IpVersion version, const Data &interfaceObj, AfterSocketCreationFuncPtr socketFunc=0, Compression &compression=Compression::Disabled, unsigned transportFlags=0, const Data &netNs=Data::Empty)
virtual void invokeAfterSocketCreationFunc() const
virtual bool hasDataToSend() const
only applies to transports that shareStackProcessAndSelect
virtual void setPollGrp(FdPollGrp *grp)
virtual void handleProcessNotification()
Called by the stack when messages are posted to it.
General exception class for Transport.
The base class for Transport classes.
Definition Transport.hxx:83
int port() const
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.
sockaddr & getMutableSockaddr()
Retrieve the binary representation of the socket address for this tuple.
Definition Tuple.hxx:113
static const Data & toData(TransportType)
Converts the TransportType to a string representation of the transport type, e.g.
Definition Tuple.cxx:927
const Data & getNetNs() const
Get the netns for this Tuple.
Definition Tuple.hxx:271
socklen_t length() const
Definition Tuple.cxx:655
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
dcm! – add UnusedChecking(_enum) below;
void(* AfterSocketCreationFuncPtr)(Socket s, int transportType, const char *file, int line)
Definition Socket.hxx:107
int Socket
Definition Socket.hxx:94
int closeSocket(Socket fd)
Definition Socket.cxx:134
TransportType
An enumeration of transport protocols.
int getErrno()
Definition Socket.hxx:97
std::string strError(int err)
Definition compat.hxx:274
IpVersion
An enumeration of IP versions.
bool makeSocketNonBlocking(Socket fd)
Definition Socket.cxx:21