lib/client/client.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "client.h"
00019
00020 #include "commandQueue.h"
00021 #include "commands.h"
00022 #include "global.h"
00023 #include "init.h"
00024 #include "nodeFactory.h"
00025 #include "packets.h"
00026 #include "server.h"
00027
00028 #include <eq/net/command.h>
00029 #include <eq/net/connection.h>
00030 #include <eq/base/dso.h>
00031
00032 namespace eq
00033 {
00035 typedef net::CommandFunc<Client> ClientFunc;
00036
00037 static net::ConnectionPtr _startLocalServer();
00038 static void _joinLocalServer();
00039
00040 typedef net::ConnectionPtr (*eqsStartLocalServer_t)( const std::string& file );
00041 typedef void (*eqsJoinLocalServer_t)();
00044 Client::Client()
00045 : _nodeThreadQueue( 0 )
00046 , _running( false )
00047 {
00048 EQINFO << "New client at " << (void*)this << std::endl;
00049 }
00050
00051 Client::~Client()
00052 {
00053 EQINFO << "Delete client at " << (void*)this << std::endl;
00054 close();
00055 }
00056
00057 bool Client::listen()
00058 {
00059 EQASSERT( !_nodeThreadQueue );
00060 _nodeThreadQueue = new CommandQueue;
00061
00062 registerCommand( CMD_CLIENT_EXIT, ClientFunc( this, &Client::_cmdExit ),
00063 _nodeThreadQueue );
00064
00065 return net::Node::listen();
00066 }
00067
00068 bool Client::close()
00069 {
00070 if( !net::Node::close( ))
00071 return false;
00072
00073 delete _nodeThreadQueue;
00074 _nodeThreadQueue = 0;
00075 return true;
00076 }
00077
00078 bool Client::connectServer( ServerPtr server )
00079 {
00080 if( server->isConnected( ))
00081 return true;
00082 bool explicitAddress = true;
00083
00084 if( server->getConnectionDescriptions().empty( ))
00085 {
00086 net::ConnectionDescriptionPtr connDesc =
00087 new net::ConnectionDescription;
00088 connDesc->port = EQ_DEFAULT_PORT;
00089
00090 const std::string globalServer = Global::getServer();
00091 const char* envServer = getenv( "EQ_SERVER" );
00092 std::string address = !globalServer.empty() ? globalServer :
00093 envServer ? envServer : "localhost";
00094
00095 if( !connDesc->fromString( address ))
00096 EQWARN << "Can't parse server address " << address << std::endl;
00097 EQASSERT( address.empty( ));
00098 EQINFO << "Connecting to " << connDesc->toString() << std::endl;
00099
00100 server->addConnectionDescription( connDesc );
00101
00102 if( globalServer.empty() && !envServer )
00103 explicitAddress = false;
00104 }
00105
00106 if( connect( net::NodePtr( server.get( )) ))
00107 {
00108 server->setClient( this );
00109 return true;
00110 }
00111
00112 if( explicitAddress )
00113 return false;
00114
00115
00116 net::ConnectionPtr connection = _startLocalServer();
00117 if( !connection )
00118 return false;
00119
00120 if( !_connect( server.get(), connection ))
00121
00122 return false;
00123
00124 server->setClient( this );
00125 server->_localServer = true;
00126 return true;
00127 }
00128
00130 namespace
00131 {
00132 base::DSO _libeqserver;
00133 }
00134
00135 net::ConnectionPtr _startLocalServer()
00136 {
00137 if( !_libeqserver.open(
00138 #ifdef WIN32_VC
00139 "EqualizerServer.dll"
00140 #elif defined (WIN32)
00141 "libeqserver.dll"
00142 #elif defined (Darwin)
00143 "libeqserver.dylib"
00144 #else
00145 "libeqserver.so"
00146 #endif
00147 ))
00148 {
00149 EQWARN << "Can't open Equalizer server library" << std::endl;
00150 return 0;
00151 }
00152
00153 eqsStartLocalServer_t eqsStartLocalServer = (eqsStartLocalServer_t)
00154 _libeqserver.getFunctionPointer( "eqsStartLocalServer" );
00155
00156 if( !eqsStartLocalServer )
00157 {
00158 EQWARN << "Can't find server entry function eqsStartLocalServer"
00159 << std::endl;
00160 return 0;
00161 }
00162
00163 return eqsStartLocalServer( Global::getConfigFile( ));
00164 }
00165
00166 static void _joinLocalServer()
00167 {
00168 eqsJoinLocalServer_t eqsJoinLocalServer = (eqsJoinLocalServer_t)
00169 _libeqserver.getFunctionPointer( "eqsJoinLocalServer" );
00170
00171 if( !eqsJoinLocalServer )
00172 {
00173 EQWARN << "Can't find server entry function eqsJoinLocalServer"
00174 << std::endl;
00175 return;
00176 }
00177
00178 eqsJoinLocalServer();
00179 _libeqserver.close();
00180 }
00183 bool Client::disconnectServer( ServerPtr server )
00184 {
00185 if( !server->isConnected( ))
00186 {
00187 EQWARN << "Trying to disconnect unconnected server" << std::endl;
00188 return false;
00189 }
00190
00191
00192 if( server->_localServer )
00193 {
00194 server->shutdown();
00195 _joinLocalServer();
00196 }
00197
00198 server->setClient( 0 );
00199 server->_localServer = false;
00200
00201 const int success = net::Node::close( server.get( ));
00202 if( !success )
00203 EQWARN << "Server disconnect failed" << std::endl;
00204
00205
00206 _nodeThreadQueue->flush();
00207 return success;
00208 }
00209
00210
00211 net::NodePtr Client::createNode( const uint32_t type )
00212 {
00213 switch( type )
00214 {
00215 case TYPE_EQ_SERVER:
00216 {
00217 Server* server = new Server;
00218 server->setClient( this );
00219 return server;
00220 }
00221
00222 default:
00223 return net::Node::createNode( type );
00224 }
00225 }
00226
00227 bool Client::clientLoop()
00228 {
00229 EQINFO << "Entered client loop" << std::endl;
00230
00231 _running = true;
00232 while( _running )
00233 processCommand();
00234
00235
00236 _nodeThreadQueue->flush();
00237 EQASSERT( !hasSessions( ));
00238
00239 return true;
00240 }
00241
00242 bool Client::exitClient()
00243 {
00244 return (net::Node::exitClient() & eq::exit( ));
00245 }
00246
00247 bool Client::hasCommands()
00248 {
00249 return !_nodeThreadQueue->isEmpty();
00250 }
00251
00252 void Client::processCommand()
00253 {
00254 net::Command* command = _nodeThreadQueue->pop();
00255 if( !command )
00256 return;
00257
00258 switch( invokeCommand( *command ))
00259 {
00260 case net::COMMAND_HANDLED:
00261 case net::COMMAND_DISCARD:
00262 break;
00263
00264 case net::COMMAND_ERROR:
00265 EQABORT( "Error handling command packet" );
00266 break;
00267 }
00268 command->release();
00269 }
00270
00271 bool Client::dispatchCommand( net::Command& command )
00272 {
00273 EQVERB << "dispatchCommand " << command << std::endl;
00274
00275 switch( command->datatype )
00276 {
00277 case DATATYPE_EQ_CLIENT:
00278 return net::Dispatcher::dispatchCommand( command );
00279
00280 case DATATYPE_EQ_SERVER:
00281 {
00282 net::NodePtr node = command.getNode();
00283
00284 EQASSERT( dynamic_cast< Server* >( node.get( )) );
00285 ServerPtr server = static_cast< Server* >( node.get( ));
00286
00287 return server->net::Dispatcher::dispatchCommand( command );
00288 }
00289
00290 default:
00291 return net::Node::dispatchCommand( command );
00292 }
00293 }
00294
00295 net::CommandResult Client::invokeCommand( net::Command& command )
00296 {
00297 EQVERB << "invokeCommand " << command << std::endl;
00298
00299 switch( command->datatype )
00300 {
00301 case DATATYPE_EQ_CLIENT:
00302 return net::Dispatcher::invokeCommand( command );
00303
00304 case DATATYPE_EQ_SERVER:
00305 {
00306 net::NodePtr node = command.getNode();
00307
00308 EQASSERT( dynamic_cast<Server*>( node.get( )) );
00309 ServerPtr server = static_cast<Server*>( node.get( ));
00310
00311 return server->net::Dispatcher::invokeCommand( command );
00312 }
00313 default:
00314 return net::Node::invokeCommand( command );
00315 }
00316 }
00317
00318 net::CommandResult Client::_cmdExit( net::Command& command )
00319 {
00320 _running = false;
00321
00322 command.getLocalNode()->close( command.getNode( ));
00323 return net::COMMAND_HANDLED;
00324 }
00325 }