* 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'.
+Fri Oct 27 11:48:00 2000 Corinna Vinschen <corinna@vinschen.de>
+
+ * 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 <corinna@vinschen.de>
* dtable.cc (dtable::release): Check for socket. Change
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 \
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)
--- /dev/null
+/* 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 <errno.h>
+#include <sys/socket.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <winsock2.h>
+#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;
+}
+
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
ifc->ifc_len = cnt * sizeof (struct ifreq);
}
-static int
+int
get_ifconf (struct ifconf *ifc, int what)
{
unsigned long lip, lnp;
{
}
-/**********************************************************************/
-/* 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 ()
{
/* 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;