|
reSIProcate/stack
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #include <iostream> 00006 00007 #if defined(HAVE_SYS_SOCKIO_H) 00008 #include <sys/sockio.h> 00009 #endif 00010 00011 #include "resip/stack/Helper.hxx" 00012 #include "resip/stack/InternalTransport.hxx" 00013 #include "resip/stack/SipMessage.hxx" 00014 #include "rutil/DnsUtil.hxx" 00015 #include "rutil/Logger.hxx" 00016 #include "rutil/WinLeakCheck.hxx" 00017 00018 using namespace resip; 00019 using namespace std; 00020 00021 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT 00022 00023 00024 InternalTransport::InternalTransport(Fifo<TransactionMessage>& rxFifo, 00025 int portNum, 00026 IpVersion version, 00027 const Data& interfaceObj, 00028 AfterSocketCreationFuncPtr socketFunc, 00029 Compression &compression, 00030 unsigned transportFlags) : 00031 Transport(rxFifo, portNum, version, interfaceObj, Data::Empty, 00032 socketFunc, compression, transportFlags), 00033 mFd(INVALID_SOCKET), 00034 mInterruptorHandle(0), 00035 mTxFifoOutBuffer(mTxFifo), 00036 mPollGrp(NULL), 00037 mPollItemHandle(NULL) 00038 {} 00039 00040 InternalTransport::~InternalTransport() 00041 { 00042 if (mPollItemHandle) 00043 mPollGrp->delPollItem(mPollItemHandle); 00044 if (mInterruptorHandle) 00045 mPollGrp->delPollItem(mInterruptorHandle); 00046 00047 if (mFd != INVALID_SOCKET) 00048 { 00049 //DebugLog (<< "Closing " << mFd); 00050 closeSocket(mFd); 00051 } 00052 mFd = -2; 00053 if(!mTxFifo.empty()) 00054 { 00055 WarningLog(<< "TX Fifo non-empty in ~InternalTransport! Has " << mTxFifo.size() << " messages."); 00056 } 00057 } 00058 00059 bool 00060 InternalTransport::isFinished() const 00061 { 00062 return !mTxFifoOutBuffer.messageAvailable(); 00063 } 00064 00065 Socket 00066 InternalTransport::socket(TransportType type, IpVersion ipVer) 00067 { 00068 Socket fd; 00069 switch (type) 00070 { 00071 case UDP: 00072 #ifdef USE_IPV6 00073 fd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_DGRAM, IPPROTO_UDP); 00074 #else 00075 fd = ::socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 00076 #endif 00077 break; 00078 case TCP: 00079 case TLS: 00080 #ifdef USE_IPV6 00081 fd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_STREAM, 0); 00082 #else 00083 fd = ::socket(PF_INET, SOCK_STREAM, 0); 00084 #endif 00085 break; 00086 default: 00087 InfoLog (<< "Try to create an unsupported socket type: " << Tuple::toData(type)); 00088 assert(0); 00089 throw Transport::Exception("Unsupported transport", __FILE__,__LINE__); 00090 } 00091 00092 if ( fd == INVALID_SOCKET ) 00093 { 00094 int e = getErrno(); 00095 ErrLog (<< "Failed to create socket: " << strerror(e)); 00096 throw Transport::Exception("Can't create TcpBaseTransport", __FILE__,__LINE__); 00097 } 00098 00099 DebugLog (<< "Creating fd=" << fd << (ipVer == V4 ? " V4/" : " V6/") << (type == UDP ? "UDP" : "TCP")); 00100 00101 return fd; 00102 } 00103 00104 void 00105 InternalTransport::bind() 00106 { 00107 DebugLog (<< "Binding to " << Tuple::inet_ntop(mTuple)); 00108 00109 if ( ::bind( mFd, &mTuple.getMutableSockaddr(), mTuple.length()) == SOCKET_ERROR ) 00110 { 00111 int e = getErrno(); 00112 if ( e == EADDRINUSE ) 00113 { 00114 error(e); 00115 ErrLog (<< mTuple << " already in use "); 00116 throw Transport::Exception("port already in use", __FILE__,__LINE__); 00117 } 00118 else 00119 { 00120 error(e); 00121 ErrLog (<< "Could not bind to " << mTuple); 00122 throw Transport::Exception("Could not use port", __FILE__,__LINE__); 00123 } 00124 } 00125 00126 // If we bound to port 0, then query OS for assigned port number 00127 if(mTuple.getPort() == 0) 00128 { 00129 socklen_t len = sizeof(mTuple.getMutableSockaddr()); 00130 if(::getsockname(mFd, &mTuple.getMutableSockaddr(), &len) == SOCKET_ERROR) 00131 { 00132 int e = getErrno(); 00133 ErrLog (<<"getsockname failed, error=" << e); 00134 throw Transport::Exception("Could not query port", __FILE__,__LINE__); 00135 } 00136 } 00137 00138 bool ok = makeSocketNonBlocking(mFd); 00139 if ( !ok ) 00140 { 00141 ErrLog (<< "Could not make socket non-blocking " << port()); 00142 throw Transport::Exception("Failed making socket non-blocking", __FILE__,__LINE__); 00143 } 00144 00145 if (mSocketFunc) 00146 { 00147 mSocketFunc(mFd, transport(), __FILE__, __LINE__); 00148 } 00149 } 00150 00151 unsigned int 00152 InternalTransport::getFifoSize() const 00153 { 00154 return mTxFifo.size(); 00155 } 00156 00157 bool 00158 InternalTransport::hasDataToSend() const 00159 { 00160 return mTxFifoOutBuffer.messageAvailable(); 00161 } 00162 00163 void 00164 InternalTransport::send(std::auto_ptr<SendData> data) 00165 { 00166 mTxFifo.add(data.release()); 00167 } 00168 00169 void 00170 InternalTransport::setPollGrp(FdPollGrp *grp) 00171 { 00172 if(!shareStackProcessAndSelect()) 00173 { 00174 // If this transport does not have its own thread, it does not need to 00175 // register its SelectInterruptor because the TransportSelector will take 00176 // care of interrupting the select()/epoll() loop when necessary. 00177 if(mPollGrp && mInterruptorHandle) 00178 { 00179 mPollGrp->delPollItem(mInterruptorHandle); 00180 mInterruptorHandle=0; 00181 } 00182 00183 if (grp) 00184 { 00185 mInterruptorHandle = grp->addPollItem(mSelectInterruptor.getReadSocket(), FPEM_Read, &mSelectInterruptor); 00186 } 00187 } 00188 00189 mPollGrp = grp; 00190 } 00191 00192 void 00193 InternalTransport::poke() 00194 { 00195 // !bwc! I have tried installing mSelectInterruptor in mTxFifo, but it 00196 // hampers performance. This seems to be because we get a significant 00197 // performance boost from having multiple messages added to mTxFifo before 00198 // mSelectInterruptor is invoked (this is what the TransactionController 00199 // does; it processes at most 16 TransactionMessages, and then pokes the 00200 // Transports). Once we have buffered producer queues in place, this 00201 // performance concern will be rendered moot, and we'll be able to install 00202 // the interruptor in mTxFifo. 00203 if(mTxFifoOutBuffer.messageAvailable()) 00204 { 00205 // This will interrupt the select statement and cause processing of 00206 // this new outgoing message. 00207 mSelectInterruptor.handleProcessNotification(); 00208 } 00209 } 00210 00211 00212 /* ==================================================================== 00213 * The Vovida Software License, Version 1.0 00214 * 00215 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00216 * 00217 * Redistribution and use in source and binary forms, with or without 00218 * modification, are permitted provided that the following conditions 00219 * are met: 00220 * 00221 * 1. Redistributions of source code must retain the above copyright 00222 * notice, this list of conditions and the following disclaimer. 00223 * 00224 * 2. Redistributions in binary form must reproduce the above copyright 00225 * notice, this list of conditions and the following disclaimer in 00226 * the documentation and/or other materials provided with the 00227 * distribution. 00228 * 00229 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00230 * and "Vovida Open Communication Application Library (VOCAL)" must 00231 * not be used to endorse or promote products derived from this 00232 * software without prior written permission. For written 00233 * permission, please contact vocal@vovida.org. 00234 * 00235 * 4. Products derived from this software may not be called "VOCAL", nor 00236 * may "VOCAL" appear in their name, without prior written 00237 * permission of Vovida Networks, Inc. 00238 * 00239 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00240 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00241 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00242 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00243 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00244 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00245 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00246 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00247 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00248 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00249 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00250 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00251 * DAMAGE. 00252 * 00253 * ==================================================================== 00254 * 00255 * This software consists of voluntary contributions made by Vovida 00256 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00257 * Inc. For more information on Vovida Networks, Inc., please see 00258 * <http://www.vovida.org/>. 00259 * 00260 * vi: set shiftwidth=3 expandtab: 00261 */
1.7.5.1