Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

fixed some bugs

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