Cygwin: sockets: Handle SO_RCVTIMEO and SO_SNDTIMEO
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
51af517cab
commit
c51a0b74dc
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 *);
|
||||
|
|
Loading…
Reference in New Issue