diff --git a/common/cpp/src/system_io.cpp b/common/cpp/src/system_io.cpp index 8498d316954363cd348c9540119f52974d559f73..bebd718fb73d66045349330cf67a0e1272e99a55 100644 --- a/common/cpp/src/system_io.cpp +++ b/common/cpp/src/system_io.cpp @@ -36,18 +36,6 @@ void StripBasePath(const std::string& folder, std::vector<FileInfo>* file_list) // PRIVATE FUNCTIONS - END - -void hidra2::SystemIO::ApplyNetworkOptions(SocketDescriptor socket_fd, IOErrors* err) const { - if ( - setsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, (char*)&kNetBufferSize, sizeof(kNetBufferSize)) != 0 - || - setsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, (char*)&kNetBufferSize, sizeof(kNetBufferSize)) != 0 - ) { - *err = GetLastError(); - } -} - - std::thread* SystemIO::NewThread(std::function<void()> function) const { return new std::thread(function); } @@ -87,11 +75,11 @@ hidra2::FileDescriptor hidra2::SystemIO::CreateAndConnectIPTCPSocket(const std:: if(*err != IOErrors::kNoError) { return -1; } - InetConnect(fd, address, err); - if(*err != IOErrors::kNoError) { - Close(fd, nullptr); - return -1; - } + InetConnect(fd, address, err); + if (*err != IOErrors::kNoError) { + CloseSocket(fd, nullptr); + return -1; + } return fd; } @@ -295,6 +283,32 @@ void hidra2::SystemIO::Listen(SocketDescriptor socket_fd, int backlog, hidra2::I } } + +size_t hidra2::SystemIO::ReceiveTimeout(SocketDescriptor socket_fd, void* buf, size_t length, long timeout_in_usec, + IOErrors* err) const { + *err = hidra2::IOErrors::kNoError; + + fd_set read_fds; + FD_ZERO(&read_fds); + FD_SET(socket_fd, &read_fds); + timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = timeout_in_usec; + + int res = ::select(socket_fd + 1, &read_fds, nullptr, nullptr, &timeout); + if (res == 0) { + *err = IOErrors::kTimeout; + return 0; + } + if (res == -1) { + *err = GetLastError(); + return 0; + } + + return Receive(socket_fd, buf, length, err); +} + + size_t hidra2::SystemIO::Receive(SocketDescriptor socket_fd, void* buf, size_t length, IOErrors* err) const { size_t already_received = 0; @@ -321,30 +335,6 @@ size_t hidra2::SystemIO::Receive(SocketDescriptor socket_fd, void* buf, size_t l } -size_t hidra2::SystemIO::ReceiveTimeout(SocketDescriptor socket_fd, void* buf, size_t length, long timeout_in_usec, - IOErrors* err) const { - *err = hidra2::IOErrors::kNoError; - - fd_set read_fds; - FD_ZERO(&read_fds); - FD_SET(socket_fd, &read_fds); - timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = timeout_in_usec; - - int res = ::select(socket_fd + 1, &read_fds, nullptr, nullptr, &timeout); - if (res == 0) { - *err = IOErrors::kTimeout; - return 0; - } - if (res == -1) { - *err = GetLastError(); - return 0; - } - - return Receive(socket_fd, buf, length, err); -} - size_t hidra2::SystemIO::Send(SocketDescriptor socket_fd, const void* buf, @@ -372,6 +362,7 @@ size_t hidra2::SystemIO::Send(SocketDescriptor socket_fd, } *err = hidra2::IOErrors::kNoError; + return already_sent; } @@ -436,8 +427,6 @@ std::unique_ptr<std::tuple<std::string, uint16_t>> SystemIO::SplitAddressToHostA } void hidra2::SystemIO::InetConnect(SocketDescriptor socket_fd, const std::string& address, IOErrors* err) const { - *err = IOErrors::kNoError; - auto host_port_tuple = SplitAddressToHostAndPort(address); if (!host_port_tuple) { *err = IOErrors::kInvalidAddressFormat; @@ -458,15 +447,18 @@ void hidra2::SystemIO::InetConnect(SocketDescriptor socket_fd, const std::string socket_address.sin_port = htons(port); socket_address.sin_family = family; - if (_connect(socket_fd, (struct sockaddr*) &socket_address, sizeof(socket_address)) == -1) { - *err = GetLastError(); - return; - } + if (_connect(socket_fd, (struct sockaddr*) &socket_address, sizeof(socket_address)) == -1) { + *err = GetLastError(); + // On windows its normal that connect might throw a "WSAEWOULDBLOCK" since the socket need time to be created + if (*err != IOErrors::kNoError && *err != IOErrors::kResourceTemporarilyUnavailable) { + return; + } + } + *err = IOErrors::kNoError; } std::unique_ptr<std::tuple<std::string, SocketDescriptor>> SystemIO::InetAccept(SocketDescriptor socket_fd, IOErrors* err) const { - *err = IOErrors::kNoError; static short family = AddressFamilyToPosixFamily(AddressFamilies::INET); if (family == -1) { *err = IOErrors::kUnsupportedAddressFamily; @@ -476,13 +468,21 @@ IOErrors* err) const { sockaddr_in client_address{}; static size_t client_address_size = sizeof(sockaddr_in); - int peer_fd = _accept(socket_fd, reinterpret_cast<sockaddr*>(&client_address), &client_address_size); - - if (peer_fd == -1) { - *err = GetLastError(); - return nullptr; - } - + int peer_fd; + while (true) { + peer_fd = _accept(socket_fd, reinterpret_cast<sockaddr*>(&client_address), &client_address_size); + + if (peer_fd == -1) { + *err = GetLastError(); + if (*err == IOErrors::kResourceTemporarilyUnavailable) { + continue; + } + return nullptr; + } + break; + } + + *err = IOErrors::kNoError; ApplyNetworkOptions(peer_fd, err); std::string diff --git a/common/cpp/src/system_io_windows.cpp b/common/cpp/src/system_io_windows.cpp index 9d36dac2729b1f1c0056d5a1a56869d577cc074b..519ed12a71232a7cedbf535c47720bdd5976ee58 100644 --- a/common/cpp/src/system_io_windows.cpp +++ b/common/cpp/src/system_io_windows.cpp @@ -31,6 +31,8 @@ IOErrors IOErrorFromGetLastError() { return IOErrors::kConnectionResetByPeer; case WSAENOTSOCK: return IOErrors::kSocketOperationOnNonSocket; + case WSAEWOULDBLOCK: + return IOErrors::kResourceTemporarilyUnavailable; default: std::cout << "[IOErrorFromGetLastError] Unknown error code: " << last_error << std::endl; return IOErrors::kUnknownError; @@ -140,6 +142,27 @@ void SystemIO::CollectFileInformationRecursivly(const std::string& path, } } + + + +void hidra2::SystemIO::ApplyNetworkOptions(SocketDescriptor socket_fd, IOErrors* err) const { + //TODO: Seeing issues when using these settings - need further investigation + //Event if NonBlockingIO is set, it seems that _recv is a blocking call :/ + /* + static u_long iMode = 1; + + if ( + ioctlsocket(socket_fd, FIONBIO, &iMode) != 0 + || + setsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, (char*)&kNetBufferSize, sizeof(kNetBufferSize)) != 0 + || + setsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, (char*)&kNetBufferSize, sizeof(kNetBufferSize)) != 0 + ) { + *err = GetLastError(); + } + */ +} + FileDescriptor SystemIO::_open(const char* filename, int posix_open_flags) const { int fd; errno = _sopen_s(&fd, filename, posix_open_flags, _SH_DENYNO, _S_IREAD | _S_IWRITE);