reSIProcate/repro  9694
Public Member Functions | Static Public Member Functions | Protected Member Functions | Private Types | Private Member Functions | Private Attributes | Static Private Attributes | Friends
repro::XmlRpcServerBase Class Reference

#include <XmlRpcServerBase.hxx>

Inheritance diagram for repro::XmlRpcServerBase:
Inheritance graph
[legend]
Collaboration diagram for repro::XmlRpcServerBase:
Collaboration graph
[legend]

List of all members.

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< ResponseInfomResponseFifo
resip::SelectInterruptor mSelectInterruptor

Static Private Attributes

static const unsigned int MaxConnections = 60

Friends

class XmlRpcConnection

Detailed Description

Definition at line 46 of file XmlRpcServerBase.hxx.


Member Typedef Documentation

typedef std::map<unsigned int, XmlRpcConnection*> repro::XmlRpcServerBase::ConnectionMap [private]

Definition at line 82 of file XmlRpcServerBase.hxx.


Constructor & Destructor Documentation

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; 
   }
}

Member Function Documentation

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]
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();
}

Friends And Related Function Documentation

friend class XmlRpcConnection [friend]

Definition at line 48 of file XmlRpcServerBase.hxx.


Member Data Documentation

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.

Definition at line 78 of file XmlRpcServerBase.hxx.

Definition at line 86 of file XmlRpcServerBase.hxx.

Definition at line 80 of file XmlRpcServerBase.hxx.

Definition at line 87 of file XmlRpcServerBase.hxx.

Definition at line 79 of file XmlRpcServerBase.hxx.


The documentation for this class was generated from the following files: