1 /* 2 * common/AckManager.hpp 3 * 4 * This file is part of Leges Motus, a networked, 2D shooter set in zero gravity. 5 * 6 * Copyright 2009-2010 Andrew Ayer, Nathan Partlan, Jeffrey Pfau 7 * 8 * Leges Motus is free and open source software. You may redistribute it and/or 9 * modify it under the terms of version 2, or (at your option) version 3, of the 10 * GNU General Public License (GPL), as published by the Free Software Foundation. 11 * 12 * Leges Motus is distributed in the hope that it will be useful, but WITHOUT ANY 13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 14 * PARTICULAR PURPOSE. See the full text of the GNU General Public License for 15 * further detail. 16 * 17 * For a full copy of the GNU General Public License, please see the COPYING file 18 * in the root of the source code tree. You may also retrieve a copy from 19 * <http://www.gnu.org/licenses/gpl-2.0.txt>, or request a copy by writing to the 20 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 21 * 02111-1307 USA 22 * 23 */ 24 25 #ifndef LM_COMMON_ACKMANAGER_HPP 26 #define LM_COMMON_ACKMANAGER_HPP 27 28 #include <string> 29 #include <list> 30 #include <map> 31 #include <set> 32 #include <stdint.h> 33 #include "IPAddress.hpp" 34 #include "PacketHeader.hpp" 35 36 namespace LM { 37 class PacketWriter; 38 class CommonNetwork; 39 40 class AckManager { 41 private: 42 // Parameters controlling ACKs 43 enum { 44 ACK_TIME = 500, 45 RETRIES = 10 46 }; 47 48 // This class represents a packet which has been sent (possibly to multiple recipients), and is awaiting ACKs 49 // Note that when the packet is sent to multiple recipients, all recipients receive the same packet data, but 50 // each recipient is sent a different packet header. That's why the packet header is stored in the recipients map. 51 class SentPacket { 52 private: 53 uint64_t send_time; // When was it sent? 54 std::map<IPAddress, PacketHeader> recipients; // Who was it sent to? (and with what header?) 55 std::string packet_data; // What it was 56 int tries_left; // How many more times to try sending it 57 58 // Use this constructor to construct a broadcast packet. 59 // Then call add_recipient() to add the peers to which it was sent. 60 explicit SentPacket(const std::string& packet_data); 61 62 // Use this function to construct a unicast packet 63 // It's just shorthand for SentPacket(data) followed by a call to add_recipient(peer_addr, header) 64 SentPacket(const IPAddress& peer_addr, const PacketHeader& header, const std::string& data); 65 66 // Add a recipient 67 void add_recipient(const IPAddress&, const PacketHeader&); 68 69 // Call when an ACK is received for this packet for the given recipient 70 // It will remove the recipient from this SentPacket 71 void ack(const IPAddress& peer); 72 73 uint64_t time_since_send() const; // How long since packet was sent? 74 uint64_t time_until_resend() const; // How long until we should try resending? 75 76 void reset_send_time(); // Call when the packet has been resent 77 78 // When has_recipients() returns false, this SentPacket should be removed 79 // from the AckManager because all its recipients have received the packet OK has_recipients() const80 bool has_recipients() const { return !recipients.empty(); } 81 82 friend class AckManager; 83 }; 84 friend class SentPacket; 85 86 typedef std::list<SentPacket> Queue; 87 typedef std::map<std::pair<IPAddress, uint64_t>, Queue::iterator> Map; 88 89 // Packets are added to this queue in the order that they are sent 90 Queue m_packets; 91 // The map allows quick lookup of a packet by IP address and sequence number 92 Map m_packets_by_id; 93 94 public: 95 void clear(); 96 void clear_peer(const IPAddress& peer); // Remove all packets for this peer from the ACK manager 97 98 typedef Queue::iterator PacketHandle; 99 100 // add_packet adds a unicast packet to the AckManager 101 void add_packet(const IPAddress& peer_addr, const PacketHeader& header, const std::string& data); 102 103 // Add_broadcast_packet adds a broadcast packet to the AckManager 104 // It returns an opaque PacketHandle object. 105 // Add each recipient of the broadcast packet by calling add_broadcast_recipient with the PacketHandle object. 106 PacketHandle add_broadcast_packet(const std::string& data); 107 void add_broadcast_recipient(PacketHandle, const IPAddress& peer_addr, const PacketHeader& header); 108 109 // Call ack() when an ACK is received from the given peer for the given sequence number 110 void ack(const IPAddress& peer_addr, uint64_t sequence_no); 111 112 // after time_until_resend() milliseconds elapses, call resend() to resend the packets 113 uint64_t time_until_resend() const; 114 void resend(CommonNetwork& network); 115 116 // if has_packets() returns false, there's no need to periodically call resend() has_packets() const117 bool has_packets() const { return !m_packets.empty(); } 118 }; 119 } 120 121 #endif 122