Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/network/udp_socket.cc @ 9235

Last change on this file since 9235 was 8802, checked in by patrick, 18 years ago

merged the network branche back to trunk

File size: 6.4 KB
RevLine 
[7540]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"
[8362]18#include "debug.h"
[7540]19
20
21void UdpSocket::init( )
22{
[7541]23  //TODO setClassId
[7540]24  this->serverSocket = NULL;
25  this->socket = NULL;
26  this->packet = NULL;
[8802]27  this->randomByte = 0;
[7540]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 );
[8362]40
[7613]41  assert( this->packet );
[8362]42
[7613]43  memset( packet->data, 0, UDP_PACKET_SIZE );
44  PRINTF(0)("PACKET DATA: %x\n", packet->data);
[8362]45
[7540]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 );
[8362]56
[7540]57  if ( !packet )
58  {
59    PRINTF(1)("SDLNet_AllocPacket: %s\n", SDLNet_GetError());
[8362]60
[7540]61    assert( false );
62    bOk = false;
63  }
[8362]64
[7540]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 */
[8802]73UdpSocket::UdpSocket( UdpServerSocket * serverSocket, IPaddress ip, int userId, byte randomByte )
[7540]74{
75  this->init();
76  this->serverSocket = serverSocket;
[7556]77  this->userId = userId;
[8802]78  this->randomByte = randomByte;
[7540]79}
80
81/**
82 * destructor
83 */
[7556]84UdpSocket::~UdpSocket( )
[7540]85{
[8228]86  this->disconnectServer();
[8362]87
[7540]88  if ( serverSocket )
89    serverSocket->removeUser( userId );
[8228]90
[7556]91  if ( this->packet )
92    SDLNet_FreePacket( this->packet );
[8362]93
[7556]94  if ( socket )
95    SDLNet_UDP_Close( socket );
[7540]96}
97
98/**
99 * connect to server
100 * @param host host name
101 * @param port port number
102 */
103void UdpSocket::connectToServer( std::string host, int port )
104{
105  assert( serverSocket == NULL );
[8362]106
[7540]107  IPaddress ip;
[8802]108 
109  this->randomByte = generateNewRandomByte();
[8362]110
[7570]111  PRINTF(0)("connect to server %s on port %d\n", host.c_str(), port);
[8362]112
[7540]113  if ( SDLNet_ResolveHost( &ip, host.c_str(), port ) != 0 )
114  {
115    PRINTF(1)("SDLNet_ResolveHost: %s\n", SDLNet_GetError() );
116    bOk = false;
117    return;
118  }
[8362]119
[7540]120  socket = SDLNet_UDP_Open(0);
121  if ( !socket )
122  {
123    PRINTF(1)("SDLNet_UDP_Open: %s\n", SDLNet_GetError() );
124    bOk = false;
125    return;
126  }
[8362]127
[7553]128  int channel = SDLNet_UDP_Bind(socket, 1, &ip);
[8362]129  if ( channel == -1 )
[7540]130  {
[7872]131    PRINTF(1)("SDLNet_UDP_Bind: %s\n", SDLNet_GetError());
[7540]132    bOk = false;
133    return;
134  }
135}
136
137/**
138 * disconnect from server
139 */
140void UdpSocket::disconnectServer( )
141{
[8228]142  PRINTF(0)("disconnect\n");
[8802]143  byte cmd = this->randomByte | UDPCMD_DISCONNECT;
144  writeRawPacket( &cmd, 1 );
[7540]145  SDLNet_UDP_Unbind( socket, -1 );
146  SDLNet_UDP_Close( socket );
[7565]147  bOk = false;
[7540]148  socket = NULL;
149}
150
151/**
152 * send one packet to other host
153 * @param data pointer to data which will be sent
154 * @param length length of data
155 * @return true on success
156 */
157bool UdpSocket::writePacket( byte * data, int length )
158{
[8802]159  byte * buf = new byte[length+1];
160  if ( length > 0 )
161    memcpy( buf+1, data, length );
162  buf[0] = this->randomByte;
163  return writeRawPacket( buf, length+1 );
[7540]164}
165
166/**
167 * recieve one packet from another host
168 * @param data pointer to buffer to copy data into
169 * @param maxLength maximal length of buffer
170 * @return less than 0 on error, number bytes read else
171 */
172int UdpSocket::readPacket( byte * data, int maxLength )
173{
[7565]174  assert( maxLength <= UDP_PACKET_SIZE );
[8362]175
[7540]176  if ( serverSocket )
177  {
178    NetworkPacket networkPacket = serverSocket->getPacket( this->userId );
[8362]179
[8802]180    byte udpCmd = 0;
181   
[7540]182    if ( networkPacket.length > 0 )
183    {
184      assert( maxLength > networkPacket.length );
[8362]185
[8802]186      memcpy( data, networkPacket.data+1, networkPacket.length-1 );
187      udpCmd = networkPacket.data[0];
[7540]188    }
[8802]189    else
190      return 0;
191     
192    if ( !checkRandomByte( networkPacket.data[0] ) )
193      return 0;
[8362]194
[7540]195    if ( networkPacket.data )
196    {
[7556]197      free( networkPacket.data );
[7540]198      networkPacket.data = NULL;
199    }
[8802]200   
201    if ( !checkUdpCmd( udpCmd ) )
202      return 0;
[8362]203
[8802]204    return networkPacket.length-1;
[7540]205  }
206  else
207  {
208    int numrecv = SDLNet_UDP_Recv( socket, packet);
[8802]209   
210    byte udpCmd = 0;
211
[8362]212    if ( numrecv > 0)
[7540]213    {
214      assert( packet->len <= maxLength );
[8362]215
[8802]216      if ( packet->len > 0 )
217        memcpy( data, packet->data+1, packet->len-1 );
218      else
[8228]219        return 0;
[8802]220           
221      if ( !checkRandomByte( packet->data[0] ) )
222        return 0;
223             
224      if ( !checkUdpCmd( udpCmd ) )
225        return 0;
[8362]226
[8802]227      return packet->len-1;
[7540]228    }
229    else if ( numrecv < 0 )
230    {
231      PRINTF(1)("SDLNet_UDP_Recv: %s\n", SDLNet_GetError());
232      bOk = false;
233      return -1;
234    }
235    else
236    {
237      return 0;
238    }
239  }
[8362]240
[7540]241  return 0;
242}
243
[8802]244bool UdpSocket::writeRawPacket( byte * data, int length )
245{
246  if ( serverSocket )
247  {
248    NetworkPacket networkPacket;
249    networkPacket.length = length;
250    networkPacket.data = data;
251    if ( !serverSocket->sendPacket( networkPacket, this->userId ) )
252    {
253      bOk = false;
254      return false;
255    }
256    else
257      return true;
258  }
259  else
260  {
261    assert( length <= packet->maxlen );
[7540]262
[8802]263    memcpy( packet->data, data, length );
264    packet->len = length;
[7540]265
[8802]266    if ( socket && SDLNet_UDP_Send( socket, 1, packet) == 0 )
267    {
268      PRINTF(1)("SDLNet_UDP_Send: %s\n", SDLNet_GetError());
269      bOk = false;
270      return false;
271    }
272
273    return true;
274  }
275}
276
277bool UdpSocket::checkUdpCmd( byte udpCmd )
278{
279  if ( udpCmd & UDPCMD_DISCONNECT )
280  {
281    this->disconnectServer();
282    PRINTF(0)("received disconnect byte\n");
283    return false;
284  }
285 
286  if ( !this->serverSocket && ( udpCmd & UDPCMD_INVALIDRNDBYTE ) )
287  {
288    PRINTF(0)("received invlid random number byte\n");
289    byte cmd = this->randomByte | UDPCMD_DISCONNECT;
290    writeRawPacket( &cmd, 1 );
291    this->randomByte = generateNewRandomByte();
292    return false;
293  }
294 
295  return true;
296}
297
298byte UdpSocket::generateNewRandomByte( )
299{
300  srand( SDL_GetTicks() );
301  byte res = ( rand() & 0xFC );
302 
303  PRINTF(0)("generated random byte: %x\n", res);
304 
305  return res;
306}
307
308bool UdpSocket::checkRandomByte( byte rndByte )
309{
310  if ( ( rndByte & 0xFC ) == this->randomByte )
311  {
312    return true;
313  }
314  else
315  {
316    PRINTF(2)("wrong random byte: %x\n", ( rndByte & 0xFC ));
317    return false;
318  }
319}
320
321
322
Note: See TracBrowser for help on using the repository browser.