Changeset - r24441:8ae6bf969767
[Not reviewed]
master
0 4 0
Patric Stout - 3 years ago 2020-12-09 16:13:34
truebrain@openttd.org
Fix: workarounds for two emscripten bugs in the network stack
4 files changed with 40 insertions and 0 deletions:
0 comments (0 inline, 0 general)
src/network/core/address.cpp
Show inline comments
 
@@ -267,6 +267,18 @@ SOCKET NetworkAddress::Resolve(int famil
 
			this->address_length = (int)runp->ai_addrlen;
 
			assert(sizeof(this->address) >= 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;
 
		}
 

	
src/network/core/os_abstraction.h
Show inline comments
 
@@ -151,6 +151,28 @@ typedef unsigned long in_addr_t;
 

	
 
#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.
 
 * @param d The socket to set the non-blocking more for.
src/network/core/tcp_listen.h
Show inline comments
 
@@ -42,6 +42,9 @@ public:
 
			socklen_t sin_len = sizeof(sin);
 
			SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
 
			if (s == INVALID_SOCKET) return;
 
#ifdef __EMSCRIPTEN__
 
			sin_len = FixAddrLenForEmscripten(sin);
 
#endif
 

	
 
			SetNonBlocking(s); // XXX error handling?
 

	
src/network/core/udp.cpp
Show inline comments
 
@@ -129,6 +129,9 @@ void NetworkUDPSocketHandler::ReceivePac
 
			/* Did we get the bytes for the base header of the packet? */
 
			if (nbytes <= 0) break;    // No data, i.e. no packet
 
			if (nbytes <= 2) continue; // Invalid data; try next packet
 
#ifdef __EMSCRIPTEN__
 
			client_len = FixAddrLenForEmscripten(client_addr);
 
#endif
 

	
 
			NetworkAddress address(client_addr, client_len);
 
			p.PrepareToRead();
0 comments (0 inline, 0 general)