Split socket creation and connect/listen

This will allow to assign the socket to a variable before connecting or
listening, so that it can be interrupted from another thread.
This commit is contained in:
Romain Vimont 2021-10-31 22:01:57 +01:00
parent ed19901db1
commit 0bfa75a48b
3 changed files with 57 additions and 42 deletions

View file

@ -116,10 +116,10 @@ disable_tunnel(struct server *server) {
return ok; return ok;
} }
static sc_socket static bool
listen_on_port(uint16_t port) { listen_on_port(sc_socket socket, uint16_t port) {
#define IPV4_LOCALHOST 0x7F000001 #define IPV4_LOCALHOST 0x7F000001
return net_listen(IPV4_LOCALHOST, port, 1); return net_listen(socket, IPV4_LOCALHOST, port, 1);
} }
static bool static bool
@ -138,8 +138,10 @@ enable_tunnel_reverse_any_port(struct server *server,
// client can listen before starting the server app, so there is no // client can listen before starting the server app, so there is no
// need to try to connect until the server socket is listening on the // need to try to connect until the server socket is listening on the
// device. // device.
sc_socket server_socket = listen_on_port(port); sc_socket server_socket = net_socket();
if (server_socket != SC_INVALID_SOCKET) { if (server_socket != SC_INVALID_SOCKET) {
bool ok = listen_on_port(server_socket, port);
if (ok) {
// success // success
server->server_socket = server_socket; server->server_socket = server_socket;
server->local_port = port; server->local_port = port;
@ -147,6 +149,9 @@ enable_tunnel_reverse_any_port(struct server *server,
return true; return true;
} }
net_close(server_socket);
}
// failure, disable tunnel and try another port // failure, disable tunnel and try another port
if (!disable_tunnel_reverse(server->serial)) { if (!disable_tunnel_reverse(server->serial)) {
LOGW("Could not remove reverse tunnel on port %" PRIu16, port); LOGW("Could not remove reverse tunnel on port %" PRIu16, port);
@ -299,11 +304,11 @@ execute_server(struct server *server, const struct server_params *params) {
return adb_execute(server->serial, cmd, ARRAY_LEN(cmd)); return adb_execute(server->serial, cmd, ARRAY_LEN(cmd));
} }
static sc_socket static bool
connect_and_read_byte(uint16_t port) { connect_and_read_byte(sc_socket socket, uint16_t port) {
sc_socket socket = net_connect(IPV4_LOCALHOST, port); bool ok = net_connect(socket, IPV4_LOCALHOST, port);
if (socket == SC_INVALID_SOCKET) { if (!ok) {
return SC_INVALID_SOCKET; return false;
} }
char byte; char byte;
@ -311,21 +316,26 @@ connect_and_read_byte(uint16_t port) {
// is not listening, so read one byte to detect a working connection // is not listening, so read one byte to detect a working connection
if (net_recv(socket, &byte, 1) != 1) { if (net_recv(socket, &byte, 1) != 1) {
// the server is not listening yet behind the adb tunnel // the server is not listening yet behind the adb tunnel
net_close(socket); return false;
return SC_INVALID_SOCKET;
} }
return socket;
return true;
} }
static sc_socket static sc_socket
connect_to_server(uint16_t port, uint32_t attempts, uint32_t delay) { connect_to_server(uint16_t port, uint32_t attempts, uint32_t delay) {
do { do {
LOGD("Remaining connection attempts: %d", (int) attempts); LOGD("Remaining connection attempts: %d", (int) attempts);
sc_socket socket = connect_and_read_byte(port); sc_socket socket = net_socket();
if (socket != SC_INVALID_SOCKET) { if (socket != SC_INVALID_SOCKET) {
bool ok = connect_and_read_byte(socket, port);
if (ok) {
// it worked! // it worked!
return socket; return socket;
} }
net_close(socket);
}
if (attempts) { if (attempts) {
SDL_Delay(delay); SDL_Delay(delay);
} }
@ -463,10 +473,15 @@ server_connect_to(struct server *server, struct server_info *info) {
} }
// we know that the device is listening, we don't need several attempts // we know that the device is listening, we don't need several attempts
control_socket = net_connect(IPV4_LOCALHOST, server->local_port); control_socket = net_socket();
if (control_socket == SC_INVALID_SOCKET) { if (control_socket == SC_INVALID_SOCKET) {
goto fail; goto fail;
} }
bool ok = net_connect(control_socket, IPV4_LOCALHOST,
server->local_port);
if (!ok) {
goto fail;
}
} }
// we don't need the adb tunnel anymore // we don't need the adb tunnel anymore

View file

@ -94,13 +94,18 @@ net_perror(const char *s) {
} }
sc_socket sc_socket
net_connect(uint32_t addr, uint16_t port) { net_socket(void) {
sc_raw_socket raw_sock = socket(AF_INET, SOCK_STREAM, 0); sc_raw_socket raw_sock = socket(AF_INET, SOCK_STREAM, 0);
sc_socket sock = wrap(raw_sock); sc_socket sock = wrap(raw_sock);
if (sock == SC_INVALID_SOCKET) { if (sock == SC_INVALID_SOCKET) {
net_perror("socket"); net_perror("socket");
return SC_INVALID_SOCKET;
} }
return sock;
}
bool
net_connect(sc_socket socket, uint32_t addr, uint16_t port) {
sc_raw_socket raw_sock = unwrap(socket);
SOCKADDR_IN sin; SOCKADDR_IN sin;
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
@ -109,21 +114,15 @@ net_connect(uint32_t addr, uint16_t port) {
if (connect(raw_sock, (SOCKADDR *) &sin, sizeof(sin)) == SOCKET_ERROR) { if (connect(raw_sock, (SOCKADDR *) &sin, sizeof(sin)) == SOCKET_ERROR) {
net_perror("connect"); net_perror("connect");
net_close(sock); return false;
return SC_INVALID_SOCKET;
} }
return sock; return true;
} }
sc_socket bool
net_listen(uint32_t addr, uint16_t port, int backlog) { net_listen(sc_socket socket, uint32_t addr, uint16_t port, int backlog) {
sc_raw_socket raw_sock = socket(AF_INET, SOCK_STREAM, 0); sc_raw_socket raw_sock = unwrap(socket);
sc_socket sock = wrap(raw_sock);
if (sock == SC_INVALID_SOCKET) {
net_perror("socket");
return SC_INVALID_SOCKET;
}
int reuse = 1; int reuse = 1;
if (setsockopt(raw_sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, if (setsockopt(raw_sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse,
@ -138,17 +137,15 @@ net_listen(uint32_t addr, uint16_t port, int backlog) {
if (bind(raw_sock, (SOCKADDR *) &sin, sizeof(sin)) == SOCKET_ERROR) { if (bind(raw_sock, (SOCKADDR *) &sin, sizeof(sin)) == SOCKET_ERROR) {
net_perror("bind"); net_perror("bind");
net_close(sock); return false;
return SC_INVALID_SOCKET;
} }
if (listen(raw_sock, backlog) == SOCKET_ERROR) { if (listen(raw_sock, backlog) == SOCKET_ERROR) {
net_perror("listen"); net_perror("listen");
net_close(sock); return false;
return SC_INVALID_SOCKET;
} }
return sock; return true;
} }
sc_socket sc_socket

View file

@ -31,10 +31,13 @@ void
net_cleanup(void); net_cleanup(void);
sc_socket sc_socket
net_connect(uint32_t addr, uint16_t port); net_socket(void);
sc_socket bool
net_listen(uint32_t addr, uint16_t port, int backlog); net_connect(sc_socket socket, uint32_t addr, uint16_t port);
bool
net_listen(sc_socket socket, uint32_t addr, uint16_t port, int backlog);
sc_socket sc_socket
net_accept(sc_socket server_socket); net_accept(sc_socket server_socket);