From 2faaf0a9faf2202e0355e3f3fae34a6baf19e655 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 22 Mar 2017 00:00:52 -0700 Subject: [PATCH] http: Cancel remote server connects faster. This way the UI doesn't appear to hang when you click cancel. --- UI/RemoteISOScreen.cpp | 42 ++++++++++++++++++++++------------ ext/native/net/http_client.cpp | 31 +++++++++++++++++++++---- ext/native/net/http_client.h | 4 ++-- 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/UI/RemoteISOScreen.cpp b/UI/RemoteISOScreen.cpp index 5d3346729c..4d3f7ec9c1 100644 --- a/UI/RemoteISOScreen.cpp +++ b/UI/RemoteISOScreen.cpp @@ -50,6 +50,7 @@ static std::mutex serverStatusLock; static std::condition_variable serverStatusCond; static bool scanCancelled = false; +static bool scanAborted = false; static void UpdateStatus(ServerStatus s) { std::lock_guard guard(serverStatusLock); @@ -69,7 +70,7 @@ static void RegisterServer(int port) { Buffer theVoid; if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT)) { - if (http.Connect()) { + if (http.Connect(2, 20.0, &scanCancelled)) { char resource[1024] = {}; std::string ip = fd_util::GetLocalIP(http.sock()); snprintf(resource, sizeof(resource) - 1, "/match/update?local=%s&port=%d", ip.c_str(), port); @@ -190,12 +191,24 @@ static bool FindServer(std::string &resultHost, int &resultPort) { Buffer result; int code = 500; + auto TryServer = [&](const std::string &host, int port) { + // Don't wait as long for a connect - we need a good connection for smooth streaming anyway. + // This way if it's down, we'll find the right one faster. + if (http.Resolve(host.c_str(), port) && http.Connect(1, 10.0, &scanCancelled)) { + http.Disconnect(); + resultHost = host; + resultPort = port; + return true; + } + + return false; + }; + // Try last server first, if it is set - if (g_Config.iLastRemoteISOPort && g_Config.sLastRemoteISOServer != "" && http.Resolve(g_Config.sLastRemoteISOServer.c_str(), g_Config.iLastRemoteISOPort) && http.Connect()) { - http.Disconnect(); - resultHost = g_Config.sLastRemoteISOServer; - resultPort = g_Config.iLastRemoteISOPort; - return true; + if (g_Config.iLastRemoteISOPort && g_Config.sLastRemoteISOServer != "") { + if (TryServer(g_Config.sLastRemoteISOServer.c_str(), g_Config.iLastRemoteISOPort)) { + return true; + } } //don't scan if in manual mode @@ -205,7 +218,7 @@ static bool FindServer(std::string &resultHost, int &resultPort) { // Start by requesting a list of recent local ips for this network. if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT)) { - if (http.Connect()) { + if (http.Connect(2, 20.0, &scanCancelled)) { code = http.GET("/match/list", &result); http.Disconnect(); } @@ -230,7 +243,7 @@ static bool FindServer(std::string &resultHost, int &resultPort) { std::vector servers; const json_value *entry = entries->first_child; - while (entry) { + while (entry && !scanCancelled) { const char *host = entry->getString("ip", ""); int port = entry->getInt("p", 0); @@ -238,10 +251,7 @@ static bool FindServer(std::string &resultHost, int &resultPort) { snprintf(url, sizeof(url), "http://%s:%d", host, port); servers.push_back(url); - if (http.Resolve(host, port) && http.Connect()) { - http.Disconnect(); - resultHost = host; - resultPort = port; + if (TryServer(host, port)) { return true; } @@ -271,7 +281,7 @@ static bool LoadGameList(const std::string &host, int port, std::vectorExecuteScan(); @@ -455,6 +466,7 @@ RemoteISOConnectScreen::~RemoteISOConnectScreen() { sleep_ms(1); if (--maxWait < 0) { // If it does ever wake up, it may crash... but better than hanging? + scanAborted = true; break; } } @@ -536,7 +548,7 @@ void RemoteISOConnectScreen::update() { void RemoteISOConnectScreen::ExecuteScan() { FindServer(host_, port_); - if (scanCancelled) { + if (scanAborted) { return; } @@ -551,7 +563,7 @@ ScanStatus RemoteISOConnectScreen::GetStatus() { void RemoteISOConnectScreen::ExecuteLoad() { bool result = LoadGameList(host_, port_, games_); - if (scanCancelled) { + if (scanAborted) { return; } diff --git a/ext/native/net/http_client.cpp b/ext/native/net/http_client.cpp index a8836b257b..becb4e4473 100644 --- a/ext/native/net/http_client.cpp +++ b/ext/native/net/http_client.cpp @@ -73,7 +73,7 @@ bool Connection::Resolve(const char *host, int port) { return true; } -bool Connection::Connect(int maxTries, double timeout) { +bool Connection::Connect(int maxTries, double timeout, bool *cancelConnect) { if (port_ <= 0) { ELOG("Bad port"); return false; @@ -106,10 +106,26 @@ bool Connection::Connect(int maxTries, double timeout) { } } - struct timeval tv; - tv.tv_sec = floor(timeout); - tv.tv_usec = (timeout - floor(timeout)) * 1000000.0; - if (select(maxfd, NULL, &fds, NULL, &tv) > 0) { + int selectResult = 0; + long timeoutHalfSeconds = floor(2 * timeout); + while (timeoutHalfSeconds >= 0 && selectResult == 0) { + struct timeval tv; + tv.tv_sec = 0; + if (timeoutHalfSeconds > 0) { + // Wait up to 0.5 seconds between cancel checks. + tv.tv_usec = 500000; + } else { + // Wait the remaining <= 0.5 seconds. Possibly 0, but that's okay. + tv.tv_usec = (timeout - floor(2 * timeout) / 2) * 1000000.0; + } + --timeoutHalfSeconds; + + selectResult = select(maxfd, nullptr, &fds, nullptr, &tv); + if (cancelConnect && *cancelConnect) { + break; + } + } + if (selectResult > 0) { // Something connected. Pick the first one that did (if multiple.) for (int sock : sockets) { if ((intptr_t)sock_ == -1 && FD_ISSET(sock, &fds)) { @@ -123,6 +139,11 @@ bool Connection::Connect(int maxTries, double timeout) { // Great, now we're good to go. return true; } + + if (cancelConnect && *cancelConnect) { + break; + } + sleep_ms(1); } diff --git a/ext/native/net/http_client.h b/ext/native/net/http_client.h index 1147540301..8cc910c4c2 100644 --- a/ext/native/net/http_client.h +++ b/ext/native/net/http_client.h @@ -29,7 +29,7 @@ public: // Inits the sockaddr_in. bool Resolve(const char *host, int port); - bool Connect(int maxTries = 2, double timeout = 20.0f); + bool Connect(int maxTries = 2, double timeout = 20.0f, bool *cancelConnect = nullptr); void Disconnect(); // Only to be used for bring-up and debugging. @@ -167,4 +167,4 @@ private: std::vector> downloads_; }; -} // http \ No newline at end of file +} // http