Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/network/connection_monitor.cc @ 8018

Last change on this file since 8018 was 7954, checked in by patrick, 18 years ago

trunk: merged the network branche back to trunk.

File size: 6.4 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 "connection_monitor.h"
17#include "network_log.h"
18
19#include <debug.h>
20#include <SDL/SDL.h>
21#include <string.h>
22
23/* using namespace std is default, this needs to be here */
24using namespace std;
25
26/**
27 * constructor
28 * @param userId user's id
29 */
30ConnectionMonitor::ConnectionMonitor( int userId )
31{
32  /* set the class id for the base object and add ist to class list*/
33  this->setClassID(CL_CONNECTION_MONITOR, "ConnectionMonitor");
34 
35  this->userId = userId;
36  this->ping = 0;
37  this->incomingUnzippedBandWidth = 0;
38  this->outgoingUnzippedBandWidth = 0;
39  this->incomingZippedBandWidth = 0;
40  this->outgoingZippedBandWidth = 0;
41  this->nIncomingPackets = 0;
42  this->nOutgoingPackets = 0;
43  this->nZIncomingPackets = 0;
44  this->nZOutgoingPackets = 0;
45 
46  this->lastPacketTick = 0;
47  this->lastPrintTick = 0;
48}
49
50/**
51 * deconstructor
52 */
53ConnectionMonitor::~ConnectionMonitor( )
54{
55}
56
57/**
58 * process unzipped outgoing packet
59 * @param data pointer to packet data
60 * @param length length of packet
61 * @param stateId packet's state id
62 */
63void ConnectionMonitor::processUnzippedOutgoingPacket( byte * data, int length, int stateId )
64{
65  int tick = SDL_GetTicks();
66 
67  nOutgoingPackets++;
68 
69  // for ping calculation
70  sentStateTicks[stateId] = tick;
71 
72  // calculate bandwidth
73  outgoingUnzippedPacketHistory[tick] = length;
74  outgoingUnzippedBandWidth = calculateBandWidth( outgoingUnzippedPacketHistory, tick );
75 
76  //NETPRINTF(n)("UNZIPPED UPSTREAM: user: %d bandwidth %f\n", userId, outgoingUnzippedBandWidth );
77 
78  // count zero bytes
79  int nZeroBytes = 0;
80 
81  for ( int i = 0; i < length; i++ )
82    if ( data[i] == '\0' )
83      nZeroBytes++;
84 
85  //NETPRINTF(n)( "ZEROBYTES: %d (%f%%)\n", nZeroBytes, ((float)100)*nZeroBytes/length );
86}
87
88/**
89 * process unzipped incoming packet
90 * @param data pointer to packet data
91 * @param length length of packet
92 * @param stateId packet's state id
93 * @param ackedState state which was acked by this packet
94 */
95void ConnectionMonitor::processUnzippedIncomingPacket( byte * data, int length, int stateId, int ackedState )
96{
97  int tick = SDL_GetTicks();
98 
99  nIncomingPackets++;
100 
101  lastPacketTick = tick;
102 
103  // calculate ping
104  if ( sentStateTicks.find( ackedState ) != sentStateTicks.end() )
105  {
106    ackDelay.push_back( tick - sentStateTicks[ackedState] );
107  }
108 
109  while ( sentStateTicks.begin() != sentStateTicks.end() && sentStateTicks.begin()->first <= ackedState )
110    sentStateTicks.erase( sentStateTicks.begin() );
111     
112  while ( ackDelay.size() > N_PACKETS_FOR_PING )
113    ackDelay.erase( ackDelay.begin() );
114     
115  ping = 0;
116     
117  for ( std::list<int>::iterator it = ackDelay.begin(); it != ackDelay.end(); it++ )
118    ping += *it;
119     
120  if ( ackDelay.size() == 0 )
121    ping = -1;
122  else
123    ping /= ackDelay.size();
124     
125  //NETPRINTF(n)("PING: user: %d ping: %d\n", userId, ping );
126 
127  // calculate bandwidth
128  incomingUnzippedPacketHistory[tick] = length;
129  incomingUnzippedBandWidth = calculateBandWidth( incomingUnzippedPacketHistory, tick );
130 
131  //NETPRINTF(n)("UNZIPPED DOWNSTREAM: user: %d bandwidth %f\n", userId, incomingUnzippedBandWidth );
132 
133}
134
135/**
136 * calculate bandwidth out of packethistory
137 * @param packetHistory packet history
138 * @param tick current tick from SDL_GetTicks
139 * @return bandwidth in bytes/sec
140 */
141float ConnectionMonitor::calculateBandWidth( std::map< int, int > packetHistory, int tick )
142{
143  // delete old packets
144  while ( packetHistory.begin()->first < tick - MSECS_TO_CALC_BWIDTH )
145    packetHistory.erase( packetHistory.begin() );
146 
147  float res = 0.0f;
148 
149  for ( std::map<int,int>::iterator it = packetHistory.begin(); it != packetHistory.end(); it++ )
150  {
151    res += it->second;
152  }
153 
154  if ( packetHistory.size() <= 1 || tick - packetHistory.begin()->first == 0 )
155    res = 0.0f;
156  else
157    res /= (float)((tick - packetHistory.begin()->first)*( 1 + 1/((float)(packetHistory.size()-1)) ));
158 
159  res *= 1000.0f;
160 
161  return res;
162}
163
164
165/**
166 * process zipped outgoing packet
167 * @param data pointer to packet data
168 * @param length length of packet
169 * @param stateId packet's state id
170 */
171void ConnectionMonitor::processZippedOutgoingPacket( byte * data, int length, int stateId )
172{
173  int tick = SDL_GetTicks();
174 
175  nZOutgoingPackets++;
176 
177  // calculate bandwidth
178  outgoingZippedPacketHistory[tick] = length;
179  outgoingZippedBandWidth = calculateBandWidth( outgoingZippedPacketHistory, tick );
180 
181  //NETPRINTF(n)("UPSTREAM: user: %d bandwidth %f nOutgoingPackets %d\n", userId, outgoingZippedBandWidth, nOutgoingPackets );
182
183  if ( lastPrintTick < tick-1000 )
184  {
185    printStatis();
186    lastPrintTick = tick;
187  }
188}
189
190
191/**
192 * process zipped incoming packet
193 * @param data pointer to packet data
194 * @param length length of packet
195 * @param stateId packet's state id
196 * @param ackedState state which was acked by this packet
197 */
198void ConnectionMonitor::processZippedIncomingPacket( byte * data, int length, int stateId, int ackedState )
199{
200  int tick = SDL_GetTicks();
201 
202  nZIncomingPackets++;
203 
204  // calculate bandwidth
205  incomingZippedPacketHistory[tick] = length;
206  incomingZippedBandWidth = calculateBandWidth( incomingZippedPacketHistory, tick );
207 
208  //NETPRINTF(n)("DOWNSTREAM: user: %d bandwidth %f nIncomingPackets %d\n", userId, incomingZippedBandWidth, nIncomingPackets );
209 
210}
211
212
213/**
214 * check if client sent no packets for SECS_TO_TIMEOUT
215 * @return true if last packet recieved \< NOW() - SECS_TO_TIMEOUT
216 */
217bool ConnectionMonitor::hasTimedOut( )
218{
219  if ( lastPacketTick + SECS_TO_TIMEOUT*1000 < SDL_GetTicks() && nIncomingPackets > 0 )
220    return true;
221 
222  if ( nIncomingPackets == 0 && nOutgoingPackets >= NETWORK_FREQUENCY*SECS_TO_TIMEOUT )
223    return true;
224 
225  return false;
226}
227
228
229
230/**
231 * prints bandwith usage, ping and other important things to telnet-console
232 */
233void ConnectionMonitor::printStatis( )
234{
235  NETPRINT(n)("=========NETWORKSTATS FOR USER %d=========\n", userId);
236  NETPRINT(n)("PING = %d\n", ping);
237  NETPRINT(n)("BANDWIDTH: UP: %f (%f) DOWN %f (%f)\n", outgoingZippedBandWidth, outgoingUnzippedBandWidth, incomingZippedBandWidth, incomingUnzippedBandWidth);
238  NETPRINT(n)("==========================================");
239}
240
241
Note: See TracBrowser for help on using the repository browser.