You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Jeff Trawick <tr...@attglobal.net> on 2001/07/10 07:43:49 UTC
[PATCH] make socket timeouts work reasonably for connect()
(Unix at least; Win32 connect is a mess for non-blocking/timed-out
sockets... it looks to me that we wait forever; I could be confused
though :) )
concerns?
old behavior on Unix:
if timeout is set on socket before apr_connect() and connect takes a
while (normal for TCP), apr_connect() returns EINPROGRESS and app must
handle any timeout
new behavior on Unix:
if timeout is set on socket before apr_connect(), app will see
APR_ETIMEUP if it takes longer than the timeout
Index: include/arch/unix/networkio.h
===================================================================
RCS file: /home/cvspublic/apr/include/arch/unix/networkio.h,v
retrieving revision 1.45
diff -u -r1.45 networkio.h
--- include/arch/unix/networkio.h 2001/07/07 22:48:09 1.45
+++ include/arch/unix/networkio.h 2001/07/10 05:46:27
@@ -159,6 +159,7 @@
const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size);
int apr_inet_pton(int af, const char *src, void *dst);
+apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read);
#define apr_is_option_set(mask, option) ((mask & option) ==option)
Index: network_io/unix/sendrecv.c
===================================================================
RCS file: /home/cvspublic/apr/network_io/unix/sendrecv.c,v
retrieving revision 1.65
diff -u -r1.65 sendrecv.c
--- network_io/unix/sendrecv.c 2001/05/03 22:38:00 1.65
+++ network_io/unix/sendrecv.c 2001/07/10 05:46:29
@@ -59,7 +59,7 @@
#include "fileio.h"
#endif /* APR_HAS_SENDFILE */
-static apr_status_t wait_for_io_or_timeout(apr_socket_t *sock, int for_read)
+apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read)
{
struct timeval tv, *tvptr;
fd_set fdset;
@@ -103,7 +103,7 @@
if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
&& sock->timeout != 0) {
- apr_status_t arv = wait_for_io_or_timeout(sock, 0);
+ apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
if (arv != APR_SUCCESS) {
*len = 0;
return arv;
@@ -132,7 +132,7 @@
if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
sock->timeout != 0) {
- apr_status_t arv = wait_for_io_or_timeout(sock, 1);
+ apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1);
if (arv != APR_SUCCESS) {
*len = 0;
return arv;
@@ -167,7 +167,7 @@
if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
&& sock->timeout != 0) {
- apr_status_t arv = wait_for_io_or_timeout(sock, 0);
+ apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
if (arv != APR_SUCCESS) {
*len = 0;
return arv;
@@ -200,7 +200,7 @@
if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
sock->timeout != 0) {
- apr_status_t arv = wait_for_io_or_timeout(sock, 1);
+ apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1);
if (arv != APR_SUCCESS) {
*len = 0;
return arv;
@@ -235,7 +235,7 @@
if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
sock->timeout != 0) {
- apr_status_t arv = wait_for_io_or_timeout(sock, 0);
+ apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
if (arv != APR_SUCCESS) {
*len = 0;
return arv;
@@ -324,7 +324,7 @@
if (rv == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK) &&
sock->timeout > 0) {
- arv = wait_for_io_or_timeout(sock, 0);
+ arv = apr_wait_for_io_or_timeout(sock, 0);
if (arv != APR_SUCCESS) {
*len = 0;
return arv;
@@ -423,7 +423,7 @@
* we get -1/EAGAIN/nbytes>0; AFAICT it just means extra syscalls
* from time to time
*/
- apr_status_t arv = wait_for_io_or_timeout(sock, 0);
+ apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
if (arv != APR_SUCCESS) {
*len = 0;
return arv;
@@ -577,7 +577,7 @@
if (rc == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK) &&
sock->timeout > 0) {
- apr_status_t arv = wait_for_io_or_timeout(sock, 0);
+ apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
if (arv != APR_SUCCESS) {
*len = 0;
@@ -710,7 +710,7 @@
if (rv == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK) &&
sock->timeout > 0) {
- arv = wait_for_io_or_timeout(sock, 0);
+ arv = apr_wait_for_io_or_timeout(sock, 0);
if (arv != APR_SUCCESS) {
*len = 0;
return arv;
Index: network_io/unix/sockets.c
===================================================================
RCS file: /home/cvspublic/apr/network_io/unix/sockets.c,v
retrieving revision 1.74
diff -u -r1.74 sockets.c
--- network_io/unix/sockets.c 2001/05/02 02:32:47 1.74
+++ network_io/unix/sockets.c 2001/07/10 05:46:29
@@ -257,39 +257,57 @@
apr_status_t apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
{
+ int rc;
+
if ((sock->socketdes < 0) || (!sock->remote_addr)) {
return APR_ENOTSOCK;
}
+
+ do {
+ rc = connect(sock->socketdes,
+ (const struct sockaddr *)&sa->sa.sin,
+ sa->salen);
+ } while (rc == -1 && errno == EINTR);
+
+ if (rc == -1 && errno == EINPROGRESS && sock->timeout != 0) {
+ apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
+ if (arv != APR_SUCCESS) {
+ return arv;
+ }
+ else {
+ do {
+ rc = connect(sock->socketdes,
+ (const struct sockaddr *)&sa->sa.sin,
+ sa->salen);
+ } while (rc == -1 && errno == EINTR);
+ }
+ }
- if ((connect(sock->socketdes,
- (const struct sockaddr *)&sa->sa.sin,
- sa->salen) < 0) &&
- (errno != EINPROGRESS)) {
+ if (rc == -1) {
return errno;
}
- else {
- sock->remote_addr = sa;
- /* XXX IPv6 assumes sin_port and sin6_port at same offset */
- if (sock->local_addr->sa.sin.sin_port == 0) {
- /* connect() got us an ephemeral port */
- sock->local_port_unknown = 1;
- }
- /* XXX IPv6 to be handled better later... */
- if (
+
+ sock->remote_addr = sa;
+ /* XXX IPv6 assumes sin_port and sin6_port at same offset */
+ if (sock->local_addr->sa.sin.sin_port == 0) {
+ /* connect() got us an ephemeral port */
+ sock->local_port_unknown = 1;
+ }
+ /* XXX IPv6 to be handled better later... */
+ if (
#if APR_HAVE_IPV6
- sock->local_addr->sa.sin.sin_family == APR_INET6 ||
+ sock->local_addr->sa.sin.sin_family == APR_INET6 ||
#endif
- sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
- /* not bound to specific local interface; connect() had to assign
- * one for the socket
- */
- sock->local_interface_unknown = 1;
- }
+ sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
+ /* not bound to specific local interface; connect() had to assign
+ * one for the socket
+ */
+ sock->local_interface_unknown = 1;
+ }
#ifndef HAVE_POLL
- sock->connected=1;
+ sock->connected=1;
#endif
- return APR_SUCCESS;
- }
+ return APR_SUCCESS;
}
apr_status_t apr_socket_data_get(void **data, const char *key, apr_socket_t *sock)
Index: test/client.c
===================================================================
RCS file: /home/cvspublic/apr/test/client.c,v
retrieving revision 1.29
diff -u -r1.29 client.c
--- test/client.c 2001/06/08 04:49:43 1.29
+++ test/client.c 2001/07/10 05:46:30
@@ -72,7 +72,7 @@
char *local_ipaddr, *remote_ipaddr;
char *dest = "127.0.0.1";
apr_port_t local_port, remote_port;
- apr_interval_time_t read_timeout = 2 * APR_USEC_PER_SEC;
+ apr_interval_time_t timeout = 2 * APR_USEC_PER_SEC;
apr_sockaddr_t *local_sa, *remote_sa;
setbuf(stdout, NULL);
@@ -81,7 +81,7 @@
}
if (argc > 2) {
- read_timeout = APR_USEC_PER_SEC * atoi(argv[2]);
+ timeout = atoi(argv[2]);
}
fprintf(stdout, "Initializing.........");
@@ -117,6 +117,14 @@
}
fprintf(stdout, "OK\n");
+ fprintf(stdout, "\tClient: Setting socket timeout.......");
+ stat = apr_setsocketopt(sock, APR_SO_TIMEOUT, timeout);
+ if (stat) {
+ fprintf(stderr, "Problem setting timeout: %d\n", stat);
+ exit(-1);
+ }
+ fprintf(stdout, "OK\n");
+
fprintf(stdout, "\tClient: Connecting to socket.......");
stat = apr_connect(sock, remote_sa);
@@ -147,14 +155,6 @@
}
fprintf(stdout, "OK\n");
- fprintf(stdout, "\tClient: Setting read timeout.......");
- stat = apr_setsocketopt(sock, APR_SO_TIMEOUT, read_timeout);
- if (stat) {
- fprintf(stderr, "Problem setting timeout: %d\n", stat);
- exit(-1);
- }
- fprintf(stdout, "OK\n");
-
length = STRLEN;
fprintf(stdout, "\tClient: Trying to receive data over socket.......");
--
Jeff Trawick | trawick@attglobal.net | PGP public key at web site:
http://www.geocities.com/SiliconValley/Park/9289/
Born in Roswell... married an alien...
Re: [PATCH] make socket timeouts work reasonably for connect()
Posted by Jeff Trawick <tr...@attglobal.net>.
Cliff Woolley <cl...@yahoo.com> writes:
> (apr_wait_for_io_or_timeout() might want a better name if it's going
> public, but that's just a nit)
It definitely isn't intended to be public (not to be called by apr
app, not in public header file) but it is prefixed with apr_ for
namespace protection reasons.
We might want to use a special prefix like apr_pvt_ for symbols like
this which are only for APR to use internally. I dunno...
--
Jeff Trawick | trawick@attglobal.net | PGP public key at web site:
http://www.geocities.com/SiliconValley/Park/9289/
Born in Roswell... married an alien...
Re: [PATCH] make socket timeouts work reasonably for connect()
Posted by rb...@covalent.net.
On Tue, 10 Jul 2001, Cliff Woolley wrote:
>
> > > (Unix at least; Win32 connect is a mess for non-blocking/timed-out
> > > sockets... it looks to me that we wait forever; I could be confused
> > > though :) )
> > >
> > > concerns?
> > >
> > > old behavior on Unix:
> > >
> > > if timeout is set on socket before apr_connect() and connect takes a
> > > while (normal for TCP), apr_connect() returns EINPROGRESS and app must
> > > handle any timeout
> > >
> > > new behavior on Unix:
> > >
> > > if timeout is set on socket before apr_connect(), app will see
> > > APR_ETIMEUP if it takes longer than the timeout
>
> +1
>
> (apr_wait_for_io_or_timeout() might want a better name if it's going
> public, but that's just a nit)
Even better, if apr_wait_for_io_or_timeout is going public, we can replace
all the duplicate code in the file_io section. :-)
I would probably recommend moving the function to the misc/ portion of
APR, so that File_io doesn't rely on network_io, but that is just a
preference.
Ryan
_____________________________________________________________________________
Ryan Bloom rbb@apache.org
Covalent Technologies rbb@covalent.net
-----------------------------------------------------------------------------
Re: [PATCH] make socket timeouts work reasonably for connect()
Posted by Cliff Woolley <cl...@yahoo.com>.
> > (Unix at least; Win32 connect is a mess for non-blocking/timed-out
> > sockets... it looks to me that we wait forever; I could be confused
> > though :) )
> >
> > concerns?
> >
> > old behavior on Unix:
> >
> > if timeout is set on socket before apr_connect() and connect takes a
> > while (normal for TCP), apr_connect() returns EINPROGRESS and app must
> > handle any timeout
> >
> > new behavior on Unix:
> >
> > if timeout is set on socket before apr_connect(), app will see
> > APR_ETIMEUP if it takes longer than the timeout
+1
(apr_wait_for_io_or_timeout() might want a better name if it's going
public, but that's just a nit)
--Cliff
--------------------------------------------------------------
Cliff Woolley
cliffwoolley@yahoo.com
Charlottesville, VA
Re: [PATCH] make socket timeouts work reasonably for connect()
Posted by Bill Stoddard <bi...@wstoddard.com>.
This seems much more consistent with how the other APR networkio calls work, so +1
Bill
> (Unix at least; Win32 connect is a mess for non-blocking/timed-out
> sockets... it looks to me that we wait forever; I could be confused
> though :) )
>
> concerns?
>
> old behavior on Unix:
>
> if timeout is set on socket before apr_connect() and connect takes a
> while (normal for TCP), apr_connect() returns EINPROGRESS and app must
> handle any timeout
>
> new behavior on Unix:
>
> if timeout is set on socket before apr_connect(), app will see
> APR_ETIMEUP if it takes longer than the timeout
>
> Index: include/arch/unix/networkio.h
> ===================================================================
> RCS file: /home/cvspublic/apr/include/arch/unix/networkio.h,v
> retrieving revision 1.45
> diff -u -r1.45 networkio.h
> --- include/arch/unix/networkio.h 2001/07/07 22:48:09 1.45
> +++ include/arch/unix/networkio.h 2001/07/10 05:46:27
> @@ -159,6 +159,7 @@
>
> const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size);
> int apr_inet_pton(int af, const char *src, void *dst);
> +apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read);
>
> #define apr_is_option_set(mask, option) ((mask & option) ==option)
>
> Index: network_io/unix/sendrecv.c
> ===================================================================
> RCS file: /home/cvspublic/apr/network_io/unix/sendrecv.c,v
> retrieving revision 1.65
> diff -u -r1.65 sendrecv.c
> --- network_io/unix/sendrecv.c 2001/05/03 22:38:00 1.65
> +++ network_io/unix/sendrecv.c 2001/07/10 05:46:29
> @@ -59,7 +59,7 @@
> #include "fileio.h"
> #endif /* APR_HAS_SENDFILE */
>
> -static apr_status_t wait_for_io_or_timeout(apr_socket_t *sock, int for_read)
> +apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read)
> {
> struct timeval tv, *tvptr;
> fd_set fdset;
> @@ -103,7 +103,7 @@
>
> if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
> && sock->timeout != 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -132,7 +132,7 @@
>
> if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout != 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 1);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -167,7 +167,7 @@
>
> if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
> && sock->timeout != 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -200,7 +200,7 @@
>
> if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout != 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 1);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -235,7 +235,7 @@
>
> if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout != 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -324,7 +324,7 @@
> if (rv == -1 &&
> (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout > 0) {
> - arv = wait_for_io_or_timeout(sock, 0);
> + arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -423,7 +423,7 @@
> * we get -1/EAGAIN/nbytes>0; AFAICT it just means extra syscalls
> * from time to time
> */
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -577,7 +577,7 @@
> if (rc == -1 &&
> (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout > 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
>
> if (arv != APR_SUCCESS) {
> *len = 0;
> @@ -710,7 +710,7 @@
> if (rv == -1 &&
> (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout > 0) {
> - arv = wait_for_io_or_timeout(sock, 0);
> + arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> Index: network_io/unix/sockets.c
> ===================================================================
> RCS file: /home/cvspublic/apr/network_io/unix/sockets.c,v
> retrieving revision 1.74
> diff -u -r1.74 sockets.c
> --- network_io/unix/sockets.c 2001/05/02 02:32:47 1.74
> +++ network_io/unix/sockets.c 2001/07/10 05:46:29
> @@ -257,39 +257,57 @@
>
> apr_status_t apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
> {
> + int rc;
> +
> if ((sock->socketdes < 0) || (!sock->remote_addr)) {
> return APR_ENOTSOCK;
> }
> +
> + do {
> + rc = connect(sock->socketdes,
> + (const struct sockaddr *)&sa->sa.sin,
> + sa->salen);
> + } while (rc == -1 && errno == EINTR);
> +
> + if (rc == -1 && errno == EINPROGRESS && sock->timeout != 0) {
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
> + if (arv != APR_SUCCESS) {
> + return arv;
> + }
> + else {
> + do {
> + rc = connect(sock->socketdes,
> + (const struct sockaddr *)&sa->sa.sin,
> + sa->salen);
> + } while (rc == -1 && errno == EINTR);
> + }
> + }
>
> - if ((connect(sock->socketdes,
> - (const struct sockaddr *)&sa->sa.sin,
> - sa->salen) < 0) &&
> - (errno != EINPROGRESS)) {
> + if (rc == -1) {
> return errno;
> }
> - else {
> - sock->remote_addr = sa;
> - /* XXX IPv6 assumes sin_port and sin6_port at same offset */
> - if (sock->local_addr->sa.sin.sin_port == 0) {
> - /* connect() got us an ephemeral port */
> - sock->local_port_unknown = 1;
> - }
> - /* XXX IPv6 to be handled better later... */
> - if (
> +
> + sock->remote_addr = sa;
> + /* XXX IPv6 assumes sin_port and sin6_port at same offset */
> + if (sock->local_addr->sa.sin.sin_port == 0) {
> + /* connect() got us an ephemeral port */
> + sock->local_port_unknown = 1;
> + }
> + /* XXX IPv6 to be handled better later... */
> + if (
> #if APR_HAVE_IPV6
> - sock->local_addr->sa.sin.sin_family == APR_INET6 ||
> + sock->local_addr->sa.sin.sin_family == APR_INET6 ||
> #endif
> - sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
> - /* not bound to specific local interface; connect() had to assign
> - * one for the socket
> - */
> - sock->local_interface_unknown = 1;
> - }
> + sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
> + /* not bound to specific local interface; connect() had to assign
> + * one for the socket
> + */
> + sock->local_interface_unknown = 1;
> + }
> #ifndef HAVE_POLL
> - sock->connected=1;
> + sock->connected=1;
> #endif
> - return APR_SUCCESS;
> - }
> + return APR_SUCCESS;
> }
>
> apr_status_t apr_socket_data_get(void **data, const char *key, apr_socket_t *sock)
> Index: test/client.c
> ===================================================================
> RCS file: /home/cvspublic/apr/test/client.c,v
> retrieving revision 1.29
> diff -u -r1.29 client.c
> --- test/client.c 2001/06/08 04:49:43 1.29
> +++ test/client.c 2001/07/10 05:46:30
> @@ -72,7 +72,7 @@
> char *local_ipaddr, *remote_ipaddr;
> char *dest = "127.0.0.1";
> apr_port_t local_port, remote_port;
> - apr_interval_time_t read_timeout = 2 * APR_USEC_PER_SEC;
> + apr_interval_time_t timeout = 2 * APR_USEC_PER_SEC;
> apr_sockaddr_t *local_sa, *remote_sa;
>
> setbuf(stdout, NULL);
> @@ -81,7 +81,7 @@
> }
>
> if (argc > 2) {
> - read_timeout = APR_USEC_PER_SEC * atoi(argv[2]);
> + timeout = atoi(argv[2]);
> }
>
> fprintf(stdout, "Initializing.........");
> @@ -117,6 +117,14 @@
> }
> fprintf(stdout, "OK\n");
>
> + fprintf(stdout, "\tClient: Setting socket timeout.......");
> + stat = apr_setsocketopt(sock, APR_SO_TIMEOUT, timeout);
> + if (stat) {
> + fprintf(stderr, "Problem setting timeout: %d\n", stat);
> + exit(-1);
> + }
> + fprintf(stdout, "OK\n");
> +
> fprintf(stdout, "\tClient: Connecting to socket.......");
>
> stat = apr_connect(sock, remote_sa);
> @@ -147,14 +155,6 @@
> }
> fprintf(stdout, "OK\n");
>
> - fprintf(stdout, "\tClient: Setting read timeout.......");
> - stat = apr_setsocketopt(sock, APR_SO_TIMEOUT, read_timeout);
> - if (stat) {
> - fprintf(stderr, "Problem setting timeout: %d\n", stat);
> - exit(-1);
> - }
> - fprintf(stdout, "OK\n");
> -
> length = STRLEN;
> fprintf(stdout, "\tClient: Trying to receive data over socket.......");
>
>
>
> --
> Jeff Trawick | trawick@attglobal.net | PGP public key at web site:
> http://www.geocities.com/SiliconValley/Park/9289/
> Born in Roswell... married an alien...
>
Re: [PATCH] make socket timeouts work reasonably for connect()
Posted by Jeff Trawick <tr...@attglobal.net>.
Luke Kenneth Casson Leighton <lk...@samba-tng.org> writes:
> Win32 has messaging (which is basically, send length of data
> first in a 16-bit or 32-bit word then send data of EXACT
> length) which is very commonly used.
>
> so no surprise that anything else is less well supported :)
>
> messaging is cool: guaranteed transmission and data size:
> a combination of the best of TCP and the best of UDP.
>
> luke
>
> On Tue, Jul 10, 2001 at 01:43:49AM -0400, Jeff Trawick wrote:
> > (Unix at least; Win32 connect is a mess for non-blocking/timed-out
> > sockets... it looks to me that we wait forever; I could be confused
> > though :) )
FYI... I wasn't immediately concerned with Win32
capabilities... instead, I was concerned about some bad code in
apr_connect() for Win32. I think Bill S. will handle, or I'll get to
it soon-ish otherwise.
Have fun...
--
Jeff Trawick | trawick@attglobal.net | PGP public key at web site:
http://www.geocities.com/SiliconValley/Park/9289/
Born in Roswell... married an alien...
Re: [PATCH] make socket timeouts work reasonably for connect()
Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
Win32 has messaging (which is basically, send length of data
first in a 16-bit or 32-bit word then send data of EXACT
length) which is very commonly used.
so no surprise that anything else is less well supported :)
messaging is cool: guaranteed transmission and data size:
a combination of the best of TCP and the best of UDP.
luke
On Tue, Jul 10, 2001 at 01:43:49AM -0400, Jeff Trawick wrote:
> (Unix at least; Win32 connect is a mess for non-blocking/timed-out
> sockets... it looks to me that we wait forever; I could be confused
> though :) )
>
> concerns?
>
> old behavior on Unix:
>
> if timeout is set on socket before apr_connect() and connect takes a
> while (normal for TCP), apr_connect() returns EINPROGRESS and app must
> handle any timeout
>
> new behavior on Unix:
>
> if timeout is set on socket before apr_connect(), app will see
> APR_ETIMEUP if it takes longer than the timeout
>
> Index: include/arch/unix/networkio.h
> ===================================================================
> RCS file: /home/cvspublic/apr/include/arch/unix/networkio.h,v
> retrieving revision 1.45
> diff -u -r1.45 networkio.h
> --- include/arch/unix/networkio.h 2001/07/07 22:48:09 1.45
> +++ include/arch/unix/networkio.h 2001/07/10 05:46:27
> @@ -159,6 +159,7 @@
>
> const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size);
> int apr_inet_pton(int af, const char *src, void *dst);
> +apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read);
>
> #define apr_is_option_set(mask, option) ((mask & option) ==option)
>
> Index: network_io/unix/sendrecv.c
> ===================================================================
> RCS file: /home/cvspublic/apr/network_io/unix/sendrecv.c,v
> retrieving revision 1.65
> diff -u -r1.65 sendrecv.c
> --- network_io/unix/sendrecv.c 2001/05/03 22:38:00 1.65
> +++ network_io/unix/sendrecv.c 2001/07/10 05:46:29
> @@ -59,7 +59,7 @@
> #include "fileio.h"
> #endif /* APR_HAS_SENDFILE */
>
> -static apr_status_t wait_for_io_or_timeout(apr_socket_t *sock, int for_read)
> +apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read)
> {
> struct timeval tv, *tvptr;
> fd_set fdset;
> @@ -103,7 +103,7 @@
>
> if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
> && sock->timeout != 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -132,7 +132,7 @@
>
> if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout != 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 1);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -167,7 +167,7 @@
>
> if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)
> && sock->timeout != 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -200,7 +200,7 @@
>
> if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout != 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 1);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -235,7 +235,7 @@
>
> if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout != 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -324,7 +324,7 @@
> if (rv == -1 &&
> (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout > 0) {
> - arv = wait_for_io_or_timeout(sock, 0);
> + arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -423,7 +423,7 @@
> * we get -1/EAGAIN/nbytes>0; AFAICT it just means extra syscalls
> * from time to time
> */
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> @@ -577,7 +577,7 @@
> if (rc == -1 &&
> (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout > 0) {
> - apr_status_t arv = wait_for_io_or_timeout(sock, 0);
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
>
> if (arv != APR_SUCCESS) {
> *len = 0;
> @@ -710,7 +710,7 @@
> if (rv == -1 &&
> (errno == EAGAIN || errno == EWOULDBLOCK) &&
> sock->timeout > 0) {
> - arv = wait_for_io_or_timeout(sock, 0);
> + arv = apr_wait_for_io_or_timeout(sock, 0);
> if (arv != APR_SUCCESS) {
> *len = 0;
> return arv;
> Index: network_io/unix/sockets.c
> ===================================================================
> RCS file: /home/cvspublic/apr/network_io/unix/sockets.c,v
> retrieving revision 1.74
> diff -u -r1.74 sockets.c
> --- network_io/unix/sockets.c 2001/05/02 02:32:47 1.74
> +++ network_io/unix/sockets.c 2001/07/10 05:46:29
> @@ -257,39 +257,57 @@
>
> apr_status_t apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
> {
> + int rc;
> +
> if ((sock->socketdes < 0) || (!sock->remote_addr)) {
> return APR_ENOTSOCK;
> }
> +
> + do {
> + rc = connect(sock->socketdes,
> + (const struct sockaddr *)&sa->sa.sin,
> + sa->salen);
> + } while (rc == -1 && errno == EINTR);
> +
> + if (rc == -1 && errno == EINPROGRESS && sock->timeout != 0) {
> + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
> + if (arv != APR_SUCCESS) {
> + return arv;
> + }
> + else {
> + do {
> + rc = connect(sock->socketdes,
> + (const struct sockaddr *)&sa->sa.sin,
> + sa->salen);
> + } while (rc == -1 && errno == EINTR);
> + }
> + }
>
> - if ((connect(sock->socketdes,
> - (const struct sockaddr *)&sa->sa.sin,
> - sa->salen) < 0) &&
> - (errno != EINPROGRESS)) {
> + if (rc == -1) {
> return errno;
> }
> - else {
> - sock->remote_addr = sa;
> - /* XXX IPv6 assumes sin_port and sin6_port at same offset */
> - if (sock->local_addr->sa.sin.sin_port == 0) {
> - /* connect() got us an ephemeral port */
> - sock->local_port_unknown = 1;
> - }
> - /* XXX IPv6 to be handled better later... */
> - if (
> +
> + sock->remote_addr = sa;
> + /* XXX IPv6 assumes sin_port and sin6_port at same offset */
> + if (sock->local_addr->sa.sin.sin_port == 0) {
> + /* connect() got us an ephemeral port */
> + sock->local_port_unknown = 1;
> + }
> + /* XXX IPv6 to be handled better later... */
> + if (
> #if APR_HAVE_IPV6
> - sock->local_addr->sa.sin.sin_family == APR_INET6 ||
> + sock->local_addr->sa.sin.sin_family == APR_INET6 ||
> #endif
> - sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
> - /* not bound to specific local interface; connect() had to assign
> - * one for the socket
> - */
> - sock->local_interface_unknown = 1;
> - }
> + sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
> + /* not bound to specific local interface; connect() had to assign
> + * one for the socket
> + */
> + sock->local_interface_unknown = 1;
> + }
> #ifndef HAVE_POLL
> - sock->connected=1;
> + sock->connected=1;
> #endif
> - return APR_SUCCESS;
> - }
> + return APR_SUCCESS;
> }
>
> apr_status_t apr_socket_data_get(void **data, const char *key, apr_socket_t *sock)
> Index: test/client.c
> ===================================================================
> RCS file: /home/cvspublic/apr/test/client.c,v
> retrieving revision 1.29
> diff -u -r1.29 client.c
> --- test/client.c 2001/06/08 04:49:43 1.29
> +++ test/client.c 2001/07/10 05:46:30
> @@ -72,7 +72,7 @@
> char *local_ipaddr, *remote_ipaddr;
> char *dest = "127.0.0.1";
> apr_port_t local_port, remote_port;
> - apr_interval_time_t read_timeout = 2 * APR_USEC_PER_SEC;
> + apr_interval_time_t timeout = 2 * APR_USEC_PER_SEC;
> apr_sockaddr_t *local_sa, *remote_sa;
>
> setbuf(stdout, NULL);
> @@ -81,7 +81,7 @@
> }
>
> if (argc > 2) {
> - read_timeout = APR_USEC_PER_SEC * atoi(argv[2]);
> + timeout = atoi(argv[2]);
> }
>
> fprintf(stdout, "Initializing.........");
> @@ -117,6 +117,14 @@
> }
> fprintf(stdout, "OK\n");
>
> + fprintf(stdout, "\tClient: Setting socket timeout.......");
> + stat = apr_setsocketopt(sock, APR_SO_TIMEOUT, timeout);
> + if (stat) {
> + fprintf(stderr, "Problem setting timeout: %d\n", stat);
> + exit(-1);
> + }
> + fprintf(stdout, "OK\n");
> +
> fprintf(stdout, "\tClient: Connecting to socket.......");
>
> stat = apr_connect(sock, remote_sa);
> @@ -147,14 +155,6 @@
> }
> fprintf(stdout, "OK\n");
>
> - fprintf(stdout, "\tClient: Setting read timeout.......");
> - stat = apr_setsocketopt(sock, APR_SO_TIMEOUT, read_timeout);
> - if (stat) {
> - fprintf(stderr, "Problem setting timeout: %d\n", stat);
> - exit(-1);
> - }
> - fprintf(stdout, "OK\n");
> -
> length = STRLEN;
> fprintf(stdout, "\tClient: Trying to receive data over socket.......");
>
>
>
> --
> Jeff Trawick | trawick@attglobal.net | PGP public key at web site:
> http://www.geocities.com/SiliconValley/Park/9289/
> Born in Roswell... married an alien...