diff options
Diffstat (limited to 'Utilities/cmcurl/lib/vquic/quiche.c')
-rw-r--r-- | Utilities/cmcurl/lib/vquic/quiche.c | 127 |
1 files changed, 66 insertions, 61 deletions
diff --git a/Utilities/cmcurl/lib/vquic/quiche.c b/Utilities/cmcurl/lib/vquic/quiche.c index d0d150e391..d138dd3a24 100644 --- a/Utilities/cmcurl/lib/vquic/quiche.c +++ b/Utilities/cmcurl/lib/vquic/quiche.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -53,21 +53,22 @@ #define QUIC_MAX_DATA (1*1024*1024) #define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */ -static CURLcode process_ingress(struct connectdata *conn, +static CURLcode process_ingress(struct Curl_easy *data, curl_socket_t sockfd, struct quicsocket *qs); -static CURLcode flush_egress(struct connectdata *conn, curl_socket_t sockfd, +static CURLcode flush_egress(struct Curl_easy *data, curl_socket_t sockfd, struct quicsocket *qs); -static CURLcode http_request(struct connectdata *conn, const void *mem, +static CURLcode http_request(struct Curl_easy *data, const void *mem, size_t len); static Curl_recv h3_stream_recv; static Curl_send h3_stream_send; -static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks) +static int quiche_getsock(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t *socks) { - struct SingleRequest *k = &conn->data->req; + struct SingleRequest *k = &data->req; int bitmap = GETSOCK_BLANK; socks[0] = conn->sock[FIRSTSOCKET]; @@ -83,20 +84,15 @@ static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks) return bitmap; } -static int quiche_perform_getsock(const struct connectdata *conn, - curl_socket_t *socks) -{ - return quiche_getsock((struct connectdata *)conn, socks); -} - -static CURLcode qs_disconnect(struct connectdata *conn, +static CURLcode qs_disconnect(struct Curl_easy *data, struct quicsocket *qs) { + DEBUGASSERT(qs); if(qs->conn) { (void)quiche_conn_close(qs->conn, TRUE, 0, NULL, 0); /* flushing the egress is not a failsafe way to deliver all the outstanding packets, but we also don't want to get stuck here... */ - (void)flush_egress(conn, qs->sockfd, qs); + (void)flush_egress(data, qs->sockfd, qs); quiche_conn_free(qs->conn); qs->conn = NULL; } @@ -111,34 +107,38 @@ static CURLcode qs_disconnect(struct connectdata *conn, return CURLE_OK; } -static CURLcode quiche_disconnect(struct connectdata *conn, +static CURLcode quiche_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead_connection) { struct quicsocket *qs = conn->quic; (void)dead_connection; - return qs_disconnect(conn, qs); + return qs_disconnect(data, qs); } -void Curl_quic_disconnect(struct connectdata *conn, +void Curl_quic_disconnect(struct Curl_easy *data, + struct connectdata *conn, int tempindex) { if(conn->transport == TRNSPRT_QUIC) - qs_disconnect(conn, &conn->hequic[tempindex]); + qs_disconnect(data, &conn->hequic[tempindex]); } -static unsigned int quiche_conncheck(struct connectdata *conn, +static unsigned int quiche_conncheck(struct Curl_easy *data, + struct connectdata *conn, unsigned int checks_to_perform) { + (void)data; (void)conn; (void)checks_to_perform; return CONNRESULT_NONE; } -static CURLcode quiche_do(struct connectdata *conn, bool *done) +static CURLcode quiche_do(struct Curl_easy *data, bool *done) { - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; stream->h3req = FALSE; /* not sent */ - return Curl_http(conn, done); + return Curl_http(data, done); } static const struct Curl_handler Curl_handler_http3 = { @@ -153,7 +153,7 @@ static const struct Curl_handler Curl_handler_http3 = { quiche_getsock, /* proto_getsock */ quiche_getsock, /* doing_getsock */ ZERO_NULL, /* domore_getsock */ - quiche_perform_getsock, /* perform_getsock */ + quiche_getsock, /* perform_getsock */ quiche_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ quiche_conncheck, /* connection_check */ @@ -171,14 +171,16 @@ static void quiche_debug_log(const char *line, void *argp) } #endif -CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd, +CURLcode Curl_quic_connect(struct Curl_easy *data, + struct connectdata *conn, curl_socket_t sockfd, int sockindex, const struct sockaddr *addr, socklen_t addrlen) { CURLcode result; struct quicsocket *qs = &conn->hequic[sockindex]; - struct Curl_easy *data = conn->data; char *keylog_file = NULL; + char ipbuf[40]; + long port; #ifdef DEBUG_QUICHE /* initialize debug log callback only once */ @@ -243,20 +245,22 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd, } #endif - result = flush_egress(conn, sockfd, qs); + result = flush_egress(data, sockfd, qs); if(result) return result; - /* store the used address as a string */ - if(!Curl_addr2string((struct sockaddr*)addr, addrlen, - conn->primary_ip, &conn->primary_port)) { + /* extract the used address as a string */ + if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) { char buffer[STRERROR_LEN]; failf(data, "ssrem inet_ntop() failed with errno %d: %s", SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_BAD_FUNCTION_ARGUMENT; } - memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); - Curl_persistconninfo(conn); + + infof(data, "Connect socket %d over QUIC to %s:%ld\n", + sockfd, ipbuf, port); + + Curl_persistconninfo(data, conn, NULL, -1); /* for connection reuse purposes: */ conn->ssl[FIRSTSOCKET].state = ssl_connection_complete; @@ -320,38 +324,39 @@ static CURLcode quiche_has_connected(struct connectdata *conn, /* * This function gets polled to check if this QUIC connection has connected. */ -CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex, +CURLcode Curl_quic_is_connected(struct Curl_easy *data, + struct connectdata *conn, + int sockindex, bool *done) { CURLcode result; struct quicsocket *qs = &conn->hequic[sockindex]; curl_socket_t sockfd = conn->tempsock[sockindex]; - result = process_ingress(conn, sockfd, qs); + result = process_ingress(data, sockfd, qs); if(result) goto error; - result = flush_egress(conn, sockfd, qs); + result = flush_egress(data, sockfd, qs); if(result) goto error; if(quiche_conn_is_established(qs->conn)) { *done = TRUE; result = quiche_has_connected(conn, 0, sockindex); - DEBUGF(infof(conn->data, "quiche established connection!\n")); + DEBUGF(infof(data, "quiche established connection!\n")); } return result; error: - qs_disconnect(conn, qs); + qs_disconnect(data, qs); return result; } -static CURLcode process_ingress(struct connectdata *conn, int sockfd, +static CURLcode process_ingress(struct Curl_easy *data, int sockfd, struct quicsocket *qs) { ssize_t recvd; - struct Curl_easy *data = conn->data; uint8_t *buf = (uint8_t *)data->state.buffer; size_t bufsize = data->set.buffer_size; @@ -364,7 +369,7 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd, break; if(recvd < 0) { - failf(conn->data, "quiche: recv() unexpectedly returned %zd " + failf(data, "quiche: recv() unexpectedly returned %zd " "(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd); return CURLE_RECV_ERROR; } @@ -374,7 +379,7 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd, break; if(recvd < 0) { - failf(conn->data, "quiche_conn_recv() == %zd", recvd); + failf(data, "quiche_conn_recv() == %zd", recvd); return CURLE_RECV_ERROR; } } while(1); @@ -386,7 +391,7 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd, * flush_egress drains the buffers and sends off data. * Calls failf() on errors. */ -static CURLcode flush_egress(struct connectdata *conn, int sockfd, +static CURLcode flush_egress(struct Curl_easy *data, int sockfd, struct quicsocket *qs) { ssize_t sent; @@ -399,14 +404,13 @@ static CURLcode flush_egress(struct connectdata *conn, int sockfd, break; if(sent < 0) { - failf(conn->data, "quiche_conn_send returned %zd\n", - sent); + failf(data, "quiche_conn_send returned %zd", sent); return CURLE_SEND_ERROR; } sent = send(sockfd, out, sent, 0); if(sent < 0) { - failf(conn->data, "send() returned %zd\n", sent); + failf(data, "send() returned %zd", sent); return CURLE_SEND_ERROR; } } while(1); @@ -415,7 +419,7 @@ static CURLcode flush_egress(struct connectdata *conn, int sockfd, timeout_ns = quiche_conn_timeout_as_nanos(qs->conn); if(timeout_ns) /* expire uses milliseconds */ - Curl_expire(conn->data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC); + Curl_expire(data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC); return CURLE_OK; } @@ -453,7 +457,7 @@ static int cb_each_header(uint8_t *name, size_t name_len, return 0; } -static ssize_t h3_stream_recv(struct connectdata *conn, +static ssize_t h3_stream_recv(struct Curl_easy *data, int sockindex, char *buf, size_t buffersize, @@ -461,18 +465,18 @@ static ssize_t h3_stream_recv(struct connectdata *conn, { ssize_t recvd = -1; ssize_t rcode; + struct connectdata *conn = data->conn; struct quicsocket *qs = conn->quic; curl_socket_t sockfd = conn->sock[sockindex]; quiche_h3_event *ev; int rc; struct h3h1header headers; - struct Curl_easy *data = conn->data; struct HTTP *stream = data->req.p.http; headers.dest = buf; headers.destlen = buffersize; headers.nlen = 0; - if(process_ingress(conn, sockfd, qs)) { + if(process_ingress(data, sockfd, qs)) { infof(data, "h3_stream_recv returns on ingress\n"); *curlcode = CURLE_RECV_ERROR; return -1; @@ -532,7 +536,7 @@ static ssize_t h3_stream_recv(struct connectdata *conn, quiche_h3_event_free(ev); } - if(flush_egress(conn, sockfd, qs)) { + if(flush_egress(data, sockfd, qs)) { *curlcode = CURLE_SEND_ERROR; return -1; } @@ -546,19 +550,20 @@ static ssize_t h3_stream_recv(struct connectdata *conn, return recvd; } -static ssize_t h3_stream_send(struct connectdata *conn, +static ssize_t h3_stream_send(struct Curl_easy *data, int sockindex, const void *mem, size_t len, CURLcode *curlcode) { ssize_t sent; + struct connectdata *conn = data->conn; struct quicsocket *qs = conn->quic; curl_socket_t sockfd = conn->sock[sockindex]; - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; if(!stream->h3req) { - CURLcode result = http_request(conn, mem, len); + CURLcode result = http_request(data, mem, len); if(result) { *curlcode = CURLE_SEND_ERROR; return -1; @@ -566,8 +571,7 @@ static ssize_t h3_stream_send(struct connectdata *conn, sent = len; } else { - H3BUGF(infof(conn->data, "Pass on %zd body bytes to quiche\n", - len)); + H3BUGF(infof(data, "Pass on %zd body bytes to quiche\n", len)); sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id, (uint8_t *)mem, len, FALSE); if(sent < 0) { @@ -576,7 +580,7 @@ static ssize_t h3_stream_send(struct connectdata *conn, } } - if(flush_egress(conn, sockfd, qs)) { + if(flush_egress(data, sockfd, qs)) { *curlcode = CURLE_SEND_ERROR; return -1; } @@ -598,12 +602,13 @@ int Curl_quic_ver(char *p, size_t len) field list. */ #define AUTHORITY_DST_IDX 3 -static CURLcode http_request(struct connectdata *conn, const void *mem, +static CURLcode http_request(struct Curl_easy *data, const void *mem, size_t len) { /* */ - struct HTTP *stream = conn->data->req.p.http; + struct connectdata *conn = data->conn; + struct HTTP *stream = data->req.p.http; size_t nheader; size_t i; size_t authority_idx; @@ -613,7 +618,6 @@ static CURLcode http_request(struct connectdata *conn, const void *mem, quiche_h3_header *nva = NULL; struct quicsocket *qs = conn->quic; CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; stream->h3req = TRUE; /* senf off! */ @@ -826,14 +830,15 @@ fail: /* * Called from transfer.c:done_sending when we stop HTTP/3 uploading. */ -CURLcode Curl_quic_done_sending(struct connectdata *conn) +CURLcode Curl_quic_done_sending(struct Curl_easy *data) { + struct connectdata *conn = data->conn; + DEBUGASSERT(conn); if(conn->handler == &Curl_handler_http3) { /* only for HTTP/3 transfers */ ssize_t sent; - struct HTTP *stream = conn->data->req.p.http; + struct HTTP *stream = data->req.p.http; struct quicsocket *qs = conn->quic; - fprintf(stderr, "!!! Curl_quic_done_sending\n"); stream->upload_done = TRUE; sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id, NULL, 0, TRUE); |