diff options
Diffstat (limited to '')
| -rw-r--r-- | src/stable/server.cpp | 252 | 
1 files changed, 126 insertions, 126 deletions
diff --git a/src/stable/server.cpp b/src/stable/server.cpp index 39ff7bb..e6c256e 100644 --- a/src/stable/server.cpp +++ b/src/stable/server.cpp  | |||
| @@ -14,138 +14,138 @@ | |||
| 14 | #include "bu/config.h" | 14 | #include "bu/config.h" | 
| 15 | 15 | ||
| 16 | Bu::Server::Server() : | 16 | Bu::Server::Server() : | 
| 17 | nTimeoutSec( 0 ), | 17 | nTimeoutSec( 0 ), | 
| 18 | nTimeoutUSec( 0 ), | 18 | nTimeoutUSec( 0 ), | 
| 19 | bAutoTick( false ) | 19 | bAutoTick( false ) | 
| 20 | { | 20 | { | 
| 21 | FD_ZERO( &fdActive ); | 21 | FD_ZERO( &fdActive ); | 
| 22 | } | 22 | } | 
| 23 | 23 | ||
| 24 | Bu::Server::~Server() | 24 | Bu::Server::~Server() | 
| 25 | { | 25 | { | 
| 26 | shutdown(); | 26 | shutdown(); | 
| 27 | } | 27 | } | 
| 28 | 28 | ||
| 29 | void Bu::Server::addPort( int nPort, int nPoolSize ) | 29 | void Bu::Server::addPort( int nPort, int nPoolSize ) | 
| 30 | { | 30 | { | 
| 31 | TcpServerSocket *s = new TcpServerSocket( nPort, nPoolSize ); | 31 | TcpServerSocket *s = new TcpServerSocket( nPort, nPoolSize ); | 
| 32 | socket_t nSocket = s->getSocket(); | 32 | socket_t nSocket = s->getSocket(); | 
| 33 | FD_SET( nSocket, &fdActive ); | 33 | FD_SET( nSocket, &fdActive ); | 
| 34 | hServers.insert( nSocket, s ); | 34 | hServers.insert( nSocket, s ); | 
| 35 | } | 35 | } | 
| 36 | 36 | ||
| 37 | void Bu::Server::addPort( const String &sAddr, int nPort, int nPoolSize ) | 37 | void Bu::Server::addPort( const String &sAddr, int nPort, int nPoolSize ) | 
| 38 | { | 38 | { | 
| 39 | TcpServerSocket *s = new TcpServerSocket( sAddr, nPort, nPoolSize ); | 39 | TcpServerSocket *s = new TcpServerSocket( sAddr, nPort, nPoolSize ); | 
| 40 | socket_t nSocket = s->getSocket(); | 40 | socket_t nSocket = s->getSocket(); | 
| 41 | FD_SET( nSocket, &fdActive ); | 41 | FD_SET( nSocket, &fdActive ); | 
| 42 | hServers.insert( nSocket, s ); | 42 | hServers.insert( nSocket, s ); | 
| 43 | } | 43 | } | 
| 44 | 44 | ||
| 45 | void Bu::Server::setTimeout( int nTimeoutSec, int nTimeoutUSec ) | 45 | void Bu::Server::setTimeout( int nTimeoutSec, int nTimeoutUSec ) | 
| 46 | { | 46 | { | 
| 47 | this->nTimeoutSec = nTimeoutSec; | 47 | this->nTimeoutSec = nTimeoutSec; | 
| 48 | this->nTimeoutUSec = nTimeoutUSec; | 48 | this->nTimeoutUSec = nTimeoutUSec; | 
| 49 | } | 49 | } | 
| 50 | 50 | ||
| 51 | void Bu::Server::scan() | 51 | void Bu::Server::scan() | 
| 52 | { | 52 | { | 
| 53 | struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; | 53 | struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; | 
| 54 | 54 | ||
| 55 | fd_set fdRead = fdActive; | 55 | fd_set fdRead = fdActive; | 
| 56 | fd_set fdWrite /* = fdActive*/; | 56 | fd_set fdWrite /* = fdActive*/; | 
| 57 | fd_set fdException = fdActive; | 57 | fd_set fdException = fdActive; | 
| 58 | 58 | ||
| 59 | FD_ZERO( &fdWrite ); | 59 | FD_ZERO( &fdWrite ); | 
| 60 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 60 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 
| 61 | { | 61 | { | 
| 62 | if( (*i)->hasOutput() ) | 62 | if( (*i)->hasOutput() ) | 
| 63 | FD_SET( i.getKey(), &fdWrite ); | 63 | FD_SET( i.getKey(), &fdWrite ); | 
| 64 | } | 64 | } | 
| 65 | 65 | ||
| 66 | if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, | 66 | if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, | 
| 67 | &fdRead, &fdWrite, &fdException, &xTimeout ) ) < 0 ) | 67 | &fdRead, &fdWrite, &fdException, &xTimeout ) ) < 0 ) | 
| 68 | { | 68 | { | 
| 69 | throw ExceptionBase("Error attempting to scan open connections."); | 69 | throw ExceptionBase("Error attempting to scan open connections."); | 
| 70 | } | 70 | } | 
| 71 | 71 | ||
| 72 | for( int j = 0; j < FD_SETSIZE; j++ ) | 72 | for( int j = 0; j < FD_SETSIZE; j++ ) | 
| 73 | { | 73 | { | 
| 74 | if( FD_ISSET( j, &fdRead ) ) | 74 | if( FD_ISSET( j, &fdRead ) ) | 
| 75 | { | 75 | { | 
| 76 | if( hServers.has( j ) ) | 76 | if( hServers.has( j ) ) | 
| 77 | { | 77 | { | 
| 78 | TcpServerSocket *pSrv = hServers.get( j ); | 78 | TcpServerSocket *pSrv = hServers.get( j ); | 
| 79 | addClient( pSrv->accept(), pSrv->getPort() ); | 79 | addClient( pSrv->accept(), pSrv->getPort() ); | 
| 80 | } | 80 | } | 
| 81 | else | 81 | else | 
| 82 | { | 82 | { | 
| 83 | Client *pClient = hClients.get( j ); | 83 | Client *pClient = hClients.get( j ); | 
| 84 | pClient->processInput(); | 84 | pClient->processInput(); | 
| 85 | if( !pClient->isOpen() ) | 85 | if( !pClient->isOpen() ) | 
| 86 | { | 86 | { | 
| 87 | closeClient( j ); | 87 | closeClient( j ); | 
| 88 | } | 88 | } | 
| 89 | } | 89 | } | 
| 90 | } | 90 | } | 
| 91 | if( FD_ISSET( j, &fdWrite ) ) | 91 | if( FD_ISSET( j, &fdWrite ) ) | 
| 92 | { | 92 | { | 
| 93 | try | 93 | try | 
| 94 | { | 94 | { | 
| 95 | Client *pClient = hClients.get( j ); | 95 | Client *pClient = hClients.get( j ); | 
| 96 | try | 96 | try | 
| 97 | { | 97 | { | 
| 98 | pClient->processOutput(); | 98 | pClient->processOutput(); | 
| 99 | } | 99 | } | 
| 100 | catch( Bu::TcpSocketException &e ) | 100 | catch( Bu::TcpSocketException &e ) | 
| 101 | { | 101 | { | 
| 102 | closeClient( j ); | 102 | closeClient( j ); | 
| 103 | } | 103 | } | 
| 104 | } | 104 | } | 
| 105 | catch( Bu::HashException &e ) | 105 | catch( Bu::HashException &e ) | 
| 106 | { | 106 | { | 
| 107 | // Do nothing, I guess, the client is already dead... | 107 | // Do nothing, I guess, the client is already dead... | 
| 108 | // TODO: Someday, we may want to handle this more graceully. | 108 | // TODO: Someday, we may want to handle this more graceully. | 
| 109 | } | 109 | } | 
| 110 | } | 110 | } | 
| 111 | } | 111 | } | 
| 112 | 112 | ||
| 113 | Bu::List<int> lDelete; | 113 | Bu::List<int> lDelete; | 
| 114 | // Now we just try to write all the pending data on all the sockets. | 114 | // Now we just try to write all the pending data on all the sockets. | 
| 115 | // this could be done better eventually, if we care about the socket | 115 | // this could be done better eventually, if we care about the socket | 
| 116 | // wanting to accept writes (using a select). | 116 | // wanting to accept writes (using a select). | 
| 117 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 117 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 
| 118 | { | 118 | { | 
| 119 | if( (*i)->wantsDisconnect() && !(*i)->hasOutput() ) | 119 | if( (*i)->wantsDisconnect() && !(*i)->hasOutput() ) | 
| 120 | { | 120 | { | 
| 121 | lDelete.append( i.getKey() ); | 121 | lDelete.append( i.getKey() ); | 
| 122 | } | 122 | } | 
| 123 | } | 123 | } | 
| 124 | 124 | ||
| 125 | for( Bu::List<int>::iterator i = lDelete.begin(); i != lDelete.end(); i++ ) | 125 | for( Bu::List<int>::iterator i = lDelete.begin(); i != lDelete.end(); i++ ) | 
| 126 | { | 126 | { | 
| 127 | closeClient( *i ); | 127 | closeClient( *i ); | 
| 128 | } | 128 | } | 
| 129 | 129 | ||
| 130 | if( bAutoTick ) | 130 | if( bAutoTick ) | 
| 131 | tick(); | 131 | tick(); | 
| 132 | } | 132 | } | 
| 133 | 133 | ||
| 134 | void Bu::Server::addClient( socket_t nSocket, int nPort ) | 134 | void Bu::Server::addClient( socket_t nSocket, int nPort ) | 
| 135 | { | 135 | { | 
| 136 | FD_SET( nSocket, &fdActive ); | 136 | FD_SET( nSocket, &fdActive ); | 
| 137 | 137 | ||
| 138 | Client *c = new Client( | 138 | Client *c = new Client( | 
| 139 | new Bu::TcpSocket( nSocket ), | 139 | new Bu::TcpSocket( nSocket ), | 
| 140 | new SrvClientLinkFactory() | 140 | new SrvClientLinkFactory() | 
| 141 | ); | 141 | ); | 
| 142 | hClients.insert( nSocket, c ); | 142 | hClients.insert( nSocket, c ); | 
| 143 | 143 | ||
| 144 | onNewConnection( c, nPort ); | 144 | onNewConnection( c, nPort ); | 
| 145 | } | 145 | } | 
| 146 | 146 | ||
| 147 | Bu::Server::SrvClientLink::SrvClientLink( Bu::Client *pClient ) : | 147 | Bu::Server::SrvClientLink::SrvClientLink( Bu::Client *pClient ) : | 
| 148 | pClient( pClient ) | 148 | pClient( pClient ) | 
| 149 | { | 149 | { | 
| 150 | } | 150 | } | 
| 151 | 151 | ||
| @@ -155,7 +155,7 @@ Bu::Server::SrvClientLink::~SrvClientLink() | |||
| 155 | 155 | ||
| 156 | void Bu::Server::SrvClientLink::sendMessage( const Bu::String &sMsg ) | 156 | void Bu::Server::SrvClientLink::sendMessage( const Bu::String &sMsg ) | 
| 157 | { | 157 | { | 
| 158 | pClient->onMessage( sMsg ); | 158 | pClient->onMessage( sMsg ); | 
| 159 | } | 159 | } | 
| 160 | 160 | ||
| 161 | Bu::Server::SrvClientLinkFactory::SrvClientLinkFactory() | 161 | Bu::Server::SrvClientLinkFactory::SrvClientLinkFactory() | 
| @@ -167,48 +167,48 @@ Bu::Server::SrvClientLinkFactory::~SrvClientLinkFactory() | |||
| 167 | } | 167 | } | 
| 168 | 168 | ||
| 169 | Bu::ClientLink *Bu::Server::SrvClientLinkFactory::createLink( | 169 | Bu::ClientLink *Bu::Server::SrvClientLinkFactory::createLink( | 
| 170 | Bu::Client *pClient ) | 170 | Bu::Client *pClient ) | 
| 171 | { | 171 | { | 
| 172 | return new SrvClientLink( pClient ); | 172 | return new SrvClientLink( pClient ); | 
| 173 | } | 173 | } | 
| 174 | 174 | ||
| 175 | void Bu::Server::setAutoTick( bool bEnable ) | 175 | void Bu::Server::setAutoTick( bool bEnable ) | 
| 176 | { | 176 | { | 
| 177 | bAutoTick = bEnable; | 177 | bAutoTick = bEnable; | 
| 178 | } | 178 | } | 
| 179 | 179 | ||
| 180 | void Bu::Server::tick() | 180 | void Bu::Server::tick() | 
| 181 | { | 181 | { | 
| 182 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 182 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 
| 183 | { | 183 | { | 
| 184 | (*i)->tick(); | 184 | (*i)->tick(); | 
| 185 | } | 185 | } | 
| 186 | } | 186 | } | 
| 187 | 187 | ||
| 188 | void Bu::Server::shutdown() | 188 | void Bu::Server::shutdown() | 
| 189 | { | 189 | { | 
| 190 | for( SrvHash::iterator i = hServers.begin(); i != hServers.end(); i++ ) | 190 | for( SrvHash::iterator i = hServers.begin(); i != hServers.end(); i++ ) | 
| 191 | { | 191 | { | 
| 192 | delete *i; | 192 | delete *i; | 
| 193 | } | 193 | } | 
| 194 | 194 | ||
| 195 | hServers.clear(); | 195 | hServers.clear(); | 
| 196 | 196 | ||
| 197 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 197 | for( ClientHash::iterator i = hClients.begin(); i != hClients.end(); i++ ) | 
| 198 | { | 198 | { | 
| 199 | closeClient( i.getKey() ); | 199 | closeClient( i.getKey() ); | 
| 200 | } | 200 | } | 
| 201 | 201 | ||
| 202 | hClients.clear(); | 202 | hClients.clear(); | 
| 203 | } | 203 | } | 
| 204 | 204 | ||
| 205 | void Bu::Server::closeClient( socket_t iSocket ) | 205 | void Bu::Server::closeClient( socket_t iSocket ) | 
| 206 | { | 206 | { | 
| 207 | Bu::Client *pClient = hClients.get( iSocket ); | 207 | Bu::Client *pClient = hClients.get( iSocket ); | 
| 208 | onClosedConnection( pClient ); | 208 | onClosedConnection( pClient ); | 
| 209 | pClient->close(); | 209 | pClient->close(); | 
| 210 | hClients.erase( iSocket ); | 210 | hClients.erase( iSocket ); | 
| 211 | FD_CLR( iSocket, &fdActive ); | 211 | FD_CLR( iSocket, &fdActive ); | 
| 212 | delete pClient; | 212 | delete pClient; | 
| 213 | } | 213 | } | 
| 214 | 214 | ||
