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:
Stefan Eissing 2023-01-11 10:30:42 +01:00 committed by Daniel Stenberg
parent 5cf5bfcd13
commit db91dbbf2c
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
29 changed files with 656 additions and 466 deletions

View File

@ -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 \

View File

@ -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,

View File

@ -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 */

View File

@ -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;
} }

View File

@ -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 */

View File

@ -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;

View File

@ -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
View 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
View 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 */

View File

@ -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;

View File

@ -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));

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}
}
}
}

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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"

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;
} }

View File

@ -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)) {

View File

@ -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;
} }

View File

@ -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;

View File

@ -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;

View File

@ -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 */