diff --git a/CMakeLists.txt b/CMakeLists.txt index c67d187e12..a4da8e4076 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1947,6 +1947,7 @@ curl_add_if("IPNS" NOT CURL_DISABLE_IPFS) curl_add_if("RTSP" NOT CURL_DISABLE_RTSP) curl_add_if("RTMP" USE_LIBRTMP) curl_add_if("MQTT" NOT CURL_DISABLE_MQTT) +curl_add_if("MQTTS" NOT CURL_DISABLE_MQTT AND _ssl_enabled) curl_add_if("WS" NOT CURL_DISABLE_WEBSOCKETS) curl_add_if("WSS" NOT CURL_DISABLE_WEBSOCKETS AND _ssl_enabled) if(_items) diff --git a/configure.ac b/configure.ac index 2700158326..fcb13c6614 100644 --- a/configure.ac +++ b/configure.ac @@ -5448,6 +5448,9 @@ if test "$CURL_DISABLE_GOPHER" != "1"; then fi if test "$CURL_DISABLE_MQTT" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS MQTT" + if test "$SSL_ENABLED" = "1"; then + SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS MQTTS" + fi fi if test "$CURL_DISABLE_POP3" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS POP3" diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index e0e0a8e63a..1859fe184a 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -968,6 +968,7 @@ CURLPROTO_IMAPS 7.20.0 CURLPROTO_LDAP 7.19.4 CURLPROTO_LDAPS 7.19.4 CURLPROTO_MQTT 7.71.0 +CURLPROTO_MQTTS 8.19.0 CURLPROTO_POP3 7.20.0 CURLPROTO_POP3S 7.20.0 CURLPROTO_RTMP 7.21.0 diff --git a/include/curl/curl.h b/include/curl/curl.h index 250f3f679a..cedae82ed7 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1100,6 +1100,7 @@ typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy, #define CURLPROTO_SMBS (1L<<27) #define CURLPROTO_MQTT (1L<<28) #define CURLPROTO_GOPHERS (1L<<29) +#define CURLPROTO_MQTTS (1L<<30) #define CURLPROTO_ALL (~0L) /* enable everything */ /* long may be 32 or 64 bits, but we should never depend on anything else diff --git a/lib/mqtt.c b/lib/mqtt.c index 7587d373b6..9daa59e663 100644 --- a/lib/mqtt.c +++ b/lib/mqtt.c @@ -39,6 +39,8 @@ #include "curlx/warnless.h" #include "multiif.h" #include "rand.h" +#include "cfilters.h" +#include "connect.h" /* first byte is command. second byte is for flags. */ @@ -134,6 +136,50 @@ const struct Curl_handler Curl_handler_mqtt = { PROTOPT_NONE /* flags */ }; +#ifdef USE_SSL + +static CURLcode mqtts_connecting(struct Curl_easy *data, bool *done) +{ + struct connectdata *conn = data->conn; + CURLcode result; + + result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, done); + if(result) + connclose(conn, "Failed TLS connection"); + return result; +} + +/* + * MQTTS protocol handler. + */ + +const struct Curl_handler Curl_handler_mqtts = { + "mqtts", /* scheme */ + mqtt_setup_conn, /* setup_connection */ + mqtt_do, /* do_it */ + mqtt_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + mqtts_connecting, /* connecting */ + mqtt_doing, /* doing */ + ZERO_NULL, /* proto_pollset */ + mqtt_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_MQTTS, /* defport */ + CURLPROTO_MQTTS, /* protocol */ + CURLPROTO_MQTT, /* family */ + PROTOPT_SSL /* flags */ +}; + +#endif + static void mqtt_easy_dtor(void *key, size_t klen, void *entry) { struct MQTT *mq = entry; diff --git a/lib/mqtt.h b/lib/mqtt.h index 8fb8a33c02..8c2c78f6ab 100644 --- a/lib/mqtt.h +++ b/lib/mqtt.h @@ -26,6 +26,9 @@ #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 #endif /* HEADER_CURL_MQTT_H */ diff --git a/lib/url.c b/lib/url.c index 29d6b34422..df8a987c7a 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1429,7 +1429,12 @@ const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, #else NULL, #endif - NULL, NULL, +#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 diff --git a/lib/urldata.h b/lib/urldata.h index 8ff5ad98b5..770b55bad8 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -52,6 +52,7 @@ #define PORT_RTMPS PORT_HTTPS #define PORT_GOPHER 70 #define PORT_MQTT 1883 +#define PORT_MQTTS 8883 struct curl_trc_featt; diff --git a/lib/version.c b/lib/version.c index 246e7871db..23acce662b 100644 --- a/lib/version.c +++ b/lib/version.c @@ -343,6 +343,9 @@ static const char * const supported_protocols[] = { #ifndef CURL_DISABLE_MQTT "mqtt", #endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_MQTT) + "mqtts", +#endif #ifndef CURL_DISABLE_POP3 "pop3", #endif diff --git a/scripts/schemetable.c b/scripts/schemetable.c index 2c1c3c0548..1f4527a943 100644 --- a/scripts/schemetable.c +++ b/scripts/schemetable.c @@ -35,45 +35,46 @@ struct detail { }; 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" }, - { "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)" }, + {"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 } };