ip_quadruple/proxy: make port uint16_t

Make `port` member in these struct of type `uint16_t`.

add `uint8_t transport` to `struct ip_quadruple

Define TRNSPRT_NONE as 0. By assigning a valid transport only on a
successful connection, it is clear when the ip_quadruple members are
valid. Also, for transports not involving ports, the getinfos for
`CURLINFO_PRIMARY_PORT` and `CURLINFO_LOCAL_PORT` will now always return
-1.

Make all `transport` members and parameters of type `uint8_t`.

Document the return value of `CURLINFO_LOCAL_PORT` and
`CURLINFO_PRIMARY_PORT` in this regard. Add tests that writeout stats
report ports correctly.

Closes #19708
This commit is contained in:
Stefan Eissing 2025-11-26 14:05:46 +01:00 committed by Daniel Stenberg
parent feea968512
commit c4f29cc508
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
20 changed files with 104 additions and 80 deletions

View file

@ -55,7 +55,7 @@ struct cf_hc_baller {
CURLcode result;
struct curltime started;
int reply_ms;
unsigned char transport;
uint8_t transport;
enum alpnid alpn_id;
BIT(shutdown);
};
@ -124,7 +124,7 @@ struct cf_hc_ctx {
static void cf_hc_baller_assign(struct cf_hc_baller *b,
enum alpnid alpn_id,
unsigned char def_transport)
uint8_t def_transport)
{
b->alpn_id = alpn_id;
b->transport = def_transport;
@ -148,7 +148,7 @@ static void cf_hc_baller_assign(struct cf_hc_baller *b,
static void cf_hc_baller_init(struct cf_hc_baller *b,
struct Curl_cfilter *cf,
struct Curl_easy *data,
int transport)
uint8_t transport)
{
struct Curl_cfilter *save = cf->next;
@ -581,7 +581,7 @@ struct Curl_cftype Curl_cft_http_connect = {
static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
enum alpnid *alpnids, size_t alpn_count,
unsigned char def_transport)
uint8_t def_transport)
{
struct Curl_cfilter *cf = NULL;
struct cf_hc_ctx *ctx;
@ -626,7 +626,7 @@ static CURLcode cf_http_connect_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
enum alpnid *alpn_ids, size_t alpn_count,
unsigned char def_transport)
uint8_t def_transport)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OK;

View file

@ -66,7 +66,7 @@
struct transport_provider {
int transport;
uint8_t transport;
cf_ip_connect_create *cf_create;
};
@ -87,7 +87,7 @@ struct transport_provider transport_providers[] = {
#endif
};
static cf_ip_connect_create *get_cf_create(int transport)
static cf_ip_connect_create *get_cf_create(uint8_t transport)
{
size_t i;
for(i = 0; i < CURL_ARRAYSIZE(transport_providers); ++i) {
@ -99,7 +99,7 @@ static cf_ip_connect_create *get_cf_create(int transport)
#ifdef UNITTESTS
/* used by unit2600.c */
void Curl_debug_set_transport_provider(int transport,
void Curl_debug_set_transport_provider(uint8_t transport,
cf_ip_connect_create *cf_create)
{
size_t i;
@ -172,7 +172,7 @@ struct cf_ip_attempt {
struct curltime started; /* start of current attempt */
CURLcode result;
int ai_family;
int transport;
uint8_t transport;
int error;
BIT(connected); /* cf has connected */
BIT(shutdown); /* cf has shutdown */
@ -195,7 +195,7 @@ static CURLcode cf_ip_attempt_new(struct cf_ip_attempt **pa,
struct Curl_easy *data,
const struct Curl_addrinfo *addr,
int ai_family,
int transport,
uint8_t transport,
cf_ip_connect_create *cf_create)
{
struct Curl_cfilter *wcf;
@ -264,7 +264,7 @@ struct cf_ip_ballers {
struct curltime last_attempt_started;
timediff_t attempt_delay_ms;
int last_attempt_ai_family;
int transport;
uint8_t transport;
};
static CURLcode cf_ip_attempt_restart(struct cf_ip_attempt *a,
@ -315,7 +315,7 @@ static void cf_ip_ballers_clear(struct Curl_cfilter *cf,
static CURLcode cf_ip_ballers_init(struct cf_ip_ballers *bs, int ip_version,
const struct Curl_addrinfo *addr_list,
cf_ip_connect_create *cf_create,
int transport,
uint8_t transport,
timediff_t attempt_delay_ms)
{
memset(bs, 0, sizeof(*bs));
@ -626,7 +626,7 @@ typedef enum {
} cf_connect_state;
struct cf_ip_happy_ctx {
int transport;
uint8_t transport;
cf_ip_connect_create *cf_create;
cf_connect_state state;
struct cf_ip_ballers ballers;
@ -713,7 +713,7 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
return CURLE_OPERATION_TIMEDOUT;
}
CURL_TRC_CF(data, cf, "init ip ballers for transport %d", ctx->transport);
CURL_TRC_CF(data, cf, "init ip ballers for transport %u", ctx->transport);
ctx->started = curlx_now();
return cf_ip_ballers_init(&ctx->ballers, cf->conn->ip_version,
dns->addr, ctx->cf_create, ctx->transport,
@ -933,7 +933,7 @@ static CURLcode cf_ip_happy_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
cf_ip_connect_create *cf_create,
int transport)
uint8_t transport)
{
struct cf_ip_happy_ctx *ctx = NULL;
CURLcode result;
@ -961,7 +961,7 @@ out:
CURLcode cf_ip_happy_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
int transport)
uint8_t transport)
{
cf_ip_connect_create *cf_create;
struct Curl_cfilter *cf;
@ -971,7 +971,7 @@ CURLcode cf_ip_happy_insert_after(struct Curl_cfilter *cf_at,
DEBUGASSERT(cf_at);
cf_create = get_cf_create(transport);
if(!cf_create) {
CURL_TRC_CF(data, cf_at, "unsupported transport type %d", transport);
CURL_TRC_CF(data, cf_at, "unsupported transport type %u", transport);
return CURLE_UNSUPPORTED_PROTOCOL;
}
result = cf_ip_happy_create(&cf, data, cf_at->conn, cf_create, transport);

View file

@ -43,16 +43,16 @@ typedef CURLcode cf_ip_connect_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
uint8_t transport);
CURLcode cf_ip_happy_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
int transport);
uint8_t transport);
extern struct Curl_cftype Curl_cft_ip_happy;
#ifdef UNITTESTS
void Curl_debug_set_transport_provider(int transport,
void Curl_debug_set_transport_provider(uint8_t transport,
cf_ip_connect_create *cf_create);
#endif

View file

@ -303,7 +303,7 @@ tcpkeepalive(struct Curl_cfilter *cf,
*/
static CURLcode sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport)
uint8_t transport)
{
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
@ -404,7 +404,7 @@ static CURLcode socket_open(struct Curl_easy *data,
CURLcode Curl_socket_open(struct Curl_easy *data,
const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
int transport,
uint8_t transport,
curl_socket_t *sockfd)
{
struct Curl_sockaddr_ex dummy;
@ -909,7 +909,7 @@ static CURLcode socket_connect_result(struct Curl_easy *data,
}
struct cf_socket_ctx {
int transport;
uint8_t transport;
struct Curl_sockaddr_ex addr; /* address to connect to */
curl_socket_t sock; /* current attempt socket */
struct ip_quadruple ip; /* The IP quadruple 2x(addr+port) */
@ -936,7 +936,7 @@ struct cf_socket_ctx {
static CURLcode cf_socket_ctx_init(struct cf_socket_ctx *ctx,
const struct Curl_addrinfo *ai,
int transport)
uint8_t transport)
{
CURLcode result;
@ -1035,7 +1035,7 @@ static void set_local_ip(struct Curl_cfilter *cf,
{
struct cf_socket_ctx *ctx = cf->ctx;
ctx->ip.local_ip[0] = 0;
ctx->ip.local_port = -1;
ctx->ip.local_port = 0;
#ifdef HAVE_GETSOCKNAME
if((ctx->sock != CURL_SOCKET_BAD) &&
@ -1069,6 +1069,7 @@ static CURLcode set_remote_ip(struct Curl_cfilter *cf,
struct cf_socket_ctx *ctx = cf->ctx;
/* store remote address and port used in this connection attempt */
ctx->ip.transport = ctx->transport;
if(!Curl_addr2string(&ctx->addr.curl_sa_addr,
(curl_socklen_t)ctx->addr.addrlen,
ctx->ip.remote_ip, &ctx->ip.remote_port)) {
@ -1743,7 +1744,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport)
uint8_t transport)
{
struct cf_socket_ctx *ctx = NULL;
struct Curl_cfilter *cf = NULL;
@ -1910,7 +1911,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport)
uint8_t transport)
{
struct cf_socket_ctx *ctx = NULL;
struct Curl_cfilter *cf = NULL;
@ -1964,7 +1965,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport)
uint8_t transport)
{
struct cf_socket_ctx *ctx = NULL;
struct Curl_cfilter *cf = NULL;

View file

@ -71,7 +71,7 @@ CURLcode Curl_parse_interface(const char *input,
CURLcode Curl_socket_open(struct Curl_easy *data,
const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
int transport,
uint8_t transport,
curl_socket_t *sockfd);
int Curl_socket_close(struct Curl_easy *data, struct connectdata *conn,
@ -103,7 +103,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
uint8_t transport);
/**
* Creates a cfilter that opens a UDP socket to the given address
@ -116,7 +116,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
uint8_t transport);
/**
* Creates a cfilter that opens a UNIX socket to the given address
@ -129,7 +129,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
uint8_t transport);
/**
* Creates a cfilter that keeps a listening socket.

View file

@ -238,7 +238,7 @@ bool Curl_shutdown_started(struct Curl_easy *data, int sockindex)
/* retrieves ip address and port from a sockaddr structure. note it calls
curlx_inet_ntop which sets errno on fail, not SOCKERRNO. */
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
char *addr, int *port)
char *addr, uint16_t *port)
{
struct sockaddr_in *si = NULL;
#ifdef USE_IPV6
@ -254,8 +254,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
case AF_INET:
si = (struct sockaddr_in *)(void *) sa;
if(curlx_inet_ntop(sa->sa_family, &si->sin_addr, addr, MAX_IPADR_LEN)) {
unsigned short us_port = ntohs(si->sin_port);
*port = us_port;
*port = ntohs(si->sin_port);
return TRUE;
}
break;
@ -264,8 +263,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
si6 = (struct sockaddr_in6 *)(void *) sa;
if(curlx_inet_ntop(sa->sa_family, &si6->sin6_addr, addr,
MAX_IPADR_LEN)) {
unsigned short us_port = ntohs(si6->sin6_port);
*port = us_port;
*port = ntohs(si6->sin6_port);
return TRUE;
}
break;
@ -366,7 +364,7 @@ typedef enum {
struct cf_setup_ctx {
cf_setup_state state;
int ssl_mode;
int transport;
uint8_t transport;
};
static CURLcode cf_setup_connect(struct Curl_cfilter *cf,
@ -521,7 +519,7 @@ struct Curl_cftype Curl_cft_setup = {
static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
int transport,
uint8_t transport,
int ssl_mode)
{
struct Curl_cfilter *cf = NULL;
@ -554,7 +552,7 @@ out:
static CURLcode cf_setup_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
int transport,
uint8_t transport,
int ssl_mode)
{
struct Curl_cfilter *cf;
@ -571,7 +569,7 @@ out:
CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
int transport,
uint8_t transport,
int ssl_mode)
{
struct Curl_cfilter *cf;

View file

@ -74,7 +74,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp);
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
char *addr, int *port);
char *addr, uint16_t *port);
/*
* Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
@ -111,7 +111,7 @@ void Curl_conncontrol(struct connectdata *conn,
CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
int transport,
uint8_t transport,
int ssl_mode);
/**

View file

@ -81,8 +81,6 @@ void Curl_initinfo(struct Curl_easy *data)
info->wouldredirect = NULL;
memset(&info->primary, 0, sizeof(info->primary));
info->primary.remote_port = -1;
info->primary.local_port = -1;
info->retry_after = 0;
info->conn_scheme = 0;
@ -304,11 +302,17 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
break;
case CURLINFO_PRIMARY_PORT:
/* Return the (remote) port of the most recent (primary) connection */
*param_longp = data->info.primary.remote_port;
if(CUR_IP_QUAD_HAS_PORTS(&data->info.primary))
*param_longp = data->info.primary.remote_port;
else
*param_longp = -1;
break;
case CURLINFO_LOCAL_PORT:
/* Return the local port of the most recent (primary) connection */
*param_longp = data->info.primary.local_port;
if(CUR_IP_QUAD_HAS_PORTS(&data->info.primary))
*param_longp = data->info.primary.local_port;
else
*param_longp = -1;
break;
case CURLINFO_PROXY_ERROR:
*param_longp = (long)data->info.pxcode;

View file

@ -1001,9 +1001,9 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#endif
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXYPORT:
if((arg < 0) || (arg > 65535))
if((arg < 0) || (arg > UINT16_MAX))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->proxyport = (unsigned short)arg;
s->proxyport = (uint16_t)arg;
break;
case CURLOPT_PROXYAUTH:

View file

@ -2171,7 +2171,6 @@ static CURLcode parse_proxy(struct Curl_easy *data,
long proxytype)
{
char *portptr = NULL;
int port = -1;
char *proxyuser = NULL;
char *proxypasswd = NULL;
char *host = NULL;
@ -2293,24 +2292,23 @@ static CURLcode parse_proxy(struct Curl_easy *data,
if(portptr) {
curl_off_t num;
const char *p = portptr;
if(!curlx_str_number(&p, &num, 0xffff))
port = (int)num;
if(!curlx_str_number(&p, &num, UINT16_MAX))
proxyinfo->port = (uint16_t)num;
/* Should we not error out when the port number is invalid? */
free(portptr);
}
else {
if(data->set.proxyport)
/* None given in the proxy string, then get the default one if it is
given */
port = (int)data->set.proxyport;
proxyinfo->port = data->set.proxyport;
else {
if(IS_HTTPS_PROXY(proxytype))
port = CURL_DEFAULT_HTTPS_PROXY_PORT;
proxyinfo->port = CURL_DEFAULT_HTTPS_PROXY_PORT;
else
port = CURL_DEFAULT_PROXY_PORT;
proxyinfo->port = CURL_DEFAULT_PROXY_PORT;
}
}
if(port >= 0)
proxyinfo->port = port;
/* now, clone the proxy hostname */
uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE);

View file

@ -528,7 +528,7 @@ struct Curl_handler {
CURLcode (*follow)(struct Curl_easy *data, const char *newurl,
followtype type);
int defport; /* Default port. */
uint16_t defport; /* Default port. */
curl_prot_t protocol; /* See CURLPROTO_* - this needs to be the single
specific protocol bit */
curl_prot_t family; /* single bit for protocol family; basically the
@ -576,26 +576,32 @@ struct Curl_handler {
#define CONNRESULT_NONE 0 /* No extra information. */
#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */
struct ip_quadruple {
char remote_ip[MAX_IPADR_LEN];
char local_ip[MAX_IPADR_LEN];
int remote_port;
int local_port;
};
struct proxy_info {
struct hostname host;
int port;
unsigned char proxytype; /* what kind of proxy that is in use */
char *user; /* proxy username string, allocated */
char *passwd; /* proxy password string, allocated */
};
#define TRNSPRT_NONE 0
#define TRNSPRT_TCP 3
#define TRNSPRT_UDP 4
#define TRNSPRT_QUIC 5
#define TRNSPRT_UNIX 6
struct ip_quadruple {
char remote_ip[MAX_IPADR_LEN];
char local_ip[MAX_IPADR_LEN];
uint16_t remote_port;
uint16_t local_port;
uint8_t transport;
};
#define CUR_IP_QUAD_HAS_PORTS(x) (((x)->transport == TRNSPRT_TCP) || \
((x)->transport == TRNSPRT_UDP) || \
((x)->transport == TRNSPRT_QUIC))
struct proxy_info {
struct hostname host;
uint16_t port;
unsigned char proxytype; /* what kind of proxy that is in use */
char *user; /* proxy username string, allocated */
char *passwd; /* proxy password string, allocated */
};
/*
* The connectdata struct contains all fields and variables that should be
* unique for an entire connection.
@ -1364,7 +1370,7 @@ struct UserDefined {
#ifndef CURL_DISABLE_PROXY
struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */
struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */
unsigned short proxyport; /* If non-zero, use this port number by
uint16_t proxyport; /* If non-zero, use this port number by
default. If the proxy string features a
":[port]" that one will override this. */
unsigned char proxytype; /* what kind of proxy */

View file

@ -687,7 +687,7 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport)
uint8_t transport)
{
(void)transport;
DEBUGASSERT(transport == TRNSPRT_QUIC);

View file

@ -45,7 +45,7 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
uint8_t transport);
extern struct Curl_cftype Curl_cft_http3;