diff --git a/include/NetAPI.h b/include/NetAPI.h index 20ad6df..65be5f0 100644 --- a/include/NetAPI.h +++ b/include/NetAPI.h @@ -235,8 +235,14 @@ Socket __cheri_compartment("NetAPI") * of the connected client. These can be null if the caller is not interested * in the client's address or port. * - * This returns a valid sealed capability to a connected socket on success, or - * an untagged value on failure. + * This returns either a valid sealed socket type or an untagged capability that + * encodes the error code, and here are what each of them represent: + * - `-ENOMEM`: allocation of the wrapper timed out or does not have memory for + * now. + * - `-EINVAL`: The timeout pointer is invalid, or FreeRTOS_accept returns + * invalid socket, or fail to claim the socket poiting to mallocCapability, or + * fail to add socket to the socket reset list, + * - `-ETIMEDOUT`: timed out on FreeRTOS_accept. */ Socket __cheri_compartment("TCPIP") network_socket_accept_tcp(Timeout *timeout, diff --git a/lib/tcpip/network_wrapper.cc b/lib/tcpip/network_wrapper.cc index fb9ca2a..caa0c0a 100644 --- a/lib/tcpip/network_wrapper.cc +++ b/lib/tcpip/network_wrapper.cc @@ -608,7 +608,8 @@ Socket network_socket_accept_tcp(Timeout *timeout, uint16_t *port) { Socket socket = nullptr; - with_sealed_socket( + int retVal = with_sealed_socket( + timeout, [&](SealedSocket *listeningSocket) { if (!check_timeout_pointer(timeout)) { @@ -621,24 +622,39 @@ Socket network_socket_accept_tcp(Timeout *timeout, if (socketWrapper == nullptr) { Debug::log("Failed to allocate socket wrapper."); - return -EINVAL; + return -ENOMEM; } socketWrapper->socketEpoch = currentSocketEpoch.load(); struct freertos_sockaddr addressTmp; uint32_t addressLength = sizeof(addressTmp); - auto rawSocket = FreeRTOS_accept( - listeningSocket->socket, &addressTmp, &addressLength); - if (rawSocket == nullptr) + FreeRTOS_Socket_t *rawSocket = nullptr; + + // acceptResult: 0 = valid socket || -EINVAL = FREERTOS_INVALID_SOCKET + // || -ETIMEDOUT = timed out + int acceptResult = with_freertos_timeout( + timeout, + listeningSocket->socket, + FREERTOS_SO_RCVTIMEO, + [&]() -> int { + rawSocket = FreeRTOS_accept( + listeningSocket->socket, &addressTmp, &addressLength); + if (rawSocket == nullptr) + { + return -ETIMEDOUT; + } + if (rawSocket == FREERTOS_INVALID_SOCKET) + { + return -EINVAL; + } + return 0; // returns a valid socket + }); + + if (acceptResult != 0) { - Debug::log("Failed to create socket."); - // This cannot fail unless buggy - we know that we - // successfully allocated the token with this malloc - // capability. Same for other calls to `token_obj_destroy` - // in this function. token_obj_destroy(mallocCapability, socket_key(), sealedSocket); - return -EINVAL; + return acceptResult; } socketWrapper->socket = rawSocket; @@ -720,6 +736,15 @@ Socket network_socket_accept_tcp(Timeout *timeout, return 0; }, sealedListeningSocket); + + if (retVal != 0) + { + __clang_ignored_warning_push("-Wcheri-capability-misuse"); + auto errCode = reinterpret_cast(retVal); + __clang_ignored_warning_pop(); + return errCode; + } + return socket; }