Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7854 was 7854, checked in by rennerc, 18 years ago

added assert

File size: 6.2 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
18
19
20/**
21 * constructor
22 * @param port port to listen on
23 */
24UdpServerSocket::UdpServerSocket( int port ) : ServerSocket( port )
25{
26  packet = SDLNet_AllocPacket( UDP_PACKET_SIZE );
27 
28  if ( !packet )
29  {
30    PRINTF(1)("SDLNet_AllocPacket: %s\n", SDLNet_GetError());
31   
32    assert( false );
33    bOk = false;
34  }
35 
36  memset( packet->data, 0, UDP_PACKET_SIZE );
37  PRINTF(0)("PACKET DATA: %x\n", packet->data);
38 
39  listen( port );
40}
41
42/**
43 * default destructor
44 */
45UdpServerSocket::~UdpServerSocket( )
46{
47  for ( int i = 0; i < 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 socket. note
80 * @return new socket or NULL if no new socket exists
81 */
82NetworkSocket * UdpServerSocket::getNewSocket( void )
83{
84  NetworkSocket * result = NULL;
85 
86  if ( newSocketList.size() > 0 )
87  {
88    result = newSocketList.front();
89 
90    newSocketList.pop_front();
91  }
92 
93  return result;
94}
95
96/**
97 * stop listening on server
98 */
99void UdpServerSocket::close( )
100{
101 
102  for ( int i = 0; i < packetBuffer.size(); i++ )
103    removeUserPackets( i );
104 
105  packetBuffer.clear();
106  userList.clear();
107 
108  SDLNet_UDP_Close( socket );
109  socket = NULL;
110}
111
112/**
113 * clean up users buffer
114 * @param userId users userid
115 */
116void UdpServerSocket::removeUserPackets( int userId )
117{
118  if ( userId >= packetBuffer.size() )
119    return;
120 
121  for ( NetworkPacketList::iterator it = packetBuffer[userId].begin(); it!=packetBuffer[userId].end(); it++ )
122  {
123    if ( it->data )
124    {
125      free( it->data );
126      it->data = NULL;
127    }
128  }
129 
130  packetBuffer[userId].clear();
131}
132
133/**
134 * get next packet for user
135 * @param userId user id
136 * @return recieved packet or packet with length 0 if no packet available
137 */
138NetworkPacket UdpServerSocket::getPacket( int userId )
139{
140  NetworkPacket res;
141  res.data = NULL;
142  res.length = 0;
143 
144  if ( packetBuffer.size() > userId && packetBuffer[userId].size() > 0 )
145  {
146    res.data = packetBuffer[userId].front().data;
147    res.length = packetBuffer[userId].front().length;
148    packetBuffer[userId].pop_front();
149  }
150 
151  return res;
152}
153
154/**
155 * get number of packets recieved for user
156 * @param userId user id
157 * @return number of packets in buffer
158 */
159int UdpServerSocket::getPacketCount( int userId )
160{
161  if ( userId >= packetBuffer.size() )
162    return -1;
163 
164  return packetBuffer[userId].size();
165}
166
167/**
168 * will set user state
169 * @param userId users id
170 * @param ip users host / port
171 */
172void UdpServerSocket::initUser( int userId, IPaddress ip )
173{
174  int channel = SDLNet_UDP_Bind( socket, userId, &ip );
175  if( channel != userId ) 
176  {
177    PRINTF(1)("SDLNet_UDP_Bind: %s\n", SDLNet_GetError());
178    assert(false);
179    return;
180  }
181 
182  if ( userId < packetBuffer.size() )
183    removeUserPackets( userId );
184 
185  if ( packetBuffer.size() <= userId )
186    packetBuffer.resize( userId + 1 );
187 
188  if ( userList.size() <= userId )
189    userList.resize( userId + 1 );
190 
191  userList[ userId ] = ip;
192}
193
194/**
195 * remove user from list
196 * @param userId user id
197 */
198void UdpServerSocket::removeUser( int userId )
199{
200  removeUserPackets( userId );
201 
202  if ( userId >= userList.size() )
203    return;
204 
205  userList[userId].host = 0;
206  userList[userId].port = 0;
207 
208  SDLNet_UDP_Unbind( socket, userId );
209}
210
211/**
212 * send one packet to client associated to userId
213 * @param networkPacket packet to send
214 * @param userId users id
215 * @return true on success
216 */
217bool UdpServerSocket::sendPacket( NetworkPacket networkPacket , int userId )
218{
219  assert( networkPacket.length <= UDP_PACKET_SIZE );
220 
221  memcpy( packet->data, networkPacket.data, networkPacket.length );
222  packet->len = networkPacket.length;
223  packet->channel = -1;
224 
225  if ( SDLNet_UDP_Send( socket, userId, packet ) == 0 )
226  {
227    PRINTF(1)("SDLNet_UDP_Send: %s\n", SDLNet_GetError());
228    return false;
229  }
230 
231  return true;
232}
233
234/**
235 * do periodically things
236 */
237void UdpServerSocket::update( )
238{
239  int res;
240  int newConn = 0;
241 
242  for ( res = SDLNet_UDP_Recv( socket, packet ); res == 1; res = SDLNet_UDP_Recv( socket, packet ) )
243  {
244    int userId;
245    bool isNewConnection = false;
246   
247    for ( userId =0; userId < userList.size(); userId++ )
248      if ( userList[userId].host == packet->address.host && userList[userId].port == packet->address.port )
249        break;
250   
251    if ( userId >= userList.size() )
252    {
253     
254      // first packet of client has size 0. else it is an old one or the first packet was lost
255      assert( packet->len == 0 );
256     
257      newConn++;
258      isNewConnection = true;
259     
260      if ( newConn > MAX_NEW_CONNECTIONS )
261      {
262        PRINTF(2)("Too many new connections. Dropping packet\n");
263        continue;
264      }
265     
266      for ( userId =0; userId < userList.size(); userId++ )
267        if ( userList[userId].host == 0 && userList[userId].port == 0 )
268          break;
269     
270      initUser( userId, packet->address );
271      UdpSocket * sock = new UdpSocket( this, packet->address, userId );
272      newSocketList.push_back( sock );
273      PRINTF(0)("NEW CONNECTION %x\n", packet->address.host );
274    }
275   
276    //add new packet to packetbuffer
277
278    NetworkPacket networkPacket;
279    networkPacket.length = packet->len;
280    if ( packet->len != 0 )
281    {
282      networkPacket.data = (byte*)malloc( packet->len );
283      assert( networkPacket.data );
284    }
285    else
286    {
287      if ( isNewConnection )
288        continue;
289     
290      networkPacket.data = NULL;
291    }
292    memcpy( networkPacket.data, packet->data, packet->len );
293    packetBuffer[userId].push_back( networkPacket );
294
295  }
296 
297  assert( res == 0 );
298}
Note: See TracBrowser for help on using the repository browser.