1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-22 08:08:50 -05:00

fix getinfo CURLINFO_LOCAL* for reused connections (take 2)

This commit is contained in:
Yang Tse 2010-11-30 22:14:37 +01:00
parent 1b2b93e074
commit 11cddb68e0
5 changed files with 90 additions and 54 deletions

View File

@ -532,6 +532,16 @@ static CURLcode trynextip(struct connectdata *conn,
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
/* Copies connection info into the session handle to make it available
when the session handle is no longer associated with a connection. */
void Curl_persistconninfo(struct connectdata *conn)
{
memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
conn->data->info.conn_primary_port = conn->primary_port;
conn->data->info.conn_local_port = conn->local_port;
}
/* retrieves ip address and port from a sockaddr structure */ /* retrieves ip address and port from a sockaddr structure */
static bool getaddressinfo(struct sockaddr* sa, char* addr, static bool getaddressinfo(struct sockaddr* sa, char* addr,
long* port) long* port)
@ -587,11 +597,8 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
struct Curl_sockaddr_storage ssrem; struct Curl_sockaddr_storage ssrem;
struct Curl_sockaddr_storage ssloc; struct Curl_sockaddr_storage ssloc;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct PureInfo *info = &conn->data->info;
if(conn->bits.reuse) if(!conn->bits.reuse) {
/* reusing same connection */
return;
len = sizeof(struct Curl_sockaddr_storage); len = sizeof(struct Curl_sockaddr_storage);
if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
@ -610,7 +617,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
} }
if(!getaddressinfo((struct sockaddr*)&ssrem, if(!getaddressinfo((struct sockaddr*)&ssrem,
info->primary_ip, &info->primary_port)) { conn->primary_ip, &conn->primary_port)) {
error = ERRNO; error = ERRNO;
failf(data, "ssrem inet_ntop() failed with errno %d: %s", failf(data, "ssrem inet_ntop() failed with errno %d: %s",
error, Curl_strerror(conn, error)); error, Curl_strerror(conn, error));
@ -618,12 +625,17 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
} }
if(!getaddressinfo((struct sockaddr*)&ssloc, if(!getaddressinfo((struct sockaddr*)&ssloc,
info->local_ip, &info->local_port)) { conn->local_ip, &conn->local_port)) {
error = ERRNO; error = ERRNO;
failf(data, "ssloc inet_ntop() failed with errno %d: %s", failf(data, "ssloc inet_ntop() failed with errno %d: %s",
error, Curl_strerror(conn, error)); error, Curl_strerror(conn, error));
return; return;
} }
}
/* persist connection info in session handle */
Curl_persistconninfo(conn);
} }
/* /*
@ -865,14 +877,16 @@ singleipconnect(struct connectdata *conn,
/* store remote address and port used in this connection attempt */ /* store remote address and port used in this connection attempt */
if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
data->info.primary_ip, &data->info.primary_port)) { conn->primary_ip, &conn->primary_port)) {
error = ERRNO; error = ERRNO;
failf(data, "sa_addr inet_ntop() failed with errno %d: %s", failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
error, Curl_strerror(conn, error)); error, Curl_strerror(conn, error));
} }
strcpy(conn->ip_addr_str, data->info.primary_ip); memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
infof(data, " Trying %s... ", conn->ip_addr_str); infof(data, " Trying %s... ", conn->ip_addr_str);
Curl_persistconninfo(conn);
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
if(addr.family == AF_INET6) if(addr.family == AF_INET6)
conn->bits.ipv6 = TRUE; conn->bits.ipv6 = TRUE;

View File

@ -69,4 +69,6 @@ void Curl_sndbufset(curl_socket_t sockfd);
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd); void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
void Curl_persistconninfo(struct connectdata *conn);
#endif #endif

View File

