mirror of
https://github.com/moparisthebest/curl
synced 2024-11-04 16:45:06 -05:00
parent
4570c22c57
commit
db061571ef
@ -626,13 +626,9 @@ void Curl_persistconninfo(struct connectdata *conn)
|
|||||||
conn->data->info.conn_local_port = conn->local_port;
|
conn->data->info.conn_local_port = conn->local_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
|
|
||||||
long *port);
|
|
||||||
|
|
||||||
/* retrieves ip address and port from a sockaddr structure.
|
/* retrieves ip address and port from a sockaddr structure.
|
||||||
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
|
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
|
||||||
UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
|
bool Curl_addr2string(struct sockaddr *sa, char *addr, long *port)
|
||||||
long *port)
|
|
||||||
{
|
{
|
||||||
struct sockaddr_in *si = NULL;
|
struct sockaddr_in *si = NULL;
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
@ -715,7 +711,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_GETPEERNAME
|
#ifdef HAVE_GETPEERNAME
|
||||||
if(!getaddressinfo((struct sockaddr*)&ssrem,
|
if(!Curl_addr2string((struct sockaddr*)&ssrem,
|
||||||
conn->primary_ip, &conn->primary_port)) {
|
conn->primary_ip, &conn->primary_port)) {
|
||||||
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
|
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
|
||||||
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||||
@ -724,7 +720,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
|
|||||||
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
|
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_GETSOCKNAME
|
#ifdef HAVE_GETSOCKNAME
|
||||||
if(!getaddressinfo((struct sockaddr*)&ssloc,
|
if(!Curl_addr2string((struct sockaddr*)&ssloc,
|
||||||
conn->local_ip, &conn->local_port)) {
|
conn->local_ip, &conn->local_port)) {
|
||||||
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
|
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
|
||||||
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||||
@ -1032,7 +1028,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
/* 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(!Curl_addr2string((struct sockaddr*)&addr.sa_addr,
|
||||||
ipaddress, &port)) {
|
ipaddress, &port)) {
|
||||||
/* malformed address or bug in inet_ntop, try next address */
|
/* malformed address or bug in inet_ntop, try next address */
|
||||||
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
|
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
|
||||||
|
@ -51,6 +51,8 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
|
|||||||
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
|
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
|
||||||
struct connectdata **connp);
|
struct connectdata **connp);
|
||||||
|
|
||||||
|
bool Curl_addr2string(struct sockaddr *sa, char *addr, long *port);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if a connection seems to be alive.
|
* Check if a connection seems to be alive.
|
||||||
*/
|
*/
|
||||||
|
@ -193,6 +193,7 @@ struct HTTP {
|
|||||||
/*********** for HTTP/3 we store stream-local data here *************/
|
/*********** for HTTP/3 we store stream-local data here *************/
|
||||||
int64_t stream3_id; /* stream we are interested in */
|
int64_t stream3_id; /* stream we are interested in */
|
||||||
bool firstbody; /* FALSE until body arrives */
|
bool firstbody; /* FALSE until body arrives */
|
||||||
|
bool h3req; /* FALSE until request is issued */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,13 +32,15 @@
|
|||||||
#include "quic.h"
|
#include "quic.h"
|
||||||
#include "strcase.h"
|
#include "strcase.h"
|
||||||
#include "multiif.h"
|
#include "multiif.h"
|
||||||
|
#include "connect.h"
|
||||||
|
#include "strerror.h"
|
||||||
|
|
||||||
/* The last 3 #include files should be in this order */
|
/* The last 3 #include files should be in this order */
|
||||||
#include "curl_printf.h"
|
#include "curl_printf.h"
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
/* #define DEBUG_HTTP3 */
|
#define DEBUG_HTTP3
|
||||||
/* #define DEBUG_QUICHE */
|
/* #define DEBUG_QUICHE */
|
||||||
#ifdef DEBUG_HTTP3
|
#ifdef DEBUG_HTTP3
|
||||||
#define H3BUGF(x) x
|
#define H3BUGF(x) x
|
||||||
@ -105,10 +107,17 @@ static unsigned int quiche_conncheck(struct connectdata *conn,
|
|||||||
return CONNRESULT_NONE;
|
return CONNRESULT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CURLcode quiche_do(struct connectdata *conn, bool *done)
|
||||||
|
{
|
||||||
|
struct HTTP *stream = conn->data->req.protop;
|
||||||
|
stream->h3req = FALSE; /* not sent */
|
||||||
|
return Curl_http(conn, done);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct Curl_handler Curl_handler_h3_quiche = {
|
static const struct Curl_handler Curl_handler_h3_quiche = {
|
||||||
"HTTPS", /* scheme */
|
"HTTPS", /* scheme */
|
||||||
ZERO_NULL, /* setup_connection */
|
ZERO_NULL, /* setup_connection */
|
||||||
Curl_http, /* do_it */
|
quiche_do, /* do_it */
|
||||||
Curl_http_done, /* done */
|
Curl_http_done, /* done */
|
||||||
ZERO_NULL, /* do_more */
|
ZERO_NULL, /* do_more */
|
||||||
ZERO_NULL, /* connect_it */
|
ZERO_NULL, /* connect_it */
|
||||||
@ -131,12 +140,13 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
|
|||||||
{
|
{
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
struct quicsocket *qs = &conn->quic;
|
struct quicsocket *qs = &conn->quic;
|
||||||
|
struct Curl_easy *data = conn->data;
|
||||||
(void)addr;
|
(void)addr;
|
||||||
(void)addrlen;
|
(void)addrlen;
|
||||||
|
|
||||||
qs->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
|
qs->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
|
||||||
if(!qs->cfg) {
|
if(!qs->cfg) {
|
||||||
failf(conn->data, "can't create quiche config");
|
failf(data, "can't create quiche config");
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +164,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
|
|||||||
sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
|
sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
|
||||||
- 1);
|
- 1);
|
||||||
|
|
||||||
result = Curl_rand(conn->data, qs->scid, sizeof(qs->scid));
|
result = Curl_rand(data, qs->scid, sizeof(qs->scid));
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -164,7 +174,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
|
|||||||
qs->conn = quiche_connect(conn->host.name, (const uint8_t *) qs->scid,
|
qs->conn = quiche_connect(conn->host.name, (const uint8_t *) qs->scid,
|
||||||
sizeof(qs->scid), qs->cfg);
|
sizeof(qs->scid), qs->cfg);
|
||||||
if(!qs->conn) {
|
if(!qs->conn) {
|
||||||
failf(conn->data, "can't create quiche connection");
|
failf(data, "can't create quiche connection");
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,12 +182,56 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
|
|||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
infof(conn->data, "Sent QUIC client Initial, ALPN: %s\n",
|
/* store the used address as a string */
|
||||||
|
if(!Curl_addr2string((struct sockaddr*)addr,
|
||||||
|
conn->primary_ip, &conn->primary_port)) {
|
||||||
|
char buffer[STRERROR_LEN];
|
||||||
|
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
|
||||||
|
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||||
|
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||||
|
}
|
||||||
|
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
|
||||||
|
|
||||||
|
/* for connection reuse purposes: */
|
||||||
|
conn->ssl[FIRSTSOCKET].state = ssl_connection_complete;
|
||||||
|
|
||||||
|
infof(data, "Sent QUIC client Initial, ALPN: %s\n",
|
||||||
QUICHE_H3_APPLICATION_PROTOCOL + 1);
|
QUICHE_H3_APPLICATION_PROTOCOL + 1);
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CURLcode quiche_has_connected(struct connectdata *conn,
|
||||||
|
int sockindex)
|
||||||
|
{
|
||||||
|
CURLcode result;
|
||||||
|
struct quicsocket *qs = &conn->quic;
|
||||||
|
|
||||||
|
conn->recv[sockindex] = h3_stream_recv;
|
||||||
|
conn->send[sockindex] = h3_stream_send;
|
||||||
|
conn->handler = &Curl_handler_h3_quiche;
|
||||||
|
conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
|
||||||
|
conn->httpversion = 30;
|
||||||
|
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
|
||||||
|
|
||||||
|
qs->h3config = quiche_h3_config_new(0, 1024, 0, 0);
|
||||||
|
if(!qs->h3config)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
/* Create a new HTTP/3 connection on the QUIC connection. */
|
||||||
|
qs->h3c = quiche_h3_conn_new_with_transport(qs->conn, qs->h3config);
|
||||||
|
if(!qs->h3c) {
|
||||||
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
return CURLE_OK;
|
||||||
|
fail:
|
||||||
|
quiche_h3_config_free(qs->h3config);
|
||||||
|
quiche_h3_conn_free(qs->h3c);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex,
|
CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex,
|
||||||
bool *done)
|
bool *done)
|
||||||
{
|
{
|
||||||
@ -194,14 +248,12 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex,
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
if(quiche_conn_is_established(qs->conn)) {
|
if(quiche_conn_is_established(qs->conn)) {
|
||||||
conn->recv[sockindex] = h3_stream_recv;
|
|
||||||
conn->send[sockindex] = h3_stream_send;
|
|
||||||
*done = TRUE;
|
*done = TRUE;
|
||||||
conn->handler = &Curl_handler_h3_quiche;
|
result = quiche_has_connected(conn, sockindex);
|
||||||
DEBUGF(infof(conn->data, "quiche established connection!\n"));
|
DEBUGF(infof(conn->data, "quiche established connection!\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return CURLE_OK;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode process_ingress(struct connectdata *conn, int sockfd)
|
static CURLcode process_ingress(struct connectdata *conn, int sockfd)
|
||||||
@ -336,6 +388,13 @@ static ssize_t h3_stream_recv(struct connectdata *conn,
|
|||||||
/* nothing more to do */
|
/* nothing more to do */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if(s != stream->stream3_id) {
|
||||||
|
/* another transfer, ignore for now */
|
||||||
|
infof(conn->data, "Got h3 for stream %u, expects %u\n",
|
||||||
|
s, stream->stream3_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch(quiche_h3_event_type(ev)) {
|
switch(quiche_h3_event_type(ev)) {
|
||||||
case QUICHE_H3_EVENT_HEADERS:
|
case QUICHE_H3_EVENT_HEADERS:
|
||||||
H3BUGF(infof(conn->data, "quiche says HEADERS\n"));
|
H3BUGF(infof(conn->data, "quiche says HEADERS\n"));
|
||||||
@ -399,8 +458,9 @@ static ssize_t h3_stream_send(struct connectdata *conn,
|
|||||||
ssize_t sent;
|
ssize_t sent;
|
||||||
struct quicsocket *qs = &conn->quic;
|
struct quicsocket *qs = &conn->quic;
|
||||||
curl_socket_t sockfd = conn->sock[sockindex];
|
curl_socket_t sockfd = conn->sock[sockindex];
|
||||||
|
struct HTTP *stream = conn->data->req.protop;
|
||||||
|
|
||||||
if(!qs->h3c) {
|
if(!stream->h3req) {
|
||||||
CURLcode result = http_request(conn, mem, len);
|
CURLcode result = http_request(conn, mem, len);
|
||||||
if(result) {
|
if(result) {
|
||||||
*curlcode = CURLE_SEND_ERROR;
|
*curlcode = CURLE_SEND_ERROR;
|
||||||
@ -467,16 +527,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
|
|||||||
quiche_enable_debug_logging(debug_log, NULL);
|
quiche_enable_debug_logging(debug_log, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qs->h3config = quiche_h3_config_new(0, 1024, 0, 0);
|
stream->h3req = TRUE; /* senf off! */
|
||||||
if(!qs->h3config)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
/* Create a new HTTP/3 connection on the QUIC connection. */
|
|
||||||
qs->h3c = quiche_h3_conn_new_with_transport(qs->conn, qs->h3config);
|
|
||||||
if(!qs->h3c) {
|
|
||||||
result = CURLE_OUT_OF_MEMORY;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate number of headers contained in [mem, mem + len). Assumes a
|
/* Calculate number of headers contained in [mem, mem + len). Assumes a
|
||||||
correctly generated HTTP header field block. */
|
correctly generated HTTP header field block. */
|
||||||
@ -678,8 +729,6 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
quiche_h3_config_free(qs->h3config);
|
|
||||||
quiche_h3_conn_free(qs->h3c);
|
|
||||||
free(nva);
|
free(nva);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,6 @@
|
|||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "share.h"
|
#include "share.h"
|
||||||
|
|
||||||
/* retrieves ip address and port from a sockaddr structure.
|
|
||||||
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
|
|
||||||
bool getaddressinfo(struct sockaddr *sa, char *addr, long *port);
|
|
||||||
|
|
||||||
#include "memdebug.h" /* LAST include file */
|
#include "memdebug.h" /* LAST include file */
|
||||||
|
|
||||||
static void unit_stop(void)
|
static void unit_stop(void)
|
||||||
@ -154,7 +150,7 @@ UNITTEST_START
|
|||||||
if(tests[i].address[j] == &skip)
|
if(tests[i].address[j] == &skip)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(addr && !getaddressinfo(addr->ai_addr,
|
if(addr && !Curl_addr2string(addr->ai_addr,
|
||||||
ipaddress, &port)) {
|
ipaddress, &port)) {
|
||||||
fprintf(stderr, "%s:%d tests[%d] failed. getaddressinfo failed.\n",
|
fprintf(stderr, "%s:%d tests[%d] failed. getaddressinfo failed.\n",
|
||||||
__FILE__, __LINE__, i);
|
__FILE__, __LINE__, i);
|
||||||
|
@ -25,10 +25,6 @@
|
|||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "share.h"
|
#include "share.h"
|
||||||
|
|
||||||
/* retrieves ip address and port from a sockaddr structure.
|
|
||||||
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
|
|
||||||
bool getaddressinfo(struct sockaddr *sa, char *addr, long *port);
|
|
||||||
|
|
||||||
#include "memdebug.h" /* LAST include file */
|
#include "memdebug.h" /* LAST include file */
|
||||||
|
|
||||||
static void unit_stop(void)
|
static void unit_stop(void)
|
||||||
@ -154,9 +150,9 @@ UNITTEST_START
|
|||||||
if(!addr && !tests[i].address[j])
|
if(!addr && !tests[i].address[j])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(addr && !getaddressinfo(addr->ai_addr,
|
if(addr && !Curl_addr2string(addr->ai_addr,
|
||||||
ipaddress, &port)) {
|
ipaddress, &port)) {
|
||||||
fprintf(stderr, "%s:%d tests[%d] failed. getaddressinfo failed.\n",
|
fprintf(stderr, "%s:%d tests[%d] failed. Curl_addr2string failed.\n",
|
||||||
__FILE__, __LINE__, i);
|
__FILE__, __LINE__, i);
|
||||||
problem = true;
|
problem = true;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user