mirror of https://github.com/OpenTTD/OpenTTD
Fix: workarounds for two emscripten bugs in the network stack
parent
d5b9f7ac37
commit
8fbf5bef60
|
@ -267,6 +267,18 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList *
|
||||||
this->address_length = (int)runp->ai_addrlen;
|
this->address_length = (int)runp->ai_addrlen;
|
||||||
assert(sizeof(this->address) >= runp->ai_addrlen);
|
assert(sizeof(this->address) >= runp->ai_addrlen);
|
||||||
memcpy(&this->address, runp->ai_addr, runp->ai_addrlen);
|
memcpy(&this->address, runp->ai_addr, runp->ai_addrlen);
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/* Emscripten doesn't zero sin_zero, but as we compare addresses
|
||||||
|
* to see if they are the same address, we need them to be zero'd.
|
||||||
|
* Emscripten is, as far as we know, the only OS not doing this.
|
||||||
|
*
|
||||||
|
* https://github.com/emscripten-core/emscripten/issues/12998
|
||||||
|
*/
|
||||||
|
if (this->address.ss_family == AF_INET) {
|
||||||
|
sockaddr_in *address_ipv4 = (sockaddr_in *)&this->address;
|
||||||
|
memset(address_ipv4->sin_zero, 0, sizeof(address_ipv4->sin_zero));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,28 @@ typedef unsigned long in_addr_t;
|
||||||
|
|
||||||
#endif /* OS/2 */
|
#endif /* OS/2 */
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
/**
|
||||||
|
* Emscripten doesn't set 'addrlen' for accept(), getsockname(), getpeername()
|
||||||
|
* and recvfrom(), which confuses other functions and causes them to crash.
|
||||||
|
* This function needs to be called after these four functions to make sure
|
||||||
|
* 'addrlen' is patched up.
|
||||||
|
*
|
||||||
|
* https://github.com/emscripten-core/emscripten/issues/12996
|
||||||
|
*
|
||||||
|
* @param address The address returned by those four functions.
|
||||||
|
* @return The correct value for addrlen.
|
||||||
|
*/
|
||||||
|
static inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address)
|
||||||
|
{
|
||||||
|
switch (address.ss_family) {
|
||||||
|
case AF_INET6: return sizeof(struct sockaddr_in6);
|
||||||
|
case AF_INET: return sizeof(struct sockaddr_in);
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to set the socket into non-blocking mode.
|
* Try to set the socket into non-blocking mode.
|
||||||
* @param d The socket to set the non-blocking more for.
|
* @param d The socket to set the non-blocking more for.
|
||||||
|
|
|
@ -42,6 +42,9 @@ public:
|
||||||
socklen_t sin_len = sizeof(sin);
|
socklen_t sin_len = sizeof(sin);
|
||||||
SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
|
SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
|
||||||
if (s == INVALID_SOCKET) return;
|
if (s == INVALID_SOCKET) return;
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
sin_len = FixAddrLenForEmscripten(sin);
|
||||||
|
#endif
|
||||||
|
|
||||||
SetNonBlocking(s); // XXX error handling?
|
SetNonBlocking(s); // XXX error handling?
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,9 @@ void NetworkUDPSocketHandler::ReceivePackets()
|
||||||
/* Did we get the bytes for the base header of the packet? */
|
/* Did we get the bytes for the base header of the packet? */
|
||||||
if (nbytes <= 0) break; // No data, i.e. no packet
|
if (nbytes <= 0) break; // No data, i.e. no packet
|
||||||
if (nbytes <= 2) continue; // Invalid data; try next packet
|
if (nbytes <= 2) continue; // Invalid data; try next packet
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
client_len = FixAddrLenForEmscripten(client_addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
NetworkAddress address(client_addr, client_len);
|
NetworkAddress address(client_addr, client_len);
|
||||||
p.PrepareToRead();
|
p.PrepareToRead();
|
||||||
|
|
Loading…
Reference in New Issue