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
This commit is contained in:
Daniel Stenberg 2026-01-19 00:15:41 +01:00
parent 63baa10951
commit 8edc0338f3
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
59 changed files with 831 additions and 1040 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -428,7 +428,7 @@ connect_sub_chain:
#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)

View file

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

View file

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

View file

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

View file

@ -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 */
CURLPROTO_RTMP, /* protocol */
CURLPROTO_RTMP, /* family */
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_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 */
CURLPROTO_RTMPT, /* protocol */
CURLPROTO_RTMPT, /* family */
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_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 */
CURLPROTO_RTMPE, /* protocol */
CURLPROTO_RTMPE, /* family */
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_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 */
CURLPROTO_RTMPTE, /* protocol */
CURLPROTO_RTMPTE, /* family */
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_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 */
CURLPROTO_RTMPS, /* protocol */
CURLPROTO_RTMP, /* family */
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_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 */
CURLPROTO_RTMPTS, /* protocol */
CURLPROTO_RTMPT, /* family */
PROTOPT_NONE /* flags */
};
#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 */
PORT_RTMP, /* defport */
};
const struct Curl_scheme Curl_scheme_rtmpt = {
"rtmpt", /* scheme */
#ifndef USE_LIBRTMP
ZERO_NULL,
#else
&Curl_protocol_rtmp,
#endif
CURLPROTO_RTMPT, /* protocol */
CURLPROTO_RTMPT, /* family */
PROTOPT_NONE, /* flags */
PORT_RTMPT, /* defport */
};
const struct Curl_scheme Curl_scheme_rtmpe = {
"rtmpe", /* scheme */
#ifndef USE_LIBRTMP
ZERO_NULL,
#else
&Curl_protocol_rtmp,
#endif
CURLPROTO_RTMPE, /* protocol */
CURLPROTO_RTMPE, /* family */
PROTOPT_NONE, /* flags */
PORT_RTMP, /* defport */
};
const struct Curl_scheme Curl_scheme_rtmpte = {
"rtmpte", /* scheme */
#ifndef USE_LIBRTMP
ZERO_NULL,
#else
&Curl_protocol_rtmp,
#endif
CURLPROTO_RTMPTE, /* protocol */
CURLPROTO_RTMPTE, /* family */
PROTOPT_NONE, /* flags */
PORT_RTMPT, /* defport */
};
const struct Curl_scheme Curl_scheme_rtmps = {
"rtmps", /* scheme */
#ifndef USE_LIBRTMP
ZERO_NULL,
#else
&Curl_protocol_rtmp,
#endif
CURLPROTO_RTMPS, /* protocol */
CURLPROTO_RTMP, /* family */
PROTOPT_NONE, /* flags */
PORT_RTMPS, /* defport */
};
const struct Curl_scheme Curl_scheme_rtmpts = {
"rtmpts", /* scheme */
#ifndef USE_LIBRTMP
ZERO_NULL,
#else
&Curl_protocol_rtmp,
#endif
CURLPROTO_RTMPTS, /* protocol */
CURLPROTO_RTMPT, /* family */
PROTOPT_NONE, /* flags */
PORT_RTMPS, /* defport */
};

View file

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

View file

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

View file

@ -22,6 +22,8 @@
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#include "dict.h"
#ifndef CURL_DISABLE_DICT
@ -51,11 +53,9 @@
#include <unistd.h>
#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 @@ error:
}
/*
* 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 */
};

View file

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

View file

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

View file

@ -22,6 +22,8 @@
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#include "file.h"
#ifndef CURL_DISABLE_FILE
@ -53,12 +55,10 @@
#include <dirent.h>
#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 @@ out:
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 */
};

View file

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

View file

@ -22,6 +22,7 @@
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#ifndef CURL_DISABLE_FTP
@ -39,7 +40,6 @@
#include <inet.h>
#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 */

View file

@ -27,13 +27,10 @@
#include "pingpong.h"
extern const struct Curl_scheme Curl_scheme_ftp;
extern const struct Curl_scheme Curl_scheme_ftps;
#ifndef CURL_DISABLE_FTP
extern const struct Curl_handler Curl_handler_ftp;
#ifdef USE_SSL
extern const struct Curl_handler Curl_handler_ftps;
#endif
bool ftp_conns_match(struct connectdata *needle, struct connectdata *conn);
#endif /* CURL_DISABLE_FTP */

View file

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

View file

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

View file

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

View file

@ -22,6 +22,7 @@
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#ifndef CURL_DISABLE_HTTP
@ -46,7 +47,6 @@
#include <sys/param.h>
#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 */

View file

@ -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 <stdint.h>
#endif
extern const struct Curl_handler Curl_handler_http;
#ifdef USE_SSL
extern const struct Curl_handler Curl_handler_https;
#endif
struct dynhds;

View file

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

View file

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

View file

@ -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 */
CURLPROTO_LDAP, /* protocol */
CURLPROTO_LDAP, /* family */
PROTOPT_SSL_REUSE /* flags */
};
#ifdef HAVE_LDAP_SSL
/*
* LDAPS protocol handler.
*/
const struct Curl_handler Curl_handler_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 */
CURLPROTO_LDAPS, /* protocol */
CURLPROTO_LDAP, /* family */
PROTOPT_SSL /* flags */
};
#endif
#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 */
PORT_LDAP, /* defport */
};
/*
* LDAPS
*/
const struct Curl_scheme Curl_scheme_ldaps = {
"ldaps", /* scheme */
#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 */
PORT_LDAPS, /* defport */
};

View file

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

View file

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

View file

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

View file

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

View file

@ -37,6 +37,8 @@
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#include "pop3.h"
#ifndef CURL_DISABLE_POP3
@ -54,7 +56,6 @@
#include <inet.h>
#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 */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 */
CURLPROTO_SMB, /* protocol */
CURLPROTO_SMB, /* family */
PROTOPT_CONN_REUSE /* flags */
};
#ifdef USE_SSL
#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 */
PORT_SMB, /* defport */
};
/*
* 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 */

View file

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

View file

@ -39,6 +39,8 @@
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#include "smtp.h"
#ifndef CURL_DISABLE_SMTP
@ -56,7 +58,6 @@
#include <inet.h>
#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 @@ out:
/*
* 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 */

View file

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

View file

@ -22,6 +22,8 @@
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#include "telnet.h"
#ifndef CURL_DISABLE_TELNET
@ -45,12 +47,10 @@
#include <sys/param.h>
#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 */
};

View file

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

View file

@ -22,6 +22,7 @@
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#ifndef CURL_DISABLE_TFTP
@ -45,7 +46,6 @@
#include <sys/param.h>
#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 */
};

View file

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

View file

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

352
lib/url.c
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 <libssh2.h>
#include <libssh2_sftp.h>
@ -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);

View file

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

View file

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

View file

@ -22,10 +22,16 @@
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
#include "urldata.h"
#ifdef CURL_DISABLE_HTTP
/* no WebSockets without HTTP present */
#undef CURL_DISABLE_WEBSOCKETS
#define CURL_DISABLE_WEBSOCKETS 1
#endif
#ifndef CURL_DISABLE_WEBSOCKETS
#include "url.h"
#include "bufq.h"
#include "curlx/dynbuf.h"
@ -1904,8 +1910,7 @@ out:
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,41 +1928,8 @@ 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
CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
@ -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 */
};

View file

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

View file

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