Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/network/proxy/proxy_control.cc @ 9824

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

orxonox/trunk: merged the proxy bache back with no conflicts

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