Merge branch 'master' into jgrpp
# Conflicts: # src/company_cmd.cpp # src/lang/japanese.txt # src/network/core/config.h # src/network/core/packet.cpp # src/network/core/tcp.cpp # src/network/network_content.cpp # src/network/network_server.cpp # src/network/network_udp.cpp # src/toolbar_gui.cpp # src/vehicle_gui_base.h
This commit is contained in:
@@ -30,8 +30,24 @@ static const uint16 NETWORK_DEFAULT_PORT = 3979; ///< The defau
|
||||
static const uint16 NETWORK_ADMIN_PORT = 3977; ///< The default port for admin network
|
||||
static const uint16 NETWORK_DEFAULT_DEBUGLOG_PORT = 3982; ///< The default port debug-log is sent to (TCP)
|
||||
|
||||
static const uint16 SEND_MTU = 1460; ///< Number of bytes we can pack in a single packet
|
||||
static const uint16 SEND_MTU_SHORT = 1400; ///< Number of bytes we can pack in a single packet (conservative)
|
||||
static const uint16 UDP_MTU = 1460; ///< Number of bytes we can pack in a single UDP packet
|
||||
static const uint16 UDP_MTU_SHORT = 1400; ///< Number of bytes we can pack in a single UDP packet (conservative)
|
||||
/*
|
||||
* Technically a TCP packet could become 64kiB, however the high bit is kept so it becomes possible in the future
|
||||
* to go to (significantly) larger packets if needed. This would entail a strategy such as employed for UTF-8.
|
||||
*
|
||||
* Packets up to 32 KiB have the high bit not set:
|
||||
* 00000000 00000000 0bbbbbbb aaaaaaaa -> aaaaaaaa 0bbbbbbb
|
||||
* Send_uint16(GB(size, 0, 15)
|
||||
*
|
||||
* Packets up to 1 GiB, first uint16 has high bit set so it knows to read a
|
||||
* next uint16 for the remaining bits of the size.
|
||||
* 00dddddd cccccccc bbbbbbbb aaaaaaaa -> cccccccc 10dddddd aaaaaaaa bbbbbbbb
|
||||
* Send_uint16(GB(size, 16, 14) | 0b10 << 14)
|
||||
* Send_uint16(GB(size, 0, 16))
|
||||
*/
|
||||
static const uint16 TCP_MTU = 32767; ///< Number of bytes we can pack in a single TCP packet
|
||||
static const uint16 COMPAT_MTU = 1460; ///< Number of bytes we can pack in a single packet for backward compatibility
|
||||
|
||||
static const byte NETWORK_GAME_ADMIN_VERSION = 1; ///< What version of the admin network do we use?
|
||||
static const byte NETWORK_GAME_INFO_VERSION = 4; ///< What version of game-info do we use?
|
||||
@@ -48,14 +64,14 @@ static const uint NETWORK_PASSWORD_LENGTH = 33; ///< The maxim
|
||||
static const uint NETWORK_CLIENTS_LENGTH = 200; ///< The maximum length for the list of clients that controls a company, in bytes including '\0'
|
||||
static const uint NETWORK_CLIENT_NAME_LENGTH = 25; ///< The maximum length of a client's name, in bytes including '\0'
|
||||
static const uint NETWORK_RCONCOMMAND_LENGTH = 500; ///< The maximum length of a rconsole command, in bytes including '\0'
|
||||
static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = SEND_MTU - 3; ///< The maximum length of a gamescript json string, in bytes including '\0'. Must not be longer than SEND_MTU including header (3 bytes)
|
||||
static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = COMPAT_MTU-3; ///< The maximum length of a gamescript json string, in bytes including '\0'. Must not be longer than COMPAT_MTU including header (3 bytes)
|
||||
static const uint NETWORK_CHAT_LENGTH = 900; ///< The maximum length of a chat message, in bytes including '\0'
|
||||
|
||||
static const uint NETWORK_GRF_NAME_LENGTH = 80; ///< Maximum length of the name of a GRF
|
||||
|
||||
/**
|
||||
* Maximum number of GRFs that can be sent.
|
||||
* This limit is reached when PACKET_UDP_SERVER_RESPONSE reaches the maximum size of SEND_MTU bytes.
|
||||
* This limit is reached when PACKET_UDP_SERVER_RESPONSE reaches the maximum size of UDP_MTU bytes.
|
||||
*/
|
||||
static const uint NETWORK_MAX_GRF_COUNT = 62;
|
||||
static const uint NETWORK_MAX_GRF_COUNT_SHORT = 59;
|
||||
|
@@ -21,6 +21,7 @@
|
||||
/**
|
||||
* Create a packet that is used to read from a network socket.
|
||||
* @param cs The socket handler associated with the socket we are reading from.
|
||||
* @param limit The maximum size of packets to accept.
|
||||
* @param initial_read_size The initial amount of data to transfer from the socket into the
|
||||
* packet. This defaults to just the required bytes to determine the
|
||||
* packet's size. That default is the wanted for streams such as TCP
|
||||
@@ -29,7 +30,7 @@
|
||||
* loose some the data of the packet, so there you pass the maximum
|
||||
* size for the packet you expect from the network.
|
||||
*/
|
||||
Packet::Packet(NetworkSocketHandler *cs, size_t initial_read_size) : pos(0)
|
||||
Packet::Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size) : pos(0), limit(limit)
|
||||
{
|
||||
assert(cs != nullptr);
|
||||
|
||||
@@ -39,9 +40,13 @@ Packet::Packet(NetworkSocketHandler *cs, size_t initial_read_size) : pos(0)
|
||||
|
||||
/**
|
||||
* Creates a packet to send
|
||||
* @param type of the packet to send
|
||||
* @param type The type of the packet to send
|
||||
* @param limit The maximum number of bytes the packet may have. Default is COMPAT_MTU.
|
||||
* Be careful of compatibility with older clients/servers when changing
|
||||
* the limit as it might break things if the other side is not expecting
|
||||
* much larger packets than what they support.
|
||||
*/
|
||||
Packet::Packet(PacketType type) : pos(0), cs(nullptr)
|
||||
Packet::Packet(PacketType type, size_t limit) : pos(0), limit(limit), cs(nullptr)
|
||||
{
|
||||
this->ResetState(type);
|
||||
}
|
||||
@@ -77,7 +82,7 @@ void Packet::PrepareToSend()
|
||||
*/
|
||||
bool Packet::CanWriteToPacket(size_t bytes_to_write)
|
||||
{
|
||||
return this->Size() + bytes_to_write < SHRT_MAX;
|
||||
return this->Size() + bytes_to_write < this->limit;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -181,7 +186,7 @@ void Packet::Send_string(const char *data)
|
||||
*/
|
||||
size_t Packet::Send_bytes(const byte *begin, const byte *end)
|
||||
{
|
||||
size_t amount = std::min<size_t>(end - begin, SHRT_MAX - this->Size());
|
||||
size_t amount = std::min<size_t>(end - begin, this->limit - this->Size());
|
||||
this->buffer.insert(this->buffer.end(), begin, begin + amount);
|
||||
return amount;
|
||||
}
|
||||
@@ -267,7 +272,7 @@ bool Packet::ParsePacketSize()
|
||||
/* If the size of the packet is less than the bytes required for the size and type of
|
||||
* the packet, or more than the allowed limit, then something is wrong with the packet.
|
||||
* In those cases the packet can generally be regarded as containing garbage data. */
|
||||
if (size < sizeof(PacketSize) + sizeof(PacketType)) return false;
|
||||
if (size < sizeof(PacketSize) + sizeof(PacketType) || size > this->limit) return false;
|
||||
|
||||
this->buffer.resize(size);
|
||||
this->pos = sizeof(PacketSize);
|
||||
|
@@ -26,10 +26,11 @@ typedef uint8 PacketType; ///< Identifier for the packet
|
||||
* Internal entity of a packet. As everything is sent as a packet,
|
||||
* all network communication will need to call the functions that
|
||||
* populate the packet.
|
||||
* Every packet can be at most SEND_MTU bytes. Overflowing this
|
||||
* limit will give an assertion when sending (i.e. writing) the
|
||||
* packet. Reading past the size of the packet when receiving
|
||||
* will return all 0 values and "" in case of the string.
|
||||
* Every packet can be at most a limited number bytes set in the
|
||||
* constructor. Overflowing this limit will give an assertion when
|
||||
* sending (i.e. writing) the packet. Reading past the size of the
|
||||
* packet when receiving will return all 0 values and "" in case of
|
||||
* the string.
|
||||
*
|
||||
* --- Points of attention ---
|
||||
* - all > 1 byte integral values are written in little endian,
|
||||
@@ -46,13 +47,15 @@ private:
|
||||
PacketSize pos;
|
||||
/** The buffer of this packet. */
|
||||
std::vector<byte> buffer;
|
||||
/** The limit for the packet size. */
|
||||
size_t limit;
|
||||
|
||||
/** Socket we're associated with. */
|
||||
NetworkSocketHandler *cs;
|
||||
|
||||
public:
|
||||
Packet(NetworkSocketHandler *cs, size_t initial_read_size = sizeof(PacketSize));
|
||||
Packet(PacketType type);
|
||||
Packet(NetworkSocketHandler *cs, size_t limit, size_t initial_read_size = sizeof(PacketSize));
|
||||
Packet(PacketType type, size_t limit = COMPAT_MTU);
|
||||
|
||||
void ResetState(PacketType type);
|
||||
|
||||
|
@@ -61,6 +61,21 @@ void NetworkTCPSocketHandler::SendPacket(std::unique_ptr<Packet> packet)
|
||||
this->packet_queue.push_back(std::move(packet));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function puts the packet in the send-queue and it is send as
|
||||
* soon as possible. This is the next tick, or maybe one tick later
|
||||
* if the OS-network-buffer is full)
|
||||
* @param packet the packet to send
|
||||
*/
|
||||
void NetworkTCPSocketHandler::SendPrependPacket(std::unique_ptr<Packet> packet)
|
||||
{
|
||||
assert(packet != nullptr);
|
||||
|
||||
packet->PrepareToSend();
|
||||
|
||||
this->packet_queue.push_front(std::move(packet));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends all the buffered packets out for this client. It stops when:
|
||||
* 1) all packets are send (queue is empty)
|
||||
@@ -123,7 +138,7 @@ std::unique_ptr<Packet> NetworkTCPSocketHandler::ReceivePacket()
|
||||
if (!this->IsConnected()) return nullptr;
|
||||
|
||||
if (this->packet_recv == nullptr) {
|
||||
this->packet_recv.reset(new Packet(this));
|
||||
this->packet_recv.reset(new Packet(this, SHRT_MAX));
|
||||
}
|
||||
|
||||
Packet *p = this->packet_recv.get();
|
||||
|
@@ -43,7 +43,8 @@ public:
|
||||
bool IsConnected() const { return this->sock != INVALID_SOCKET; }
|
||||
|
||||
NetworkRecvStatus CloseConnection(bool error = true) override;
|
||||
virtual void SendPacket(std::unique_ptr<Packet> packet);
|
||||
void SendPacket(std::unique_ptr<Packet> packet);
|
||||
void SendPrependPacket(std::unique_ptr<Packet> packet);
|
||||
|
||||
void SendPacket(Packet *packet)
|
||||
{
|
||||
|
@@ -86,7 +86,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a
|
||||
{
|
||||
if (this->sockets.size() == 0) this->Listen();
|
||||
|
||||
const uint MTU = short_mtu ? SEND_MTU_SHORT : SEND_MTU;
|
||||
const uint MTU = short_mtu ? UDP_MTU_SHORT : UDP_MTU;
|
||||
|
||||
if (p->Size() > MTU) {
|
||||
p->PrepareToSend();
|
||||
@@ -155,7 +155,8 @@ void NetworkUDPSocketHandler::ReceivePackets()
|
||||
struct sockaddr_storage client_addr;
|
||||
memset(&client_addr, 0, sizeof(client_addr));
|
||||
|
||||
Packet p(this, SEND_MTU);
|
||||
/* The limit is UDP_MTU, but also allocate that much as we need to read the whole packet in one go. */
|
||||
Packet p(this, UDP_MTU, UDP_MTU);
|
||||
socklen_t client_len = sizeof(client_addr);
|
||||
|
||||
/* Try to receive anything */
|
||||
@@ -506,7 +507,7 @@ void NetworkUDPSocketHandler::Receive_EX_MULTI(Packet *p, NetworkAddress *client
|
||||
DEBUG(net, 6, "[udp] merged multi-part packet from %s: " OTTD_PRINTFHEX64 ", %u bytes",
|
||||
NetworkAddressDumper().GetAddressAsString(client_addr), token, total_payload);
|
||||
|
||||
Packet merged(this, 0);
|
||||
Packet merged(this, SHRT_MAX, 0);
|
||||
merged.ReserveBuffer(total_payload);
|
||||
for (auto &frag : fs.fragments) {
|
||||
merged.Send_binary(frag.data(), frag.size());
|
||||
|
Reference in New Issue
Block a user