diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2006-07-05 00:10:43 +0400 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2006-07-05 00:10:43 +0400 |
commit | c2ab308c81a0f9a3a705e743b3123598d5b33243 (patch) | |
tree | 4561f90892ab6a7231b4c50e96227824dfeb0e44 /winsup | |
parent | 6dbfd8f9baf505c3bf11ef8ba4245a74372c4cab (diff) |
* fhandler_socket.cc (fhandler_socket::listen): Allow listening on
unbound INET socket.
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/ChangeLog | 5 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_socket.cc | 20 |
2 files changed, 22 insertions, 3 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 02324649c..a8a0520f4 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,5 +1,10 @@ 2006-07-04 Corinna Vinschen <corinna@vinschen.de> + * fhandler_socket.cc (fhandler_socket::listen): Allow listening on + unbound INET socket. + +2006-07-04 Corinna Vinschen <corinna@vinschen.de> + * fhandler.h (fhandler_socket::wait): Set default timeout to INFINITE. 2006-07-03 Corinna Vinschen <corinna@vinschen.de> diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index e27949600..c3c24d24e 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -804,14 +804,28 @@ int fhandler_socket::listen (int backlog) { int res = ::listen (get_socket (), backlog); - if (res) - set_winsock_errno (); - else + if (res && WSAGetLastError () == WSAEINVAL && get_addr_family () == AF_INET) + { + /* It's perfectly valid to call listen on an unbound INET socket. + In this case the socket is automatically bound to an unused + port number, listening on all interfaces. On Winsock, listen + fails with WSAEINVAL when it's called on an unbound socket. + So we have to bind manually here to have POSIX semantics. */ + struct sockaddr_in sa; + sa.sin_family = AF_INET; + sa.sin_port = 0; + sa.sin_addr.s_addr = INADDR_ANY; + if (!::bind (get_socket (), (struct sockaddr *) &sa, sizeof sa)) + res = ::listen (get_socket (), backlog); + } + if (!res) { if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM) af_local_set_cred (); connect_state (connected); } + else + set_winsock_errno (); return res; } |