|
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 "rutil/Socket.hxx" 00012 #include "rutil/DnsUtil.hxx" 00013 #include "rutil/Logger.hxx" 00014 #include "rutil/ParseBuffer.hxx" 00015 00016 #include "resip/stack/ConnectionTerminated.hxx" 00017 #include "resip/stack/KeepAlivePong.hxx" 00018 #include "resip/stack/Transport.hxx" 00019 #include "resip/stack/SipMessage.hxx" 00020 #include "resip/stack/TransportFailure.hxx" 00021 #include "resip/stack/Helper.hxx" 00022 #include "resip/stack/SendData.hxx" 00023 #include "rutil/WinLeakCheck.hxx" 00024 00025 using namespace resip; 00026 using namespace std; 00027 00028 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT 00029 00030 Transport::Exception::Exception(const Data& msg, const Data& file, const int line) : 00031 BaseException(msg,file,line) 00032 { 00033 } 00034 00035 Transport::Transport(Fifo<TransactionMessage>& rxFifo, 00036 const GenericIPAddress& address, 00037 const Data& tlsDomain, 00038 AfterSocketCreationFuncPtr socketFunc, 00039 Compression &compression) : 00040 mTuple(address), 00041 mHasRecordRoute(false), 00042 mKey(0), 00043 mCongestionManager(0), 00044 mStateMachineFifo(rxFifo, 8), 00045 mShuttingDown(false), 00046 mTlsDomain(tlsDomain), 00047 mSocketFunc(socketFunc), 00048 mCompression(compression), 00049 mTransportFlags(0) 00050 { 00051 mInterface = Tuple::inet_ntop(mTuple); 00052 } 00053 00054 Transport::Transport(Fifo<TransactionMessage>& rxFifo, 00055 int portNum, 00056 IpVersion version, 00057 const Data& intfc, 00058 const Data& tlsDomain, 00059 AfterSocketCreationFuncPtr socketFunc, 00060 Compression &compression, 00061 unsigned transportFlags) : 00062 mInterface(intfc), 00063 mTuple(intfc, portNum, version), 00064 mHasRecordRoute(false), 00065 mKey(0), 00066 mCongestionManager(0), 00067 mStateMachineFifo(rxFifo,8), 00068 mShuttingDown(false), 00069 mTlsDomain(tlsDomain), 00070 mSocketFunc(socketFunc), 00071 mCompression(compression), 00072 mTransportFlags(transportFlags) 00073 { 00074 } 00075 00076 Transport::~Transport() 00077 { 00078 } 00079 00080 void 00081 Transport::error(int e) 00082 { 00083 switch (e) 00084 { 00085 case EAGAIN: 00086 //InfoLog (<< "No data ready to read" << strerror(e)); 00087 break; 00088 case EINTR: 00089 InfoLog (<< "The call was interrupted by a signal before any data was read : " << strerror(e)); 00090 break; 00091 case EIO: 00092 InfoLog (<< "I/O error : " << strerror(e)); 00093 break; 00094 case EBADF: 00095 InfoLog (<< "fd is not a valid file descriptor or is not open for reading : " << strerror(e)); 00096 break; 00097 case EINVAL: 00098 InfoLog (<< "fd is attached to an object which is unsuitable for reading : " << strerror(e)); 00099 break; 00100 case EFAULT: 00101 InfoLog (<< "buf is outside your accessible address space : " << strerror(e)); 00102 break; 00103 00104 #if defined(WIN32) 00105 case WSAENETDOWN: 00106 InfoLog (<<" The network subsystem has failed. "); 00107 break; 00108 case WSAEFAULT: 00109 InfoLog (<<" The buf or from parameters are not part of the user address space, " 00110 "or the fromlen parameter is too small to accommodate the peer address. "); 00111 break; 00112 case WSAEINTR: 00113 InfoLog (<<" The (blocking) call was canceled through WSACancelBlockingCall. "); 00114 break; 00115 case WSAEINPROGRESS: 00116 InfoLog (<<" A blocking Windows Sockets 1.1 call is in progress, or the " 00117 "service provider is still processing a callback function. "); 00118 break; 00119 case WSAEINVAL: 00120 InfoLog (<<" The socket has not been bound with bind, or an unknown flag was specified, " 00121 "or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, " 00122 "or (for byte stream-style sockets only) len was zero or negative. "); 00123 break; 00124 case WSAEISCONN : 00125 InfoLog (<<"The socket is connected. This function is not permitted with a connected socket, " 00126 "whether the socket is connection-oriented or connectionless. "); 00127 break; 00128 case WSAENETRESET: 00129 InfoLog (<<" The connection has been broken due to the keep-alive activity " 00130 "detecting a failure while the operation was in progress. "); 00131 break; 00132 case WSAENOTSOCK : 00133 InfoLog (<<"The descriptor is not a socket. "); 00134 break; 00135 case WSAEOPNOTSUPP: 00136 InfoLog (<<" MSG_OOB was specified, but the socket is not stream-style such as type " 00137 "SOCK_STREAM, OOB data is not supported in the communication domain associated with this socket, " 00138 "or the socket is unidirectional and supports only send operations. "); 00139 break; 00140 case WSAESHUTDOWN: 00141 InfoLog (<<"The socket has been shut down; it is not possible to recvfrom on a socket after " 00142 "shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH. "); 00143 break; 00144 case WSAEMSGSIZE: 00145 InfoLog (<<" The message was too large to fit into the specified buffer and was truncated. "); 00146 break; 00147 case WSAETIMEDOUT: 00148 InfoLog (<<" The connection has been dropped, because of a network failure or because the " 00149 "system on the other end went down without notice. "); 00150 break; 00151 case WSAECONNRESET : 00152 InfoLog (<<"Connection reset "); 00153 break; 00154 00155 case WSAEWOULDBLOCK: 00156 DebugLog (<<"Would Block "); 00157 break; 00158 00159 case WSAEHOSTUNREACH: 00160 InfoLog (<<"A socket operation was attempted to an unreachable host "); 00161 break; 00162 case WSANOTINITIALISED: 00163 InfoLog (<<"Either the application has not called WSAStartup or WSAStartup failed. " 00164 "The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks)," 00165 "or WSACleanup has been called too many times. "); 00166 break; 00167 case WSAEACCES: 00168 InfoLog (<<"An attempt was made to access a socket in a way forbidden by its access permissions "); 00169 break; 00170 case WSAENOBUFS: 00171 InfoLog (<<"An operation on a socket could not be performed because the system lacked sufficient " 00172 "buffer space or because a queue was full"); 00173 break; 00174 case WSAENOTCONN: 00175 InfoLog (<<"A request to send or receive data was disallowed because the socket is not connected " 00176 "and (when sending on a datagram socket using sendto) no address was supplied"); 00177 break; 00178 case WSAECONNABORTED: 00179 InfoLog (<<"An established connection was aborted by the software in your host computer, possibly " 00180 "due to a data transmission time-out or protocol error"); 00181 break; 00182 case WSAEADDRNOTAVAIL: 00183 InfoLog (<<"The requested address is not valid in its context. This normally results from an attempt to " 00184 "bind to an address that is not valid for the local computer"); 00185 break; 00186 case WSAEAFNOSUPPORT: 00187 InfoLog (<<"An address incompatible with the requested protocol was used"); 00188 break; 00189 case WSAEDESTADDRREQ: 00190 InfoLog (<<"A required address was omitted from an operation on a socket"); 00191 break; 00192 case WSAENETUNREACH: 00193 InfoLog (<<"A socket operation was attempted to an unreachable network"); 00194 break; 00195 00196 #endif 00197 00198 default: 00199 InfoLog (<< "Some other error (" << e << "): " << strerror(e)); 00200 break; 00201 } 00202 } 00203 00204 void 00205 Transport::flowTerminated(const Tuple& flow) 00206 { 00207 mStateMachineFifo.add(new ConnectionTerminated(flow)); 00208 } 00209 00210 void 00211 Transport::keepAlivePong(const Tuple& flow) 00212 { 00213 mStateMachineFifo.add(new KeepAlivePong(flow)); 00214 } 00215 00216 void 00217 Transport::fail(const Data& tid, TransportFailure::FailureReason reason, int subCode) 00218 { 00219 if (!tid.empty()) 00220 { 00221 mStateMachineFifo.add(new TransportFailure(tid, reason, subCode)); 00222 } 00223 } 00224 00225 std::auto_ptr<SendData> 00226 Transport::makeSendData( const Tuple& dest, const Data& d, const Data& tid, const Data &sigcompId) 00227 { 00228 assert(dest.getPort() != -1); 00229 std::auto_ptr<SendData> data(new SendData(dest, d, tid, sigcompId)); 00230 return data; 00231 } 00232 00233 void 00234 Transport::makeFailedResponse(const SipMessage& msg, 00235 int responseCode, 00236 const char * warning) 00237 { 00238 if (msg.isResponse()) return; 00239 00240 const Tuple& dest = msg.getSource(); 00241 00242 std::auto_ptr<SipMessage> errMsg(Helper::makeResponse(msg, 00243 responseCode, 00244 warning ? warning : "Original request had no Vias")); 00245 00246 // make send data here w/ blank tid and blast it out. 00247 // encode message 00248 Data encoded; 00249 encoded.clear(); 00250 DataStream encodeStream(encoded); 00251 errMsg->encode(encodeStream); 00252 encodeStream.flush(); 00253 assert(!encoded.empty()); 00254 00255 InfoLog(<<"Sending response directly to " << dest << " : " << errMsg->brief() ); 00256 00257 // Calculate compartment ID for outbound message 00258 Data remoteSigcompId; 00259 setRemoteSigcompId(*errMsg,remoteSigcompId); 00260 send(std::auto_ptr<SendData>(makeSendData(dest, encoded, Data::Empty, remoteSigcompId))); 00261 } 00262 00263 std::auto_ptr<SendData> 00264 Transport::make503(SipMessage& msg, UInt16 retryAfter) 00265 { 00266 std::auto_ptr<SendData> result; 00267 if (msg.isResponse()) return result; 00268 00269 try 00270 { 00271 if(msg.method()==ACK) 00272 { 00273 return result; 00274 } 00275 } 00276 catch(BaseException&) 00277 { 00278 // .bwc. Parse failed on the start-line. Stop. 00279 return result; 00280 } 00281 00282 const Tuple& dest = msg.getSource(); 00283 00284 // Calculate compartment ID for outbound message 00285 Data remoteSigcompId; 00286 setRemoteSigcompId(msg,remoteSigcompId); 00287 00288 // .bwc. msg is completely unverified. Handle with caution. 00289 result=makeSendData(dest, Data::Empty, Data::Empty, remoteSigcompId); 00290 static const Data retryAfterHeader("Retry-After: "); 00291 Data value(retryAfter); 00292 Helper::makeRawResponse(result->data, msg, 503, retryAfterHeader+value+"\r\n"); 00293 00294 return result; 00295 } 00296 00297 std::auto_ptr<SendData> 00298 Transport::make100(SipMessage& msg) 00299 { 00300 std::auto_ptr<SendData> result; 00301 if (msg.isResponse()) return result; 00302 00303 try 00304 { 00305 if(msg.method()==ACK) 00306 { 00307 return result; 00308 } 00309 } 00310 catch(BaseException&) 00311 { 00312 // .bwc. Parse failed on the start-line. Stop. 00313 return result; 00314 } 00315 00316 const Tuple& dest = msg.getSource(); 00317 00318 // Calculate compartment ID for outbound message 00319 Data remoteSigcompId; 00320 setRemoteSigcompId(msg,remoteSigcompId); 00321 00322 // .bwc. msg is completely unverified. Handle with caution. 00323 result=makeSendData(dest, Data::Empty, Data::Empty, remoteSigcompId); 00324 Helper::makeRawResponse(result->data, msg, 100); 00325 00326 return result; 00327 } 00328 00329 void 00330 Transport::setRemoteSigcompId(SipMessage& msg, Data& remoteSigcompId) 00331 { 00332 if (mCompression.isEnabled()) 00333 { 00334 try 00335 { 00336 const Via &topVia(msg.const_header(h_Vias).front()); 00337 00338 if(topVia.exists(p_comp) && topVia.param(p_comp) == "sigcomp") 00339 { 00340 if (topVia.exists(p_sigcompId)) 00341 { 00342 remoteSigcompId = topVia.param(p_sigcompId); 00343 } 00344 else 00345 { 00346 // XXX rohc-sigcomp-sip-03 says "sent-by", 00347 // but this should probably be "received" if present, 00348 // and "sent-by" otherwise. 00349 // XXX Also, the spec is ambiguous about whether 00350 // to include the port in this identifier. 00351 remoteSigcompId = topVia.sentHost(); 00352 } 00353 } 00354 } 00355 catch(BaseException&) 00356 { 00357 // ?bwc? Couldn't grab sigcomp compartment id. We don't even know if 00358 // the initial request was using sigcomp or not. 00359 // What should we do here? 00360 } 00361 } 00362 } 00363 00364 void 00365 Transport::stampReceived(SipMessage* message) 00366 { 00367 // set the received= and rport= parameters in the message if necessary !jf! 00368 if (message->isRequest() && message->exists(h_Vias) && !message->const_header(h_Vias).empty()) 00369 { 00370 const Tuple& tuple = message->getSource(); 00371 Data received = Tuple::inet_ntop(tuple); 00372 if(message->const_header(h_Vias).front().sentHost() != received) // only add if received address is different from sent-by in Via 00373 { 00374 message->header(h_Vias).front().param(p_received) = received; 00375 } 00376 //message->header(h_Vias).front().param(p_received) = Tuple::inet_ntop(tuple); 00377 if (message->const_header(h_Vias).front().exists(p_rport)) 00378 { 00379 message->header(h_Vias).front().param(p_rport).port() = tuple.getPort(); 00380 } 00381 } 00382 DebugLog (<< "incoming from: " << message->getSource()); 00383 StackLog (<< endl << endl << *message); 00384 } 00385 00386 00387 bool 00388 Transport::basicCheck(const SipMessage& msg) 00389 { 00390 resip::Data reason; 00391 if (msg.isExternal()) 00392 { 00393 try 00394 { 00395 if (!Helper::validateMessage(msg,&reason)) 00396 { 00397 InfoLog(<<"Message Failed basicCheck :" << msg.brief()); 00398 if (msg.isRequest() && msg.method()!=ACK ) 00399 { 00400 // this is VERY low-level b/c we don't have a transaction... 00401 // here we make a response to warn the offending party. 00402 makeFailedResponse(msg,400,reason.c_str()); 00403 } 00404 return false; 00405 } 00406 else if (mShuttingDown && msg.isRequest() && msg.method() != ACK) 00407 { 00408 InfoLog (<< "Server has been shutdown, reject message with 503"); 00409 // this is VERY low-level b/c we don't have a transaction... 00410 // here we make a response to warn the offending party. 00411 makeFailedResponse(msg, 503, "Server has been shutdown"); 00412 return false; 00413 } 00414 } 00415 catch (BaseException& e) 00416 { 00417 InfoLog (<< "Cannot make failure response to badly constructed message: " << e); 00418 return false; 00419 } 00420 } 00421 return true; 00422 } 00423 00424 void 00425 Transport::callSocketFunc(Socket sock) 00426 { 00427 if (mSocketFunc) 00428 { 00429 mSocketFunc(sock, transport(), __FILE__, __LINE__); 00430 } 00431 } 00432 00433 void 00434 Transport::pushRxMsgUp(TransactionMessage* msg) 00435 { 00436 mStateMachineFifo.add(msg); 00437 } 00438 00439 00440 bool 00441 Transport::operator==(const Transport& rhs) const 00442 { 00443 return ( ( mTuple.isV4() == rhs.isV4()) && 00444 ( port() == rhs.port()) && 00445 ( memcmp(&boundInterface(),&rhs.boundInterface(),mTuple.length()) == 0) ); 00446 } 00447 00448 EncodeStream& 00449 resip::operator<<(EncodeStream& strm, const resip::Transport& rhs) 00450 { 00451 strm << "Transport: " << rhs.mTuple; 00452 if (!rhs.mInterface.empty()) strm << " on " << rhs.mInterface; 00453 return strm; 00454 } 00455 00456 /* ==================================================================== 00457 * The Vovida Software License, Version 1.0 00458 * 00459 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00460 * 00461 * Redistribution and use in source and binary forms, with or without 00462 * modification, are permitted provided that the following conditions 00463 * are met: 00464 * 00465 * 1. Redistributions of source code must retain the above copyright 00466 * notice, this list of conditions and the following disclaimer. 00467 * 00468 * 2. Redistributions in binary form must reproduce the above copyright 00469 * notice, this list of conditions and the following disclaimer in 00470 * the documentation and/or other materials provided with the 00471 * distribution. 00472 * 00473 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00474 * and "Vovida Open Communication Application Library (VOCAL)" must 00475 * not be used to endorse or promote products derived from this 00476 * software without prior written permission. For written 00477 * permission, please contact vocal@vovida.org. 00478 * 00479 * 4. Products derived from this software may not be called "VOCAL", nor 00480 * may "VOCAL" appear in their name, without prior written 00481 * permission of Vovida Networks, Inc. 00482 * 00483 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00484 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00485 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00486 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00487 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00488 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00489 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00490 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00491 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00492 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00493 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00494 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00495 * DAMAGE. 00496 * 00497 * ==================================================================== 00498 * 00499 * This software consists of voluntary contributions made by Vovida 00500 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00501 * Inc. For more information on Vovida Networks, Inc., please see 00502 * <http://www.vovida.org/>. 00503 * 00504 * vi: set shiftwidth=3 expandtab: 00505 */
1.7.5.1