Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/proxy/src/lib/network/udp_server_socket.cc @ 9461

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

working on a dual connection server socket

File size: 6.9 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_server_socket.h"
17#include "debug.h"
18
19
20
21/**
22 * constructor
23 * @param port port to listen on
24 */
25UdpServerSocket::UdpServerSocket( int port ) : ServerSocket( port )
26{
27  packet = SDLNet_AllocPacket( UDP_PACKET_SIZE );
28
29  if ( !packet )
30  {
31    PRINTF(1)("SDLNet_AllocPacket: %s\n", SDLNet_GetError());
32
33    assert( false );
34    bOk = false;
35  }
36
37  memset( packet->data, 0, UDP_PACKET_SIZE );
38
39  listen( port );
40}
41
42/**
43 * default destructor
44 */
45UdpServerSocket::~UdpServerSocket( )
46{
47  for ( int i = 0; i < (int)packetBuffer.size(); i++ )
48    removeUserPackets( i );
49
50  if ( packet )
51    SDLNet_FreePacket( packet );
52
53  if ( socket )
54    SDLNet_UDP_Close( socket );
55}
56
57/**
58 * tell udpServerSocket to recieve packets on port
59 * @param port port
60 * @return true on success
61 */
62bool UdpServerSocket::listen( unsigned int port )
63{
64  socket = SDLNet_UDP_Open( port );
65
66  PRINTF(0)("listening on port: %d\n", port);
67
68  if ( !socket )
69  {
70
71    bOk = false;
72    return false;
73  }
74
75  return true;
76}
77
78/**
79 * get newly connected client socket. note
80 * @return new socket or NULL if no new socket exists
81 *
82 *  only clients connect to this socket
83 */
84NetworkSocket * UdpServerSocket::getNewClientSocket( void )
85{
86  NetworkSocket * result = NULL;
87
88  if ( newSocketList.size() > 0 )
89  {
90    result = newSocketList.front();
91
92    newSocketList.pop_front();
93  }
94
95  return result;
96}
97
98
99/**
100 * get newly connected proxy socket. note
101 * @return new socket or NULL if no new socket exists
102 *
103 * only proxy servers connect to this socket
104 */
105NetworkSocket * UdpServerSocket::getNewProxySocket( void )
106{
107  NetworkSocket * result = NULL;
108
109  if ( newSocketList.size() > 0 )
110  {
111    result = newSocketList.front();
112
113    newSocketList.pop_front();
114  }
115
116  return result;
117}
118
119
120
121/**
122 * stop listening on server
123 */
124void UdpServerSocket::close( )
125{
126
127  for ( int i = 0; i < (int)packetBuffer.size(); i++ )
128    removeUserPackets( i );
129
130  packetBuffer.clear();
131  userList.clear();
132
133  SDLNet_UDP_Close( socket );
134  socket = NULL;
135}
136
137/**
138 * clean up users buffer
139 * @param userId users userid
140 */
141void UdpServerSocket::removeUserPackets( int userId )
142{
143  if ( userId >= (int)packetBuffer.size() )
144    return;
145
146  for ( NetworkPacketList::iterator it = packetBuffer[userId].begin(); it!=packetBuffer[userId].end(); it++ )
147  {
148    if ( it->data )
149    {
150      free( it->data );
151      it->data = NULL;
152    }
153  }
154
155  packetBuffer[userId].clear();
156}
157
158/**
159 * get next packet for user
160 * @param userId user id
161 * @return recieved packet or packet with length 0 if no packet available
162 */
163NetworkPacket UdpServerSocket::getPacket( int userId )
164{
165  NetworkPacket res;
166  res.data = NULL;
167  res.length = 0;
168
169  if ( (int)packetBuffer.size() > userId && (int)packetBuffer[userId].size() > 0 )
170  {
171    res.data = packetBuffer[userId].front().data;
172    res.length = packetBuffer[userId].front().length;
173    packetBuffer[userId].pop_front();
174  }
175
176  return res;
177}
178
179/**
180 * get number of packets recieved for user
181 * @param userId user id
182 * @return number of packets in buffer
183 */
184int UdpServerSocket::getPacketCount( int userId )
185{
186  if ( userId >= (int)packetBuffer.size() )
187    return -1;
188
189  return packetBuffer[userId].size();
190}
191
192/**
193 * will set user state
194 * @param userId users id
195 * @param ip users host / port
196 */
197void UdpServerSocket::initUser( int userId, IPaddress ip, byte randomByte )
198{
199  int channel = SDLNet_UDP_Bind( socket, userId, &ip );
200  if( channel != userId )
201  {
202    PRINTF(1)("SDLNet_UDP_Bind: %s\n", SDLNet_GetError());
203    assert(false);
204    return;
205  }
206
207  if ( userId < (int)packetBuffer.size() )
208    removeUserPackets( userId );
209
210  if ( (int)packetBuffer.size() <= userId )
211    packetBuffer.resize( userId + 1 );
212
213  if ( (int)userList.size() <= userId )
214    userList.resize( userId + 1 );
215
216  userList[ userId ].addr = ip;
217  userList[ userId ].randomByte = randomByte;
218}
219
220/**
221 * remove user from list
222 * @param userId user id
223 */
224void UdpServerSocket::removeUser( int userId )
225{
226  removeUserPackets( userId );
227
228  if ( userId >= (int)userList.size() )
229    return;
230
231  userList[userId].addr.host = 0;
232  userList[userId].addr.port = 0;
233
234  SDLNet_UDP_Unbind( socket, userId );
235}
236
237/**
238 * send one packet to client associated to userId
239 * @param networkPacket packet to send
240 * @param userId users id
241 * @return true on success
242 */
243bool UdpServerSocket::sendPacket( NetworkPacket networkPacket , int userId )
244{
245  if ( !socket )
246    return false;
247
248  assert( networkPacket.length <= UDP_PACKET_SIZE );
249
250  memcpy( packet->data, networkPacket.data, networkPacket.length );
251  packet->len = networkPacket.length;
252  packet->channel = -1;
253
254  if ( SDLNet_UDP_Send( socket, userId, packet ) == 0 )
255  {
256    PRINTF(1)("SDLNet_UDP_Send: %s\n", SDLNet_GetError());
257    return false;
258  }
259
260  return true;
261}
262
263/**
264 * do periodically things
265 */
266void UdpServerSocket::update( )
267{
268  int res;
269  int newConn = 0;
270
271  // iterate through all newly received packets and assign them to the users packet buffer
272  for ( res = SDLNet_UDP_Recv( socket, packet ); res == 1; res = SDLNet_UDP_Recv( socket, packet ) )
273  {
274    int userId;
275    bool isNewConnection = false;
276
277    if ( packet->len <= 0 )
278      continue;
279
280    // search the user id this backet belongs to
281    for ( userId = 0; userId < (int)userList.size(); userId++ )
282    {
283      if ( userList[userId].addr.host == packet->address.host &&
284           userList[userId].addr.port == packet->address.port &&
285           userList[userId].randomByte == ( packet->data[0] & 0xFC ) )
286        break;
287    }
288
289    // is it a new packet initializing a new connecion?
290    if ( userId >= (int)userList.size() )
291    {
292      newConn++;
293      isNewConnection = true;
294
295      if ( newConn > MAX_NEW_CONNECTIONS )
296      {
297        PRINTF(2)("Too many new connections. Dropping packet\n");
298        continue;
299      }
300
301      for ( userId =0; userId < (int)userList.size(); userId++ )
302        if ( userList[userId].addr.host == 0 && userList[userId].addr.port == 0 )
303          break;
304
305      initUser( userId, packet->address, packet->data[0] & 0xFC );
306      UdpSocket * sock = new UdpSocket( this, packet->address, userId, packet->data[0] & 0xFC );
307      newSocketList.push_back( sock );
308      PRINTF(0)("NEW CONNECTION %x\n", packet->address.host );
309    }
310
311
312    // add new packet to packetbuffer
313    NetworkPacket networkPacket;
314    networkPacket.length = packet->len;
315    if ( packet->len != 0 )
316    {
317      networkPacket.data = (byte*)malloc( packet->len );
318      assert( networkPacket.data );
319    }
320    else
321    {
322      networkPacket.data = NULL;
323    }
324    memcpy( networkPacket.data, packet->data, packet->len );
325    packetBuffer[userId].push_back( networkPacket );
326  }
327
328  assert( res == 0 );
329}
Note: See TracBrowser for help on using the repository browser.