]>
sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/fhandler_socket.cc
1 /* fhandler_socket.cc. See fhandler.h for a description of the fhandler classes.
3 Copyright 2000, 2001 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 /* #define DEBUG_NEST_ON 1 */
13 #define __INSIDE_CYGWIN_NET__
17 #include <sys/socket.h>
18 #include <asm/byteorder.h>
23 #define USE_SYS_TYPES_FD_SET
27 #include "cygwin/version.h"
28 #include "perprocess.h"
34 #define SECRET_EVENT_NAME "cygwin.local_socket.secret.%d.%08x-%08x-%08x-%08x"
35 #define ENTROPY_SOURCE_NAME "/dev/urandom"
36 #define ENTROPY_SOURCE_DEV_UNIT 9
38 fhandler_dev_random
* entropy_source
= NULL
;
40 /**********************************************************************/
43 fhandler_socket::fhandler_socket (const char *name
) :
44 fhandler_base (FH_SOCKET
, name
)
46 set_cb (sizeof *this);
47 set_need_fork_fixup ();
48 prot_info_ptr
= (LPWSAPROTOCOL_INFOA
) cmalloc (HEAP_BUF
,
49 sizeof (WSAPROTOCOL_INFOA
));
52 fhandler_socket::~fhandler_socket ()
55 cfree (prot_info_ptr
);
59 fhandler_socket::set_connect_secret ()
63 void *buf
= malloc (sizeof (fhandler_dev_random
));
64 entropy_source
= new (buf
) fhandler_dev_random (ENTROPY_SOURCE_NAME
,
65 ENTROPY_SOURCE_DEV_UNIT
);
68 !entropy_source
->open (ENTROPY_SOURCE_NAME
, O_RDONLY
))
70 delete entropy_source
;
71 entropy_source
= NULL
;
73 if (!entropy_source
||
74 (entropy_source
->read (connect_secret
, sizeof (connect_secret
)) !=
75 sizeof (connect_secret
)))
76 bzero ((char*) connect_secret
, sizeof (connect_secret
));
80 fhandler_socket::get_connect_secret (char* buf
)
82 __small_sprintf (buf
, "%08x-%08x-%08x-%08x",
83 connect_secret
[0], connect_secret
[1],
84 connect_secret
[2], connect_secret
[3]);
88 fhandler_socket::create_secret_event (int* secret
)
91 int* secret_ptr
= (secret
? : connect_secret
);
92 struct sockaddr_in sin
;
93 int sin_len
= sizeof (sin
);
95 if (getsockname (get_socket (), (struct sockaddr
*) &sin
, &sin_len
))
97 debug_printf ("error getting local socket name (%d)", WSAGetLastError ());
101 __small_sprintf (buf
, SECRET_EVENT_NAME
, sin
.sin_port
,
102 secret_ptr
[0], secret_ptr
[1],
103 secret_ptr
[2], secret_ptr
[3]);
104 secret_event
= CreateEvent (get_inheritance (), FALSE
, FALSE
, buf
);
105 if (!secret_event
&& GetLastError () == ERROR_ALREADY_EXISTS
)
106 secret_event
= OpenEvent (EVENT_ALL_ACCESS
, FALSE
, buf
);
109 ProtectHandle (secret_event
);
115 fhandler_socket::signal_secret_event ()
118 SetEvent (secret_event
);
122 fhandler_socket::close_secret_event ()
125 ForceCloseHandle (secret_event
);
130 fhandler_socket::check_peer_secret_event (struct sockaddr_in
* peer
, int* secret
)
134 int* secret_ptr
= (secret
? : connect_secret
);
136 __small_sprintf (buf
, SECRET_EVENT_NAME
, peer
->sin_port
,
137 secret_ptr
[0], secret_ptr
[1],
138 secret_ptr
[2], secret_ptr
[3]);
139 ev
= CreateEvent (&sec_none_nih
, FALSE
, FALSE
, buf
);
140 if (!ev
&& GetLastError () == ERROR_ALREADY_EXISTS
)
142 debug_printf ("%s event already exist");
143 ev
= OpenEvent (EVENT_ALL_ACCESS
, FALSE
, buf
);
146 signal_secret_event ();
150 DWORD rc
= WaitForSingleObject (ev
, 10000);
151 debug_printf ("WFSO rc=%d", rc
);
153 return (rc
== WAIT_OBJECT_0
? 1 : 0 );
160 fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id
)
165 (ret
= WSADuplicateSocketA (get_socket (), win_proc_id
, prot_info_ptr
)))
167 debug_printf ("WSADuplicateSocket error");
168 set_winsock_errno ();
170 if (!ret
&& ws2_32_handle
)
172 debug_printf ("WSADuplicateSocket went fine, dwServiceFlags1=%d",
173 prot_info_ptr
->dwServiceFlags1
);
177 fhandler_base::fixup_before_fork_exec (win_proc_id
);
178 debug_printf ("Without Winsock 2.0");
183 fhandler_socket::fixup_after_fork (HANDLE parent
)
185 SOCKET new_sock
= INVALID_SOCKET
;
187 debug_printf ("WSASocket begin, dwServiceFlags1=%d",
188 prot_info_ptr
->dwServiceFlags1
);
190 (new_sock
= WSASocketA (FROM_PROTOCOL_INFO
,
193 prot_info_ptr
, 0, 0)) == INVALID_SOCKET
)
195 debug_printf ("WSASocket error");
196 set_winsock_errno ();
198 if (new_sock
!= INVALID_SOCKET
&& ws2_32_handle
)
200 debug_printf ("WSASocket went fine");
201 set_io_handle ((HANDLE
) new_sock
);
205 fhandler_base::fixup_after_fork (parent
);
206 debug_printf ("Without Winsock 2.0");
209 fork_fixup (parent
, secret_event
, "secret_event");
213 fhandler_socket::dup (fhandler_base
*child
)
215 fhandler_socket
*fhs
= (fhandler_socket
*) child
;
216 fhs
->addr_family
= addr_family
;
217 fhs
->set_io_handle (get_io_handle ());
218 fhs
->fixup_before_fork_exec (GetCurrentProcessId ());
221 fhs
->fixup_after_fork (hMainProc
);
224 return fhandler_base::dup (child
);
228 fhandler_socket::read (void *ptr
, size_t len
)
230 sigframe
thisframe (mainthread
);
231 int res
= recv (get_socket (), (char *) ptr
, len
, 0);
232 if (res
== SOCKET_ERROR
)
234 set_winsock_errno ();
240 fhandler_socket::write (const void *ptr
, size_t len
)
242 sigframe
thisframe (mainthread
);
243 int res
= send (get_socket (), (const char *) ptr
, len
, 0);
244 if (res
== SOCKET_ERROR
)
246 set_winsock_errno ();
247 if (get_errno () == ECONNABORTED
|| get_errno () == ECONNRESET
)
253 /* Cygwin internal */
255 fhandler_socket::close ()
258 sigframe
thisframe (mainthread
);
260 /* HACK to allow a graceful shutdown even if shutdown() hasn't been
261 called by the application. Note that this isn't the ultimate
262 solution but it helps in many cases. */
263 struct linger linger
;
265 linger
.l_linger
= 60; /* seconds. 2MSL according to BSD implementation. */
266 setsockopt (get_socket (), SOL_SOCKET
, SO_LINGER
,
267 (const char *)&linger
, sizeof linger
);
269 if (closesocket (get_socket ()))
271 set_winsock_errno ();
275 close_secret_event ();
277 debug_printf ("%d = fhandler_socket::close()", res
);
281 #define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT)
283 /* Cygwin internal */
285 fhandler_socket::ioctl (unsigned int cmd
, void *p
)
287 extern int get_ifconf (struct ifconf
*ifc
, int what
); /* net.cc */
289 struct ifconf ifc
, *ifcp
;
290 struct ifreq
*ifr
, *ifrp
;
291 sigframe
thisframe (mainthread
);
296 ifcp
= (struct ifconf
*) p
;
302 res
= get_ifconf (ifcp
, cmd
);
304 debug_printf ("error in get_ifconf\n");
307 ifr
= (struct ifreq
*) p
;
313 ifr
->ifr_flags
= IFF_NOTRAILERS
| IFF_UP
| IFF_RUNNING
;
314 if (ntohl (((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
)
316 ifr
->ifr_flags
|= IFF_LOOPBACK
;
318 ifr
->ifr_flags
|= IFF_BROADCAST
;
329 ifc
.ifc_buf
= (char *) alloca (2048);
331 ifr
= (struct ifreq
*) p
;
334 debug_printf ("ifr == NULL\n");
339 res
= get_ifconf (&ifc
, cmd
);
342 debug_printf ("error in get_ifconf\n");
346 debug_printf (" name: %s\n", ifr
->ifr_name
);
347 for (ifrp
= ifc
.ifc_req
;
348 (caddr_t
) ifrp
< ifc
.ifc_buf
+ ifc
.ifc_len
;
351 debug_printf ("testname: %s\n", ifrp
->ifr_name
);
352 if (! strcmp (ifrp
->ifr_name
, ifr
->ifr_name
))
357 ifr
->ifr_addr
= ifrp
->ifr_addr
;
360 ifr
->ifr_broadaddr
= ifrp
->ifr_broadaddr
;
363 ifr
->ifr_netmask
= ifrp
->ifr_netmask
;
366 ifr
->ifr_hwaddr
= ifrp
->ifr_hwaddr
;
369 ifr
->ifr_metric
= ifrp
->ifr_metric
;
372 ifr
->ifr_mtu
= ifrp
->ifr_mtu
;
378 if ((caddr_t
) ifrp
>= ifc
.ifc_buf
+ ifc
.ifc_len
)
386 res
= WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO
,
387 *(int *) p
? ASYNC_MASK
: 0);
388 syscall_printf ("Async I/O on socket %s",
389 *(int *) p
? "started" : "cancelled");
390 set_async (*(int *) p
);
393 /* We must cancel WSAAsyncSelect (if any) before setting socket to
396 if (cmd
== FIONBIO
&& *(int *) p
== 0)
397 WSAAsyncSelect (get_socket (), gethwnd (), 0, 0);
398 res
= ioctlsocket (get_socket (), cmd
, (unsigned long *) p
);
399 if (res
== SOCKET_ERROR
)
400 set_winsock_errno ();
403 syscall_printf ("socket is now %sblocking",
404 *(int *) p
? "un" : "");
405 /* Start AsyncSelect if async socket unblocked */
406 if (*(int *) p
&& get_async ())
407 WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO
, ASYNC_MASK
);
409 int current
= get_flags () & O_NONBLOCK_MASK
;
410 int new_flags
= *(int *) p
? (!current
? O_NONBLOCK
: current
) : 0;
411 set_flags ((get_flags () & ~O_NONBLOCK_MASK
) | new_flags
);
415 syscall_printf ("%d = ioctl_socket (%x, %x)", res
, cmd
, p
);
420 fhandler_socket::fcntl (int cmd
, void *arg
)
423 int request
, current
;
429 /* Carefully test for the O_NONBLOCK or deprecated OLD_O_NDELAY flag.
430 Set only the flag that has been passed in. If both are set, just
431 record O_NONBLOCK. */
432 int new_flags
= (int) arg
& O_NONBLOCK_MASK
;
433 if ((new_flags
& OLD_O_NDELAY
) && (new_flags
& O_NONBLOCK
))
434 new_flags
= O_NONBLOCK
;
435 current
= get_flags () & O_NONBLOCK_MASK
;
436 request
= new_flags
? 1 : 0;
437 if (!!current
!= !!new_flags
&& (res
= ioctl (FIONBIO
, &request
)))
439 set_flags ((get_flags () & ~O_NONBLOCK_MASK
) | new_flags
);
443 res
= fhandler_base::fcntl (cmd
, arg
);
450 fhandler_socket::set_close_on_exec (int val
)
452 extern WSADATA wsadata
;
453 if (wsadata
.wVersion
< 512) /* < Winsock 2.0 */
454 set_inheritance (get_handle (), val
);
455 set_close_on_exec_flag (val
);
456 debug_printf ("set close_on_exec for %s to %d", get_name (), val
);
This page took 0.055385 seconds and 5 git commands to generate.