Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: merged the new_class_id branche back to the trunk.
merged with command:
svn merge https://svn.orxonox.net/orxonox/branches/new_class_id trunk -r9683:HEAD
no conflicts… puh..

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