@ -67,6 +67,11 @@ CURLcode Curl_initinfo(struct SessionHandle *data)
info->request_size = 0; info->request_size = 0;
info->numconnects = 0; info->numconnects = 0;
info->conn_primary_ip[0] = '\0';
info->conn_local_ip[0] = '\0';
info->conn_primary_port = 0;
info->conn_local_port = 0;
return CURLE_OK; return CURLE_OK;
} }
@ -233,20 +238,20 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
break; break;
case CURLINFO_PRIMARY_IP: case CURLINFO_PRIMARY_IP:
/* Return the ip address of the most recent (primary) connection */ /* Return the ip address of the most recent (primary) connection */
*param_charp = data->info.primary_ip; *param_charp = data->info.conn_primary_ip;
break; break;
case CURLINFO_PRIMARY_PORT: case CURLINFO_PRIMARY_PORT:
/* Return the (remote) port of the most recent (primary) connection */ /* Return the (remote) port of the most recent (primary) connection */
*param_longp = data->info.primary_port; *param_longp = data->info.conn_primary_port;
break; break;
case CURLINFO_LOCAL_IP: case CURLINFO_LOCAL_IP:
/* Return the source/local ip address of the most recent (primary) /* Return the source/local ip address of the most recent (primary)
connection */ connection */
*param_charp = data->info.local_ip; *param_charp = data->info.conn_local_ip;
break; break;
case CURLINFO_LOCAL_PORT: case CURLINFO_LOCAL_PORT:
/* Return the local port of the most recent (primary) connection */ /* Return the local port of the most recent (primary) connection */
*param_longp = data->info.local_port; *param_longp = data->info.conn_local_port;
break; break;
case CURLINFO_CERTINFO: case CURLINFO_CERTINFO:
/* Return the a pointer to the certinfo struct. Not really an slist /* Return the a pointer to the certinfo struct. Not really an slist

View File

@ -4599,7 +4599,8 @@ static void reuse_conn(struct connectdata *old_conn,
else else
free(old_conn->host.rawalloc); /* free the newly allocated name buffer */ free(old_conn->host.rawalloc); /* free the newly allocated name buffer */
strcpy(conn->ip_addr_str, old_conn->ip_addr_str); /* persist connection info in session handle */
Curl_persistconninfo(conn);
/* re-use init */ /* re-use init */
conn->bits.reuse = TRUE; /* yes, we're re-using here */ conn->bits.reuse = TRUE; /* yes, we're re-using here */

View File

@ -757,6 +757,23 @@ struct connectdata {
unsigned short remote_port; /* what remote port to connect to, unsigned short remote_port; /* what remote port to connect to,
not the proxy port! */ not the proxy port! */
/* 'primary_ip' and 'primary_port' get filled with peer's numerical
ip address and port number whenever an outgoing connection is
*attemted* from the primary socket to a remote address. When more
than one address is tried for a connection these will hold data
for the last attempt. When the connection is actualy established
these are updated with data which comes directly from the socket. */
char primary_ip[MAX_IPADR_LEN];
long primary_port;
/* 'local_ip' and 'local_port' get filled with local's numerical
ip address and port number whenever an outgoing connection is
**established** from the primary socket to a remote address. */
char local_ip[MAX_IPADR_LEN];
long local_port;
char *user; /* user name string, allocated */ char *user; /* user name string, allocated */
char *passwd; /* password string, allocated */ char *passwd; /* password string, allocated */
@ -915,22 +932,19 @@ struct PureInfo {
char *contenttype; /* the content type of the object */ char *contenttype; /* the content type of the object */
char *wouldredirect; /* URL this would've been redirected to if asked to */ char *wouldredirect; /* URL this would've been redirected to if asked to */
/* 'primary_ip' and 'primary_port' get filled with peer's numerical /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip'
ip address and port number whenever an outgoing connection is and, 'conn_local_port' are copied over from the connectdata struct in
*attemted* from the primary socket to a remote address. When more order to allow curl_easy_getinfo() to return this information even when
than one address is tried for a connection these will hold data the session handle is no longer associated with a connection, and also
for the last attempt. When the connection is actualy established allow curl_easy_reset() to clear this information from the session handle
these are updated with data which comes directly from the socket. */ without disturbing information which is still alive, and that might be
reused, in the connection cache. */
char primary_ip[MAX_IPADR_LEN]; char conn_primary_ip[MAX_IPADR_LEN];
long primary_port; long conn_primary_port;
/* 'local_ip' and 'local_port' get filled with local's numerical char conn_local_ip[MAX_IPADR_LEN];
ip address and port number whenever an outgoing connection is long conn_local_port;
**established** from the primary socket to a remote address. */
char local_ip[MAX_IPADR_LEN];
long local_port;
struct curl_certinfo certs; /* info about the certs, only populated in struct curl_certinfo certs; /* info about the certs, only populated in
OpenSSL builds. Asked for with OpenSSL builds. Asked for with