Merge branch 'master' into jgrpp

# Conflicts:
#	src/company_cmd.cpp
#	src/network/core/packet.cpp
#	src/network/core/packet.h
#	src/network/core/tcp.cpp
#	src/network/core/udp.cpp
#	src/network/network_server.cpp
#	src/network/network_server.h
#	src/toolbar_gui.cpp
#	src/vehicle_gui_base.h
This commit is contained in:
Jonathan G Rennison
2021-04-25 19:48:57 +01:00
12 changed files with 364 additions and 171 deletions

View File

@@ -12,10 +12,12 @@
#ifndef NETWORK_CORE_PACKET_H
#define NETWORK_CORE_PACKET_H
#include "os_abstraction.h"
#include "config.h"
#include "core.h"
#include "../../string_type.h"
#include <string>
#include <functional>
typedef uint16 PacketSize; ///< Size of the whole packet.
typedef uint8 PacketType; ///< Identifier for the packet
@@ -39,44 +41,43 @@ typedef uint8 PacketType; ///< Identifier for the packet
* (year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0))
*/
struct Packet {
/**
* The size of the whole packet for received packets. For packets
* that will be sent, the value is filled in just before the
* actual transmission.
*/
PacketSize size;
private:
/** The current read/write position in the packet */
PacketSize pos;
/** The buffer of this packet, of basically variable length up to SHRT_MAX. */
byte *buffer;
/** The buffer of this packet. */
std::vector<byte> buffer;
private:
/** Socket we're associated with. */
NetworkSocketHandler *cs;
public:
Packet(NetworkSocketHandler *cs);
Packet(NetworkSocketHandler *cs, size_t initial_read_size = sizeof(PacketSize));
Packet(PacketType type);
~Packet();
void ResetState(PacketType type);
/* Sending/writing of packets */
void PrepareToSend();
void Send_bool (bool data);
void Send_uint8 (uint8 data);
void Send_uint16(uint16 data);
void Send_uint32(uint32 data);
void Send_uint64(uint64 data);
void Send_string(const char *data);
void Send_binary(const char *data, const size_t size);
bool CanWriteToPacket(size_t bytes_to_write);
void Send_bool (bool data);
void Send_uint8 (uint8 data);
void Send_uint16(uint16 data);
void Send_uint32(uint32 data);
void Send_uint64(uint64 data);
void Send_string(const char *data);
size_t Send_bytes (const byte *begin, const byte *end);
void Send_binary(const char *data, const size_t size);
/* Reading/receiving of packets */
void ReadRawPacketSize();
size_t ReadRawPacketSize() const;
bool HasPacketSizeData() const;
bool ParsePacketSize();
size_t Size() const;
void PrepareToRead();
PacketType GetPacketType() const;
bool CanReadFromPacket (uint bytes_to_read, bool non_fatal = false);
bool CanReadFromPacket(size_t bytes_to_read, bool close_connection = false);
bool Recv_bool ();
uint8 Recv_uint8 ();
uint16 Recv_uint16();
@@ -86,6 +87,108 @@ public:
void Recv_string(std::string &buffer, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
void Recv_binary(char *buffer, size_t size);
void Recv_binary(std::string &buffer, size_t size);
size_t RemainingBytesToTransfer() const;
const byte *GetBufferData() const { return this->buffer.data(); }
PacketSize GetRawPos() const { return this->pos; }
void ReserveBuffer(size_t size) { this->buffer.reserve(size); }
/**
* Transfer data from the packet to the given function. It starts reading at the
* position the last transfer stopped.
* See Packet::TransferIn for more information about transferring data to functions.
* @param transfer_function The function to pass the buffer as second parameter and the
* amount to write as third parameter. It returns the amount that
* was written or -1 upon errors.
* @param limit The maximum amount of bytes to transfer.
* @param destination The first parameter of the transfer function.
* @param args The fourth and further parameters to the transfer function, if any.
* @return The return value of the transfer_function.
*/
template <
typename A = size_t, ///< The type for the amount to be passed, so it can be cast to the right type.
typename F, ///< The type of the function.
typename D, ///< The type of the destination.
typename ... Args> ///< The types of the remaining arguments to the function.
ssize_t TransferOutWithLimit(F transfer_function, size_t limit, D destination, Args&& ... args)
{
size_t amount = std::min(this->RemainingBytesToTransfer(), limit);
if (amount == 0) return 0;
assert(this->pos < this->buffer.size());
assert(this->pos + amount <= this->buffer.size());
/* Making buffer a char means casting a lot in the Recv/Send functions. */
const char *output_buffer = reinterpret_cast<const char*>(this->buffer.data() + this->pos);
ssize_t bytes = transfer_function(destination, output_buffer, static_cast<A>(amount), std::forward<Args>(args)...);
if (bytes > 0) this->pos += bytes;
return bytes;
}
/**
* Transfer data from the packet to the given function. It starts reading at the
* position the last transfer stopped.
* See Packet::TransferIn for more information about transferring data to functions.
* @param transfer_function The function to pass the buffer as second parameter and the
* amount to write as third parameter. It returns the amount that
* was written or -1 upon errors.
* @param destination The first parameter of the transfer function.
* @param args The fourth and further parameters to the transfer function, if any.
* @tparam A The type for the amount to be passed, so it can be cast to the right type.
* @tparam F The type of the transfer_function.
* @tparam D The type of the destination.
* @tparam Args The types of the remaining arguments to the function.
* @return The return value of the transfer_function.
*/
template <typename A = size_t, typename F, typename D, typename ... Args>
ssize_t TransferOut(F transfer_function, D destination, Args&& ... args)
{
return TransferOutWithLimit<A>(transfer_function, std::numeric_limits<size_t>::max(), destination, std::forward<Args>(args)...);
}
/**
* Transfer data from the given function into the packet. It starts writing at the
* position the last transfer stopped.
*
* Examples of functions that can be used to transfer data into a packet are TCP's
* recv and UDP's recvfrom functions. They will directly write their data into the
* packet without an intermediate buffer.
* Examples of functions that can be used to transfer data from a packet are TCP's
* send and UDP's sendto functions. They will directly read the data from the packet's
* buffer without an intermediate buffer.
* These are functions are special in a sense as even though the packet can send or
* receive an amount of data, those functions can say they only processed a smaller
* amount, so special handling is required to keep the position pointers correct.
* Most of these transfer functions are in the form function(source, buffer, amount, ...),
* so the template of this function will assume that as the base parameter order.
*
* This will attempt to write all the remaining bytes into the packet. It updates the
* position based on how many bytes were actually written by the called transfer_function.
* @param transfer_function The function to pass the buffer as second parameter and the
* amount to read as third parameter. It returns the amount that
* was read or -1 upon errors.
* @param source The first parameter of the transfer function.
* @param args The fourth and further parameters to the transfer function, if any.
* @tparam A The type for the amount to be passed, so it can be cast to the right type.
* @tparam F The type of the transfer_function.
* @tparam S The type of the source.
* @tparam Args The types of the remaining arguments to the function.
* @return The return value of the transfer_function.
*/
template <typename A = size_t, typename F, typename S, typename ... Args>
ssize_t TransferIn(F transfer_function, S source, Args&& ... args)
{
size_t amount = this->RemainingBytesToTransfer();
if (amount == 0) return 0;
assert(this->pos < this->buffer.size());
assert(this->pos + amount <= this->buffer.size());
/* Making buffer a char means casting a lot in the Recv/Send functions. */
char *input_buffer = reinterpret_cast<char*>(this->buffer.data() + this->pos);
ssize_t bytes = transfer_function(source, input_buffer, static_cast<A>(amount), std::forward<Args>(args)...);
if (bytes > 0) this->pos += bytes;
return bytes;
}
};
#endif /* NETWORK_CORE_PACKET_H */