Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/network/proxy/proxy_control.cc @ 9690

Last change on this file since 9690 was 9690, checked in by bensch, 18 years ago

some network-stuff

File size: 11.7 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11### File Specific:
12   main-programmer: Patrick Boenzli (patrick@orxonox.ethz.ch)
13*/
14
15#include "proxy_control.h"
16
17#include "class_list.h"
18#include "shell_command.h"
19
20#include "state.h"
21#include "shared_network_data.h"
22#include "network_manager.h"
23#include "network_game_manager.h"
24#include "ip.h"
25#include "peer_info.h"
26#include "network_stream.h"
27
28#include "converter.h"
29
30#include "preferences.h"
31
32#include "debug.h"
33
34#include "monitor/network_monitor.h"
35
36
37#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_NETWORK
38
39ProxyControl* ProxyControl::singletonRef = NULL;
40
41
42SHELL_COMMAND(forceReconnect, ProxyControl, forceReconnectionShell);
43NewObjectListDefinition(ProxyControl);
44
45/**
46 * constructor
47 */
48ProxyControl::ProxyControl()
49{
50  this->setClassID( CL_PROXY_CONTROL, "ProxyControl" );
51
52  this->setSynchronized(false);
53
54  MessageManager::getInstance()->registerMessageHandler( MSGID_PROXY_NEWCLIENT, messageHandlerNewClient, NULL );
55  MessageManager::getInstance()->registerMessageHandler( MSGID_PROXY_LEAVECLIENT, messageHandlerLeaveClient, NULL );
56  MessageManager::getInstance()->registerMessageHandler( MSGID_PROXY_COMMAND, messageHandlerCommand, NULL );
57
58
59  PRINTF(0)("ProxyControl created\n");
60}
61
62
63/**
64 * standard deconstructor
65 */
66ProxyControl::~ProxyControl()
67{
68  ProxyControl::singletonRef = NULL;
69}
70
71
72 /**
73 * override this function to be notified on change
74 * of your registred variables.
75 * @param id id's which have changed
76  */
77void ProxyControl::varChangeHandler( std::list< int > & id )
78{
79//   if ( std::find( id.begin(), id.end(), playableUniqueId_handle ) != id.end() )
80//   {
81//     this->setPlayableUniqueId( this->playableUniqueId );
82//
83//     PRINTF(0)("uniqueID changed %d %d %d\n", userId, SharedNetworkData::getInstance()->getHostID(), getUniqueID());
84//   }
85}
86
87
88/**
89 *  signals new client connected to this local proxy
90 *
91 *  byte 0 - 3     :      userId
92 *  byte 4 - 7     :      ip address (IPaddress.host)
93 *
94 * @param userId userId of the new client
95 */
96void ProxyControl::signalNewClient(int userId)
97{
98  PRINTF(0)("Signaling new Client: %i\n", userId);
99  // make sure we are a proxy server
100  assert(SharedNetworkData::getInstance()->isProxyServerActive());
101
102  byte data[2 * INTSIZE];
103  // write the userId in the message
104  assert( Converter::intToByteArray( userId, data, INTSIZE ) == INTSIZE );
105  // and the ip as an int
106  PeerInfo* pInfo = SharedNetworkData::getInstance()->getNetworkMonitor()->getPeerByUserId(userId);
107  assert(pInfo != NULL);
108  assert( Converter::intToByteArray( pInfo->ip.host(), data + INTSIZE, INTSIZE ) == INTSIZE );
109
110  MessageManager::getInstance()->sendMessage( MSGID_PROXY_NEWCLIENT, data, 2*INTSIZE, RT_SERVER, NET_UNASSIGNED, MP_HIGHBANDWIDTH );
111}
112
113
114/**
115 * this is the handler for proxy signals: new clients
116 *
117 * @param messageType the type of the message
118 * @param data message data
119 * @param dataLength length of the message data
120 * @param someData some other atteched data
121 * @param senderId id of the sender client
122 * @param destinationId id of the destination client
123 * @return true if succeeded
124 */
125bool ProxyControl::messageHandlerNewClient( MessageType messageType, byte * data, int dataLength, void * someData, int senderId, int destinationId  )
126{
127  // body data length correct?
128  if ( dataLength != 2 * INTSIZE )
129  {
130    PRINTF(2)("new client message has wrong size: %d\n", dataLength );
131    return true;
132  }
133  // read the userId fromt he message body
134  int newClientId = 0;
135  assert( Converter::byteArrayToInt( data, &newClientId) == INTSIZE );
136  // now read the ip address
137  int ipHost = 0;
138  assert( Converter::byteArrayToInt( data + INTSIZE, &ipHost) == INTSIZE );
139
140  // register the new node at the network monitor
141  NetworkMonitor* netMon = SharedNetworkData::getInstance()->getNetworkMonitor();
142  NetworkNode* nNode = netMon->getNodeByUserId(senderId); // this gets the proxy server who sent the msg
143  if( nNode == NULL)
144    PRINTF(0)("Couldn't find node %i! Error\n", senderId);
145  PeerInfo* pInfo = new PeerInfo();
146  pInfo->bLocal = false;
147  pInfo->ip = IP(ipHost, 9999);
148  pInfo->nodeType = NET_CLIENT;
149  pInfo->userId = newClientId;
150  netMon->addNode(nNode, pInfo);
151
152  PRINTF(0)("Got Signal: from %i new player arrived with userId: %i and ip: %s on %i\n", senderId, newClientId, pInfo->ip.ipString().c_str(), senderId);
153  // part for the master server
154  if( SharedNetworkData::getInstance()->isMasterServer())
155  {
156    // we now create the new player ship and stuff...
157    NetworkGameManager::getInstance()->signalNewPlayer(newClientId);
158  }
159
160  return true;
161}
162
163
164
165/**
166 *  signals client disconnect
167 * @param userId userId of the old client
168 */
169void ProxyControl::signalLeaveClient(int userId)
170{
171  PRINTF(0)("Signaling new Client: %i\n", userId);
172  // make sure we are a proxy server
173  assert(SharedNetworkData::getInstance()->isProxyServerActive());
174
175  byte data[INTSIZE];
176
177  assert( Converter::intToByteArray( userId, data, INTSIZE ) == INTSIZE );
178
179  MessageManager::getInstance()->sendMessage( MSGID_PROXY_LEAVECLIENT, data, INTSIZE, RT_SERVER, NET_UNASSIGNED, MP_HIGHBANDWIDTH );
180}
181
182
183/**
184 * this is the handler for proxy signals: removing clients
185 *
186 * @param messageType the type of the message
187 * @param data message data
188 * @param dataLength length of the message data
189 * @param someData some other atteched data
190 * @param senderId id of the sender client
191 * @param destinationId id of the destination client
192 * @return true if succeeded
193 */
194bool ProxyControl::messageHandlerLeaveClient( MessageType messageType, byte * data, int dataLength, void * someData, int senderId, int destinationId  )
195{
196  // body data length correct?
197  if ( dataLength != INTSIZE )
198  {
199    PRINTF(2)("leave client message has wrong size: %d\n", dataLength );
200    return true;
201  }
202  // read the userId fromt he message body
203  int leaveClientId = 0;
204  assert( Converter::byteArrayToInt( data, &leaveClientId) == INTSIZE );
205
206  // remove the node from the network monitor
207  NetworkMonitor* netMon = SharedNetworkData::getInstance()->getNetworkMonitor();
208  NetworkNode* nNode = netMon->getNodeByUserId(senderId); // this gets the proxy server who sent the msg
209  netMon->removeNode(nNode, netMon->getPeerByUserId(leaveClientId));
210
211  PRINTF(0)("Got Signal: from %i player left with userId: %i\n", senderId, leaveClientId);
212  // part for the master server
213  if( SharedNetworkData::getInstance()->isMasterServer())
214  {
215    // we now create the new player ship and stuff...
216    NetworkGameManager::getInstance()->signalLeftPlayer(leaveClientId);
217  }
218  else if(SharedNetworkData::getInstance()->isProxyServerActive())
219  {
220
221  }
222
223  return true;
224}
225
226
227
228/**
229 * forces a client to reconnect to another server
230 * @param userId the userId of the client/user :D
231 * @param newAddress the addresss the client should connect to (fully quali dns)
232 */
233void ProxyControl::forceReconnection(int userId, const std::string& newAddress)
234{
235  IP ipAddr = IP(newAddress, 9999);
236  this->forceReconnection(userId, newAddress);
237}
238
239
240
241/**
242 * thumb command: staticly reconnect node 10 to node 0
243 */
244void ProxyControl::forceReconnectionShellThumb()
245{
246  this->forceReconnectionShell(10, 0);
247}
248
249/**
250 * a shell command wrapper
251 * @param userId the userId of the client/user :D
252 * @param serverId the userId of the server to connect to
253 */
254void ProxyControl::forceReconnectionShell(int userId, int serverId)
255{
256  PRINTF(0)("shell reconnectoin command: %i to %i\n", userId, serverId);
257
258  this->forceReconnection(userId, serverId);
259}
260
261
262/**
263 * forces a client to reconnect to another server
264 * @param userId the userId of the client/user :D
265 * @param serverId the userId of the server to connect to
266 */
267void ProxyControl::forceReconnection(int userId, int serverId)
268{
269  PeerInfo* serverInfo = SharedNetworkData::getInstance()->getNetworkMonitor()->getPeerByUserId(serverId);
270  if( serverInfo == NULL)
271  {
272    PRINTF(0)("There is no server with userId %i registered in this network. Check the uid again\n", serverId);
273    return;
274  }
275  else if( serverInfo->isClient())
276  {
277    PRINTF(0)("You can't connec to to a client (userId %i)\n", serverId);
278    return;
279  }
280
281
282  this->forceReconnection(userId, serverId, serverInfo->ip);
283}
284
285
286/**
287 * forces a client to reconnect to another server
288 * @param userId the userId of the client/user :D
289 * @param newAddress the addresss the client should connect to
290 */
291void ProxyControl::forceReconnection(int userId, int serverId, IP newAddress)
292{
293  PRINTF(0)("forcing reconnection: userId %i to %s\n", userId, newAddress.ipString().c_str());
294  // make sure we are a proxy server
295
296  if( SharedNetworkData::getInstance()->isClient())
297  {
298    PRINTF(0)("I am client, got no right to force reconnection\n");
299    return;
300  }
301
302
303  byte data[3 * INTSIZE];
304
305  // write type of message
306  int type = PXY_RECONNECT;
307  assert( Converter::intToByteArray( type, data, INTSIZE ) == INTSIZE );
308  // write the userId in the message
309  assert( Converter::intToByteArray( userId, data + INTSIZE, INTSIZE ) == INTSIZE );
310  // and the ip as an int
311  PeerInfo* pInfo = SharedNetworkData::getInstance()->getNetworkMonitor()->getPeerByUserId(userId);
312  if( pInfo == NULL)
313  {
314    PRINTF(0)("There is no client with userId %i registered in this network. Check the uid again\n", userId);
315    return;
316  }
317  else if( pInfo->isMasterServer() || pInfo->isProxyServerActive())
318  {
319    PRINTF(0)("You cannont reconnect a %s, abording\n", pInfo->getNodeTypeString().c_str());
320    return;
321  }
322  assert( Converter::intToByteArray( newAddress.host(), data + 2 * INTSIZE, INTSIZE ) == INTSIZE );
323
324  PRINTF(0)("Sending reconnection command to: %i\n", userId);
325  // send the reconnection signal to the client who must reconnect
326  MessageManager::getInstance()->sendMessage( MSGID_PROXY_COMMAND, data, 3*INTSIZE, RT_USER, userId, MP_HIGHBANDWIDTH );
327  // and to the server who needs to accept the new client
328  MessageManager::getInstance()->sendMessage( MSGID_PROXY_COMMAND, data, 3*INTSIZE, RT_USER, serverId, MP_HIGHBANDWIDTH );
329}
330
331
332/**
333 * this is the handler for proxy commands
334 *
335 * @param messageType the type of the message
336 * @param data message data
337 * @param dataLength length of the message data
338 * @param someData some other atteched data
339 * @param senderId id of the sender client
340 * @param destinationId id of the destination client
341 * @return true if succeeded
342 */
343bool ProxyControl::messageHandlerCommand( MessageType messageType, byte * data, int dataLength, void * someData, int senderId, int destinationId  )
344{
345  // body data length correct?
346  if ( dataLength != 3 * INTSIZE )
347  {
348    PRINTF(1)("leave client message has wrong size: %d\n", dataLength );
349    return true;
350  }
351
352  // read the command type
353  int type = 0;
354  assert( Converter::byteArrayToInt( data, &type) == INTSIZE );
355  PRINTF(0)("got command from %i with code %i\n", senderId, type);
356
357  // now distingush all different sorts of commands
358  switch( type)
359  {
360    case PXY_RECONNECT:
361    {
362      // now read the user id
363      int userId;
364      assert( Converter::byteArrayToInt( data + INTSIZE, &userId) == INTSIZE );
365      // and read the dest address
366      int ipHost = 0;
367      assert( Converter::byteArrayToInt( data + INTSIZE, &ipHost) == INTSIZE );
368
369      PRINTF(0)("Got reconnection command from %i: reconnect!\n", senderId);
370      // handle it
371      if( SharedNetworkData::getInstance()->getHostID() == userId)
372      {
373        if( SharedNetworkData::getInstance()->isClient())
374          SharedNetworkData::getInstance()->getDefaultSyncStream()->softReconnectToServer(userId, IP(ipHost, 9999));
375        else
376          SharedNetworkData::getInstance()->getDefaultSyncStream()->prepareSoftConnection(userId);
377      }
378      break;
379    }
380    default:
381      PRINTF(0)("Command not known with id %i\n", type);
382  }
383
384
385
386  return true;
387}
388
Note: See TracBrowser for help on using the repository browser.