Cygwin: sockets: Handle SO_RCVTIMEO and SO_SNDTIMEO
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
		| @@ -523,6 +523,13 @@ class fhandler_socket: public fhandler_base | ||||
|   void rmem (int nrmem) { _rmem = nrmem; } | ||||
|   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: | ||||
|   | ||||
| @@ -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: | ||||
|   | ||||
| @@ -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; | ||||
| 	    } | ||||
|   | ||||
							
								
								
									
										13
									
								
								winsup/cygwin/release/2.10.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								winsup/cygwin/release/2.10.1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| What's new: | ||||
| ----------- | ||||
|  | ||||
|  | ||||
| What changed: | ||||
| ------------- | ||||
|  | ||||
| - SO_RCVTIMEO and SO_SNDTIMEO socket options are now honored. | ||||
|  | ||||
|  | ||||
| Bug Fixes | ||||
| --------- | ||||
|  | ||||
| @@ -215,6 +215,22 @@ timeval_to_filetime (const struct timeval *time_in, PLARGE_INTEGER out) | ||||
| 		  + time_in->tv_usec * (NS100PERSEC/USPERSEC) + FACTOR; | ||||
| } | ||||
|  | ||||
| /* 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) | ||||
|   | ||||
| @@ -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 *); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user