1 /* 2 * This file is part of OpenTTD. 3 * OpenTTD 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, version 2. 4 * OpenTTD 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. 5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. 6 */ 7 8 /** 9 * @file packet.h Basic functions to create, fill and read packets. 10 */ 11 12 #ifndef NETWORK_CORE_PACKET_H 13 #define NETWORK_CORE_PACKET_H 14 15 #include "os_abstraction.h" 16 #include "config.h" 17 #include "core.h" 18 #include "../../string_type.h" 19 #include <functional> 20 #include <limits> 21 22 typedef uint16 PacketSize; ///< Size of the whole packet. 23 typedef uint8 PacketType; ///< Identifier for the packet 24 25 /** 26 * Internal entity of a packet. As everything is sent as a packet, 27 * all network communication will need to call the functions that 28 * populate the packet. 29 * Every packet can be at most a limited number bytes set in the 30 * constructor. Overflowing this limit will give an assertion when 31 * sending (i.e. writing) the packet. Reading past the size of the 32 * packet when receiving will return all 0 values and "" in case of 33 * the string. 34 * 35 * --- Points of attention --- 36 * - all > 1 byte integral values are written in little endian, 37 * unless specified otherwise. 38 * Thus, 0x01234567 would be sent as {0x67, 0x45, 0x23, 0x01}. 39 * - all sent strings are of variable length and terminated by a '\0'. 40 * Thus, the length of the strings is not sent. 41 * - years that are leap years in the 'days since X' to 'date' calculations: 42 * (year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0)) 43 */ 44 struct Packet { 45 private: 46 /** The next packet. Used for queueing packets before sending. */ 47 Packet *next; 48 /** The current read/write position in the packet */ 49 PacketSize pos; 50 /** The buffer of this packet. */ 51 std::vector<byte> buffer; 52 /** The limit for the packet size. */ 53 size_t limit; 54 55 /** Socket we're associated with. */ 56 NetworkSocketHandler *cs; 57 58 public: 59 Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size = sizeof(PacketSize)); 60 Packet(PacketType type, size_t limit = COMPAT_MTU); 61 62 static void AddToQueue(Packet **queue, Packet *packet); 63 static Packet *PopFromQueue(Packet **queue); 64 65 /* Sending/writing of packets */ 66 void PrepareToSend(); 67 68 bool CanWriteToPacket(size_t bytes_to_write); 69 void Send_bool (bool data); 70 void Send_uint8 (uint8 data); 71 void Send_uint16(uint16 data); 72 void Send_uint32(uint32 data); 73 void Send_uint64(uint64 data); 74 void Send_string(const std::string_view data); 75 size_t Send_bytes (const byte *begin, const byte *end); 76 77 /* Reading/receiving of packets */ 78 bool HasPacketSizeData() const; 79 bool ParsePacketSize(); 80 size_t Size() const; 81 void PrepareToRead(); 82 PacketType GetPacketType() const; 83 84 bool CanReadFromPacket(size_t bytes_to_read, bool close_connection = false); 85 bool Recv_bool (); 86 uint8 Recv_uint8 (); 87 uint16 Recv_uint16(); 88 uint32 Recv_uint32(); 89 uint64 Recv_uint64(); 90 std::string Recv_string(size_t length, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); 91 92 size_t RemainingBytesToTransfer() const; 93 94 /** 95 * Transfer data from the packet to the given function. It starts reading at the 96 * position the last transfer stopped. 97 * See Packet::TransferIn for more information about transferring data to functions. 98 * @param transfer_function The function to pass the buffer as second parameter and the 99 * amount to write as third parameter. It returns the amount that 100 * was written or -1 upon errors. 101 * @param limit The maximum amount of bytes to transfer. 102 * @param destination The first parameter of the transfer function. 103 * @param args The fourth and further parameters to the transfer function, if any. 104 * @return The return value of the transfer_function. 105 */ 106 template < 107 typename A = size_t, ///< The type for the amount to be passed, so it can be cast to the right type. 108 typename F, ///< The type of the function. 109 typename D, ///< The type of the destination. 110 typename ... Args> ///< The types of the remaining arguments to the function. TransferOutWithLimitPacket111 ssize_t TransferOutWithLimit(F transfer_function, size_t limit, D destination, Args&& ... args) 112 { 113 size_t amount = std::min(this->RemainingBytesToTransfer(), limit); 114 if (amount == 0) return 0; 115 116 assert(this->pos < this->buffer.size()); 117 assert(this->pos + amount <= this->buffer.size()); 118 /* Making buffer a char means casting a lot in the Recv/Send functions. */ 119 const char *output_buffer = reinterpret_cast<const char*>(this->buffer.data() + this->pos); 120 ssize_t bytes = transfer_function(destination, output_buffer, static_cast<A>(amount), std::forward<Args>(args)...); 121 if (bytes > 0) this->pos += bytes; 122 return bytes; 123 } 124 125 /** 126 * Transfer data from the packet to the given function. It starts reading at the 127 * position the last transfer stopped. 128 * See Packet::TransferIn for more information about transferring data to functions. 129 * @param transfer_function The function to pass the buffer as second parameter and the 130 * amount to write as third parameter. It returns the amount that 131 * was written or -1 upon errors. 132 * @param destination The first parameter of the transfer function. 133 * @param args The fourth and further parameters to the transfer function, if any. 134 * @tparam A The type for the amount to be passed, so it can be cast to the right type. 135 * @tparam F The type of the transfer_function. 136 * @tparam D The type of the destination. 137 * @tparam Args The types of the remaining arguments to the function. 138 * @return The return value of the transfer_function. 139 */ 140 template <typename A = size_t, typename F, typename D, typename ... Args> TransferOutPacket141 ssize_t TransferOut(F transfer_function, D destination, Args&& ... args) 142 { 143 return TransferOutWithLimit<A>(transfer_function, std::numeric_limits<size_t>::max(), destination, std::forward<Args>(args)...); 144 } 145 146 /** 147 * Transfer data from the given function into the packet. It starts writing at the 148 * position the last transfer stopped. 149 * 150 * Examples of functions that can be used to transfer data into a packet are TCP's 151 * recv and UDP's recvfrom functions. They will directly write their data into the 152 * packet without an intermediate buffer. 153 * Examples of functions that can be used to transfer data from a packet are TCP's 154 * send and UDP's sendto functions. They will directly read the data from the packet's 155 * buffer without an intermediate buffer. 156 * These are functions are special in a sense as even though the packet can send or 157 * receive an amount of data, those functions can say they only processed a smaller 158 * amount, so special handling is required to keep the position pointers correct. 159 * Most of these transfer functions are in the form function(source, buffer, amount, ...), 160 * so the template of this function will assume that as the base parameter order. 161 * 162 * This will attempt to write all the remaining bytes into the packet. It updates the 163 * position based on how many bytes were actually written by the called transfer_function. 164 * @param transfer_function The function to pass the buffer as second parameter and the 165 * amount to read as third parameter. It returns the amount that 166 * was read or -1 upon errors. 167 * @param source The first parameter of the transfer function. 168 * @param args The fourth and further parameters to the transfer function, if any. 169 * @tparam A The type for the amount to be passed, so it can be cast to the right type. 170 * @tparam F The type of the transfer_function. 171 * @tparam S The type of the source. 172 * @tparam Args The types of the remaining arguments to the function. 173 * @return The return value of the transfer_function. 174 */ 175 template <typename A = size_t, typename F, typename S, typename ... Args> TransferInPacket176 ssize_t TransferIn(F transfer_function, S source, Args&& ... args) 177 { 178 size_t amount = this->RemainingBytesToTransfer(); 179 if (amount == 0) return 0; 180 181 assert(this->pos < this->buffer.size()); 182 assert(this->pos + amount <= this->buffer.size()); 183 /* Making buffer a char means casting a lot in the Recv/Send functions. */ 184 char *input_buffer = reinterpret_cast<char*>(this->buffer.data() + this->pos); 185 ssize_t bytes = transfer_function(source, input_buffer, static_cast<A>(amount), std::forward<Args>(args)...); 186 if (bytes > 0) this->pos += bytes; 187 return bytes; 188 } 189 }; 190 191 #endif /* NETWORK_CORE_PACKET_H */ 192