Merge branch 'master' into jgrpp-beta

# Conflicts:
#	.github/workflows/commit-checker.yml
#	src/company_cmd.cpp
#	src/console_cmds.cpp
#	src/crashlog.cpp
#	src/lang/english.txt
#	src/lang/german.txt
#	src/lang/indonesian.txt
#	src/lang/japanese.txt
#	src/lang/korean.txt
#	src/lang/swedish.txt
#	src/linkgraph/linkgraphjob.cpp
#	src/linkgraph/mcf.cpp
#	src/network/core/tcp.cpp
#	src/network/core/tcp.h
#	src/network/core/tcp_game.h
#	src/network/core/udp.h
#	src/network/network.cpp
#	src/network/network_admin.cpp
#	src/network/network_admin.h
#	src/network/network_chat_gui.cpp
#	src/network/network_client.cpp
#	src/network/network_client.h
#	src/network/network_func.h
#	src/network/network_internal.h
#	src/network/network_server.cpp
#	src/network/network_server.h
#	src/newgrf.cpp
#	src/newgrf_station.cpp
#	src/order_gui.cpp
#	src/rail_cmd.cpp
#	src/saveload/saveload.cpp
#	src/settings.cpp
#	src/settings_gui.cpp
#	src/settings_internal.h
#	src/settings_type.h
#	src/station_cmd.cpp
#	src/stdafx.h
#	src/table/currency_settings.ini
#	src/table/misc_settings.ini
#	src/table/settings.h.preamble
#	src/table/settings.ini
#	src/terraform_cmd.cpp
#	src/timetable_gui.cpp
#	src/train_cmd.cpp
#	src/tree_cmd.cpp
#	src/water_cmd.cpp
This commit is contained in:
Jonathan G Rennison
2021-09-27 22:47:13 +01:00
204 changed files with 1829 additions and 1549 deletions

View File

@@ -180,7 +180,7 @@ bool NetworkAddress::IsInNetmask(const char *netmask)
int tmp_cidr = atoi(chr_cidr + 1);
/* Invalid CIDR, treat as single host */
if (tmp_cidr > 0 || tmp_cidr < cidr) cidr = tmp_cidr;
if (tmp_cidr > 0 && tmp_cidr < cidr) cidr = tmp_cidr;
/* Remove the / so that NetworkAddress works on the IP portion */
std::string ip_str(netmask, chr_cidr - netmask);

View File

