Index Source Files Annotated Class List Alphabetical Class List Class Hierarchy Graphical Class Hierarchy

# SocketServer.cpp

Go to the documentation of this file.

    00001 /****************************************************************************
    00002 ** Copyright (c) quickfixengine.org  All rights reserved.
    00003 **
    00004 ** This file is part of the QuickFIX FIX Engine
    00005 **
    00006 ** This file may be distributed under the terms of the quickfixengine.org
    00007 ** license as defined by quickfixengine.org and appearing in the file
    00008 ** LICENSE included in the packaging of this file.
    00009 **
    00010 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
    00011 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
    00012 **
    00013 ** See http://www.quickfixengine.org/LICENSE for licensing information.
    00014 **
    00015 ** Contact ask@quickfixengine.org if any conditions of this licensing are
    00016 ** not clear to you.
    00017 **
    00018 ****************************************************************************/
    00019
    00020 #ifdef _MSC_VER
    00021 #include "stdafx.h"
    00022 #else
    00023 #include "config.h"
    00024 #endif
    00025 #include "CallStack.h"
    00026
    00027 #include "SocketServer.h"
    00028 #include "Utility.h"
    00029 #include "Exceptions.h"
    00030 #ifndef _MSC_VER
    00031 #include <unistd.h>
    00032 #include <sys/ioctl.h>
    00033 #include <sys/types.h>
    00034 #include <sys/stat.h>
    00035 #endif
    00036 #include <exception>
    00037
    00038 namespace FIX
    00039 {
    00041 class ServerWrapper : public SocketMonitor::Strategy
    00042 {
    00043 public:
    00044   ServerWrapper( std::set<int> sockets, SocketServer& server,
    00045                  SocketServer::Strategy& strategy )
    00046 : m_sockets( sockets ), m_server( server ), m_strategy( strategy ) {}
    00047
    00048 private:
    00049   void onConnect( SocketMonitor&, int socket )
    00050   { QF_STACK_PUSH(ServerWrapper::onConnect)
    00051     QF_STACK_POP
    00052   }
    00053
    00054   void onEvent( SocketMonitor& monitor, int socket )
    00055   { QF_STACK_PUSH(ServerWrapper::onEvent)
    00056
    00057     if( m_sockets.find(socket) != m_sockets.end() )
    00058     {
    00059       m_strategy.onConnect( m_server, socket, m_server.accept(socket) );
    00060     }
    00061     else
    00062     {
    00063       if( !m_strategy.onData( m_server, socket ) )
    00064         onError( monitor, socket );
    00065     }
    00066
    00067     QF_STACK_POP
    00068   }
    00069
    00070   void onWrite( SocketMonitor&, int socket )
    00071   { QF_STACK_PUSH(ServerWrapper::onWrite)
    00072
    00073     m_strategy.onWrite( m_server, socket );
    00074
    00075     QF_STACK_POP
    00076   }
    00077
    00078   void onError( SocketMonitor& monitor, int socket )
    00079   { QF_STACK_PUSH(ServerWrapper::onError)
    00080
    00081     m_strategy.onDisconnect( m_server, socket );
    00082     monitor.drop( socket );
    00083
    00084     QF_STACK_POP
    00085   }
    00086
    00087   void onError( SocketMonitor& )
    00088   { QF_STACK_PUSH(ServerWrapper::onError)
    00089     m_strategy.onError( m_server );
    00090     QF_STACK_POP
    00091   }
    00092
    00093   void onTimeout( SocketMonitor& )
    00094   { QF_STACK_PUSH(ServerWrapper::onTimeout)
    00095     m_strategy.onTimeout( m_server );
    00096     QF_STACK_POP
    00097   };
    00098
    00099   typedef std::set<int>
    00100     Sockets;
    00101
    00102   Sockets m_sockets;
    00103   SocketServer& m_server;
    00104   SocketServer::Strategy& m_strategy;
    00105 };
    00106
    00107 SocketServer::SocketServer( int timeout )
    00108 : m_monitor( timeout ) {}
    00109
    00110 int SocketServer::add( int port, bool reuse, bool noDelay,
    00111                        int sendBufSize, int rcvBufSize )
    00112   throw( SocketException& )
    00113 {
    00114   if( m_portToInfo.find(port) != m_portToInfo.end() )
    00115     return m_portToInfo[port].m_socket;
    00116
    00117   int socket = socket_createAcceptor( port, reuse );
    00118   if( socket < 0 )
    00119     throw SocketException();
    00120   if( noDelay )
    00121     socket_setsockopt( socket, TCP_NODELAY );
    00122   if( sendBufSize )
    00123     socket_setsockopt( socket, SO_SNDBUF, sendBufSize );
    00124   if( rcvBufSize )
    00125     socket_setsockopt( socket, SO_RCVBUF, rcvBufSize );
    00126   m_monitor.addRead( socket );
    00127
    00128   SocketInfo info( socket, port, noDelay, sendBufSize, rcvBufSize );
    00129   m_socketToInfo[socket] = info;
    00130   m_portToInfo[port] = info;
    00131   return socket;
    00132 }
    00133
    00134 int SocketServer::accept( int socket )
    00135 { QF_STACK_PUSH(SocketServer::accept)
    00136
    00137   SocketInfo info = m_socketToInfo[socket];
    00138
    00139   int result = socket_accept( socket );
    00140   if( info.m_noDelay )
    00141     socket_setsockopt( result, TCP_NODELAY );
    00142   if( info.m_sendBufSize )
    00143     socket_setsockopt( result, SO_SNDBUF, info.m_sendBufSize );
    00144   if( info.m_rcvBufSize )
    00145     socket_setsockopt( result, SO_RCVBUF, info.m_rcvBufSize );
    00146   if ( result >= 0 )
    00147     m_monitor.addConnect( result );
    00148   return result;
    00149
    00150   QF_STACK_POP
    00151 }
    00152
    00153 void SocketServer::close()
    00154 { QF_STACK_PUSH(SocketServer::close)
    00155
    00156   SocketToInfo::iterator i = m_socketToInfo.begin();
    00157   for( ; i != m_socketToInfo.end(); ++i )
    00158   {
    00159     int s = i->first;
    00160     socket_close( s );
    00161     socket_invalidate( s );
    00162   }
    00163
    00164   QF_STACK_POP
    00165 }
    00166
    00167 bool SocketServer::block( Strategy& strategy, bool poll, double timeout )
    00168 { QF_STACK_PUSH(SocketServer::block)
    00169
    00170   std::set<int> sockets;
    00171   SocketToInfo::iterator i = m_socketToInfo.begin();
    00172   for( ; i != m_socketToInfo.end(); ++i )
    00173   {
    00174     if( !socket_isValid(i->first) )
    00175       return false;
    00176     sockets.insert( i->first );
    00177   }
    00178
    00179   ServerWrapper wrapper( sockets, *this, strategy );
    00180   m_monitor.block( wrapper, poll, timeout );
    00181   return true;
    00182
    00183   QF_STACK_POP
    00184 }
    00185
    00186 int SocketServer::socketToPort( int socket )
    00187 {
    00188   SocketToInfo::iterator find = m_socketToInfo.find( socket );
    00189   if( find == m_socketToInfo.end() ) return 0;
    00190   return find->second.m_port;
    00191 }
    00192
    00193 int SocketServer::portToSocket( int port )
    00194 {
    00195   SocketToInfo::iterator find = m_portToInfo.find( port );
    00196   if( find == m_portToInfo.end() ) return 0;
    00197   return find->second.m_socket;
    00198 }
    00199 }