This is the mail archive of the cygwin-cvs@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[newlib-cygwin] Cygwin: sockets: Handle SO_RCVTIMEO and SO_SNDTIMEO


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=c51a0b74dcec39222d5a61189bfe4a6aa73dcf46

commit c51a0b74dcec39222d5a61189bfe4a6aa73dcf46
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Wed Feb 7 16:16:51 2018 +0100

    Cygwin: sockets: Handle SO_RCVTIMEO and SO_SNDTIMEO
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/fhandler.h         |  7 +++++++
 winsup/cygwin/fhandler_socket.cc | 21 ++++++++++++++++++--
 winsup/cygwin/net.cc             | 42 ++++++++++++++++++++++++++++++++++++++++
 winsup/cygwin/release/2.10.1     | 13 +++++++++++++
 winsup/cygwin/times.cc           | 16 +++++++++++++++
 winsup/cygwin/winsup.h           |  1 +
 6 files changed, 98 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 153e384..a446e75 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -524,6 +524,13 @@ class fhandler_socket: public fhandler_base
   void wmem (int nwmem) { _wmem = nwmem; }
 
  private:
+  DWORD _rcvtimeo; /* msecs */
+  DWORD _sndtimeo; /* msecs */
+ public:
+  DWORD &rcvtimeo () { return _rcvtimeo; }
+  DWORD &sndtimeo () { return _sndtimeo; }
+
+ private:
   struct _WSAPROTOCOL_INFOW *prot_info_ptr;
  public:
   void init_fixup_before ();
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 6eac689..92b4db9 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -227,6 +227,8 @@ fhandler_socket::fhandler_socket () :
   wsock_events (NULL),
   wsock_mtx (NULL),
   wsock_evt (NULL),
+  _rcvtimeo (INFINITE),
+  _sndtimeo (INFINITE),
   prot_info_ptr (NULL),
   sun_path (NULL),
   peer_sun_path (NULL),
@@ -752,6 +754,8 @@ fhandler_socket::wait_for_events (const long event_mask, const DWORD flags)
 
   int ret;
   long events = 0;
+  DWORD wfmo_timeout = 50;
+  DWORD timeout;
 
   WSAEVENT ev[3] = { wsock_evt, NULL, NULL };
   wait_signal_arrived here (ev[1]);
@@ -759,19 +763,32 @@ fhandler_socket::wait_for_events (const long event_mask, const DWORD flags)
   if ((ev[2] = pthread::get_cancel_event ()) != NULL)
     ++ev_cnt;
 
+  if (is_nonblocking () || (flags & MSG_DONTWAIT))
+    timeout = 0;
+  else if (event_mask & FD_READ)
+    timeout = rcvtimeo ();
+  else if (event_mask & FD_WRITE)
+    timeout = sndtimeo ();
+  else
+    timeout = INFINITE;
+
   while (!(ret = evaluate_events (event_mask, events, !(flags & MSG_PEEK)))
 	 && !events)
     {
-      if (is_nonblocking () || (flags & MSG_DONTWAIT))
+      if (timeout == 0)
 	{
 	  WSASetLastError (WSAEWOULDBLOCK);
 	  return SOCKET_ERROR;
 	}
 
-      switch (WSAWaitForMultipleEvents (ev_cnt, ev, FALSE, 50, FALSE))
+      if (timeout < wfmo_timeout)
+	wfmo_timeout = timeout;
+      switch (WSAWaitForMultipleEvents (ev_cnt, ev, FALSE, wfmo_timeout, FALSE))
 	{
 	  case WSA_WAIT_TIMEOUT:
 	  case WSA_WAIT_EVENT_0:
+	    if (timeout != INFINITE)
+	      timeout -= wfmo_timeout;
 	    break;
 
 	  case WSA_WAIT_EVENT_0 + 1:
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 6f96acb..43da5dc 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -851,6 +851,21 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval,
 		ignore = true;
 	      break;
 
+	    case SO_RCVTIMEO:
+	    case SO_SNDTIMEO:
+	      if (optlen < (socklen_t) sizeof (struct timeval))
+		{
+		  set_errno (EINVAL);
+		  __leave;
+		}
+	      if (timeval_to_ms ((struct timeval *) optval,
+				 (optname == SO_RCVTIMEO)
+				 ? fh->rcvtimeo () : fh->sndtimeo ()))
+		res = 0;
+	      else
+		set_errno (EDOM);
+	      __leave;
+
 	    default:
 	      break;
 	    }
@@ -999,6 +1014,33 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval,
 	      }
 	      break;
 
+	    case SO_RCVTIMEO:
+	    case SO_SNDTIMEO:
+	      {
+		struct timeval *time_out = (struct timeval *) optval;
+
+		if (*optlen < (socklen_t) sizeof *time_out)
+		  {
+		    set_errno (EINVAL);
+		    __leave;
+		  }
+		DWORD ms = (optname == SO_RCVTIMEO) ? fh->rcvtimeo ()
+						    : fh->sndtimeo ();
+		if (ms == 0 || ms == INFINITE)
+		  {
+		    time_out->tv_sec = 0;
+		    time_out->tv_usec = 0;
+		  }
+		else
+		  {
+		    time_out->tv_sec = ms / HZ;
+		    time_out->tv_usec = ((ms % HZ) * USPERSEC) / HZ;
+		  }
+		*optlen = (socklen_t) sizeof *time_out;
+		res = 0;
+		__leave;
+	      }
+
 	    default:
 	      break;
 	    }
diff --git a/winsup/cygwin/release/2.10.1 b/winsup/cygwin/release/2.10.1
new file mode 100644
index 0000000..f8fd4cb
--- /dev/null
+++ b/winsup/cygwin/release/2.10.1
@@ -0,0 +1,13 @@
+What's new:
+-----------
+
+
+What changed:
+-------------
+
+- SO_RCVTIMEO and SO_SNDTIMEO socket options are now honored.
+
+
+Bug Fixes
+---------
+
diff --git a/winsup/cygwin/times.cc b/winsup/cygwin/times.cc
index 86e32b8..198fc32 100644
--- a/winsup/cygwin/times.cc
+++ b/winsup/cygwin/times.cc
@@ -216,6 +216,22 @@ timeval_to_filetime (const struct timeval *time_in, PLARGE_INTEGER out)
 }
 
 /* Cygwin internal */
+bool
+timeval_to_ms (const struct timeval *time_in, DWORD &ms)
+{
+  if (time_in->tv_sec < 0 || time_in->tv_usec < 0
+      || time_in->tv_usec >= USPERSEC)
+    return false;
+  if ((time_in->tv_sec == 0 && time_in->tv_usec == 0)
+      || time_in->tv_sec >= INFINITE / HZ)
+    ms = INFINITE;
+  else
+    ms = time_in->tv_sec * HZ + (time_in->tv_usec + (USPERSEC/HZ) - 1)
+				/ (USPERSEC/HZ);
+  return true;
+}
+
+/* Cygwin internal */
 static timeval __stdcall
 time_t_to_timeval (time_t in)
 {
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index fcb08e2..1b3fbfe 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -206,6 +206,7 @@ void __stdcall to_timestruc_t (PLARGE_INTEGER, timestruc_t *);
 void __stdcall time_as_timestruc_t (timestruc_t *);
 void __stdcall timeval_to_filetime (const struct timeval *, PLARGE_INTEGER);
 void __stdcall timespec_to_filetime (const struct timespec *, PLARGE_INTEGER);
+bool timeval_to_ms (const struct timeval *, DWORD &);
 
 /* Console related */
 void __stdcall set_console_title (char *);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]