From 63baa10951ebe9dd04520ee5f6eb7b119ba176cb Mon Sep 17 00:00:00 2001 From: Arnav-Purushotam-CUBoulder Date: Tue, 13 Jan 2026 15:12:42 -0700 Subject: [PATCH 1/4] docs/INSTALL: update configure details Note the default libpsl requirement in INSTALL and polish the TLS library wording. Closes #20301 --- docs/INSTALL.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index bb026486d17f..df9095df7f38 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -46,6 +46,9 @@ unpacked the source archive): (Adjust the configure line accordingly to use the TLS library you want.) +By default curl builds with libpsl (Public Suffix List) support. If libpsl is +not available on your system, install it or disable it with `--without-libpsl`. + You probably need to be root when doing the last command. Get a full listing of all available configure options by invoking it like: @@ -65,10 +68,9 @@ your own home directory: make make install -The configure script always tries to find a working SSL library unless -explicitly told not to. If you have OpenSSL installed in the default search -path for your compiler/linker, you do not need to do anything special. If you -have OpenSSL installed in `/usr/local/ssl`, you can run configure like: +The configure script requires you to select a TLS backend explicitly unless +you disable TLS with `--without-ssl`. If you have OpenSSL installed in the +default search path for your compiler/linker, you can run configure like: ./configure --with-openssl @@ -91,7 +93,7 @@ header files somewhere else, you have to set the `LDFLAGS` and `CPPFLAGS` environment variables prior to running configure. Something like this should work: - CPPFLAGS="-I/path/to/ssl/include" LDFLAGS="-L/path/to/ssl/lib" ./configure + CPPFLAGS="-I/path/to/ssl/include" LDFLAGS="-L/path/to/ssl/lib" ./configure --with-openssl If you have shared SSL libs installed in a directory where your runtime linker does not find them (which usually causes configure failures), you can From 8edc0338f30f458f812f9ea355de1240771fa343 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 19 Jan 2026 00:15:41 +0100 Subject: [PATCH 2/4] lib: separate scheme info from protocol implementation This allows builds know about all schemes - but only have the protocol implementations for those actually built-in. It further allows multiple protocols to reuse the same protocol setup and functions for both TLS and non-TLS implementations instead of needing two (or more) structs. The scheme information is now in 'struct Curl_scheme' and all the function pointers for each scheme/protocol implementation are in struct Curl_protocol. The URL API now always work with all known protocols. Closes #20351 --- lib/cf-h1-proxy.c | 4 +- lib/cf-ip-happy.c | 2 +- lib/cf-socket.c | 2 +- lib/cfilters.c | 2 +- lib/connect.c | 6 +- lib/cookie.c | 2 +- lib/cshutdn.c | 4 +- lib/curl_ldap.h | 12 +- lib/curl_rtmp.c | 165 +++++++------------- lib/curl_rtmp.h | 13 +- lib/cw-out.c | 2 +- lib/dict.c | 29 ++-- lib/dict.h | 4 +- lib/doh.c | 2 +- lib/file.c | 30 ++-- lib/file.h | 4 +- lib/ftp.c | 57 ++++--- lib/ftp.h | 9 +- lib/gopher.c | 44 ++++-- lib/gopher.h | 8 +- lib/headers.c | 2 +- lib/http.c | 78 +++++----- lib/http.h | 8 +- lib/imap.c | 62 ++++---- lib/imap.h | 4 +- lib/ldap.c | 67 ++++---- lib/mqtt.c | 51 ++++-- lib/mqtt.h | 8 +- lib/multi.c | 68 ++++---- lib/openldap.c | 43 +----- lib/pop3.c | 61 ++++---- lib/pop3.h | 4 +- lib/rtsp.c | 27 +++- lib/rtsp.h | 2 +- lib/sendf.c | 2 +- lib/setopt.c | 4 +- lib/smb.c | 56 ++++--- lib/smb.h | 9 +- lib/smtp.c | 59 ++++--- lib/smtp.h | 4 +- lib/telnet.c | 27 +++- lib/telnet.h | 4 +- lib/tftp.c | 25 ++- lib/tftp.h | 4 +- lib/transfer.c | 20 +-- lib/url.c | 352 ++++++++++++------------------------------ lib/url.h | 5 +- lib/urlapi.c | 22 +-- lib/urldata.h | 17 +- lib/vauth/vauth.c | 2 +- lib/vquic/vquic.c | 2 +- lib/vssh/libssh.c | 26 +--- lib/vssh/libssh2.c | 24 +-- lib/vssh/ssh.h | 13 +- lib/vssh/vssh.c | 39 ++++- lib/vssh/vssh.h | 6 +- lib/ws.c | 77 ++++----- lib/ws.h | 8 +- scripts/schemetable.c | 116 ++++++-------- 59 files changed, 800 insertions(+), 1009 deletions(-) diff --git a/lib/cf-h1-proxy.c b/lib/cf-h1-proxy.c index c41a68dee1d1..fcf2b70ed706 100644 --- a/lib/cf-h1-proxy.c +++ b/lib/cf-h1-proxy.c @@ -106,8 +106,8 @@ static CURLcode tunnel_init(struct Curl_cfilter *cf, { struct h1_tunnel_state *ts; - if(cf->conn->handler->flags & PROTOPT_NOTCPPROXY) { - failf(data, "%s cannot be done over CONNECT", cf->conn->handler->scheme); + if(cf->conn->scheme->flags & PROTOPT_NOTCPPROXY) { + failf(data, "%s cannot be done over CONNECT", cf->conn->scheme->name); return CURLE_UNSUPPORTED_PROTOCOL; } diff --git a/lib/cf-ip-happy.c b/lib/cf-ip-happy.c index a802ddacb42b..8db8c15b9f5b 100644 --- a/lib/cf-ip-happy.c +++ b/lib/cf-ip-happy.c @@ -793,7 +793,7 @@ static CURLcode cf_ip_happy_connect(struct Curl_cfilter *cf, cf_ip_happy_ctx_clear(cf, data); Curl_expire_done(data, EXPIRE_HAPPY_EYEBALLS); - if(cf->conn->handler->protocol & PROTO_FAMILY_SSH) + if(cf->conn->scheme->protocol & PROTO_FAMILY_SSH) Curl_pgrsTime(data, TIMER_APPCONNECT); /* we are connected already */ #ifndef CURL_DISABLE_VERBOSE_STRINGS if(Curl_trc_cf_is_verbose(cf, data)) { diff --git a/lib/cf-socket.c b/lib/cf-socket.c index 837f72e9af59..17b1a478700d 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -993,7 +993,7 @@ static void set_local_ip(struct Curl_cfilter *cf, #ifdef HAVE_GETSOCKNAME if((ctx->sock != CURL_SOCKET_BAD) && - !(data->conn->handler->protocol & CURLPROTO_TFTP)) { + !(data->conn->scheme->protocol & CURLPROTO_TFTP)) { /* TFTP does not connect, so it cannot get the IP like this */ char buffer[STRERROR_LEN]; diff --git a/lib/cfilters.c b/lib/cfilters.c index c6aa06a3b87e..47c05c87a29a 100644 --- a/lib/cfilters.c +++ b/lib/cfilters.c @@ -611,7 +611,7 @@ bool Curl_conn_is_connected(struct connectdata *conn, int sockindex) cf = conn->cfilter[sockindex]; if(cf) return (bool)cf->connected; - else if(conn->handler->flags & PROTOPT_NONETWORK) + else if(conn->scheme->flags & PROTOPT_NONETWORK) return TRUE; return FALSE; } diff --git a/lib/connect.c b/lib/connect.c index c832f8608609..a13405450bb1 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -428,7 +428,7 @@ static CURLcode cf_setup_connect(struct Curl_cfilter *cf, #ifdef USE_SSL if((ctx->ssl_mode == CURL_CF_SSL_ENABLE || (ctx->ssl_mode != CURL_CF_SSL_DISABLE && - cf->conn->handler->flags & PROTOPT_SSL)) /* we want SSL */ + cf->conn->scheme->flags & PROTOPT_SSL)) /* we want SSL */ && !Curl_conn_is_ssl(cf->conn, cf->sockindex)) { /* it is missing */ result = Curl_cf_ssl_insert_after(cf, data); if(result) @@ -563,7 +563,7 @@ CURLcode Curl_conn_setup(struct Curl_easy *data, CURLcode result = CURLE_OK; DEBUGASSERT(data); - DEBUGASSERT(conn->handler); + DEBUGASSERT(conn->scheme); DEBUGASSERT(dns); Curl_resolv_unlink(data, &data->state.dns[sockindex]); @@ -571,7 +571,7 @@ CURLcode Curl_conn_setup(struct Curl_easy *data, #ifndef CURL_DISABLE_HTTP if(!conn->cfilter[sockindex] && - conn->handler->protocol == CURLPROTO_HTTPS) { + conn->scheme->protocol == CURLPROTO_HTTPS) { DEBUGASSERT(ssl_mode != CURL_CF_SSL_DISABLE); result = Curl_cf_https_setup(data, conn, sockindex); if(result) diff --git a/lib/cookie.c b/lib/cookie.c index e385f6e9e993..2c57226dc5cb 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -1234,7 +1234,7 @@ static int cookie_sort_ct(const void *p1, const void *p2) bool Curl_secure_context(struct connectdata *conn, const char *host) { - return conn->handler->protocol & (CURLPROTO_HTTPS | CURLPROTO_WSS) || + return conn->scheme->protocol & (CURLPROTO_HTTPS | CURLPROTO_WSS) || curl_strequal("localhost", host) || !strcmp(host, "127.0.0.1") || !strcmp(host, "::1"); diff --git a/lib/cshutdn.c b/lib/cshutdn.c index 7de6c07b289e..1bd62346f3b1 100644 --- a/lib/cshutdn.c +++ b/lib/cshutdn.c @@ -43,7 +43,7 @@ static void cshutdn_run_conn_handler(struct Curl_easy *data, { if(!conn->bits.shutdown_handler) { - if(conn->handler && conn->handler->disconnect) { + if(conn->scheme && conn->scheme->run->disconnect) { /* Some disconnect handlers do a blocking wait on server responses. * FTP/IMAP/SMTP and SFTP are among them. When using the internal * handle, set an overall short timeout so we do not hang for the @@ -59,7 +59,7 @@ static void cshutdn_run_conn_handler(struct Curl_easy *data, conn->connection_id, conn->bits.aborted)); /* There are protocol handlers that block on retrieving * server responses here (FTP). Set a short timeout. */ - conn->handler->disconnect(data, conn, (bool)conn->bits.aborted); + conn->scheme->run->disconnect(data, conn, (bool)conn->bits.aborted); } conn->bits.shutdown_handler = TRUE; diff --git a/lib/curl_ldap.h b/lib/curl_ldap.h index 5ef32a5a30ae..7c1e1c4e9a96 100644 --- a/lib/curl_ldap.h +++ b/lib/curl_ldap.h @@ -23,15 +23,11 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#ifndef CURL_DISABLE_LDAP -extern const struct Curl_handler Curl_handler_ldap; +extern const struct Curl_protocol Curl_protocol_ldap; -#if !defined(CURL_DISABLE_LDAPS) && \ - ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ - (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) -extern const struct Curl_handler Curl_handler_ldaps; -#endif +extern const struct Curl_scheme Curl_scheme_ldap; +extern const struct Curl_scheme Curl_scheme_ldaps; void Curl_ldap_version(char *buf, size_t bufsz); -#endif + #endif /* HEADER_CURL_LDAP_H */ diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c index 245ce04f6e8c..75b80913d8b9 100644 --- a/lib/curl_rtmp.c +++ b/lib/curl_rtmp.c @@ -24,10 +24,11 @@ ***************************************************************************/ #include "curl_setup.h" -#ifdef USE_LIBRTMP - #include "curl_rtmp.h" #include "urldata.h" + +#ifdef USE_LIBRTMP + #include "url.h" #include "curlx/nonblock.h" #include "progress.h" /* for Curl_pgrsSetUploadSize */ @@ -224,8 +225,7 @@ void Curl_rtmp_version(char *version, size_t len) * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu/ */ -const struct Curl_handler Curl_handler_rtmp = { - "rtmp", /* scheme */ +static const struct Curl_protocol Curl_protocol_rtmp = { rtmp_setup_connection, /* setup_connection */ rtmp_do, /* do_it */ rtmp_done, /* done */ @@ -243,135 +243,84 @@ const struct Curl_handler Curl_handler_rtmp = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_RTMP, /* defport */ +}; + +#endif /* USE_LIBRTMP */ + +const struct Curl_scheme Curl_scheme_rtmp = { + "rtmp", /* scheme */ +#ifndef USE_LIBRTMP + ZERO_NULL, +#else + &Curl_protocol_rtmp, +#endif CURLPROTO_RTMP, /* protocol */ CURLPROTO_RTMP, /* family */ - PROTOPT_NONE /* flags */ + PROTOPT_NONE, /* flags */ + PORT_RTMP, /* defport */ }; -const struct Curl_handler Curl_handler_rtmpt = { +const struct Curl_scheme Curl_scheme_rtmpt = { "rtmpt", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMPT, /* defport */ +#ifndef USE_LIBRTMP + ZERO_NULL, +#else + &Curl_protocol_rtmp, +#endif CURLPROTO_RTMPT, /* protocol */ CURLPROTO_RTMPT, /* family */ - PROTOPT_NONE /* flags */ + PROTOPT_NONE, /* flags */ + PORT_RTMPT, /* defport */ }; -const struct Curl_handler Curl_handler_rtmpe = { +const struct Curl_scheme Curl_scheme_rtmpe = { "rtmpe", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMP, /* defport */ +#ifndef USE_LIBRTMP + ZERO_NULL, +#else + &Curl_protocol_rtmp, +#endif CURLPROTO_RTMPE, /* protocol */ CURLPROTO_RTMPE, /* family */ - PROTOPT_NONE /* flags */ + PROTOPT_NONE, /* flags */ + PORT_RTMP, /* defport */ }; -const struct Curl_handler Curl_handler_rtmpte = { +const struct Curl_scheme Curl_scheme_rtmpte = { "rtmpte", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMPT, /* defport */ +#ifndef USE_LIBRTMP + ZERO_NULL, +#else + &Curl_protocol_rtmp, +#endif CURLPROTO_RTMPTE, /* protocol */ CURLPROTO_RTMPTE, /* family */ - PROTOPT_NONE /* flags */ + PROTOPT_NONE, /* flags */ + PORT_RTMPT, /* defport */ }; -const struct Curl_handler Curl_handler_rtmps = { +const struct Curl_scheme Curl_scheme_rtmps = { "rtmps", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMPS, /* defport */ +#ifndef USE_LIBRTMP + ZERO_NULL, +#else + &Curl_protocol_rtmp, +#endif CURLPROTO_RTMPS, /* protocol */ CURLPROTO_RTMP, /* family */ - PROTOPT_NONE /* flags */ + PROTOPT_NONE, /* flags */ + PORT_RTMPS, /* defport */ }; -const struct Curl_handler Curl_handler_rtmpts = { +const struct Curl_scheme Curl_scheme_rtmpts = { "rtmpts", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMPS, /* defport */ +#ifndef USE_LIBRTMP + ZERO_NULL, +#else + &Curl_protocol_rtmp, +#endif CURLPROTO_RTMPTS, /* protocol */ CURLPROTO_RTMPT, /* family */ - PROTOPT_NONE /* flags */ + PROTOPT_NONE, /* flags */ + PORT_RTMPS, /* defport */ }; - -#endif /* USE_LIBRTMP */ diff --git a/lib/curl_rtmp.h b/lib/curl_rtmp.h index 339d3a4384de..e57d20c33a83 100644 --- a/lib/curl_rtmp.h +++ b/lib/curl_rtmp.h @@ -23,14 +23,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ +extern const struct Curl_scheme Curl_scheme_rtmp; +extern const struct Curl_scheme Curl_scheme_rtmpt; +extern const struct Curl_scheme Curl_scheme_rtmpe; +extern const struct Curl_scheme Curl_scheme_rtmpte; +extern const struct Curl_scheme Curl_scheme_rtmps; +extern const struct Curl_scheme Curl_scheme_rtmpts; #ifdef USE_LIBRTMP -extern const struct Curl_handler Curl_handler_rtmp; -extern const struct Curl_handler Curl_handler_rtmpt; -extern const struct Curl_handler Curl_handler_rtmpe; -extern const struct Curl_handler Curl_handler_rtmpte; -extern const struct Curl_handler Curl_handler_rtmps; -extern const struct Curl_handler Curl_handler_rtmpts; - void Curl_rtmp_version(char *version, size_t len); #endif diff --git a/lib/cw-out.c b/lib/cw-out.c index 3936cf0276b3..88abbb7758f4 100644 --- a/lib/cw-out.c +++ b/lib/cw-out.c @@ -191,7 +191,7 @@ static CURLcode cw_out_cb_write(struct cw_out_ctx *ctx, blen, (otype == CW_OUT_HDS) ? "header" : "body", nwritten); if(CURL_WRITEFUNC_PAUSE == nwritten) { - if(data->conn->handler->flags & PROTOPT_NONETWORK) { + if(data->conn->scheme->flags & PROTOPT_NONETWORK) { /* Protocols that work without network cannot be paused. This is actually only FILE:// just now, and it cannot pause since the transfer is not done using the "normal" procedure. */ diff --git a/lib/dict.c b/lib/dict.c index 54563b4e4514..fcdea918cf2b 100644 --- a/lib/dict.c +++ b/lib/dict.c @@ -22,6 +22,8 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" +#include "dict.h" #ifndef CURL_DISABLE_DICT @@ -51,11 +53,9 @@ #include #endif -#include "urldata.h" #include "transfer.h" #include "curl_trc.h" #include "escape.h" -#include "dict.h" #define DICT_MATCH "/MATCH:" #define DICT_MATCH2 "/M:" @@ -273,10 +273,9 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) } /* - * DICT protocol handler. + * DICT protocol */ -const struct Curl_handler Curl_handler_dict = { - "dict", /* scheme */ +static const struct Curl_protocol Curl_protocol_dict = { ZERO_NULL, /* setup_connection */ dict_do, /* do_it */ ZERO_NULL, /* done */ @@ -294,10 +293,22 @@ const struct Curl_handler Curl_handler_dict = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_DICT, /* defport */ - CURLPROTO_DICT, /* protocol */ - CURLPROTO_DICT, /* family */ - PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ }; #endif /* CURL_DISABLE_DICT */ + +/* + * DICT protocol handler. + */ +const struct Curl_scheme Curl_scheme_dict = { + "dict", /* scheme */ +#ifdef CURL_DISABLE_DICT + ZERO_NULL, +#else + &Curl_protocol_dict, +#endif + CURLPROTO_DICT, /* protocol */ + CURLPROTO_DICT, /* family */ + PROTOPT_NONE | PROTOPT_NOURLQUERY, /* flags */ + PORT_DICT, /* defport */ +}; diff --git a/lib/dict.h b/lib/dict.h index 4025c8bcdd06..b5d6947d2386 100644 --- a/lib/dict.h +++ b/lib/dict.h @@ -23,8 +23,6 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#ifndef CURL_DISABLE_DICT -extern const struct Curl_handler Curl_handler_dict; -#endif +extern const struct Curl_scheme Curl_scheme_dict; #endif /* HEADER_CURL_DICT_H */ diff --git a/lib/doh.c b/lib/doh.c index faf38d7adc1e..34801c266775 100644 --- a/lib/doh.c +++ b/lib/doh.c @@ -495,7 +495,7 @@ CURLcode Curl_doh(struct Curl_easy *data, const char *hostname, #endif #ifdef USE_HTTPSRR - if(conn->handler->protocol & PROTO_FAMILY_HTTP) { + if(conn->scheme->protocol & PROTO_FAMILY_HTTP) { /* Only use HTTPS RR for HTTP(S) transfers */ char *qname = NULL; if(port != PORT_HTTPS) { diff --git a/lib/file.c b/lib/file.c index ef4fc8042f81..753aed2dbe30 100644 --- a/lib/file.c +++ b/lib/file.c @@ -22,6 +22,8 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" +#include "file.h" #ifndef CURL_DISABLE_FILE @@ -53,12 +55,10 @@ #include #endif -#include "urldata.h" #include "progress.h" #include "sendf.h" #include "curl_trc.h" #include "escape.h" -#include "file.h" #include "multiif.h" #include "transfer.h" #include "url.h" @@ -605,11 +605,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) return result; } -/* - * FILE scheme handler. - */ -const struct Curl_handler Curl_handler_file = { - "file", /* scheme */ +static const struct Curl_protocol Curl_protocol_file = { file_setup_connection, /* setup_connection */ file_do, /* do_it */ file_done, /* done */ @@ -627,10 +623,22 @@ const struct Curl_handler Curl_handler_file = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - 0, /* defport */ - CURLPROTO_FILE, /* protocol */ - CURLPROTO_FILE, /* family */ - PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */ }; #endif + +/* + * FILE scheme handler. + */ +const struct Curl_scheme Curl_scheme_file = { + "file", /* scheme */ +#ifdef CURL_DISABLE_FILE + ZERO_NULL, +#else + &Curl_protocol_file, +#endif + CURLPROTO_FILE, /* protocol */ + CURLPROTO_FILE, /* family */ + PROTOPT_NONETWORK | PROTOPT_NOURLQUERY, /* flags */ + 0 /* defport */ +}; diff --git a/lib/file.h b/lib/file.h index cb3552d924dc..a3065441aee2 100644 --- a/lib/file.h +++ b/lib/file.h @@ -23,8 +23,6 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#ifndef CURL_DISABLE_FILE -extern const struct Curl_handler Curl_handler_file; -#endif +extern const struct Curl_scheme Curl_scheme_file; #endif /* HEADER_CURL_FILE_H */ diff --git a/lib/ftp.c b/lib/ftp.c index 42ac5f5c74b4..fa08b3d5c6c1 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -22,6 +22,7 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" #ifndef CURL_DISABLE_FTP @@ -39,7 +40,6 @@ #include #endif -#include "urldata.h" #include "sendf.h" #include "curl_addrinfo.h" #include "curl_trc.h" @@ -4340,10 +4340,9 @@ bool ftp_conns_match(struct connectdata *needle, struct connectdata *conn) } /* - * FTP protocol handler. + * FTP protocol. */ -const struct Curl_handler Curl_handler_ftp = { - "ftp", /* scheme */ +static const struct Curl_protocol Curl_protocol_ftp = { ftp_setup_connection, /* setup_connection */ ftp_do, /* do_it */ ftp_done, /* done */ @@ -4361,45 +4360,43 @@ const struct Curl_handler Curl_handler_ftp = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_FTP, /* defport */ +}; + +#endif /* CURL_DISABLE_FTP */ + +/* + * FTP protocol handler. + */ +const struct Curl_scheme Curl_scheme_ftp = { + "ftp", /* scheme */ +#ifdef CURL_DISABLE_FTP + ZERO_NULL, +#else + &Curl_protocol_ftp, +#endif CURLPROTO_FTP, /* protocol */ CURLPROTO_FTP, /* family */ PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP | PROTOPT_WILDCARD | PROTOPT_SSL_REUSE | - PROTOPT_CONN_REUSE /* flags */ + PROTOPT_CONN_REUSE, /* flags */ + PORT_FTP, /* defport */ }; -#ifdef USE_SSL /* * FTPS protocol handler. */ -const struct Curl_handler Curl_handler_ftps = { +const struct Curl_scheme Curl_scheme_ftps = { "ftps", /* scheme */ - ftp_setup_connection, /* setup_connection */ - ftp_do, /* do_it */ - ftp_done, /* done */ - ftp_do_more, /* do_more */ - ftp_connect, /* connect_it */ - ftp_multi_statemach, /* connecting */ - ftp_doing, /* doing */ - ftp_pollset, /* proto_pollset */ - ftp_pollset, /* doing_pollset */ - ftp_domore_pollset, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - ftp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_FTPS, /* defport */ +#if defined(CURL_DISABLE_FTP) || !defined(USE_SSL) + ZERO_NULL, +#else + &Curl_protocol_ftp, +#endif CURLPROTO_FTPS, /* protocol */ CURLPROTO_FTP, /* family */ PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD | - PROTOPT_CONN_REUSE /* flags */ + PROTOPT_CONN_REUSE, /* flags */ + PORT_FTPS, /* defport */ }; -#endif - -#endif /* CURL_DISABLE_FTP */ diff --git a/lib/ftp.h b/lib/ftp.h index 0e32d39832db..ef1aacb40c89 100644 --- a/lib/ftp.h +++ b/lib/ftp.h @@ -27,13 +27,10 @@ #include "pingpong.h" -#ifndef CURL_DISABLE_FTP -extern const struct Curl_handler Curl_handler_ftp; - -#ifdef USE_SSL -extern const struct Curl_handler Curl_handler_ftps; -#endif +extern const struct Curl_scheme Curl_scheme_ftp; +extern const struct Curl_scheme Curl_scheme_ftps; +#ifndef CURL_DISABLE_FTP bool ftp_conns_match(struct connectdata *needle, struct connectdata *conn); #endif /* CURL_DISABLE_FTP */ diff --git a/lib/gopher.c b/lib/gopher.c index 9d35c68f316a..3ab88ad1532d 100644 --- a/lib/gopher.c +++ b/lib/gopher.c @@ -22,16 +22,16 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" +#include "gopher.h" #ifndef CURL_DISABLE_GOPHER -#include "urldata.h" #include "transfer.h" #include "sendf.h" #include "curl_trc.h" #include "cfilters.h" #include "connect.h" -#include "gopher.h" #include "select.h" #include "url.h" #include "escape.h" @@ -172,8 +172,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done) * connect-command-download protocols. */ -const struct Curl_handler Curl_handler_gopher = { - "gopher", /* scheme */ +static const struct Curl_protocol Curl_protocol_gopher = { ZERO_NULL, /* setup_connection */ gopher_do, /* do_it */ ZERO_NULL, /* done */ @@ -191,15 +190,10 @@ const struct Curl_handler Curl_handler_gopher = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_GOPHER, /* defport */ - CURLPROTO_GOPHER, /* protocol */ - CURLPROTO_GOPHER, /* family */ - PROTOPT_NONE /* flags */ }; #ifdef USE_SSL -const struct Curl_handler Curl_handler_gophers = { - "gophers", /* scheme */ +static const struct Curl_protocol Curl_protocol_gophers = { ZERO_NULL, /* setup_connection */ gopher_do, /* do_it */ ZERO_NULL, /* done */ @@ -217,11 +211,33 @@ const struct Curl_handler Curl_handler_gophers = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_GOPHER, /* defport */ - CURLPROTO_GOPHERS, /* protocol */ - CURLPROTO_GOPHER, /* family */ - PROTOPT_SSL /* flags */ }; #endif #endif /* CURL_DISABLE_GOPHER */ + +const struct Curl_scheme Curl_scheme_gopher = { + "gopher", /* scheme */ +#ifdef CURL_DISABLE_GOPHER + ZERO_NULL, +#else + &Curl_protocol_gopher, +#endif + CURLPROTO_GOPHER, /* protocol */ + CURLPROTO_GOPHER, /* family */ + PROTOPT_NONE, /* flags */ + PORT_GOPHER, /* defport */ +}; + +const struct Curl_scheme Curl_scheme_gophers = { + "gophers", /* scheme */ +#if defined(CURL_DISABLE_GOPHER) || !defined(USE_SSL) + ZERO_NULL, +#else + &Curl_protocol_gophers, +#endif + CURLPROTO_GOPHERS, /* protocol */ + CURLPROTO_GOPHER, /* family */ + PROTOPT_SSL, /* flags */ + PORT_GOPHER, /* defport */ +}; diff --git a/lib/gopher.h b/lib/gopher.h index 1e6a5d2d30e6..bc977bc1bcc0 100644 --- a/lib/gopher.h +++ b/lib/gopher.h @@ -23,11 +23,7 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#ifndef CURL_DISABLE_GOPHER -extern const struct Curl_handler Curl_handler_gopher; -#ifdef USE_SSL -extern const struct Curl_handler Curl_handler_gophers; -#endif -#endif +extern const struct Curl_scheme Curl_scheme_gopher; +extern const struct Curl_scheme Curl_scheme_gophers; #endif /* HEADER_CURL_GOPHER_H */ diff --git a/lib/headers.c b/lib/headers.c index c1880453540c..5a6b120c962f 100644 --- a/lib/headers.c +++ b/lib/headers.c @@ -326,7 +326,7 @@ CURLcode Curl_headers_init(struct Curl_easy *data) struct Curl_cwriter *writer; CURLcode result; - if(data->conn && (data->conn->handler->protocol & PROTO_FAMILY_HTTP)) { + if(data->conn && (data->conn->scheme->protocol & PROTO_FAMILY_HTTP)) { /* avoid installing it twice */ if(Curl_cwriter_get_by_name(data, hds_cw_collect.name)) return CURLE_OK; diff --git a/lib/http.c b/lib/http.c index 4334428bec12..44e64b1d509e 100644 --- a/lib/http.c +++ b/lib/http.c @@ -22,6 +22,7 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" #ifndef CURL_DISABLE_HTTP @@ -46,7 +47,6 @@ #include #endif -#include "urldata.h" #include "transfer.h" #include "sendf.h" #include "curl_trc.h" @@ -1236,14 +1236,14 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, } else { char *scheme; - const struct Curl_handler *p; + const struct Curl_scheme *p; uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); if(uc) { curlx_free(follow_url); return Curl_uc_to_curlcode(uc); } - p = Curl_get_scheme_handler(scheme); + p = Curl_get_scheme(scheme); if(p && (p->protocol != data->info.conn_protocol)) { infof(data, "Clear auth, redirects scheme from %s to %s", data->info.conn_scheme, scheme); @@ -1930,11 +1930,11 @@ void Curl_http_method(struct Curl_easy *data, Curl_HttpReq httpreq = (Curl_HttpReq)data->state.httpreq; const char *request; #ifndef CURL_DISABLE_WEBSOCKETS - if(data->conn->handler->protocol & (CURLPROTO_WS | CURLPROTO_WSS)) + if(data->conn->scheme->protocol & (CURLPROTO_WS | CURLPROTO_WSS)) httpreq = HTTPREQ_GET; else #endif - if((data->conn->handler->protocol & (PROTO_FAMILY_HTTP | CURLPROTO_FTP)) && + if((data->conn->scheme->protocol & (PROTO_FAMILY_HTTP | CURLPROTO_FTP)) && data->state.upload) httpreq = HTTPREQ_PUT; @@ -1999,7 +1999,7 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data) return CURLE_OUT_OF_MEMORY; data->state.first_remote_port = conn->remote_port; - data->state.first_remote_protocol = conn->handler->protocol; + data->state.first_remote_protocol = conn->scheme->protocol; } Curl_safefree(aptr->host); @@ -2971,7 +2971,7 @@ static CURLcode http_add_hd(struct Curl_easy *data, result = Curl_http2_request_upgrade(req, data); } #ifndef CURL_DISABLE_WEBSOCKETS - if(!result && conn->handler->protocol & (CURLPROTO_WS | CURLPROTO_WSS)) + if(!result && conn->scheme->protocol & (CURLPROTO_WS | CURLPROTO_WSS)) result = Curl_ws_request(data, req); #endif break; @@ -3172,7 +3172,7 @@ static statusline checkprotoprefix(struct Curl_easy *data, const char *s, size_t len) { #ifndef CURL_DISABLE_RTSP - if(conn->handler->protocol & CURLPROTO_RTSP) + if(conn->scheme->protocol & CURLPROTO_RTSP) return checkrtspprefix(data, s, len); #else (void)conn; @@ -3701,7 +3701,7 @@ static CURLcode http_header(struct Curl_easy *data, if(!result) { struct connectdata *conn = data->conn; - if(conn->handler->protocol & CURLPROTO_RTSP) + if(conn->scheme->protocol & CURLPROTO_RTSP) result = Curl_rtsp_parseheader(data, hd); } return result; @@ -3993,7 +3993,7 @@ static CURLcode http_on_response(struct Curl_easy *data, if((k->size == -1) && !k->chunk && !conn->bits.close && (k->httpversion == 11) && - !(conn->handler->protocol & CURLPROTO_RTSP) && + !(conn->scheme->protocol & CURLPROTO_RTSP) && data->state.httpreq != HTTPREQ_HEAD) { /* On HTTP 1.1, when connection is not to get closed, but no Content-Length nor Transfer-Encoding chunked have been @@ -4212,7 +4212,7 @@ static CURLcode http_rw_hd(struct Curl_easy *data, bool fine_statusline = FALSE; k->httpversion = 0; /* Do not know yet */ - if(data->conn->handler->protocol & PROTO_FAMILY_HTTP) { + if(data->conn->scheme->protocol & PROTO_FAMILY_HTTP) { /* * https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2 * @@ -4279,7 +4279,7 @@ static CURLcode http_rw_hd(struct Curl_easy *data, } } } - else if(data->conn->handler->protocol & CURLPROTO_RTSP) { + else if(data->conn->scheme->protocol & CURLPROTO_RTSP) { const char *p = hd; struct Curl_str ver; curl_off_t status; @@ -4984,8 +4984,7 @@ void Curl_http_resp_free(struct http_resp *resp) /* * HTTP handler interface. */ -const struct Curl_handler Curl_handler_http = { - "http", /* scheme */ +static const struct Curl_protocol Curl_protocol_http = { Curl_http_setup_conn, /* setup_connection */ Curl_http, /* do_it */ Curl_http_done, /* done */ @@ -5003,43 +5002,40 @@ const struct Curl_handler Curl_handler_http = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ Curl_http_follow, /* follow */ - PORT_HTTP, /* defport */ +}; + +#endif /* CURL_DISABLE_HTTP */ + +/* + * HTTP handler interface. + */ +const struct Curl_scheme Curl_scheme_http = { + "http", /* scheme */ +#ifdef CURL_DISABLE_HTTP + ZERO_NULL, +#else + &Curl_protocol_http, +#endif CURLPROTO_HTTP, /* protocol */ CURLPROTO_HTTP, /* family */ PROTOPT_CREDSPERREQUEST | /* flags */ - PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE - + PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE, + PORT_HTTP, /* defport */ }; -#ifdef USE_SSL /* * HTTPS handler interface. */ -const struct Curl_handler Curl_handler_https = { +const struct Curl_scheme Curl_scheme_https = { "https", /* scheme */ - Curl_http_setup_conn, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - NULL, /* connecting */ - ZERO_NULL, /* doing */ - NULL, /* proto_pollset */ - Curl_http_doing_pollset, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - Curl_http_perform_pollset, /* perform_pollset */ - ZERO_NULL, /* disconnect */ - Curl_http_write_resp, /* write_resp */ - Curl_http_write_resp_hd, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - Curl_http_follow, /* follow */ - PORT_HTTPS, /* defport */ +#if defined(CURL_DISABLE_HTTP) || !defined(USE_SSL) + ZERO_NULL, +#else + &Curl_protocol_http, +#endif CURLPROTO_HTTPS, /* protocol */ CURLPROTO_HTTP, /* family */ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */ - PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE + PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE, + PORT_HTTPS, /* defport */ }; -#endif - -#endif /* CURL_DISABLE_HTTP */ diff --git a/lib/http.h b/lib/http.h index 89810b1757e1..c78565bb2090 100644 --- a/lib/http.h +++ b/lib/http.h @@ -53,17 +53,15 @@ typedef enum { /* bitmask of CURL_HTTP_V* values */ typedef unsigned char http_majors; +extern const struct Curl_scheme Curl_scheme_http; +extern const struct Curl_scheme Curl_scheme_https; + #ifndef CURL_DISABLE_HTTP #ifdef USE_HTTP3 #include #endif -extern const struct Curl_handler Curl_handler_http; - -#ifdef USE_SSL -extern const struct Curl_handler Curl_handler_https; -#endif struct dynhds; diff --git a/lib/imap.c b/lib/imap.c index 3a73521ac6ed..dc519e8264ef 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -35,6 +35,8 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" +#include "imap.h" #ifndef CURL_DISABLE_IMAP @@ -53,7 +55,6 @@ #endif #include "curlx/dynbuf.h" -#include "urldata.h" #include "sendf.h" #include "curl_trc.h" #include "hostip.h" @@ -61,7 +62,6 @@ #include "transfer.h" #include "escape.h" #include "pingpong.h" -#include "imap.h" #include "mime.h" #include "curlx/strparse.h" #include "strcase.h" @@ -559,7 +559,7 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data, if(result) goto out; /* Change the connection handler */ - conn->handler = &Curl_handler_imaps; + conn->scheme = &Curl_scheme_imaps; } DEBUGASSERT(!imapc->ssldone); @@ -2260,10 +2260,9 @@ static CURLcode imap_setup_connection(struct Curl_easy *data, } /* - * IMAP protocol handler. + * IMAP protocol. */ -const struct Curl_handler Curl_handler_imap = { - "imap", /* scheme */ +static const struct Curl_protocol Curl_protocol_imap = { imap_setup_connection, /* setup_connection */ imap_do, /* do_it */ imap_done, /* done */ @@ -2281,43 +2280,42 @@ const struct Curl_handler Curl_handler_imap = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_IMAP, /* defport */ +}; + +#endif /* CURL_DISABLE_IMAP */ + + +/* + * IMAP protocol handler. + */ +const struct Curl_scheme Curl_scheme_imap = { + "imap", /* scheme */ +#ifdef CURL_DISABLE_IMAP + ZERO_NULL, +#else + &Curl_protocol_imap, +#endif CURLPROTO_IMAP, /* protocol */ CURLPROTO_IMAP, /* family */ PROTOPT_CLOSEACTION | /* flags */ PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | - PROTOPT_CONN_REUSE + PROTOPT_CONN_REUSE, + PORT_IMAP, /* defport */ }; -#ifdef USE_SSL /* * IMAPS protocol handler. */ -const struct Curl_handler Curl_handler_imaps = { +const struct Curl_scheme Curl_scheme_imaps = { "imaps", /* scheme */ - imap_setup_connection, /* setup_connection */ - imap_do, /* do_it */ - imap_done, /* done */ - ZERO_NULL, /* do_more */ - imap_connect, /* connect_it */ - imap_multi_statemach, /* connecting */ - imap_doing, /* doing */ - imap_pollset, /* proto_pollset */ - imap_pollset, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - imap_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_IMAPS, /* defport */ +#if defined(CURL_DISABLE_IMAP) || !defined(USE_SSL) + ZERO_NULL, +#else + &Curl_protocol_imap, +#endif CURLPROTO_IMAPS, /* protocol */ CURLPROTO_IMAP, /* family */ PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ - PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE + PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE, + PORT_IMAPS, /* defport */ }; -#endif - -#endif /* CURL_DISABLE_IMAP */ diff --git a/lib/imap.h b/lib/imap.h index 26306a6a22fc..f179991a65d2 100644 --- a/lib/imap.h +++ b/lib/imap.h @@ -23,8 +23,8 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -extern const struct Curl_handler Curl_handler_imap; -extern const struct Curl_handler Curl_handler_imaps; +extern const struct Curl_scheme Curl_scheme_imap; +extern const struct Curl_scheme Curl_scheme_imaps; /* Authentication type flags */ #define IMAP_TYPE_CLEARTEXT (1 << 0) diff --git a/lib/ldap.c b/lib/ldap.c index e0f233d0c38c..bff1f0f16756 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -22,6 +22,8 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" +#include "curl_ldap.h" #if !defined(CURL_DISABLE_LDAP) && !defined(USE_OPENLDAP) @@ -75,7 +77,6 @@ # endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */ #endif -#include "urldata.h" #include "cfilters.h" #include "sendf.h" #include "curl_trc.h" @@ -84,7 +85,6 @@ #include "transfer.h" #include "curlx/strparse.h" #include "bufref.h" -#include "curl_ldap.h" #include "curlx/multibyte.h" #include "curlx/base64.h" #include "connect.h" @@ -989,8 +989,7 @@ void Curl_ldap_version(char *buf, size_t bufsz) /* * LDAP protocol handler. */ -const struct Curl_handler Curl_handler_ldap = { - "ldap", /* scheme */ +const struct Curl_protocol Curl_protocol_ldap = { ZERO_NULL, /* setup_connection */ ldap_do, /* do_it */ ZERO_NULL, /* done */ @@ -1008,44 +1007,42 @@ const struct Curl_handler Curl_handler_ldap = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_LDAP, /* defport */ +}; + +#if defined(__GNUC__) && defined(__APPLE__) +#pragma GCC diagnostic pop +#endif + +#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */ + +/* + * LDAP + */ +const struct Curl_scheme Curl_scheme_ldap = { + "ldap", /* scheme */ +#ifdef CURL_DISABLE_LDAP + ZERO_NULL, +#else + &Curl_protocol_ldap, +#endif CURLPROTO_LDAP, /* protocol */ CURLPROTO_LDAP, /* family */ - PROTOPT_SSL_REUSE /* flags */ + PROTOPT_SSL_REUSE, /* flags */ + PORT_LDAP, /* defport */ }; -#ifdef HAVE_LDAP_SSL /* - * LDAPS protocol handler. + * LDAPS */ -const struct Curl_handler Curl_handler_ldaps = { +const struct Curl_scheme Curl_scheme_ldaps = { "ldaps", /* scheme */ - ZERO_NULL, /* setup_connection */ - ldap_do, /* do_it */ - ZERO_NULL, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - ZERO_NULL, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_LDAPS, /* defport */ +#if defined(CURL_DISABLE_LDAP) || !defined(HAVE_LDAP_SSL) + ZERO_NULL, +#else + &Curl_protocol_ldap, +#endif CURLPROTO_LDAPS, /* protocol */ CURLPROTO_LDAP, /* family */ - PROTOPT_SSL /* flags */ + PROTOPT_SSL, /* flags */ + PORT_LDAPS, /* defport */ }; -#endif - -#if defined(__GNUC__) && defined(__APPLE__) -#pragma GCC diagnostic pop -#endif - -#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */ diff --git a/lib/mqtt.c b/lib/mqtt.c index 8ad59b8658e8..f5c8353a9f78 100644 --- a/lib/mqtt.c +++ b/lib/mqtt.c @@ -23,10 +23,10 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" #ifndef CURL_DISABLE_MQTT -#include "urldata.h" #include "transfer.h" #include "sendf.h" #include "curl_trc.h" @@ -950,11 +950,10 @@ static CURLcode mqtts_connecting(struct Curl_easy *data, bool *done) } /* - * MQTTS protocol handler. + * MQTTS protocol. */ -const struct Curl_handler Curl_handler_mqtts = { - "mqtts", /* scheme */ +static const struct Curl_protocol Curl_protocol_mqtts = { mqtt_setup_conn, /* setup_connection */ mqtt_do, /* do_it */ mqtt_done, /* done */ @@ -972,20 +971,15 @@ const struct Curl_handler Curl_handler_mqtts = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_MQTTS, /* defport */ - CURLPROTO_MQTTS, /* protocol */ - CURLPROTO_MQTT, /* family */ - PROTOPT_SSL /* flags */ }; #endif /* - * MQTT protocol handler. + * MQTT protocol. */ -const struct Curl_handler Curl_handler_mqtt = { - "mqtt", /* scheme */ +static const struct Curl_protocol Curl_protocol_mqtt = { mqtt_setup_conn, /* setup_connection */ mqtt_do, /* do_it */ mqtt_done, /* done */ @@ -1003,10 +997,37 @@ const struct Curl_handler Curl_handler_mqtt = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_MQTT, /* defport */ - CURLPROTO_MQTT, /* protocol */ - CURLPROTO_MQTT, /* family */ - PROTOPT_NONE /* flags */ }; #endif /* CURL_DISABLE_MQTT */ + + +const struct Curl_scheme Curl_scheme_mqtts = { + "mqtts", /* scheme */ +#if defined(CURL_DISABLE_MQTT) || !defined(USE_SSL) + ZERO_NULL, +#else + &Curl_protocol_mqtts, +#endif + CURLPROTO_MQTTS, /* protocol */ + CURLPROTO_MQTT, /* family */ + PROTOPT_SSL, /* flags */ + PORT_MQTTS, /* defport */ +}; + +/* + * MQTT protocol. + */ + +const struct Curl_scheme Curl_scheme_mqtt = { + "mqtt", /* scheme */ +#ifdef CURL_DISABLE_MQTT + ZERO_NULL, +#else + &Curl_protocol_mqtt, +#endif + CURLPROTO_MQTT, /* protocol */ + CURLPROTO_MQTT, /* family */ + PROTOPT_NONE, /* flags */ + PORT_MQTT, /* defport */ +}; diff --git a/lib/mqtt.h b/lib/mqtt.h index 43040d001bad..67d1df43dd02 100644 --- a/lib/mqtt.h +++ b/lib/mqtt.h @@ -23,11 +23,7 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#ifndef CURL_DISABLE_MQTT -extern const struct Curl_handler Curl_handler_mqtt; -#ifdef USE_SSL -extern const struct Curl_handler Curl_handler_mqtts; -#endif -#endif +extern const struct Curl_scheme Curl_scheme_mqtt; +extern const struct Curl_scheme Curl_scheme_mqtts; #endif /* HEADER_CURL_MQTT_H */ diff --git a/lib/multi.c b/lib/multi.c index 39cf594c624e..2f8cb055c60c 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -569,8 +569,8 @@ static bool multi_conn_should_close(struct connectdata *conn, /* Unless this connection is for a "connect-only" transfer, it * needs to be closed if the protocol handler does not support reuse. */ - if(!data->set.connect_only && conn->handler && - !(conn->handler->flags & PROTOPT_CONN_REUSE)) + if(!data->set.connect_only && conn->scheme && + !(conn->scheme->flags & PROTOPT_CONN_REUSE)) return TRUE; /* if premature is TRUE, it means this connection was said to be DONE before @@ -699,8 +699,8 @@ static CURLcode multi_done(struct Curl_easy *data, } /* this calls the protocol-specific function pointer previously set */ - if(conn->handler->done && (data->mstate >= MSTATE_PROTOCONNECT)) - result = conn->handler->done(data, status, premature); + if(conn->scheme->run->done && (data->mstate >= MSTATE_PROTOCONNECT)) + result = conn->scheme->run->done(data, status, premature); else result = status; @@ -936,8 +936,8 @@ void Curl_attach_connection(struct Curl_easy *data, conn->attached_multi = data->multi; DEBUGASSERT(conn->attached_multi == data->multi); - if(conn->handler && conn->handler->attach) - conn->handler->attach(data, conn); + if(conn->scheme && conn->scheme->run->attach) + conn->scheme->run->attach(data, conn); } /* adjust pollset for rate limits/pauses */ @@ -1015,8 +1015,8 @@ static CURLcode mstate_protocol_pollset(struct Curl_easy *data, struct connectdata *conn = data->conn; CURLcode result = CURLE_OK; - if(conn->handler->proto_pollset) - result = conn->handler->proto_pollset(data, ps); + if(conn->scheme->run->proto_pollset) + result = conn->scheme->run->proto_pollset(data, ps); else { curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; if(sockfd != CURL_SOCKET_BAD) { @@ -1037,8 +1037,8 @@ static CURLcode mstate_do_pollset(struct Curl_easy *data, struct connectdata *conn = data->conn; CURLcode result = CURLE_OK; - if(conn->handler->doing_pollset) - result = conn->handler->doing_pollset(data, ps); + if(conn->scheme->run->doing_pollset) + result = conn->scheme->run->doing_pollset(data, ps); else if(CONN_SOCK_IDX_VALID(conn->send_idx)) { /* Default is that we want to send something to the server */ result = Curl_pollset_add_out(data, ps, conn->sock[conn->send_idx]); @@ -1056,8 +1056,8 @@ static CURLcode mstate_domore_pollset(struct Curl_easy *data, struct connectdata *conn = data->conn; CURLcode result = CURLE_OK; - if(conn->handler->domore_pollset) - result = conn->handler->domore_pollset(data, ps); + if(conn->scheme->run->domore_pollset) + result = conn->scheme->run->domore_pollset(data, ps); else if(CONN_SOCK_IDX_VALID(conn->send_idx)) { /* Default is that we want to send something to the server */ result = Curl_pollset_add_out(data, ps, conn->sock[conn->send_idx]); @@ -1075,8 +1075,8 @@ static CURLcode mstate_perform_pollset(struct Curl_easy *data, struct connectdata *conn = data->conn; CURLcode result = CURLE_OK; - if(conn->handler->perform_pollset) - result = conn->handler->perform_pollset(data, ps); + if(conn->scheme->run->perform_pollset) + result = conn->scheme->run->perform_pollset(data, ps); else { /* Default is to obey the data->req.keepon flags for send/recv */ if(Curl_req_want_recv(data) && CONN_SOCK_IDX_VALID(conn->recv_idx)) { @@ -1683,10 +1683,10 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done) struct connectdata *conn = data->conn; DEBUGASSERT(conn); - DEBUGASSERT(conn->handler); + DEBUGASSERT(conn->scheme); - if(conn->handler->do_it) - result = conn->handler->do_it(data, done); + if(conn->scheme->run->do_it) + result = conn->scheme->run->do_it(data, done); return result; } @@ -1707,8 +1707,8 @@ static CURLcode multi_do_more(struct Curl_easy *data, int *complete) *complete = 0; - if(conn->handler->do_more) - result = conn->handler->do_more(data, complete); + if(conn->scheme->run->do_more) + result = conn->scheme->run->do_more(data, complete); return result; } @@ -1781,9 +1781,9 @@ static CURLcode protocol_connecting(struct Curl_easy *data, bool *done) CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; - if(conn && conn->handler->connecting) { + if(conn && conn->scheme->run->connecting) { *done = FALSE; - result = conn->handler->connecting(data, done); + result = conn->scheme->run->connecting(data, done); } else *done = TRUE; @@ -1801,9 +1801,9 @@ static CURLcode protocol_doing(struct Curl_easy *data, bool *done) CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; - if(conn && conn->handler->doing) { + if(conn && conn->scheme->run->doing) { *done = FALSE; - result = conn->handler->doing(data, done); + result = conn->scheme->run->doing(data, done); } else *done = TRUE; @@ -1827,9 +1827,9 @@ static CURLcode protocol_connect(struct Curl_easy *data, bool *protocol_done) *protocol_done = FALSE; if(!conn->bits.protoconnstart) { - if(conn->handler->connect_it) { + if(conn->scheme->run->connect_it) { /* Call the protocol-specific connect function */ - result = conn->handler->connect_it(data, protocol_done); + result = conn->scheme->run->connect_it(data, protocol_done); if(result) return result; } @@ -1838,7 +1838,7 @@ static CURLcode protocol_connect(struct Curl_easy *data, bool *protocol_done) /* Unless this protocol does not have any protocol-connect callback, as then we know we are done. */ - if(!conn->handler->connecting) + if(!conn->scheme->run->connecting) *protocol_done = TRUE; return CURLE_OK; } @@ -1869,12 +1869,12 @@ static void multi_posttransfer(struct Curl_easy *data) * This function DOES NOT FREE the given url. */ static CURLcode multi_follow(struct Curl_easy *data, - const struct Curl_handler *handler, + const struct Curl_scheme *handler, const char *newurl, /* the Location: string */ followtype type) /* see transfer.h */ { - if(handler && handler->follow) - return handler->follow(data, newurl, type); + if(handler && handler->run->follow) + return handler->run->follow(data, newurl, type); return CURLE_TOO_MANY_REDIRECTS; } @@ -1996,7 +1996,7 @@ static CURLMcode state_performing(struct Curl_easy *data, * connection. */ - if(!(data->conn->handler->flags & PROTOPT_DUAL) && + if(!(data->conn->scheme->flags & PROTOPT_DUAL) && result != CURLE_HTTP2_STREAM) streamclose(data->conn, "Transfer returned error"); @@ -2004,7 +2004,7 @@ static CURLMcode state_performing(struct Curl_easy *data, multi_done(data, result, TRUE); } else if(data->req.done && !Curl_cwriter_is_paused(data)) { - const struct Curl_handler *handler = data->conn->handler; + const struct Curl_scheme *handler = data->conn->scheme; /* call this even if the readwrite function returned error */ multi_posttransfer(data); @@ -2143,7 +2143,7 @@ static CURLMcode state_do(struct Curl_easy *data, * unexpectedly died. If possible, send the connection back to the * CONNECT phase so we can try again. */ - const struct Curl_handler *handler = data->conn->handler; + const struct Curl_scheme *handler = data->conn->scheme; char *newurl = NULL; followtype follow = FOLLOW_NONE; CURLcode drc; @@ -2208,7 +2208,7 @@ static CURLMcode state_ratelimiting(struct Curl_easy *data, result = Curl_pgrsCheck(data); if(result) { - if(!(data->conn->handler->flags & PROTOPT_DUAL) && + if(!(data->conn->scheme->flags & PROTOPT_DUAL) && result != CURLE_HTTP2_STREAM) streamclose(data->conn, "Transfer returned error"); @@ -2556,7 +2556,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, else { #ifndef CURL_DISABLE_FTP if(data->state.wildcardmatch && - ((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) { + ((data->conn->scheme->flags & PROTOPT_WILDCARD) == 0)) { data->wildcard->state = CURLWC_DONE; } #endif diff --git a/lib/openldap.c b/lib/openldap.c index 6805efc2423d..1cb04e7b27cf 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -615,7 +615,7 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) goto out; hosturl = curl_maprintf("%s://%s%s%s:%d", - conn->handler->scheme, + conn->scheme->name, conn->bits.ipv6_ip ? "[" : "", conn->host.name, conn->bits.ipv6_ip ? "]" : "", @@ -1261,8 +1261,7 @@ void Curl_ldap_version(char *buf, size_t bufsz) /* * LDAP protocol handler. */ -const struct Curl_handler Curl_handler_ldap = { - "ldap", /* scheme */ +const struct Curl_protocol Curl_protocol_ldap = { oldap_setup_connection, /* setup_connection */ oldap_do, /* do_it */ oldap_done, /* done */ @@ -1280,42 +1279,8 @@ const struct Curl_handler Curl_handler_ldap = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_LDAP, /* defport */ - CURLPROTO_LDAP, /* protocol */ - CURLPROTO_LDAP, /* family */ - PROTOPT_SSL_REUSE | /* flags */ - PROTOPT_CONN_REUSE }; -#ifdef USE_SSL -/* - * LDAPS protocol handler. - */ -const struct Curl_handler Curl_handler_ldaps = { - "ldaps", /* scheme */ - oldap_setup_connection, /* setup_connection */ - oldap_do, /* do_it */ - oldap_done, /* done */ - ZERO_NULL, /* do_more */ - oldap_connect, /* connect_it */ - oldap_connecting, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - oldap_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_LDAPS, /* defport */ - CURLPROTO_LDAPS, /* protocol */ - CURLPROTO_LDAP, /* family */ - PROTOPT_SSL | /* flags */ - PROTOPT_CONN_REUSE -}; -#endif - #endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */ + +/* The LDAP scheme structs are in ldap.c */ diff --git a/lib/pop3.c b/lib/pop3.c index 6faad63c97a6..089af4890e2f 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -37,6 +37,8 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" +#include "pop3.h" #ifndef CURL_DISABLE_POP3 @@ -54,7 +56,6 @@ #include #endif -#include "urldata.h" #include "sendf.h" #include "curl_trc.h" #include "hostip.h" @@ -62,7 +63,6 @@ #include "transfer.h" #include "escape.h" #include "pingpong.h" -#include "pop3.h" #include "vtls/vtls.h" #include "cfilters.h" #include "connect.h" @@ -490,7 +490,7 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data, if(result) goto out; /* Change the connection handler */ - conn->handler = &Curl_handler_pop3s; + conn->scheme = &Curl_scheme_pop3s; } DEBUGASSERT(!pop3c->ssldone); @@ -1691,10 +1691,9 @@ static CURLcode pop3_setup_connection(struct Curl_easy *data, } /* - * POP3 protocol handler. + * POP3 protocol. */ -const struct Curl_handler Curl_handler_pop3 = { - "pop3", /* scheme */ +static const struct Curl_protocol Curl_protocol_pop3 = { pop3_setup_connection, /* setup_connection */ pop3_do, /* do_it */ pop3_done, /* done */ @@ -1712,42 +1711,40 @@ const struct Curl_handler Curl_handler_pop3 = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_POP3, /* defport */ +}; + +#endif /* CURL_DISABLE_POP3 */ + +/* + * POP3 protocol handler. + */ +const struct Curl_scheme Curl_scheme_pop3 = { + "pop3", /* scheme */ +#ifdef CURL_DISABLE_POP3 + ZERO_NULL, +#else + &Curl_protocol_pop3, +#endif CURLPROTO_POP3, /* protocol */ CURLPROTO_POP3, /* family */ PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ - PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE + PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE, + PORT_POP3, /* defport */ }; -#ifdef USE_SSL /* * POP3S protocol handler. */ -const struct Curl_handler Curl_handler_pop3s = { +const struct Curl_scheme Curl_scheme_pop3s = { "pop3s", /* scheme */ - pop3_setup_connection, /* setup_connection */ - pop3_do, /* do_it */ - pop3_done, /* done */ - ZERO_NULL, /* do_more */ - pop3_connect, /* connect_it */ - pop3_multi_statemach, /* connecting */ - pop3_doing, /* doing */ - pop3_pollset, /* proto_pollset */ - pop3_pollset, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - pop3_disconnect, /* disconnect */ - pop3_write, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_POP3S, /* defport */ +#if defined(CURL_DISABLE_POP3) || !defined(USE_SSL) + ZERO_NULL, +#else + &Curl_protocol_pop3, +#endif CURLPROTO_POP3S, /* protocol */ CURLPROTO_POP3, /* family */ PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ - PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE + PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE, + PORT_POP3S, /* defport */ }; -#endif - -#endif /* CURL_DISABLE_POP3 */ diff --git a/lib/pop3.h b/lib/pop3.h index ed00dd15ae46..77e30f832d23 100644 --- a/lib/pop3.h +++ b/lib/pop3.h @@ -23,7 +23,7 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -extern const struct Curl_handler Curl_handler_pop3; -extern const struct Curl_handler Curl_handler_pop3s; +extern const struct Curl_scheme Curl_scheme_pop3; +extern const struct Curl_scheme Curl_scheme_pop3s; #endif /* HEADER_CURL_POP3_H */ diff --git a/lib/rtsp.c b/lib/rtsp.c index c3711caf049e..a36ea1cac46e 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -22,10 +22,10 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" #ifndef CURL_DISABLE_RTSP -#include "urldata.h" #include "transfer.h" #include "sendf.h" #include "curl_trc.h" @@ -316,7 +316,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) return CURLE_OUT_OF_MEMORY; data->state.first_remote_port = conn->remote_port; - data->state.first_remote_protocol = conn->handler->protocol; + data->state.first_remote_protocol = conn->scheme->protocol; } /* Setup the 'p_request' pointer to the proper p_request string @@ -1045,8 +1045,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header) /* * RTSP handler interface. */ -const struct Curl_handler Curl_handler_rtsp = { - "rtsp", /* scheme */ +static const struct Curl_protocol Curl_protocol_rtsp = { rtsp_setup_connection, /* setup_connection */ rtsp_do, /* do_it */ rtsp_done, /* done */ @@ -1064,10 +1063,22 @@ const struct Curl_handler Curl_handler_rtsp = { rtsp_conncheck, /* connection_check */ ZERO_NULL, /* attach connection */ Curl_http_follow, /* follow */ - PORT_RTSP, /* defport */ - CURLPROTO_RTSP, /* protocol */ - CURLPROTO_RTSP, /* family */ - PROTOPT_CONN_REUSE /* flags */ }; #endif /* CURL_DISABLE_RTSP */ + +/* + * RTSP handler interface. + */ +const struct Curl_scheme Curl_scheme_rtsp = { + "rtsp", /* scheme */ +#ifdef CURL_DISABLE_RTSP + ZERO_NULL, +#else + &Curl_protocol_rtsp, +#endif + CURLPROTO_RTSP, /* protocol */ + CURLPROTO_RTSP, /* family */ + PROTOPT_CONN_REUSE, /* flags */ + PORT_RTSP, /* defport */ +}; diff --git a/lib/rtsp.h b/lib/rtsp.h index 70ca00f69a8b..92b28e54f8ed 100644 --- a/lib/rtsp.h +++ b/lib/rtsp.h @@ -23,8 +23,8 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ +extern const struct Curl_scheme Curl_scheme_rtsp; #ifndef CURL_DISABLE_RTSP -extern const struct Curl_handler Curl_handler_rtsp; CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header); #else #define Curl_rtsp_parseheader(x, y) CURLE_NOT_BUILT_IN diff --git a/lib/sendf.c b/lib/sendf.c index 674b0a4573d9..f2d30a4269a1 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -696,7 +696,7 @@ static CURLcode cr_in_read(struct Curl_easy *data, break; case CURL_READFUNC_PAUSE: - if(data->conn->handler->flags & PROTOPT_NONETWORK) { + if(data->conn->scheme->flags & PROTOPT_NONETWORK) { /* protocols that work without network cannot be paused. This is actually only FILE:// just now, and it cannot pause since the transfer is not done using the "normal" procedure. */ diff --git a/lib/setopt.c b/lib/setopt.c index c82e8c206b93..713a6d2d7cd3 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -214,9 +214,9 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val) str = strchr(str, ','); tlen = str ? (size_t)(str - token) : strlen(token); if(tlen) { - const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen); + const struct Curl_scheme *h = Curl_getn_scheme(token, tlen); - if(!h) + if(!h || !h->run) return CURLE_UNSUPPORTED_PROTOCOL; *val |= h->protocol; diff --git a/lib/smb.c b/lib/smb.c index e4a1df141211..4463719c042c 100644 --- a/lib/smb.c +++ b/lib/smb.c @@ -23,11 +23,11 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) #include "smb.h" -#include "urldata.h" #include "url.h" #include "sendf.h" #include "curl_trc.h" @@ -1201,8 +1201,7 @@ static CURLcode smb_do(struct Curl_easy *data, bool *done) /* * SMB handler interface */ -const struct Curl_handler Curl_handler_smb = { - "smb", /* scheme */ +static const struct Curl_protocol Curl_protocol_smb = { smb_setup_connection, /* setup_connection */ smb_do, /* do_it */ ZERO_NULL, /* done */ @@ -1220,40 +1219,39 @@ const struct Curl_handler Curl_handler_smb = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_SMB, /* defport */ +}; + +#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE && SIZEOF_CURL_OFF_T > 4 */ + +/* + * SMB handler interface + */ +const struct Curl_scheme Curl_scheme_smb = { + "smb", /* scheme */ +#if defined(CURL_DISABLE_SMB) || !defined(USE_CURL_NTLM_CORE) + ZERO_NULL, +#else + &Curl_protocol_smb, +#endif CURLPROTO_SMB, /* protocol */ CURLPROTO_SMB, /* family */ - PROTOPT_CONN_REUSE /* flags */ + PROTOPT_CONN_REUSE, /* flags */ + PORT_SMB, /* defport */ }; -#ifdef USE_SSL /* * SMBS handler interface */ -const struct Curl_handler Curl_handler_smbs = { +const struct Curl_scheme Curl_scheme_smbs = { "smbs", /* scheme */ - smb_setup_connection, /* setup_connection */ - smb_do, /* do_it */ - ZERO_NULL, /* done */ - ZERO_NULL, /* do_more */ - smb_connect, /* connect_it */ - smb_connection_state, /* connecting */ - smb_request_state, /* doing */ - smb_pollset, /* proto_pollset */ - smb_pollset, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - ZERO_NULL, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_SMBS, /* defport */ +#if defined(CURL_DISABLE_SMB) || !defined(USE_CURL_NTLM_CORE) || \ + !defined(USE_SSL) + ZERO_NULL, +#else + &Curl_protocol_smb, +#endif CURLPROTO_SMBS, /* protocol */ CURLPROTO_SMB, /* family */ - PROTOPT_SSL | PROTOPT_CONN_REUSE /* flags */ + PROTOPT_SSL | PROTOPT_CONN_REUSE, /* flags */ + PORT_SMBS, /* defport */ }; -#endif - -#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE && SIZEOF_CURL_OFF_T > 4 */ diff --git a/lib/smb.h b/lib/smb.h index 474f8d6a5f7b..d3754047a7d2 100644 --- a/lib/smb.h +++ b/lib/smb.h @@ -24,12 +24,7 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ - (SIZEOF_CURL_OFF_T > 4) - -extern const struct Curl_handler Curl_handler_smb; -extern const struct Curl_handler Curl_handler_smbs; - -#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE && SIZEOF_CURL_OFF_T > 4 */ +extern const struct Curl_scheme Curl_scheme_smb; +extern const struct Curl_scheme Curl_scheme_smbs; #endif /* HEADER_CURL_SMB_H */ diff --git a/lib/smtp.c b/lib/smtp.c index 70fdba8cc6a0..2427fd932d59 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -39,6 +39,8 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" +#include "smtp.h" #ifndef CURL_DISABLE_SMTP @@ -56,7 +58,6 @@ #include #endif -#include "urldata.h" #include "sendf.h" #include "curl_trc.h" #include "hostip.h" @@ -65,7 +66,6 @@ #include "escape.h" #include "pingpong.h" #include "mime.h" -#include "smtp.h" #include "vtls/vtls.h" #include "cfilters.h" #include "connect.h" @@ -695,7 +695,7 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data, if(result) goto out; /* Change the connection handler and SMTP state */ - conn->handler = &Curl_handler_smtps; + conn->scheme = &Curl_scheme_smtps; } DEBUGASSERT(!smtpc->ssldone); @@ -1987,8 +1987,7 @@ static CURLcode smtp_setup_connection(struct Curl_easy *data, /* * SMTP protocol handler. */ -const struct Curl_handler Curl_handler_smtp = { - "smtp", /* scheme */ +static const struct Curl_protocol Curl_protocol_smtp = { smtp_setup_connection, /* setup_connection */ smtp_do, /* do_it */ smtp_done, /* done */ @@ -2006,42 +2005,40 @@ const struct Curl_handler Curl_handler_smtp = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_SMTP, /* defport */ +}; + +#endif /* CURL_DISABLE_SMTP */ + +/* + * SMTP protocol handler. + */ +const struct Curl_scheme Curl_scheme_smtp = { + "smtp", /* scheme */ +#ifdef CURL_DISABLE_SMTP + ZERO_NULL, +#else + &Curl_protocol_smtp, +#endif CURLPROTO_SMTP, /* protocol */ CURLPROTO_SMTP, /* family */ PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ - PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE + PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE, + PORT_SMTP, /* defport */ }; -#ifdef USE_SSL /* * SMTPS protocol handler. */ -const struct Curl_handler Curl_handler_smtps = { +const struct Curl_scheme Curl_scheme_smtps = { "smtps", /* scheme */ - smtp_setup_connection, /* setup_connection */ - smtp_do, /* do_it */ - smtp_done, /* done */ - ZERO_NULL, /* do_more */ - smtp_connect, /* connect_it */ - smtp_multi_statemach, /* connecting */ - smtp_doing, /* doing */ - smtp_pollset, /* proto_pollset */ - smtp_pollset, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - smtp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_SMTPS, /* defport */ +#if defined(CURL_DISABLE_SMTP) || !defined(USE_SSL) + ZERO_NULL, +#else + &Curl_protocol_smtp, +#endif CURLPROTO_SMTPS, /* protocol */ CURLPROTO_SMTP, /* family */ PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ - PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE + PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE, + PORT_SMTPS, /* defport */ }; -#endif - -#endif /* CURL_DISABLE_SMTP */ diff --git a/lib/smtp.h b/lib/smtp.h index 7e3cf774ae88..39f8d78473f1 100644 --- a/lib/smtp.h +++ b/lib/smtp.h @@ -23,7 +23,7 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -extern const struct Curl_handler Curl_handler_smtp; -extern const struct Curl_handler Curl_handler_smtps; +extern const struct Curl_scheme Curl_scheme_smtp; +extern const struct Curl_scheme Curl_scheme_smtps; #endif /* HEADER_CURL_SMTP_H */ diff --git a/lib/telnet.c b/lib/telnet.c index 02fc3a1edc1b..4a38bfc6c906 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -22,6 +22,8 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" +#include "telnet.h" #ifndef CURL_DISABLE_TELNET @@ -45,12 +47,10 @@ #include #endif -#include "urldata.h" #include "url.h" #include "transfer.h" #include "sendf.h" #include "curl_trc.h" -#include "telnet.h" #include "connect.h" #include "progress.h" #include "arpa_telnet.h" @@ -1570,8 +1570,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) /* * TELNET protocol handler. */ -const struct Curl_handler Curl_handler_telnet = { - "telnet", /* scheme */ +static const struct Curl_protocol Curl_protocol_telnet = { ZERO_NULL, /* setup_connection */ telnet_do, /* do_it */ telnet_done, /* done */ @@ -1589,10 +1588,22 @@ const struct Curl_handler Curl_handler_telnet = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_TELNET, /* defport */ - CURLPROTO_TELNET, /* protocol */ - CURLPROTO_TELNET, /* family */ - PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ }; #endif /* !CURL_DISABLE_TELNET */ + +/* + * TELNET protocol handler. + */ +const struct Curl_scheme Curl_scheme_telnet = { + "telnet", /* scheme */ +#ifdef CURL_DISABLE_TELNET + ZERO_NULL, +#else + &Curl_protocol_telnet, +#endif + CURLPROTO_TELNET, /* protocol */ + CURLPROTO_TELNET, /* family */ + PROTOPT_NONE | PROTOPT_NOURLQUERY, /* flags */ + PORT_TELNET, /* defport */ +}; diff --git a/lib/telnet.h b/lib/telnet.h index 30782d837576..c10617964a8a 100644 --- a/lib/telnet.h +++ b/lib/telnet.h @@ -23,8 +23,6 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#ifndef CURL_DISABLE_TELNET -extern const struct Curl_handler Curl_handler_telnet; -#endif +extern const struct Curl_scheme Curl_scheme_telnet; #endif /* HEADER_CURL_TELNET_H */ diff --git a/lib/tftp.c b/lib/tftp.c index 584d146a30ff..1b882efe377d 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -22,6 +22,7 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" #ifndef CURL_DISABLE_TFTP @@ -45,7 +46,6 @@ #include #endif -#include "urldata.h" #include "cfilters.h" #include "cf-socket.h" #include "transfer.h" @@ -1338,8 +1338,7 @@ static CURLcode tftp_setup_connection(struct Curl_easy *data, /* * TFTP protocol handler. */ -const struct Curl_handler Curl_handler_tftp = { - "tftp", /* scheme */ +static const struct Curl_protocol Curl_protocol_tftp = { tftp_setup_connection, /* setup_connection */ tftp_do, /* do_it */ tftp_done, /* done */ @@ -1357,10 +1356,22 @@ const struct Curl_handler Curl_handler_tftp = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_TFTP, /* defport */ - CURLPROTO_TFTP, /* protocol */ - CURLPROTO_TFTP, /* family */ - PROTOPT_NOTCPPROXY | PROTOPT_NOURLQUERY /* flags */ }; #endif + +/* + * TFTP protocol handler. + */ +const struct Curl_scheme Curl_scheme_tftp = { + "tftp", /* scheme */ +#ifdef CURL_DISABLE_TFTP + ZERO_NULL, +#else + &Curl_protocol_tftp, +#endif + CURLPROTO_TFTP, /* protocol */ + CURLPROTO_TFTP, /* family */ + PROTOPT_NOTCPPROXY | PROTOPT_NOURLQUERY, /* flags */ + PORT_TFTP, /* defport */ +}; diff --git a/lib/tftp.h b/lib/tftp.h index 12404bf6d20d..91ecd2978af4 100644 --- a/lib/tftp.h +++ b/lib/tftp.h @@ -23,11 +23,9 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#ifndef CURL_DISABLE_TFTP -extern const struct Curl_handler Curl_handler_tftp; +extern const struct Curl_scheme Curl_scheme_tftp; #define TFTP_BLKSIZE_MIN 8 #define TFTP_BLKSIZE_MAX 65464 -#endif #endif /* HEADER_CURL_TFTP_H */ diff --git a/lib/transfer.c b/lib/transfer.c index fed6a1786e7e..63d2e15047d9 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -104,13 +104,13 @@ static int data_pending(struct Curl_easy *data, bool rcvd_eagain) { struct connectdata *conn = data->conn; - if(conn->handler->protocol & PROTO_FAMILY_FTP) + if(conn->scheme->protocol & PROTO_FAMILY_FTP) return Curl_conn_data_pending(data, SECONDARYSOCKET); /* in the case of libssh2, we can never be really sure that we have emptied its internal buffers so we MUST always try until we get EAGAIN back */ return (!rcvd_eagain && - conn->handler->protocol & (CURLPROTO_SCP | CURLPROTO_SFTP)) || + conn->scheme->protocol & (CURLPROTO_SCP | CURLPROTO_SFTP)) || Curl_conn_data_pending(data, FIRSTSOCKET); } @@ -623,13 +623,13 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url) protocol is HTTP as when uploading over HTTP we will still get a response */ if(data->state.upload && - !(conn->handler->protocol & (PROTO_FAMILY_HTTP | CURLPROTO_RTSP))) + !(conn->scheme->protocol & (PROTO_FAMILY_HTTP | CURLPROTO_RTSP))) return CURLE_OK; if(conn->bits.reuse && (data->req.bytecount + data->req.headerbytecount == 0) && ((!data->req.no_body && !data->req.done) || - (conn->handler->protocol & PROTO_FAMILY_HTTP)) + (conn->scheme->protocol & PROTO_FAMILY_HTTP)) #ifndef CURL_DISABLE_RTSP && (data->set.rtspreq != RTSPREQ_RECEIVE) #endif @@ -701,7 +701,7 @@ static void xfer_setup( /* without receiving, there should be not recv_size */ DEBUGASSERT((conn->recv_idx >= 0) || (recv_size == -1)); k->size = recv_size; - k->header = !!conn->handler->write_resp_hd; + k->header = !!conn->scheme->run->write_resp_hd; /* by default, we do not shutdown at the end of the transfer */ k->shutdown = FALSE; k->shutdown_err_ignore = FALSE; @@ -713,7 +713,7 @@ static void xfer_setup( Curl_pgrsSetDownloadSize(data, recv_size); /* we want header and/or body, if neither then do not do this! */ - if(conn->handler->write_resp_hd || !data->req.no_body) { + if(conn->scheme->run->write_resp_hd || !data->req.no_body) { if(conn->recv_idx != -1) k->keepon |= KEEP_RECV; @@ -768,10 +768,10 @@ CURLcode Curl_xfer_write_resp(struct Curl_easy *data, { CURLcode result = CURLE_OK; - if(data->conn->handler->write_resp) { + if(data->conn->scheme->run->write_resp) { /* protocol handlers offering this function take full responsibility * for writing all received download data to the client. */ - result = data->conn->handler->write_resp(data, buf, blen, is_eos); + result = data->conn->scheme->run->write_resp(data, buf, blen, is_eos); } else { /* No special handling by protocol handler, write all received data @@ -802,11 +802,11 @@ bool Curl_xfer_write_is_paused(struct Curl_easy *data) CURLcode Curl_xfer_write_resp_hd(struct Curl_easy *data, const char *hd0, size_t hdlen, bool is_eos) { - if(data->conn->handler->write_resp_hd) { + if(data->conn->scheme->run->write_resp_hd) { DEBUGASSERT(!hd0[hdlen]); /* null terminated */ /* protocol handlers offering this function take full responsibility * for writing all received download data to the client. */ - return data->conn->handler->write_resp_hd(data, hd0, hdlen, is_eos); + return data->conn->scheme->run->write_resp_hd(data, hd0, hdlen, is_eos); } /* No special handling by protocol handler, write as response bytes */ return Curl_xfer_write_resp(data, hd0, hdlen, is_eos); diff --git a/lib/url.c b/lib/url.c index dd1bc2aed88c..99efe38631b4 100644 --- a/lib/url.c +++ b/lib/url.c @@ -71,6 +71,7 @@ #include "mime.h" #include "bufref.h" #include "vtls/vtls.h" +#include "vssh/vssh.h" #include "hostip.h" #include "transfer.h" #include "curl_addrinfo.h" @@ -148,15 +149,15 @@ static void data_priority_cleanup(struct Curl_easy *data); * * Parameters: * - * 'h' [in] - struct Curl_handler pointer. + * 's' [in] - struct Curl_scheme pointer. * * Returns the family as a single bit protocol identifier. */ -static curl_prot_t get_protocol_family(const struct Curl_handler *h) +static curl_prot_t get_protocol_family(const struct Curl_scheme *s) { - DEBUGASSERT(h); - DEBUGASSERT(h->family); - return h->family; + DEBUGASSERT(s); + DEBUGASSERT(s->family); + return s->family; } void Curl_freeset(struct Curl_easy *data) @@ -519,9 +520,9 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn) DEBUGASSERT(conn); - if(conn->handler && conn->handler->disconnect && + if(conn->scheme && conn->scheme->run->disconnect && !conn->bits.shutdown_handler) - conn->handler->disconnect(data, conn, TRUE); + conn->scheme->run->disconnect(data, conn, TRUE); for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) { Curl_conn_cf_discard_all(data, conn, (int)i); @@ -571,7 +572,7 @@ static bool xfer_may_multiplex(const struct Curl_easy *data, { #ifndef CURL_DISABLE_HTTP /* If an HTTP protocol and multiplexing is enabled */ - if((conn->handler->protocol & PROTO_FAMILY_HTTP) && + if((conn->scheme->protocol & PROTO_FAMILY_HTTP) && (!conn->bits.protoconnstart || !conn->bits.close)) { if(Curl_multiplex_wanted(data->multi) && @@ -670,7 +671,7 @@ bool Curl_conn_seems_dead(struct connectdata *conn, /* avoid check if already too old */ dead = TRUE; } - else if(conn->handler->connection_check) { + else if(conn->scheme->run->connection_check) { /* The protocol has a special method for checking the state of the connection. Use it to check if the connection is dead. */ unsigned int state; @@ -679,7 +680,8 @@ bool Curl_conn_seems_dead(struct connectdata *conn, checking it */ Curl_attach_connection(data, conn); - state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD); + state = conn->scheme->run->connection_check(data, conn, + CONNCHECK_ISDEAD); dead = (state & CONNRESULT_DEAD); /* detach the connection again */ Curl_detach_connection(data); @@ -724,10 +726,11 @@ CURLcode Curl_conn_upkeep(struct Curl_easy *data, /* briefly attach for action */ Curl_attach_connection(data, conn); - if(conn->handler->connection_check) { + if(conn->scheme->run->connection_check) { /* Do a protocol-specific keepalive check on the connection. */ unsigned int rc; - rc = conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE); + rc = conn->scheme->run->connection_check(data, conn, + CONNCHECK_KEEPALIVE); if(rc & CONNRESULT_DEAD) result = CURLE_RECV_ERROR; } @@ -901,7 +904,7 @@ static bool url_match_multiplex_limits(struct connectdata *conn, static bool url_match_ssl_use(struct connectdata *conn, struct url_conn_match *m) { - if(m->needle->handler->flags & PROTOPT_SSL) { + if(m->needle->scheme->flags & PROTOPT_SSL) { /* We are looking for SSL, if `conn` does not do it, not a match. */ if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) return FALSE; @@ -909,8 +912,8 @@ static bool url_match_ssl_use(struct connectdata *conn, else if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) { /* If the protocol does not allow reuse of SSL connections OR is of another protocol family, not a match. */ - if(!(m->needle->handler->flags & PROTOPT_SSL_REUSE) || - (get_protocol_family(conn->handler) != m->needle->handler->protocol)) + if(!(m->needle->scheme->flags & PROTOPT_SSL_REUSE) || + (get_protocol_family(conn->scheme) != m->needle->scheme->protocol)) return FALSE; } return TRUE; @@ -963,7 +966,7 @@ static bool url_match_http_multiplex(struct connectdata *conn, { if(m->may_multiplex && (m->data->state.http_neg.allowed & (CURL_HTTP_V2x | CURL_HTTP_V3x)) && - (m->needle->handler->protocol & CURLPROTO_HTTP) && + (m->needle->scheme->protocol & CURLPROTO_HTTP) && !conn->httpversion_seen) { if(m->data->set.pipewait) { infof(m->data, "Server upgrade does not support multiplex yet, wait"); @@ -982,7 +985,7 @@ static bool url_match_http_version(struct connectdata *conn, { /* If looking for HTTP and the HTTP versions allowed do not include * the HTTP version of conn, continue looking. */ - if((m->needle->handler->protocol & PROTO_FAMILY_HTTP)) { + if((m->needle->scheme->protocol & PROTO_FAMILY_HTTP)) { switch(Curl_conn_http_version(m->data, conn)) { case 30: if(!(m->data->state.http_neg.allowed & CURL_HTTP_V3x)) { @@ -1021,13 +1024,13 @@ static bool url_match_proto_config(struct connectdata *conn, return FALSE; #ifdef USE_SSH - if(get_protocol_family(m->needle->handler) & PROTO_FAMILY_SSH) { + if(get_protocol_family(m->needle->scheme) & PROTO_FAMILY_SSH) { if(!ssh_config_matches(m->needle, conn)) return FALSE; } #endif #ifndef CURL_DISABLE_FTP - else if(get_protocol_family(m->needle->handler) & PROTO_FAMILY_FTP) { + else if(get_protocol_family(m->needle->scheme) & PROTO_FAMILY_FTP) { if(!ftp_conns_match(m->needle, conn)) return FALSE; } @@ -1038,7 +1041,7 @@ static bool url_match_proto_config(struct connectdata *conn, static bool url_match_auth(struct connectdata *conn, struct url_conn_match *m) { - if(!(m->needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { + if(!(m->needle->scheme->flags & PROTOPT_CREDSPERREQUEST)) { /* This protocol requires credentials per connection, so verify that we are using the same name and password as well */ if(Curl_timestrcmp(m->needle->user, conn->user) || @@ -1064,14 +1067,14 @@ static bool url_match_destination(struct connectdata *conn, { /* Additional match requirements if talking TLS OR * not talking to an HTTP proxy OR using a tunnel through a proxy */ - if((m->needle->handler->flags & PROTOPT_SSL) + if((m->needle->scheme->flags & PROTOPT_SSL) #ifndef CURL_DISABLE_PROXY || !m->needle->bits.httpproxy || m->needle->bits.tunnel_proxy #endif ) { - if(!curl_strequal(m->needle->handler->scheme, conn->handler->scheme)) { + if(!curl_strequal(m->needle->scheme->name, conn->scheme->name)) { /* `needle` and `conn` do not have the same scheme... */ - if(get_protocol_family(conn->handler) != m->needle->handler->protocol) { + if(get_protocol_family(conn->scheme) != m->needle->scheme->protocol) { /* and `conn`s protocol family is not the protocol `needle` wants. * IMAPS would work for IMAP, but no vice versa. */ return FALSE; @@ -1104,7 +1107,7 @@ static bool url_match_ssl_config(struct connectdata *conn, struct url_conn_match *m) { /* If talking TLS, conn needs to use the same SSL options. */ - if((m->needle->handler->flags & PROTOPT_SSL) && + if((m->needle->scheme->flags & PROTOPT_SSL) && !Curl_ssl_conn_config_match(m->data, conn, FALSE)) { DEBUGF(infof(m->data, "Connection #%" FMT_OFF_T @@ -1292,12 +1295,12 @@ static bool ConnectionExists(struct Curl_easy *data, #ifdef USE_NTLM match.want_ntlm_http = ((data->state.authhost.want & CURLAUTH_NTLM) && - (needle->handler->protocol & PROTO_FAMILY_HTTP)); + (needle->scheme->protocol & PROTO_FAMILY_HTTP)); #ifndef CURL_DISABLE_PROXY match.want_proxy_ntlm_http = (needle->bits.proxy_user_passwd && (data->state.authproxy.want & CURLAUTH_NTLM) && - (needle->handler->protocol & PROTO_FAMILY_HTTP)); + (needle->scheme->protocol & PROTO_FAMILY_HTTP)); #endif #endif @@ -1398,14 +1401,15 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) return NULL; } -const struct Curl_handler *Curl_get_scheme_handler(const char *scheme) +const struct Curl_scheme *Curl_get_scheme(const char *scheme) { - return Curl_getn_scheme_handler(scheme, strlen(scheme)); + return Curl_getn_scheme(scheme, strlen(scheme)); } -/* returns the handler if the given scheme is built-in */ -const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, - size_t len) +/* Returns a struct scheme pointer if the name is a known scheme. Check the + ->run struct field for non-NULL to figure out if an implementation is + present. */ +const struct Curl_scheme *Curl_getn_scheme(const char *scheme, size_t len) { /* table generated by schemetable.c: 1. gcc schemetable.c && ./a.out @@ -1415,199 +1419,47 @@ const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, 5. copy the table into this source code 6. make sure this function uses the same hash function that worked for schemetable.c - 7. if needed, adjust the #ifdefs in schemetable.c and rerun */ - static const struct Curl_handler * const protocols[67] = { -#ifndef CURL_DISABLE_FILE - &Curl_handler_file, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_MQTT) - &Curl_handler_mqtts, -#else - NULL, -#endif - NULL, -#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER) - &Curl_handler_gophers, -#else - NULL, -#endif - NULL, -#ifdef USE_LIBRTMP - &Curl_handler_rtmpe, -#else - NULL, -#endif -#ifndef CURL_DISABLE_SMTP - &Curl_handler_smtp, -#else - NULL, -#endif -#ifdef USE_SSH - &Curl_handler_sftp, -#else - NULL, -#endif -#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \ - (SIZEOF_CURL_OFF_T > 4) - &Curl_handler_smb, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP) - &Curl_handler_smtps, -#else - NULL, -#endif -#ifndef CURL_DISABLE_TELNET - &Curl_handler_telnet, -#else - NULL, -#endif -#ifndef CURL_DISABLE_GOPHER - &Curl_handler_gopher, -#else - NULL, -#endif -#ifndef CURL_DISABLE_TFTP - &Curl_handler_tftp, -#else - NULL, -#endif - NULL, NULL, NULL, -#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) - &Curl_handler_ftps, -#else - NULL, -#endif -#ifndef CURL_DISABLE_HTTP - &Curl_handler_http, -#else - NULL, -#endif -#ifndef CURL_DISABLE_IMAP - &Curl_handler_imap, -#else - NULL, -#endif -#ifdef USE_LIBRTMP - &Curl_handler_rtmps, -#else - NULL, -#endif -#ifdef USE_LIBRTMP - &Curl_handler_rtmpt, -#else - NULL, -#endif - NULL, NULL, NULL, -#if !defined(CURL_DISABLE_LDAP) && \ - !defined(CURL_DISABLE_LDAPS) && \ - ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ - (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) - &Curl_handler_ldaps, -#else - NULL, -#endif -#if !defined(CURL_DISABLE_WEBSOCKETS) && \ - defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_wss, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_https, -#else - NULL, -#endif - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#ifndef CURL_DISABLE_RTSP - &Curl_handler_rtsp, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \ - defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4) - &Curl_handler_smbs, -#else - NULL, -#endif -#ifdef USE_SSH - &Curl_handler_scp, -#else - NULL, -#endif - NULL, NULL, NULL, -#ifndef CURL_DISABLE_POP3 - &Curl_handler_pop3, -#else - NULL, -#endif - NULL, NULL, -#ifdef USE_LIBRTMP - &Curl_handler_rtmp, -#else - NULL, -#endif - NULL, NULL, NULL, -#ifdef USE_LIBRTMP - &Curl_handler_rtmpte, -#else - NULL, -#endif - NULL, NULL, NULL, -#ifndef CURL_DISABLE_DICT - &Curl_handler_dict, -#else - NULL, -#endif - NULL, NULL, NULL, -#ifndef CURL_DISABLE_MQTT - &Curl_handler_mqtt, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3) - &Curl_handler_pop3s, -#else - NULL, -#endif -#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP) - &Curl_handler_imaps, -#else - NULL, -#endif - NULL, -#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) - &Curl_handler_ws, -#else - NULL, -#endif - NULL, -#ifdef USE_LIBRTMP - &Curl_handler_rtmpts, -#else - NULL, -#endif -#ifndef CURL_DISABLE_LDAP - &Curl_handler_ldap, -#else - NULL, -#endif - NULL, NULL, -#ifndef CURL_DISABLE_FTP - &Curl_handler_ftp, -#else - NULL, -#endif + static const struct Curl_scheme * const all_schemes[67] = { + &Curl_scheme_file, + &Curl_scheme_mqtts, NULL, + &Curl_scheme_gophers, NULL, + &Curl_scheme_rtmpe, + &Curl_scheme_smtp, + &Curl_scheme_sftp, + &Curl_scheme_smb, + &Curl_scheme_smtps, + &Curl_scheme_telnet, + &Curl_scheme_gopher, + &Curl_scheme_tftp, NULL, NULL, NULL, + &Curl_scheme_ftps, + &Curl_scheme_http, + &Curl_scheme_imap, + &Curl_scheme_rtmps, + &Curl_scheme_rtmpt, NULL, NULL, NULL, + &Curl_scheme_ldaps, + &Curl_scheme_wss, + &Curl_scheme_https, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + &Curl_scheme_rtsp, + &Curl_scheme_smbs, + &Curl_scheme_scp, NULL, NULL, NULL, + &Curl_scheme_pop3, NULL, NULL, + &Curl_scheme_rtmp, NULL, NULL, NULL, + &Curl_scheme_rtmpte, NULL, NULL, NULL, + &Curl_scheme_dict, NULL, NULL, NULL, + &Curl_scheme_mqtt, + &Curl_scheme_pop3s, + &Curl_scheme_imaps, NULL, + &Curl_scheme_ws, NULL, + &Curl_scheme_rtmpts, + &Curl_scheme_ldap, NULL, NULL, + &Curl_scheme_ftp, }; if(len && (len <= 7)) { const char *s = scheme; size_t l = len; - const struct Curl_handler *h; + const struct Curl_scheme *h; unsigned int c = 978; while(l) { c <<= 5; @@ -1616,8 +1468,8 @@ const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, l--; } - h = protocols[c % 67]; - if(h && curl_strnequal(scheme, h->scheme, len) && !h->scheme[len]) + h = all_schemes[c % 67]; + if(h && curl_strnequal(scheme, h->name, len) && !h->name[len]) return h; } return NULL; @@ -1627,9 +1479,9 @@ static CURLcode findprotocol(struct Curl_easy *data, struct connectdata *conn, const char *protostr) { - const struct Curl_handler *p = Curl_get_scheme_handler(protostr); + const struct Curl_scheme *p = Curl_get_scheme(protostr); - if(p && /* Protocol found in table. Check if allowed */ + if(p && p->run && /* Protocol found supported. Check if allowed */ (data->set.allowed_protocols & p->protocol)) { /* it is allowed for "normal" request, now do an extra check if this is @@ -1640,7 +1492,7 @@ static CURLcode findprotocol(struct Curl_easy *data, ; else { /* Perform setup complement if some. */ - conn->handler = conn->given = p; + conn->scheme = conn->given = p; /* 'port' and 'remote_port' are set in setup_connection_internals() */ return CURLE_OK; } @@ -1850,7 +1702,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, if(!uc) { char *decoded; result = Curl_urldecode(data->state.up.password, 0, &decoded, NULL, - conn->handler->flags&PROTOPT_USERPWDCTRL ? + conn->scheme->flags&PROTOPT_USERPWDCTRL ? REJECT_ZERO : REJECT_CTRL); if(result) return result; @@ -1872,7 +1724,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, if(!uc) { char *decoded; result = Curl_urldecode(data->state.up.user, 0, &decoded, NULL, - conn->handler->flags&PROTOPT_USERPWDCTRL ? + conn->scheme->flags&PROTOPT_USERPWDCTRL ? REJECT_ZERO : REJECT_CTRL); if(result) return result; @@ -1982,8 +1834,8 @@ static CURLcode setup_connection_internals(struct Curl_easy *data, CURLcode result; DEBUGF(infof(data, "setup connection, bits.close=%d", conn->bits.close)); - if(conn->handler->setup_connection) { - result = conn->handler->setup_connection(data, conn); + if(conn->scheme->run->setup_connection) { + result = conn->scheme->run->setup_connection(data, conn); if(result) return result; } @@ -2054,7 +1906,7 @@ static char *detect_proxy(struct Curl_easy *data, const char *envp = proxy_env; curl_msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy", - conn->handler->scheme); + conn->scheme->name); /* read the protocol proxy: */ proxy = curl_getenv(proxy_env); @@ -2415,13 +2267,13 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, } #endif - if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) { + if(proxy && (!*proxy || (conn->scheme->flags & PROTOPT_NONETWORK))) { curlx_free(proxy); /* Do not bother with an empty proxy string or if the protocol does not work with network */ proxy = NULL; } if(socksproxy && (!*socksproxy || - (conn->handler->flags & PROTOPT_NONETWORK))) { + (conn->scheme->flags & PROTOPT_NONETWORK))) { curlx_free(socksproxy); /* Do not bother with an empty socks proxy string or if the protocol does not work with network */ @@ -2457,10 +2309,10 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, goto out; #else /* force this connection's protocol to become HTTP if compatible */ - if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) { - if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) && + if(!(conn->scheme->protocol & PROTO_FAMILY_HTTP)) { + if((conn->scheme->flags & PROTOPT_PROXY_AS_HTTP) && !conn->bits.tunnel_proxy) - conn->handler = &Curl_handler_http; + conn->scheme = &Curl_scheme_http; else /* if not converting to HTTP over the proxy, enforce tunneling */ conn->bits.tunnel_proxy = TRUE; @@ -2705,7 +2557,7 @@ static CURLcode override_login(struct Curl_easy *data, return CURLE_READ_ERROR; } else { - if(!(conn->handler->flags & PROTOPT_USERPWDCTRL)) { + if(!(conn->scheme->flags & PROTOPT_USERPWDCTRL)) { /* if the protocol cannot handle control codes in credentials, make sure there are none */ if(str_has_ctrl(*userp) || str_has_ctrl(*passwdp)) { @@ -2788,7 +2640,7 @@ static CURLcode set_login(struct Curl_easy *data, const char *setpasswd = CURL_DEFAULT_PASSWORD; /* If our protocol needs a password and we have none, use the defaults */ - if((conn->handler->flags & PROTOPT_NEEDSPWD) && !data->state.aptr.user) + if((conn->scheme->flags & PROTOPT_NEEDSPWD) && !data->state.aptr.user) ; else { setuser = ""; @@ -3025,7 +2877,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, #ifndef CURL_DISABLE_ALTSVC if(data->asi && !host && (port == -1) && - ((conn->handler->protocol == CURLPROTO_HTTPS) || + ((conn->scheme->protocol == CURLPROTO_HTTPS) || #ifdef DEBUGBUILD /* allow debug builds to circumvent the HTTPS restriction */ getenv("CURL_ALTSVC_HTTP") @@ -3533,15 +3385,15 @@ static CURLcode create_conn(struct Curl_easy *data, * file: is a special case in that it does not need a network connection ***********************************************************************/ #ifndef CURL_DISABLE_FILE - if(conn->handler->flags & PROTOPT_NONETWORK) { + if(conn->scheme->flags & PROTOPT_NONETWORK) { bool done; /* this is supposed to be the connect function so we better at least check that the file is present here! */ - DEBUGASSERT(conn->handler->connect_it); - data->info.conn_scheme = conn->handler->scheme; + DEBUGASSERT(conn->scheme->run->connect_it); + data->info.conn_scheme = conn->scheme->name; /* conn_protocol can only provide "old" protocols */ - data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK; - result = conn->handler->connect_it(data, &done); + data->info.conn_protocol = (conn->scheme->protocol) & CURLPROTO_MASK; + result = conn->scheme->run->connect_it(data, &done); if(result) goto out; @@ -3558,9 +3410,9 @@ static CURLcode create_conn(struct Curl_easy *data, } if(result) { - DEBUGASSERT(conn->handler->done); + DEBUGASSERT(conn->scheme->run->done); /* we ignore the return code for the protocol-specific DONE */ - (void)conn->handler->done(data, result, FALSE); + (void)conn->scheme->run->done(data, result, FALSE); } goto out; } @@ -3614,7 +3466,7 @@ static CURLcode create_conn(struct Curl_easy *data, #ifndef CURL_DISABLE_PROXY infof(data, "Reusing existing %s: connection%s with %s %s", - conn->given->scheme, + conn->given->name, tls_upgraded ? " (upgraded to SSL)" : "", conn->bits.proxy ? "proxy" : "host", conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname : @@ -3622,7 +3474,7 @@ static CURLcode create_conn(struct Curl_easy *data, conn->host.dispname); #else infof(data, "Reusing existing %s: connection%s with host %s", - conn->given->scheme, + conn->given->name, tls_upgraded ? " (upgraded to SSL)" : "", conn->host.dispname); #endif @@ -3633,7 +3485,7 @@ static CURLcode create_conn(struct Curl_easy *data, connections we are allowed to open. */ DEBUGF(infof(data, "new connection, bits.close=%d", conn->bits.close)); - if(conn->handler->flags & PROTOPT_ALPN) { + if(conn->scheme->flags & PROTOPT_ALPN) { /* The protocol wants it, so set the bits if enabled in the easy handle (default) */ if(data->set.ssl_enable_alpn) @@ -3733,9 +3585,9 @@ static CURLcode create_conn(struct Curl_easy *data, } /* persist the scheme and handler the transfer is using */ - data->info.conn_scheme = conn->handler->scheme; + data->info.conn_scheme = conn->scheme->name; /* conn_protocol can only provide "old" protocols */ - data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK; + data->info.conn_protocol = (conn->scheme->protocol) & CURLPROTO_MASK; data->info.used_proxy = #ifdef CURL_DISABLE_PROXY 0 @@ -3808,7 +3660,7 @@ CURLcode Curl_connect(struct Curl_easy *data, /* multiplexed */ *protocol_done = TRUE; } - else if(conn->handler->flags & PROTOPT_NONETWORK) { + else if(conn->scheme->flags & PROTOPT_NONETWORK) { *asyncp = FALSE; Curl_pgrsTime(data, TIMER_NAMELOOKUP); *protocol_done = TRUE; @@ -3859,7 +3711,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) use */ /* if the protocol used does not support wildcards, switch it off */ if(data->state.wildcardmatch && - !(conn->handler->flags & PROTOPT_WILDCARD)) + !(conn->scheme->flags & PROTOPT_WILDCARD)) data->state.wildcardmatch = FALSE; } diff --git a/lib/url.h b/lib/url.h index df80b93ab892..1e44ebe43bb0 100644 --- a/lib/url.h +++ b/lib/url.h @@ -71,9 +71,8 @@ void *Curl_conn_meta_get(struct connectdata *conn, const char *key); * @param scheme URI scheme, case-insensitive * @return NULL of handler not found */ -const struct Curl_handler *Curl_get_scheme_handler(const char *scheme); -const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, - size_t len); +const struct Curl_scheme *Curl_get_scheme(const char *scheme); +const struct Curl_scheme *Curl_getn_scheme(const char *scheme, size_t len); #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ #define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless diff --git a/lib/urlapi.c b/lib/urlapi.c index c7c48ed79892..9899f6aff39e 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -256,7 +256,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, char *userp = NULL; char *passwdp = NULL; char *optionsp = NULL; - const struct Curl_handler *h = NULL; + const struct Curl_scheme *h = NULL; /* At this point, we assume all the other special cases have been taken * care of, so the host is at most @@ -281,7 +281,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, /* if this is a known scheme, get some details */ if(u->scheme) - h = Curl_get_scheme_handler(u->scheme); + h = Curl_get_scheme(u->scheme); /* We could use the login information in the URL so extract it. Only parse options if the handler says we should. Note that 'h' might be NULL! */ @@ -948,7 +948,7 @@ static CURLUcode parse_scheme(const char *url, CURLU *u, char *schemebuf, } schemep = schemebuf; - if(!Curl_get_scheme_handler(schemep) && + if(!Curl_get_scheme(schemep) && !(flags & CURLU_NON_SUPPORT_SCHEME)) return CURLUE_UNSUPPORTED_SCHEME; @@ -1448,7 +1448,7 @@ static CURLUcode urlget_url(const CURLU *u, char **part, unsigned int flags) else if(!u->host) return CURLUE_NO_HOST; else { - const struct Curl_handler *h = NULL; + const struct Curl_scheme *h = NULL; char schemebuf[MAX_SCHEME_LEN + 5]; if(u->scheme) scheme = u->scheme; @@ -1457,7 +1457,7 @@ static CURLUcode urlget_url(const CURLU *u, char **part, unsigned int flags) else return CURLUE_NO_SCHEME; - h = Curl_get_scheme_handler(scheme); + h = Curl_get_scheme(scheme); if(!port && (flags & CURLU_DEFAULT_PORT)) { /* there is no stored port number, but asked to deliver a default one for the scheme */ @@ -1586,7 +1586,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what, if(!ptr && (flags & CURLU_DEFAULT_PORT) && u->scheme) { /* there is no stored port number, but asked to deliver a default one for the scheme */ - const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme); + const struct Curl_scheme *h = Curl_get_scheme(u->scheme); if(h) { curl_msnprintf(portbuf, sizeof(portbuf), "%u", h->defport); ptr = portbuf; @@ -1595,7 +1595,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what, else if(ptr && u->scheme) { /* there is a stored port number, but ask to inhibit if it matches the default one for the scheme */ - const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme); + const struct Curl_scheme *h = Curl_get_scheme(u->scheme); if(h && (h->defport == u->portnum) && (flags & CURLU_NO_DEFAULT_PORT)) ptr = NULL; @@ -1637,16 +1637,16 @@ static CURLUcode set_url_scheme(CURLU *u, const char *scheme, unsigned int flags) { size_t plen = strlen(scheme); - const struct Curl_handler *h = NULL; + const struct Curl_scheme *h = NULL; if((plen > MAX_SCHEME_LEN) || (plen < 1)) /* too long or too short */ return CURLUE_BAD_SCHEME; /* verify that it is a fine scheme */ - h = Curl_get_scheme_handler(scheme); + h = Curl_get_scheme(scheme); + if(!(flags & CURLU_NON_SUPPORT_SCHEME) && (!h || !h->run)) + return CURLUE_UNSUPPORTED_SCHEME; if(!h) { const char *s = scheme; - if(!(flags & CURLU_NON_SUPPORT_SCHEME)) - return CURLUE_UNSUPPORTED_SCHEME; if(ISALPHA(*s)) { /* ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */ while(--plen) { diff --git a/lib/urldata.h b/lib/urldata.h index a3a37a8e039e..f423d3376739 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -427,9 +427,7 @@ struct hostname { * Specific protocol handler. */ -struct Curl_handler { - const char *scheme; /* URL scheme name in lowercase */ - +struct Curl_protocol { /* Complement to setup_connection_internals(). This is done before the transfer "owns" the connection. */ CURLcode (*setup_connection)(struct Curl_easy *data, @@ -514,14 +512,17 @@ struct Curl_handler { the way the follow request is performed. */ CURLcode (*follow)(struct Curl_easy *data, const char *newurl, followtype type); +}; - uint16_t defport; /* Default port. */ +struct Curl_scheme { + const char *name; /* URL scheme name in lowercase */ + const struct Curl_protocol *run; /* implementation */ curl_prot_t protocol; /* See CURLPROTO_* - this needs to be the single specific protocol bit */ curl_prot_t family; /* single bit for protocol family; basically the non-TLS name of the protocol this is */ - uint32_t flags; /* Extra particular characteristics, see PROTOPT_* */ - + uint32_t flags; /* Extra particular characteristics, see PROTOPT_* */ + uint16_t defport; /* Default port. */ }; #define PROTOPT_NONE 0 /* nothing extra */ @@ -659,8 +660,8 @@ struct connectdata { #endif struct ConnectBits bits; /* various state-flags for this connection */ - const struct Curl_handler *handler; /* Connection's protocol handler */ - const struct Curl_handler *given; /* The protocol first given */ + const struct Curl_scheme *scheme; /* Connection's protocol handler */ + const struct Curl_scheme *given; /* The protocol first given */ /* Protocols can use a custom keepalive mechanism to keep connections alive. This allows those protocols to track the last time the keepalive mechanism diff --git a/lib/vauth/vauth.c b/lib/vauth/vauth.c index 5c2ae8db1e23..112838b0ccaf 100644 --- a/lib/vauth/vauth.c +++ b/lib/vauth/vauth.c @@ -143,7 +143,7 @@ bool Curl_auth_allowed_to_host(struct Curl_easy *data) (data->state.first_host && curl_strequal(data->state.first_host, conn->host.name) && (data->state.first_remote_port == conn->remote_port) && - (data->state.first_remote_protocol == conn->handler->protocol)); + (data->state.first_remote_protocol == conn->scheme->protocol)); } #ifdef USE_NTLM diff --git a/lib/vquic/vquic.c b/lib/vquic/vquic.c index 9d45833820d7..3cc2eb98a3bc 100644 --- a/lib/vquic/vquic.c +++ b/lib/vquic/vquic.c @@ -719,7 +719,7 @@ CURLcode Curl_conn_may_http3(struct Curl_easy *data, /* cannot do QUIC over a Unix domain socket */ return CURLE_QUIC_CONNECT_ERROR; } - if(!(conn->handler->flags & PROTOPT_SSL)) { + if(!(conn->scheme->flags & PROTOPT_SSL)) { failf(data, "HTTP/3 requested for non-HTTPS URL"); return CURLE_URL_MALFORMAT; } diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c index 52063445283c..5a2c9203f2da 100644 --- a/lib/vssh/libssh.c +++ b/lib/vssh/libssh.c @@ -1034,7 +1034,7 @@ static int myssh_in_AUTH_DONE(struct Curl_easy *data, conn->recv_idx = FIRSTSOCKET; conn->send_idx = -1; - if(conn->handler->protocol == CURLPROTO_SFTP) { + if(conn->scheme->protocol == CURLPROTO_SFTP) { myssh_to(data, sshc, SSH_SFTP_INIT); return SSH_NO_ERROR; } @@ -2501,7 +2501,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done) return CURLE_FAILED_INIT; CURL_TRC_SSH(data, "myssh_connect"); - if(conn->handler->protocol & CURLPROTO_SCP) { + if(conn->scheme->protocol & CURLPROTO_SCP) { conn->recv[FIRSTSOCKET] = scp_recv; conn->send[FIRSTSOCKET] = scp_send; } @@ -3034,7 +3034,7 @@ static CURLcode myssh_do_it(struct Curl_easy *data, bool *done) Curl_pgrsReset(data); - if(conn->handler->protocol & CURLPROTO_SCP) + if(conn->scheme->protocol & CURLPROTO_SCP) result = scp_perform(data, &connected, done); else result = sftp_perform(data, &connected, done); @@ -3062,10 +3062,9 @@ void Curl_ssh_version(char *buffer, size_t buflen) } /* - * SCP protocol handler. + * SCP. */ -const struct Curl_handler Curl_handler_scp = { - "SCP", /* scheme */ +const struct Curl_protocol Curl_protocol_scp = { myssh_setup_connection, /* setup_connection */ myssh_do_it, /* do_it */ scp_done, /* done */ @@ -3083,18 +3082,12 @@ const struct Curl_handler Curl_handler_scp = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_SSH, /* defport */ - CURLPROTO_SCP, /* protocol */ - CURLPROTO_SCP, /* family */ - PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ - PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE }; /* - * SFTP protocol handler. + * SFTP. */ -const struct Curl_handler Curl_handler_sftp = { - "SFTP", /* scheme */ +const struct Curl_protocol Curl_protocol_sftp = { myssh_setup_connection, /* setup_connection */ myssh_do_it, /* do_it */ sftp_done, /* done */ @@ -3112,11 +3105,6 @@ const struct Curl_handler Curl_handler_sftp = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ ZERO_NULL, /* follow */ - PORT_SSH, /* defport */ - CURLPROTO_SFTP, /* protocol */ - CURLPROTO_SFTP, /* family */ - PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ - PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE }; #endif /* USE_LIBSSH */ diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c index 7362b420d30f..a0f6cd243c05 100644 --- a/lib/vssh/libssh2.c +++ b/lib/vssh/libssh2.c @@ -1858,7 +1858,7 @@ static CURLcode ssh_state_auth_done(struct Curl_easy *data, data->conn->recv_idx = FIRSTSOCKET; conn->send_idx = -1; - if(conn->handler->protocol == CURLPROTO_SFTP) { + if(conn->scheme->protocol == CURLPROTO_SFTP) { myssh_state(data, sshc, SSH_SFTP_INIT); return CURLE_OK; } @@ -3478,7 +3478,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) } #endif /* CURL_DISABLE_PROXY */ - if(conn->handler->protocol & CURLPROTO_SCP) { + if(conn->scheme->protocol & CURLPROTO_SCP) { conn->recv[FIRSTSOCKET] = scp_recv; conn->send[FIRSTSOCKET] = scp_send; } @@ -3867,7 +3867,7 @@ static CURLcode ssh_do(struct Curl_easy *data, bool *done) Curl_pgrsReset(data); - if(conn->handler->protocol & CURLPROTO_SCP) + if(conn->scheme->protocol & CURLPROTO_SCP) result = scp_perform(data, &connected, done); else result = sftp_perform(data, &connected, done); @@ -3902,7 +3902,7 @@ static void ssh_attach(struct Curl_easy *data, struct connectdata *conn) { DEBUGASSERT(data); DEBUGASSERT(conn); - if(conn->handler->protocol & PROTO_FAMILY_SSH) { + if(conn->scheme->protocol & PROTO_FAMILY_SSH) { struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN); if(sshc && sshc->ssh_session) { /* only re-attach if the session already exists */ @@ -3915,8 +3915,7 @@ static void ssh_attach(struct Curl_easy *data, struct connectdata *conn) /* * SCP protocol handler. */ -const struct Curl_handler Curl_handler_scp = { - "SCP", /* scheme */ +const struct Curl_protocol Curl_protocol_scp = { ssh_setup_connection, /* setup_connection */ ssh_do, /* do_it */ scp_done, /* done */ @@ -3934,18 +3933,12 @@ const struct Curl_handler Curl_handler_scp = { ZERO_NULL, /* connection_check */ ssh_attach, /* attach */ ZERO_NULL, /* follow */ - PORT_SSH, /* defport */ - CURLPROTO_SCP, /* protocol */ - CURLPROTO_SCP, /* family */ - PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ - PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE }; /* * SFTP protocol handler. */ -const struct Curl_handler Curl_handler_sftp = { - "SFTP", /* scheme */ +const struct Curl_protocol Curl_protocol_sftp = { ssh_setup_connection, /* setup_connection */ ssh_do, /* do_it */ sftp_done, /* done */ @@ -3963,11 +3956,6 @@ const struct Curl_handler Curl_handler_sftp = { ZERO_NULL, /* connection_check */ ssh_attach, /* attach */ ZERO_NULL, /* follow */ - PORT_SSH, /* defport */ - CURLPROTO_SFTP, /* protocol */ - CURLPROTO_SFTP, /* family */ - PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ - PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE }; #endif /* USE_LIBSSH2 */ diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h index 6fdf3f794bc1..d98070856c80 100644 --- a/lib/vssh/ssh.h +++ b/lib/vssh/ssh.h @@ -1,5 +1,5 @@ -#ifndef HEADER_CURL_SSH_H -#define HEADER_CURL_SSH_H +#ifndef HEADER_CURL_VSSH_SSH_H +#define HEADER_CURL_VSSH_SSH_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -25,6 +25,12 @@ ***************************************************************************/ #include "../curl_setup.h" +extern const struct Curl_protocol Curl_protocol_sftp; +extern const struct Curl_protocol Curl_protocol_scp; + +extern const struct Curl_scheme Curl_scheme_sftp; +extern const struct Curl_scheme Curl_scheme_scp; + #ifdef USE_LIBSSH2 #include #include @@ -232,9 +238,6 @@ struct ssh_conn { #ifdef USE_SSH -extern const struct Curl_handler Curl_handler_scp; -extern const struct Curl_handler Curl_handler_sftp; - /* generic SSH backend functions */ CURLcode Curl_ssh_init(void); void Curl_ssh_cleanup(void); diff --git a/lib/vssh/vssh.c b/lib/vssh/vssh.c index 77fa89b557e6..f51669906b97 100644 --- a/lib/vssh/vssh.c +++ b/lib/vssh/vssh.c @@ -23,9 +23,9 @@ ***************************************************************************/ #include "../curl_setup.h" -#ifdef USE_SSH - #include "vssh.h" +#include "ssh.h" +#ifdef USE_SSH #include "../curlx/strparse.h" #include "../curl_trc.h" #include "../escape.h" @@ -51,7 +51,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, curlx_dyn_init(&npath, MAX_SSHPATH_LEN); /* Check for /~/, indicating relative to the user's home directory */ - if((data->conn->handler->protocol & CURLPROTO_SCP) && + if((data->conn->scheme->protocol & CURLPROTO_SCP) && (working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) { /* It is referenced to the home directory, so strip the leading '/~/' */ if(curlx_dyn_addn(&npath, &working_path[3], working_path_len - 3)) { @@ -59,7 +59,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } } - else if((data->conn->handler->protocol & CURLPROTO_SFTP) && + else if((data->conn->scheme->protocol & CURLPROTO_SFTP) && (!strcmp("/~", working_path) || ((working_path_len > 2) && !memcmp(working_path, "/~/", 3)))) { if(curlx_dyn_add(&npath, homedir)) { @@ -239,3 +239,34 @@ CURLcode Curl_ssh_range(struct Curl_easy *data, } #endif /* USE_SSH */ + +/* + * SFTP protocol handler. + */ +const struct Curl_scheme Curl_scheme_sftp = { + "SFTP", /* scheme */ +#ifndef USE_SSH + NULL, +#else + &Curl_protocol_sftp, +#endif + CURLPROTO_SFTP, /* protocol */ + CURLPROTO_SFTP, /* family */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ + PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE, + PORT_SSH /* defport */ +}; + +const struct Curl_scheme Curl_scheme_scp = { + "SCP", /* scheme */ +#ifndef USE_SSH + NULL, +#else + &Curl_protocol_scp, +#endif + CURLPROTO_SCP, /* protocol */ + CURLPROTO_SCP, /* family */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ + PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE, + PORT_SSH, /* defport */ +}; diff --git a/lib/vssh/vssh.h b/lib/vssh/vssh.h index 4bc6d808074a..f3a4873e7f3e 100644 --- a/lib/vssh/vssh.h +++ b/lib/vssh/vssh.h @@ -1,5 +1,5 @@ -#ifndef HEADER_CURL_PATH_H -#define HEADER_CURL_PATH_H +#ifndef HEADER_CURL_VSSH_VSSH_H +#define HEADER_CURL_VSSH_VSSH_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -37,4 +37,4 @@ CURLcode Curl_ssh_range(struct Curl_easy *data, const char *range, curl_off_t filesize, curl_off_t *startp, curl_off_t *sizep); -#endif /* HEADER_CURL_PATH_H */ +#endif /* HEADER_CURL_VSSH_VSSH_H */ diff --git a/lib/ws.c b/lib/ws.c index d3e004fcf079..f9075f518f01 100644 --- a/lib/ws.c +++ b/lib/ws.c @@ -22,10 +22,16 @@ * ***************************************************************************/ #include "curl_setup.h" +#include "urldata.h" -#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) +#ifdef CURL_DISABLE_HTTP +/* no WebSockets without HTTP present */ +#undef CURL_DISABLE_WEBSOCKETS +#define CURL_DISABLE_WEBSOCKETS 1 +#endif + +#ifndef CURL_DISABLE_WEBSOCKETS -#include "urldata.h" #include "url.h" #include "bufq.h" #include "curlx/dynbuf.h" @@ -1904,8 +1910,7 @@ CURL_EXTERN CURLcode curl_ws_start_frame(CURL *d, return result; } -const struct Curl_handler Curl_handler_ws = { - "WS", /* scheme */ +static const struct Curl_protocol Curl_protocol_ws = { ws_setup_conn, /* setup_connection */ Curl_http, /* do_it */ Curl_http_done, /* done */ @@ -1923,40 +1928,7 @@ const struct Curl_handler Curl_handler_ws = { ZERO_NULL, /* connection_check */ ZERO_NULL, /* attach connection */ Curl_http_follow, /* follow */ - PORT_HTTP, /* defport */ - CURLPROTO_WS, /* protocol */ - CURLPROTO_HTTP, /* family */ - PROTOPT_CREDSPERREQUEST | /* flags */ - PROTOPT_USERPWDCTRL -}; - -#ifdef USE_SSL -const struct Curl_handler Curl_handler_wss = { - "WSS", /* scheme */ - ws_setup_conn, /* setup_connection */ - Curl_http, /* do_it */ - Curl_http_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - NULL, /* connecting */ - ZERO_NULL, /* doing */ - NULL, /* proto_pollset */ - Curl_http_doing_pollset, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - Curl_http_perform_pollset, /* perform_pollset */ - ZERO_NULL, /* disconnect */ - Curl_http_write_resp, /* write_resp */ - Curl_http_write_resp_hd, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - Curl_http_follow, /* follow */ - PORT_HTTPS, /* defport */ - CURLPROTO_WSS, /* protocol */ - CURLPROTO_HTTP, /* family */ - PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */ - PROTOPT_USERPWDCTRL }; -#endif #else @@ -2002,4 +1974,33 @@ CURL_EXTERN CURLcode curl_ws_start_frame(CURL *curl, return CURLE_NOT_BUILT_IN; } -#endif /* !CURL_DISABLE_WEBSOCKETS && !CURL_DISABLE_HTTP */ +#endif /* !CURL_DISABLE_WEBSOCKETS */ + +const struct Curl_scheme Curl_scheme_ws = { + "WS", /* scheme */ +#ifdef CURL_DISABLE_WEBSOCKETS + ZERO_NULL, +#else + &Curl_protocol_ws, +#endif + CURLPROTO_WS, /* protocol */ + CURLPROTO_HTTP, /* family */ + PROTOPT_CREDSPERREQUEST | /* flags */ + PROTOPT_USERPWDCTRL, + PORT_HTTP /* defport */ +} +; + +const struct Curl_scheme Curl_scheme_wss = { + "WSS", /* scheme */ +#if defined(CURL_DISABLE_WEBSOCKETS) || !defined(USE_SSL) + ZERO_NULL, +#else + &Curl_protocol_ws, +#endif + CURLPROTO_WSS, /* protocol */ + CURLPROTO_HTTP, /* family */ + PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */ + PROTOPT_USERPWDCTRL, + PORT_HTTPS /* defport */ +}; diff --git a/lib/ws.h b/lib/ws.h index a6e770694dee..d4d6d46f3a51 100644 --- a/lib/ws.h +++ b/lib/ws.h @@ -25,6 +25,9 @@ ***************************************************************************/ #include "curl_setup.h" +extern const struct Curl_scheme Curl_scheme_ws; +extern const struct Curl_scheme Curl_scheme_wss; + #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) /* meta key for storing protocol meta at connection */ @@ -33,11 +36,6 @@ CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req); CURLcode Curl_ws_accept(struct Curl_easy *data, const char *mem, size_t len); -extern const struct Curl_handler Curl_handler_ws; -#ifdef USE_SSL -extern const struct Curl_handler Curl_handler_wss; -#endif - #else #define Curl_ws_request(x, y) CURLE_OK #define Curl_ws_free(x) Curl_nop_stmt diff --git a/scripts/schemetable.c b/scripts/schemetable.c index dded8dc753fa..49660c94d326 100644 --- a/scripts/schemetable.c +++ b/scripts/schemetable.c @@ -29,53 +29,41 @@ * function in url.c. */ -struct detail { - const char *n; - const char *ifdef; -}; - -static const struct detail scheme[] = { - { "dict", "#ifndef CURL_DISABLE_DICT" }, - { "file", "#ifndef CURL_DISABLE_FILE" }, - { "ftp", "#ifndef CURL_DISABLE_FTP" }, - { "ftps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)" }, - { "gopher", "#ifndef CURL_DISABLE_GOPHER" }, - { "gophers", "#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)" }, - { "http", "#ifndef CURL_DISABLE_HTTP" }, - { "https", "#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" }, - { "imap", "#ifndef CURL_DISABLE_IMAP" }, - { "imaps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)" }, - { "ldap", "#ifndef CURL_DISABLE_LDAP" }, - { "ldaps", "#if !defined(CURL_DISABLE_LDAP) && \\\n" - " !defined(CURL_DISABLE_LDAPS) && \\\n" - " ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \\\n" - " (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))" }, - { "mqtt", "#ifndef CURL_DISABLE_MQTT" }, - { "mqtts", "#if defined(USE_SSL) && !defined(CURL_DISABLE_MQTT)" }, - { "pop3", "#ifndef CURL_DISABLE_POP3" }, - { "pop3s", "#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)" }, - { "rtmp", "#ifdef USE_LIBRTMP" }, - { "rtmpt", "#ifdef USE_LIBRTMP" }, - { "rtmpe", "#ifdef USE_LIBRTMP" }, - { "rtmpte", "#ifdef USE_LIBRTMP" }, - { "rtmps", "#ifdef USE_LIBRTMP" }, - { "rtmpts", "#ifdef USE_LIBRTMP" }, - { "rtsp", "#ifndef CURL_DISABLE_RTSP" }, - { "scp", "#ifdef USE_SSH" }, - { "sftp", "#ifdef USE_SSH" }, - { "smb", "#if !defined(CURL_DISABLE_SMB) && \\\n" - " defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)" }, - { "smbs", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \\\n" - " defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)" }, - { "smtp", "#ifndef CURL_DISABLE_SMTP" }, - { "smtps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)" }, - { "telnet", "#ifndef CURL_DISABLE_TELNET" }, - { "tftp", "#ifndef CURL_DISABLE_TFTP" }, - { "ws", - "#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)" }, - { "wss", "#if !defined(CURL_DISABLE_WEBSOCKETS) && \\\n" - " defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" }, - { NULL, NULL } +static const char *scheme[] = { + "dict", + "file", + "ftp", + "ftps", + "gopher", + "gophers", + "http", + "https", + "imap", + "imaps", + "ldap", + "ldaps", + "mqtt", + "mqtts", + "pop3", + "pop3s", + "rtmp", + "rtmpt", + "rtmpe", + "rtmpte", + "rtmps", + "rtmpts", + "rtsp", + "scp", + "sftp", + "smb", + "smbs", + "smtp", + "smtps", + "telnet", + "tftp", + "ws", + "wss", + NULL, }; unsigned int calc(const char *s, int add, int shift) @@ -97,9 +85,9 @@ static void showtable(int try, int init, int shift) { int nulls = 0; int i; - for(i = 0; scheme[i].n; ++i) - num[i] = calc(scheme[i].n, init, shift); - for(i = 0; scheme[i].n; ++i) + for(i = 0; scheme[i]; ++i) + num[i] = calc(scheme[i], init, shift); + for(i = 0; scheme[i]; ++i) ix[i] = num[i] % try; printf("/*\n" " unsigned int c = %d\n" @@ -112,32 +100,22 @@ static void showtable(int try, int init, int shift) "*/\n", init, shift); - printf(" static const struct Curl_handler * const protocols[%d] = {", try); + printf(" static const struct Curl_scheme * const all_schemes[%d] = {", try); /* generate table */ for(i = 0; i < try; i++) { int match = 0; int j; - for(j = 0; scheme[j].n; j++) { + for(j = 0; scheme[j]; j++) { if(ix[j] == i) { - printf("\n"); - printf("%s\n", scheme[j].ifdef); - printf(" &Curl_handler_%s,\n", scheme[j].n); - printf("#else\n NULL,\n"); - printf("#endif"); + printf("\n &Curl_scheme_%s,", scheme[j]); match = 1; nulls = 0; break; } } - if(!match) { - if(!nulls || (nulls > 10)) { - printf("\n "); - nulls = 0; - } - printf(" NULL,", nulls); - nulls++; - } + if(!match) + printf(" NULL,"); } printf("\n };\n"); } @@ -153,8 +131,8 @@ int main(void) int shift; for(shift = 0; shift < 8; shift++) { for(add = 0; add < 999; add++) { - for(i = 0; scheme[i].n; ++i) { - unsigned int v = calc(scheme[i].n, add, shift); + for(i = 0; scheme[i]; ++i) { + unsigned int v = calc(scheme[i], add, shift); int j; int badcombo = 0; for(j = 0; j < i; j++) { @@ -180,11 +158,11 @@ int main(void) /* try different remainders to find smallest possible table */ for(try = 28; try < 199; try++) { int good = 1; - for(i = 0; scheme[i].n; ++i) { + for(i = 0; scheme[i]; ++i) { ix[i] = num[i] % try; } /* check for dupes */ - for(i = 0; scheme[i].n && good; ++i) { + for(i = 0; scheme[i] && good; ++i) { int j; for(j = 0; j < i; j++) { if(ix[j] == ix[i]) { From 1cacfcd30f52ccc630b941514830925bc9c5053a Mon Sep 17 00:00:00 2001 From: tommy Date: Tue, 13 Jan 2026 12:48:17 +0800 Subject: [PATCH 3/4] sigpipe: unset SA_SIGINFO since it is using sa_handler Closes #20278 Signed-off-by: tommy --- lib/sigpipe.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/sigpipe.h b/lib/sigpipe.h index 2fd211c51429..9fe13af92b64 100644 --- a/lib/sigpipe.h +++ b/lib/sigpipe.h @@ -58,6 +58,8 @@ static CURL_INLINE void sigpipe_ignore(struct Curl_easy *data, action = ig->old_pipe_act; /* ignore this signal */ action.sa_handler = SIG_IGN; + /* clear SA_SIGINFO flag since we are using sa_handler */ + action.sa_flags &= ~SA_SIGINFO; sigaction(SIGPIPE, &action, NULL); } } From e8189c44201db6bff987a8771df90f853d93dec5 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Mon, 19 Jan 2026 23:21:30 +0100 Subject: [PATCH 4/4] tool_getparam: avoid `-Wcomma` with Apple clang in C89 mode Seen with Apple clang 17: ``` curl/src/tool_getparam.c:3062:12: warning: possible misuse of comma operator here [-Wcomma] 3062 | for(i = 1, stillflags = TRUE; i < argc && !result; i++) { | ^ curl/src/tool_getparam.c:3062:7: note: cast expression to void to silence warning 3062 | for(i = 1, stillflags = TRUE; i < argc && !result; i++) { | ^~~~~ | (void)( ) ``` Closes #20362 --- src/tool_getparam.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 56f4d58f7338..54b209869dbc 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -3059,7 +3059,8 @@ ParameterError parse_args(int argc, argv_item_t argv[]) ParameterError result = PARAM_OK; struct OperationConfig *config = global->first; - for(i = 1, stillflags = TRUE; i < argc && !result; i++) { + stillflags = TRUE; + for(i = 1; i < argc && !result; i++) { orig_opt = convert_tchar_to_UTF8(argv[i]); if(!orig_opt) return PARAM_NO_MEM;