Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/terrain.older/src/lib/network/udp_socket.cc @ 10262

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

merged the network branche back to trunk

File size: 6.4 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->serverSocket = serverSocket;
77  this->userId = userId;
78  this->randomByte = randomByte;
79}
80
81/**
82 * destructor
83 */
84UdpSocket::~UdpSocket( )
85{
86  this->disconnectServer();
87
88  if ( serverSocket )
89    serverSocket->removeUser( userId );
90
91  if ( this->packet )
92    SDLNet_FreePacket( this->packet );
93
94  if ( socket )
95    SDLNet_UDP_Close( socket );
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 );
106
107  IPaddress ip;
108 
109  this->randomByte = generateNewRandomByte();
110
111  PRINTF(0)("connect to server %s on port %d\n", host.c_str(), port);
112
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  }
119
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  }
127
128  int channel = SDLNet_UDP_Bind(socket, 1, &ip);
129  if ( channel == -1 )
130  {
131    PRINTF(1)("SDLNet_UDP_Bind: %s\n", SDLNet_GetError());
132    bOk = false;
133    return;
134  }
135}
136
137/**
138 * disconnect from server
139 */
140void UdpSocket::disconnectServer( )
141{
142  PRINTF(0)("disconnect\n");
143  byte cmd = this->randomByte | UDPCMD_DISCONNECT;
144  writeRawPacket( &cmd, 1 );
145  SDLNet_UDP_Unbind( socket, -1 );
146  SDLNet_UDP_Close( socket );
147  bOk = false;
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{
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 );
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{
174  assert( maxLength <= UDP_PACKET_SIZE );
175
176  if ( serverSocket )
177  {
178    NetworkPacket networkPacket = serverSocket->getPacket( this->userId );
179
180    byte udpCmd = 0;
181   
182    if ( networkPacket.length > 0 )
183    {
184      assert( maxLength > networkPacket.length );
185
186      memcpy( data, networkPacket.data+1, networkPacket.length-1 );
187      udpCmd = networkPacket.data[0];
188    }
189    else
190      return 0;
191     
192    if ( !checkRandomByte( networkPacket.data[0] ) )
193      return 0;
194
195    if ( networkPacket.data )
196    {
197      free( networkPacket.data );
198      networkPacket.data = NULL;
199    }
200   
201    if ( !checkUdpCmd( udpCmd ) )
202      return 0;
203
204    return networkPacket.length-1;
205  }
206  else
207  {
208    int numrecv = SDLNet_UDP_Recv( socket, packet);
209   
210    byte udpCmd = 0;
211
212    if ( numrecv > 0)
213    {
214      assert( packet->len <= maxLength );
215
216      if ( packet->len > 0 )
217        memcpy( data, packet->data+1, packet->len-1 );
218      else
219        return 0;
220           
221      if ( !checkRandomByte( packet->data[0] ) )
222        return 0;
223             
224      if ( !checkUdpCmd( udpCmd ) )
225        return 0;
226
227      return packet->len-1;
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  }
240
241  return 0;
242}
243
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 );
262
263    memcpy( packet->data, data, length );
264    packet->len = length;
265
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.