Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

fixed some bugs in udpSockets. subprojects/network should work now

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