Skip to content

Commit

Permalink
http: Set an explicit timeout on HTTP connect.
Browse files Browse the repository at this point in the history
Before we were just relying on whatever timeout connect() wanted.
  • Loading branch information
unknownbrackets committed Jul 4, 2016
1 parent f53735f commit 3c47440
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 28 deletions.
28 changes: 15 additions & 13 deletions UI/RemoteISOScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ static void RegisterServer(int port) {
Buffer theVoid;

if (http.Resolve(REPORT_HOSTNAME, REPORT_PORT)) {
http.Connect();
if (http.Connect()) {
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);

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);

http.GET(resource, &theVoid);
http.Disconnect();
http.GET(resource, &theVoid);
http.Disconnect();
}
}
}

Expand Down Expand Up @@ -191,9 +191,10 @@ 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)) {
http.Connect();
code = http.GET("/match/list", &result);
http.Disconnect();
if (http.Connect()) {
code = http.GET("/match/list", &result);
http.Disconnect();
}
}

if (code != 200 || scanCancelled) {
Expand Down Expand Up @@ -244,9 +245,10 @@ static bool LoadGameList(const std::string &host, int port, std::vector<std::str

// Start by requesting a list of recent local ips for this network.
if (http.Resolve(host.c_str(), port)) {
http.Connect();
code = http.GET("/", &result);
http.Disconnect();
if (http.Connect()) {
code = http.GET("/", &result);
http.Disconnect();
}
}

if (code != 200 || scanCancelled) {
Expand Down
59 changes: 45 additions & 14 deletions ext/native/net/http_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

#ifndef _WIN32
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define closesocket close
#else
Expand All @@ -12,19 +14,21 @@
#include <io.h>
#endif

#include <cmath>
#include <stdio.h>
#include <stdlib.h>

#include "base/logging.h"
#include "base/buffer.h"
#include "base/stringutil.h"
#include "data/compression.h"
#include "file/fd_util.h"
#include "net/resolve.h"
#include "net/url.h"

namespace net {

Connection::Connection()
Connection::Connection()
: port_(-1), resolved_(NULL), sock_(-1) {
}

Expand Down Expand Up @@ -68,33 +72,60 @@ bool Connection::Resolve(const char *host, int port) {
return true;
}

bool Connection::Connect(int maxTries) {
bool Connection::Connect(int maxTries, double timeout) {
if (port_ <= 0) {
ELOG("Bad port");
return false;
}
sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ((intptr_t)sock_ == -1) {
ELOG("Bad socket");
return false;
}
sock_ = -1;

for (int tries = maxTries; tries > 0; --tries) {
for (addrinfo *possible = resolved_; possible != NULL; possible = possible->ai_next) {
std::vector<uintptr_t> sockets;
fd_set fds;
int maxfd = 1;
FD_ZERO(&fds);
for (addrinfo *possible = resolved_; possible != nullptr; possible = possible->ai_next) {
// TODO: Could support ipv6 without huge difficulty...
if (possible->ai_family != AF_INET)
continue;

int retval = connect(sock_, possible->ai_addr, (int)possible->ai_addrlen);
if (retval >= 0)
return true;
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ((intptr_t)sock == -1) {
ELOG("Bad socket");
continue;
}
fd_util::SetNonBlocking(sock, true);

// Start trying to connect (async with timeout.)
connect(sock, possible->ai_addr, (int)possible->ai_addrlen);
sockets.push_back(sock);
FD_SET(sock, &fds);
if (maxfd < sock + 1) {
maxfd = sock + 1;
}
}

struct timeval tv;
tv.tv_sec = floor(timeout);
tv.tv_usec = (timeout - floor(timeout)) * 1000000.0;
if (select(maxfd, NULL, &fds, NULL, &tv) > 0) {
// Something connected. Pick the first one that did (if multiple.)
for (int sock : sockets) {
if ((intptr_t)sock_ == -1 && FD_ISSET(sock, &fds)) {
fd_util::SetNonBlocking(sock, false);
sock_ = sock;
} else {
closesocket(sock);
}
}

// Great, now we're good to go.
return true;
}
sleep_ms(1);
}

// Let's not leak this socket.
closesocket(sock_);
sock_ = -1;
// Nothing connected, unfortunately.
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion ext/native/net/http_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Connection {
// Inits the sockaddr_in.
bool Resolve(const char *host, int port);

bool Connect(int maxTries = 2);
bool Connect(int maxTries = 2, double timeout = 20.0f);
void Disconnect();

// Only to be used for bring-up and debugging.
Expand Down

0 comments on commit 3c47440

Please sign in to comment.