X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fconnection.cpp;h=42262846fbb789806071adba7ff4194c1d1c7f4c;hb=b38afc9311e235d2b90d61dbbcf1a18e549073a7;hp=5bf47f13c2b861bd09d392761fa384c86568c77e;hpb=ed772da0cce100be856fb1c3bbce949e333543fb;p=dragonfireclient.git diff --git a/src/connection.cpp b/src/connection.cpp index 5bf47f13c..42262846f 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -1,18 +1,18 @@ /* -Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola 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. */ @@ -22,10 +22,23 @@ with this program; if not, write to the Free Software Foundation, Inc., #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) { @@ -63,19 +76,20 @@ SharedBuffer makeOriginalPacket( return b; } -core::list > makeSplitPacket( +std::list > makeSplitPacket( SharedBuffer data, u32 chunksize_max, u16 seqnum) { // Chunk packets, containing the TYPE_SPLIT header - core::list > chunks; + std::list > 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) @@ -93,16 +107,15 @@ core::list > makeSplitPacket( 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 >::Iterator i = chunks.begin(); - for(; i != chunks.end(); i++) + for(std::list >::iterator i = chunks.begin(); + i != chunks.end(); ++i) { // Write chunk_count writeU16(&((*i)[3]), chunk_count); @@ -111,13 +124,13 @@ core::list > makeSplitPacket( return chunks; } -core::list > makeAutoSplitPacket( +std::list > makeAutoSplitPacket( SharedBuffer data, u32 chunksize_max, u16 &split_seqnum) { u32 original_header_size = 1; - core::list > list; + std::list > list; if(data.getSize() + original_header_size > chunksize_max) { list = makeSplitPacket(data, chunksize_max, split_seqnum); @@ -157,11 +170,13 @@ SharedBuffer makeReliablePacket( ReliablePacketBuffer */ +ReliablePacketBuffer::ReliablePacketBuffer(): m_list_size(0) {} + void ReliablePacketBuffer::print() { - core::list::Iterator i; - i = m_list.begin(); - for(; i != m_list.end(); i++) + for(std::list::iterator i = m_list.begin(); + i != m_list.end(); + ++i) { u16 s = readU16(&(i->data[BASE_HEADER_SIZE+1])); dout_con<::Iterator i; - i = m_list.begin(); - for(; i != m_list.end(); i++) + std::list::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="<::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) @@ -218,6 +233,7 @@ BufferedPacket ReliablePacketBuffer::popSeqnum(u16 seqnum) } BufferedPacket p = *r; m_list.erase(r); + --m_list_size; return p; } void ReliablePacketBuffer::insert(BufferedPacket &p) @@ -227,6 +243,7 @@ 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 @@ -237,12 +254,12 @@ void ReliablePacketBuffer::insert(BufferedPacket &p) return; } // Otherwise find the right place - core::list::Iterator i; - i = m_list.begin(); + std::list::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)){ @@ -258,14 +275,14 @@ void ReliablePacketBuffer::insert(BufferedPacket &p) return; } // Insert before i - m_list.insert_before(i, p); + m_list.insert(i, p); } void ReliablePacketBuffer::incrementTimeouts(float dtime) { - core::list::Iterator i; - i = m_list.begin(); - for(; i != m_list.end(); i++){ + for(std::list::iterator i = m_list.begin(); + i != m_list.end(); ++i) + { i->time += dtime; i->totaltime += dtime; } @@ -273,9 +290,9 @@ void ReliablePacketBuffer::incrementTimeouts(float dtime) void ReliablePacketBuffer::resetTimedOuts(float timeout) { - core::list::Iterator i; - i = m_list.begin(); - for(; i != m_list.end(); i++){ + for(std::list::iterator i = m_list.begin(); + i != m_list.end(); ++i) + { if(i->time >= timeout) i->time = 0.0; } @@ -283,21 +300,20 @@ void ReliablePacketBuffer::resetTimedOuts(float timeout) bool ReliablePacketBuffer::anyTotaltimeReached(float timeout) { - core::list::Iterator i; - i = m_list.begin(); - for(; i != m_list.end(); i++){ + for(std::list::iterator i = m_list.begin(); + i != m_list.end(); ++i) + { if(i->totaltime >= timeout) return true; } return false; } -core::list ReliablePacketBuffer::getTimedOuts(float timeout) +std::list ReliablePacketBuffer::getTimedOuts(float timeout) { - core::list timed_outs; - core::list::Iterator i; - i = m_list.begin(); - for(; i != m_list.end(); i++) + std::list timed_outs; + for(std::list::iterator i = m_list.begin(); + i != m_list.end(); ++i) { if(i->time >= timeout) timed_outs.push_back(*i); @@ -311,11 +327,10 @@ core::list ReliablePacketBuffer::getTimedOuts(float timeout) IncomingSplitBuffer::~IncomingSplitBuffer() { - core::map::Iterator i; - i = m_buf.getIterator(); - for(; i.atEnd() == false; i++) + for(std::map::iterator i = m_buf.begin(); + i != m_buf.end(); ++i) { - delete i.getNode()->getValue(); + delete i->second; } } /* @@ -333,7 +348,7 @@ SharedBuffer IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable) 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; @@ -356,7 +371,7 @@ SharedBuffer IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable) // 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) != NULL) + if(sp->chunks.find(chunk_num) != sp->chunks.end()) return SharedBuffer(); // Cut chunk data out of packet @@ -373,11 +388,10 @@ SharedBuffer IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable) // Calculate total size u32 totalsize = 0; - core::map >::Iterator i; - i = sp->chunks.getIterator(); - for(; i.atEnd() == false; i++) + for(std::map >::iterator i = sp->chunks.begin(); + i != sp->chunks.end(); ++i) { - totalsize += i.getNode()->getValue().getSize(); + totalsize += i->second.getSize(); } SharedBuffer fulldata(totalsize); @@ -394,34 +408,32 @@ SharedBuffer IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable) } // 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 remove_queue; - core::map::Iterator i; - i = m_buf.getIterator(); - for(; i.atEnd() == false; i++) + std::list remove_queue; + for(std::map::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::Iterator j; - j = remove_queue.begin(); - for(; j != remove_queue.end(); j++) + for(std::list::iterator j = remove_queue.begin(); + j != remove_queue.end(); ++j) { dout_con<<"NOTE: Removing timed out unreliable split packet" <= 0.0){ if(rtt < 0.01){ - if(m_max_packets_per_second < 400) + 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; } } @@ -506,10 +521,12 @@ void Peer::reportRTT(float rtt) 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), @@ -521,10 +538,11 @@ Connection::Connection(u32 protocol_id, u32 max_packet_size, float timeout): } 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), @@ -540,12 +558,11 @@ Connection::~Connection() { stop(); // Delete peers - for(core::map::Iterator - j = m_peers.getIterator(); - j.atEnd() == false; j++) + for(std::map::iterator + j = m_peers.begin(); + j != m_peers.end(); ++j) { - Peer *peer = j.getNode()->getValue(); - delete peer; + delete j->second; } } @@ -575,7 +592,7 @@ void * Connection::Thread() runTimeouts(dtime); - while(m_command_queue.size() != 0){ + while(!m_command_queue.empty()){ ConnectionCommand c = m_command_queue.pop_front(); processCommand(c); } @@ -632,18 +649,18 @@ void Connection::processCommand(ConnectionCommand &c) void Connection::send(float dtime) { - for(core::map::Iterator - j = m_peers.getIterator(); - j.atEnd() == false; j++) + for(std::map::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 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) @@ -658,14 +675,14 @@ void Connection::send(float dtime) 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::Iterator - j = m_peers.getIterator(); - j.atEnd() == false; j++) + for(std::map::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) @@ -684,7 +701,7 @@ void Connection::receive() 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 */ @@ -735,11 +752,11 @@ void Connection::receive() Allow only entries that have has_sent_with_id==false. */ - core::map::Iterator j; - j = m_peers.getIterator(); - for(; j.atEnd() == false; j++) + std::map::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) @@ -750,14 +767,14 @@ void Connection::receive() 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 " @@ -781,7 +798,7 @@ void Connection::receive() 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){ @@ -801,7 +818,7 @@ void Connection::receive() // 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; @@ -821,9 +838,9 @@ void Connection::receive() // Go on and process whatever it sent } - core::map::Node *node = m_peers.find(peer_id); + std::map::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 @@ -833,7 +850,7 @@ void Connection::receive() throw InvalidIncomingDataException("Peer not found (possible timeout)"); } - Peer *peer = node->getValue(); + Peer *peer = node->second; // Validate peer address if(peer->address != sender) @@ -879,12 +896,23 @@ void Connection::receive() void Connection::runTimeouts(float dtime) { - core::list timeouted_peers; - core::map::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 timeouted_peers; + for(std::map::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 @@ -906,8 +934,7 @@ void Connection::runTimeouts(float dtime) float resend_timeout = peer->resend_timeout; for(u16 i=0; i timed_outs; - core::list::Iterator j; + std::list timed_outs; Channel *channel = &peer->channels[i]; @@ -938,8 +965,8 @@ void Connection::runTimeouts(float dtime) channel->outgoing_reliables.resetTimedOuts(resend_timeout); - j = timed_outs.begin(); - for(; j != timed_outs.end(); j++) + for(std::list::iterator j = timed_outs.begin(); + j != timed_outs.end(); ++j) { u16 peer_id = readPeerId(*(j->data)); u8 channel = readChannel(*(j->data)); @@ -984,8 +1011,8 @@ void Connection::runTimeouts(float dtime) } // Remove timed out peers - core::list::Iterator i = timeouted_peers.begin(); - for(; i != timeouted_peers.end(); i++) + for(std::list::iterator i = timeouted_peers.begin(); + i != timeouted_peers.end(); ++i) { PrintInfo(derr_con); derr_con<<"RunTimeouts(): Removing peer "<<(*i)<::Node *node = m_peers.find(PEER_ID_SERVER); - if(node != NULL){ + std::map::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; @@ -1044,22 +1071,20 @@ void Connection::disconnect() writeU8(&data[1], CONTROLTYPE_DISCO); // Send to all - core::map::Iterator j; - j = m_peers.getIterator(); - for(; j.atEnd() == false; j++) + for(std::map::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 data, bool reliable) { - core::map::Iterator j; - j = m_peers.getIterator(); - for(; j.atEnd() == false; j++) + for(std::map::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); } } @@ -1080,13 +1105,12 @@ void Connection::send(u16 peer_id, u8 channelnum, if(reliable) chunksize_max -= RELIABLE_HEADER_SIZE; - core::list > originals; + std::list > originals; originals = makeAutoSplitPacket(data, chunksize_max, channel->next_outgoing_split_seqnum); - core::list >::Iterator i; - i = originals.begin(); - for(; i != originals.end(); i++) + for(std::list >::iterator i = originals.begin(); + i != originals.end(); ++i) { SharedBuffer original = *i; @@ -1159,40 +1183,39 @@ void Connection::rawSend(const BufferedPacket &packet) Peer* Connection::getPeer(u16 peer_id) { - core::map::Node *node = m_peers.find(peer_id); + std::map::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::Node *node = m_peers.find(peer_id); + std::map::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 Connection::getPeers() +std::list Connection::getPeers() { - core::list list; - core::map::Iterator j; - j = m_peers.getIterator(); - for(; j.atEnd() == false; j++) + std::list list; + for(std::map::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; @@ -1200,11 +1223,10 @@ core::list Connection::getPeers() bool Connection::getFromBuffers(u16 &peer_id, SharedBuffer &dst) { - core::map::Iterator j; - j = m_peers.getIterator(); - for(; j.atEnd() == false; j++) + for(std::map::iterator j = m_peers.begin(); + j != m_peers.end(); ++j) { - Peer *peer = j.getNode()->getValue(); + Peer *peer = j->second; for(u16 i=0; ichannels[i]; @@ -1224,17 +1246,16 @@ bool Connection::checkIncomingBuffers(Channel *channel, u16 &peer_id, { 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) { @@ -1415,7 +1436,8 @@ SharedBuffer Connection::processPacket(Channel *channel, 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 @@ -1510,7 +1532,7 @@ SharedBuffer Connection::processPacket(Channel *channel, 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]; @@ -1521,7 +1543,7 @@ bool Connection::deletePeer(u16 peer_id, bool timeout) putEvent(e); delete m_peers[peer_id]; - m_peers.remove(peer_id); + m_peers.erase(peer_id); return true; } @@ -1529,7 +1551,7 @@ bool Connection::deletePeer(u16 peer_id, bool timeout) ConnectionEvent Connection::getEvent() { - if(m_event_queue.size() == 0){ + if(m_event_queue.empty()){ ConnectionEvent e; e.type = CONNEVENT_NONE; return e; @@ -1574,8 +1596,8 @@ bool Connection::Connected() if(m_peers.size() != 1) return false; - core::map::Node *node = m_peers.find(PEER_ID_SERVER); - if(node == NULL) + std::map::iterator node = m_peers.find(PEER_ID_SERVER); + if(node == m_peers.end()) return false; if(m_peer_id == PEER_ID_INEXISTENT)