VirtualBox

Changeset 100171 in vbox


Ignore:
Timestamp:
Jun 13, 2023 9:07:56 PM (18 months ago)
Author:
vboxsync
Message:

IPRT: tcp.h+tcp.cpp,socket.h+socket.cpp: Add RTTcpSetKeepAlive() which
allows one to enable or disable sending periodic keep-alive messages on
a socket (SO_KEEPALIVE) as described in RFC 1122. RTTcpSetKeepAlive()
also allows one to adjust several keep-alive options on a per-socket
basis: the idle time before keep-alive probes are sent (TCP_KEEPIDLE
(TCP_KEEPALIVE on macOS)), the amount of time between keep-alive probes
(TCP_KEEPINTVL), and the number of keep-alive probes to send before
closing the connection (TCP_KEEPCNT).

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/mangling.h

    r100037 r100171  
    24722472# define RTTcpServerListen2                             RT_MANGLER(RTTcpServerListen2)
    24732473# define RTTcpServerShutdown                            RT_MANGLER(RTTcpServerShutdown)
     2474# define RTTcpSetBufferSize                             RT_MANGLER(RTTcpSetBufferSize)
     2475# define RTTcpSetKeepAlive                              RT_MANGLER(RTTcpSetKeepAlive)
    24742476# define RTTcpSetSendCoalescing                         RT_MANGLER(RTTcpSetSendCoalescing)
    2475 # define RTTcpSetBufferSize                             RT_MANGLER(RTTcpSetBufferSize)
    24762477# define RTTcpSgWrite                                   RT_MANGLER(RTTcpSgWrite)
    24772478# define RTTcpSgWriteL                                  RT_MANGLER(RTTcpSgWriteL)
  • trunk/include/iprt/tcp.h

    r98103 r100171  
    310310
    311311/**
     312 * Enables or disables sending of periodic keep-alive messages on a socket.
     313 * Also set values relating to TCP keep-alive messages on a socket.  The TCP
     314 * keep-alive mechanism is described in RFC 1122 which states:
     315 * "Keep-alive packets MUST only be sent when no data or acknowledgement
     316 * packets have been received for the connection within an interval. This
     317 * interval MUST be configurable and MUST default to no less than two hours."
     318 * The following per-socket options allow fine-tuning the keep-alive interval,
     319 * frequency, and timeout when SO_KEEPALIVE has been set for the socket.
     320 *
     321 * @returns iprt status code.
     322 * @retval  VERR_NOT_SUPPORTED is returned if these keep-alive options aren't
     323 *          supported by the OS.
     324 *
     325 * @param   hSocket                 Socket descriptor.
     326 * @param   fEnable                 When set to true enables keep-alive messages.
     327 * @param   cSecsIdle               The amount of time, in seconds, that the connection must be idle before
     328 *                                  keep-alive probes are sent for this socket. (TCP_KEEPIDLE (TCP_KEEPALIVE on macOS))
     329 *                                  If zero then the system default is used (the default value varies by OS
     330 *                                  but is typically 2 hours (7200 seconds)).
     331 * @param   cSecsInterval           The amount of time, in seconds, between each keep-alive probe sent to a
     332 *                                  peer. (TCP_KEEPINTVL)
     333 *                                  If zero then the system default is used (the default value varies by OS
     334 *                                  but is typically 75 seconds).
     335 * @param   cFailedPktsBeforeClose  The number of keep-alive probes to send which receive no response before
     336 *                                  closing the connection. (TCP_KEEPCNT)
     337 *                                  If zero then the system default is used (the default value varies by OS
     338 *                                  but is typically 8 packets).
     339 */
     340RTR3DECL(int)  RTTcpSetKeepAlive(RTSOCKET hSocket, bool fEnable, uint32_t cSecsIdle, uint32_t cSecsInterval,
     341                                 uint32_t cFailedPktsBeforeClose);
     342
     343/**
    312344 * Socket I/O multiplexing.
    313345 * Checks if the socket is ready for reading.
  • trunk/src/VBox/Runtime/include/internal/socket.h

    r98103 r100171  
    7979
    8080DECLHIDDEN(int)         rtSocketPollGetHandle(RTSOCKET hSocket, uint32_t fEvents, PRTHCINTPTR phNative);
     81DECLHIDDEN(int)         rtSocketSetKeepAlive(RTSOCKET hSocket, bool fEnable, uint32_t cSecsIdle, uint32_t cSecsInterval);
    8182DECLHIDDEN(uint32_t)    rtSocketPollStart(RTSOCKET hSocket, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait);
    8283DECLHIDDEN(uint32_t)    rtSocketPollDone(RTSOCKET hSocket, uint32_t fEvents, bool fFinalEntry, bool fHarvestEvents);
  • trunk/src/VBox/Runtime/r3/socket.cpp

    r98103 r100171  
    4242# include <iprt/win/winsock2.h>
    4343# include <iprt/win/ws2tcpip.h>
     44# include <mstcpip.h>  /* for struct tcp_keepalive */
    4445#else /* !RT_OS_WINDOWS */
    4546# include <errno.h>
     
    28832884}
    28842885
     2886
     2887DECLHIDDEN(int) rtSocketSetKeepAlive(RTSOCKET hSocket, bool fEnable, uint32_t cSecsIdle, uint32_t cSecsInterval)
     2888{
     2889    RTSOCKETINT *pThis = hSocket;
     2890    AssertPtrReturn(pThis, UINT32_MAX);
     2891    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
     2892
     2893    if (!g_pfnWSAIoctl)
     2894        return VERR_NET_NOT_UNSUPPORTED;
     2895
     2896    struct tcp_keepalive keepAliveOptions;
     2897    DWORD dwBytesReturned;
     2898
     2899    keepAliveOptions.onoff = fEnable ? 1 : 0;
     2900    keepAliveOptions.keepalivetime = cSecsIdle * 1000;
     2901    keepAliveOptions.keepaliveinterval = cSecsInterval * 1000;
     2902
     2903    if (g_pfnWSAIoctl(pThis->hNative,
     2904                      SIO_KEEPALIVE_VALS,
     2905                      &keepAliveOptions, sizeof(keepAliveOptions),
     2906                      NULL, 0, &dwBytesReturned, NULL, NULL) == 0)
     2907        return VINF_SUCCESS;
     2908
     2909    int rc = rtSocketError();
     2910    AssertMsgFailed(("WSAIoctl(.., SIO_KEEPALIVE_VALS, ...) failed: rc=%Rrc\n", rc));
     2911    return rc;
     2912}
     2913
    28852914#endif  /* RT_OS_WINDOWS */
    28862915
  • trunk/src/VBox/Runtime/r3/tcp.cpp

    r99758 r100171  
    10011001
    10021002
     1003RTR3DECL(int)  RTTcpSetKeepAlive(RTSOCKET hSocket, bool fEnable, uint32_t cSecsIdle,
     1004                                 uint32_t cSecsInterval, uint32_t cFailedPktsBeforeClose)
     1005{
     1006#if !defined(RT_OS_WINDOWS)
     1007    int fFlag = fEnable ? 1 : 0;
     1008    int rc = rtSocketSetOpt(hSocket, SOL_SOCKET, SO_KEEPALIVE, &fFlag, sizeof(fFlag));
     1009    if (RT_FAILURE(rc))
     1010        return rc;
     1011
     1012# if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE)
     1013    rc = VINF_SUCCESS;
     1014
     1015    /* time in seconds that the connection must be idle before sending keep-alive probes */
     1016    if (cSecsIdle)
     1017    {
     1018#  if defined(TCP_KEEPALIVE) && !defined(TCP_KEEPIDLE)  /* macOS */
     1019#   define TCP_KEEPIDLE    TCP_KEEPALIVE
     1020#  endif
     1021        rc = rtSocketSetOpt(hSocket, IPPROTO_TCP, TCP_KEEPIDLE, &cSecsIdle, sizeof(cSecsIdle));
     1022        if (RT_FAILURE(rc))
     1023            return rc;
     1024    }
     1025
     1026    /* time in seconds between each keep-alive probe */
     1027    if (cSecsInterval)
     1028    {
     1029        rc = rtSocketSetOpt(hSocket, IPPROTO_TCP, TCP_KEEPINTVL, &cSecsInterval, sizeof(cSecsInterval));
     1030        if (RT_FAILURE(rc))
     1031            return rc;
     1032    }
     1033
     1034    /* count of keep-alive probes to send which don't receive a response before closing connection */
     1035    if (cFailedPktsBeforeClose)
     1036    {
     1037        rc = rtSocketSetOpt(hSocket, IPPROTO_TCP, TCP_KEEPCNT, &cFailedPktsBeforeClose, sizeof(cFailedPktsBeforeClose));
     1038        if (RT_FAILURE(rc))
     1039            return rc;
     1040    }
     1041
     1042    return rc;
     1043# else
     1044    return VERR_NOT_SUPPORTED;
     1045# endif
     1046#else
     1047    NOREF(cFailedPktsBeforeClose);
     1048    return rtSocketSetKeepAlive(hSocket, fEnable, cSecsIdle, cSecsInterval);
     1049#endif
     1050}
     1051
     1052
    10031053RTR3DECL(int)  RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)
    10041054{
  • trunk/src/VBox/Runtime/r3/win/init-win.cpp

    r98103 r100171  
    136136/** WSASend */
    137137DECL_HIDDEN_DATA(PFNWSASEND)                    g_pfnWSASend = NULL;
     138/** WSAIoctl */
     139DECL_HIDDEN_DATA(PFNWSAIOCTL)                   g_pfnWSAIoctl = NULL;
    138140/** socket */
    139141DECL_HIDDEN_DATA(PFNWINSOCKSOCKET)              g_pfnsocket = NULL;
     
    447449    g_pfnWSASocketW           = (decltype(g_pfnWSASocketW))         GetProcAddress(g_hModWinSock, "WSASocketW");
    448450    g_pfnWSASend              = (decltype(g_pfnWSASend))            GetProcAddress(g_hModWinSock, "WSASend");
     451    g_pfnWSAIoctl             = (decltype(g_pfnWSAIoctl))           GetProcAddress(g_hModWinSock, "WSAIoctl");
    449452    g_pfnsocket               = (decltype(g_pfnsocket))             GetProcAddress(g_hModWinSock, "socket");
    450453    g_pfnclosesocket          = (decltype(g_pfnclosesocket))        GetProcAddress(g_hModWinSock, "closesocket");
     
    478481    Assert(g_pfnWSASocketW           || g_fOldWinSock);
    479482    Assert(g_pfnWSASend              || g_fOldWinSock);
     483    Assert(g_pfnWSAIoctl             || g_fOldWinSock);
    480484    Assert(g_pfnsocket);
    481485    Assert(g_pfnclosesocket);
  • trunk/src/VBox/Runtime/r3/win/internal-r3-win.h

    r98103 r100171  
    167167/** WSASend */
    168168typedef int             (WINAPI *PFNWSASEND)(UINT_PTR, struct _WSABUF *, DWORD, LPDWORD, DWORD dwFlags,
     169                                             struct _OVERLAPPED *, uintptr_t /*LPWSAOVERLAPPED_COMPLETION_ROUTINE*/);
     170/** WSAIoctl */
     171typedef int             (WINAPI *PFNWSAIOCTL)(UINT_PTR, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD,
    169172                                             struct _OVERLAPPED *, uintptr_t /*LPWSAOVERLAPPED_COMPLETION_ROUTINE*/);
    170173
     
    219222extern DECL_HIDDEN_DATA(PFNWSASOCKETW)                   g_pfnWSASocketW;
    220223extern DECL_HIDDEN_DATA(PFNWSASEND)                      g_pfnWSASend;
     224extern DECL_HIDDEN_DATA(PFNWSAIOCTL)                     g_pfnWSAIoctl;
    221225extern DECL_HIDDEN_DATA(PFNWINSOCKSOCKET)                g_pfnsocket;
    222226extern DECL_HIDDEN_DATA(PFNWINSOCKCLOSESOCKET)           g_pfnclosesocket;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette