|
reSIProcate/repro
9694
|
00001 #ifdef HAVE_CONFIG_H 00002 #include "config.h" 00003 #endif 00004 00005 #include <cassert> 00006 00007 #include <rutil/Data.hxx> 00008 #include <rutil/Socket.hxx> 00009 #include <resip/stack/Symbols.hxx> 00010 #include <rutil/TransportType.hxx> 00011 #include <rutil/Logger.hxx> 00012 #include <resip/stack/Tuple.hxx> 00013 #include <rutil/DnsUtil.hxx> 00014 #include <rutil/ParseBuffer.hxx> 00015 #include <resip/stack/Transport.hxx> 00016 00017 #include "repro/XmlRpcServerBase.hxx" 00018 #include "repro/XmlRpcConnection.hxx" 00019 #include <rutil/WinLeakCheck.hxx> 00020 00021 using namespace repro; 00022 using namespace resip; 00023 using namespace std; 00024 00025 #define RESIPROCATE_SUBSYSTEM Subsystem::REPRO 00026 00027 00028 XmlRpcServerBase::XmlRpcServerBase(int port, IpVersion ipVer) : 00029 mTuple(Data::Empty,port,ipVer,TCP,Data::Empty), 00030 mSane(true) 00031 { 00032 #ifdef USE_IPV6 00033 mFd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_STREAM, 0); 00034 #else 00035 mFd = ::socket(PF_INET, SOCK_STREAM, 0); 00036 #endif 00037 00038 if (mFd == INVALID_SOCKET) 00039 { 00040 int e = getErrno(); 00041 logSocketError(e); 00042 ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Failed to create socket: " << strerror(e)); 00043 mSane = false; 00044 return; 00045 } 00046 00047 DebugLog (<< "XmlRpcServerBase::XmlRpcServerBase: Creating fd=" << (int)mFd 00048 << (ipVer == V4 ? " V4/" : " V6/") ); 00049 00050 int on = 1; 00051 #if !defined(WIN32) 00052 if (::setsockopt(mFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) 00053 #else 00054 if (::setsockopt(mFd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on))) 00055 #endif 00056 { 00057 int e = getErrno(); 00058 logSocketError(e); 00059 ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Couldn't set sockoptions SO_REUSEPORT | SO_REUSEADDR: " << strerror(e)); 00060 mSane = false; 00061 return; 00062 } 00063 00064 DebugLog(<< "XmlRpcServerBase::XmlRpcServerBase: Binding to " << Tuple::inet_ntop(mTuple)); 00065 00066 if (::bind( mFd, &mTuple.getMutableSockaddr(), mTuple.length()) == SOCKET_ERROR) 00067 { 00068 int e = getErrno(); 00069 logSocketError(e); 00070 if (e == EADDRINUSE) 00071 { 00072 ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: " << mTuple << " already in use "); 00073 } 00074 else 00075 { 00076 ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Could not bind to " << mTuple); 00077 } 00078 mSane = false; 00079 return; 00080 } 00081 00082 bool ok = makeSocketNonBlocking(mFd); 00083 if (!ok) 00084 { 00085 int e = getErrno(); 00086 logSocketError(e); 00087 ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Could not make HTTP socket non-blocking " << port); 00088 mSane = false; 00089 return; 00090 } 00091 00092 // do the listen, seting the maximum queue size for compeletly established 00093 // sockets -- on linux, tcp_max_syn_backlog should be used for the incomplete 00094 // queue size(see man listen) 00095 int e = listen(mFd,5); 00096 00097 if (e != 0) 00098 { 00099 int e = getErrno(); 00100 InfoLog(<< "XmlRpcServerBase::XmlRpcServerBase: Failed listen " << strerror(e)); 00101 mSane = false; 00102 return; 00103 } 00104 } 00105 00106 00107 XmlRpcServerBase::~XmlRpcServerBase() 00108 { 00109 #if defined(WIN32) 00110 closesocket(mFd); 00111 #else 00112 close(mFd); 00113 #endif 00114 mFd = 0; 00115 ConnectionMap::iterator it = mConnections.begin(); 00116 for(; it != mConnections.end(); it++) 00117 { 00118 delete it->second; 00119 } 00120 } 00121 00122 00123 void 00124 XmlRpcServerBase::buildFdSet(FdSet& fdset) 00125 { 00126 mSelectInterruptor.buildFdSet(fdset); 00127 00128 fdset.setRead(mFd); // listen socket for server 00129 00130 ConnectionMap::iterator it = mConnections.begin(); 00131 for(; it != mConnections.end(); it++) 00132 { 00133 it->second->buildFdSet(fdset); 00134 } 00135 } 00136 00137 00138 void 00139 XmlRpcServerBase::process(FdSet& fdset) 00140 { 00141 // Process Response fifo first 00142 while (mResponseFifo.messageAvailable()) 00143 { 00144 ResponseInfo* responseInfo = mResponseFifo.getNext(); 00145 if(responseInfo->getRequestId() == 0) 00146 { 00147 // This is an event and not a response - dispatch to appropriate connection or all connections 00148 if(responseInfo->getConnectionId() == 0) 00149 { 00150 ConnectionMap::iterator it = mConnections.begin(); 00151 for(; it != mConnections.end(); it++) 00152 { 00153 it->second->sendEvent(responseInfo->getResponseData()); 00154 } 00155 } 00156 else 00157 { 00158 ConnectionMap::iterator it = mConnections.find(responseInfo->getConnectionId()); 00159 if(it != mConnections.end()) 00160 { 00161 it->second->sendEvent(responseInfo->getResponseData()); 00162 } 00163 } 00164 } 00165 else 00166 { 00167 // This is a response to a request - dispatch to appropriate connection 00168 ConnectionMap::iterator it = mConnections.find(responseInfo->getConnectionId()); 00169 if(it != mConnections.end()) 00170 { 00171 it->second->sendResponse(responseInfo->getRequestId(), responseInfo->getResponseData(), responseInfo->getIsFinal()); 00172 } 00173 } 00174 delete responseInfo; 00175 } 00176 00177 mSelectInterruptor.process(fdset); 00178 00179 if (fdset.readyToRead(mFd)) 00180 { 00181 Tuple tuple(mTuple); 00182 struct sockaddr& peer = tuple.getMutableSockaddr(); 00183 socklen_t peerLen = tuple.length(); 00184 Socket sock = accept( mFd, &peer, &peerLen); 00185 if (sock == SOCKET_ERROR) 00186 { 00187 int e = getErrno(); 00188 switch (e) 00189 { 00190 case EWOULDBLOCK: 00191 return; 00192 default: 00193 logSocketError(e); 00194 ErrLog(<< "XmlRpcServerBase::process: Some error reading from socket: " << e); 00195 } 00196 return; 00197 } 00198 makeSocketNonBlocking(sock); 00199 00200 if(mConnections.size() == MaxConnections) 00201 { 00202 closeOldestConnection(); 00203 } 00204 00205 XmlRpcConnection* connection = new XmlRpcConnection(*this,sock); 00206 mConnections[connection->getConnectionId()] = connection; 00207 00208 DebugLog (<< "XmlRpcServerBase::process: Received TCP connection as connection=" << connection->getConnectionId() << " fd=" << (int)sock); 00209 } 00210 00211 // Call process on each connection 00212 ConnectionMap::iterator it = mConnections.begin(); 00213 for(; it != mConnections.end(); ) 00214 { 00215 bool ok = it->second->process(fdset); 00216 if (!ok) 00217 { 00218 delete it->second; 00219 mConnections.erase(it++); 00220 } 00221 else 00222 { 00223 it++; 00224 } 00225 } 00226 } 00227 00228 void 00229 XmlRpcServerBase::sendResponse(unsigned int connectionId, 00230 unsigned int requestId, 00231 const Data& responseData, 00232 bool isFinal) 00233 { 00234 mResponseFifo.add(new ResponseInfo(connectionId, requestId, responseData, isFinal)); 00235 mSelectInterruptor.interrupt(); 00236 } 00237 00238 void 00239 XmlRpcServerBase::sendEvent(unsigned int connectionId, 00240 const Data& eventData) 00241 { 00242 mResponseFifo.add(new ResponseInfo(connectionId, 0 /* requestId */, eventData, true /* isFinal */)); 00243 mSelectInterruptor.interrupt(); 00244 } 00245 00246 bool 00247 XmlRpcServerBase::isSane() 00248 { 00249 return mSane; 00250 } 00251 00252 void 00253 XmlRpcServerBase::closeOldestConnection() 00254 { 00255 if(mConnections.empty()) return; 00256 00257 // Oldest Connection is the one with the lowest Id 00258 ConnectionMap::iterator lowestConnectionIdIt = mConnections.end(); 00259 ConnectionMap::iterator it = mConnections.begin(); 00260 for(; it != mConnections.end(); it++) 00261 { 00262 if(it->second->getConnectionId() < lowestConnectionIdIt->second->getConnectionId()) 00263 { 00264 lowestConnectionIdIt = it; 00265 } 00266 } 00267 delete lowestConnectionIdIt->second; 00268 mConnections.erase(lowestConnectionIdIt); 00269 } 00270 00271 void 00272 XmlRpcServerBase::logSocketError(int e) 00273 { 00274 switch (e) 00275 { 00276 case EAGAIN: 00277 InfoLog (<< "No data ready to read" << strerror(e)); 00278 break; 00279 case EINTR: 00280 InfoLog (<< "The call was interrupted by a signal before any data was read : " << strerror(e)); 00281 break; 00282 case EIO: 00283 InfoLog (<< "I/O error : " << strerror(e)); 00284 break; 00285 case EBADF: 00286 InfoLog (<< "fd is not a valid file descriptor or is not open for reading : " << strerror(e)); 00287 break; 00288 case EINVAL: 00289 InfoLog (<< "fd is attached to an object which is unsuitable for reading : " << strerror(e)); 00290 break; 00291 case EFAULT: 00292 InfoLog (<< "buf is outside your accessible address space : " << strerror(e)); 00293 break; 00294 00295 #if defined(WIN32) 00296 case WSAENETDOWN: 00297 InfoLog (<<" The network subsystem has failed. "); 00298 break; 00299 case WSAEFAULT: 00300 InfoLog (<<" The buf or from parameters are not part of the user address space, " 00301 "or the fromlen parameter is too small to accommodate the peer address. "); 00302 break; 00303 case WSAEINTR: 00304 InfoLog (<<" The (blocking) call was canceled through WSACancelBlockingCall. "); 00305 break; 00306 case WSAEINPROGRESS: 00307 InfoLog (<<" A blocking Windows Sockets 1.1 call is in progress, or the " 00308 "service provider is still processing a callback function. "); 00309 break; 00310 case WSAEINVAL: 00311 InfoLog (<<" The socket has not been bound with bind, or an unknown flag was specified, " 00312 "or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, " 00313 "or (for byte stream-style sockets only) len was zero or negative. "); 00314 break; 00315 case WSAEISCONN : 00316 InfoLog (<<"The socket is connected. This function is not permitted with a connected socket, " 00317 "whether the socket is connection-oriented or connectionless. "); 00318 break; 00319 case WSAENETRESET: 00320 InfoLog (<<" The connection has been broken due to the keep-alive activity " 00321 "detecting a failure while the operation was in progress. "); 00322 break; 00323 case WSAENOTSOCK : 00324 InfoLog (<<"The descriptor is not a socket. "); 00325 break; 00326 case WSAEOPNOTSUPP: 00327 InfoLog (<<" MSG_OOB was specified, but the socket is not stream-style such as type " 00328 "SOCK_STREAM, OOB data is not supported in the communication domain associated with this socket, " 00329 "or the socket is unidirectional and supports only send operations. "); 00330 break; 00331 case WSAESHUTDOWN: 00332 InfoLog (<<"The socket has been shut down; it is not possible to recvfrom on a socket after " 00333 "shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH. "); 00334 break; 00335 case WSAEMSGSIZE: 00336 InfoLog (<<" The message was too large to fit into the specified buffer and was truncated. "); 00337 break; 00338 case WSAETIMEDOUT: 00339 InfoLog (<<" The connection has been dropped, because of a network failure or because the " 00340 "system on the other end went down without notice. "); 00341 break; 00342 case WSAECONNRESET : 00343 InfoLog (<<"Connection reset "); 00344 break; 00345 00346 case WSAEWOULDBLOCK: 00347 DebugLog (<<"Would Block "); 00348 break; 00349 00350 case WSAEHOSTUNREACH: 00351 InfoLog (<<"A socket operation was attempted to an unreachable host "); 00352 break; 00353 case WSANOTINITIALISED: 00354 InfoLog (<<"Either the application has not called WSAStartup or WSAStartup failed. " 00355 "The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks)," 00356 "or WSACleanup has been called too many times. "); 00357 break; 00358 case WSAEACCES: 00359 InfoLog (<<"An attempt was made to access a socket in a way forbidden by its access permissions "); 00360 break; 00361 case WSAENOBUFS: 00362 InfoLog (<<"An operation on a socket could not be performed because the system lacked sufficient " 00363 "buffer space or because a queue was full"); 00364 break; 00365 case WSAENOTCONN: 00366 InfoLog (<<"A request to send or receive data was disallowed because the socket is not connected " 00367 "and (when sending on a datagram socket using sendto) no address was supplied"); 00368 break; 00369 case WSAECONNABORTED: 00370 InfoLog (<<"An established connection was aborted by the software in your host computer, possibly " 00371 "due to a data transmission time-out or protocol error"); 00372 break; 00373 case WSAEADDRNOTAVAIL: 00374 InfoLog (<<"The requested address is not valid in its context. This normally results from an attempt to " 00375 "bind to an address that is not valid for the local computer"); 00376 break; 00377 case WSAEAFNOSUPPORT: 00378 InfoLog (<<"An address incompatible with the requested protocol was used"); 00379 break; 00380 case WSAEDESTADDRREQ: 00381 InfoLog (<<"A required address was omitted from an operation on a socket"); 00382 break; 00383 case WSAENETUNREACH: 00384 InfoLog (<<"A socket operation was attempted to an unreachable network"); 00385 break; 00386 00387 #endif 00388 00389 default: 00390 InfoLog (<< "Some other error (" << e << "): " << strerror(e)); 00391 break; 00392 } 00393 } 00394 00395 00396 /* ==================================================================== 00397 * The Vovida Software License, Version 1.0 00398 * 00399 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00400 * Copyright (c) 2010 SIP Spectrum, Inc. All rights reserved. 00401 * 00402 * Redistribution and use in source and binary forms, with or without 00403 * modification, are permitted provided that the following conditions 00404 * are met: 00405 * 00406 * 1. Redistributions of source code must retain the above copyright 00407 * notice, this list of conditions and the following disclaimer. 00408 * 00409 * 2. Redistributions in binary form must reproduce the above copyright 00410 * notice, this list of conditions and the following disclaimer in 00411 * the documentation and/or other materials provided with the 00412 * distribution. 00413 * 00414 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00415 * and "Vovida Open Communication Application Library (VOCAL)" must 00416 * not be used to endorse or promote products derived from this 00417 * software without prior written permission. For written 00418 * permission, please contact vocal@vovida.org. 00419 * 00420 * 4. Products derived from this software may not be called "VOCAL", nor 00421 * may "VOCAL" appear in their name, without prior written 00422 * permission of Vovida Networks, Inc. 00423 * 00424 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00425 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00426 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00427 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00428 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00429 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00430 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00431 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00432 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00433 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00434 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00435 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00436 * DAMAGE. 00437 * 00438 * ==================================================================== 00439 * 00440 * This software consists of voluntary contributions made by Vovida 00441 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00442 * Inc. For more information on Vovida Networks, Inc., please see 00443 * <http://www.vovida.org/>. 00444 * 00445 */ 00446
1.7.5.1