From afd5033d83e5871f96c15cd72d790692f643c4bd Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 27 Oct 2000 09:50:33 +0000 Subject: [PATCH] * fhandler_socket.cc: New file. * Makefile.in: Add fhandler_socket.o to dependencies. * fhandler.h: Change comment. * net.cc Move all fhandler_socket methods to fhandler_socket.cc. * winsup.h: Add declaration for `ws2_32_handle'. --- winsup/cygwin/ChangeLog | 8 + winsup/cygwin/Makefile.in | 4 +- winsup/cygwin/fhandler.h | 2 +- winsup/cygwin/fhandler_socket.cc | 310 +++++++++++++++++++++++++++++++ winsup/cygwin/net.cc | 299 +---------------------------- winsup/cygwin/winsup.h | 1 + 6 files changed, 324 insertions(+), 300 deletions(-) create mode 100644 winsup/cygwin/fhandler_socket.cc diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index fbb75b33e..a33842f56 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,11 @@ +Fri Oct 27 11:48:00 2000 Corinna Vinschen + + * fhandler_socket.cc: New file. + * Makefile.in: Add fhandler_socket.o to dependencies. + * fhandler.h: Change comment. + * net.cc Move all fhandler_socket methods to fhandler_socket.cc. + * winsup.h: Add declaration for `ws2_32_handle'. + Thu Oct 26 11:51:59 2000 Corinna Vinschen * dtable.cc (dtable::release): Check for socket. Change diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 294cadaf9..85a535e99 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -115,8 +115,8 @@ DLL_IMPORTS:=$(w32api_lib)/libkernel32.a DLL_OFILES:=assert.o cygheap.o dcrt0.o debug.o delqueue.o dir.o dlfcn.o \ dll_init.o dtable.o environ.o errno.o exceptions.o exec.o external.o \ fcntl.o fhandler.o fhandler_clipboard.o fhandler_console.o \ - fhandler_floppy.o fhandler_mem.o \ - fhandler_random.o fhandler_raw.o fhandler_serial.o fhandler_tape.o \ + fhandler_floppy.o fhandler_mem.o fhandler_random.o fhandler_raw.o \ + fhandler_serial.o fhandler_socket.o fhandler_tape.o \ fhandler_termios.o fhandler_tty.o fhandler_windows.o fhandler_zero.o \ fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o malloc.o \ miscfuncs.o mmap.o \ diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index f8c3bd7e8..1732b99c5 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -29,7 +29,7 @@ details. */ fhandler_dev_tape (fhandler_tape.cc) fhandler_pipe - fhandler_socket (net.cc) + fhandler_socket (fhandler_socket.cc) fhandler_tty_slave (tty.cc) fhandler_pty_master (tty.cc) diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc new file mode 100644 index 000000000..f859f0936 --- /dev/null +++ b/winsup/cygwin/fhandler_socket.cc @@ -0,0 +1,310 @@ +/* fhandler_socket.cc. See fhandler.h for a description of the fhandler classes. + + Copyright 2000 Cygnus Solutions. + + This file is part of Cygwin. + + This software is a copyrighted work licensed under the terms of the + Cygwin license. Please consult the file "CYGWIN_LICENSE" for + details. */ + +/* #define DEBUG_NEST_ON 1 */ + +#define __INSIDE_CYGWIN_NET__ + +#define Win32_Winsock +#include "winsup.h" +#include +#include + +#include +#include +#include +#include "cygheap.h" +#include "cygerrno.h" +#include "fhandler.h" +#include "dtable.h" +#include "sigproc.h" + +/**********************************************************************/ +/* fhandler_socket */ + +fhandler_socket::fhandler_socket (const char *name) : + fhandler_base (FH_SOCKET, name) +{ + set_cb (sizeof *this); + set_need_fork_fixup (); + prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF, + sizeof (WSAPROTOCOL_INFOA)); +} + +fhandler_socket::~fhandler_socket () +{ + if (prot_info_ptr) + cfree (prot_info_ptr); +} + +void +fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id) +{ + int ret = 1; + + if (prot_info_ptr && + (ret = WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr))) + { + debug_printf ("WSADuplicateSocket error"); + set_winsock_errno (); + } + if (!ret && ws2_32_handle) + { + debug_printf ("WSADuplicateSocket went fine, dwServiceFlags1=%d", + prot_info_ptr->dwServiceFlags1); + } + else + { + fhandler_base::fixup_before_fork_exec (win_proc_id); + debug_printf ("Without Winsock 2.0"); + } +} + +void +fhandler_socket::fixup_after_fork (HANDLE parent) +{ + SOCKET new_sock = INVALID_SOCKET; + + debug_printf ("WSASocket begin, dwServiceFlags1=%d", + prot_info_ptr->dwServiceFlags1); + if (prot_info_ptr && + (new_sock = WSASocketA (FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + prot_info_ptr, 0, 0)) == INVALID_SOCKET) + { + debug_printf ("WSASocket error"); + set_winsock_errno (); + } + if (new_sock != INVALID_SOCKET && ws2_32_handle) + { + debug_printf ("WSASocket went fine"); + set_io_handle ((HANDLE) new_sock); + } + else + { + fhandler_base::fixup_after_fork (parent); + debug_printf ("Without Winsock 2.0"); + } +} + +int +fhandler_socket::dup (fhandler_base *child) +{ + fhandler_socket *fhs = (fhandler_socket *) child; + fhs->set_io_handle (get_io_handle ()); + fhs->fixup_before_fork_exec (GetCurrentProcessId ()); + if (ws2_32_handle) + { + fhs->fixup_after_fork (hMainProc); + return 0; + } + return fhandler_base::dup (child); +} + +int +fhandler_socket::read (void *ptr, size_t len) +{ + sigframe thisframe (mainthread); + int res = recv (get_socket (), (char *) ptr, len, 0); + if (res == SOCKET_ERROR) + { + set_winsock_errno (); + } + return res; +} + +int +fhandler_socket::write (const void *ptr, size_t len) +{ + sigframe thisframe (mainthread); + int res = send (get_socket (), (const char *) ptr, len, 0); + if (res == SOCKET_ERROR) + { + set_winsock_errno (); + if (get_errno () == ECONNABORTED || get_errno () == ECONNRESET) + _raise (SIGPIPE); + } + return res; +} + +/* Cygwin internal */ +int +fhandler_socket::close () +{ + int res = 0; + sigframe thisframe (mainthread); + + if (closesocket (get_socket ())) + { + set_winsock_errno (); + res = -1; + } + + return res; +} + +#define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT) + +/* Cygwin internal */ +int +fhandler_socket::ioctl (unsigned int cmd, void *p) +{ + extern int get_ifconf (struct ifconf *ifc, int what); /* net.cc */ + int res; + struct ifconf *ifc; + struct ifreq *ifr; + sigframe thisframe (mainthread); + + switch (cmd) + { + case SIOCGIFCONF: + ifc = (struct ifconf *) p; + if (ifc == 0) + { + set_errno (EINVAL); + return -1; + } + res = get_ifconf (ifc, cmd); + if (res) + debug_printf ("error in get_ifconf\n"); + break; + case SIOCGIFFLAGS: + ifr = (struct ifreq *) p; + if (ifr == 0) + { + set_errno (EINVAL); + return -1; + } + ifr->ifr_flags = IFF_NOTRAILERS | IFF_UP | IFF_RUNNING; + if (((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr + == INADDR_LOOPBACK) + ifr->ifr_flags |= IFF_LOOPBACK; + else + ifr->ifr_flags |= IFF_BROADCAST; + res = 0; + break; + case SIOCGIFBRDADDR: + case SIOCGIFNETMASK: + case SIOCGIFADDR: + { + char buf[2048]; + struct ifconf ifc; + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + struct ifreq *ifrp; + + struct ifreq *ifr = (struct ifreq *) p; + if (ifr == 0) + { + debug_printf ("ifr == NULL\n"); + set_errno (EINVAL); + return -1; + } + + res = get_ifconf (&ifc, cmd); + if (res) + { + debug_printf ("error in get_ifconf\n"); + break; + } + + debug_printf (" name: %s\n", ifr->ifr_name); + for (ifrp = ifc.ifc_req; + (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len; + ++ifrp) + { + debug_printf ("testname: %s\n", ifrp->ifr_name); + if (! strcmp (ifrp->ifr_name, ifr->ifr_name)) + { + switch (cmd) + { + case SIOCGIFADDR: + ifr->ifr_addr = ifrp->ifr_addr; + break; + case SIOCGIFBRDADDR: + ifr->ifr_broadaddr = ifrp->ifr_broadaddr; + break; + case SIOCGIFNETMASK: + ifr->ifr_netmask = ifrp->ifr_netmask; + break; + } + break; + } + } + if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len) + { + set_errno (EINVAL); + return -1; + } + break; + } + case FIOASYNC: + res = WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, + *(int *) p ? ASYNC_MASK : 0); + syscall_printf ("Async I/O on socket %s", + *(int *) p ? "started" : "cancelled"); + set_async (*(int *) p); + break; + default: + /* We must cancel WSAAsyncSelect (if any) before setting socket to + * blocking mode + */ + if (cmd == FIONBIO && *(int *) p == 0) + WSAAsyncSelect (get_socket (), gethwnd (), 0, 0); + res = ioctlsocket (get_socket (), cmd, (unsigned long *) p); + if (res == SOCKET_ERROR) + set_winsock_errno (); + if (cmd == FIONBIO) + { + syscall_printf ("socket is now %sblocking", + *(int *) p ? "un" : ""); + /* Start AsyncSelect if async socket unblocked */ + if (*(int *) p && get_async ()) + WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, ASYNC_MASK); + } + break; + } + syscall_printf ("%d = ioctl_socket (%x, %x)", res, cmd, p); + return res; +} + +int +fhandler_socket::fcntl (int cmd, void *arg) +{ + int res = 0; + int request, current; + + switch (cmd) + { + case F_SETFL: + { + /* Care for the old O_NDELAY flag. If one of the flags is set, + both flags are set. */ + int new_flags = (int) arg; + if (new_flags & (O_NONBLOCK | OLD_O_NDELAY)) + new_flags |= O_NONBLOCK | OLD_O_NDELAY; + request = (new_flags & O_NONBLOCK) ? 1 : 0; + current = (get_flags () & O_NONBLOCK) ? 1 : 0; + if (request != current && (res = ioctl (FIONBIO, &request))) + break; + if (request) + set_flags (get_flags () | O_NONBLOCK | OLD_O_NDELAY); + else + set_flags (get_flags () & ~(O_NONBLOCK | OLD_O_NDELAY)); + break; + } + default: + res = fhandler_base::fcntl (cmd, arg); + break; + } + return res; +} + diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 7f587a1de..50c097d74 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -44,8 +44,7 @@ int __stdcall rresvport (int *); int sscanf (const char *, const char *, ...); } /* End of "C" section */ -extern HANDLE ws2_32_handle; -WSADATA wsadata; +static WSADATA wsadata; /* Cygwin internal */ static SOCKET __stdcall @@ -1514,7 +1513,7 @@ out: ifc->ifc_len = cnt * sizeof (struct ifreq); } -static int +int get_ifconf (struct ifconf *ifc, int what) { unsigned long lip, lnp; @@ -1783,300 +1782,6 @@ endhostent (void) { } -/**********************************************************************/ -/* fhandler_socket */ - -fhandler_socket::fhandler_socket (const char *name) : - fhandler_base (FH_SOCKET, name) -{ - set_cb (sizeof *this); - set_need_fork_fixup (); - prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF, - sizeof (WSAPROTOCOL_INFOA)); -} - -fhandler_socket::~fhandler_socket () -{ - if (prot_info_ptr) - cfree (prot_info_ptr); -} - -void -fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id) -{ - int ret = 1; - - if (prot_info_ptr && - (ret = WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr))) - { - debug_printf ("WSADuplicateSocket error"); - set_winsock_errno (); - } - if (!ret && ws2_32_handle) - { - debug_printf ("WSADuplicateSocket went fine, dwServiceFlags1=%d", - prot_info_ptr->dwServiceFlags1); - } - else - { - fhandler_base::fixup_before_fork_exec (win_proc_id); - debug_printf ("Without Winsock 2.0"); - } -} - -void -fhandler_socket::fixup_after_fork (HANDLE parent) -{ - SOCKET new_sock = INVALID_SOCKET; - - debug_printf ("WSASocket begin, dwServiceFlags1=%d", - prot_info_ptr->dwServiceFlags1); - if (prot_info_ptr && - (new_sock = WSASocketA (FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - prot_info_ptr, 0, 0)) == INVALID_SOCKET) - { - debug_printf ("WSASocket error"); - set_winsock_errno (); - } - if (new_sock != INVALID_SOCKET && ws2_32_handle) - { - debug_printf ("WSASocket went fine"); - set_io_handle ((HANDLE) new_sock); - } - else - { - fhandler_base::fixup_after_fork (parent); - debug_printf ("Without Winsock 2.0"); - } -} - -int -fhandler_socket::dup (fhandler_base *child) -{ - fhandler_socket *fhs = (fhandler_socket *) child; - fhs->set_io_handle (get_io_handle ()); - fhs->fixup_before_fork_exec (GetCurrentProcessId ()); - if (ws2_32_handle) - { - fhs->fixup_after_fork (hMainProc); - return 0; - } - return fhandler_base::dup (child); -} - -int -fhandler_socket::read (void *ptr, size_t len) -{ - sigframe thisframe (mainthread); - int res = recv (get_socket (), (char *) ptr, len, 0); - if (res == SOCKET_ERROR) - { - set_winsock_errno (); - } - return res; -} - -int -fhandler_socket::write (const void *ptr, size_t len) -{ - sigframe thisframe (mainthread); - int res = send (get_socket (), (const char *) ptr, len, 0); - if (res == SOCKET_ERROR) - { - set_winsock_errno (); - if (get_errno () == ECONNABORTED || get_errno () == ECONNRESET) - _raise (SIGPIPE); - } - return res; -} - -/* Cygwin internal */ -int -fhandler_socket::close () -{ - int res = 0; - sigframe thisframe (mainthread); - - if (closesocket (get_socket ())) - { - set_winsock_errno (); - res = -1; - } - - return res; -} - -/* Cygwin internal */ -/* - * Return the flags settings for an interface. - */ -static int -get_if_flags (struct ifreq *ifr) -{ - struct sockaddr_in *sa = (struct sockaddr_in *) &ifr->ifr_addr; - - short flags = IFF_NOTRAILERS | IFF_UP | IFF_RUNNING; - if (sa->sin_addr.s_addr == INADDR_LOOPBACK) - flags |= IFF_LOOPBACK; - else - flags |= IFF_BROADCAST; - - ifr->ifr_flags = flags; - return 0; -} - -#define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT) - -/* Cygwin internal */ -int -fhandler_socket::ioctl (unsigned int cmd, void *p) -{ - int res; - struct ifconf *ifc; - struct ifreq *ifr; - sigframe thisframe (mainthread); - - switch (cmd) - { - case SIOCGIFCONF: - ifc = (struct ifconf *) p; - if (ifc == 0) - { - set_errno (EINVAL); - return -1; - } - res = get_ifconf (ifc, cmd); - if (res) - debug_printf ("error in get_ifconf\n"); - break; - case SIOCGIFFLAGS: - ifr = (struct ifreq *) p; - if (ifr == 0) - { - set_errno (EINVAL); - return -1; - } - res = get_if_flags (ifr); - break; - case SIOCGIFBRDADDR: - case SIOCGIFNETMASK: - case SIOCGIFADDR: - { - char buf[2048]; - struct ifconf ifc; - ifc.ifc_len = sizeof (buf); - ifc.ifc_buf = buf; - struct ifreq *ifrp; - - struct ifreq *ifr = (struct ifreq *) p; - if (ifr == 0) - { - debug_printf ("ifr == NULL\n"); - set_errno (EINVAL); - return -1; - } - - res = get_ifconf (&ifc, cmd); - if (res) - { - debug_printf ("error in get_ifconf\n"); - break; - } - - debug_printf (" name: %s\n", ifr->ifr_name); - for (ifrp = ifc.ifc_req; - (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len; - ++ifrp) - { - debug_printf ("testname: %s\n", ifrp->ifr_name); - if (! strcmp (ifrp->ifr_name, ifr->ifr_name)) - { - switch (cmd) - { - case SIOCGIFADDR: - ifr->ifr_addr = ifrp->ifr_addr; - break; - case SIOCGIFBRDADDR: - ifr->ifr_broadaddr = ifrp->ifr_broadaddr; - break; - case SIOCGIFNETMASK: - ifr->ifr_netmask = ifrp->ifr_netmask; - break; - } - break; - } - } - if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len) - { - set_errno (EINVAL); - return -1; - } - break; - } - case FIOASYNC: - res = WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, - *(int *) p ? ASYNC_MASK : 0); - syscall_printf ("Async I/O on socket %s", - *(int *) p ? "started" : "cancelled"); - set_async (*(int *) p); - break; - default: - /* We must cancel WSAAsyncSelect (if any) before setting socket to - * blocking mode - */ - if (cmd == FIONBIO && *(int *) p == 0) - WSAAsyncSelect (get_socket (), gethwnd (), 0, 0); - res = ioctlsocket (get_socket (), cmd, (unsigned long *) p); - if (res == SOCKET_ERROR) - set_winsock_errno (); - if (cmd == FIONBIO) - { - syscall_printf ("socket is now %sblocking", - *(int *) p ? "un" : ""); - /* Start AsyncSelect if async socket unblocked */ - if (*(int *) p && get_async ()) - WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, ASYNC_MASK); - } - break; - } - syscall_printf ("%d = ioctl_socket (%x, %x)", res, cmd, p); - return res; -} - -int -fhandler_socket::fcntl (int cmd, void *arg) -{ - int res = 0; - int request, current; - - switch (cmd) - { - case F_SETFL: - { - /* Care for the old O_NDELAY flag. If one of the flags is set, - both flags are set. */ - int new_flags = (int) arg; - if (new_flags & (O_NONBLOCK | OLD_O_NDELAY)) - new_flags |= O_NONBLOCK | OLD_O_NDELAY; - request = (new_flags & O_NONBLOCK) ? 1 : 0; - current = (get_flags () & O_NONBLOCK) ? 1 : 0; - if (request != current && (res = ioctl (FIONBIO, &request))) - break; - if (request) - set_flags (get_flags () | O_NONBLOCK | OLD_O_NDELAY); - else - set_flags (get_flags () & ~(O_NONBLOCK | OLD_O_NDELAY)); - break; - } - default: - res = fhandler_base::fcntl (cmd, arg); - break; - } - return res; -} - static void wsock_init () { diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index dbbcb620e..29cf92d11 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -173,6 +173,7 @@ void __stdcall window_terminate (void); /* Globals that handle initialization of winsock in a child process. */ extern HANDLE wsock32_handle; +extern HANDLE ws2_32_handle; /* Globals that handle initialization of netapi in a child process. */ extern HANDLE netapi32_handle; -- 2.43.5