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 rmem (int nrmem) { _rmem = nrmem; }
|
||||||
void wmem (int nwmem) { _wmem = nwmem; }
|
void wmem (int nwmem) { _wmem = nwmem; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
DWORD _rcvtimeo; /* msecs */
|
||||||
|
DWORD _sndtimeo; /* msecs */
|
||||||
|
public:
|
||||||
|
DWORD &rcvtimeo () { return _rcvtimeo; }
|
||||||
|
DWORD &sndtimeo () { return _sndtimeo; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct _WSAPROTOCOL_INFOW *prot_info_ptr;
|
struct _WSAPROTOCOL_INFOW *prot_info_ptr;
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -227,6 +227,8 @@ fhandler_socket::fhandler_socket () :
|
||||||
wsock_events (NULL),
|
wsock_events (NULL),
|
||||||
wsock_mtx (NULL),
|
wsock_mtx (NULL),
|
||||||
wsock_evt (NULL),
|
wsock_evt (NULL),
|
||||||
|
_rcvtimeo (INFINITE),
|
||||||
|
_sndtimeo (INFINITE),
|
||||||
prot_info_ptr (NULL),
|
prot_info_ptr (NULL),
|
||||||
sun_path (NULL),
|
sun_path (NULL),
|
||||||
peer_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;
|
int ret;
|
||||||
long events = 0;
|
long events = 0;
|
||||||
|
DWORD wfmo_timeout = 50;
|
||||||
|
DWORD timeout;
|
||||||
|
|
||||||
WSAEVENT ev[3] = { wsock_evt, NULL, NULL };
|
WSAEVENT ev[3] = { wsock_evt, NULL, NULL };
|
||||||
wait_signal_arrived here (ev[1]);
|
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)
|
if ((ev[2] = pthread::get_cancel_event ()) != NULL)
|
||||||
++ev_cnt;
|
++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)))
|
while (!(ret = evaluate_events (event_mask, events, !(flags & MSG_PEEK)))
|
||||||
&& !events)
|
&& !events)
|
||||||
{
|
{
|
||||||
if (is_nonblocking () || (flags & MSG_DONTWAIT))
|
if (timeout == 0)
|
||||||
{
|
{
|
||||||
WSASetLastError (WSAEWOULDBLOCK);
|
WSASetLastError (WSAEWOULDBLOCK);
|
||||||
return SOCKET_ERROR;
|
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_TIMEOUT:
|
||||||
case WSA_WAIT_EVENT_0:
|
case WSA_WAIT_EVENT_0:
|
||||||
|
if (timeout != INFINITE)
|
||||||
|
timeout -= wfmo_timeout;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WSA_WAIT_EVENT_0 + 1:
|
case WSA_WAIT_EVENT_0 + 1:
|
||||||
|
|
|
@ -851,6 +851,21 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval,
|
||||||
ignore = true;
|
ignore = true;
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -999,6 +1014,33 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval,
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
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;
|
+ 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 */
|
/* Cygwin internal */
|
||||||
static timeval __stdcall
|
static timeval __stdcall
|
||||||
time_t_to_timeval (time_t in)
|
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 time_as_timestruc_t (timestruc_t *);
|
||||||
void __stdcall timeval_to_filetime (const struct timeval *, PLARGE_INTEGER);
|
void __stdcall timeval_to_filetime (const struct timeval *, PLARGE_INTEGER);
|
||||||
void __stdcall timespec_to_filetime (const struct timespec *, PLARGE_INTEGER);
|
void __stdcall timespec_to_filetime (const struct timespec *, PLARGE_INTEGER);
|
||||||
|
bool timeval_to_ms (const struct timeval *, DWORD &);
|
||||||
|
|
||||||
/* Console related */
|
/* Console related */
|
||||||
void __stdcall set_console_title (char *);
|
void __stdcall set_console_title (char *);
|
||||||
|
|
Loading…
Reference in New Issue