1 /* $Id: servercommunicator.cpp,v 1.8.4.1 2006/03/09 14:59:42 chfreund Exp $ */
2 
3 // #include "tcpconnection.hpp"
4 #include "servercommunicator.hpp"
5 // #include "clientcommunicator.hpp"
6 #include "clientconnection.hpp"
7 #include "clientconnectionlistener.hpp"
8 #include "clientconnectiondirect.hpp"
9 #include "gamereplay.hpp"
10 #include "wopsettings.hpp"
11 
ServerCommunicator(World * world,GameReplay * replay)12 ServerCommunicator::ServerCommunicator( World* world, GameReplay* replay )
13 	: m_directConnection( 0 ), m_world( world ), m_frameSequenceCounter( 0 ),
14 	  m_replay( replay ) {
15 	// initialize vector with unused client ids
16 	// m_freeClientIDs.reserve(256);
17 	for ( Uint8 i = 0; i < 255; i++ ) {
18 		m_freeClientIDs.push_back( i );
19 	}
20 
21 	// add TCP listener
22 	ClientConnectionListenerTCP* listener = new ClientConnectionListenerTCP( this, 0xb8b8 );
23 	m_listeners.push_back( listener );
24 }
25 
~ServerCommunicator()26 ServerCommunicator::~ServerCommunicator() {
27 	// delete all listeners
28 	for ( unsigned int i = 0; i < m_listeners.size(); i++ ) {
29 		ClientConnectionListener* listener = m_listeners[i];
30 		delete listener;
31 	}
32 	// delete all connections
33 	for ( std::vector<ClientConnection*>::iterator it = m_idleConnections.begin();
34 	      it != m_idleConnections.end(); it++ )
35 		delete *it;
36 	for ( std::vector<ClientConnection*>::iterator it = m_activeConnections.begin();
37 	      it != m_activeConnections.end(); it++ )
38 		delete *it;
39 /*	if ( m_directConnection )
40 		delete m_directConnection;*/
41 }
42 
listenForClients()43 void ServerCommunicator::listenForClients() {
44 	for ( std::vector<ClientConnectionListener*>::iterator it = m_listeners.begin();
45 	      it != m_listeners.end(); it++ ) {
46 		while ( ClientConnection* connection = (*it)->getNewConnection( m_freeClientIDs.front() ) ) {
47 			LOG( 2 ) INFO( "ServerCommunicator::listenForClients: adding new connection\n" );
48 			addConnection( connection );
49 			// connection->openConnection( clientID );
50 		}
51 	}
52 }
53 
collectEvents()54 void ServerCommunicator::collectEvents() {
55 	DBG( 5 ) INFO( "ServerCommunicator::collectEvents: collecting events\n" );
56 
57 	std::vector<Player*> playerVector = m_world->getPlayerList();
58 
59 	// Collect game events from all active connected clients
60 	for ( unsigned int c = 0; c < m_activeConnections.size(); c++ ) {
61 		ClientConnection* connection = m_activeConnections[c];
62 		EventMessage* eventMessage = connection->getEventMessage();
63 		if ( eventMessage ) {
64 			// Copy the events for all players in this client in the global
65 			// echo message
66 			for ( Uint8 p = 0; p < connection->getNumberConnectedPlayers(); p++ ) {
67 				// get global index for player
68 				Uint8 index = m_world->getPlayerIndex( connection->getGlobalPlayerNumber( p ) );
69 				if ( index >= m_world->getNumberPlayers() ) {
70 					DBG( 2 ) INFO( "ServerCommunicator::collectEvents: player with ID %d not found in player vector -> ignoring event\n", connection->getGlobalPlayerNumber( p ) );
71 					continue;
72 				}
73 				// store event at the right position
74 				if ( p < eventMessage->numberEvents ) {
75 					m_echoMessage.event[index] = eventMessage->event[p];
76 					// check for replay bookmark
77 					if ( m_replay ) {
78 						static int bookmarkDeadTime = 0;
79 						if ( bookmarkDeadTime > 0 )
80 							bookmarkDeadTime--;
81 						else if ( eventMessage->event[p].testAnyActions( Event::INSERT_REPLAY_BOOKMARK ) ) {
82 							LOG( 1 ) INFO( "ServerCommunicator::collectEvents: inserting replay bookmark\n" );
83 							m_replay->addBookmark();
84 							bookmarkDeadTime = 25 * 5; // 5 seconds bookmark dead time
85 						}
86 					}
87 				}
88 				else {
89 					m_echoMessage.event[index] = Event::EMPTY;
90 				}
91 			}
92 
93 			delete eventMessage;
94 		}
95 		else {
96 			DBG( 2 ) INFO( "ServerCommunicator::collectEvents: no event message "
97 			               " from connection %d, lag is now %d\n", c, connection->getLag() );
98 			for ( Uint8 p = 0; p < connection->getNumberConnectedPlayers(); p++ ) {
99 				Uint8 index = m_world->getPlayerIndex( connection->getGlobalPlayerNumber( p ) );
100 				if ( index >= m_world->getNumberPlayers() ) {
101 					DBG( 2 ) INFO( "ServerCommunicator::collectEvents: player with ID %d not found in player vector -> setting event nonetheless to N_A\n", connection->getGlobalPlayerNumber( p ) );
102 					continue;
103 				}
104 
105 				m_echoMessage.event[index] = Event::N_A;
106 			}
107 		}
108 	}
109 }
110 
broadcastEcho()111 void ServerCommunicator::broadcastEcho() {
112 	m_echoMessage.frame = m_world->getFrame();
113 	m_echoMessage.randomCounter = m_world->getRandom().getCounter();
114 	m_echoMessage.numberMessages = m_frameSequenceCounter;
115 
116 	DBG( 5 ) INFO( "ServerCommunicator::broadcastEcho: bc echo for frame %d (random = %d, messages = %d)\n", m_echoMessage.frame, m_echoMessage.randomCounter, m_echoMessage.numberMessages );
117 	for ( unsigned int c = 0; c < m_activeConnections.size(); c++ ) {
118 		ClientConnection* connection = m_activeConnections[c];
119 		connection->sendEchoMessage( &m_echoMessage );
120 	}
121 }
122 
handleMessages()123 void ServerCommunicator::handleMessages() {
124 	Message* message;
125 	m_frameSequenceCounter = 0;
126 	for ( unsigned int c = 0; c < m_activeConnections.size(); c++ ) {
127 		ClientConnection* connection = m_activeConnections[c];
128 		while ( ( message = connection->getMessage() ) ) {
129 			// Handle the message properly
130 			switch ( message->type ) {
131 				case Message::ADD_PLAYER: {
132 					DBG( 2 ) INFO( "ServerCommunicator::handleMessages: handling ADD_PLAYER message\n" );
133 					AddPlayerMessage* addPlayerMessage =
134 						static_cast<AddPlayerMessage*>( message );
135 					Player* player = addPlayerMessage->player;
136 
137 					Uint8 playerID = m_world->getNextPlayerID();
138 					addPlayerMessage->globalPlayerNumber = playerID;
139 					player->setPlayerID( playerID );
140 					connection->setGlobalPlayerNumber( connection->getNumberConnectedPlayers(),
141 						playerID );
142 
143 					// TODO: Can we assume that the new player is added to the end of the player vector?
144 					Uint8 index = m_world->getNumberPlayers();
145 					DBG( 2 ) INFO( "Setting action for player %d to %x\n", index, Event::EMPTY );
146 					m_echoMessage.event[index].setAction( Event::EMPTY );
147 					connection->addPlayer();
148 
149 					// store event in replay
150 					if ( m_replay ) m_replay->addPlayerEnter( *player );
151 
152 					m_world->addPlayer( player );
153 					addPlayerMessage->frame = m_world->getFrame();
154 					addPlayerMessage->frameSequenceIndex = m_frameSequenceCounter++;
155 					broadcastMessage( addPlayerMessage );
156 					break;
157 				}
158 				case Message::CHAT: {
159 					DBG( 2 ) INFO( "ServerCommunicator::handleMessages: handling CHAT message\n" );
160 					ChatMessage* chatMessage =
161 						static_cast<ChatMessage*>( message );
162 					m_frameSequenceCounter++;
163 					// store message in replay
164 					if ( m_replay ) m_replay->addChatMessage( chatMessage->message );
165 					broadcastMessage( chatMessage );
166 					break;
167 				}
168 				case Message::QUIT: {
169 					DBG( 2 ) INFO( "ServerCommunicator::handleMessages: handling QUIT message\n" );
170 					// disabled to avoid compiler warning, Tom
171 					//QuitMessage* quitMessage =
172 					//	static_cast<QuitMessage*>( message );
173 					connection->closeConnection();
174 					break;
175 				}
176 				default:
177 					ASSERT( false, "ServerCommunicator::handleMessages: don't know how to handle message of type %d\n", message->type );
178 					break;
179 			}
180 			delete message;
181 		}
182 	}
183 
184 	// Handle messages from idle connections
185 	for ( unsigned int c = 0; c < m_idleConnections.size(); c++ ) {
186 		ClientConnection* connection = m_idleConnections[c];
187 		while ( ( message = connection->getMessage() ) ) {
188 			DBG( 2 ) INFO( "ServerCommunicator::handleMessages: got message from idle connection %d\n", c );
189 			if ( message->type != Message::REQUEST ) {
190 				LOG( 2 ) INFO( "ServerCommunicator::handleMessages: can only handle REQUEST messages from idle clients\n" );
191 				delete message;
192 				continue;
193 			}
194 
195 			RequestMessage* requestMessage = static_cast<RequestMessage*>( message );
196 
197 			if ( requestMessage->request == Message::WORLD ) {
198 				WorldMessage* worldMessage = NEW WorldMessage();
199 				worldMessage->world = m_world;
200 				DBG( 2 ) INFO( "ServerCommunicator::handleMessages: send world to the client\n" );
201 				connection->setCompression( true );
202 				connection->setProgressListener( this );
203 				connection->sendMessage( worldMessage );
204 				connection->setCompression( false );
205 				connection->setProgressListener( 0 );
206 				delete worldMessage;
207 				// change client state from 'idle' to 'active'
208 				m_idleConnections.erase( m_idleConnections.begin() + c );
209 				c--;
210 				m_activeConnections.push_back( connection );
211 			}
212 			else if ( requestMessage->request == Message::INFO ) {
213 				WopSettings* settings = WopSettings::getInstance();
214 				InfoMessage infoMessage;
215 				infoMessage.theme = settings->getTheme();
216 				infoMessage.gamemode = settings->getGameMode();
217 				infoMessage.numberPlayers = m_world->getNumberPlayers();
218 				for ( int p = 0; p < m_world->getNumberPlayers(); p++ ) {
219 					infoMessage.player.push_back( m_world->getPlayer( p ) );
220 				}
221 				connection->sendMessage( &infoMessage );
222 			}
223 			else {
224 				LOG( 2 ) INFO( "ServerCommunicator::handleMessages: cannot handle request of type %d\n",
225 									requestMessage->request );
226 			}
227 
228 			delete requestMessage;
229 		}
230 	}
231 
232 	// Remove disconnected clients
233 	for ( unsigned int c = 0; c < m_activeConnections.size(); c++ ) {
234 		ClientConnection* connection = m_activeConnections[c];
235 		if ( !connection->isConnected() ) {
236 			DBG( 2 ) INFO( "ServerCommunicator::handleMessages: removing active client %d\n", c );
237 			cleanupConnection( connection );
238 			// recover client ID
239 			Uint8 clientID = connection->getId();
240 			m_freeClientIDs.push_back( clientID );
241 			delete connection;
242 			m_activeConnections.erase( m_activeConnections.begin() + c );
243 			c--;
244 		}
245 	}
246 	for ( unsigned int c = 0; c < m_idleConnections.size(); c++ ) {
247 		ClientConnection* connection = m_idleConnections[c];
248 		if ( !connection->isConnected() ) {
249 			DBG( 2 ) INFO( "ServerCommunicator::handleMessages: removing idle client %d\n", c );
250 			// cleanupConnection( connection );
251 			// recover client ID
252 			Uint8 clientID = connection->getId();
253 			m_freeClientIDs.push_back( clientID );
254 			delete connection;
255 			m_idleConnections.erase( m_idleConnections.begin() + c );
256 			c--;
257 		}
258 	}
259 }
260 
addConnection(ClientConnection * connection)261 Uint8 ServerCommunicator::addConnection( ClientConnection* connection ) {
262 	INFO( "ServerCommunicator::addConnection: client is connecting\n" );
263 	Uint8 newClientID = m_freeClientIDs.front();
264 	m_freeClientIDs.pop_front();
265 	m_idleConnections.push_back( connection );
266 	return newClientID;
267 }
268 
getDirectConnection(ServerConnectionDirect * serverConnection)269 ClientConnectionDirect* ServerCommunicator::getDirectConnection
270 ( ServerConnectionDirect* serverConnection ) {
271 	// INFO( "ServerCommunicator::getDirectConnection: local client is connecting\n" );
272 	ClientConnectionDirect* clientConnection =
273 		new ClientConnectionDirect( this, serverConnection );
274 	// m_connections.push_back( clientConnection );
275 	return clientConnection;
276 }
277 
broadcastMessage(Message * message)278 void ServerCommunicator::broadcastMessage( Message* message ) {
279 	for ( std::vector<ClientConnection*>::iterator it =
280 	      m_activeConnections.begin(); it != m_activeConnections.end(); it++ ) {
281 		ClientConnection* connection = *it;
282 		connection->sendMessage( message );
283 	}
284 }
285 
cleanupConnection(ClientConnection * connection)286 void ServerCommunicator::cleanupConnection( ClientConnection* connection ) {
287 	// Remove all players from this client
288 	for ( Uint8 p = 0; p < connection->getNumberConnectedPlayers(); p++ ) {
289 		Uint8 globalPlayerID = connection->getGlobalPlayerNumber( p );
290 
291 		// fetch player
292 		Player* player = m_world->getPlayerByID( globalPlayerID );
293 		// store event in replay
294 		if ( m_replay ) m_replay->addPlayerQuit( globalPlayerID );
295 		// remove player from world
296 		m_world->removePlayer( globalPlayerID );
297 		// delete player object
298 		delete player;
299 
300 		// inform all clients
301 		RemovePlayerMessage message;
302 		message.playerNumber = globalPlayerID;
303 		message.frame = m_world->getFrame();
304 		message.frameSequenceIndex = m_frameSequenceCounter++;
305 
306 		broadcastMessage( &message );
307 	}
308 }
309 
sendProgress(Sint32 size,Sint32 sent)310 void ServerCommunicator::sendProgress( Sint32 size, Sint32 sent ) {
311 	// inform all active clients about sync progress
312 	SyncProgressMessage message;
313 	message.messageSize = size;
314 	message.dataSent    = sent;
315 	for ( unsigned int c = 0; c < m_activeConnections.size(); c++ ) {
316 		ClientConnection* connection = m_activeConnections[c];
317 		connection->sendEchoMessage( &message );
318 	}
319 }
320 
recvProgress(Sint32 size,Sint32 received)321 void ServerCommunicator::recvProgress( Sint32 size, Sint32 received ) {
322 }
323