|
reSIProcate/repro
9694
|
#include <XmlRpcServerBase.hxx>


Public Member Functions | |
| XmlRpcServerBase (int port, resip::IpVersion version) | |
| virtual | ~XmlRpcServerBase () |
| void | buildFdSet (resip::FdSet &fdset) |
| void | process (resip::FdSet &fdset) |
| bool | isSane () |
| void | sendResponse (unsigned int connectionId, unsigned int requestId, const resip::Data &responseData, bool isFinal=true) |
| void | sendEvent (unsigned int connectionId, const resip::Data &eventData) |
Static Public Member Functions | |
| static void | logSocketError (int e) |
Protected Member Functions | |
| virtual void | handleRequest (unsigned int connectionId, unsigned int requestId, const resip::Data &request)=0 |
Private Types | |
| typedef std::map< unsigned int, XmlRpcConnection * > | ConnectionMap |
Private Member Functions | |
| void | closeOldestConnection () |
Private Attributes | |
| resip::Socket | mFd |
| resip::Tuple | mTuple |
| bool | mSane |
| ConnectionMap | mConnections |
| resip::Fifo< ResponseInfo > | mResponseFifo |
| resip::SelectInterruptor | mSelectInterruptor |
Static Private Attributes | |
| static const unsigned int | MaxConnections = 60 |
Friends | |
| class | XmlRpcConnection |
Definition at line 46 of file XmlRpcServerBase.hxx.
typedef std::map<unsigned int, XmlRpcConnection*> repro::XmlRpcServerBase::ConnectionMap [private] |
Definition at line 82 of file XmlRpcServerBase.hxx.
| XmlRpcServerBase::XmlRpcServerBase | ( | int | port, |
| resip::IpVersion | version | ||
| ) |
Definition at line 28 of file XmlRpcServerBase.cxx.
: mTuple(Data::Empty,port,ipVer,TCP,Data::Empty), mSane(true) { #ifdef USE_IPV6 mFd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_STREAM, 0); #else mFd = ::socket(PF_INET, SOCK_STREAM, 0); #endif if (mFd == INVALID_SOCKET) { int e = getErrno(); logSocketError(e); ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Failed to create socket: " << strerror(e)); mSane = false; return; } DebugLog (<< "XmlRpcServerBase::XmlRpcServerBase: Creating fd=" << (int)mFd << (ipVer == V4 ? " V4/" : " V6/") ); int on = 1; #if !defined(WIN32) if (::setsockopt(mFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) #else if (::setsockopt(mFd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on))) #endif { int e = getErrno(); logSocketError(e); ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Couldn't set sockoptions SO_REUSEPORT | SO_REUSEADDR: " << strerror(e)); mSane = false; return; } DebugLog(<< "XmlRpcServerBase::XmlRpcServerBase: Binding to " << Tuple::inet_ntop(mTuple)); if (::bind( mFd, &mTuple.getMutableSockaddr(), mTuple.length()) == SOCKET_ERROR) { int e = getErrno(); logSocketError(e); if (e == EADDRINUSE) { ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: " << mTuple << " already in use "); } else { ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Could not bind to " << mTuple); } mSane = false; return; } bool ok = makeSocketNonBlocking(mFd); if (!ok) { int e = getErrno(); logSocketError(e); ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Could not make HTTP socket non-blocking " << port); mSane = false; return; } // do the listen, seting the maximum queue size for compeletly established // sockets -- on linux, tcp_max_syn_backlog should be used for the incomplete // queue size(see man listen) int e = listen(mFd,5); if (e != 0) { int e = getErrno(); InfoLog(<< "XmlRpcServerBase::XmlRpcServerBase: Failed listen " << strerror(e)); mSane = false; return; } }
| XmlRpcServerBase::~XmlRpcServerBase | ( | ) | [virtual] |
Definition at line 107 of file XmlRpcServerBase.cxx.
{
#if defined(WIN32)
closesocket(mFd);
#else
close(mFd);
#endif
mFd = 0;
ConnectionMap::iterator it = mConnections.begin();
for(; it != mConnections.end(); it++)
{
delete it->second;
}
}
| void XmlRpcServerBase::buildFdSet | ( | resip::FdSet & | fdset | ) |
Definition at line 124 of file XmlRpcServerBase.cxx.
{
mSelectInterruptor.buildFdSet(fdset);
fdset.setRead(mFd); // listen socket for server
ConnectionMap::iterator it = mConnections.begin();
for(; it != mConnections.end(); it++)
{
it->second->buildFdSet(fdset);
}
}
| void XmlRpcServerBase::closeOldestConnection | ( | ) | [private] |
Definition at line 253 of file XmlRpcServerBase.cxx.
{
if(mConnections.empty()) return;
// Oldest Connection is the one with the lowest Id
ConnectionMap::iterator lowestConnectionIdIt = mConnections.end();
ConnectionMap::iterator it = mConnections.begin();
for(; it != mConnections.end(); it++)
{
if(it->second->getConnectionId() < lowestConnectionIdIt->second->getConnectionId())
{
lowestConnectionIdIt = it;
}
}
delete lowestConnectionIdIt->second;
mConnections.erase(lowestConnectionIdIt);
}
| virtual void repro::XmlRpcServerBase::handleRequest | ( | unsigned int | connectionId, |
| unsigned int | requestId, | ||
| const resip::Data & | request | ||
| ) | [protected, pure virtual] |
Implemented in repro::CommandServer, and repro::RegSyncServer.
| bool XmlRpcServerBase::isSane | ( | ) |
Definition at line 247 of file XmlRpcServerBase.cxx.
{
return mSane;
}
| void XmlRpcServerBase::logSocketError | ( | int | e | ) | [static] |
Definition at line 272 of file XmlRpcServerBase.cxx.
{
switch (e)
{
case EAGAIN:
InfoLog (<< "No data ready to read" << strerror(e));
break;
case EINTR:
InfoLog (<< "The call was interrupted by a signal before any data was read : " << strerror(e));
break;
case EIO:
InfoLog (<< "I/O error : " << strerror(e));
break;
case EBADF:
InfoLog (<< "fd is not a valid file descriptor or is not open for reading : " << strerror(e));
break;
case EINVAL:
InfoLog (<< "fd is attached to an object which is unsuitable for reading : " << strerror(e));
break;
case EFAULT:
InfoLog (<< "buf is outside your accessible address space : " << strerror(e));
break;
#if defined(WIN32)
case WSAENETDOWN:
InfoLog (<<" The network subsystem has failed. ");
break;
case WSAEFAULT:
InfoLog (<<" The buf or from parameters are not part of the user address space, "
"or the fromlen parameter is too small to accommodate the peer address. ");
break;
case WSAEINTR:
InfoLog (<<" The (blocking) call was canceled through WSACancelBlockingCall. ");
break;
case WSAEINPROGRESS:
InfoLog (<<" A blocking Windows Sockets 1.1 call is in progress, or the "
"service provider is still processing a callback function. ");
break;
case WSAEINVAL:
InfoLog (<<" The socket has not been bound with bind, or an unknown flag was specified, "
"or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, "
"or (for byte stream-style sockets only) len was zero or negative. ");
break;
case WSAEISCONN :
InfoLog (<<"The socket is connected. This function is not permitted with a connected socket, "
"whether the socket is connection-oriented or connectionless. ");
break;
case WSAENETRESET:
InfoLog (<<" The connection has been broken due to the keep-alive activity "
"detecting a failure while the operation was in progress. ");
break;
case WSAENOTSOCK :
InfoLog (<<"The descriptor is not a socket. ");
break;
case WSAEOPNOTSUPP:
InfoLog (<<" MSG_OOB was specified, but the socket is not stream-style such as type "
"SOCK_STREAM, OOB data is not supported in the communication domain associated with this socket, "
"or the socket is unidirectional and supports only send operations. ");
break;
case WSAESHUTDOWN:
InfoLog (<<"The socket has been shut down; it is not possible to recvfrom on a socket after "
"shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH. ");
break;
case WSAEMSGSIZE:
InfoLog (<<" The message was too large to fit into the specified buffer and was truncated. ");
break;
case WSAETIMEDOUT:
InfoLog (<<" The connection has been dropped, because of a network failure or because the "
"system on the other end went down without notice. ");
break;
case WSAECONNRESET :
InfoLog (<<"Connection reset ");
break;
case WSAEWOULDBLOCK:
DebugLog (<<"Would Block ");
break;
case WSAEHOSTUNREACH:
InfoLog (<<"A socket operation was attempted to an unreachable host ");
break;
case WSANOTINITIALISED:
InfoLog (<<"Either the application has not called WSAStartup or WSAStartup failed. "
"The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks),"
"or WSACleanup has been called too many times. ");
break;
case WSAEACCES:
InfoLog (<<"An attempt was made to access a socket in a way forbidden by its access permissions ");
break;
case WSAENOBUFS:
InfoLog (<<"An operation on a socket could not be performed because the system lacked sufficient "
"buffer space or because a queue was full");
break;
case WSAENOTCONN:
InfoLog (<<"A request to send or receive data was disallowed because the socket is not connected "
"and (when sending on a datagram socket using sendto) no address was supplied");
break;
case WSAECONNABORTED:
InfoLog (<<"An established connection was aborted by the software in your host computer, possibly "
"due to a data transmission time-out or protocol error");
break;
case WSAEADDRNOTAVAIL:
InfoLog (<<"The requested address is not valid in its context. This normally results from an attempt to "
"bind to an address that is not valid for the local computer");
break;
case WSAEAFNOSUPPORT:
InfoLog (<<"An address incompatible with the requested protocol was used");
break;
case WSAEDESTADDRREQ:
InfoLog (<<"A required address was omitted from an operation on a socket");
break;
case WSAENETUNREACH:
InfoLog (<<"A socket operation was attempted to an unreachable network");
break;
#endif
default:
InfoLog (<< "Some other error (" << e << "): " << strerror(e));
break;
}
}
| void XmlRpcServerBase::process | ( | resip::FdSet & | fdset | ) |
Definition at line 139 of file XmlRpcServerBase.cxx.
{
// Process Response fifo first
while (mResponseFifo.messageAvailable())
{
ResponseInfo* responseInfo = mResponseFifo.getNext();
if(responseInfo->getRequestId() == 0)
{
// This is an event and not a response - dispatch to appropriate connection or all connections
if(responseInfo->getConnectionId() == 0)
{
ConnectionMap::iterator it = mConnections.begin();
for(; it != mConnections.end(); it++)
{
it->second->sendEvent(responseInfo->getResponseData());
}
}
else
{
ConnectionMap::iterator it = mConnections.find(responseInfo->getConnectionId());
if(it != mConnections.end())
{
it->second->sendEvent(responseInfo->getResponseData());
}
}
}
else
{
// This is a response to a request - dispatch to appropriate connection
ConnectionMap::iterator it = mConnections.find(responseInfo->getConnectionId());
if(it != mConnections.end())
{
it->second->sendResponse(responseInfo->getRequestId(), responseInfo->getResponseData(), responseInfo->getIsFinal());
}
}
delete responseInfo;
}
mSelectInterruptor.process(fdset);
if (fdset.readyToRead(mFd))
{
Tuple tuple(mTuple);
struct sockaddr& peer = tuple.getMutableSockaddr();
socklen_t peerLen = tuple.length();
Socket sock = accept( mFd, &peer, &peerLen);
if (sock == SOCKET_ERROR)
{
int e = getErrno();
switch (e)
{
case EWOULDBLOCK:
return;
default:
logSocketError(e);
ErrLog(<< "XmlRpcServerBase::process: Some error reading from socket: " << e);
}
return;
}
makeSocketNonBlocking(sock);
if(mConnections.size() == MaxConnections)
{
closeOldestConnection();
}
XmlRpcConnection* connection = new XmlRpcConnection(*this,sock);
mConnections[connection->getConnectionId()] = connection;
DebugLog (<< "XmlRpcServerBase::process: Received TCP connection as connection=" << connection->getConnectionId() << " fd=" << (int)sock);
}
// Call process on each connection
ConnectionMap::iterator it = mConnections.begin();
for(; it != mConnections.end(); )
{
bool ok = it->second->process(fdset);
if (!ok)
{
delete it->second;
mConnections.erase(it++);
}
else
{
it++;
}
}
}
| void XmlRpcServerBase::sendEvent | ( | unsigned int | connectionId, |
| const resip::Data & | eventData | ||
| ) |
Definition at line 239 of file XmlRpcServerBase.cxx.
{
mResponseFifo.add(new ResponseInfo(connectionId, 0 /* requestId */, eventData, true /* isFinal */));
mSelectInterruptor.interrupt();
}
| void XmlRpcServerBase::sendResponse | ( | unsigned int | connectionId, |
| unsigned int | requestId, | ||
| const resip::Data & | responseData, | ||
| bool | isFinal = true |
||
| ) |
Definition at line 229 of file XmlRpcServerBase.cxx.
{
mResponseFifo.add(new ResponseInfo(connectionId, requestId, responseData, isFinal));
mSelectInterruptor.interrupt();
}
friend class XmlRpcConnection [friend] |
Definition at line 48 of file XmlRpcServerBase.hxx.
const unsigned int repro::XmlRpcServerBase::MaxConnections = 60 [static, private] |
Definition at line 76 of file XmlRpcServerBase.hxx.
Definition at line 83 of file XmlRpcServerBase.hxx.
resip::Socket repro::XmlRpcServerBase::mFd [private] |
Definition at line 78 of file XmlRpcServerBase.hxx.
Definition at line 86 of file XmlRpcServerBase.hxx.
bool repro::XmlRpcServerBase::mSane [private] |
Definition at line 80 of file XmlRpcServerBase.hxx.
Definition at line 87 of file XmlRpcServerBase.hxx.
resip::Tuple repro::XmlRpcServerBase::mTuple [private] |
Definition at line 79 of file XmlRpcServerBase.hxx.
1.7.5.1