@@ -40,7 +40,9 @@ struct Packet;
* SocketHandler for all network sockets in OpenTTD.
*/
class NetworkSocketHandler {
private:
bool has_quit; ///< Whether the current client has quit/send a bad packet
public:
/** Create a new unbound socket */
NetworkSocketHandler() { this->has_quit = false; }
@@ -49,12 +51,13 @@ public:
virtual ~NetworkSocketHandler() {}
/**
* Close the current connection; for TCP this will be mostly equivalent
* to Close(), but for UDP it just means the packet has to be dropped.
* @param error Whether we quit under an error condition or not.
* @return new status of the connection.
* Mark the connection as closed.
*
* This doesn't mean the actual connection is closed, but just that we
* act like it is. This is useful for UDP, which doesn't normally close
* a socket, but its handler might need to pretend it does.
*/
virtual NetworkRecvStatus CloseConnection(bool error = true) { this->has_quit = true; return NETWORK_RECV_STATUS_OKAY; }
void MarkClosed() { this->has_quit = true; }
/**
* Whether the current client connected to the socket has quit.

View File

@@ -128,7 +128,7 @@ void CheckGameCompatibility(NetworkGameInfo &ngi, bool extended)
*/
void FillStaticNetworkServerGameInfo()
{
_network_game_info.use_password = !StrEmpty(_settings_client.network.server_password);
_network_game_info.use_password = !_settings_client.network.server_password.empty();
_network_game_info.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
_network_game_info.clients_max = _settings_client.network.max_clients;
_network_game_info.companies_max = _settings_client.network.max_companies;

View File

@@ -20,72 +20,7 @@
*/
static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast);
#if defined(__HAIKU__) /* doesn't have neither getifaddrs or net/if.h */
/* Based on Andrew Bachmann's netstat+.c. Big thanks to him! */
extern "C" int _netstat(int fd, char **output, int verbose);
int seek_past_header(char **pos, const char *header)
{
char *new_pos = strstr(*pos, header);
if (new_pos == 0) {
return B_ERROR;
}
*pos += strlen(header) + new_pos - *pos + 1;
return B_OK;
}
static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // BEOS implementation
{
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
DEBUG(net, 0, "Could not create socket: %s", NetworkError::GetLast().AsString());
return;
}
char *output_pointer = nullptr;
int output_length = _netstat(sock, &output_pointer, 1);
if (output_length < 0) {
DEBUG(net, 0, "Error running _netstat()");
return;
}
char **output = &output_pointer;
if (seek_past_header(output, "IP Interfaces:") == B_OK) {
for (;;) {
uint32 n;
int fields, read;
uint8 i1, i2, i3, i4, j1, j2, j3, j4;
uint32 ip;
uint32 netmask;
fields = sscanf(*output, "%u: %hhu.%hhu.%hhu.%hhu, netmask %hhu.%hhu.%hhu.%hhu%n",
&n, &i1, &i2, &i3, &i4, &j1, &j2, &j3, &j4, &read);
read += 1;
if (fields != 9) {
break;
}
ip = (uint32)i1 << 24 | (uint32)i2 << 16 | (uint32)i3 << 8 | (uint32)i4;
netmask = (uint32)j1 << 24 | (uint32)j2 << 16 | (uint32)j3 << 8 | (uint32)j4;
if (ip != INADDR_LOOPBACK && ip != INADDR_ANY) {
sockaddr_storage address;
memset(&address, 0, sizeof(address));
((sockaddr_in*)&address)->sin_addr.s_addr = htonl(ip | ~netmask);
NetworkAddress addr(address, sizeof(sockaddr));
if (std::none_of(broadcast->begin(), broadcast->end(), [&addr](NetworkAddress const& elem) -> bool { return elem == addr; })) broadcast->push_back(addr);
}
if (read < 0) {
break;
}
*output += read;
}
closesocket(sock);
}
}
#elif defined(HAVE_GETIFADDRS)
#if defined(HAVE_GETIFADDRS)
static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // GETIFADDRS implementation
{
struct ifaddrs *ifap, *ifa;

View File

@@ -124,6 +124,13 @@ typedef unsigned long in_addr_t;
# undef FD_SETSIZE
# define FD_SETSIZE 64
# endif
/* Haiku says it supports FD_SETSIZE fds, but it really only supports 512. */
# if defined(__HAIKU__)
# undef FD_SETSIZE
# define FD_SETSIZE 512
# endif
#endif /* UNIX */
/* OS/2 stuff */

View File

@@ -224,7 +224,7 @@ bool Packet::CanReadFromPacket(size_t bytes_to_read, bool close_connection)
/* Check if variable is within packet-size */
if (this->pos + bytes_to_read > this->Size()) {
if (close_connection) this->cs->NetworkSocketHandler::CloseConnection();
if (close_connection) this->cs->NetworkSocketHandler::MarkClosed();
return false;
}
@@ -381,14 +381,13 @@ uint64 Packet::Recv_uint64()
*/
void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings settings)
{
PacketSize pos;
char *bufp = buffer;
const char *last = buffer + size - 1;
/* Don't allow reading from a closed socket */
if (cs->HasClientQuit()) return;
pos = this->pos;
size_t pos = this->pos;
while (--size > 0 && pos < this->Size() && (*buffer++ = this->buffer[pos++]) != '\0') {}
if (size == 0 || pos == this->Size()) {
@@ -398,7 +397,9 @@ void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings set
while (pos < this->Size() && this->buffer[pos] != '\0') pos++;
pos++;
}
this->pos = pos;
assert(pos <= std::numeric_limits<PacketSize>::max());
this->pos = static_cast<PacketSize>(pos);
str_validate(bufp, last, settings);
}

