Merge branch 'master' into jgrpp
# Conflicts: # .github/workflows/ci-build.yml # .github/workflows/release-linux.yml # .github/workflows/release-macos.yml # .github/workflows/release-source.yml # .github/workflows/release.yml # CMakeLists.txt # COMPILING.md # src/ai/ai_core.cpp # src/ai/ai_gui.cpp # src/bridge_gui.cpp # src/company_gui.cpp # src/console_cmds.cpp # src/core/CMakeLists.txt # src/core/smallmap_type.hpp # src/disaster_vehicle.h # src/effectvehicle_base.h # src/fontcache.cpp # src/game/game_core.cpp # src/game/game_gui.cpp # src/gamelog.cpp # src/gamelog_internal.h # src/group_gui.cpp # src/linkgraph/linkgraph.h # src/misc.cpp # src/network/core/config.h # src/network/core/udp.cpp # src/network/network_chat_gui.cpp # src/network/network_content_gui.cpp # src/network/network_gui.cpp # src/newgrf.cpp # src/newgrf_gui.cpp # src/newgrf_profiling.cpp # src/newgrf_profiling.h # src/object_gui.cpp # src/openttd.cpp # src/openttd.h # src/order_gui.cpp # src/os/windows/font_win32.cpp # src/rail_gui.cpp # src/road.cpp # src/road_gui.cpp # src/saveload/afterload.cpp # src/saveload/saveload.h # src/script/api/script_controller.cpp # src/script/api/script_roadtypelist.cpp # src/script/script_config.cpp # src/script/script_config.hpp # src/script/script_instance.cpp # src/script/script_scanner.cpp # src/script/squirrel.cpp # src/script/squirrel_helper.hpp # src/settings_gui.cpp # src/settings_internal.h # src/settings_type.h # src/table/settings/network_private_settings.ini # src/timetable_gui.cpp # src/vehicle.cpp # src/vehicle_base.h # src/window_gui.h
This commit is contained in:
@@ -282,7 +282,7 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList *
|
||||
* of course totally unneeded ;) */
|
||||
if (sockets != nullptr) {
|
||||
NetworkAddress address(runp->ai_addr, (int)runp->ai_addrlen);
|
||||
if (sockets->Contains(address)) continue;
|
||||
if (std::any_of(sockets->begin(), sockets->end(), [&address](const auto &p) { return p.second == address; })) continue;
|
||||
}
|
||||
sock = func(runp);
|
||||
if (sock == INVALID_SOCKET) continue;
|
||||
@@ -307,7 +307,7 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList *
|
||||
}
|
||||
|
||||
NetworkAddress addr(runp->ai_addr, (int)runp->ai_addrlen);
|
||||
(*sockets)[addr] = sock;
|
||||
(*sockets)[sock] = addr;
|
||||
sock = INVALID_SOCKET;
|
||||
}
|
||||
freeaddrinfo (ai);
|
||||
|
@@ -14,13 +14,13 @@
|
||||
#include "config.h"
|
||||
#include "../../company_type.h"
|
||||
#include "../../string_func.h"
|
||||
#include "../../core/smallmap_type.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class NetworkAddress;
|
||||
typedef std::vector<NetworkAddress> NetworkAddressList; ///< Type for a list of addresses.
|
||||
typedef SmallMap<NetworkAddress, SOCKET> SocketList; ///< Type for a mapping between address and socket.
|
||||
using SocketList = std::map<SOCKET, NetworkAddress>; ///< Type for a mapping between address and socket.
|
||||
|
||||
/**
|
||||
* Wrapper for (un)resolved network addresses; there's no reason to transform
|
||||
|
@@ -67,3 +67,13 @@ const char *NetworkContentMirrorUriString()
|
||||
{
|
||||
return GetEnv("OTTD_CONTENT_MIRROR_URI", "https://binaries.openttd.org/bananas");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URI string for the survey from the environment variable OTTD_SURVEY_URI,
|
||||
* or when it has not been set a hard coded URI of the production server.
|
||||
* @return The survey's URI string.
|
||||
*/
|
||||
const char *NetworkSurveyUriString()
|
||||
{
|
||||
return GetEnv("OTTD_SURVEY_URI", "https://survey-participate.openttd.org/");
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ const char *NetworkCoordinatorConnectionString();
|
||||
const char *NetworkStunConnectionString();
|
||||
const char *NetworkContentServerConnectionString();
|
||||
const char *NetworkContentMirrorUriString();
|
||||
const char *NetworkSurveyUriString();
|
||||
|
||||
static const uint16 NETWORK_COORDINATOR_SERVER_PORT = 3976; ///< The default port of the Game Coordinator server (TCP)
|
||||
static const uint16 NETWORK_STUN_SERVER_PORT = 3975; ///< The default port of the STUN server (TCP)
|
||||
@@ -27,6 +28,8 @@ static const uint16 NETWORK_DEFAULT_DEBUGLOG_PORT = 3982; ///< The d
|
||||
|
||||
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)
|
||||
|
||||
static const std::string NETWORK_SURVEY_DETAILS_LINK = "https://survey.openttd.org/participate"; ///< Link with more details & privacy statement of the survey.
|
||||
/*
|
||||
* 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.
|
||||
@@ -47,6 +50,7 @@ static const uint16 COMPAT_MTU = 1460; ///< Numbe
|
||||
static const byte NETWORK_GAME_ADMIN_VERSION = 3; ///< What version of the admin network do we use?
|
||||
static const byte NETWORK_GAME_INFO_VERSION = 6; ///< What version of game-info do we use?
|
||||
static const byte NETWORK_COORDINATOR_VERSION = 6; ///< What version of game-coordinator-protocol do we use?
|
||||
static const byte NETWORK_SURVEY_VERSION = 1; ///< What version of the survey do we use?
|
||||
|
||||
static const uint NETWORK_NAME_LENGTH = 80; ///< The maximum length of the server name and map name, in bytes including '\0'
|
||||
static const uint NETWORK_COMPANY_NAME_LENGTH = 128; ///< The maximum length of the company name, in bytes including '\0'
|
||||
|
@@ -48,7 +48,7 @@ public:
|
||||
NetworkSocketHandler() { this->has_quit = false; }
|
||||
|
||||
/** Close the socket when destructing the socket handler */
|
||||
virtual ~NetworkSocketHandler() {}
|
||||
virtual ~NetworkSocketHandler() = default;
|
||||
|
||||
/**
|
||||
* Mark the connection as closed.
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../core/alloc_func.hpp"
|
||||
#include "address.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "tcp.h"
|
||||
|
||||
constexpr int HTTP_429_TOO_MANY_REQUESTS = 429;
|
||||
|
||||
/** Callback for when the HTTP handler has something to tell us. */
|
||||
struct HTTPCallback {
|
||||
/**
|
||||
@@ -40,7 +42,7 @@ struct HTTPCallback {
|
||||
virtual bool IsCancelled() const = 0;
|
||||
|
||||
/** Silentium */
|
||||
virtual ~HTTPCallback() {}
|
||||
virtual ~HTTPCallback() = default;
|
||||
};
|
||||
|
||||
/** Base socket handler for HTTP traffic. */
|
||||
|
@@ -117,6 +117,7 @@ void HttpThread()
|
||||
|
||||
/* Reset to default settings. */
|
||||
curl_easy_reset(curl);
|
||||
curl_slist *headers = nullptr;
|
||||
|
||||
if (_debug_net_level >= 5) {
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
@@ -147,8 +148,16 @@ void HttpThread()
|
||||
|
||||
/* Prepare POST body and URI. */
|
||||
if (!request->data.empty()) {
|
||||
/* When the payload starts with a '{', it is a JSON payload. */
|
||||
if (StrStartsWith(request->data, "{")) {
|
||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||
} else {
|
||||
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request->data.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
}
|
||||
curl_easy_setopt(curl, CURLOPT_URL, request->uri.c_str());
|
||||
|
||||
@@ -175,11 +184,17 @@ void HttpThread()
|
||||
/* Perform the request. */
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
|
||||
curl_slist_free_all(headers);
|
||||
|
||||
if (res == CURLE_OK) {
|
||||
Debug(net, 1, "HTTP request succeeded");
|
||||
request->callback->OnReceiveData(nullptr, 0);
|
||||
} else {
|
||||
Debug(net, (request->callback->IsCancelled() || _http_thread_exit) ? 1 : 0, "HTTP request failed: {}", curl_easy_strerror(res));
|
||||
long status_code = 0;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status_code);
|
||||
|
||||
/* No need to be verbose about rate limiting. */
|
||||
Debug(net, (request->callback->IsCancelled() || _http_thread_exit || status_code == HTTP_429_TOO_MANY_REQUESTS) ? 1 : 0, "HTTP request failed: status_code: {}, error: {}", status_code, curl_easy_strerror(res));
|
||||
request->callback->OnFailure();
|
||||
}
|
||||
}
|
||||
|
@@ -131,7 +131,8 @@ void NetworkHTTPRequest::WinHttpCallback(DWORD code, void *info, DWORD length)
|
||||
|
||||
/* If there is any error, we simply abort the request. */
|
||||
if (status_code >= 400) {
|
||||
Debug(net, 0, "HTTP request failed: status-code {}", status_code);
|
||||
/* No need to be verbose about rate limiting. */
|
||||
Debug(net, status_code == HTTP_429_TOO_MANY_REQUESTS ? 1 : 0, "HTTP request failed: status-code {}", status_code);
|
||||
this->finished = true;
|
||||
this->callback->OnFailure();
|
||||
return;
|
||||
@@ -242,7 +243,9 @@ void NetworkHTTPRequest::Connect()
|
||||
if (data.empty()) {
|
||||
WinHttpSendRequest(this->request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, reinterpret_cast<DWORD_PTR>(this));
|
||||
} else {
|
||||
WinHttpSendRequest(this->request, L"Content-Type: application/x-www-form-urlencoded\r\n", -1, const_cast<char *>(data.c_str()), static_cast<DWORD>(data.size()), static_cast<DWORD>(data.size()), reinterpret_cast<DWORD_PTR>(this));
|
||||
/* When the payload starts with a '{', it is a JSON payload. */
|
||||
LPCWSTR content_type = StrStartsWith(data, "{") ? L"Content-Type: application/json\r\n" : L"Content-Type: application/x-www-form-urlencoded\r\n";
|
||||
WinHttpSendRequest(this->request, content_type, -1, const_cast<char *>(data.c_str()), static_cast<DWORD>(data.size()), static_cast<DWORD>(data.size()), reinterpret_cast<DWORD_PTR>(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -565,7 +565,7 @@ public:
|
||||
* @param status The reason the connection got closed.
|
||||
*/
|
||||
virtual NetworkRecvStatus CloseConnection(NetworkRecvStatus status) = 0;
|
||||
virtual ~NetworkGameSocketHandler() {}
|
||||
virtual ~NetworkGameSocketHandler() = default;
|
||||
|
||||
/**
|
||||
* Sets the client info for this socket handler.
|
||||
|
@@ -114,7 +114,7 @@ public:
|
||||
|
||||
/* take care of listener port */
|
||||
for (auto &s : sockets) {
|
||||
FD_SET(s.second, &read_fd);
|
||||
FD_SET(s.first, &read_fd);
|
||||
}
|
||||
|
||||
tv.tv_sec = tv.tv_usec = 0; // don't block at all.
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
|
||||
/* accept clients.. */
|
||||
for (auto &s : sockets) {
|
||||
if (FD_ISSET(s.second, &read_fd)) AcceptClient(s.second);
|
||||
if (FD_ISSET(s.first, &read_fd)) AcceptClient(s.first);
|
||||
}
|
||||
|
||||
/* read stuff from clients */
|
||||
@@ -164,7 +164,7 @@ public:
|
||||
static void CloseListeners()
|
||||
{
|
||||
for (auto &s : sockets) {
|
||||
closesocket(s.second);
|
||||
closesocket(s.first);
|
||||
}
|
||||
sockets.clear();
|
||||
DEBUG(net, 5, "[%s] Closed listeners", Tsocket::GetName());
|
||||
|
@@ -61,7 +61,7 @@ bool NetworkUDPSocketHandler::Listen()
|
||||
void NetworkUDPSocketHandler::CloseSocket()
|
||||
{
|
||||
for (auto &s : this->sockets) {
|
||||
closesocket(s.second);
|
||||
closesocket(s.first);
|
||||
}
|
||||
this->sockets.clear();
|
||||
}
|
||||
@@ -113,20 +113,20 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool a
|
||||
NetworkAddress send(*recv);
|
||||
|
||||
/* Not the same type */
|
||||
if (!send.IsFamily(s.first.GetAddress()->ss_family)) continue;
|
||||
if (!send.IsFamily(s.second.GetAddress()->ss_family)) continue;
|
||||
|
||||
p->PrepareToSend();
|
||||
|
||||
if (broadcast) {
|
||||
/* Enable broadcast */
|
||||
unsigned long val = 1;
|
||||
if (setsockopt(s.second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) {
|
||||
if (setsockopt(s.first, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) {
|
||||
DEBUG(net, 1, "Setting broadcast mode failed: %s", NetworkError::GetLast().AsString());
|
||||
}
|
||||
}
|
||||
|
||||
/* Send the buffer */
|
||||
ssize_t res = p->TransferOut<int>(sendto, s.second, 0, (const struct sockaddr *)send.GetAddress(), send.GetAddressLength());
|
||||
ssize_t res = p->TransferOut<int>(sendto, s.first, 0, (const struct sockaddr *)send.GetAddress(), send.GetAddressLength());
|
||||
DEBUG(net, 7, "sendto(%s)", NetworkAddressDumper().GetAddressAsString(&send));
|
||||
|
||||
/* Check for any errors, but ignore it otherwise */
|
||||
@@ -151,8 +151,8 @@ void NetworkUDPSocketHandler::ReceivePackets()
|
||||
socklen_t client_len = sizeof(client_addr);
|
||||
|
||||
/* Try to receive anything */
|
||||
SetNonBlocking(s.second); // Some OSes seem to lose the non-blocking status of the socket
|
||||
ssize_t nbytes = p.TransferIn<int>(recvfrom, s.second, 0, (struct sockaddr *)&client_addr, &client_len);
|
||||
SetNonBlocking(s.first); // Some OSes seem to lose the non-blocking status of the socket
|
||||
ssize_t nbytes = p.TransferIn<int>(recvfrom, s.first, 0, (struct sockaddr *)&client_addr, &client_len);
|
||||
|
||||
/* Did we get the bytes for the base header of the packet? */
|
||||
if (nbytes <= 0) break; // No data, i.e. no packet
|
||||
|
Reference in New Issue
Block a user