Attempt to socket connect before establishing websocket connection

Summary:
^

Changelog: Check if there's a process listening at the specified port before attempting to establish a websocket connection on iOS

Reviewed By: fabiomassimo

Differential Revision: D35546817

fbshipit-source-id: 92ccca9afd8bcdc6d79205cc277ac813e0999166
This commit is contained in:
Lorenzo Blasa
2022-04-11 07:03:51 -07:00
committed by Facebook GitHub Bot
parent f7fc00cde2
commit fd2d7bc1a4

View File

@@ -10,6 +10,10 @@
#import "FlipperPlatformWebSocket.h" #import "FlipperPlatformWebSocket.h"
#import <Flipper/Log.h> #import <Flipper/Log.h>
#import <SocketRocket/SocketRocket.h> #import <SocketRocket/SocketRocket.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
static constexpr int connectionKeepaliveSeconds = 10; static constexpr int connectionKeepaliveSeconds = 10;
@@ -140,6 +144,57 @@ static constexpr int connectionKeepaliveSeconds = 10;
return; return;
} }
// Before attempting to establish a connection, check if
// there is a process listening at the specified port.
// CFNetwork seems to be quite verbose when the host cannot be reached
// causing unnecessary and annoying logs to be printed to the console.
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo* address;
getaddrinfo(
_url.host.UTF8String, _url.port.stringValue.UTF8String, &hints, &address);
int sfd =
socket(address->ai_family, address->ai_socktype, address->ai_protocol);
fcntl(sfd, F_SETFL, O_NONBLOCK);
connect(sfd, address->ai_addr, address->ai_addrlen);
fd_set fdset;
struct timeval tv;
FD_ZERO(&fdset);
FD_SET(sfd, &fdset);
// Set a timeout of 3 seconds.
tv.tv_sec = 3;
tv.tv_usec = 0;
bool listening = false;
if (select(sfd + 1, NULL, &fdset, NULL, &tv) == 1) {
int so_error;
socklen_t len = sizeof so_error;
getsockopt(sfd, SOL_SOCKET, SO_ERROR, &so_error, &len);
if (so_error == 0) {
listening = true;
}
// If there's an error, most likely there is no process
// listening at the specified host/port (ECONNREFUSED).
}
freeaddrinfo(address);
close(sfd);
if (!listening) {
_eventHandler(facebook::flipper::SocketEvent::ERROR);
return;
}
self.socket = [[SRWebSocket alloc] initWithURL:_url securityPolicy:_policy]; self.socket = [[SRWebSocket alloc] initWithURL:_url securityPolicy:_policy];
[_socket setDelegate:self]; [_socket setDelegate:self];
[_socket open]; [_socket open];