View File

@@ -28,21 +28,42 @@ NetworkTCPSocketHandler::NetworkTCPSocketHandler(SOCKET s) :
NetworkTCPSocketHandler::~NetworkTCPSocketHandler()
{
/* Virtual functions get called statically in destructors, so make it explicit to remove any confusion. */
this->NetworkTCPSocketHandler::CloseConnection();
this->EmptyPacketQueue();
this->CloseSocket();
}
/**
* Free all pending and partially received packets.
*/
void NetworkTCPSocketHandler::EmptyPacketQueue()
{
this->packet_queue.clear();
this->packet_recv.reset();
}
/**
* Close the actual socket of the connection.
* Please make sure CloseConnection is called before CloseSocket, as
* otherwise not all resources might be released.
*/
void NetworkTCPSocketHandler::CloseSocket()
{
if (this->sock != INVALID_SOCKET) closesocket(this->sock);
this->sock = INVALID_SOCKET;
}
/**
* This will put this socket handler in a close state. It will not
* actually close the OS socket; use CloseSocket for this.
* @param error Whether we quit under an error condition or not.
* @return new status of the connection.
*/
NetworkRecvStatus NetworkTCPSocketHandler::CloseConnection(bool error)
{
this->MarkClosed();
this->writable = false;
NetworkSocketHandler::CloseConnection(error);
/* Free all pending and partially received packets */
this->packet_queue.clear();
this->packet_recv.reset();
this->EmptyPacketQueue();
return NETWORK_RECV_STATUS_OKAY;
}

View File

