1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
#ifndef _REMOTE_CONNECTION
#define _REMOTE_CONNECTION
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio/ip/udp.hpp>
#include <deque>
#include <list>
#include "Connection.h"
#include "System/myTime.h"
namespace netcode {
class Chunk
{
public:
unsigned GetSize() const
{
return data.size() + headerSize;
};
static const unsigned maxSize = 254;
static const unsigned headerSize = 5;
int32_t chunkNumber;
uint8_t chunkSize;
std::vector<uint8_t> data;
};
typedef boost::shared_ptr<Chunk> ChunkPtr;
class Packet
{
public:
static const unsigned headerSize = 5;
Packet(const unsigned char* data, unsigned length);
Packet(int lastContinuous, int nak);
unsigned GetSize() const
{
unsigned size = headerSize + naks.size();
for (std::list<ChunkPtr>::const_iterator it = chunks.begin(); it != chunks.end(); ++it)
size += (*it)->GetSize();
return size;
};
void Serialize(std::vector<uint8_t>& data);
int32_t lastContinuous;
int8_t nakType; // if < 0, we lost -x packets since lastContinuous, if >0, x = size of naks
std::vector<uint8_t> naks;
std::list<ChunkPtr> chunks;
};
/**
How Spring protocolheader looks like (size in bytes):
4 (int): number of packet (continuous)
4 (int): last in order (tell the client we received all packages with packetNumber less or equal)
1 (unsigned char): nak (we missed x packets, starting with firstUnacked)
*/
/**
@brief Communication class over UDP
*/
class UDPConnection : public CConnection
{
public:
UDPConnection(boost::shared_ptr<boost::asio::ip::udp::socket> NetSocket, const boost::asio::ip::udp::endpoint& MyAddr);
UDPConnection(int sourceport, const std::string& address, const unsigned port);
virtual ~UDPConnection();
/**
@brief Send packet to other instance
*/
virtual void SendData(boost::shared_ptr<const RawPacket> data);
virtual bool HasIncomingData() const;
virtual boost::shared_ptr<const RawPacket> Peek(unsigned ahead) const;
/**
@brief use this to recieve ready data
@return a network message encapsulated in a RawPacket,
or NULL if there are no more messages available.
*/
virtual boost::shared_ptr<const RawPacket> GetData();
/**
@brief update internals
Check for unack'd packets, timeout etc.
*/
virtual void Update();
/**
@brief strip and parse header data and add data to waitingPackets
UDPConnection takes the ownership of the packet and will delete it in this func
*/
void ProcessRawPacket(Packet& packet);
/// send all data waiting in char outgoingData[]
virtual void Flush(const bool forced = false);
virtual bool CheckTimeout() const;
virtual std::string Statistics() const;
/// do we have these address?
bool CheckAddress(const boost::asio::ip::udp::endpoint&) const;
std::string GetFullAddress() const;
void SetMTU(unsigned mtu);
private:
void Init();
spring_time lastChunkCreated;
spring_time lastReceiveTime;
spring_time lastSendTime;
typedef boost::ptr_map<int,RawPacket> packetMap;
typedef std::list< boost::shared_ptr<const RawPacket> > packetList;
/// add header to data and send it
void CreateChunk(const unsigned char* data, const unsigned length, const int packetNum);
void SendIfNecessary(bool flushed);
/// address of the other end
boost::asio::ip::udp::endpoint addr;
/// maximum size of packets to send
unsigned mtu;
bool sharedSocket;
///outgoing stuff (pure data without header) waiting to be sended
packetList outgoingData;
/// Newly created and not yet sent
std::deque<ChunkPtr> newChunks;
/// packets the other side didn't ack'ed until now
std::deque<ChunkPtr> unackedChunks;
void AckChunks(int lastAck);
spring_time lastUnackResent;
/// Packets the other side missed
void RequestResend(ChunkPtr);
std::deque<ChunkPtr> resendRequested;
int currentNum;
void SendPacket(Packet& pkt);
/// packets we have received but not yet read
packetMap waitingPackets;
int lastInOrder;
int lastNak;
spring_time lastNakTime;
std::deque< boost::shared_ptr<const RawPacket> > msgQueue;
/** Our socket.
*/
boost::shared_ptr<boost::asio::ip::udp::socket> mySocket;
RawPacket* fragmentBuffer;
// Traffic statistics and stuff //
/// packets that are resent
unsigned resentChunks;
unsigned droppedChunks;
unsigned sentOverhead, recvOverhead;
unsigned sentPackets, recvPackets;
class BandwidthUsage
{
public:
BandwidthUsage();
void UpdateTime(unsigned newTime);
void DataSent(unsigned amount);
float GetAverage() const;
private:
unsigned lastTime;
unsigned trafficSinceLastTime;
float average;
};
BandwidthUsage outgoing;
};
} //namespace netcode
#endif
|