Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

reimplemented NetworkStream

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