+ if (command == SIO_KEEPALIVE_VALS) {
+ uint32_t onoff;
+ uint32_t keepalivetime;
+ uint32_t keepaliveinterval;
+
+ if (i_len < (3 * sizeof (uint32_t))) {
+ WSASetLastError (WSAEINVAL);
+ return SOCKET_ERROR;
+ }
+ memcpy (&onoff, input, sizeof (uint32_t));
+ memcpy (&keepalivetime, input + sizeof (uint32_t), sizeof (uint32_t));
+ memcpy (&keepaliveinterval, input + 2 * sizeof (uint32_t), sizeof (uint32_t));
+ ret = setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (uint32_t));
+ if (ret < 0) {
+ gint errnum = errno;
+ errnum = errno_to_WSA (errnum, __func__);
+ WSASetLastError (errnum);
+ return SOCKET_ERROR;
+ }
+ if (onoff != 0) {
+#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
+ /* Values are in ms, but we need s */
+ uint32_t rem;
+
+ /* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
+ rem = keepalivetime % 1000;
+ keepalivetime /= 1000;
+ if (keepalivetime == 0 || rem >= 500)
+ keepalivetime++;
+ ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (uint32_t));
+ if (ret == 0) {
+ rem = keepaliveinterval % 1000;
+ keepaliveinterval /= 1000;
+ if (keepaliveinterval == 0 || rem >= 500)
+ keepaliveinterval++;
+ ret = setsockopt (fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (uint32_t));
+ }
+ if (ret != 0) {
+ gint errnum = errno;
+ errnum = errno_to_WSA (errnum, __func__);
+ WSASetLastError (errnum);
+ return SOCKET_ERROR;
+ }
+ return 0;
+#endif
+ }
+ return 0;
+ }
+