@@ -35,6 +35,8 @@ class NetworkTCPSocketHandler : public NetworkSocketHandler {
private:
std::deque<std::unique_ptr<Packet>> packet_queue; ///< Packets that are awaiting delivery
std::unique_ptr<Packet> packet_recv; ///< Partially received packet
void EmptyPacketQueue();
public:
SOCKET sock; ///< The socket currently connected to
bool writable; ///< Can we write to this socket?
@@ -45,7 +47,9 @@ public:
*/
bool IsConnected() const { return this->sock != INVALID_SOCKET; }
NetworkRecvStatus CloseConnection(bool error = true) override;
virtual NetworkRecvStatus CloseConnection(bool error = true);
void CloseSocket();
void SendPacket(std::unique_ptr<Packet> packet);
void SendPrependPacket(std::unique_ptr<Packet> packet, int queue_after_packet_type);

View File

@@ -34,10 +34,6 @@ NetworkAdminSocketHandler::NetworkAdminSocketHandler(SOCKET s) : status(ADMIN_ST
this->admin_version[0] = '\0';
}
NetworkAdminSocketHandler::~NetworkAdminSocketHandler()
{
}
NetworkRecvStatus NetworkAdminSocketHandler::CloseConnection(bool error)
{
delete this;

View File

@@ -482,7 +482,6 @@ public:
NetworkRecvStatus CloseConnection(bool error = true) override;
NetworkAdminSocketHandler(SOCKET s);
~NetworkAdminSocketHandler();
NetworkRecvStatus ReceivePackets();

View File

@@ -137,17 +137,6 @@ const char *ContentInfo::GetTextfile(TextfileType type) const
return ::GetTextfile(type, GetContentInfoSubDir(this->type), tmp);
}
/**
* Close the actual socket.
*/
void NetworkContentSocketHandler::CloseSocket()
{
if (this->sock == INVALID_SOCKET) return;
closesocket(this->sock);
this->sock = INVALID_SOCKET;
}
/**
* Handle the given packet, i.e. pass it to the right
* parser receive command.

View File

@@ -21,8 +21,6 @@
/** Base socket handler for all Content TCP sockets */
class NetworkContentSocketHandler : public NetworkTCPSocketHandler {
protected:
void CloseSocket();
bool ReceiveInvalidPacket(PacketContentType type);
/**

View File

@@ -310,7 +310,7 @@ protected:
virtual NetworkRecvStatus Receive_SERVER_SETTINGS_ACCESS(Packet *p);
/**
* The client is joined and ready to receive his map:
* The client is joined and ready to receive their map:
* uint32 Own client ID.
* uint32 Generation seed.
* string Network ID of the server.

View File

@@ -68,17 +68,18 @@ NetworkHTTPSocketHandler::NetworkHTTPSocketHandler(SOCKET s,
/** Free whatever needs to be freed. */
NetworkHTTPSocketHandler::~NetworkHTTPSocketHandler()
{
this->CloseConnection();
this->CloseSocket();
if (this->sock != INVALID_SOCKET) closesocket(this->sock);
this->sock = INVALID_SOCKET;
free(this->data);
}
NetworkRecvStatus NetworkHTTPSocketHandler::CloseConnection(bool error)
/**
* Close the actual socket of the connection.
*/
void NetworkHTTPSocketHandler::CloseSocket()
{
NetworkSocketHandler::CloseConnection(error);
return NETWORK_RECV_STATUS_OKAY;
if (this->sock != INVALID_SOCKET) closesocket(this->sock);
this->sock = INVALID_SOCKET;
}
/**
@@ -313,7 +314,7 @@ int NetworkHTTPSocketHandler::Receive()
if (ret < 0) cur->callback->OnFailure();
if (ret <= 0) {
/* Then... the connection can be closed */
cur->CloseConnection();
cur->CloseSocket();
iter = _http_connections.erase(iter);
delete cur;
continue;

View File

@@ -58,7 +58,7 @@ public:
return this->sock != INVALID_SOCKET;
}
NetworkRecvStatus CloseConnection(bool error = true) override;
void CloseSocket();
NetworkHTTPSocketHandler(SOCKET sock, HTTPCallback *callback,
const char *host, const char *url, const char *data, int depth);

View File

@@ -46,7 +46,7 @@ NetworkUDPSocketHandler::NetworkUDPSocketHandler(NetworkAddressList *bind)
bool NetworkUDPSocketHandler::Listen()
{
/* Make sure socket is closed */
this->Close();
this->CloseSocket();
for (NetworkAddress &addr : this->bind) {
addr.Listen(SOCK_DGRAM, &this->sockets);
@@ -56,9 +56,9 @@ bool NetworkUDPSocketHandler::Listen()
}
/**
* Close the given UDP socket
* Close the actual UDP socket.
*/
void NetworkUDPSocketHandler::Close()
void NetworkUDPSocketHandler::CloseSocket()
{
for (auto &s : this->sockets) {
closesocket(s.second);
@@ -66,12 +66,6 @@ void NetworkUDPSocketHandler::Close()
this->sockets.clear();
}
NetworkRecvStatus NetworkUDPSocketHandler::CloseConnection(bool error)
{
NetworkSocketHandler::CloseConnection(error);
return NETWORK_RECV_STATUS_OKAY;
}
/**
* Send a packet over UDP
* @param p the packet to send

View File

@@ -66,8 +66,6 @@ protected:
};
std::vector<FragmentSet> fragments;
NetworkRecvStatus CloseConnection(bool error = true) override;
void ReceiveInvalidPacket(PacketUDPType, NetworkAddress *client_addr);
/**
@@ -208,10 +206,10 @@ public:
NetworkUDPSocketHandler(NetworkAddressList *bind = nullptr);
/** On destructing of this class, the socket needs to be closed */
virtual ~NetworkUDPSocketHandler() { this->Close(); }
virtual ~NetworkUDPSocketHandler() { this->CloseSocket(); }
bool Listen();
void Close();
void CloseSocket();
void SendPacket(Packet *p, NetworkAddress *recv, bool all = false, bool broadcast = false, bool short_mtu = false);
void ReceivePackets();