You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by tr...@apache.org on 2013/10/27 18:34:42 UTC
svn commit: r1536167 - in /apr/apr/branches/1.5.x: ./ CHANGES
network_io/win32/sockets.c
Author: trawick
Date: Sun Oct 27 17:34:42 2013
New Revision: 1536167
URL: http://svn.apache.org/r1536167
Log:
Merge 1089031 from trunk:
restructure Windows apr_socket_connect() to more closely match
the Unix implementation, fixing the getpeername() optimization
and WSAEISCONN behavior
PR: 48736 (covered WSAISCONN issue)
Submitted by: <inoue ariel-networks.com> (WSAISCONN handling)
Reworked/extended by: trawick
Modified:
apr/apr/branches/1.5.x/ (props changed)
apr/apr/branches/1.5.x/CHANGES
apr/apr/branches/1.5.x/network_io/win32/sockets.c
Propchange: apr/apr/branches/1.5.x/
------------------------------------------------------------------------------
Merged /apr/apr/trunk:r1089031
Modified: apr/apr/branches/1.5.x/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/CHANGES?rev=1536167&r1=1536166&r2=1536167&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/CHANGES [utf-8] (original)
+++ apr/apr/branches/1.5.x/CHANGES [utf-8] Sun Oct 27 17:34:42 2013
@@ -1,6 +1,9 @@
-*- coding: utf-8 -*-
Changes for APR 1.5.0
+ *) apr_socket_connect() on Windows: Handle WSAEISCONN. PR 48736.
+ [<inoue ariel-networks.com>, Jeff Trawick]
+
*) z/OS: threadsafe apr_pollset_poll support for sockets [Greg Ames]
*) Windows: Don't obtain a mutex for buffered file I/O unless the
Modified: apr/apr/branches/1.5.x/network_io/win32/sockets.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/network_io/win32/sockets.c?rev=1536167&r1=1536166&r2=1536167&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/network_io/win32/sockets.c (original)
+++ apr/apr/branches/1.5.x/network_io/win32/sockets.c Sun Oct 27 17:34:42 2013
@@ -311,6 +311,47 @@ APR_DECLARE(apr_status_t) apr_socket_acc
return APR_SUCCESS;
}
+static apr_status_t wait_for_connect(apr_socket_t *sock)
+{
+ int rc;
+ struct timeval tv, *tvptr;
+ fd_set wfdset, efdset;
+
+ /* wait for the connect to complete or timeout */
+ FD_ZERO(&wfdset);
+ FD_SET(sock->socketdes, &wfdset);
+ FD_ZERO(&efdset);
+ FD_SET(sock->socketdes, &efdset);
+
+ if (sock->timeout < 0) {
+ tvptr = NULL;
+ }
+ else {
+ /* casts for winsock/timeval definition */
+ tv.tv_sec = (long)apr_time_sec(sock->timeout);
+ tv.tv_usec = (int)apr_time_usec(sock->timeout);
+ tvptr = &tv;
+ }
+ rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, tvptr);
+ if (rc == SOCKET_ERROR) {
+ return apr_get_netos_error();
+ }
+ else if (!rc) {
+ return APR_FROM_OS_ERROR(WSAETIMEDOUT);
+ }
+ /* Evaluate the efdset */
+ if (FD_ISSET(sock->socketdes, &efdset)) {
+ /* The connect failed. */
+ int rclen = sizeof(rc);
+ if (getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen)) {
+ return apr_get_netos_error();
+ }
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ return APR_SUCCESS;
+}
+
APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock,
apr_sockaddr_t *sa)
{
@@ -322,59 +363,41 @@ APR_DECLARE(apr_status_t) apr_socket_con
if (connect(sock->socketdes, (const struct sockaddr *)&sa->sa.sin,
sa->salen) == SOCKET_ERROR) {
- int rc;
- struct timeval tv, *tvptr;
- fd_set wfdset, efdset;
-
rv = apr_get_netos_error();
- if (rv != APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) {
- return rv;
- }
+ }
+ else {
+ rv = APR_SUCCESS;
+ }
+ if (rv == APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) {
if (sock->timeout == 0) {
/* Tell the app that the connect is in progress...
* Gotta play some games here. connect on Unix will return
* EINPROGRESS under the same circumstances that Windows
* returns WSAEWOULDBLOCK. Do some adhoc canonicalization...
*/
- return APR_FROM_OS_ERROR(WSAEINPROGRESS);
- }
-
- /* wait for the connect to complete or timeout */
- FD_ZERO(&wfdset);
- FD_SET(sock->socketdes, &wfdset);
- FD_ZERO(&efdset);
- FD_SET(sock->socketdes, &efdset);
-
- if (sock->timeout < 0) {
- tvptr = NULL;
+ rv = APR_FROM_OS_ERROR(WSAEINPROGRESS);
}
else {
- /* casts for winsock/timeval definition */
- tv.tv_sec = (long)apr_time_sec(sock->timeout);
- tv.tv_usec = (int)apr_time_usec(sock->timeout);
- tvptr = &tv;
- }
- rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, tvptr);
- if (rc == SOCKET_ERROR) {
- return apr_get_netos_error();
- }
- else if (!rc) {
- return APR_FROM_OS_ERROR(WSAETIMEDOUT);
- }
- /* Evaluate the efdset */
- if (FD_ISSET(sock->socketdes, &efdset)) {
- /* The connect failed. */
- int rclen = sizeof(rc);
- if (getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen)) {
- return apr_get_netos_error();
+ rv = wait_for_connect(sock);
+ if (rv != APR_SUCCESS) {
+ return rv;
}
- return APR_FROM_OS_ERROR(rc);
}
}
- /* connect was OK .. amazing */
- sock->remote_addr = sa;
+
+ if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) {
+ /* A real remote address was passed in. If the unspecified
+ * address was used, the actual remote addr will have to be
+ * determined using getpeername() if required. */
+ sock->remote_addr_unknown = 0;
+
+ /* Copy the address structure details in. */
+ sock->remote_addr = sa;
+ }
+
if (sock->local_addr->sa.sin.sin_port == 0) {
+ /* connect() got us an ephemeral port */
sock->local_port_unknown = 1;
}
if (!memcmp(sock->local_addr->ipaddr_ptr,
@@ -385,6 +408,11 @@ APR_DECLARE(apr_status_t) apr_socket_con
*/
sock->local_interface_unknown = 1;
}
+
+ if (rv != APR_SUCCESS && rv != APR_FROM_OS_ERROR(WSAEISCONN)) {
+ return rv;
+ }
+
return APR_SUCCESS;
}