Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/proxy/src/lib/network/udp_socket.cc @ 9453

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

orxonox/trunk: merged the proxy back

merged with commandsvn merge -r9346:HEAD https://svn.orxonox.net/orxonox/branches/proxy .

no conflicts

File size: 7.0 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: Christoph Renner
13   co-programmer:
14*/
15
16#include "udp_socket.h"
17#include "udp_server_socket.h"
18#include "debug.h"
19
20
21void UdpSocket::init( )
22{
23  //TODO setClassId
24  this->serverSocket = NULL;
25  this->socket = NULL;
26  this->packet = NULL;
27  this->randomByte = 0;
28}
29
30
31/**
32 * constructor - connects to give host
33 * @param host host
34 * @param port port
35 */
36UdpSocket::UdpSocket( std::string host, int port )
37{
38  init();
39  this->packet = SDLNet_AllocPacket( UDP_PACKET_SIZE );
40
41  assert( this->packet );
42
43  memset( packet->data, 0, UDP_PACKET_SIZE );
44  PRINTF(0)("PACKET DATA: %x\n", packet->data);
45
46  this->connectToServer( host, port );
47}
48
49/**
50 * default constructor. use this one if you want to call connecttoServer
51 */
52UdpSocket::UdpSocket( )
53{
54  this->init();
55  this->packet = SDLNet_AllocPacket( UDP_PACKET_SIZE );
56
57  if ( !packet )
58  {
59    PRINTF(1)("SDLNet_AllocPacket: %s\n", SDLNet_GetError());
60
61    assert( false );
62    bOk = false;
63  }
64
65}
66
67/**
68 * constructor. used by UdpServerSocket
69 * @param serverSocket pointer to serverSocket
70 * @param ip client's ip address
71 * @param userId userid used by serverSocket
72 */
73UdpSocket::UdpSocket( UdpServerSocket * serverSocket, IPaddress ip, int userId, byte randomByte )
74{
75  this->init();
76  this->ip = ip;
77  this->serverSocket = serverSocket;
78  this->userId = userId;
79  this->randomByte = randomByte;
80}
81
82/**
83 * destructor
84 */
85UdpSocket::~UdpSocket( )
86{
87  this->disconnectServer();
88
89  if ( serverSocket )
90    serverSocket->removeUser( userId );
91
92  if ( this->packet )
93    SDLNet_FreePacket( this->packet );
94
95  if ( socket )
96    SDLNet_UDP_Close( socket );
97}
98
99/**
100 * connect to server
101 * @param host host name
102 * @param port port number
103 */
104void UdpSocket::connectToServer( std::string host, int port )
105{
106  assert( serverSocket == NULL );
107
108  this->randomByte = generateNewRandomByte();
109
110  PRINTF(0)("connect to server %s on port %d\n", host.c_str(), port);
111
112  if ( SDLNet_ResolveHost( &this->ip, host.c_str(), port ) != 0 )
113  {
114    PRINTF(1)("SDLNet_ResolveHost: %s\n", SDLNet_GetError() );
115    bOk = false;
116    return;
117  }
118
119  socket = SDLNet_UDP_Open(0);
120  if ( !socket )
121  {
122    PRINTF(1)("SDLNet_UDP_Open: %s\n", SDLNet_GetError() );
123    bOk = false;
124    return;
125  }
126
127  int channel = SDLNet_UDP_Bind(socket, 1, &this->ip);
128  if ( channel == -1 )
129  {
130    PRINTF(1)("SDLNet_UDP_Bind: %s\n", SDLNet_GetError());
131    bOk = false;
132    return;
133  }
134}
135
136/**
137 * disconnect from server
138 */
139void UdpSocket::disconnectServer( )
140{
141  PRINTF(0)("disconnect\n");
142  byte cmd = this->randomByte | UDPCMD_DISCONNECT;
143  writeRawPacket( &cmd, 1 );
144  SDLNet_UDP_Unbind( socket, -1 );
145  SDLNet_UDP_Close( socket );
146  bOk = false;
147  socket = NULL;
148
149  this->ip.host = 0;
150  this->ip.port = 0;
151}
152
153
154/**
155 * reconnects to
156 * @param host new server address
157 * @param port new port number
158 *
159 * this terminates the current connection and starts a new connection to the new server
160 */
161void UdpSocket::reconnectToServer( std::string host, int port)
162{
163  // first disconnect the old server
164  this->disconnectServer();
165
166  // now connect to the new
167  this->connectToServer( host, port);
168}
169
170
171/**
172 * reconnects to
173 * @param host new server address
174 * @param port new port number
175 *
176 * this terminates the current connection and starts a new connection to the new server
177 */
178void UdpSocket::reconnectToServerSoft( std::string host, int port)
179{}
180
181
182/**
183 * send one packet to other host
184 * @param data pointer to data which will be sent
185 * @param length length of data
186 * @return true on success
187 */
188bool UdpSocket::writePacket( byte * data, int length )
189{
190  byte * buf = new byte[length+1];
191  if ( length > 0 )
192    memcpy( buf+1, data, length );
193  buf[0] = this->randomByte;
194  return writeRawPacket( buf, length+1 );
195}
196
197/**
198 * recieve one packet from another host
199 * @param data pointer to buffer to copy data into
200 * @param maxLength maximal length of buffer
201 * @return less than 0 on error, number bytes read else
202 */
203int UdpSocket::readPacket( byte * data, int maxLength )
204{
205  assert( maxLength <= UDP_PACKET_SIZE );
206
207  if ( serverSocket )
208  {
209    NetworkPacket networkPacket = serverSocket->getPacket( this->userId );
210
211    byte udpCmd = 0;
212
213    if ( networkPacket.length > 0 )
214    {
215      assert( maxLength > networkPacket.length );
216
217      memcpy( data, networkPacket.data+1, networkPacket.length-1 );
218      udpCmd = networkPacket.data[0];
219    }
220    else
221      return 0;
222
223    if ( !checkRandomByte( networkPacket.data[0] ) )
224      return 0;
225
226    if ( networkPacket.data )
227    {
228      free( networkPacket.data );
229      networkPacket.data = NULL;
230    }
231
232    if ( !checkUdpCmd( udpCmd ) )
233      return 0;
234
235    return networkPacket.length-1;
236  }
237  else
238  {
239    int numrecv = SDLNet_UDP_Recv( socket, packet);
240
241    byte udpCmd = 0;
242
243    if ( numrecv > 0)
244    {
245      assert( packet->len <= maxLength );
246
247      if ( packet->len > 0 )
248        memcpy( data, packet->data+1, packet->len-1 );
249      else
250        return 0;
251
252      if ( !checkRandomByte( packet->data[0] ) )
253        return 0;
254
255      if ( !checkUdpCmd( udpCmd ) )
256        return 0;
257
258      return packet->len-1;
259    }
260    else if ( numrecv < 0 )
261    {
262      PRINTF(1)("SDLNet_UDP_Recv: %s\n", SDLNet_GetError());
263      bOk = false;
264      return -1;
265    }
266    else
267    {
268      return 0;
269    }
270  }
271
272  return 0;
273}
274
275bool UdpSocket::writeRawPacket( byte * data, int length )
276{
277  if ( serverSocket )
278  {
279    NetworkPacket networkPacket;
280    networkPacket.length = length;
281    networkPacket.data = data;
282    if ( !serverSocket->sendPacket( networkPacket, this->userId ) )
283    {
284      bOk = false;
285      return false;
286    }
287    else
288      return true;
289  }
290  else
291  {
292    assert( length <= packet->maxlen );
293
294    memcpy( packet->data, data, length );
295    packet->len = length;
296
297    if ( socket && SDLNet_UDP_Send( socket, 1, packet) == 0 )
298    {
299      PRINTF(1)("SDLNet_UDP_Send: %s\n", SDLNet_GetError());
300      bOk = false;
301      return false;
302    }
303
304    return true;
305  }
306}
307
308bool UdpSocket::checkUdpCmd( byte udpCmd )
309{
310  if ( udpCmd & UDPCMD_DISCONNECT )
311  {
312    this->disconnectServer();
313    PRINTF(0)("received disconnect byte\n");
314    return false;
315  }
316
317  if ( !this->serverSocket && ( udpCmd & UDPCMD_INVALIDRNDBYTE ) )
318  {
319    PRINTF(0)("received invlid random number byte\n");
320    byte cmd = this->randomByte | UDPCMD_DISCONNECT;
321    writeRawPacket( &cmd, 1 );
322    this->randomByte = generateNewRandomByte();
323    return false;
324  }
325
326  return true;
327}
328
329byte UdpSocket::generateNewRandomByte( )
330{
331  srand( SDL_GetTicks() );
332  byte res = ( rand() & 0xFC );
333
334  PRINTF(0)("generated random byte: %x\n", res);
335
336  return res;
337}
338
339bool UdpSocket::checkRandomByte( byte rndByte )
340{
341  if ( ( rndByte & 0xFC ) == this->randomByte )
342  {
343    return true;
344  }
345  else
346  {
347    PRINTF(2)("wrong random byte: %x\n", ( rndByte & 0xFC ));
348    return false;
349  }
350}
351
352
353
Note: See TracBrowser for help on using the repository browser.