diff --git a/src/openrct2/network/Http.cpp b/src/openrct2/network/Http.cpp index 5391cea198..4ac48ea746 100644 --- a/src/openrct2/network/Http.cpp +++ b/src/openrct2/network/Http.cpp @@ -44,6 +44,7 @@ struct HttpRequest2 std::string Method; std::string Url; http_data_type Type; + bool ForceIPv4 = false; size_t Size = 0; union { @@ -59,6 +60,7 @@ struct HttpRequest2 Method = request.Method; Url = request.Url; Type = request.Type; + ForceIPv4 = request.ForceIPv4; Size = request.Size; if (request.Type == HTTP_DATA_JSON) { @@ -77,6 +79,7 @@ struct HttpRequest2 Method = std::string(request->method); Url = std::string(request->url); Type = request->type; + ForceIPv4 = request->forceIPv4; Size = request->size; if (request->type == HTTP_DATA_JSON) { @@ -198,8 +201,11 @@ static http_response_t *http_request(const HttpRequest2 &request) curl_easy_setopt(curl, CURLOPT_URL, request.Url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &writeBuffer); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_request_write_func); - // Force resolving to IPv4 to fix issues where advertising over IPv6 does not work - curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + if (request.ForceIPv4) + { + // Force resolving to IPv4 to fix issues where advertising over IPv6 does not work + curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + } curlResult = curl_easy_perform(curl); diff --git a/src/openrct2/network/NetworkServerAdvertiser.cpp b/src/openrct2/network/NetworkServerAdvertiser.cpp index 093353ba35..26d8dcf2b6 100644 --- a/src/openrct2/network/NetworkServerAdvertiser.cpp +++ b/src/openrct2/network/NetworkServerAdvertiser.cpp @@ -61,6 +61,9 @@ private: // Key received from the master server std::string _key; + // See https://github.com/OpenRCT2/OpenRCT2/issues/6277 and 4953 + bool _forceIPv4 = false; + public: explicit NetworkServerAdvertiser(uint16 port) { @@ -79,7 +82,7 @@ public: case ADVERTISE_STATUS::UNREGISTERED: if (_lastAdvertiseTime == 0 || platform_get_ticks() > _lastAdvertiseTime + MASTER_SERVER_REGISTER_TIME) { - SendRegistration(); + SendRegistration(_forceIPv4); } break; case ADVERTISE_STATUS::REGISTERED: @@ -95,7 +98,7 @@ public: } private: - void SendRegistration() + void SendRegistration(bool forceIPv4) { _lastAdvertiseTime = platform_get_ticks(); @@ -104,6 +107,7 @@ private: request.tag = this; request.url = GetMasterServerUrl(); request.method = HTTP_METHOD_POST; + request.forceIPv4 = forceIPv4; json_t *body = json_object(); json_object_set_new(body, "key", json_string(_key.c_str())); @@ -180,7 +184,14 @@ private: { message = json_string_value(jsonMessage); } - Console::Error::WriteLine("Unable to advertise: %s", message); + Console::Error::WriteLine("Unable to advertise (%d): %s", status, message); + // Hack for https://github.com/OpenRCT2/OpenRCT2/issues/6277 + // Master server may not reply correctly if using IPv6, retry forcing IPv4 + if (!_forceIPv4 && status == 500) + { + _forceIPv4 = true; + log_info("Retry with ipv4 only"); + } } } } diff --git a/src/openrct2/network/http.h b/src/openrct2/network/http.h index 239d3c9515..f038b184f0 100644 --- a/src/openrct2/network/http.h +++ b/src/openrct2/network/http.h @@ -33,6 +33,7 @@ typedef struct http_request_t { std::string method; std::string url; http_data_type type = HTTP_DATA_NONE; + bool forceIPv4; size_t size; union { const json_t *root;