/*
-Minetest-c55
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
-You should have received a copy of the GNU General Public License along
+You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "serialization.h"
#include "log.h"
#include "porting.h"
+#include "util/serialize.h"
+#include "util/numeric.h"
+#include "util/string.h"
+#include "settings.h"
namespace con
{
+static u16 readPeerId(u8 *packetdata)
+{
+ return readU16(&packetdata[4]);
+}
+static u8 readChannel(u8 *packetdata)
+{
+ return readU8(&packetdata[6]);
+}
+
BufferedPacket makePacket(Address &address, u8 *data, u32 datasize,
u32 protocol_id, u16 sender_peer_id, u8 channel)
{
return b;
}
-core::list<SharedBuffer<u8> > makeSplitPacket(
+std::list<SharedBuffer<u8> > makeSplitPacket(
SharedBuffer<u8> data,
u32 chunksize_max,
u16 seqnum)
{
// Chunk packets, containing the TYPE_SPLIT header
- core::list<SharedBuffer<u8> > chunks;
+ std::list<SharedBuffer<u8> > chunks;
u32 chunk_header_size = 7;
u32 maximum_data_size = chunksize_max - chunk_header_size;
u32 start = 0;
u32 end = 0;
u32 chunk_num = 0;
+ u16 chunk_count = 0;
do{
end = start + maximum_data_size - 1;
if(end > data.getSize() - 1)
memcpy(&chunk[chunk_header_size], &data[start], payload_size);
chunks.push_back(chunk);
+ chunk_count++;
start = end + 1;
chunk_num++;
}
while(end != data.getSize() - 1);
- u16 chunk_count = chunks.getSize();
-
- core::list<SharedBuffer<u8> >::Iterator i = chunks.begin();
- for(; i != chunks.end(); i++)
+ for(std::list<SharedBuffer<u8> >::iterator i = chunks.begin();
+ i != chunks.end(); ++i)
{
// Write chunk_count
writeU16(&((*i)[3]), chunk_count);
return chunks;
}
-core::list<SharedBuffer<u8> > makeAutoSplitPacket(
+std::list<SharedBuffer<u8> > makeAutoSplitPacket(
SharedBuffer<u8> data,
u32 chunksize_max,
u16 &split_seqnum)
{
u32 original_header_size = 1;
- core::list<SharedBuffer<u8> > list;
+ std::list<SharedBuffer<u8> > list;
if(data.getSize() + original_header_size > chunksize_max)
{
list = makeSplitPacket(data, chunksize_max, split_seqnum);
ReliablePacketBuffer
*/
+ReliablePacketBuffer::ReliablePacketBuffer(): m_list_size(0) {}
+
void ReliablePacketBuffer::print()
{
- core::list<BufferedPacket>::Iterator i;
- i = m_list.begin();
- for(; i != m_list.end(); i++)
+ for(std::list<BufferedPacket>::iterator i = m_list.begin();
+ i != m_list.end();
+ ++i)
{
u16 s = readU16(&(i->data[BASE_HEADER_SIZE+1]));
dout_con<<s<<" ";
}
u32 ReliablePacketBuffer::size()
{
- return m_list.getSize();
+ return m_list_size;
}
RPBSearchResult ReliablePacketBuffer::findPacket(u16 seqnum)
{
- core::list<BufferedPacket>::Iterator i;
- i = m_list.begin();
- for(; i != m_list.end(); i++)
+ std::list<BufferedPacket>::iterator i = m_list.begin();
+ for(; i != m_list.end(); ++i)
{
u16 s = readU16(&(i->data[BASE_HEADER_SIZE+1]));
/*dout_con<<"findPacket(): finding seqnum="<<seqnum
{
return m_list.end();
}
-u16 ReliablePacketBuffer::getFirstSeqnum()
+bool ReliablePacketBuffer::getFirstSeqnum(u16 *result)
{
if(empty())
- throw NotFoundException("Buffer is empty");
+ return false;
BufferedPacket p = *m_list.begin();
- return readU16(&p.data[BASE_HEADER_SIZE+1]);
+ *result = readU16(&p.data[BASE_HEADER_SIZE+1]);
+ return true;
}
BufferedPacket ReliablePacketBuffer::popFirst()
{
if(empty())
throw NotFoundException("Buffer is empty");
BufferedPacket p = *m_list.begin();
- core::list<BufferedPacket>::Iterator i = m_list.begin();
- m_list.erase(i);
+ m_list.erase(m_list.begin());
+ --m_list_size;
return p;
}
BufferedPacket ReliablePacketBuffer::popSeqnum(u16 seqnum)
}
BufferedPacket p = *r;
m_list.erase(r);
+ --m_list_size;
return p;
}
void ReliablePacketBuffer::insert(BufferedPacket &p)
assert(type == TYPE_RELIABLE);
u16 seqnum = readU16(&p.data[BASE_HEADER_SIZE+1]);
+ ++m_list_size;
// Find the right place for the packet and insert it there
// If list is empty, just add it
return;
}
// Otherwise find the right place
- core::list<BufferedPacket>::Iterator i;
- i = m_list.begin();
+ std::list<BufferedPacket>::iterator i = m_list.begin();
// Find the first packet in the list which has a higher seqnum
- for(; i != m_list.end(); i++){
+ for(; i != m_list.end(); ++i){
u16 s = readU16(&(i->data[BASE_HEADER_SIZE+1]));
if(s == seqnum){
+ --m_list_size;
throw AlreadyExistsException("Same seqnum in list");
}
if(seqnum_higher(s, seqnum)){
return;
}
// Insert before i
- m_list.insert_before(i, p);
+ m_list.insert(i, p);
}
void ReliablePacketBuffer::incrementTimeouts(float dtime)
{
- core::list<BufferedPacket>::Iterator i;
- i = m_list.begin();
- for(; i != m_list.end(); i++){
+ for(std::list<BufferedPacket>::iterator i = m_list.begin();
+ i != m_list.end(); ++i)
+ {
i->time += dtime;
i->totaltime += dtime;
}
void ReliablePacketBuffer::resetTimedOuts(float timeout)
{
- core::list<BufferedPacket>::Iterator i;
- i = m_list.begin();
- for(; i != m_list.end(); i++){
+ for(std::list<BufferedPacket>::iterator i = m_list.begin();
+ i != m_list.end(); ++i)
+ {
if(i->time >= timeout)
i->time = 0.0;
}
bool ReliablePacketBuffer::anyTotaltimeReached(float timeout)
{
- core::list<BufferedPacket>::Iterator i;
- i = m_list.begin();
- for(; i != m_list.end(); i++){
+ for(std::list<BufferedPacket>::iterator i = m_list.begin();
+ i != m_list.end(); ++i)
+ {
if(i->totaltime >= timeout)
return true;
}
return false;
}
-core::list<BufferedPacket> ReliablePacketBuffer::getTimedOuts(float timeout)
+std::list<BufferedPacket> ReliablePacketBuffer::getTimedOuts(float timeout)
{
- core::list<BufferedPacket> timed_outs;
- core::list<BufferedPacket>::Iterator i;
- i = m_list.begin();
- for(; i != m_list.end(); i++)
+ std::list<BufferedPacket> timed_outs;
+ for(std::list<BufferedPacket>::iterator i = m_list.begin();
+ i != m_list.end(); ++i)
{
if(i->time >= timeout)
timed_outs.push_back(*i);
IncomingSplitBuffer::~IncomingSplitBuffer()
{
- core::map<u16, IncomingSplitPacket*>::Iterator i;
- i = m_buf.getIterator();
- for(; i.atEnd() == false; i++)
+ for(std::map<u16, IncomingSplitPacket*>::iterator i = m_buf.begin();
+ i != m_buf.end(); ++i)
{
- delete i.getNode()->getValue();
+ delete i->second;
}
}
/*
u16 chunk_num = readU16(&p.data[BASE_HEADER_SIZE+5]);
// Add if doesn't exist
- if(m_buf.find(seqnum) == NULL)
+ if(m_buf.find(seqnum) == m_buf.end())
{
IncomingSplitPacket *sp = new IncomingSplitPacket();
sp->chunk_count = chunk_count;
<<" != sp->reliable="<<sp->reliable
<<std::endl;
- // If chunk already exists, cancel
- if(sp->chunks.find(chunk_num) != NULL)
- throw AlreadyExistsException("Chunk already in buffer");
+ // If chunk already exists, ignore it.
+ // Sometimes two identical packets may arrive when there is network
+ // lag and the server re-sends stuff.
+ if(sp->chunks.find(chunk_num) != sp->chunks.end())
+ return SharedBuffer<u8>();
// Cut chunk data out of packet
u32 chunkdatasize = p.data.getSize() - headersize;
// Calculate total size
u32 totalsize = 0;
- core::map<u16, SharedBuffer<u8> >::Iterator i;
- i = sp->chunks.getIterator();
- for(; i.atEnd() == false; i++)
+ for(std::map<u16, SharedBuffer<u8> >::iterator i = sp->chunks.begin();
+ i != sp->chunks.end(); ++i)
{
- totalsize += i.getNode()->getValue().getSize();
+ totalsize += i->second.getSize();
}
SharedBuffer<u8> fulldata(totalsize);
}
// Remove sp from buffer
- m_buf.remove(seqnum);
+ m_buf.erase(seqnum);
delete sp;
return fulldata;
}
void IncomingSplitBuffer::removeUnreliableTimedOuts(float dtime, float timeout)
{
- core::list<u16> remove_queue;
- core::map<u16, IncomingSplitPacket*>::Iterator i;
- i = m_buf.getIterator();
- for(; i.atEnd() == false; i++)
+ std::list<u16> remove_queue;
+ for(std::map<u16, IncomingSplitPacket*>::iterator i = m_buf.begin();
+ i != m_buf.end(); ++i)
{
- IncomingSplitPacket *p = i.getNode()->getValue();
+ IncomingSplitPacket *p = i->second;
// Reliable ones are not removed by timeout
if(p->reliable == true)
continue;
p->time += dtime;
if(p->time >= timeout)
- remove_queue.push_back(i.getNode()->getKey());
+ remove_queue.push_back(i->first);
}
- core::list<u16>::Iterator j;
- j = remove_queue.begin();
- for(; j != remove_queue.end(); j++)
+ for(std::list<u16>::iterator j = remove_queue.begin();
+ j != remove_queue.end(); ++j)
{
dout_con<<"NOTE: Removing timed out unreliable split packet"
<<std::endl;
delete m_buf[*j];
- m_buf.remove(*j);
+ m_buf.erase(*j);
}
}
m_sendtime_accu(0),
m_max_packets_per_second(10),
m_num_sent(0),
- m_max_num_sent(0)
+ m_max_num_sent(0),
+ congestion_control_aim_rtt(0.2),
+ congestion_control_max_rate(400),
+ congestion_control_min_rate(10)
{
}
Peer::~Peer()
{
if(rtt >= 0.0){
if(rtt < 0.01){
- if(m_max_packets_per_second < 100)
+ if(m_max_packets_per_second < congestion_control_max_rate)
m_max_packets_per_second += 10;
- } else if(rtt < 0.2){
- if(m_max_packets_per_second < 100)
+ } else if(rtt < congestion_control_aim_rtt){
+ if(m_max_packets_per_second < congestion_control_max_rate)
m_max_packets_per_second += 2;
} else {
m_max_packets_per_second *= 0.8;
- if(m_max_packets_per_second < 10)
- m_max_packets_per_second = 10;
+ if(m_max_packets_per_second < congestion_control_min_rate)
+ m_max_packets_per_second = congestion_control_min_rate;
}
}
Connection
*/
-Connection::Connection(u32 protocol_id, u32 max_packet_size, float timeout):
+Connection::Connection(u32 protocol_id, u32 max_packet_size, float timeout,
+ bool ipv6):
m_protocol_id(protocol_id),
m_max_packet_size(max_packet_size),
m_timeout(timeout),
+ m_socket(ipv6),
m_peer_id(0),
m_bc_peerhandler(NULL),
m_bc_receive_timeout(0),
}
Connection::Connection(u32 protocol_id, u32 max_packet_size, float timeout,
- PeerHandler *peerhandler):
+ bool ipv6, PeerHandler *peerhandler):
m_protocol_id(protocol_id),
m_max_packet_size(max_packet_size),
m_timeout(timeout),
+ m_socket(ipv6),
m_peer_id(0),
m_bc_peerhandler(peerhandler),
m_bc_receive_timeout(0),
Connection::~Connection()
{
stop();
+ // Delete peers
+ for(std::map<u16, Peer*>::iterator
+ j = m_peers.begin();
+ j != m_peers.end(); ++j)
+ {
+ delete j->second;
+ }
}
/* Internal stuff */
runTimeouts(dtime);
- while(m_command_queue.size() != 0){
+ while(!m_command_queue.empty()){
ConnectionCommand c = m_command_queue.pop_front();
processCommand(c);
}
void Connection::send(float dtime)
{
- for(core::map<u16, Peer*>::Iterator
- j = m_peers.getIterator();
- j.atEnd() == false; j++)
+ for(std::map<u16, Peer*>::iterator
+ j = m_peers.begin();
+ j != m_peers.end(); ++j)
{
- Peer *peer = j.getNode()->getValue();
+ Peer *peer = j->second;
peer->m_sendtime_accu += dtime;
peer->m_num_sent = 0;
peer->m_max_num_sent = peer->m_sendtime_accu *
peer->m_max_packets_per_second;
}
Queue<OutgoingPacket> postponed_packets;
- while(m_outgoing_queue.size() != 0){
+ while(!m_outgoing_queue.empty()){
OutgoingPacket packet = m_outgoing_queue.pop_front();
Peer *peer = getPeerNoEx(packet.peer_id);
if(!peer)
postponed_packets.push_back(packet);
}
}
- while(postponed_packets.size() != 0){
+ while(!postponed_packets.empty()){
m_outgoing_queue.push_back(postponed_packets.pop_front());
}
- for(core::map<u16, Peer*>::Iterator
- j = m_peers.getIterator();
- j.atEnd() == false; j++)
+ for(std::map<u16, Peer*>::iterator
+ j = m_peers.begin();
+ j != m_peers.end(); ++j)
{
- Peer *peer = j.getNode()->getValue();
+ Peer *peer = j->second;
peer->m_sendtime_accu -= (float)peer->m_num_sent /
peer->m_max_packets_per_second;
if(peer->m_sendtime_accu > 10. / peer->m_max_packets_per_second)
// Receive packets from the network and buffers and create ConnectionEvents
void Connection::receive()
{
- u32 datasize = 100000;
+ u32 datasize = m_max_packet_size * 2; // Double it just to be safe
// TODO: We can not know how many layers of header there are.
// For now, just assume there are no other than the base headers.
u32 packet_maxsize = datasize + BASE_HEADER_SIZE;
- Buffer<u8> packetdata(packet_maxsize);
+ SharedBuffer<u8> packetdata(packet_maxsize);
bool single_wait_done = false;
- for(;;)
+ for(u32 loop_i=0; loop_i<1000; loop_i++) // Limit in case of DoS
{
try{
/* Check if some buffer has relevant data */
Allow only entries that have has_sent_with_id==false.
*/
- core::map<u16, Peer*>::Iterator j;
- j = m_peers.getIterator();
- for(; j.atEnd() == false; j++)
+ std::map<u16, Peer*>::iterator j;
+ j = m_peers.begin();
+ for(; j != m_peers.end(); ++j)
{
- Peer *peer = j.getNode()->getValue();
+ Peer *peer = j->second;
if(peer->has_sent_with_id)
continue;
if(peer->address == sender)
If no peer was found with the same address and port,
we shall assume it is a new peer and create an entry.
*/
- if(j.atEnd())
+ if(j == m_peers.end())
{
// Pass on to adding the peer
}
// Else: A peer was found.
else
{
- Peer *peer = j.getNode()->getValue();
+ Peer *peer = j->second;
peer_id = peer->id;
PrintInfo(derr_con);
derr_con<<"WARNING: Assuming unknown peer to be "
for(;;)
{
// Check if exists
- if(m_peers.find(peer_id_new) == NULL)
+ if(m_peers.find(peer_id_new) == m_peers.end())
break;
// Check for overflow
if(peer_id_new == 65535){
// Create a peer
Peer *peer = new Peer(peer_id_new, sender);
- m_peers.insert(peer->id, peer);
+ m_peers[peer->id] = peer;
// Create peer addition event
ConnectionEvent e;
// Go on and process whatever it sent
}
- core::map<u16, Peer*>::Node *node = m_peers.find(peer_id);
+ std::map<u16, Peer*>::iterator node = m_peers.find(peer_id);
- if(node == NULL)
+ if(node == m_peers.end())
{
// Peer not found
// This means that the peer id of the sender is not PEER_ID_INEXISTENT
throw InvalidIncomingDataException("Peer not found (possible timeout)");
}
- Peer *peer = node->getValue();
+ Peer *peer = node->second;
// Validate peer address
if(peer->address != sender)
dout_con<<"ProcessPacket returned data of size "
<<resultdata.getSize()<<std::endl;
- if(datasize < resultdata.getSize())
- throw InvalidIncomingDataException
- ("Buffer too small for received data");
-
ConnectionEvent e;
e.dataReceived(peer_id, resultdata);
putEvent(e);
void Connection::runTimeouts(float dtime)
{
- core::list<u16> timeouted_peers;
- core::map<u16, Peer*>::Iterator j;
- j = m_peers.getIterator();
- for(; j.atEnd() == false; j++)
+ float congestion_control_aim_rtt
+ = g_settings->getFloat("congestion_control_aim_rtt");
+ float congestion_control_max_rate
+ = g_settings->getFloat("congestion_control_max_rate");
+ float congestion_control_min_rate
+ = g_settings->getFloat("congestion_control_min_rate");
+
+ std::list<u16> timeouted_peers;
+ for(std::map<u16, Peer*>::iterator j = m_peers.begin();
+ j != m_peers.end(); ++j)
{
- Peer *peer = j.getNode()->getValue();
+ Peer *peer = j->second;
+
+ // Update congestion control values
+ peer->congestion_control_aim_rtt = congestion_control_aim_rtt;
+ peer->congestion_control_max_rate = congestion_control_max_rate;
+ peer->congestion_control_min_rate = congestion_control_min_rate;
/*
Check peer timeout
float resend_timeout = peer->resend_timeout;
for(u16 i=0; i<CHANNEL_COUNT; i++)
{
- core::list<BufferedPacket> timed_outs;
- core::list<BufferedPacket>::Iterator j;
+ std::list<BufferedPacket> timed_outs;
Channel *channel = &peer->channels[i];
channel->outgoing_reliables.resetTimedOuts(resend_timeout);
- j = timed_outs.begin();
- for(; j != timed_outs.end(); j++)
+ for(std::list<BufferedPacket>::iterator j = timed_outs.begin();
+ j != timed_outs.end(); ++j)
{
u16 peer_id = readPeerId(*(j->data));
u8 channel = readChannel(*(j->data));
}
// Remove timed out peers
- core::list<u16>::Iterator i = timeouted_peers.begin();
- for(; i != timeouted_peers.end(); i++)
+ for(std::list<u16>::iterator i = timeouted_peers.begin();
+ i != timeouted_peers.end(); ++i)
{
PrintInfo(derr_con);
derr_con<<"RunTimeouts(): Removing peer "<<(*i)<<std::endl;
void Connection::serve(u16 port)
{
dout_con<<getDesc()<<" serving at port "<<port<<std::endl;
- m_socket.Bind(port);
- m_peer_id = PEER_ID_SERVER;
+ try{
+ m_socket.Bind(port);
+ m_peer_id = PEER_ID_SERVER;
+ }
+ catch(SocketException &e){
+ // Create event
+ ConnectionEvent ce;
+ ce.bindFailed();
+ putEvent(ce);
+ }
}
void Connection::connect(Address address)
dout_con<<getDesc()<<" connecting to "<<address.serializeString()
<<":"<<address.getPort()<<std::endl;
- core::map<u16, Peer*>::Node *node = m_peers.find(PEER_ID_SERVER);
- if(node != NULL){
+ std::map<u16, Peer*>::iterator node = m_peers.find(PEER_ID_SERVER);
+ if(node != m_peers.end()){
throw ConnectionException("Already connected to a server");
}
Peer *peer = new Peer(PEER_ID_SERVER, address);
- m_peers.insert(peer->id, peer);
+ m_peers[peer->id] = peer;
// Create event
ConnectionEvent e;
writeU8(&data[1], CONTROLTYPE_DISCO);
// Send to all
- core::map<u16, Peer*>::Iterator j;
- j = m_peers.getIterator();
- for(; j.atEnd() == false; j++)
+ for(std::map<u16, Peer*>::iterator j = m_peers.begin();
+ j != m_peers.end(); ++j)
{
- Peer *peer = j.getNode()->getValue();
+ Peer *peer = j->second;
rawSendAsPacket(peer->id, 0, data, false);
}
}
void Connection::sendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable)
{
- core::map<u16, Peer*>::Iterator j;
- j = m_peers.getIterator();
- for(; j.atEnd() == false; j++)
+ for(std::map<u16, Peer*>::iterator j = m_peers.begin();
+ j != m_peers.end(); ++j)
{
- Peer *peer = j.getNode()->getValue();
+ Peer *peer = j->second;
send(peer->id, channelnum, data, reliable);
}
}
if(reliable)
chunksize_max -= RELIABLE_HEADER_SIZE;
- core::list<SharedBuffer<u8> > originals;
+ std::list<SharedBuffer<u8> > originals;
originals = makeAutoSplitPacket(data, chunksize_max,
channel->next_outgoing_split_seqnum);
- core::list<SharedBuffer<u8> >::Iterator i;
- i = originals.begin();
- for(; i != originals.end(); i++)
+ for(std::list<SharedBuffer<u8> >::iterator i = originals.begin();
+ i != originals.end(); ++i)
{
SharedBuffer<u8> original = *i;
Peer* Connection::getPeer(u16 peer_id)
{
- core::map<u16, Peer*>::Node *node = m_peers.find(peer_id);
+ std::map<u16, Peer*>::iterator node = m_peers.find(peer_id);
- if(node == NULL){
+ if(node == m_peers.end()){
throw PeerNotFoundException("GetPeer: Peer not found (possible timeout)");
}
// Error checking
- assert(node->getValue()->id == peer_id);
+ assert(node->second->id == peer_id);
- return node->getValue();
+ return node->second;
}
Peer* Connection::getPeerNoEx(u16 peer_id)
{
- core::map<u16, Peer*>::Node *node = m_peers.find(peer_id);
+ std::map<u16, Peer*>::iterator node = m_peers.find(peer_id);
- if(node == NULL){
+ if(node == m_peers.end()){
return NULL;
}
// Error checking
- assert(node->getValue()->id == peer_id);
+ assert(node->second->id == peer_id);
- return node->getValue();
+ return node->second;
}
-core::list<Peer*> Connection::getPeers()
+std::list<Peer*> Connection::getPeers()
{
- core::list<Peer*> list;
- core::map<u16, Peer*>::Iterator j;
- j = m_peers.getIterator();
- for(; j.atEnd() == false; j++)
+ std::list<Peer*> list;
+ for(std::map<u16, Peer*>::iterator j = m_peers.begin();
+ j != m_peers.end(); ++j)
{
- Peer *peer = j.getNode()->getValue();
+ Peer *peer = j->second;
list.push_back(peer);
}
return list;
bool Connection::getFromBuffers(u16 &peer_id, SharedBuffer<u8> &dst)
{
- core::map<u16, Peer*>::Iterator j;
- j = m_peers.getIterator();
- for(; j.atEnd() == false; j++)
+ for(std::map<u16, Peer*>::iterator j = m_peers.begin();
+ j != m_peers.end(); ++j)
{
- Peer *peer = j.getNode()->getValue();
+ Peer *peer = j->second;
for(u16 i=0; i<CHANNEL_COUNT; i++)
{
Channel *channel = &peer->channels[i];
{
u16 firstseqnum = 0;
// Clear old packets from start of buffer
- try{
for(;;){
- firstseqnum = channel->incoming_reliables.getFirstSeqnum();
+ bool found = channel->incoming_reliables.getFirstSeqnum(&firstseqnum);
+ if(!found)
+ break;
if(seqnum_higher(channel->next_incoming_seqnum, firstseqnum))
channel->incoming_reliables.popFirst();
else
break;
}
// This happens if all packets are old
- }catch(con::NotFoundException)
- {}
if(channel->incoming_reliables.empty() == false)
{
else if(type == TYPE_RELIABLE)
{
// Recursive reliable packets not allowed
- assert(reliable == false);
+ if(reliable)
+ throw InvalidIncomingDataException("Found nested reliable packets");
if(packetdata.getSize() < RELIABLE_HEADER_SIZE)
throw InvalidIncomingDataException
bool Connection::deletePeer(u16 peer_id, bool timeout)
{
- if(m_peers.find(peer_id) == NULL)
+ if(m_peers.find(peer_id) == m_peers.end())
return false;
Peer *peer = m_peers[peer_id];
putEvent(e);
delete m_peers[peer_id];
- m_peers.remove(peer_id);
+ m_peers.erase(peer_id);
return true;
}
ConnectionEvent Connection::getEvent()
{
- if(m_event_queue.size() == 0){
+ if(m_event_queue.empty()){
ConnectionEvent e;
e.type = CONNEVENT_NONE;
return e;
{
try{
return m_event_queue.pop_front(timeout_ms);
- } catch(ItemNotFoundException &e){
+ } catch(ItemNotFoundException &ex){
ConnectionEvent e;
e.type = CONNEVENT_NONE;
return e;
if(m_peers.size() != 1)
return false;
- core::map<u16, Peer*>::Node *node = m_peers.find(PEER_ID_SERVER);
- if(node == NULL)
+ std::map<u16, Peer*>::iterator node = m_peers.find(PEER_ID_SERVER);
+ if(node == m_peers.end())
return false;
if(m_peer_id == PEER_ID_INEXISTENT)
putCommand(c);
}
-u32 Connection::Receive(u16 &peer_id, u8 *data, u32 datasize)
+u32 Connection::Receive(u16 &peer_id, SharedBuffer<u8> &data)
{
for(;;){
ConnectionEvent e = waitEvent(m_bc_receive_timeout);
throw NoIncomingDataException("No incoming data");
case CONNEVENT_DATA_RECEIVED:
peer_id = e.peer_id;
- memcpy(data, *e.data, e.data.getSize());
+ data = SharedBuffer<u8>(e.data);
return e.data.getSize();
case CONNEVENT_PEER_ADDED: {
Peer tmp(e.peer_id, e.address);
if(m_bc_peerhandler)
m_bc_peerhandler->deletingPeer(&tmp, e.timeout);
continue; }
+ case CONNEVENT_BIND_FAILED:
+ throw ConnectionBindFailed("Failed to bind socket "
+ "(port already in use?)");
}
}
throw NoIncomingDataException("No incoming data");