curl_log: for failf/infof and debug logging implementations
- new functions and macros for cfilter debugging - set CURL_DEBUG with names of cfilters where debug logging should be enabled - use GNUC __attribute__ to enable printf format checks during compile Closes #10271
This commit is contained in:
parent
5cf5bfcd13
commit
db91dbbf2c
@ -120,6 +120,7 @@ LIB_CFILES = \
|
|||||||
curl_get_line.c \
|
curl_get_line.c \
|
||||||
curl_gethostname.c \
|
curl_gethostname.c \
|
||||||
curl_gssapi.c \
|
curl_gssapi.c \
|
||||||
|
curl_log.c \
|
||||||
curl_memrchr.c \
|
curl_memrchr.c \
|
||||||
curl_multibyte.c \
|
curl_multibyte.c \
|
||||||
curl_ntlm_core.c \
|
curl_ntlm_core.c \
|
||||||
@ -249,6 +250,7 @@ LIB_HFILES = \
|
|||||||
curl_hmac.h \
|
curl_hmac.h \
|
||||||
curl_krb5.h \
|
curl_krb5.h \
|
||||||
curl_ldap.h \
|
curl_ldap.h \
|
||||||
|
curl_log.h \
|
||||||
curl_md4.h \
|
curl_md4.h \
|
||||||
curl_md5.h \
|
curl_md5.h \
|
||||||
curl_memory.h \
|
curl_memory.h \
|
||||||
|
|||||||
@ -79,14 +79,6 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
|
||||||
#define DEBUG_CF 1
|
|
||||||
|
|
||||||
#if DEBUG_CF
|
|
||||||
#define CF_DEBUGF(x) x
|
|
||||||
#else
|
|
||||||
#define CF_DEBUGF(x) do { } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
|
static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
|
||||||
{
|
{
|
||||||
#if defined(TCP_NODELAY)
|
#if defined(TCP_NODELAY)
|
||||||
@ -305,7 +297,6 @@ static int socket_close(struct Curl_easy *data, struct connectdata *conn,
|
|||||||
{
|
{
|
||||||
if(use_callback && conn && conn->fclosesocket) {
|
if(use_callback && conn && conn->fclosesocket) {
|
||||||
int rc;
|
int rc;
|
||||||
CF_DEBUGF(infof(data, "socket_close(%d) via callback", (int)sock));
|
|
||||||
Curl_multi_closed(data, sock);
|
Curl_multi_closed(data, sock);
|
||||||
Curl_set_in_callback(data, true);
|
Curl_set_in_callback(data, true);
|
||||||
rc = conn->fclosesocket(conn->closesocket_client, sock);
|
rc = conn->fclosesocket(conn->closesocket_client, sock);
|
||||||
@ -313,7 +304,6 @@ static int socket_close(struct Curl_easy *data, struct connectdata *conn,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, "socket_close(%d)", (int)sock));
|
|
||||||
if(conn)
|
if(conn)
|
||||||
/* tell the multi-socket code about this */
|
/* tell the multi-socket code about this */
|
||||||
Curl_multi_closed(data, sock);
|
Curl_multi_closed(data, sock);
|
||||||
@ -777,22 +767,20 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||||||
* closed it) and we just forget about it.
|
* closed it) and we just forget about it.
|
||||||
*/
|
*/
|
||||||
if(ctx->sock == cf->conn->sock[cf->sockindex]) {
|
if(ctx->sock == cf->conn->sock[cf->sockindex]) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "cf_socket_close(%d) active"),
|
DEBUGF(LOG_CF(data, cf, "cf_socket_close(%d) active", (int)ctx->sock));
|
||||||
(int)ctx->sock));
|
|
||||||
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
|
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
|
||||||
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
|
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "cf_socket_close(%d) no longer at "
|
DEBUGF(LOG_CF(data, cf, "cf_socket_close(%d) no longer at "
|
||||||
"conn->sock[%d], discarding"), (int)ctx->sock));
|
"conn->sock[], discarding", (int)ctx->sock));
|
||||||
}
|
}
|
||||||
if(cf->sockindex == FIRSTSOCKET)
|
if(cf->sockindex == FIRSTSOCKET)
|
||||||
cf->conn->remote_addr = NULL;
|
cf->conn->remote_addr = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* this is our local socket, we did never publish it */
|
/* this is our local socket, we did never publish it */
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "cf_socket_close(%d) local"),
|
DEBUGF(LOG_CF(data, cf, "cf_socket_close(%d) local", (int)ctx->sock));
|
||||||
(int)ctx->sock));
|
|
||||||
sclose(ctx->sock);
|
sclose(ctx->sock);
|
||||||
}
|
}
|
||||||
ctx->sock = CURL_SOCKET_BAD;
|
ctx->sock = CURL_SOCKET_BAD;
|
||||||
@ -807,6 +795,7 @@ static void cf_socket_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||||||
struct cf_socket_ctx *ctx = cf->ctx;
|
struct cf_socket_ctx *ctx = cf->ctx;
|
||||||
|
|
||||||
cf_socket_close(cf, data);
|
cf_socket_close(cf, data);
|
||||||
|
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||||
free(ctx);
|
free(ctx);
|
||||||
cf->ctx = NULL;
|
cf->ctx = NULL;
|
||||||
}
|
}
|
||||||
@ -1018,7 +1007,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
|
|||||||
CURLcode result = CURLE_COULDNT_CONNECT;
|
CURLcode result = CURLE_COULDNT_CONNECT;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "connect")));
|
DEBUGF(LOG_CF(data, cf, "connect"));
|
||||||
(void)data;
|
(void)data;
|
||||||
if(cf->connected) {
|
if(cf->connected) {
|
||||||
*done = TRUE;
|
*done = TRUE;
|
||||||
@ -1036,7 +1025,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
|
|||||||
if(result)
|
if(result)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "connect opened(%d)"), (int)ctx->sock));
|
DEBUGF(LOG_CF(data, cf, "connect opened(%d)", (int)ctx->sock));
|
||||||
/* Connect TCP socket */
|
/* Connect TCP socket */
|
||||||
rc = do_connect(cf, data);
|
rc = do_connect(cf, data);
|
||||||
if(-1 == rc) {
|
if(-1 == rc) {
|
||||||
@ -1141,7 +1130,7 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
|
|
||||||
DEBUGASSERT(data->conn == cf->conn);
|
DEBUGASSERT(data->conn == cf->conn);
|
||||||
nwritten = Curl_send_plain(data, cf->sockindex, buf, len, err);
|
nwritten = Curl_send_plain(data, cf->sockindex, buf, len, err);
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "send(len=%zu) -> %d, err=%d"),
|
DEBUGF(LOG_CF(data, cf, "send(len=%zu) -> %d, err=%d",
|
||||||
len, (int)nwritten, *err));
|
len, (int)nwritten, *err));
|
||||||
return nwritten;
|
return nwritten;
|
||||||
}
|
}
|
||||||
@ -1153,8 +1142,8 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
|
|
||||||
DEBUGASSERT(data->conn == cf->conn);
|
DEBUGASSERT(data->conn == cf->conn);
|
||||||
nread = Curl_recv_plain(data, cf->sockindex, buf, len, err);
|
nread = Curl_recv_plain(data, cf->sockindex, buf, len, err);
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "recv(len=%zu) -> %d, err=%d"),
|
DEBUGF(LOG_CF(data, cf, "recv(len=%zu) -> %d, err=%d", len, (int)nread,
|
||||||
len, (int)nread, *err));
|
*err));
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1263,9 +1252,10 @@ static bool cf_socket_conn_is_alive(struct Curl_cfilter *cf,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct Curl_cftype cft_tcp = {
|
struct Curl_cftype Curl_cft_tcp = {
|
||||||
"TCP",
|
"TCP",
|
||||||
CF_TYPE_IP_CONNECT,
|
CF_TYPE_IP_CONNECT,
|
||||||
|
CURL_LOG_DEFAULT,
|
||||||
cf_socket_destroy,
|
cf_socket_destroy,
|
||||||
cf_tcp_connect,
|
cf_tcp_connect,
|
||||||
cf_socket_close,
|
cf_socket_close,
|
||||||
@ -1300,7 +1290,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
|
|||||||
Curl_sock_assign_addr(&ctx->addr, ai, ctx->transport);
|
Curl_sock_assign_addr(&ctx->addr, ai, ctx->transport);
|
||||||
ctx->sock = CURL_SOCKET_BAD;
|
ctx->sock = CURL_SOCKET_BAD;
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_tcp, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_tcp, ctx);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
*pcf = (!result)? cf : NULL;
|
*pcf = (!result)? cf : NULL;
|
||||||
@ -1342,9 +1332,10 @@ static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct Curl_cftype cft_udp = {
|
struct Curl_cftype Curl_cft_udp = {
|
||||||
"UDP",
|
"UDP",
|
||||||
CF_TYPE_IP_CONNECT,
|
CF_TYPE_IP_CONNECT,
|
||||||
|
CURL_LOG_DEFAULT,
|
||||||
cf_socket_destroy,
|
cf_socket_destroy,
|
||||||
cf_udp_connect,
|
cf_udp_connect,
|
||||||
cf_socket_close,
|
cf_socket_close,
|
||||||
@ -1379,7 +1370,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
|
|||||||
Curl_sock_assign_addr(&ctx->addr, ai, ctx->transport);
|
Curl_sock_assign_addr(&ctx->addr, ai, ctx->transport);
|
||||||
ctx->sock = CURL_SOCKET_BAD;
|
ctx->sock = CURL_SOCKET_BAD;
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_udp, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_udp, ctx);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
*pcf = (!result)? cf : NULL;
|
*pcf = (!result)? cf : NULL;
|
||||||
@ -1392,9 +1383,10 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* this is the TCP filter which can also handle this case */
|
/* this is the TCP filter which can also handle this case */
|
||||||
static const struct Curl_cftype cft_unix = {
|
struct Curl_cftype Curl_cft_unix = {
|
||||||
"UNIX",
|
"UNIX",
|
||||||
CF_TYPE_IP_CONNECT,
|
CF_TYPE_IP_CONNECT,
|
||||||
|
CURL_LOG_DEFAULT,
|
||||||
cf_socket_destroy,
|
cf_socket_destroy,
|
||||||
cf_tcp_connect,
|
cf_tcp_connect,
|
||||||
cf_socket_close,
|
cf_socket_close,
|
||||||
@ -1429,7 +1421,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
|
|||||||
Curl_sock_assign_addr(&ctx->addr, ai, ctx->transport);
|
Curl_sock_assign_addr(&ctx->addr, ai, ctx->transport);
|
||||||
ctx->sock = CURL_SOCKET_BAD;
|
ctx->sock = CURL_SOCKET_BAD;
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_unix, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_unix, ctx);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
*pcf = (!result)? cf : NULL;
|
*pcf = (!result)? cf : NULL;
|
||||||
@ -1455,9 +1447,10 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
|
|||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct Curl_cftype cft_tcp_accept = {
|
struct Curl_cftype Curl_cft_tcp_accept = {
|
||||||
"TCP-ACCEPT",
|
"TCP-ACCEPT",
|
||||||
CF_TYPE_IP_CONNECT,
|
CF_TYPE_IP_CONNECT,
|
||||||
|
CURL_LOG_DEFAULT,
|
||||||
cf_socket_destroy,
|
cf_socket_destroy,
|
||||||
cf_tcp_accept_connect,
|
cf_tcp_accept_connect,
|
||||||
cf_socket_close,
|
cf_socket_close,
|
||||||
@ -1492,7 +1485,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
|
|||||||
ctx->transport = conn->transport;
|
ctx->transport = conn->transport;
|
||||||
ctx->sock = *s;
|
ctx->sock = *s;
|
||||||
ctx->accepted = FALSE;
|
ctx->accepted = FALSE;
|
||||||
result = Curl_cf_create(&cf, &cft_tcp_accept, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_tcp_accept, ctx);
|
||||||
if(result)
|
if(result)
|
||||||
goto out;
|
goto out;
|
||||||
Curl_conn_cf_add(data, conn, sockindex, cf);
|
Curl_conn_cf_add(data, conn, sockindex, cf);
|
||||||
@ -1502,8 +1495,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
|
|||||||
set_local_ip(cf, data);
|
set_local_ip(cf, data);
|
||||||
ctx->active = TRUE;
|
ctx->active = TRUE;
|
||||||
cf->connected = TRUE;
|
cf->connected = TRUE;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "Curl_conn_tcp_listen_set(%d)"),
|
DEBUGF(LOG_CF(data, cf, "Curl_conn_tcp_listen_set(%d)", (int)ctx->sock));
|
||||||
(int)ctx->sock));
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if(result) {
|
if(result) {
|
||||||
@ -1521,7 +1513,7 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
|
|||||||
struct cf_socket_ctx *ctx = NULL;
|
struct cf_socket_ctx *ctx = NULL;
|
||||||
|
|
||||||
cf = conn->cfilter[sockindex];
|
cf = conn->cfilter[sockindex];
|
||||||
if(!cf || cf->cft != &cft_tcp_accept)
|
if(!cf || cf->cft != &Curl_cft_tcp_accept)
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
|
|
||||||
ctx = cf->ctx;
|
ctx = cf->ctx;
|
||||||
@ -1534,16 +1526,17 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
|
|||||||
ctx->active = TRUE;
|
ctx->active = TRUE;
|
||||||
ctx->accepted = TRUE;
|
ctx->accepted = TRUE;
|
||||||
cf->connected = TRUE;
|
cf->connected = TRUE;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "Curl_conn_tcp_accepted_set(%d)"),
|
DEBUGF(LOG_CF(data, cf, "Curl_conn_tcp_accepted_set(%d)", (int)ctx->sock));
|
||||||
(int)ctx->sock));
|
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Curl_cf_is_socket(struct Curl_cfilter *cf)
|
bool Curl_cf_is_socket(struct Curl_cfilter *cf)
|
||||||
{
|
{
|
||||||
return cf && (cf->cft == &cft_tcp || cf->cft == &cft_udp ||
|
return cf && (cf->cft == &Curl_cft_tcp ||
|
||||||
cf->cft == &cft_unix || cf->cft == &cft_tcp_accept);
|
cf->cft == &Curl_cft_udp ||
|
||||||
|
cf->cft == &Curl_cft_unix ||
|
||||||
|
cf->cft == &Curl_cft_tcp_accept);
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
|
CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
|
||||||
|
|||||||
@ -178,4 +178,9 @@ CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
|
|||||||
const char **premote_ip_str,
|
const char **premote_ip_str,
|
||||||
int *premote_port);
|
int *premote_port);
|
||||||
|
|
||||||
|
extern struct Curl_cftype Curl_cft_tcp;
|
||||||
|
extern struct Curl_cftype Curl_cft_udp;
|
||||||
|
extern struct Curl_cftype Curl_cft_unix;
|
||||||
|
extern struct Curl_cftype Curl_cft_tcp_accept;
|
||||||
|
|
||||||
#endif /* HEADER_CURL_CF_SOCKET_H */
|
#endif /* HEADER_CURL_CF_SOCKET_H */
|
||||||
|
|||||||
@ -44,13 +44,6 @@
|
|||||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEBUG_CF 0
|
|
||||||
|
|
||||||
#if DEBUG_CF
|
|
||||||
#define CF_DEBUGF(x) x
|
|
||||||
#else
|
|
||||||
#define CF_DEBUGF(x) do { } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Curl_cf_def_destroy_this(struct Curl_cfilter *cf, struct Curl_easy *data)
|
void Curl_cf_def_destroy_this(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||||
{
|
{
|
||||||
@ -197,7 +190,6 @@ ssize_t Curl_conn_recv(struct Curl_easy *data, int num, char *buf,
|
|||||||
size_t len, CURLcode *code)
|
size_t len, CURLcode *code)
|
||||||
{
|
{
|
||||||
struct Curl_cfilter *cf;
|
struct Curl_cfilter *cf;
|
||||||
ssize_t nread;
|
|
||||||
|
|
||||||
DEBUGASSERT(data);
|
DEBUGASSERT(data);
|
||||||
DEBUGASSERT(data->conn);
|
DEBUGASSERT(data->conn);
|
||||||
@ -206,10 +198,7 @@ ssize_t Curl_conn_recv(struct Curl_easy *data, int num, char *buf,
|
|||||||
cf = cf->next;
|
cf = cf->next;
|
||||||
}
|
}
|
||||||
if(cf) {
|
if(cf) {
|
||||||
nread = cf->cft->do_recv(cf, data, buf, len, code);
|
return cf->cft->do_recv(cf, data, buf, len, code);
|
||||||
CF_DEBUGF(infof(data, "Curl_conn_recv(handle=%p, index=%d)"
|
|
||||||
"-> %ld, err=%d", data, num, nread, *code));
|
|
||||||
return nread;
|
|
||||||
}
|
}
|
||||||
failf(data, CMSGI(data->conn, num, "recv: no filter connected"));
|
failf(data, CMSGI(data->conn, num, "recv: no filter connected"));
|
||||||
*code = CURLE_FAILED_INIT;
|
*code = CURLE_FAILED_INIT;
|
||||||
@ -220,7 +209,6 @@ ssize_t Curl_conn_send(struct Curl_easy *data, int num,
|
|||||||
const void *mem, size_t len, CURLcode *code)
|
const void *mem, size_t len, CURLcode *code)
|
||||||
{
|
{
|
||||||
struct Curl_cfilter *cf;
|
struct Curl_cfilter *cf;
|
||||||
ssize_t nwritten;
|
|
||||||
|
|
||||||
DEBUGASSERT(data);
|
DEBUGASSERT(data);
|
||||||
DEBUGASSERT(data->conn);
|
DEBUGASSERT(data->conn);
|
||||||
@ -229,10 +217,7 @@ ssize_t Curl_conn_send(struct Curl_easy *data, int num,
|
|||||||
cf = cf->next;
|
cf = cf->next;
|
||||||
}
|
}
|
||||||
if(cf) {
|
if(cf) {
|
||||||
nwritten = cf->cft->do_send(cf, data, mem, len, code);
|
return cf->cft->do_send(cf, data, mem, len, code);
|
||||||
CF_DEBUGF(infof(data, "Curl_conn_send(handle=%p, index=%d, len=%ld)"
|
|
||||||
" -> %ld, err=%d", data, num, len, nwritten, *code));
|
|
||||||
return nwritten;
|
|
||||||
}
|
}
|
||||||
failf(data, CMSGI(data->conn, num, "send: no filter connected"));
|
failf(data, CMSGI(data->conn, num, "send: no filter connected"));
|
||||||
DEBUGASSERT(0);
|
DEBUGASSERT(0);
|
||||||
@ -274,7 +259,7 @@ void Curl_conn_cf_add(struct Curl_easy *data,
|
|||||||
cf->conn = conn;
|
cf->conn = conn;
|
||||||
cf->sockindex = index;
|
cf->sockindex = index;
|
||||||
conn->cfilter[index] = cf;
|
conn->cfilter[index] = cf;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "added")));
|
DEBUGF(LOG_CF(data, cf, "added"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
|
void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
|
||||||
@ -381,18 +366,6 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUGBUILD
|
|
||||||
if(result) {
|
|
||||||
CF_DEBUGF(infof(data, DMSGI(data, sockindex, "connect()-> %d, done=%d"),
|
|
||||||
result, *done));
|
|
||||||
}
|
|
||||||
else if(!*done) {
|
|
||||||
while(cf->next && !cf->next->connected)
|
|
||||||
cf = cf->next;
|
|
||||||
CF_DEBUGF(infof(data, DMSGI(data, sockindex, "connect()-> waiting for %s"),
|
|
||||||
cf->cft->name));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -153,7 +153,8 @@ typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf,
|
|||||||
/* A connection filter type, e.g. specific implementation. */
|
/* A connection filter type, e.g. specific implementation. */
|
||||||
struct Curl_cftype {
|
struct Curl_cftype {
|
||||||
const char *name; /* name of the filter type */
|
const char *name; /* name of the filter type */
|
||||||
long flags; /* flags of filter type */
|
int flags; /* flags of filter type */
|
||||||
|
int log_level; /* log level for such filters */
|
||||||
Curl_cft_destroy_this *destroy; /* destroy resources of this cf */
|
Curl_cft_destroy_this *destroy; /* destroy resources of this cf */
|
||||||
Curl_cft_connect *connect; /* establish connection */
|
Curl_cft_connect *connect; /* establish connection */
|
||||||
Curl_cft_close *close; /* close conn */
|
Curl_cft_close *close; /* close conn */
|
||||||
|
|||||||
@ -82,13 +82,6 @@
|
|||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
#define DEBUG_CF 0
|
|
||||||
|
|
||||||
#if DEBUG_CF
|
|
||||||
#define CF_DEBUGF(x) x
|
|
||||||
#else
|
|
||||||
#define CF_DEBUGF(x) do { } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_timeleft() returns the amount of milliseconds left allowed for the
|
* Curl_timeleft() returns the amount of milliseconds left allowed for the
|
||||||
@ -473,7 +466,7 @@ static void baller_initiate(struct Curl_cfilter *cf,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
if(result) {
|
if(result) {
|
||||||
CF_DEBUGF(infof(data, "eyeballer[%s] failed", baller->name));
|
DEBUGF(LOG_CF(data, cf, "%s failed", baller->name));
|
||||||
baller_close(baller, data);
|
baller_close(baller, data);
|
||||||
}
|
}
|
||||||
if(cf_prev)
|
if(cf_prev)
|
||||||
@ -597,8 +590,8 @@ evaluate:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
baller->result = baller_connect(cf, data, baller, &now, connected);
|
baller->result = baller_connect(cf, data, baller, &now, connected);
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] connect -> %d, "
|
DEBUGF(LOG_CF(data, cf, "%s connect -> %d, connected=%d",
|
||||||
"connected=%d"), baller->name, baller->result, *connected));
|
baller->name, baller->result, *connected));
|
||||||
|
|
||||||
if(!baller->result) {
|
if(!baller->result) {
|
||||||
if(*connected) {
|
if(*connected) {
|
||||||
@ -621,12 +614,11 @@ evaluate:
|
|||||||
baller->timeoutms = baller->addr->ai_next == NULL ? allow : allow / 2;
|
baller->timeoutms = baller->addr->ai_next == NULL ? allow : allow / 2;
|
||||||
baller_start_next(cf, data, baller);
|
baller_start_next(cf, data, baller);
|
||||||
if(baller->is_done) {
|
if(baller->is_done) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] done"), baller->name));
|
DEBUGF(LOG_CF(data, cf, "%s done", baller->name));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* next attempt was started */
|
/* next attempt was started */
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] trying next"),
|
DEBUGF(LOG_CF(data, cf, "%s trying next", baller->name));
|
||||||
baller->name));
|
|
||||||
++ongoing;
|
++ongoing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -660,12 +652,10 @@ evaluate:
|
|||||||
Curl_timediff(now, ctx->started) >= baller->delay_ms) {
|
Curl_timediff(now, ctx->started) >= baller->delay_ms) {
|
||||||
baller_start(cf, data, baller);
|
baller_start(cf, data, baller);
|
||||||
if(baller->is_done) {
|
if(baller->is_done) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] done"),
|
DEBUGF(LOG_CF(data, cf, "%s done", baller->name));
|
||||||
baller->name));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] starting"),
|
DEBUGF(LOG_CF(data, cf, "%s starting", baller->name));
|
||||||
baller->name));
|
|
||||||
++ongoing;
|
++ongoing;
|
||||||
++added;
|
++added;
|
||||||
}
|
}
|
||||||
@ -682,12 +672,11 @@ evaluate:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* all ballers have failed to connect. */
|
/* all ballers have failed to connect. */
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "all eyeballers failed")));
|
DEBUGF(LOG_CF(data, cf, "all eyeballers failed"));
|
||||||
result = CURLE_COULDNT_CONNECT;
|
result = CURLE_COULDNT_CONNECT;
|
||||||
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
|
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
|
||||||
struct eyeballer *baller = ctx->baller[i];
|
struct eyeballer *baller = ctx->baller[i];
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] assess started=%d, "
|
DEBUGF(LOG_CF(data, cf, "%s assess started=%d, result=%d",
|
||||||
"result=%d"),
|
|
||||||
baller->name, baller->has_started, baller->result));
|
baller->name, baller->has_started, baller->result));
|
||||||
if(baller && baller->has_started && baller->result) {
|
if(baller && baller->has_started && baller->result) {
|
||||||
result = baller->result;
|
result = baller->result;
|
||||||
@ -926,7 +915,7 @@ static void cf_he_close(struct Curl_cfilter *cf,
|
|||||||
{
|
{
|
||||||
struct cf_he_ctx *ctx = cf->ctx;
|
struct cf_he_ctx *ctx = cf->ctx;
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "close")));
|
DEBUGF(LOG_CF(data, cf, "close"));
|
||||||
cf_he_ctx_clear(cf, data);
|
cf_he_ctx_clear(cf, data);
|
||||||
cf->connected = FALSE;
|
cf->connected = FALSE;
|
||||||
ctx->state = SCFST_INIT;
|
ctx->state = SCFST_INIT;
|
||||||
@ -960,7 +949,7 @@ static void cf_he_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||||||
{
|
{
|
||||||
struct cf_he_ctx *ctx = cf->ctx;
|
struct cf_he_ctx *ctx = cf->ctx;
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "destroy")));
|
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||||
if(ctx) {
|
if(ctx) {
|
||||||
cf_he_ctx_clear(cf, data);
|
cf_he_ctx_clear(cf, data);
|
||||||
}
|
}
|
||||||
@ -968,9 +957,10 @@ static void cf_he_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||||||
Curl_safefree(ctx);
|
Curl_safefree(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct Curl_cftype cft_happy_eyeballs = {
|
struct Curl_cftype Curl_cft_happy_eyeballs = {
|
||||||
"HAPPY-EYEBALLS",
|
"HAPPY-EYEBALLS",
|
||||||
0,
|
0,
|
||||||
|
CURL_LOG_DEFAULT,
|
||||||
cf_he_destroy,
|
cf_he_destroy,
|
||||||
cf_he_connect,
|
cf_he_connect,
|
||||||
cf_he_close,
|
cf_he_close,
|
||||||
@ -1005,7 +995,7 @@ CURLcode Curl_cf_happy_eyeballs_create(struct Curl_cfilter **pcf,
|
|||||||
ctx->cf_create = cf_create;
|
ctx->cf_create = cf_create;
|
||||||
ctx->remotehost = remotehost;
|
ctx->remotehost = remotehost;
|
||||||
|
|
||||||
result = Curl_cf_create(pcf, &cft_happy_eyeballs, ctx);
|
result = Curl_cf_create(pcf, &Curl_cft_happy_eyeballs, ctx);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if(result) {
|
if(result) {
|
||||||
@ -1046,8 +1036,7 @@ static CURLcode cf_he_insert_after(struct Curl_cfilter *cf_at,
|
|||||||
DEBUGASSERT(cf_at);
|
DEBUGASSERT(cf_at);
|
||||||
cf_create = get_cf_create(transport);
|
cf_create = get_cf_create(transport);
|
||||||
if(!cf_create) {
|
if(!cf_create) {
|
||||||
CF_DEBUGF(infof(data, DMSG(data, "unsupported transport type %d"),
|
DEBUGF(LOG_CF(data, cf_at, "unsupported transport type %d", transport));
|
||||||
transport));
|
|
||||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||||
}
|
}
|
||||||
result = Curl_cf_happy_eyeballs_create(&cf, data, cf_at->conn,
|
result = Curl_cf_happy_eyeballs_create(&cf, data, cf_at->conn,
|
||||||
@ -1184,7 +1173,7 @@ static void cf_setup_close(struct Curl_cfilter *cf,
|
|||||||
{
|
{
|
||||||
struct cf_setup_ctx *ctx = cf->ctx;
|
struct cf_setup_ctx *ctx = cf->ctx;
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "close")));
|
DEBUGF(LOG_CF(data, cf, "close"));
|
||||||
cf->connected = FALSE;
|
cf->connected = FALSE;
|
||||||
ctx->state = CF_SETUP_INIT;
|
ctx->state = CF_SETUP_INIT;
|
||||||
|
|
||||||
@ -1199,14 +1188,15 @@ static void cf_setup_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||||||
struct cf_setup_ctx *ctx = cf->ctx;
|
struct cf_setup_ctx *ctx = cf->ctx;
|
||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "destroy")));
|
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||||
Curl_safefree(ctx);
|
Curl_safefree(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct Curl_cftype cft_setup = {
|
struct Curl_cftype Curl_cft_setup = {
|
||||||
"SETUP",
|
"SETUP",
|
||||||
0,
|
0,
|
||||||
|
CURL_LOG_DEFAULT,
|
||||||
cf_setup_destroy,
|
cf_setup_destroy,
|
||||||
cf_setup_connect,
|
cf_setup_connect,
|
||||||
cf_setup_close,
|
cf_setup_close,
|
||||||
@ -1245,7 +1235,7 @@ CURLcode Curl_conn_setup(struct Curl_easy *data,
|
|||||||
ctx->remotehost = remotehost;
|
ctx->remotehost = remotehost;
|
||||||
ctx->ssl_mode = ssl_mode;
|
ctx->ssl_mode = ssl_mode;
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_setup, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_setup, ctx);
|
||||||
if(result)
|
if(result)
|
||||||
goto out;
|
goto out;
|
||||||
ctx = NULL;
|
ctx = NULL;
|
||||||
|
|||||||
@ -132,5 +132,7 @@ CURLcode Curl_conn_setup(struct Curl_easy *data,
|
|||||||
const struct Curl_dns_entry *remotehost,
|
const struct Curl_dns_entry *remotehost,
|
||||||
int ssl_mode);
|
int ssl_mode);
|
||||||
|
|
||||||
|
extern struct Curl_cftype Curl_cft_happy_eyeballs;
|
||||||
|
extern struct Curl_cftype Curl_cft_setup;
|
||||||
|
|
||||||
#endif /* HEADER_CURL_CONNECT_H */
|
#endif /* HEADER_CURL_CONNECT_H */
|
||||||
|
|||||||
219
lib/curl_log.c
Normal file
219
lib/curl_log.c
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 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
|
||||||
|
* are also available at https://curl.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: curl
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "curl_setup.h"
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
#include "curl_log.h"
|
||||||
|
#include "urldata.h"
|
||||||
|
#include "easyif.h"
|
||||||
|
#include "cfilters.h"
|
||||||
|
#include "timeval.h"
|
||||||
|
#include "multiif.h"
|
||||||
|
#include "strcase.h"
|
||||||
|
|
||||||
|
#include "cf-socket.h"
|
||||||
|
#include "connect.h"
|
||||||
|
#include "http2.h"
|
||||||
|
#include "http_proxy.h"
|
||||||
|
#include "socks.h"
|
||||||
|
#include "strtok.h"
|
||||||
|
#include "vtls/vtls.h"
|
||||||
|
#include "vquic/vquic.h"
|
||||||
|
|
||||||
|
/* The last 3 #include files should be in this order */
|
||||||
|
#include "curl_printf.h"
|
||||||
|
#include "curl_memory.h"
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
||||||
|
char *ptr, size_t size)
|
||||||
|
{
|
||||||
|
if(data->set.verbose) {
|
||||||
|
static const char s_infotype[CURLINFO_END][3] = {
|
||||||
|
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
|
||||||
|
if(data->set.fdebug) {
|
||||||
|
bool inCallback = Curl_is_in_callback(data);
|
||||||
|
Curl_set_in_callback(data, true);
|
||||||
|
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
|
||||||
|
Curl_set_in_callback(data, inCallback);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch(type) {
|
||||||
|
case CURLINFO_TEXT:
|
||||||
|
case CURLINFO_HEADER_OUT:
|
||||||
|
case CURLINFO_HEADER_IN:
|
||||||
|
fwrite(s_infotype[type], 2, 1, data->set.err);
|
||||||
|
fwrite(ptr, size, 1, data->set.err);
|
||||||
|
break;
|
||||||
|
default: /* nada */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Curl_failf() is for messages stating why we failed.
|
||||||
|
* The message SHALL NOT include any LF or CR.
|
||||||
|
*/
|
||||||
|
void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(!strchr(fmt, '\n'));
|
||||||
|
if(data->set.verbose || data->set.errorbuffer) {
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
char error[CURL_ERROR_SIZE + 2];
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
|
||||||
|
|
||||||
|
if(data->set.errorbuffer && !data->state.errorbuf) {
|
||||||
|
strcpy(data->set.errorbuffer, error);
|
||||||
|
data->state.errorbuf = TRUE; /* wrote error string */
|
||||||
|
}
|
||||||
|
error[len++] = '\n';
|
||||||
|
error[len] = '\0';
|
||||||
|
Curl_debug(data, CURLINFO_TEXT, error, len);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Curl_infof() is for info message along the way */
|
||||||
|
#define MAXINFO 2048
|
||||||
|
|
||||||
|
void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(!strchr(fmt, '\n'));
|
||||||
|
if(data && data->set.verbose) {
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
char buffer[MAXINFO + 2];
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len = mvsnprintf(buffer, MAXINFO, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
buffer[len++] = '\n';
|
||||||
|
buffer[len] = '\0';
|
||||||
|
Curl_debug(data, CURLINFO_TEXT, buffer, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUGBUILD
|
||||||
|
|
||||||
|
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(cf);
|
||||||
|
if(data && Curl_log_cf_is_debug(cf)) {
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
char buffer[MAXINFO + 2];
|
||||||
|
len = msnprintf(buffer, MAXINFO, "[CONN-%ld%s-%s] ",
|
||||||
|
cf->conn->connection_id, cf->sockindex? "/2" : "",
|
||||||
|
cf->cft->name);
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
buffer[len++] = '\n';
|
||||||
|
buffer[len] = '\0';
|
||||||
|
Curl_debug(data, CURLINFO_TEXT, buffer, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct Curl_cftype *cf_types[] = {
|
||||||
|
&Curl_cft_tcp,
|
||||||
|
&Curl_cft_udp,
|
||||||
|
&Curl_cft_unix,
|
||||||
|
&Curl_cft_tcp_accept,
|
||||||
|
&Curl_cft_happy_eyeballs,
|
||||||
|
&Curl_cft_setup,
|
||||||
|
#ifdef USE_NGHTTP2
|
||||||
|
&Curl_cft_nghttp2,
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SSL
|
||||||
|
&Curl_cft_ssl,
|
||||||
|
&Curl_cft_ssl_proxy,
|
||||||
|
#endif
|
||||||
|
#if !defined(CURL_DISABLE_PROXY)
|
||||||
|
#if !defined(CURL_DISABLE_HTTP)
|
||||||
|
&Curl_cft_http_proxy,
|
||||||
|
#endif /* !CURL_DISABLE_HTTP */
|
||||||
|
&Curl_cft_haproxy,
|
||||||
|
&Curl_cft_socks_proxy,
|
||||||
|
#endif /* !CURL_DISABLE_PROXY */
|
||||||
|
#ifdef ENABLE_QUIC
|
||||||
|
&Curl_cft_http3,
|
||||||
|
#endif
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef ARRAYSIZE
|
||||||
|
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CURLcode Curl_log_init(void)
|
||||||
|
{
|
||||||
|
const char *setting = getenv("CURL_DEBUG");
|
||||||
|
if(setting) {
|
||||||
|
char *token, *tok_buf, *tmp;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
tmp = strdup(setting);
|
||||||
|
if(!tmp)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
token = strtok_r(tmp, ", ", &tok_buf);
|
||||||
|
while(token) {
|
||||||
|
for(i = 0; cf_types[i]; ++i) {
|
||||||
|
if(strcasecompare(token, cf_types[i]->name)) {
|
||||||
|
cf_types[i]->log_level = CURL_LOG_DEBUG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
token = strtok_r(NULL, ", ", &tok_buf);
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
#else /* DEBUGBUILD */
|
||||||
|
|
||||||
|
CURLcode Curl_log_init(void)
|
||||||
|
{
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
|
||||||
|
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
(void)data;
|
||||||
|
(void)cf;
|
||||||
|
(void)fmt;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !DEBUGBUILD */
|
||||||
137
lib/curl_log.h
Normal file
137
lib/curl_log.h
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#ifndef HEADER_CURL_LOG_H
|
||||||
|
#define HEADER_CURL_LOG_H
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 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
|
||||||
|
* are also available at https://curl.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: curl
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
struct Curl_easy;
|
||||||
|
struct Curl_cfilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init logging, return != 0 on failure.
|
||||||
|
*/
|
||||||
|
CURLcode Curl_log_init(void);
|
||||||
|
|
||||||
|
|
||||||
|
void Curl_infof(struct Curl_easy *, const char *fmt, ...);
|
||||||
|
void Curl_failf(struct Curl_easy *, const char *fmt, ...);
|
||||||
|
|
||||||
|
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||||
|
|
||||||
|
#if defined(HAVE_VARIADIC_MACROS_C99)
|
||||||
|
#define infof(...) Curl_nop_stmt
|
||||||
|
#elif defined(HAVE_VARIADIC_MACROS_GCC)
|
||||||
|
#define infof(x...) Curl_nop_stmt
|
||||||
|
#else
|
||||||
|
#error "missing VARIADIC macro define, fix and rebuild!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* CURL_DISABLE_VERBOSE_STRINGS */
|
||||||
|
|
||||||
|
#define infof Curl_infof
|
||||||
|
|
||||||
|
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
|
||||||
|
|
||||||
|
#define failf Curl_failf
|
||||||
|
|
||||||
|
|
||||||
|
#define CURL_LOG_DEFAULT 0
|
||||||
|
#define CURL_LOG_DEBUG 1
|
||||||
|
#define CURL_LOG_TRACE 2
|
||||||
|
|
||||||
|
|
||||||
|
/* the function used to output verbose information */
|
||||||
|
void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
||||||
|
char *ptr, size_t size);
|
||||||
|
|
||||||
|
#ifdef DEBUGBUILD
|
||||||
|
|
||||||
|
/* explainer: we have some mix configuration and werror settings
|
||||||
|
* that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
|
||||||
|
* on gnuc and some other compiler. Need to treat carefully.
|
||||||
|
*/
|
||||||
|
#if defined(HAVE_VARIADIC_MACROS_C99) && \
|
||||||
|
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||||
|
|
||||||
|
#define LOG_CF(data, cf, ...) \
|
||||||
|
do { if(Curl_log_cf_is_debug(cf)) \
|
||||||
|
Curl_log_cf_debug(data, cf, __VA_ARGS__); } while(0)
|
||||||
|
#else
|
||||||
|
#define LOG_CF Curl_log_cf_debug
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||||
|
#if defined(__GNUC__) && !defined(printf) && \
|
||||||
|
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||||
|
const char *fmt, ...)
|
||||||
|
__attribute__((format(printf, 3, 4)));
|
||||||
|
#else
|
||||||
|
const char *fmt, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Curl_log_cf_is_debug(cf) \
|
||||||
|
((cf) && (cf)->cft->log_level >= CURL_LOG_DEBUG)
|
||||||
|
|
||||||
|
#else /* !DEBUGBUILD */
|
||||||
|
|
||||||
|
#if defined(HAVE_VARIADIC_MACROS_C99) && \
|
||||||
|
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||||
|
#define LOG_CF(...) Curl_nop_stmt
|
||||||
|
#define Curl_log_cf_debug(...) Curl_nop_stmt
|
||||||
|
#elif defined(HAVE_VARIADIC_MACROS_GCC) && \
|
||||||
|
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||||
|
#define LOG_CF(x...) Curl_nop_stmt
|
||||||
|
#define Curl_log_cf_debug(x...) Curl_nop_stmt
|
||||||
|
#else
|
||||||
|
#define LOG_CF Curl_log_cf_debug
|
||||||
|
/* without c99, we seem unable to completely define away this function. */
|
||||||
|
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||||
|
const char *fmt, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Curl_log_cf_is_debug(x) ((void)(x), FALSE)
|
||||||
|
|
||||||
|
#endif /* !DEBUGBUILD */
|
||||||
|
|
||||||
|
#define LOG_CF_IS_DEBUG(x) Curl_log_cf_is_debug(x)
|
||||||
|
|
||||||
|
/* Macros intended for DEBUGF logging, use like:
|
||||||
|
* DEBUGF(infof(data, CFMSG(cf, "this filter %s rocks"), "very much"));
|
||||||
|
* and it will output:
|
||||||
|
* [CONN-1-0][CF-SSL] this filter very much rocks
|
||||||
|
* on connection #1 with sockindex 0 for filter of type "SSL". */
|
||||||
|
#define DMSG(d,msg) \
|
||||||
|
"[CONN-%ld] "msg, (d)->conn->connection_id
|
||||||
|
#define DMSGI(d,i,msg) \
|
||||||
|
"[CONN-%ld-%d] "msg, (d)->conn->connection_id, (i)
|
||||||
|
#define CMSG(c,msg) \
|
||||||
|
"[CONN-%ld] "msg, (c)->connection_id
|
||||||
|
#define CMSGI(c,i,msg) \
|
||||||
|
"[CONN-%ld-%d] "msg, (c)->connection_id, (i)
|
||||||
|
#define CFMSG(cf,msg) \
|
||||||
|
"[CONN-%ld-%d][CF-%s] "msg, (cf)->conn->connection_id, \
|
||||||
|
(cf)->sockindex, (cf)->cft->name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HEADER_CURL_LOG_H */
|
||||||
@ -165,6 +165,11 @@ static CURLcode global_init(long flags, bool memoryfuncs)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Curl_log_init()) {
|
||||||
|
DEBUGF(fprintf(stderr, "Error: Curl_log_init failed\n"));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if(!Curl_ssl_init()) {
|
if(!Curl_ssl_init()) {
|
||||||
DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
|
DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|||||||
47
lib/http2.c
47
lib/http2.c
@ -64,6 +64,7 @@
|
|||||||
|
|
||||||
#define HTTP2_HUGE_WINDOW_SIZE (32 * 1024 * 1024) /* 32 MB */
|
#define HTTP2_HUGE_WINDOW_SIZE (32 * 1024 * 1024) /* 32 MB */
|
||||||
|
|
||||||
|
|
||||||
#define DEBUG_HTTP2
|
#define DEBUG_HTTP2
|
||||||
#ifdef DEBUG_HTTP2
|
#ifdef DEBUG_HTTP2
|
||||||
#define H2BUGF(x) x
|
#define H2BUGF(x) x
|
||||||
@ -776,19 +777,19 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
switch(frame->hd.type) {
|
switch(frame->hd.type) {
|
||||||
case NGHTTP2_SETTINGS: {
|
case NGHTTP2_SETTINGS: {
|
||||||
uint32_t max_conn = ctx->max_concurrent_streams;
|
uint32_t max_conn = ctx->max_concurrent_streams;
|
||||||
H2BUGF(infof(data, CFMSG(cf, "recv frame SETTINGS")));
|
DEBUGF(LOG_CF(data, cf, "recv frame SETTINGS"));
|
||||||
ctx->max_concurrent_streams = nghttp2_session_get_remote_settings(
|
ctx->max_concurrent_streams = nghttp2_session_get_remote_settings(
|
||||||
session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
|
session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
|
||||||
ctx->enable_push = nghttp2_session_get_remote_settings(
|
ctx->enable_push = nghttp2_session_get_remote_settings(
|
||||||
session, NGHTTP2_SETTINGS_ENABLE_PUSH);
|
session, NGHTTP2_SETTINGS_ENABLE_PUSH);
|
||||||
H2BUGF(infof(data, CFMSG(cf, "MAX_CONCURRENT_STREAMS == %d"),
|
DEBUGF(LOG_CF(data, cf, "MAX_CONCURRENT_STREAMS == %d",
|
||||||
ctx->max_concurrent_streams));
|
ctx->max_concurrent_streams));
|
||||||
H2BUGF(infof(data, CFMSG(cf, "ENABLE_PUSH == %s"),
|
DEBUGF(LOG_CF(data, cf, "ENABLE_PUSH == %s",
|
||||||
ctx->enable_push?"TRUE":"false"));
|
ctx->enable_push ? "TRUE" : "false"));
|
||||||
if(data && max_conn != ctx->max_concurrent_streams) {
|
if(data && max_conn != ctx->max_concurrent_streams) {
|
||||||
/* only signal change if the value actually changed */
|
/* only signal change if the value actually changed */
|
||||||
infof(data, CFMSG(cf, "MAX_CONCURRENT_STREAMS now %u"),
|
DEBUGF(LOG_CF(data, cf, "MAX_CONCURRENT_STREAMS now %u",
|
||||||
ctx->max_concurrent_streams);
|
ctx->max_concurrent_streams));
|
||||||
multi_connchanged(data->multi);
|
multi_connchanged(data->multi);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -801,31 +802,30 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_WINDOW_UPDATE:
|
case NGHTTP2_WINDOW_UPDATE:
|
||||||
H2BUGF(infof(data, CFMSG(cf, "recv frame WINDOW_UPDATE")));
|
DEBUGF(LOG_CF(data, cf, "recv frame WINDOW_UPDATE"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
H2BUGF(infof(data, CFMSG(cf, "recv frame %x on 0"), frame->hd.type));
|
DEBUGF(LOG_CF(data, cf, "recv frame %x on 0", frame->hd.type));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
|
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
|
||||||
if(!data_s) {
|
if(!data_s) {
|
||||||
H2BUGF(infof(data, CFMSG(cf, "No Curl_easy associated with stream: %u"),
|
DEBUGF(LOG_CF(data, cf, "No Curl_easy associated with stream: %u",
|
||||||
stream_id));
|
stream_id));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream = data_s->req.p.http;
|
stream = data_s->req.p.http;
|
||||||
if(!stream) {
|
if(!stream) {
|
||||||
H2BUGF(infof(data_s, CFMSG(cf, "No proto pointer for stream: %u"),
|
DEBUGF(LOG_CF(data_s, cf, "No proto pointer for stream: %u", stream_id));
|
||||||
stream_id));
|
|
||||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(frame->hd.type) {
|
switch(frame->hd.type) {
|
||||||
case NGHTTP2_DATA:
|
case NGHTTP2_DATA:
|
||||||
/* If body started on this stream, then receiving DATA is illegal. */
|
/* If body started on this stream, then receiving DATA is illegal. */
|
||||||
H2BUGF(infof(data_s, CFMSG(cf, "recv frame DATA stream %u"), stream_id));
|
DEBUGF(LOG_CF(data_s, cf, "recv frame DATA stream %u", stream_id));
|
||||||
if(!stream->bodystarted) {
|
if(!stream->bodystarted) {
|
||||||
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
stream_id, NGHTTP2_PROTOCOL_ERROR);
|
stream_id, NGHTTP2_PROTOCOL_ERROR);
|
||||||
@ -836,8 +836,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_HEADERS:
|
case NGHTTP2_HEADERS:
|
||||||
H2BUGF(infof(data_s, CFMSG(cf, "recv frame HEADERS stream %u"),
|
DEBUGF(LOG_CF(data_s, cf, "recv frame HEADERS stream %u", stream_id));
|
||||||
stream_id));
|
|
||||||
if(stream->bodystarted) {
|
if(stream->bodystarted) {
|
||||||
/* Only valid HEADERS after body started is trailer HEADERS. We
|
/* Only valid HEADERS after body started is trailer HEADERS. We
|
||||||
buffer them in on_header callback. */
|
buffer them in on_header callback. */
|
||||||
@ -871,8 +870,8 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
stream->nread_header_recvbuf += ncopy;
|
stream->nread_header_recvbuf += ncopy;
|
||||||
|
|
||||||
DEBUGASSERT(stream->mem);
|
DEBUGASSERT(stream->mem);
|
||||||
H2BUGF(infof(data_s, CFMSG(cf, "%zu header bytes, stream %u at %p"),
|
DEBUGF(LOG_CF(data_s, cf, "%zu header bytes, stream %u at %p",
|
||||||
ncopy, stream_id, stream->mem));
|
ncopy, stream_id, (void *)stream->mem));
|
||||||
|
|
||||||
stream->len -= ncopy;
|
stream->len -= ncopy;
|
||||||
stream->memlen += ncopy;
|
stream->memlen += ncopy;
|
||||||
@ -883,8 +882,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_PUSH_PROMISE:
|
case NGHTTP2_PUSH_PROMISE:
|
||||||
H2BUGF(infof(data_s, CFMSG(cf, "recv frame PUSH_PROMISE stream %u"),
|
DEBUGF(LOG_CF(data_s, cf, "recv frame PUSH_PROMISE stream %u", stream_id));
|
||||||
stream_id));
|
|
||||||
rv = push_promise(cf, data_s, &frame->push_promise);
|
rv = push_promise(cf, data_s, &frame->push_promise);
|
||||||
if(rv) { /* deny! */
|
if(rv) { /* deny! */
|
||||||
int h2;
|
int h2;
|
||||||
@ -895,13 +893,13 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
if(nghttp2_is_fatal(h2))
|
if(nghttp2_is_fatal(h2))
|
||||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
else if(rv == CURL_PUSH_ERROROUT) {
|
else if(rv == CURL_PUSH_ERROROUT) {
|
||||||
DEBUGF(infof(data_s, CFMSG(cf, "Fail the parent stream (too)")));
|
DEBUGF(LOG_CF(data_s, cf, "Fail the parent stream (too)"));
|
||||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
H2BUGF(infof(data_s, CFMSG(cf, "recv frame %x for stream %u"),
|
DEBUGF(LOG_CF(data_s, cf, "recv frame %x for stream %u",
|
||||||
frame->hd.type, stream_id));
|
frame->hd.type, stream_id));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2248,9 +2246,10 @@ static CURLcode h2_cf_query(struct Curl_cfilter *cf,
|
|||||||
CURLE_UNKNOWN_OPTION;
|
CURLE_UNKNOWN_OPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct Curl_cftype cft_nghttp2 = {
|
struct Curl_cftype Curl_cft_nghttp2 = {
|
||||||
"NGHTTP2",
|
"NGHTTP2",
|
||||||
CF_TYPE_MULTIPLEX,
|
CF_TYPE_MULTIPLEX,
|
||||||
|
CURL_LOG_DEFAULT,
|
||||||
h2_cf_destroy,
|
h2_cf_destroy,
|
||||||
h2_cf_connect,
|
h2_cf_connect,
|
||||||
h2_cf_close,
|
h2_cf_close,
|
||||||
@ -2279,7 +2278,7 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf,
|
|||||||
if(!ctx)
|
if(!ctx)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_nghttp2, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_nghttp2, ctx);
|
||||||
if(result)
|
if(result)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -2301,7 +2300,7 @@ bool Curl_conn_is_http2(const struct Curl_easy *data,
|
|||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
for(; cf; cf = cf->next) {
|
for(; cf; cf = cf->next) {
|
||||||
if(cf->cft == &cft_nghttp2)
|
if(cf->cft == &Curl_cft_nghttp2)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
|
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -2343,7 +2342,7 @@ CURLcode Curl_http2_switch(struct Curl_easy *data,
|
|||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
DEBUGASSERT(cf->cft == &cft_nghttp2);
|
DEBUGASSERT(cf->cft == &Curl_cft_nghttp2);
|
||||||
ctx = cf->ctx;
|
ctx = cf->ctx;
|
||||||
|
|
||||||
result = h2_cf_ctx_init(cf, data, (data->req.upgr101 == UPGR101_RECEIVED));
|
result = h2_cf_ctx_init(cf, data, (data->req.upgr101 == UPGR101_RECEIVED));
|
||||||
|
|||||||
@ -58,6 +58,8 @@ CURLcode Curl_http2_switch(struct Curl_easy *data,
|
|||||||
struct connectdata *conn, int sockindex,
|
struct connectdata *conn, int sockindex,
|
||||||
const char *ptr, size_t nread);
|
const char *ptr, size_t nread);
|
||||||
|
|
||||||
|
extern struct Curl_cftype Curl_cft_nghttp2;
|
||||||
|
|
||||||
#else /* USE_NGHTTP2 */
|
#else /* USE_NGHTTP2 */
|
||||||
|
|
||||||
#define Curl_conn_is_http2(a,b,c) FALSE
|
#define Curl_conn_is_http2(a,b,c) FALSE
|
||||||
|
|||||||
@ -50,14 +50,6 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
|
||||||
#define DEBUG_CF 0
|
|
||||||
|
|
||||||
#if DEBUG_CF
|
|
||||||
#define CF_DEBUGF(x) x
|
|
||||||
#else
|
|
||||||
#define CF_DEBUGF(x) do { } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(CURL_DISABLE_HTTP)
|
#if !defined(CURL_DISABLE_HTTP)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -182,35 +174,35 @@ static void tunnel_go_state(struct Curl_cfilter *cf,
|
|||||||
/* entering this one */
|
/* entering this one */
|
||||||
switch(new_state) {
|
switch(new_state) {
|
||||||
case TUNNEL_INIT:
|
case TUNNEL_INIT:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "new tunnel state 'init'")));
|
DEBUGF(LOG_CF(data, cf, "new tunnel state 'init'"));
|
||||||
tunnel_reinit(ts, cf->conn, data);
|
tunnel_reinit(ts, cf->conn, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUNNEL_CONNECT:
|
case TUNNEL_CONNECT:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "new tunnel state 'connect'")));
|
DEBUGF(LOG_CF(data, cf, "new tunnel state 'connect'"));
|
||||||
ts->tunnel_state = TUNNEL_CONNECT;
|
ts->tunnel_state = TUNNEL_CONNECT;
|
||||||
ts->keepon = KEEPON_CONNECT;
|
ts->keepon = KEEPON_CONNECT;
|
||||||
Curl_dyn_reset(&ts->rcvbuf);
|
Curl_dyn_reset(&ts->rcvbuf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUNNEL_RECEIVE:
|
case TUNNEL_RECEIVE:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "new tunnel state 'receive'")));
|
DEBUGF(LOG_CF(data, cf, "new tunnel state 'receive'"));
|
||||||
ts->tunnel_state = TUNNEL_RECEIVE;
|
ts->tunnel_state = TUNNEL_RECEIVE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUNNEL_RESPONSE:
|
case TUNNEL_RESPONSE:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "new tunnel state 'response'")));
|
DEBUGF(LOG_CF(data, cf, "new tunnel state 'response'"));
|
||||||
ts->tunnel_state = TUNNEL_RESPONSE;
|
ts->tunnel_state = TUNNEL_RESPONSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUNNEL_ESTABLISHED:
|
case TUNNEL_ESTABLISHED:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "new tunnel state 'established'")));
|
DEBUGF(LOG_CF(data, cf, "new tunnel state 'established'"));
|
||||||
infof(data, "CONNECT phase completed");
|
infof(data, "CONNECT phase completed");
|
||||||
data->state.authproxy.done = TRUE;
|
data->state.authproxy.done = TRUE;
|
||||||
data->state.authproxy.multipass = FALSE;
|
data->state.authproxy.multipass = FALSE;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case TUNNEL_FAILED:
|
case TUNNEL_FAILED:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "new tunnel state 'failed'")));
|
DEBUGF(LOG_CF(data, cf, "new tunnel state 'failed'"));
|
||||||
ts->tunnel_state = new_state;
|
ts->tunnel_state = new_state;
|
||||||
Curl_dyn_reset(&ts->rcvbuf);
|
Curl_dyn_reset(&ts->rcvbuf);
|
||||||
Curl_dyn_reset(&ts->req);
|
Curl_dyn_reset(&ts->req);
|
||||||
@ -403,13 +395,15 @@ out:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode on_resp_header(struct Curl_easy *data,
|
static CURLcode on_resp_header(struct Curl_cfilter *cf,
|
||||||
|
struct Curl_easy *data,
|
||||||
struct tunnel_state *ts,
|
struct tunnel_state *ts,
|
||||||
const char *header)
|
const char *header)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct SingleRequest *k = &data->req;
|
struct SingleRequest *k = &data->req;
|
||||||
int subversion = 0;
|
int subversion = 0;
|
||||||
|
(void)cf;
|
||||||
|
|
||||||
if((checkprefix("WWW-Authenticate:", header) &&
|
if((checkprefix("WWW-Authenticate:", header) &&
|
||||||
(401 == k->httpcode)) ||
|
(401 == k->httpcode)) ||
|
||||||
@ -421,8 +415,7 @@ static CURLcode on_resp_header(struct Curl_easy *data,
|
|||||||
if(!auth)
|
if(!auth)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, "CONNECT: fwd auth header '%s'",
|
DEBUGF(LOG_CF(data, cf, "CONNECT: fwd auth header '%s'", header));
|
||||||
header));
|
|
||||||
result = Curl_http_input_auth(data, proxy, auth);
|
result = Curl_http_input_auth(data, proxy, auth);
|
||||||
|
|
||||||
free(auth);
|
free(auth);
|
||||||
@ -476,14 +469,14 @@ static CURLcode on_resp_header(struct Curl_easy *data,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode recv_CONNECT_resp(struct Curl_easy *data,
|
static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
||||||
struct connectdata *conn,
|
struct Curl_easy *data,
|
||||||
struct tunnel_state *ts,
|
struct tunnel_state *ts,
|
||||||
bool *done)
|
bool *done)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct SingleRequest *k = &data->req;
|
struct SingleRequest *k = &data->req;
|
||||||
curl_socket_t tunnelsocket = conn->sock[ts->sockindex];
|
curl_socket_t tunnelsocket = cf->conn->sock[ts->sockindex];
|
||||||
char *linep;
|
char *linep;
|
||||||
size_t perline;
|
size_t perline;
|
||||||
int error;
|
int error;
|
||||||
@ -639,7 +632,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_easy *data,
|
|||||||
/* without content-length or chunked encoding, we
|
/* without content-length or chunked encoding, we
|
||||||
can't keep the connection alive since the close is
|
can't keep the connection alive since the close is
|
||||||
the end signal so we bail out at once instead */
|
the end signal so we bail out at once instead */
|
||||||
CF_DEBUGF(infof(data, "CONNECT: no content-length or chunked"));
|
DEBUGF(LOG_CF(data, cf, "CONNECT: no content-length or chunked"));
|
||||||
ts->keepon = KEEPON_DONE;
|
ts->keepon = KEEPON_DONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -652,7 +645,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_easy *data,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = on_resp_header(data, ts, linep);
|
result = on_resp_header(cf, data, ts, linep);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -919,8 +912,8 @@ error:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode recv_CONNECT_resp(struct Curl_easy *data,
|
static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
||||||
struct connectdata *conn,
|
struct Curl_easy *data,
|
||||||
struct tunnel_state *ts,
|
struct tunnel_state *ts,
|
||||||
bool *done)
|
bool *done)
|
||||||
{
|
{
|
||||||
@ -930,7 +923,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_easy *data,
|
|||||||
|
|
||||||
(void)ts;
|
(void)ts;
|
||||||
*done = FALSE;
|
*done = FALSE;
|
||||||
result = Curl_hyper_stream(data, conn, &didwhat, done,
|
result = Curl_hyper_stream(data, cf->conn, &didwhat, done,
|
||||||
CURL_CSELECT_IN | CURL_CSELECT_OUT);
|
CURL_CSELECT_IN | CURL_CSELECT_OUT);
|
||||||
if(result || !*done)
|
if(result || !*done)
|
||||||
return result;
|
return result;
|
||||||
@ -977,7 +970,7 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
|
|||||||
switch(ts->tunnel_state) {
|
switch(ts->tunnel_state) {
|
||||||
case TUNNEL_INIT:
|
case TUNNEL_INIT:
|
||||||
/* Prepare the CONNECT request and make a first attempt to send. */
|
/* Prepare the CONNECT request and make a first attempt to send. */
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "CONNECT start")));
|
DEBUGF(LOG_CF(data, cf, "CONNECT start"));
|
||||||
result = start_CONNECT(data, cf->conn, ts);
|
result = start_CONNECT(data, cf->conn, ts);
|
||||||
if(result)
|
if(result)
|
||||||
goto out;
|
goto out;
|
||||||
@ -986,7 +979,7 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
|
|||||||
|
|
||||||
case TUNNEL_CONNECT:
|
case TUNNEL_CONNECT:
|
||||||
/* see that the request is completely sent */
|
/* see that the request is completely sent */
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "CONNECT send")));
|
DEBUGF(LOG_CF(data, cf, "CONNECT send"));
|
||||||
result = send_CONNECT(data, cf->conn, ts, &done);
|
result = send_CONNECT(data, cf->conn, ts, &done);
|
||||||
if(result || !done)
|
if(result || !done)
|
||||||
goto out;
|
goto out;
|
||||||
@ -995,8 +988,8 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
|
|||||||
|
|
||||||
case TUNNEL_RECEIVE:
|
case TUNNEL_RECEIVE:
|
||||||
/* read what is there */
|
/* read what is there */
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "CONNECT receive")));
|
DEBUGF(LOG_CF(data, cf, "CONNECT receive"));
|
||||||
result = recv_CONNECT_resp(data, cf->conn, ts, &done);
|
result = recv_CONNECT_resp(cf, data, ts, &done);
|
||||||
if(Curl_pgrsUpdate(data)) {
|
if(Curl_pgrsUpdate(data)) {
|
||||||
result = CURLE_ABORTED_BY_CALLBACK;
|
result = CURLE_ABORTED_BY_CALLBACK;
|
||||||
goto out;
|
goto out;
|
||||||
@ -1009,7 +1002,7 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
|
|||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
case TUNNEL_RESPONSE:
|
case TUNNEL_RESPONSE:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "CONNECT response")));
|
DEBUGF(LOG_CF(data, cf, "CONNECT response"));
|
||||||
if(data->req.newurl) {
|
if(data->req.newurl) {
|
||||||
/* not the "final" response, we need to do a follow up request.
|
/* not the "final" response, we need to do a follow up request.
|
||||||
* If the other side indicated a connection close, or if someone
|
* If the other side indicated a connection close, or if someone
|
||||||
@ -1021,7 +1014,7 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
|
|||||||
* reset our tunnel state. To avoid recursion, we return
|
* reset our tunnel state. To avoid recursion, we return
|
||||||
* and expect to be called again.
|
* and expect to be called again.
|
||||||
*/
|
*/
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "CONNECT need to close+open")));
|
DEBUGF(LOG_CF(data, cf, "CONNECT need to close+open"));
|
||||||
infof(data, "Connect me again please");
|
infof(data, "Connect me again please");
|
||||||
Curl_conn_cf_close(cf, data);
|
Curl_conn_cf_close(cf, data);
|
||||||
connkeep(conn, "HTTP proxy CONNECT");
|
connkeep(conn, "HTTP proxy CONNECT");
|
||||||
@ -1076,12 +1069,12 @@ static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "connect")));
|
DEBUGF(LOG_CF(data, cf, "connect"));
|
||||||
result = cf->next->cft->connect(cf->next, data, blocking, done);
|
result = cf->next->cft->connect(cf->next, data, blocking, done);
|
||||||
if(result || !*done)
|
if(result || !*done)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "subchain is connected")));
|
DEBUGF(LOG_CF(data, cf, "subchain is connected"));
|
||||||
/* TODO: can we do blocking? */
|
/* TODO: can we do blocking? */
|
||||||
/* We want "seamless" operations through HTTP proxy tunnel */
|
/* We want "seamless" operations through HTTP proxy tunnel */
|
||||||
|
|
||||||
@ -1159,7 +1152,7 @@ static int http_proxy_cf_get_select_socks(struct Curl_cfilter *cf,
|
|||||||
static void http_proxy_cf_destroy(struct Curl_cfilter *cf,
|
static void http_proxy_cf_destroy(struct Curl_cfilter *cf,
|
||||||
struct Curl_easy *data)
|
struct Curl_easy *data)
|
||||||
{
|
{
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "destroy")));
|
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||||
tunnel_free(cf, data);
|
tunnel_free(cf, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1167,7 +1160,7 @@ static void http_proxy_cf_close(struct Curl_cfilter *cf,
|
|||||||
struct Curl_easy *data)
|
struct Curl_easy *data)
|
||||||
{
|
{
|
||||||
DEBUGASSERT(cf->next);
|
DEBUGASSERT(cf->next);
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "close")));
|
DEBUGF(LOG_CF(data, cf, "close"));
|
||||||
cf->connected = FALSE;
|
cf->connected = FALSE;
|
||||||
cf->next->cft->close(cf->next, data);
|
cf->next->cft->close(cf->next, data);
|
||||||
if(cf->ctx) {
|
if(cf->ctx) {
|
||||||
@ -1176,9 +1169,10 @@ static void http_proxy_cf_close(struct Curl_cfilter *cf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct Curl_cftype cft_http_proxy = {
|
struct Curl_cftype Curl_cft_http_proxy = {
|
||||||
"HTTP-PROXY",
|
"HTTP-PROXY",
|
||||||
CF_TYPE_IP_CONNECT,
|
CF_TYPE_IP_CONNECT,
|
||||||
|
0,
|
||||||
http_proxy_cf_destroy,
|
http_proxy_cf_destroy,
|
||||||
http_proxy_cf_connect,
|
http_proxy_cf_connect,
|
||||||
http_proxy_cf_close,
|
http_proxy_cf_close,
|
||||||
@ -1200,7 +1194,7 @@ CURLcode Curl_conn_http_proxy_add(struct Curl_easy *data,
|
|||||||
struct Curl_cfilter *cf;
|
struct Curl_cfilter *cf;
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_http_proxy, NULL);
|
result = Curl_cf_create(&cf, &Curl_cft_http_proxy, NULL);
|
||||||
if(!result)
|
if(!result)
|
||||||
Curl_conn_cf_add(data, conn, sockindex, cf);
|
Curl_conn_cf_add(data, conn, sockindex, cf);
|
||||||
return result;
|
return result;
|
||||||
@ -1213,7 +1207,7 @@ CURLcode Curl_cf_http_proxy_insert_after(struct Curl_cfilter *cf_at,
|
|||||||
CURLcode result;
|
CURLcode result;
|
||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
result = Curl_cf_create(&cf, &cft_http_proxy, NULL);
|
result = Curl_cf_create(&cf, &Curl_cft_http_proxy, NULL);
|
||||||
if(!result)
|
if(!result)
|
||||||
Curl_conn_cf_insert_after(cf_at, cf);
|
Curl_conn_cf_insert_after(cf_at, cf);
|
||||||
return result;
|
return result;
|
||||||
@ -1335,14 +1329,14 @@ static void cf_haproxy_destroy(struct Curl_cfilter *cf,
|
|||||||
struct Curl_easy *data)
|
struct Curl_easy *data)
|
||||||
{
|
{
|
||||||
(void)data;
|
(void)data;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "destroy")));
|
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||||
cf_haproxy_ctx_free(cf->ctx);
|
cf_haproxy_ctx_free(cf->ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cf_haproxy_close(struct Curl_cfilter *cf,
|
static void cf_haproxy_close(struct Curl_cfilter *cf,
|
||||||
struct Curl_easy *data)
|
struct Curl_easy *data)
|
||||||
{
|
{
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "close")));
|
DEBUGF(LOG_CF(data, cf, "close"));
|
||||||
cf->connected = FALSE;
|
cf->connected = FALSE;
|
||||||
cf_haproxy_ctx_reset(cf->ctx);
|
cf_haproxy_ctx_reset(cf->ctx);
|
||||||
if(cf->next)
|
if(cf->next)
|
||||||
@ -1368,9 +1362,10 @@ static int cf_haproxy_get_select_socks(struct Curl_cfilter *cf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct Curl_cftype cft_haproxy = {
|
struct Curl_cftype Curl_cft_haproxy = {
|
||||||
"HAPROXY",
|
"HAPROXY",
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
cf_haproxy_destroy,
|
cf_haproxy_destroy,
|
||||||
cf_haproxy_connect,
|
cf_haproxy_connect,
|
||||||
cf_haproxy_close,
|
cf_haproxy_close,
|
||||||
@ -1401,7 +1396,7 @@ static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
|
|||||||
ctx->state = HAPROXY_INIT;
|
ctx->state = HAPROXY_INIT;
|
||||||
Curl_dyn_init(&ctx->data_out, DYN_HAXPROXY);
|
Curl_dyn_init(&ctx->data_out, DYN_HAXPROXY);
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_haproxy, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_haproxy, ctx);
|
||||||
if(result)
|
if(result)
|
||||||
goto out;
|
goto out;
|
||||||
ctx = NULL;
|
ctx = NULL;
|
||||||
|
|||||||
@ -40,6 +40,8 @@ CURLcode Curl_conn_http_proxy_add(struct Curl_easy *data,
|
|||||||
CURLcode Curl_cf_http_proxy_insert_after(struct Curl_cfilter *cf_at,
|
CURLcode Curl_cf_http_proxy_insert_after(struct Curl_cfilter *cf_at,
|
||||||
struct Curl_easy *data);
|
struct Curl_easy *data);
|
||||||
|
|
||||||
|
extern struct Curl_cftype Curl_cft_http_proxy;
|
||||||
|
|
||||||
#endif /* !CURL_DISABLE_HTTP */
|
#endif /* !CURL_DISABLE_HTTP */
|
||||||
|
|
||||||
CURLcode Curl_conn_haproxy_add(struct Curl_easy *data,
|
CURLcode Curl_conn_haproxy_add(struct Curl_easy *data,
|
||||||
@ -48,6 +50,9 @@ CURLcode Curl_conn_haproxy_add(struct Curl_easy *data,
|
|||||||
|
|
||||||
CURLcode Curl_cf_haproxy_insert_after(struct Curl_cfilter *cf_at,
|
CURLcode Curl_cf_haproxy_insert_after(struct Curl_cfilter *cf_at,
|
||||||
struct Curl_easy *data);
|
struct Curl_easy *data);
|
||||||
|
|
||||||
|
extern struct Curl_cftype Curl_cft_haproxy;
|
||||||
|
|
||||||
#endif /* !CURL_DISABLE_PROXY */
|
#endif /* !CURL_DISABLE_PROXY */
|
||||||
|
|
||||||
#endif /* HEADER_CURL_HTTP_PROXY_H */
|
#endif /* HEADER_CURL_HTTP_PROXY_H */
|
||||||
|
|||||||
71
lib/sendf.c
71
lib/sendf.c
@ -237,50 +237,6 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
|
|||||||
#define get_pre_recved(c,n,b,l) 0
|
#define get_pre_recved(c,n,b,l) 0
|
||||||
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
|
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
|
||||||
|
|
||||||
/* Curl_infof() is for info message along the way */
|
|
||||||
#define MAXINFO 2048
|
|
||||||
|
|
||||||
void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
DEBUGASSERT(!strchr(fmt, '\n'));
|
|
||||||
if(data && data->set.verbose) {
|
|
||||||
va_list ap;
|
|
||||||
int len;
|
|
||||||
char buffer[MAXINFO + 2];
|
|
||||||
va_start(ap, fmt);
|
|
||||||
len = mvsnprintf(buffer, MAXINFO, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
buffer[len++] = '\n';
|
|
||||||
buffer[len] = '\0';
|
|
||||||
Curl_debug(data, CURLINFO_TEXT, buffer, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Curl_failf() is for messages stating why we failed.
|
|
||||||
* The message SHALL NOT include any LF or CR.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
DEBUGASSERT(!strchr(fmt, '\n'));
|
|
||||||
if(data->set.verbose || data->set.errorbuffer) {
|
|
||||||
va_list ap;
|
|
||||||
int len;
|
|
||||||
char error[CURL_ERROR_SIZE + 2];
|
|
||||||
va_start(ap, fmt);
|
|
||||||
len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
|
|
||||||
|
|
||||||
if(data->set.errorbuffer && !data->state.errorbuf) {
|
|
||||||
strcpy(data->set.errorbuffer, error);
|
|
||||||
data->state.errorbuf = TRUE; /* wrote error string */
|
|
||||||
}
|
|
||||||
error[len++] = '\n';
|
|
||||||
error[len] = '\0';
|
|
||||||
Curl_debug(data, CURLINFO_TEXT, error, len);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_write() is an internal write function that sends data to the
|
* Curl_write() is an internal write function that sends data to the
|
||||||
* server. Works with plain sockets, SCP, SSL or kerberos.
|
* server. Works with plain sockets, SCP, SSL or kerberos.
|
||||||
@ -752,30 +708,3 @@ out:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return 0 on success */
|
|
||||||
void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
|
||||||
char *ptr, size_t size)
|
|
||||||
{
|
|
||||||
if(data->set.verbose) {
|
|
||||||
static const char s_infotype[CURLINFO_END][3] = {
|
|
||||||
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
|
|
||||||
if(data->set.fdebug) {
|
|
||||||
bool inCallback = Curl_is_in_callback(data);
|
|
||||||
Curl_set_in_callback(data, true);
|
|
||||||
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
|
|
||||||
Curl_set_in_callback(data, inCallback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
switch(type) {
|
|
||||||
case CURLINFO_TEXT:
|
|
||||||
case CURLINFO_HEADER_OUT:
|
|
||||||
case CURLINFO_HEADER_IN:
|
|
||||||
fwrite(s_infotype[type], 2, 1, data->set.err);
|
|
||||||
fwrite(ptr, size, 1, data->set.err);
|
|
||||||
break;
|
|
||||||
default: /* nada */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
25
lib/sendf.h
25
lib/sendf.h
@ -26,26 +26,8 @@
|
|||||||
|
|
||||||
#include "curl_setup.h"
|
#include "curl_setup.h"
|
||||||
|
|
||||||
void Curl_infof(struct Curl_easy *, const char *fmt, ...);
|
#include "curl_log.h"
|
||||||
void Curl_failf(struct Curl_easy *, const char *fmt, ...);
|
|
||||||
|
|
||||||
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
|
|
||||||
|
|
||||||
#if defined(HAVE_VARIADIC_MACROS_C99)
|
|
||||||
#define infof(...) Curl_nop_stmt
|
|
||||||
#elif defined(HAVE_VARIADIC_MACROS_GCC)
|
|
||||||
#define infof(x...) Curl_nop_stmt
|
|
||||||
#else
|
|
||||||
#error "missing VARIADIC macro define, fix and rebuild!"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else /* CURL_DISABLE_VERBOSE_STRINGS */
|
|
||||||
|
|
||||||
#define infof Curl_infof
|
|
||||||
|
|
||||||
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
|
|
||||||
|
|
||||||
#define failf Curl_failf
|
|
||||||
|
|
||||||
#define CLIENTWRITE_BODY (1<<0)
|
#define CLIENTWRITE_BODY (1<<0)
|
||||||
#define CLIENTWRITE_HEADER (1<<1)
|
#define CLIENTWRITE_HEADER (1<<1)
|
||||||
@ -89,9 +71,4 @@ CURLcode Curl_write_plain(struct Curl_easy *data,
|
|||||||
const void *mem, size_t len,
|
const void *mem, size_t len,
|
||||||
ssize_t *written);
|
ssize_t *written);
|
||||||
|
|
||||||
/* the function used to output verbose information */
|
|
||||||
void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
|
||||||
char *ptr, size_t size);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HEADER_CURL_SENDF_H */
|
#endif /* HEADER_CURL_SENDF_H */
|
||||||
|
|||||||
@ -1221,9 +1221,10 @@ static void socks_cf_get_host(struct Curl_cfilter *cf,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct Curl_cftype cft_socks_proxy = {
|
struct Curl_cftype Curl_cft_socks_proxy = {
|
||||||
"SOCKS-PROXYY",
|
"SOCKS-PROXYY",
|
||||||
CF_TYPE_IP_CONNECT,
|
CF_TYPE_IP_CONNECT,
|
||||||
|
0,
|
||||||
socks_proxy_cf_destroy,
|
socks_proxy_cf_destroy,
|
||||||
socks_proxy_cf_connect,
|
socks_proxy_cf_connect,
|
||||||
socks_proxy_cf_close,
|
socks_proxy_cf_close,
|
||||||
@ -1245,7 +1246,7 @@ CURLcode Curl_conn_socks_proxy_add(struct Curl_easy *data,
|
|||||||
struct Curl_cfilter *cf;
|
struct Curl_cfilter *cf;
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_socks_proxy, NULL);
|
result = Curl_cf_create(&cf, &Curl_cft_socks_proxy, NULL);
|
||||||
if(!result)
|
if(!result)
|
||||||
Curl_conn_cf_add(data, conn, sockindex, cf);
|
Curl_conn_cf_add(data, conn, sockindex, cf);
|
||||||
return result;
|
return result;
|
||||||
@ -1258,7 +1259,7 @@ CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
|
|||||||
CURLcode result;
|
CURLcode result;
|
||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
result = Curl_cf_create(&cf, &cft_socks_proxy, NULL);
|
result = Curl_cf_create(&cf, &Curl_cft_socks_proxy, NULL);
|
||||||
if(!result)
|
if(!result)
|
||||||
Curl_conn_cf_insert_after(cf_at, cf);
|
Curl_conn_cf_insert_after(cf_at, cf);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -58,6 +58,8 @@ CURLcode Curl_conn_socks_proxy_add(struct Curl_easy *data,
|
|||||||
CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
|
CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
|
||||||
struct Curl_easy *data);
|
struct Curl_easy *data);
|
||||||
|
|
||||||
|
extern struct Curl_cftype Curl_cft_socks_proxy;
|
||||||
|
|
||||||
#endif /* CURL_DISABLE_PROXY */
|
#endif /* CURL_DISABLE_PROXY */
|
||||||
|
|
||||||
#endif /* HEADER_CURL_SOCKS_H */
|
#endif /* HEADER_CURL_SOCKS_H */
|
||||||
|
|||||||
@ -113,23 +113,6 @@ typedef unsigned int curl_prot_t;
|
|||||||
input easier and better. */
|
input easier and better. */
|
||||||
#define CURL_MAX_INPUT_LENGTH 8000000
|
#define CURL_MAX_INPUT_LENGTH 8000000
|
||||||
|
|
||||||
/* Macros intended for DEBUGF logging, use like:
|
|
||||||
* DEBUGF(infof(data, CFMSG(cf, "this filter %s rocks"), "very much"));
|
|
||||||
* and it will output:
|
|
||||||
* [CONN-1-0][CF-SSL] this filter very much rocks
|
|
||||||
* on connection #1 with sockindex 0 for filter of type "SSL". */
|
|
||||||
#define DMSG(d,msg) \
|
|
||||||
"[CONN-%ld] "msg, (d)->conn->connection_id
|
|
||||||
#define DMSGI(d,i,msg) \
|
|
||||||
"[CONN-%ld-%d] "msg, (d)->conn->connection_id, (i)
|
|
||||||
#define CMSG(c,msg) \
|
|
||||||
"[CONN-%ld] "msg, (c)->connection_id
|
|
||||||
#define CMSGI(c,i,msg) \
|
|
||||||
"[CONN-%ld-%d] "msg, (c)->connection_id, (i)
|
|
||||||
#define CFMSG(cf,msg) \
|
|
||||||
"[CONN-%ld-%d][CF-%s] "msg, (cf)->conn->connection_id, \
|
|
||||||
(cf)->sockindex, (cf)->cft->name
|
|
||||||
|
|
||||||
|
|
||||||
#include "cookie.h"
|
#include "cookie.h"
|
||||||
#include "psl.h"
|
#include "psl.h"
|
||||||
|
|||||||
@ -30,12 +30,14 @@
|
|||||||
#include "timeval.h"
|
#include "timeval.h"
|
||||||
#include "multiif.h"
|
#include "multiif.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
|
#include "curl_log.h"
|
||||||
#include "cfilters.h"
|
#include "cfilters.h"
|
||||||
#include "cf-socket.h"
|
#include "cf-socket.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "h2h3.h"
|
#include "h2h3.h"
|
||||||
#include "curl_msh3.h"
|
#include "curl_msh3.h"
|
||||||
#include "socketpair.h"
|
#include "socketpair.h"
|
||||||
|
#include "vquic/vquic.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"
|
||||||
@ -44,7 +46,7 @@
|
|||||||
|
|
||||||
#define DEBUG_CF 1
|
#define DEBUG_CF 1
|
||||||
|
|
||||||
#if DEBUG_CF
|
#if DEBUG_CF && defined(DEBUGBUILD)
|
||||||
#define CF_DEBUGF(x) x
|
#define CF_DEBUGF(x) x
|
||||||
#else
|
#else
|
||||||
#define CF_DEBUGF(x) do { } while(0)
|
#define CF_DEBUGF(x) do { } while(0)
|
||||||
@ -176,7 +178,7 @@ static CURLcode msh3_data_setup(struct Curl_cfilter *cf,
|
|||||||
|
|
||||||
DEBUGASSERT(stream);
|
DEBUGASSERT(stream);
|
||||||
if(!stream->recv_buf) {
|
if(!stream->recv_buf) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: setup")));
|
DEBUGF(LOG_CF(data, cf, "req: setup"));
|
||||||
stream->recv_buf = malloc(MSH3_REQ_INIT_BUF_LEN);
|
stream->recv_buf = malloc(MSH3_REQ_INIT_BUF_LEN);
|
||||||
if(!stream->recv_buf) {
|
if(!stream->recv_buf) {
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
@ -364,8 +366,7 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
size_t outsize = 0;
|
size_t outsize = 0;
|
||||||
|
|
||||||
(void)cf;
|
(void)cf;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: recv with %zu byte buffer"),
|
DEBUGF(LOG_CF(data, cf, "req: recv with %zu byte buffer", len));
|
||||||
len));
|
|
||||||
|
|
||||||
if(stream->recv_error) {
|
if(stream->recv_error) {
|
||||||
failf(data, "request aborted");
|
failf(data, "request aborted");
|
||||||
@ -388,8 +389,7 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
stream->recv_header_len + stream->recv_data_len - outsize);
|
stream->recv_header_len + stream->recv_data_len - outsize);
|
||||||
}
|
}
|
||||||
stream->recv_header_len -= outsize;
|
stream->recv_header_len -= outsize;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: returned %zu bytes of header"),
|
DEBUGF(LOG_CF(data, cf, "req: returned %zu bytes of header", outsize));
|
||||||
outsize));
|
|
||||||
}
|
}
|
||||||
else if(stream->recv_data_len) {
|
else if(stream->recv_data_len) {
|
||||||
outsize = len;
|
outsize = len;
|
||||||
@ -402,17 +402,16 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
stream->recv_data_len - outsize);
|
stream->recv_data_len - outsize);
|
||||||
}
|
}
|
||||||
stream->recv_data_len -= outsize;
|
stream->recv_data_len -= outsize;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: returned %zu bytes of data"),
|
DEBUGF(LOG_CF(data, cf, "req: returned %zu bytes of data", outsize));
|
||||||
outsize));
|
|
||||||
if(stream->recv_data_len == 0 && stream->recv_data_complete)
|
if(stream->recv_data_len == 0 && stream->recv_data_complete)
|
||||||
data->state.drain = 1;
|
data->state.drain = 1;
|
||||||
}
|
}
|
||||||
else if(stream->recv_data_complete) {
|
else if(stream->recv_data_complete) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: receive complete")));
|
DEBUGF(LOG_CF(data, cf, "req: receive complete"));
|
||||||
data->state.drain = 0;
|
data->state.drain = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: nothing here, call again")));
|
DEBUGF(LOG_CF(data, cf, "req: nothing here, call again"));
|
||||||
*err = CURLE_AGAIN;
|
*err = CURLE_AGAIN;
|
||||||
outsize = -1;
|
outsize = -1;
|
||||||
}
|
}
|
||||||
@ -433,7 +432,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
|
|
||||||
/* Sizes must match for cast below to work" */
|
/* Sizes must match for cast below to work" */
|
||||||
DEBUGASSERT(sizeof(MSH3_HEADER) == sizeof(struct h2h3pseudo));
|
DEBUGASSERT(sizeof(MSH3_HEADER) == sizeof(struct h2h3pseudo));
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: send %zu bytes"), len));
|
DEBUGF(LOG_CF(data, cf, "req: send %zu bytes", len));
|
||||||
|
|
||||||
if(!stream->req) {
|
if(!stream->req) {
|
||||||
/* The first send on the request contains the headers and possibly some
|
/* The first send on the request contains the headers and possibly some
|
||||||
@ -452,8 +451,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: send %zu headers"),
|
DEBUGF(LOG_CF(data, cf, "req: send %zu headers", hreq->entries));
|
||||||
hreq->entries));
|
|
||||||
stream->req = MsH3RequestOpen(ctx->qconn, &msh3_request_if, data,
|
stream->req = MsH3RequestOpen(ctx->qconn, &msh3_request_if, data,
|
||||||
(MSH3_HEADER*)hreq->header, hreq->entries,
|
(MSH3_HEADER*)hreq->header, hreq->entries,
|
||||||
hdrlen == len ? MSH3_REQUEST_FLAG_FIN :
|
hdrlen == len ? MSH3_REQUEST_FLAG_FIN :
|
||||||
@ -468,7 +466,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: send %zd body bytes"), len));
|
DEBUGF(LOG_CF(data, cf, "req: send %zd body bytes", len));
|
||||||
if(len > 0xFFFFFFFF) {
|
if(len > 0xFFFFFFFF) {
|
||||||
/* msh3 doesn't support size_t sends currently. */
|
/* msh3 doesn't support size_t sends currently. */
|
||||||
*err = CURLE_SEND_ERROR;
|
*err = CURLE_SEND_ERROR;
|
||||||
@ -508,7 +506,7 @@ static int cf_msh3_get_select_socks(struct Curl_cfilter *cf,
|
|||||||
data->state.drain = 1;
|
data->state.drain = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "select_sock %u -> %d"),
|
DEBUGF(LOG_CF(data, cf, "select_sock %u -> %d",
|
||||||
(uint32_t)data->state.drain, bitmap));
|
(uint32_t)data->state.drain, bitmap));
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
@ -520,7 +518,7 @@ static bool cf_msh3_data_pending(struct Curl_cfilter *cf,
|
|||||||
struct HTTP *stream = data->req.p.http;
|
struct HTTP *stream = data->req.p.http;
|
||||||
|
|
||||||
(void)cf;
|
(void)cf;
|
||||||
CF_DEBUGF(infof((struct Curl_easy *)data, CFMSG(cf, "data pending = %hhu"),
|
DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data pending = %hhu",
|
||||||
(bool)(stream->recv_header_len || stream->recv_data_len)));
|
(bool)(stream->recv_header_len || stream->recv_data_len)));
|
||||||
return stream->recv_header_len || stream->recv_data_len;
|
return stream->recv_header_len || stream->recv_data_len;
|
||||||
}
|
}
|
||||||
@ -557,7 +555,7 @@ static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CF_CTRL_DATA_DONE:
|
case CF_CTRL_DATA_DONE:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: done")));
|
DEBUGF(LOG_CF(data, cf, "req: done"));
|
||||||
if(stream) {
|
if(stream) {
|
||||||
if(stream->recv_buf) {
|
if(stream->recv_buf) {
|
||||||
Curl_safefree(stream->recv_buf);
|
Curl_safefree(stream->recv_buf);
|
||||||
@ -571,12 +569,12 @@ static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CF_CTRL_DATA_DONE_SEND:
|
case CF_CTRL_DATA_DONE_SEND:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: send done")));
|
DEBUGF(LOG_CF(data, cf, "req: send done"));
|
||||||
stream->upload_done = TRUE;
|
stream->upload_done = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CF_CTRL_CONN_INFO_UPDATE:
|
case CF_CTRL_CONN_INFO_UPDATE:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "req: update")));
|
DEBUGF(LOG_CF(data, cf, "req: update"));
|
||||||
cf_msh3_active(cf, data);
|
cf_msh3_active(cf, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -600,16 +598,16 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
|||||||
/* TODO: need a way to provide trust anchors to MSH3 */
|
/* TODO: need a way to provide trust anchors to MSH3 */
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
/* we need this for our test cases to run */
|
/* we need this for our test cases to run */
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "non-standard CA not supported, "
|
DEBUGF(LOG_CF(data, cf, "non-standard CA not supported, "
|
||||||
"switching off verifypeer in DEBUG mode")));
|
"switching off verifypeer in DEBUG mode"));
|
||||||
verify = 0;
|
verify = 0;
|
||||||
#else
|
#else
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "non-standard CA not supported, "
|
DEBUGF(LOG_CF(data, cf, "non-standard CA not supported, "
|
||||||
"attempting with built-in verification")));
|
"attempting with built-in verification"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "connecting to %s:%d (verify=%d)"),
|
DEBUGF(LOG_CF(data, cf, "connecting to %s:%d (verify=%d)",
|
||||||
cf->conn->host.name, (int)cf->conn->remote_port, verify));
|
cf->conn->host.name, (int)cf->conn->remote_port, verify));
|
||||||
|
|
||||||
ctx->api = MsH3ApiOpen();
|
ctx->api = MsH3ApiOpen();
|
||||||
@ -690,7 +688,7 @@ static void cf_msh3_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
if(ctx) {
|
if(ctx) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "destroying")));
|
DEBUGF(LOG_CF(data, cf, "destroying"));
|
||||||
if(ctx->qconn)
|
if(ctx->qconn)
|
||||||
MsH3ConnectionClose(ctx->qconn);
|
MsH3ConnectionClose(ctx->qconn);
|
||||||
if(ctx->api)
|
if(ctx->api)
|
||||||
@ -702,13 +700,13 @@ static void cf_msh3_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||||||
* closed it) and we just forget about it.
|
* closed it) and we just forget about it.
|
||||||
*/
|
*/
|
||||||
if(ctx->sock[SP_LOCAL] == cf->conn->sock[cf->sockindex]) {
|
if(ctx->sock[SP_LOCAL] == cf->conn->sock[cf->sockindex]) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "cf_msh3_close(%d) active"),
|
DEBUGF(LOG_CF(data, cf, "cf_msh3_close(%d) active",
|
||||||
(int)ctx->sock[SP_LOCAL]));
|
(int)ctx->sock[SP_LOCAL]));
|
||||||
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
|
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "cf_socket_close(%d) no longer at "
|
DEBUGF(LOG_CF(data, cf, "cf_socket_close(%d) no longer at "
|
||||||
"conn->sock[%d], discarding"), (int)ctx->sock[SP_LOCAL]));
|
"conn->sock[], discarding", (int)ctx->sock[SP_LOCAL]));
|
||||||
ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
|
ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
|
||||||
}
|
}
|
||||||
if(cf->sockindex == FIRSTSOCKET)
|
if(cf->sockindex == FIRSTSOCKET)
|
||||||
@ -764,9 +762,10 @@ static bool cf_msh3_conn_is_alive(struct Curl_cfilter *cf,
|
|||||||
ctx->connected;
|
ctx->connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct Curl_cftype cft_msh3 = {
|
struct Curl_cftype Curl_cft_http3 = {
|
||||||
"HTTP/3-MSH3",
|
"HTTP/3",
|
||||||
CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
|
CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
|
||||||
|
0,
|
||||||
cf_msh3_destroy,
|
cf_msh3_destroy,
|
||||||
cf_msh3_connect,
|
cf_msh3_connect,
|
||||||
cf_msh3_close,
|
cf_msh3_close,
|
||||||
@ -802,7 +801,7 @@ CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf,
|
|||||||
ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
|
ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
|
||||||
ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD;
|
ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD;
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_msh3, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
*pcf = (!result)? cf : NULL;
|
*pcf = (!result)? cf : NULL;
|
||||||
@ -822,7 +821,7 @@ bool Curl_conn_is_msh3(const struct Curl_easy *data,
|
|||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
for(; cf; cf = cf->next) {
|
for(; cf; cf = cf->next) {
|
||||||
if(cf->cft == &cft_msh3)
|
if(cf->cft == &Curl_cft_http3)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
|
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@ -66,24 +66,6 @@
|
|||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
/* #define DEBUG_NGTCP2 */
|
|
||||||
#define DEBUG_CF 0
|
|
||||||
|
|
||||||
#if DEBUG_CF
|
|
||||||
#define CF_DEBUGF(x) x
|
|
||||||
#define H3STRM(cf,sid,msg) \
|
|
||||||
"[CONN-%ld-%d][CF-%s][h3sid=%" PRIx64 "] "msg, (cf)->conn->connection_id, \
|
|
||||||
(cf)->sockindex, (cf)->cft->name, sid
|
|
||||||
#define QSTRM(cf,sid,msg) \
|
|
||||||
"[CONN-%ld-%d][CF-%s][qsid=%" PRIx64 "] "msg, (cf)->conn->connection_id, \
|
|
||||||
(cf)->sockindex, (cf)->cft->name, sid
|
|
||||||
|
|
||||||
#else
|
|
||||||
#define H3STRM(cf,sid,msg)
|
|
||||||
#define QSTRM(cf,sid,msg)
|
|
||||||
#define CF_DEBUGF(x) do { } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define H3_ALPN_H3_29 "\x5h3-29"
|
#define H3_ALPN_H3_29 "\x5h3-29"
|
||||||
#define H3_ALPN_H3 "\x2h3"
|
#define H3_ALPN_H3 "\x2h3"
|
||||||
@ -450,14 +432,14 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
|
|||||||
gnutls_session_set_ptr(ctx->gtls->session, &ctx->conn_ref);
|
gnutls_session_set_ptr(ctx->gtls->session, &ctx->conn_ref);
|
||||||
|
|
||||||
if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls->session) != 0) {
|
if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls->session) != 0) {
|
||||||
CF_DEBUGF(fprintf(stderr,
|
DEBUGF(LOG_CF(data, cf,
|
||||||
"ngtcp2_crypto_gnutls_configure_client_session failed\n"));
|
"ngtcp2_crypto_gnutls_configure_client_session failed\n"));
|
||||||
return CURLE_QUIC_CONNECT_ERROR;
|
return CURLE_QUIC_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = gnutls_priority_set_direct(ctx->gtls->session, QUIC_PRIORITY, NULL);
|
rc = gnutls_priority_set_direct(ctx->gtls->session, QUIC_PRIORITY, NULL);
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
CF_DEBUGF(fprintf(stderr, "gnutls_priority_set_direct failed: %s\n",
|
DEBUGF(LOG_CF(data, cf, "gnutls_priority_set_direct failed: %s\n",
|
||||||
gnutls_strerror(rc)));
|
gnutls_strerror(rc)));
|
||||||
return CURLE_QUIC_CONNECT_ERROR;
|
return CURLE_QUIC_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
@ -693,7 +675,7 @@ static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
|
|||||||
|
|
||||||
rv = nghttp3_conn_close_stream(ctx->h3conn, stream_id,
|
rv = nghttp3_conn_close_stream(ctx->h3conn, stream_id,
|
||||||
app_error_code);
|
app_error_code);
|
||||||
CF_DEBUGF(infof(data, QSTRM(cf, stream_id, "close -> %d"), rv));
|
DEBUGF(LOG_CF(data, cf, "[qsid=%" PRIx64 "] close -> %d", stream_id, rv));
|
||||||
if(rv) {
|
if(rv) {
|
||||||
ngtcp2_connection_close_error_set_application_error(
|
ngtcp2_connection_close_error_set_application_error(
|
||||||
&ctx->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0);
|
&ctx->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0);
|
||||||
@ -717,7 +699,7 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
|
|||||||
(void)data;
|
(void)data;
|
||||||
|
|
||||||
rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
|
rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
|
||||||
CF_DEBUGF(infof(data, QSTRM(cf, stream_id, "reset -> %d"), rv));
|
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRIx64 "] reset -> %d", stream_id, rv));
|
||||||
if(rv) {
|
if(rv) {
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
@ -906,7 +888,7 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
|
|||||||
(void)app_error_code;
|
(void)app_error_code;
|
||||||
(void)cf;
|
(void)cf;
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, H3STRM(cf, stream_id, "close")));
|
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRIx64 "] close", stream_id));
|
||||||
stream->closed = TRUE;
|
stream->closed = TRUE;
|
||||||
stream->error3 = app_error_code;
|
stream->error3 = app_error_code;
|
||||||
Curl_expire(data, 0, EXPIRE_QUIC);
|
Curl_expire(data, 0, EXPIRE_QUIC);
|
||||||
@ -954,8 +936,8 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream_id,
|
|||||||
(void)cf;
|
(void)cf;
|
||||||
|
|
||||||
result = write_data(stream, buf, buflen);
|
result = write_data(stream, buf, buflen);
|
||||||
CF_DEBUGF(infof(data, H3STRM(cf, stream_id, "recv_data(len=%zu) -> %d"),
|
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRIx64 "] recv_data(len=%zu) -> %d",
|
||||||
buflen, result));
|
stream_id, buflen, result));
|
||||||
if(result) {
|
if(result) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1027,8 +1009,8 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, H3STRM(cf, stream_id, "end_headers(status_code=%d"),
|
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRIx64 "] end_headers(status_code=%d",
|
||||||
stream->status_code));
|
stream_id, stream->status_code));
|
||||||
if(stream->status_code / 100 != 1) {
|
if(stream->status_code / 100 != 1) {
|
||||||
stream->bodystarted = TRUE;
|
stream->bodystarted = TRUE;
|
||||||
}
|
}
|
||||||
@ -1117,7 +1099,7 @@ static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t stream_id,
|
|||||||
|
|
||||||
rv = ngtcp2_conn_shutdown_stream_write(ctx->qconn, stream_id,
|
rv = ngtcp2_conn_shutdown_stream_write(ctx->qconn, stream_id,
|
||||||
app_error_code);
|
app_error_code);
|
||||||
CF_DEBUGF(infof(data, H3STRM(cf, stream_id, "reset -> %d"), rv));
|
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRIx64 "] reset -> %d", stream_id, rv));
|
||||||
if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
|
if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
@ -1303,15 +1285,16 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
|
|||||||
uint64_t datalen, void *user_data,
|
uint64_t datalen, void *user_data,
|
||||||
void *stream_user_data)
|
void *stream_user_data)
|
||||||
{
|
{
|
||||||
|
struct Curl_cfilter *cf = user_data;
|
||||||
struct Curl_easy *data = stream_user_data;
|
struct Curl_easy *data = stream_user_data;
|
||||||
struct HTTP *stream = data->req.p.http;
|
struct HTTP *stream = data->req.p.http;
|
||||||
(void)user_data;
|
(void)user_data;
|
||||||
|
|
||||||
|
(void)cf;
|
||||||
if(!data->set.postfields) {
|
if(!data->set.postfields) {
|
||||||
stream->h3out->used -= datalen;
|
stream->h3out->used -= datalen;
|
||||||
CF_DEBUGF(infof(data,
|
DEBUGF(LOG_CF(data, cf, "cb_h3_acked_stream_data, %"PRIu64" bytes, "
|
||||||
"cb_h3_acked_stream_data, %zd bytes, %zd left unacked",
|
"%zd left unacked", datalen, stream->h3out->used));
|
||||||
datalen, stream->h3out->used));
|
|
||||||
DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);
|
DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);
|
||||||
|
|
||||||
if(stream->h3out->used == 0) {
|
if(stream->h3out->used == 0) {
|
||||||
@ -1329,9 +1312,11 @@ static nghttp3_ssize cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
|
|||||||
uint32_t *pflags, void *user_data,
|
uint32_t *pflags, void *user_data,
|
||||||
void *stream_user_data)
|
void *stream_user_data)
|
||||||
{
|
{
|
||||||
|
struct Curl_cfilter *cf = user_data;
|
||||||
struct Curl_easy *data = stream_user_data;
|
struct Curl_easy *data = stream_user_data;
|
||||||
size_t nread;
|
size_t nread;
|
||||||
struct HTTP *stream = data->req.p.http;
|
struct HTTP *stream = data->req.p.http;
|
||||||
|
(void)cf;
|
||||||
(void)conn;
|
(void)conn;
|
||||||
(void)stream_id;
|
(void)stream_id;
|
||||||
(void)user_data;
|
(void)user_data;
|
||||||
@ -1376,13 +1361,13 @@ static nghttp3_ssize cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
|
|||||||
if(!stream->upload_left)
|
if(!stream->upload_left)
|
||||||
*pflags = NGHTTP3_DATA_FLAG_EOF;
|
*pflags = NGHTTP3_DATA_FLAG_EOF;
|
||||||
}
|
}
|
||||||
CF_DEBUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)",
|
DEBUGF(LOG_CF(data, cf, "cb_h3_readfunction %zd bytes%s (at %zd unacked)",
|
||||||
nread, *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
|
nread, *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
|
||||||
out->used));
|
out->used));
|
||||||
}
|
}
|
||||||
if(stream->upload_done && !stream->upload_len &&
|
if(stream->upload_done && !stream->upload_len &&
|
||||||
(stream->upload_left <= 0)) {
|
(stream->upload_left <= 0)) {
|
||||||
CF_DEBUGF(infof(data, "cb_h3_readfunction sets EOF"));
|
DEBUGF(LOG_CF(data, cf, "cb_h3_readfunction sets EOF"));
|
||||||
*pflags = NGHTTP3_DATA_FLAG_EOF;
|
*pflags = NGHTTP3_DATA_FLAG_EOF;
|
||||||
return nread ? 1 : 0;
|
return nread ? 1 : 0;
|
||||||
}
|
}
|
||||||
@ -1527,7 +1512,7 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
sent = len;
|
sent = len;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CF_DEBUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes",
|
DEBUGF(LOG_CF(data, cf, "ngh3_stream_send() wants to send %zd bytes",
|
||||||
len));
|
len));
|
||||||
if(!stream->upload_len) {
|
if(!stream->upload_len) {
|
||||||
stream->upload_mem = buf;
|
stream->upload_mem = buf;
|
||||||
@ -2413,9 +2398,10 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct Curl_cftype cft_qng = {
|
struct Curl_cftype Curl_cft_http3 = {
|
||||||
"HTTP/3-NGTCP2",
|
"HTTP/3",
|
||||||
CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
|
CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
|
||||||
|
0,
|
||||||
cf_ngtcp2_destroy,
|
cf_ngtcp2_destroy,
|
||||||
cf_ngtcp2_connect,
|
cf_ngtcp2_connect,
|
||||||
cf_ngtcp2_close,
|
cf_ngtcp2_close,
|
||||||
@ -2447,7 +2433,7 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_qng, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
|
||||||
if(result)
|
if(result)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -2479,7 +2465,7 @@ bool Curl_conn_is_ngtcp2(const struct Curl_easy *data,
|
|||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
for(; cf; cf = cf->next) {
|
for(; cf; cf = cf->next) {
|
||||||
if(cf->cft == &cft_qng)
|
if(cf->cft == &Curl_cft_http3)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
|
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@ -50,13 +50,6 @@
|
|||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
#define DEBUG_CF 0
|
|
||||||
|
|
||||||
#if DEBUG_CF
|
|
||||||
#define CF_DEBUGF(x) x
|
|
||||||
#else
|
|
||||||
#define CF_DEBUGF(x) do { } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define QUIC_MAX_STREAMS (256*1024)
|
#define QUIC_MAX_STREAMS (256*1024)
|
||||||
#define QUIC_MAX_DATA (1*1024*1024)
|
#define QUIC_MAX_DATA (1*1024*1024)
|
||||||
@ -192,7 +185,7 @@ static CURLcode h3_add_event(struct Curl_cfilter *cf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!mdata) {
|
if(!mdata) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "event for unknown stream %u, discarded"),
|
DEBUGF(LOG_CF(data, cf, "event for unknown stream %"PRId64", discarded",
|
||||||
stream3_id));
|
stream3_id));
|
||||||
quiche_h3_event_free(ev);
|
quiche_h3_event_free(ev);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
@ -278,12 +271,12 @@ static ssize_t h3_process_event(struct Curl_cfilter *cf,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
recvd = headers.nlen;
|
recvd = headers.nlen;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "h3[%u] HEADERS len=%d"),
|
DEBUGF(LOG_CF(data, cf, "h3[%"PRId64"] HEADERS len=%d",
|
||||||
stream3_id, (int)recvd));
|
stream3_id, (int)recvd));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUICHE_H3_EVENT_DATA:
|
case QUICHE_H3_EVENT_DATA:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "h3[%u] DATA"), stream3_id));
|
DEBUGF(LOG_CF(data, cf, "h3[%"PRId64"] DATA", stream3_id));
|
||||||
if(!stream->firstbody) {
|
if(!stream->firstbody) {
|
||||||
/* add a header-body separator CRLF */
|
/* add a header-body separator CRLF */
|
||||||
buf[0] = '\r';
|
buf[0] = '\r';
|
||||||
@ -307,14 +300,14 @@ static ssize_t h3_process_event(struct Curl_cfilter *cf,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QUICHE_H3_EVENT_RESET:
|
case QUICHE_H3_EVENT_RESET:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "h3[%u] RESET"), stream3_id));
|
DEBUGF(LOG_CF(data, cf, "h3[%"PRId64"] RESET", stream3_id));
|
||||||
streamclose(cf->conn, "Stream reset");
|
streamclose(cf->conn, "Stream reset");
|
||||||
*err = CURLE_PARTIAL_FILE;
|
*err = CURLE_PARTIAL_FILE;
|
||||||
recvd = -1;
|
recvd = -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QUICHE_H3_EVENT_FINISHED:
|
case QUICHE_H3_EVENT_FINISHED:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "h3[%u] FINISHED"), stream3_id));
|
DEBUGF(LOG_CF(data, cf, "h3[%"PRId64"] FINISHED", stream3_id));
|
||||||
stream->closed = TRUE;
|
stream->closed = TRUE;
|
||||||
streamclose(cf->conn, "End of stream");
|
streamclose(cf->conn, "End of stream");
|
||||||
*err = CURLE_OK;
|
*err = CURLE_OK;
|
||||||
@ -328,7 +321,7 @@ static ssize_t h3_process_event(struct Curl_cfilter *cf,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "h3[%u] unhandled event %d"),
|
DEBUGF(LOG_CF(data, cf, "h3[%"PRId64"] unhandled event %d",
|
||||||
stream3_id, quiche_h3_event_type(ev)));
|
stream3_id, quiche_h3_event_type(ev)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -466,13 +459,13 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
quiche_h3_event *ev;
|
quiche_h3_event *ev;
|
||||||
struct HTTP *stream = data->req.p.http;
|
struct HTTP *stream = data->req.p.http;
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "recv[%u]"), stream->stream3_id));
|
DEBUGF(LOG_CF(data, cf, "recv[%"PRId64"]", stream->stream3_id));
|
||||||
|
|
||||||
*err = CURLE_AGAIN;
|
*err = CURLE_AGAIN;
|
||||||
recvd = -1;
|
recvd = -1;
|
||||||
|
|
||||||
if(cf_process_ingress(cf, data)) {
|
if(cf_process_ingress(cf, data)) {
|
||||||
CF_DEBUGF(infof(data, "h3_stream_recv returns on ingress"));
|
DEBUGF(LOG_CF(data, cf, "h3_stream_recv returns on ingress"));
|
||||||
*err = CURLE_RECV_ERROR;
|
*err = CURLE_RECV_ERROR;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -504,7 +497,7 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
|
|
||||||
if(stream3_id != stream->stream3_id) {
|
if(stream3_id != stream->stream3_id) {
|
||||||
/* event for another transfer, preserver for later */
|
/* event for another transfer, preserver for later */
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "h3[%u] queuing event"), stream3_id));
|
DEBUGF(LOG_CF(data, cf, "h3[%"PRId64"] queuing event", stream3_id));
|
||||||
if(h3_add_event(cf, data, stream3_id, ev) != CURLE_OK) {
|
if(h3_add_event(cf, data, stream3_id, ev) != CURLE_OK) {
|
||||||
*err = CURLE_OUT_OF_MEMORY;
|
*err = CURLE_OUT_OF_MEMORY;
|
||||||
goto out;
|
goto out;
|
||||||
@ -517,7 +510,7 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(cf_flush_egress(cf, data)) {
|
if(cf_flush_egress(cf, data)) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "recv(), flush egress failed")));
|
DEBUGF(LOG_CF(data, cf, "recv(), flush egress failed"));
|
||||||
*err = CURLE_SEND_ERROR;
|
*err = CURLE_SEND_ERROR;
|
||||||
recvd = -1;
|
recvd = -1;
|
||||||
goto out;
|
goto out;
|
||||||
@ -534,7 +527,7 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
data->state.drain = (recvd >= 0) ? 1 : 0;
|
data->state.drain = (recvd >= 0) ? 1 : 0;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "recv[%u] -> %ld, err=%d"),
|
DEBUGF(LOG_CF(data, cf, "recv[%"PRId64"] -> %ld, err=%d",
|
||||||
stream->stream3_id, (long)recvd, *err));
|
stream->stream3_id, (long)recvd, *err));
|
||||||
return recvd;
|
return recvd;
|
||||||
}
|
}
|
||||||
@ -591,7 +584,7 @@ static CURLcode cf_http_request(struct Curl_cfilter *cf,
|
|||||||
|
|
||||||
stream3_id = quiche_h3_send_request(ctx->h3c, ctx->qconn, nva, nheader,
|
stream3_id = quiche_h3_send_request(ctx->h3c, ctx->qconn, nva, nheader,
|
||||||
stream->upload_left ? FALSE: TRUE);
|
stream->upload_left ? FALSE: TRUE);
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "send_request(with_body=%d) -> %zd"),
|
DEBUGF(LOG_CF(data, cf, "send_request(with_body=%d) -> %"PRId64,
|
||||||
!!stream->upload_left, stream3_id));
|
!!stream->upload_left, stream3_id));
|
||||||
if((stream3_id >= 0) && data->set.postfields) {
|
if((stream3_id >= 0) && data->set.postfields) {
|
||||||
ssize_t sent = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream3_id,
|
ssize_t sent = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream3_id,
|
||||||
@ -613,13 +606,13 @@ static CURLcode cf_http_request(struct Curl_cfilter *cf,
|
|||||||
Curl_safefree(nva);
|
Curl_safefree(nva);
|
||||||
|
|
||||||
if(stream3_id < 0) {
|
if(stream3_id < 0) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "quiche_h3_send_request returned %ld"),
|
DEBUGF(LOG_CF(data, cf, "quiche_h3_send_request returned %ld",
|
||||||
(long)stream3_id));
|
(long)stream3_id));
|
||||||
result = CURLE_SEND_ERROR;
|
result = CURLE_SEND_ERROR;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "Using HTTP/3 Stream ID: %u"), stream3_id));
|
DEBUGF(LOG_CF(data, cf, "Using HTTP/3 Stream ID: %"PRId64, stream3_id));
|
||||||
stream->stream3_id = stream3_id;
|
stream->stream3_id = stream3_id;
|
||||||
|
|
||||||
Curl_pseudo_free(hreq);
|
Curl_pseudo_free(hreq);
|
||||||
@ -653,13 +646,12 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
sent = 0;
|
sent = 0;
|
||||||
}
|
}
|
||||||
else if(sent == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) {
|
else if(sent == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) {
|
||||||
DEBUGF(infof(data, CFMSG(cf, "send_body(len=%zu) -> exceeds size"),
|
DEBUGF(LOG_CF(data, cf, "send_body(len=%zu) -> exceeds size", len));
|
||||||
len));
|
|
||||||
*err = CURLE_SEND_ERROR;
|
*err = CURLE_SEND_ERROR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if(sent < 0) {
|
else if(sent < 0) {
|
||||||
DEBUGF(infof(data, CFMSG(cf, "send_body(len=%zu) -> %zd"), len, sent));
|
DEBUGF(LOG_CF(data, cf, "send_body(len=%zu) -> %zd", len, sent));
|
||||||
*err = CURLE_SEND_ERROR;
|
*err = CURLE_SEND_ERROR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -708,13 +700,13 @@ static bool cf_quiche_data_pending(struct Curl_cfilter *cf,
|
|||||||
|
|
||||||
for(node = ctx->pending; node; node = node->next) {
|
for(node = ctx->pending; node; node = node->next) {
|
||||||
if(node->stream3_id == stream->stream3_id) {
|
if(node->stream3_id == stream->stream3_id) {
|
||||||
CF_DEBUGF(infof((struct Curl_easy *)data,
|
DEBUGF(LOG_CF((struct Curl_easy *)data, cf,
|
||||||
CFMSG(cf, "h3[%u] has data pending"), stream->stream3_id));
|
"h3[%"PRId64"] has data pending", stream->stream3_id));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CF_DEBUGF(infof((struct Curl_easy *)data,
|
DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "h3[%"PRId64"] no data pending",
|
||||||
CFMSG(cf, "h3[%u] no data pending"), stream->stream3_id));
|
stream->stream3_id));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,10 +758,10 @@ static CURLcode cf_verify_peer(struct Curl_cfilter *cf,
|
|||||||
X509_free(server_cert);
|
X509_free(server_cert);
|
||||||
if(result)
|
if(result)
|
||||||
goto out;
|
goto out;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "Verified certificate just fine")));
|
DEBUGF(LOG_CF(data, cf, "Verified certificate just fine"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "Skipped certificate verification")));
|
DEBUGF(LOG_CF(data, cf, "Skipped certificate verification"));
|
||||||
|
|
||||||
ctx->h3config = quiche_h3_config_new();
|
ctx->h3config = quiche_h3_config_new();
|
||||||
if(!ctx->h3config) {
|
if(!ctx->h3config) {
|
||||||
@ -935,7 +927,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
|||||||
offset += 1 + alpn_len;
|
offset += 1 + alpn_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "Sent QUIC client Initial, ALPN: %s"),
|
DEBUGF(LOG_CF(data, cf, "Sent QUIC client Initial, ALPN: %s",
|
||||||
alpn_protocols + 1));
|
alpn_protocols + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1057,7 +1049,7 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
|
|||||||
max_streams += quiche_conn_peer_streams_left_bidi(ctx->qconn);
|
max_streams += quiche_conn_peer_streams_left_bidi(ctx->qconn);
|
||||||
}
|
}
|
||||||
*pres1 = (max_streams > INT_MAX)? INT_MAX : (int)max_streams;
|
*pres1 = (max_streams > INT_MAX)? INT_MAX : (int)max_streams;
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "query: MAX_CONCURRENT -> %ld"), *pres1));
|
DEBUGF(LOG_CF(data, cf, "query: MAX_CONCURRENT -> %d", *pres1));
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -1069,9 +1061,10 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct Curl_cftype cft_quiche = {
|
struct Curl_cftype Curl_cft_http3 = {
|
||||||
"HTTP/3-QUICHE",
|
"HTTP/3",
|
||||||
CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
|
CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
|
||||||
|
0,
|
||||||
cf_quiche_destroy,
|
cf_quiche_destroy,
|
||||||
cf_quiche_connect,
|
cf_quiche_connect,
|
||||||
cf_quiche_close,
|
cf_quiche_close,
|
||||||
@ -1103,7 +1096,7 @@ CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_quiche, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
|
||||||
if(result)
|
if(result)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -1135,7 +1128,7 @@ bool Curl_conn_is_quiche(const struct Curl_easy *data,
|
|||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
for(; cf; cf = cf->next) {
|
for(; cf; cf = cf->next) {
|
||||||
if(cf->cft == &cft_quiche)
|
if(cf->cft == &Curl_cft_http3)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
|
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@ -49,6 +49,8 @@ bool Curl_conn_is_http3(const struct Curl_easy *data,
|
|||||||
const struct connectdata *conn,
|
const struct connectdata *conn,
|
||||||
int sockindex);
|
int sockindex);
|
||||||
|
|
||||||
|
extern struct Curl_cftype Curl_cft_http3;
|
||||||
|
|
||||||
#else /* ENABLE_QUIC */
|
#else /* ENABLE_QUIC */
|
||||||
|
|
||||||
#define Curl_conn_is_http3(a,b,c) FALSE
|
#define Curl_conn_is_http3(a,b,c) FALSE
|
||||||
|
|||||||
@ -166,8 +166,8 @@ static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
|
|||||||
|
|
||||||
DEBUGASSERT(data);
|
DEBUGASSERT(data);
|
||||||
nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result);
|
nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result);
|
||||||
/* DEBUGF(infof(data, CFMSG(cf, "bio_cf_out_write(len=%d) -> %d, err=%d"),
|
DEBUGF(LOG_CF(data, cf, "bio_cf_out_write(len=%zu) -> %zd, err=%d",
|
||||||
blen, (int)nwritten, result)); */
|
blen, nwritten, result));
|
||||||
if(nwritten < 0 && CURLE_AGAIN == result) {
|
if(nwritten < 0 && CURLE_AGAIN == result) {
|
||||||
nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
|
nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||||
}
|
}
|
||||||
@ -188,8 +188,8 @@ static int bio_cf_read(void *bio, unsigned char *buf, size_t blen)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result);
|
nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result);
|
||||||
/* DEBUGF(infof(data, CFMSG(cf, "bio_cf_in_read(len=%d) -> %d, err=%d"),
|
DEBUGF(LOG_CF(data, cf, "bio_cf_in_read(len=%zu) -> %zd, err=%d",
|
||||||
blen, (int)nread, result)); */
|
blen, nread, result));
|
||||||
if(nread < 0 && CURLE_AGAIN == result) {
|
if(nread < 0 && CURLE_AGAIN == result) {
|
||||||
nread = MBEDTLS_ERR_SSL_WANT_READ;
|
nread = MBEDTLS_ERR_SSL_WANT_READ;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,9 +97,6 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
|
||||||
#define DEBUG_ME 0
|
|
||||||
|
|
||||||
|
|
||||||
/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
|
/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
|
||||||
renegotiations when built with BoringSSL. Renegotiating is non-compliant
|
renegotiations when built with BoringSSL. Renegotiating is non-compliant
|
||||||
with HTTP/2 and "an extremely dangerous protocol feature". Beware.
|
with HTTP/2 and "an extremely dangerous protocol feature". Beware.
|
||||||
@ -710,10 +707,8 @@ static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
|
|||||||
|
|
||||||
DEBUGASSERT(data);
|
DEBUGASSERT(data);
|
||||||
nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
|
nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
|
||||||
#if DEBUG_ME
|
DEBUGF(LOG_CF(data, cf, "bio_cf_out_write(len=%d) -> %d, err=%d",
|
||||||
DEBUGF(infof(data, CFMSG(cf, "bio_cf_out_write(len=%d) -> %d, err=%d"),
|
|
||||||
blen, (int)nwritten, result));
|
blen, (int)nwritten, result));
|
||||||
#endif
|
|
||||||
BIO_clear_retry_flags(bio);
|
BIO_clear_retry_flags(bio);
|
||||||
connssl->backend->io_result = result;
|
connssl->backend->io_result = result;
|
||||||
if(nwritten < 0) {
|
if(nwritten < 0) {
|
||||||
@ -737,10 +732,8 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
|
nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
|
||||||
#if DEBUG_ME
|
DEBUGF(LOG_CF(data, cf, "bio_cf_in_read(len=%d) -> %d, err=%d",
|
||||||
DEBUGF(infof(data, CFMSG(cf, "bio_cf_in_read(len=%d) -> %d, err=%d"),
|
|
||||||
blen, (int)nread, result));
|
blen, (int)nread, result));
|
||||||
#endif
|
|
||||||
BIO_clear_retry_flags(bio);
|
BIO_clear_retry_flags(bio);
|
||||||
connssl->backend->io_result = result;
|
connssl->backend->io_result = result;
|
||||||
if(nread < 0) {
|
if(nread < 0) {
|
||||||
@ -2735,7 +2728,7 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
txt_len = msnprintf(ssl_buf, sizeof(ssl_buf),
|
txt_len = msnprintf(ssl_buf, sizeof(ssl_buf),
|
||||||
CFMSG(cf, "%s (%s), %s, %s (%d):\n"),
|
"%s (%s), %s, %s (%d):\n",
|
||||||
verstr, direction?"OUT":"IN",
|
verstr, direction?"OUT":"IN",
|
||||||
tls_rt_name, msg_name, msg_type);
|
tls_rt_name, msg_name, msg_type);
|
||||||
if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
|
if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
|
||||||
|
|||||||
@ -161,7 +161,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
io_error = rustls_connection_read_tls(rconn, read_cb, &io_ctx,
|
io_error = rustls_connection_read_tls(rconn, read_cb, &io_ctx,
|
||||||
&tls_bytes_read);
|
&tls_bytes_read);
|
||||||
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
|
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
|
||||||
infof(data, CFMSG(cf, "cr_recv: EAGAIN or EWOULDBLOCK"));
|
DEBUGF(LOG_CF(data, cf, "cr_recv: EAGAIN or EWOULDBLOCK"));
|
||||||
}
|
}
|
||||||
else if(io_error) {
|
else if(io_error) {
|
||||||
char buffer[STRERROR_LEN];
|
char buffer[STRERROR_LEN];
|
||||||
@ -171,7 +171,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
infof(data, CFMSG(cf, "cr_recv: read %ld TLS bytes"), tls_bytes_read);
|
DEBUGF(LOG_CF(data, cf, "cr_recv: read %ld TLS bytes", tls_bytes_read));
|
||||||
|
|
||||||
rresult = rustls_connection_process_new_packets(rconn);
|
rresult = rustls_connection_process_new_packets(rconn);
|
||||||
if(rresult != RUSTLS_RESULT_OK) {
|
if(rresult != RUSTLS_RESULT_OK) {
|
||||||
@ -189,7 +189,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
plainlen - plain_bytes_copied,
|
plainlen - plain_bytes_copied,
|
||||||
&n);
|
&n);
|
||||||
if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
|
if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
|
||||||
infof(data, CFMSG(cf, "cr_recv: got PLAINTEXT_EMPTY. "
|
DEBUGF(LOG_CF(data, cf, "cr_recv: got PLAINTEXT_EMPTY. "
|
||||||
"will try again later."));
|
"will try again later."));
|
||||||
backend->data_pending = FALSE;
|
backend->data_pending = FALSE;
|
||||||
break;
|
break;
|
||||||
@ -207,7 +207,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
infof(data, CFMSG(cf, "cr_recv: got %ld plain bytes"), n);
|
DEBUGF(LOG_CF(data, cf, "cr_recv: got %ld plain bytes", n));
|
||||||
plain_bytes_copied += n;
|
plain_bytes_copied += n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,7 +258,7 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
DEBUGASSERT(backend);
|
DEBUGASSERT(backend);
|
||||||
rconn = backend->conn;
|
rconn = backend->conn;
|
||||||
|
|
||||||
infof(data, CFMSG(cf, "cr_send: %ld plain bytes"), plainlen);
|
DEBUGF(LOG_CF(data, cf, "cr_send: %ld plain bytes", plainlen));
|
||||||
|
|
||||||
if(plainlen > 0) {
|
if(plainlen > 0) {
|
||||||
rresult = rustls_connection_write(rconn, plainbuf, plainlen,
|
rresult = rustls_connection_write(rconn, plainbuf, plainlen,
|
||||||
@ -282,8 +282,8 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
io_error = rustls_connection_write_tls(rconn, write_cb, &io_ctx,
|
io_error = rustls_connection_write_tls(rconn, write_cb, &io_ctx,
|
||||||
&tlswritten);
|
&tlswritten);
|
||||||
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
|
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
|
||||||
infof(data, CFMSG(cf, "cr_send: EAGAIN after %ld bytes"),
|
DEBUGF(LOG_CF(data, cf, "cr_send: EAGAIN after %zu bytes",
|
||||||
tlswritten_total);
|
tlswritten_total));
|
||||||
*err = CURLE_AGAIN;
|
*err = CURLE_AGAIN;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -299,7 +299,7 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
*err = CURLE_WRITE_ERROR;
|
*err = CURLE_WRITE_ERROR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
infof(data, CFMSG(cf, "cr_send: wrote %ld TLS bytes"), tlswritten);
|
DEBUGF(LOG_CF(data, cf, "cr_send: wrote %zu TLS bytes", tlswritten));
|
||||||
tlswritten_total += tlswritten;
|
tlswritten_total += tlswritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -137,14 +137,6 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
|
||||||
#define DEBUG_CF 0
|
|
||||||
|
|
||||||
#if DEBUG_CF
|
|
||||||
#define CF_DEBUGF(x) x
|
|
||||||
#else
|
|
||||||
#define CF_DEBUGF(x) do { } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* From MacTypes.h (which we can't include because it isn't present in iOS: */
|
/* From MacTypes.h (which we can't include because it isn't present in iOS: */
|
||||||
#define ioErr -36
|
#define ioErr -36
|
||||||
#define paramErr -50
|
#define paramErr -50
|
||||||
@ -847,7 +839,7 @@ static OSStatus bio_cf_in_read(SSLConnectionRef connection,
|
|||||||
|
|
||||||
DEBUGASSERT(data);
|
DEBUGASSERT(data);
|
||||||
nread = Curl_conn_cf_recv(cf->next, data, buf, *dataLength, &result);
|
nread = Curl_conn_cf_recv(cf->next, data, buf, *dataLength, &result);
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "bio_read(len=%zu) -> %zd, result=%d"),
|
DEBUGF(LOG_CF(data, cf, "bio_read(len=%zu) -> %zd, result=%d",
|
||||||
*dataLength, nread, result));
|
*dataLength, nread, result));
|
||||||
if(nread < 0) {
|
if(nread < 0) {
|
||||||
switch(result) {
|
switch(result) {
|
||||||
@ -883,7 +875,7 @@ static OSStatus bio_cf_out_write(SSLConnectionRef connection,
|
|||||||
|
|
||||||
DEBUGASSERT(data);
|
DEBUGASSERT(data);
|
||||||
nwritten = Curl_conn_cf_send(cf->next, data, buf, *dataLength, &result);
|
nwritten = Curl_conn_cf_send(cf->next, data, buf, *dataLength, &result);
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "bio_send(len=%zu) -> %zd, result=%d"),
|
DEBUGF(LOG_CF(data, cf, "bio_send(len=%zu) -> %zd, result=%d",
|
||||||
*dataLength, nwritten, result));
|
*dataLength, nwritten, result));
|
||||||
if(nwritten <= 0) {
|
if(nwritten <= 0) {
|
||||||
if(result == CURLE_AGAIN) {
|
if(result == CURLE_AGAIN) {
|
||||||
@ -1657,7 +1649,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
|
|||||||
|
|
||||||
DEBUGASSERT(backend);
|
DEBUGASSERT(backend);
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "connect_step1")));
|
DEBUGF(LOG_CF(data, cf, "connect_step1"));
|
||||||
GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
|
GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
|
||||||
#endif /* CURL_BUILD_MAC */
|
#endif /* CURL_BUILD_MAC */
|
||||||
|
|
||||||
@ -2307,7 +2299,7 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
|
|||||||
/* This is not a PEM file, probably a certificate in DER format. */
|
/* This is not a PEM file, probably a certificate in DER format. */
|
||||||
rc = append_cert_to_array(data, certbuf, buflen, array);
|
rc = append_cert_to_array(data, certbuf, buflen, array);
|
||||||
if(rc != CURLE_OK) {
|
if(rc != CURLE_OK) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "append_cert for CA failed")));
|
DEBUGF(LOG_CF(data, cf, "append_cert for CA failed"));
|
||||||
result = rc;
|
result = rc;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -2321,7 +2313,7 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
|
|||||||
rc = append_cert_to_array(data, der, derlen, array);
|
rc = append_cert_to_array(data, der, derlen, array);
|
||||||
free(der);
|
free(der);
|
||||||
if(rc != CURLE_OK) {
|
if(rc != CURLE_OK) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "append_cert for CA failed")));
|
DEBUGF(LOG_CF(data, cf, "append_cert for CA failed"));
|
||||||
result = rc;
|
result = rc;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -2337,7 +2329,7 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "setting %d trust anchors"), n));
|
DEBUGF(LOG_CF(data, cf, "setting %d trust anchors", n));
|
||||||
ret = SecTrustSetAnchorCertificates(trust, array);
|
ret = SecTrustSetAnchorCertificates(trust, array);
|
||||||
if(ret != noErr) {
|
if(ret != noErr) {
|
||||||
failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
|
failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
|
||||||
@ -2359,11 +2351,11 @@ static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
|
|||||||
switch(trust_eval) {
|
switch(trust_eval) {
|
||||||
case kSecTrustResultUnspecified:
|
case kSecTrustResultUnspecified:
|
||||||
/* what does this really mean? */
|
/* what does this really mean? */
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "trust result: Unspecified")));
|
DEBUGF(LOG_CF(data, cf, "trust result: Unspecified"));
|
||||||
result = CURLE_OK;
|
result = CURLE_OK;
|
||||||
goto out;
|
goto out;
|
||||||
case kSecTrustResultProceed:
|
case kSecTrustResultProceed:
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "trust result: Proceed")));
|
DEBUGF(LOG_CF(data, cf, "trust result: Proceed"));
|
||||||
result = CURLE_OK;
|
result = CURLE_OK;
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -2396,7 +2388,7 @@ static CURLcode verify_cert(struct Curl_cfilter *cf,
|
|||||||
size_t buflen;
|
size_t buflen;
|
||||||
|
|
||||||
if(ca_info_blob) {
|
if(ca_info_blob) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "verify_peer, CA from config blob")));
|
DEBUGF(LOG_CF(data, cf, "verify_peer, CA from config blob"));
|
||||||
certbuf = (unsigned char *)malloc(ca_info_blob->len + 1);
|
certbuf = (unsigned char *)malloc(ca_info_blob->len + 1);
|
||||||
if(!certbuf) {
|
if(!certbuf) {
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
@ -2406,8 +2398,7 @@ static CURLcode verify_cert(struct Curl_cfilter *cf,
|
|||||||
certbuf[ca_info_blob->len]='\0';
|
certbuf[ca_info_blob->len]='\0';
|
||||||
}
|
}
|
||||||
else if(cafile) {
|
else if(cafile) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "verify_peer, CA from file '%s'"),
|
DEBUGF(LOG_CF(data, cf, "verify_peer, CA from file '%s'", cafile));
|
||||||
cafile));
|
|
||||||
if(read_cert(cafile, &certbuf, &buflen) < 0) {
|
if(read_cert(cafile, &certbuf, &buflen) < 0) {
|
||||||
failf(data, "SSL: failed to read or invalid CA certificate");
|
failf(data, "SSL: failed to read or invalid CA certificate");
|
||||||
return CURLE_SSL_CACERT_BADFILE;
|
return CURLE_SSL_CACERT_BADFILE;
|
||||||
@ -2543,7 +2534,7 @@ static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
|
|||||||
|| ssl_connect_2_reading == connssl->connecting_state
|
|| ssl_connect_2_reading == connssl->connecting_state
|
||||||
|| ssl_connect_2_writing == connssl->connecting_state);
|
|| ssl_connect_2_writing == connssl->connecting_state);
|
||||||
DEBUGASSERT(backend);
|
DEBUGASSERT(backend);
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "connect_step2")));
|
DEBUGF(LOG_CF(data, cf, "connect_step2"));
|
||||||
|
|
||||||
/* Here goes nothing: */
|
/* Here goes nothing: */
|
||||||
check_handshake:
|
check_handshake:
|
||||||
@ -3008,7 +2999,7 @@ static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf,
|
|||||||
{
|
{
|
||||||
struct ssl_connect_data *connssl = cf->ctx;
|
struct ssl_connect_data *connssl = cf->ctx;
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "connect_step3")));
|
DEBUGF(LOG_CF(data, cf, "connect_step3"));
|
||||||
/* There is no step 3!
|
/* There is no step 3!
|
||||||
* Well, okay, let's collect server certificates, and if verbose mode is on,
|
* Well, okay, let's collect server certificates, and if verbose mode is on,
|
||||||
* let's print the details of the server certificates. */
|
* let's print the details of the server certificates. */
|
||||||
@ -3117,7 +3108,7 @@ sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(ssl_connect_done == connssl->connecting_state) {
|
if(ssl_connect_done == connssl->connecting_state) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "connected")));
|
DEBUGF(LOG_CF(data, cf, "connected"));
|
||||||
connssl->state = ssl_connection_complete;
|
connssl->state = ssl_connection_complete;
|
||||||
*done = TRUE;
|
*done = TRUE;
|
||||||
}
|
}
|
||||||
@ -3163,7 +3154,7 @@ static void sectransp_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||||||
DEBUGASSERT(backend);
|
DEBUGASSERT(backend);
|
||||||
|
|
||||||
if(backend->ssl_ctx) {
|
if(backend->ssl_ctx) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "close")));
|
DEBUGF(LOG_CF(data, cf, "close"));
|
||||||
(void)SSLClose(backend->ssl_ctx);
|
(void)SSLClose(backend->ssl_ctx);
|
||||||
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
||||||
if(SSLCreateContext)
|
if(SSLCreateContext)
|
||||||
@ -3207,7 +3198,7 @@ static int sectransp_shutdown(struct Curl_cfilter *cf,
|
|||||||
|
|
||||||
what = SOCKET_READABLE(cf->conn->sock[cf->sockindex], SSL_SHUTDOWN_TIMEOUT);
|
what = SOCKET_READABLE(cf->conn->sock[cf->sockindex], SSL_SHUTDOWN_TIMEOUT);
|
||||||
|
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "shutdown")));
|
DEBUGF(LOG_CF(data, cf, "shutdown"));
|
||||||
while(loop--) {
|
while(loop--) {
|
||||||
if(what < 0) {
|
if(what < 0) {
|
||||||
/* anything that gets here is fatally bad */
|
/* anything that gets here is fatally bad */
|
||||||
@ -3276,7 +3267,7 @@ static int sectransp_check_cxn(struct Curl_cfilter *cf,
|
|||||||
DEBUGASSERT(backend);
|
DEBUGASSERT(backend);
|
||||||
|
|
||||||
if(backend->ssl_ctx) {
|
if(backend->ssl_ctx) {
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "check connection")));
|
DEBUGF(LOG_CF(data, cf, "check connection"));
|
||||||
err = SSLGetSessionState(backend->ssl_ctx, &state);
|
err = SSLGetSessionState(backend->ssl_ctx, &state);
|
||||||
if(err == noErr)
|
if(err == noErr)
|
||||||
return state == kSSLConnected || state == kSSLHandshake;
|
return state == kSSLConnected || state == kSSLHandshake;
|
||||||
@ -3297,7 +3288,7 @@ static bool sectransp_data_pending(struct Curl_cfilter *cf,
|
|||||||
DEBUGASSERT(backend);
|
DEBUGASSERT(backend);
|
||||||
|
|
||||||
if(backend->ssl_ctx) { /* SSL is in use */
|
if(backend->ssl_ctx) { /* SSL is in use */
|
||||||
CF_DEBUGF(infof(data, CFMSG(cf, "data_pending")));
|
DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data_pending"));
|
||||||
err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
|
err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
|
||||||
if(err == noErr)
|
if(err == noErr)
|
||||||
return buffer > 0UL;
|
return buffer > 0UL;
|
||||||
|
|||||||
@ -73,6 +73,7 @@
|
|||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
|
||||||
/* convenience macro to check if this handle is using a shared SSL session */
|
/* convenience macro to check if this handle is using a shared SSL session */
|
||||||
#define SSLSESSION_SHARED(data) (data->share && \
|
#define SSLSESSION_SHARED(data) (data->share && \
|
||||||
(data->share->specifier & \
|
(data->share->specifier & \
|
||||||
@ -1611,9 +1612,10 @@ static bool cf_ssl_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||||||
return Curl_ssl->check_cxn(cf, data) != 0;
|
return Curl_ssl->check_cxn(cf, data) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct Curl_cftype cft_ssl = {
|
struct Curl_cftype Curl_cft_ssl = {
|
||||||
"SSL",
|
"SSL",
|
||||||
CF_TYPE_SSL,
|
CF_TYPE_SSL,
|
||||||
|
CURL_LOG_DEFAULT,
|
||||||
ssl_cf_destroy,
|
ssl_cf_destroy,
|
||||||
ssl_cf_connect,
|
ssl_cf_connect,
|
||||||
ssl_cf_close,
|
ssl_cf_close,
|
||||||
@ -1628,9 +1630,10 @@ static const struct Curl_cftype cft_ssl = {
|
|||||||
Curl_cf_def_query,
|
Curl_cf_def_query,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct Curl_cftype cft_ssl_proxy = {
|
struct Curl_cftype Curl_cft_ssl_proxy = {
|
||||||
"SSL-PROXY",
|
"SSL-PROXY",
|
||||||
CF_TYPE_SSL,
|
CF_TYPE_SSL,
|
||||||
|
CURL_LOG_DEFAULT,
|
||||||
ssl_cf_destroy,
|
ssl_cf_destroy,
|
||||||
ssl_cf_connect,
|
ssl_cf_connect,
|
||||||
ssl_cf_close,
|
ssl_cf_close,
|
||||||
@ -1659,7 +1662,7 @@ static CURLcode cf_ssl_create(struct Curl_cfilter **pcf,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_ssl, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_ssl, ctx);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if(result)
|
if(result)
|
||||||
@ -1707,7 +1710,7 @@ static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Curl_cf_create(&cf, &cft_ssl_proxy, ctx);
|
result = Curl_cf_create(&cf, &Curl_cft_ssl_proxy, ctx);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if(result)
|
if(result)
|
||||||
@ -1775,7 +1778,7 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
|
|||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
for(; cf; cf = cf->next) {
|
for(; cf; cf = cf->next) {
|
||||||
if(cf->cft == &cft_ssl) {
|
if(cf->cft == &Curl_cft_ssl) {
|
||||||
if(Curl_ssl->shut_down(cf, data))
|
if(Curl_ssl->shut_down(cf, data))
|
||||||
result = CURLE_SSL_SHUTDOWN_FAILED;
|
result = CURLE_SSL_SHUTDOWN_FAILED;
|
||||||
Curl_conn_cf_discard(cf, data);
|
Curl_conn_cf_discard(cf, data);
|
||||||
@ -1791,7 +1794,7 @@ static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn,
|
|||||||
struct Curl_cfilter *cf, *lowest_ssl_cf = NULL;
|
struct Curl_cfilter *cf, *lowest_ssl_cf = NULL;
|
||||||
|
|
||||||
for(cf = conn->cfilter[sockindex]; cf; cf = cf->next) {
|
for(cf = conn->cfilter[sockindex]; cf; cf = cf->next) {
|
||||||
if(cf->cft == &cft_ssl || cf->cft == &cft_ssl_proxy) {
|
if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) {
|
||||||
lowest_ssl_cf = cf;
|
lowest_ssl_cf = cf;
|
||||||
if(cf->connected || (cf->next && cf->next->connected)) {
|
if(cf->connected || (cf->next && cf->next->connected)) {
|
||||||
/* connected or about to start */
|
/* connected or about to start */
|
||||||
@ -1804,7 +1807,7 @@ static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn,
|
|||||||
|
|
||||||
bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
|
bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
|
||||||
{
|
{
|
||||||
return (cf->cft == &cft_ssl_proxy);
|
return (cf->cft == &Curl_cft_ssl_proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ssl_config_data *
|
struct ssl_config_data *
|
||||||
@ -1856,7 +1859,7 @@ Curl_ssl_get_primary_config(struct Curl_easy *data,
|
|||||||
struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf)
|
struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf)
|
||||||
{
|
{
|
||||||
for(; cf; cf = cf->next) {
|
for(; cf; cf = cf->next) {
|
||||||
if(cf->cft == &cft_ssl || cf->cft == &cft_ssl_proxy)
|
if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy)
|
||||||
return cf;
|
return cf;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@ -215,6 +215,9 @@ bool Curl_ssl_supports(struct Curl_easy *data, int ssl_option);
|
|||||||
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
|
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
|
||||||
CURLINFO info, int n);
|
CURLINFO info, int n);
|
||||||
|
|
||||||
|
extern struct Curl_cftype Curl_cft_ssl;
|
||||||
|
extern struct Curl_cftype Curl_cft_ssl_proxy;
|
||||||
|
|
||||||
#else /* if not USE_SSL */
|
#else /* if not USE_SSL */
|
||||||
|
|
||||||
/* When SSL support is not present, just define away these function calls */
|
/* When SSL support is not present, just define away these function calls */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user