mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2026-06-17 22:31:21 +00:00
Add createSocket() helper to reduce code duplication
This commit is contained in:
+4
-20
@@ -109,9 +109,10 @@ unsigned int LiTestClientConnectivity(const char* testServer, unsigned short ref
|
|||||||
|
|
||||||
for (i = 0; i < PORT_FLAGS_MAX_COUNT; i++) {
|
for (i = 0; i < PORT_FLAGS_MAX_COUNT; i++) {
|
||||||
if (testPortFlags & (1 << i)) {
|
if (testPortFlags & (1 << i)) {
|
||||||
sockets[i] = socket(address.ss_family,
|
sockets[i] = createSocket(address.ss_family,
|
||||||
LiGetProtocolFromPortFlagIndex(i) == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM,
|
LiGetProtocolFromPortFlagIndex(i) == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM,
|
||||||
LiGetProtocolFromPortFlagIndex(i));
|
LiGetProtocolFromPortFlagIndex(i),
|
||||||
|
1);
|
||||||
if (sockets[i] == INVALID_SOCKET) {
|
if (sockets[i] == INVALID_SOCKET) {
|
||||||
err = LastSocketFail();
|
err = LastSocketFail();
|
||||||
Limelog("Failed to create socket: %d\n", err);
|
Limelog("Failed to create socket: %d\n", err);
|
||||||
@@ -119,25 +120,8 @@ unsigned int LiTestClientConnectivity(const char* testServer, unsigned short ref
|
|||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LC_DARWIN
|
|
||||||
{
|
|
||||||
// Disable SIGPIPE on iOS
|
|
||||||
int val = 1;
|
|
||||||
setsockopt(sockets[i], SOL_SOCKET, SO_NOSIGPIPE, (char*)&val, sizeof(val));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
((struct sockaddr_in6*)&address)->sin6_port = htons(LiGetPortFromPortFlagIndex(i));
|
((struct sockaddr_in6*)&address)->sin6_port = htons(LiGetPortFromPortFlagIndex(i));
|
||||||
if (LiGetProtocolFromPortFlagIndex(i) == IPPROTO_TCP) {
|
if (LiGetProtocolFromPortFlagIndex(i) == IPPROTO_TCP) {
|
||||||
// Enable non-blocking I/O for connect timeout support
|
|
||||||
if (setSocketNonBlocking(sockets[i] , 1) != 0) {
|
|
||||||
// If non-blocking sockets are not available, TCP tests are not supported
|
|
||||||
err = LastSocketFail();
|
|
||||||
Limelog("Failed to enable non-blocking I/O: %d\n", err);
|
|
||||||
failingPortFlags = ML_TEST_RESULT_INCONCLUSIVE;
|
|
||||||
goto Exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initiate an asynchronous connection
|
// Initiate an asynchronous connection
|
||||||
err = connect(sockets[i], (struct sockaddr*)&address, address_length);
|
err = connect(sockets[i], (struct sockaddr*)&address, address_length);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
|||||||
+56
-43
@@ -180,9 +180,8 @@ SOCKET bindUdpSocket(int addrfamily, int bufferSize) {
|
|||||||
|
|
||||||
LC_ASSERT(addrfamily == AF_INET || addrfamily == AF_INET6);
|
LC_ASSERT(addrfamily == AF_INET || addrfamily == AF_INET6);
|
||||||
|
|
||||||
s = socket(addrfamily, SOCK_DGRAM, IPPROTO_UDP);
|
s = createSocket(addrfamily, SOCK_DGRAM, IPPROTO_UDP, 0);
|
||||||
if (s == INVALID_SOCKET) {
|
if (s == INVALID_SOCKET) {
|
||||||
Limelog("socket() failed: %d\n", (int)LastSocketError());
|
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,14 +250,11 @@ int setSocketNonBlocking(SOCKET s, int val) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port, int timeoutSec) {
|
SOCKET createSocket(int addressFamily, int socketType, int protocol, int nonBlocking) {
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
struct sockaddr_in6 addr;
|
|
||||||
int err;
|
|
||||||
int nonBlocking;
|
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
s = socket(dstaddr->ss_family, SOCK_STREAM, IPPROTO_TCP);
|
s = socket(addressFamily, socketType, protocol);
|
||||||
if (s == INVALID_SOCKET) {
|
if (s == INVALID_SOCKET) {
|
||||||
Limelog("socket() failed: %d\n", (int)LastSocketError());
|
Limelog("socket() failed: %d\n", (int)LastSocketError());
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
@@ -270,6 +266,26 @@ SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen,
|
|||||||
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char*)&val, sizeof(val));
|
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char*)&val, sizeof(val));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (nonBlocking) {
|
||||||
|
setSocketNonBlocking(s, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port, int timeoutSec) {
|
||||||
|
SOCKET s;
|
||||||
|
struct sockaddr_in6 addr;
|
||||||
|
struct pollfd pfd;
|
||||||
|
int err;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
// Create a non-blocking TCP socket
|
||||||
|
s = createSocket(dstaddr->ss_family, SOCK_STREAM, IPPROTO_TCP, 1);
|
||||||
|
if (s == INVALID_SOCKET) {
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
// Some broken routers/firewalls (or routes with multiple broken routers) may result in TCP packets
|
// Some broken routers/firewalls (or routes with multiple broken routers) may result in TCP packets
|
||||||
// being dropped without without us receiving an ICMP Fragmentation Needed packet. For example,
|
// being dropped without without us receiving an ICMP Fragmentation Needed packet. For example,
|
||||||
// a router can elect to drop rather than fragment even without DF set. A misconfigured firewall
|
// a router can elect to drop rather than fragment even without DF set. A misconfigured firewall
|
||||||
@@ -312,53 +328,50 @@ SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable non-blocking I/O for connect timeout support
|
|
||||||
nonBlocking = setSocketNonBlocking(s, 1) == 0;
|
|
||||||
|
|
||||||
// Start connection
|
// Start connection
|
||||||
memcpy(&addr, dstaddr, addrlen);
|
memcpy(&addr, dstaddr, addrlen);
|
||||||
addr.sin6_port = htons(port);
|
addr.sin6_port = htons(port);
|
||||||
err = connect(s, (struct sockaddr*) &addr, addrlen);
|
err = connect(s, (struct sockaddr*) &addr, addrlen);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
err = (int)LastSocketError();
|
err = (int)LastSocketError();
|
||||||
|
if (err != EWOULDBLOCK && err != EAGAIN && err != EINPROGRESS) {
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nonBlocking) {
|
// Wait for the connection to complete or the timeout to elapse
|
||||||
struct pollfd pfd;
|
pfd.fd = s;
|
||||||
|
pfd.events = POLLOUT;
|
||||||
// Wait for the connection to complete or the timeout to elapse
|
err = pollSockets(&pfd, 1, timeoutSec * 1000);
|
||||||
pfd.fd = s;
|
if (err < 0) {
|
||||||
pfd.events = POLLOUT;
|
// pollSockets() failed
|
||||||
err = pollSockets(&pfd, 1, timeoutSec * 1000);
|
err = LastSocketError();
|
||||||
if (err < 0) {
|
Limelog("pollSockets() failed: %d\n", err);
|
||||||
// pollSockets() failed
|
closeSocket(s);
|
||||||
err = LastSocketError();
|
SetLastSocketError(err);
|
||||||
Limelog("pollSockets() failed: %d\n", err);
|
return INVALID_SOCKET;
|
||||||
closeSocket(s);
|
}
|
||||||
SetLastSocketError(err);
|
else if (err == 0) {
|
||||||
return INVALID_SOCKET;
|
// pollSockets() timed out
|
||||||
|
Limelog("Connection timed out after %d seconds (TCP port %u)\n", timeoutSec, port);
|
||||||
|
closeSocket(s);
|
||||||
|
SetLastSocketError(ETIMEDOUT);
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The socket was signalled
|
||||||
|
SOCKADDR_LEN len = sizeof(err);
|
||||||
|
getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&err, &len);
|
||||||
|
if (err != 0 || (pfd.revents & POLLERR)) {
|
||||||
|
// Get the error code
|
||||||
|
err = (err != 0) ? err : LastSocketFail();
|
||||||
}
|
}
|
||||||
else if (err == 0) {
|
|
||||||
// pollSockets() timed out
|
|
||||||
Limelog("Connection timed out after %d seconds (TCP port %u)\n", timeoutSec, port);
|
|
||||||
closeSocket(s);
|
|
||||||
SetLastSocketError(ETIMEDOUT);
|
|
||||||
return INVALID_SOCKET;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The socket was signalled
|
|
||||||
SOCKADDR_LEN len = sizeof(err);
|
|
||||||
getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&err, &len);
|
|
||||||
if (err != 0 || (pfd.revents & POLLERR)) {
|
|
||||||
// Get the error code
|
|
||||||
err = (err != 0) ? err : LastSocketFail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable non-blocking I/O now that the connection is established
|
|
||||||
setSocketNonBlocking(s, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable non-blocking I/O now that the connection is established
|
||||||
|
setSocketNonBlocking(s, 0);
|
||||||
|
|
||||||
|
Exit:
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
Limelog("connect() failed: %d\n", err);
|
Limelog("connect() failed: %d\n", err);
|
||||||
closeSocket(s);
|
closeSocket(s);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ typedef socklen_t SOCKADDR_LEN;
|
|||||||
#define URLSAFESTRING_LEN (INET6_ADDRSTRLEN+2)
|
#define URLSAFESTRING_LEN (INET6_ADDRSTRLEN+2)
|
||||||
void addrToUrlSafeString(struct sockaddr_storage* addr, char* string);
|
void addrToUrlSafeString(struct sockaddr_storage* addr, char* string);
|
||||||
|
|
||||||
|
SOCKET createSocket(int addressFamily, int socketType, int protocol, int nonBlocking);
|
||||||
int resolveHostName(const char* host, int family, int tcpTestPort, struct sockaddr_storage* addr, SOCKADDR_LEN* addrLen);
|
int resolveHostName(const char* host, int family, int tcpTestPort, struct sockaddr_storage* addr, SOCKADDR_LEN* addrLen);
|
||||||
SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port, int timeoutSec);
|
SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port, int timeoutSec);
|
||||||
int sendMtuSafe(SOCKET s, char* buffer, int size);
|
int sendMtuSafe(SOCKET s, char* buffer, int size);
|
||||||
|
|||||||
Reference in New Issue
Block a user