From a2cdb048f6d311c6d5b59efa76343006553f8438 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 15 May 2001 08:15:54 +0000 Subject: [PATCH] * autoload.cc: Add autoload statements for ws2_32 functions `WSACloseEvent', `WSACreateEvent', `WSAGetOverlappedResult', `WSARecv', `WSARecvFrom', `WSASend', `WSASendTo' and `WSASetEvent', `WSAWaitForMultipleEvents'. * net.cc: Define wsock_evt. (wsock_event): New class. (cygwin_sendto): Use overlapped socket io if available. (cygwin_recvfrom): Ditto. (cygwin_recv): Ditto. (cygwin_send): Ditto. * security.cc (subauth): Set Win32 error to 0 to safely ask for the error code of dynamically loaded function `LsaRegisterLogonProcess'. --- winsup/cygwin/ChangeLog | 15 +++ winsup/cygwin/autoload.cc | 9 ++ winsup/cygwin/net.cc | 191 +++++++++++++++++++++++++++++++++----- winsup/cygwin/security.cc | 1 + 4 files changed, 191 insertions(+), 25 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 376170fdf..062a0c6df 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +Tue May 15 9:03:00 2001 Corinna Vinschen + + * autoload.cc: Add autoload statements for ws2_32 functions + `WSACloseEvent', `WSACreateEvent', `WSAGetOverlappedResult', + `WSARecv', `WSARecvFrom', `WSASend', `WSASendTo' and `WSASetEvent', + `WSAWaitForMultipleEvents'. + * net.cc: Define wsock_evt. + (wsock_event): New class. + (cygwin_sendto): Use overlapped socket io if available. + (cygwin_recvfrom): Ditto. + (cygwin_recv): Ditto. + (cygwin_send): Ditto. + * security.cc (subauth): Set Win32 error to 0 to safely ask for the + error code of dynamically loaded function `LsaRegisterLogonProcess'. + Mon May 14 15:37:29 2001 Christopher Faylor * errno.cc (_sys_errlist): Add missing commas. diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 633d91a51..f94a44512 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -265,8 +265,17 @@ LoadDLLfunc (shutdown, 8, wsock32) LoadDLLfunc (socket, 12, wsock32) LoadDLLinit (ws2_32) +LoadDLLfuncEx (WSACloseEvent, 4, ws2_32, 1) +LoadDLLfuncEx (WSACreateEvent, 0, ws2_32, 1) LoadDLLfuncEx (WSADuplicateSocketA, 12, ws2_32, 1) +LoadDLLfuncEx (WSAGetOverlappedResult, 20, ws2_32, 1) +LoadDLLfuncEx (WSARecv, 28, ws2_32, 1) +LoadDLLfuncEx (WSARecvFrom, 36, ws2_32, 1) +LoadDLLfuncEx (WSASend, 28, ws2_32, 1) +LoadDLLfuncEx (WSASendTo, 36, ws2_32, 1) +LoadDLLfuncEx (WSASetEvent, 4, ws2_32, 1) LoadDLLfuncEx (WSASocketA, 24, ws2_32, 1) +LoadDLLfuncEx (WSAWaitForMultipleEvents, 20, ws2_32, 1) LoadDLLinit (iphlpapi) LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1) diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 56848877b..b1b42ed4a 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -46,6 +46,63 @@ int __stdcall rresvport (int *); int sscanf (const char *, const char *, ...); } /* End of "C" section */ +class wsock_event +{ + WSAEVENT event; + WSAOVERLAPPED ovr; +public: + wsock_event () : event (NULL) {}; + + LPWSAOVERLAPPED prepare (); + int wait (int socket, LPDWORD flags); +}; + +LPWSAOVERLAPPED +wsock_event::prepare () +{ + LPWSAOVERLAPPED ret = NULL; + + SetLastError (0); + if ((event = WSACreateEvent ())) + { + memset (&ovr, 0, sizeof ovr); + ovr.hEvent = event; + ret = &ovr; + } + else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */ + WSASetLastError (0); + + debug_printf ("%d = wsock_event::prepare ()", ret); + return ret; +} + +int +wsock_event::wait (int socket, LPDWORD flags) +{ + int ret = -1; + WSAEVENT ev[2] = { event, signal_arrived }; + + switch (WSAWaitForMultipleEvents(2, ev, FALSE, WSA_INFINITE, FALSE)) + { + case WSA_WAIT_EVENT_0: + DWORD len; + if (WSAGetOverlappedResult(socket, &ovr, &len, FALSE, flags)) + ret = (int) len; + break; + case WSA_WAIT_EVENT_0 + 1: + WSASetLastError (WSAEINTR); + break; + case WSA_WAIT_FAILED: + break; + default: /* Should be impossible. *LOL* */ + WSASetLastError (WSAEFAULT); + break; + } + WSACloseEvent (event); + event = NULL; + return ret; +} + static WSADATA wsadata; /* Cygwin internal */ @@ -431,6 +488,9 @@ cygwin_sendto (int fd, const struct sockaddr *to, int tolen) { + int res; + wsock_event wsock_evt; + LPWSAOVERLAPPED ovr; fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd]; sockaddr_in sin; sigframe thisframe (mainthread); @@ -438,13 +498,34 @@ cygwin_sendto (int fd, if (get_inet_addr (to, tolen, &sin, &tolen) == 0) return -1; - int res = sendto (h->get_socket (), (const char *) buf, len, - flags, to, tolen); - if (res == SOCKET_ERROR) + if (!(ovr = wsock_evt.prepare ())) { - set_winsock_errno (); - res = -1; + debug_printf ("Fallback to winsock 1 sendto call"); + if ((res = sendto (h->get_socket (), (const char *) buf, len, flags, + to, tolen)) == SOCKET_ERROR) + { + set_winsock_errno (); + res = -1; + } } + else + { + WSABUF wsabuf = { len, (char *) buf }; + DWORD ret = 0; + if (WSASendTo (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags, + to, tolen, ovr, NULL) != SOCKET_ERROR) + res = ret; + else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) + { + set_winsock_errno (); + res = -1; + } + else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1) + set_winsock_errno (); + } + + syscall_printf ("%d = sendto (%d, %x, %x, %x)", res, fd, buf, len, flags); + return res; } @@ -457,17 +538,39 @@ cygwin_recvfrom (int fd, struct sockaddr *from, int *fromlen) { + int res; + wsock_event wsock_evt; + LPWSAOVERLAPPED ovr; fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd]; sigframe thisframe (mainthread); - debug_printf ("recvfrom %d", h->get_socket ()); - - int res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen); - if (res == SOCKET_ERROR) + if (!(ovr = wsock_evt.prepare ())) { - set_winsock_errno (); - res = -1; + debug_printf ("Fallback to winsock 1 recvfrom call"); + if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen)) + == SOCKET_ERROR) + { + set_winsock_errno (); + res = -1; + } } + else + { + WSABUF wsabuf = { len, (char *) buf }; + DWORD ret = 0; + if (WSARecvFrom (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags, + from, fromlen, ovr, NULL) != SOCKET_ERROR) + res = ret; + else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) + { + set_winsock_errno (); + res = -1; + } + else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1) + set_winsock_errno (); + } + + syscall_printf ("%d = recvfrom (%d, %x, %x, %x)", res, fd, buf, len, flags); return res; } @@ -1064,21 +1167,37 @@ cygwin_getpeername (int fd, struct sockaddr *name, int *len) extern "C" int cygwin_recv (int fd, void *buf, int len, unsigned int flags) { + int res; + wsock_event wsock_evt; + LPWSAOVERLAPPED ovr; fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd]; sigframe thisframe (mainthread); - int res = recv (h->get_socket (), (char *) buf, len, flags); - if (res == SOCKET_ERROR) + if (!(ovr = wsock_evt.prepare ())) { - set_winsock_errno (); - res = -1; + debug_printf ("Fallback to winsock 1 recv call"); + if ((res = recv (h->get_socket (), (char *) buf, len, flags)) + == SOCKET_ERROR) + { + set_winsock_errno (); + res = -1; + } + } + else + { + WSABUF wsabuf = { len, (char *) buf }; + DWORD ret = 0; + if (WSARecv (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags, + ovr, NULL) != SOCKET_ERROR) + res = ret; + else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) + { + set_winsock_errno (); + res = -1; + } + else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1) + set_winsock_errno (); } - -#if 0 - if (res > 0 && res < 200) - for (int i=0; i < res; i++) - system_printf ("%d %x %c", i, ((char *) buf)[i], ((char *) buf)[i]); -#endif syscall_printf ("%d = recv (%d, %x, %x, %x)", res, fd, buf, len, flags); @@ -1089,14 +1208,36 @@ cygwin_recv (int fd, void *buf, int len, unsigned int flags) extern "C" int cygwin_send (int fd, const void *buf, int len, unsigned int flags) { + int res; + wsock_event wsock_evt; + LPWSAOVERLAPPED ovr; fhandler_socket *h = (fhandler_socket *) cygheap->fdtab[fd]; sigframe thisframe (mainthread); - int res = send (h->get_socket (), (const char *) buf, len, flags); - if (res == SOCKET_ERROR) + if (!(ovr = wsock_evt.prepare ())) { - set_winsock_errno (); - res = -1; + debug_printf ("Fallback to winsock 1 send call"); + if ((res = send (h->get_socket (), (const char *) buf, len, flags)) + == SOCKET_ERROR) + { + set_winsock_errno (); + res = -1; + } + } + else + { + WSABUF wsabuf = { len, (char *) buf }; + DWORD ret = 0; + if (WSASend (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags, + ovr, NULL) != SOCKET_ERROR) + res = ret; + else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) + { + set_winsock_errno (); + res = -1; + } + else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1) + set_winsock_errno (); } syscall_printf ("%d = send (%d, %x, %d, %x)", res, fd, buf, len, flags); diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 5755cc3c5..95058f4a9 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -188,6 +188,7 @@ subauth (struct passwd *pw) /* Register as logon process. */ str2lsa (name, "Cygwin"); + SetLastError (0); ret = LsaRegisterLogonProcess(&name, &lsa_hdl, &sec_mode); if (ret != STATUS_SUCCESS) {