int32_t OsNetworkReceiveFrom(THandle aHandle, uint8_t* aBuffer, uint32_t aBytes, TIpAddress* aAddress, uint16_t* aPort) { OsNetworkHandle* handle = (OsNetworkHandle*)aHandle; if (SocketInterrupted(handle)) { return -1; } struct sockaddr_in addr; sockaddrFromEndpoint(&addr, 0, 0); socklen_t addrLen = sizeof(addr); SetFdNonBlocking(handle->iSocket); fd_set read; FD_ZERO(&read); FD_SET(handle->iPipe[0], &read); FD_SET(handle->iSocket, &read); fd_set error; FD_ZERO(&error); FD_SET(handle->iSocket, &error); int32_t received = TEMP_FAILURE_RETRY_2(recvfrom(handle->iSocket, aBuffer, aBytes, MSG_NOSIGNAL, (struct sockaddr*)&addr, &addrLen), handle); if (received==-1 && errno==EWOULDBLOCK) { int32_t selectErr = TEMP_FAILURE_RETRY_2(select(nfds(handle), &read, NULL, &error, NULL), handle); if (selectErr > 0 && FD_ISSET(handle->iSocket, &read)) { received = TEMP_FAILURE_RETRY_2(recvfrom(handle->iSocket, aBuffer, aBytes, MSG_NOSIGNAL, (struct sockaddr*)&addr, &addrLen), handle); } } SetFdBlocking(handle->iSocket); *aAddress = addr.sin_addr.s_addr; *aPort = ntohs(addr.sin_port); return received; }
int32_t OsNetworkReceive(THandle aHandle, uint8_t* aBuffer, uint32_t aBytes) { OsNetworkHandle* handle = (OsNetworkHandle*)aHandle; if (SocketInterrupted(handle)) { return -1; } SetFdNonBlocking(handle->iSocket); fd_set read; FD_ZERO(&read); FD_SET(handle->iPipe[0], &read); FD_SET(handle->iSocket, &read); fd_set error; FD_ZERO(&error); FD_SET(handle->iSocket, &error); int32_t received = TEMP_FAILURE_RETRY_2(recv(handle->iSocket, aBuffer, aBytes, MSG_NOSIGNAL), handle); if (received==-1 && errno==EWOULDBLOCK) { int32_t selectErr = TEMP_FAILURE_RETRY_2(select(nfds(handle), &read, NULL, &error, NULL), handle); if (selectErr > 0 && FD_ISSET(handle->iSocket, &read)) { received = TEMP_FAILURE_RETRY_2(recv(handle->iSocket, aBuffer, aBytes, MSG_NOSIGNAL), handle); } } SetFdBlocking(handle->iSocket); return received; }
THandle OsNetworkAccept(THandle aHandle, TIpAddress* aClientAddress, uint32_t* aClientPort) { OsNetworkHandle* handle = (OsNetworkHandle*)aHandle; *aClientAddress = 0; *aClientPort = 0; if (SocketInterrupted(handle)) { return kHandleNull; } struct sockaddr_in addr; sockaddrFromEndpoint(&addr, 0, 0); socklen_t len = sizeof(addr); SetFdNonBlocking(handle->iSocket); fd_set read; FD_ZERO(&read); FD_SET(handle->iPipe[0], &read); FD_SET(handle->iSocket, &read); fd_set error; FD_ZERO(&error); FD_SET(handle->iSocket, &error); int32_t h = TEMP_FAILURE_RETRY_2(accept(handle->iSocket, (struct sockaddr*)&addr, &len), handle); if (h==-1 && errno==EWOULDBLOCK) { int32_t selectErr = TEMP_FAILURE_RETRY_2(select(nfds(handle), &read, NULL, &error, NULL), handle); if (selectErr > 0 && FD_ISSET(handle->iSocket, &read)) { h = TEMP_FAILURE_RETRY_2(accept(handle->iSocket, (struct sockaddr*)&addr, &len), handle); } } SetFdBlocking(handle->iSocket); if (h == -1) { return kHandleNull; } OsNetworkHandle* newHandle = CreateHandle(handle->iCtx, h); if (newHandle == NULL) { close(h); return kHandleNull; } *aClientAddress = addr.sin_addr.s_addr; *aClientPort = ntohs(addr.sin_port); return (THandle)newHandle; }
static OsNetworkHandle* CreateHandle(int32_t aSocket) { OsNetworkHandle* handle = (OsNetworkHandle*)malloc(sizeof(OsNetworkHandle)); #ifdef PLATFORM_MACOSX_GNU int set = 1; setsockopt(aSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int)); #endif /* PLATFORM_MACOSX_GNU */ if (handle == NULL) { return kHandleNull; } if (pipe(handle->iPipe) == -1) { free(handle); return kHandleNull; } SetFdNonBlocking(handle->iPipe[0]); handle->iSocket = aSocket; assert(aSocket >= 0 && aSocket < MAX_FILE_DESCRIPTOR); handle->iInterrupted = 0; return handle; }
int32_t OsNetworkConnect(THandle aHandle, TIpAddress aAddress, uint16_t aPort, uint32_t aTimeoutMs) { OsNetworkHandle* handle = (OsNetworkHandle*)aHandle; if (SocketInterrupted(handle)) { return -1; } int32_t err = -1; SetFdNonBlocking(handle->iSocket); struct sockaddr_in addr; sockaddrFromEndpoint(&addr, aAddress, aPort); /* ignore err as we expect this to fail due to EINPROGRESS */ (void)connect(handle->iSocket, (struct sockaddr*)&addr, sizeof(addr)); fd_set read; FD_ZERO(&read); FD_SET(handle->iPipe[0], &read); fd_set write; FD_ZERO(&write); FD_SET(handle->iSocket, &write); fd_set error; FD_ZERO(&error); FD_SET(handle->iSocket, &error); struct timeval tv; tv.tv_sec = aTimeoutMs / 1000; tv.tv_usec = (aTimeoutMs % 1000) * 1000; int32_t selectErr = TEMP_FAILURE_RETRY_2(select(nfds(handle), &read, &write, &error, &tv), handle); if (selectErr > 0 && FD_ISSET(handle->iSocket, &write)) { err = 0; } SetFdBlocking(handle->iSocket); return err; }