Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

trunk: merged the network branche back to trunk with command: svn merge branches/network trunk -r8150:HEAD

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