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 }

Generated on Mon Apr 5 20:59:51 2010 for QuickFIX by doxygen 1.6.1 written by Dimitri van Heesch, © 1997-2001