"David Reid" <[EMAIL PROTECTED]> writes:
> OK, I've done some work on this but am getting an error now
> Could not connect: Can't assign requested address (49)
I have it working on Linux now...
Changes to your patch or to other code to get it to work:
1) The existing apr_set_port() doesn't get along with the new
apr_connect(). When apr_connect() replaces the remote sockaddr,
we lose the port set previously.
For now, I added apr_set_sockaddr_port(), but I think we just
need to change apr_set_port() to take a sockaddr instead of a
socket and a local/remote flag.
2) socket address-related vars weren't set up in apr_gethostbyname()
when we created the sockaddr; I hit a segfault due to this
3) I made a fix/tweak to get_local_addr() (not shown below; will be
committed shortly); I don't *think* it was required but I may be
confused
New patch:
(Setting the port in client.c is in a different order than in your
patch due to my initial confusion about why the remote port was
getting lost.)
Index: include/apr_network_io.h
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/lib/apr/include/apr_network_io.h,v
retrieving revision 1.71
diff -u -r1.71 apr_network_io.h
--- include/apr_network_io.h 2000/11/16 14:48:50 1.71
+++ include/apr_network_io.h 2000/11/16 15:42:14
@@ -265,7 +265,7 @@
* APR assumes that the sockaddr_in in the apr_socket is
* completely filled out.
*/
-apr_status_t apr_connect(apr_socket_t *sock, const char *hostname);
+apr_status_t apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa);
/**
* Get name of a machine we are currently connected to.
@@ -275,6 +275,9 @@
*/
apr_status_t apr_get_hostname(char **name, apr_interface_e which, apr_socket_t
*sock);
+apr_status_t apr_gethostbyname(apr_sockaddr_t **sa, const char *hostname,
+ apr_pool_t *p);
+
/**
* Get name of the current machine
* @param buf A buffer to store the hostname in.
@@ -434,6 +437,8 @@
* the port is already used, we won't find out about it here.
*/
apr_status_t apr_set_port(apr_socket_t *sock, apr_interface_e which,
apr_port_t port);
+
+apr_status_t apr_set_sockaddr_port(apr_sockaddr_t *sa, apr_port_t port);
/**
* Return the port associated with a socket.
Index: network_io/unix/sa_common.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/lib/apr/network_io/unix/sa_common.c,v
retrieving revision 1.6
diff -u -r1.6 sa_common.c
--- network_io/unix/sa_common.c 2000/11/16 14:48:49 1.6
+++ network_io/unix/sa_common.c 2000/11/16 15:42:15
@@ -78,6 +78,13 @@
return APR_SUCCESS;
}
+apr_status_t apr_set_sockaddr_port(apr_sockaddr_t *sa, apr_port_t port)
+{
+ /* XXX IPv6: assumes sin_port and sin6_port at same offset */
+ sa->sa.sin.sin_port = htons(port);
+ return APR_SUCCESS;
+}
+
apr_status_t apr_get_port(apr_port_t *port, apr_interface_e which,
apr_socket_t *sock)
{
/* XXX IPv6: assumes sin_port and sin6_port at same offset */
@@ -171,3 +178,62 @@
return APR_SUCCESS;
}
+static void set_sockaddr_vars(apr_sockaddr_t *addr, int family)
+{
+ addr->sa.sin.sin_family = family;
+ addr->sa.sin.sin_family = family;
+
+ if (family == AF_INET) {
+ addr->sa_len = sizeof(struct sockaddr_in);
+ addr->addr_str_len = 16;
+ addr->ipaddr_ptr = &(addr->sa.sin.sin_addr);
+ addr->ipaddr_len = sizeof(struct in_addr);
+ }
+#if APR_HAVE_IPV6
+ else if (family == AF_INET6) {
+ addr->sa_len = sizeof(struct sockaddr_in6);
+ addr->addr_str_len = 46;
+ addr->ipaddr_ptr = &(addr->sa.sin6.sin6_addr);
+ addr->ipaddr_len = sizeof(struct in6_addr);
+ }
+#endif
+}
+
+apr_status_t apr_gethostbyname(apr_sockaddr_t **sa, const char *hostname,
apr_pool_t *p)
+{
+ struct hostent *hp;
+
+ (*sa) = (apr_sockaddr_t *)apr_pcalloc(p, sizeof(apr_sockaddr_t));
+ if ((*sa) == NULL)
+ return APR_ENOMEM;
+ (*sa)->pool = p;
+ (*sa)->sa.sin.sin_family = AF_INET; /* we don't yet support IPv6 */
+ set_sockaddr_vars(*sa, (*sa)->sa.sin.sin_family);
+
+ if (hostname != NULL) {
+#ifndef GETHOSTBYNAME_HANDLES_NAS
+ if (*hostname >= '0' && *hostname <= '9' &&
+ strspn(hostname, "0123456789.") == strlen(hostname)) {
+ (*sa)->sa.sin.sin_addr.s_addr = inet_addr(hostname);
+ (*sa)->sa_len = sizeof(struct sockaddr_in);
+ }
+ else {
+#endif
+ hp = gethostbyname(hostname);
+
+ if (!hp) {
+ return (h_errno + APR_OS_START_SYSERR);
+ }
+
+ memcpy((char *)&(*sa)->sa.sin.sin_addr, hp->h_addr_list[0],
+ hp->h_length);
+ (*sa)->sa_len = sizeof(struct sockaddr_in);
+ (*sa)->ipaddr_len = hp->h_length;
+
+#ifndef GETHOSTBYNAME_HANDLES_NAS
+ }
+#endif
+ }
+ (*sa)->hostname = apr_pstrdup(p, hostname);
+ return APR_SUCCESS;
+}
Index: network_io/unix/sockets.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/lib/apr/network_io/unix/sockets.c,v
retrieving revision 1.56
diff -u -r1.56 sockets.c
--- network_io/unix/sockets.c 2000/11/16 14:48:49 1.56
+++ network_io/unix/sockets.c 2000/11/16 15:42:16
@@ -226,57 +226,35 @@
return APR_SUCCESS;
}
-apr_status_t apr_connect(apr_socket_t *sock, const char *hostname)
+apr_status_t apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
{
- struct hostent *hp;
-
if ((sock->socketdes < 0) || (!sock->remote_addr)) {
return APR_ENOTSOCK;
}
- if (hostname != NULL) {
-#ifndef GETHOSTBYNAME_HANDLES_NAS
- if (*hostname >= '0' && *hostname <= '9' &&
- strspn(hostname, "0123456789.") == strlen(hostname)) {
- sock->remote_addr->sa.sin.sin_addr.s_addr = inet_addr(hostname);
- }
- else {
-#endif
- hp = gethostbyname(hostname);
-
- if (!hp) {
- return (h_errno + APR_OS_START_SYSERR);
- }
-
- /* XXX IPv6: move name resolution out of this function */
- memcpy((char *)&sock->remote_addr->sa.sin.sin_addr,
hp->h_addr_list[0],
- hp->h_length);
-
-#ifndef GETHOSTBYNAME_HANDLES_NAS
- }
-#endif
- }
- if ((connect(sock->socketdes,
- (const struct sockaddr *)&sock->remote_addr->sa.sin,
- sock->remote_addr->sa_len) < 0) &&
+ if ((connect(sock->socketdes,
+ (const struct sockaddr *)&sa->sa.sin,
+ sa->sa_len) < 0) &&
(errno != EINPROGRESS)) {
return errno;
}
else {
- /* XXX IPv6 */
+ 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 */
- if (sock->local_addr->sa.sin.sin_addr.s_addr == 0) {
+ /* XXX IPv6 to be handled better later... */
+ if (sock->local_addr->sa.sin.sin_family == AF_INET6 ||
+ 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;
}
Index: test/client.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/lib/apr/test/client.c,v
retrieving revision 1.17
diff -u -r1.17 client.c
--- test/client.c 2000/11/09 15:01:35 1.17
+++ test/client.c 2000/11/16 15:42:16
@@ -73,6 +73,7 @@
char *dest = "127.0.0.1";
apr_port_t local_port, remote_port;
apr_interval_time_t read_timeout = -1;
+ apr_sockaddr_t *destsa;
setbuf(stdout, NULL);
if (argc > 1) {
@@ -115,8 +116,17 @@
fprintf(stdout, "OK\n");
}
+ fprintf(stdout,"\tClient: Making socket address...............");
+ if (apr_gethostbyname(&destsa, dest, context) != APR_SUCCESS){
+ apr_close_socket(sock);
+ fprintf(stdout, "Failed!\n");
+ fprintf(stdout, "Couldn't create a socket address structure for %s\n",
dest);
+ exit(-1);
+ }
+ fprintf(stdout,"OK\n");
+
fprintf(stdout, "\tClient: Setting port for socket.......");
- if (apr_set_port(sock, APR_REMOTE, 8021) != APR_SUCCESS) {
+ if (apr_set_sockaddr_port(destsa, 8021) != APR_SUCCESS) {
apr_close_socket(sock);
fprintf(stderr, "Couldn't set the port correctly\n");
exit(-1);
@@ -125,7 +135,7 @@
fprintf(stdout, "\tClient: Connecting to socket.......");
- stat = apr_connect(sock, dest);
+ stat = apr_connect(sock, destsa);
if (stat != APR_SUCCESS) {
apr_close_socket(sock);
--
Jeff Trawick | [EMAIL PROTECTED] | PGP public key at web site:
http://www.geocities.com/SiliconValley/Park/9289/
Born in Roswell... married an alien...