mirror of
https://github.com/eclipse-mosquitto/mosquitto.git
synced 2026-09-23 00:24:47 +08:00
Merge branch 'master' into develop
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
name: Delete old workflow runs
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 1 * *'
|
||||
# Run monthly, at 00:00 on the 1st day of month.
|
||||
|
||||
jobs:
|
||||
del_runs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Delete workflow runs
|
||||
uses: Mattraks/delete-workflow-runs@v2
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
repository: ${{ github.repository }}
|
||||
retain_days: 30
|
||||
keep_minimum_runs: 6
|
||||
+18
-1
@@ -1,3 +1,4 @@
|
||||
# .gitignore
|
||||
*.a
|
||||
*.db
|
||||
*.gcda
|
||||
@@ -112,9 +113,25 @@ test/unit/lib/lib_test
|
||||
test/unit/broker/persist_read_test
|
||||
test/unit/broker/persist_write_test
|
||||
test/unit/broker/subs_test
|
||||
test/unit/tls_test
|
||||
test/unit/out/
|
||||
|
||||
www/cache/
|
||||
__pycache__
|
||||
|
||||
*.sync-conflict-*
|
||||
# Debian generated files
|
||||
debian/.debhelper/
|
||||
debian/debhelper-build-stamp
|
||||
debian/files
|
||||
debian/*.log
|
||||
debian/*.substvars
|
||||
debian/*mosquitto*/
|
||||
debian/*.debhelper
|
||||
debian/tmp/
|
||||
obj-*/
|
||||
|
||||
# Emacs generated files
|
||||
*~
|
||||
|
||||
# Others
|
||||
tmp/
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ project(mosquitto
|
||||
LANGUAGES C CXX
|
||||
)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
|
||||
@@ -189,6 +189,77 @@ Build:
|
||||
- cJSON is now a required dependency.
|
||||
|
||||
|
||||
2.0.17 - 2023-08-22
|
||||
===================
|
||||
|
||||
Broker:
|
||||
- Fix `max_queued_messages 0` stopping clients from receiving messages.
|
||||
Closes #2879.
|
||||
- Fix `max_inflight_messages` not being set correctly. Closes #2876.
|
||||
|
||||
Apps:
|
||||
- Fix `mosquitto_passwd -U` backup file creation. Closes #2873.
|
||||
|
||||
|
||||
2.0.16 - 2023-08-16
|
||||
===================
|
||||
|
||||
Security:
|
||||
- CVE-2023-28366: Fix memory leak in broker when clients send multiple QoS 2
|
||||
messages with the same message ID, but then never respond to the PUBREC
|
||||
commands.
|
||||
- CVE-2023-0809: Fix excessive memory being allocated based on malicious
|
||||
initial packets that are not CONNECT packets.
|
||||
- CVE-2023-3592: Fix memory leak when clients send v5 CONNECT packets with a
|
||||
will message that contains invalid property types.
|
||||
- Broker will now reject Will messages that attempt to publish to $CONTROL/.
|
||||
- Broker now validates usernames provided in a TLS certificate or TLS-PSK
|
||||
identity are valid UTF-8.
|
||||
- Fix potential crash when loading invalid persistence file.
|
||||
- Library will no longer allow single level wildcard certificates, e.g. *.com
|
||||
|
||||
Broker:
|
||||
- Fix $SYS messages being expired after 60 seconds and hence unchanged values
|
||||
disappearing.
|
||||
- Fix some retained topic memory not being cleared immediately after used.
|
||||
- Fix error handling related to the `bind_interface` option.
|
||||
- Fix std* files not being redirected when daemonising, when built with
|
||||
assertions removed. Closes #2708.
|
||||
- Fix default settings incorrectly allowing TLS v1.1. Closes #2722.
|
||||
- Use line buffered mode for stdout. Closes #2354. Closes #2749.
|
||||
- Fix bridges with non-matching cleansession/local_cleansession being expired
|
||||
on start after restoring from persistence. Closes #2634.
|
||||
- Fix connections being limited to 2048 on Windows. The limit is now 8192,
|
||||
where supported. Closes #2732.
|
||||
- Broker will log warnings if sensitive files are world readable/writable, or
|
||||
if the owner/group is not the same as the user/group the broker is running
|
||||
as. In future versions the broker will refuse to open these files.
|
||||
- mosquitto_memcmp_const is now more constant time.
|
||||
- Only register with DLT if DLT logging is enabled.
|
||||
- Fix any possible case where a json string might be incorrectly loaded. This
|
||||
could have caused a crash if a textname or textdescription field of a role was
|
||||
not a string, when loading the dynsec config from file only.
|
||||
- Dynsec plugin will not allow duplicate clients/groups/roles when loading
|
||||
config from file, which matches the behaviour for when creating them.
|
||||
- Fix heap overflow when reading corrupt config with "log_dest file".
|
||||
|
||||
Client library:
|
||||
- Use CLOCK_BOOTTIME when available, to keep track of time. This solves the
|
||||
problem of the client OS sleeping and the client hence not being able to
|
||||
calculate the actual time for keepalive purposes. Closes #2760.
|
||||
- Fix default settings incorrectly allowing TLS v1.1. Closes #2722.
|
||||
- Fix high CPU use on slow TLS connect. Closes #2794.
|
||||
|
||||
Clients:
|
||||
- Fix incorrect topic-alias property value in mosquitto_sub json output.
|
||||
- Fix confusing message on TLS certificate verification. Closes #2746.
|
||||
|
||||
Apps:
|
||||
- mosquitto_passwd uses mkstemp() for backup files.
|
||||
- `mosquitto_ctrl dynsec init` will refuse to overwrite an existing file,
|
||||
without a race-condition.
|
||||
|
||||
|
||||
2.0.15 - 2022-08-16
|
||||
===================
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
@@ -11,6 +11,7 @@ if(WITH_TLS AND CJSON_FOUND)
|
||||
dynsec_role.c
|
||||
../mosquitto_passwd/get_password.c ../mosquitto_passwd/get_password.h
|
||||
../../lib/memory_mosq.c ../../lib/memory_mosq.h
|
||||
../../lib/misc_mosq.c ../../lib/misc_mosq.h
|
||||
../../src/memory_public.c
|
||||
options.c
|
||||
../../common/json_help.c ../../common/json_help.h
|
||||
|
||||
@@ -23,6 +23,8 @@ Contributors:
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <errno.h>
|
||||
# include <fcntl.h>
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
@@ -32,6 +34,7 @@ Contributors:
|
||||
#include "json_help.h"
|
||||
#include "password_mosq.h"
|
||||
#include "get_password.h"
|
||||
#include "misc_mosq.h"
|
||||
|
||||
#define MAX_STRING_LEN 4096
|
||||
|
||||
@@ -709,13 +712,6 @@ static int dynsec_init(int argc, char *argv[])
|
||||
admin_password = password;
|
||||
}
|
||||
|
||||
fptr = fopen(filename, "rb");
|
||||
if(fptr){
|
||||
fclose(fptr);
|
||||
fprintf(stderr, "dynsec init: '%s' already exists. Remove the file or use a different location..\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree = init_create(admin_user, admin_password, "admin");
|
||||
if(tree == NULL){
|
||||
fprintf(stderr, "dynsec init: Out of memory.\n");
|
||||
@@ -724,7 +720,17 @@ static int dynsec_init(int argc, char *argv[])
|
||||
json_str = cJSON_Print(tree);
|
||||
cJSON_Delete(tree);
|
||||
|
||||
fptr = fopen(filename, "wb");
|
||||
#ifdef WIN32
|
||||
fptr = mosquitto__fopen(filename, "wb", true);
|
||||
#else
|
||||
int fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0640);
|
||||
if(fd < 0){
|
||||
free(json_str);
|
||||
fprintf(stderr, "dynsec init: Unable to open '%s' for writing (%s).\n", filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
fptr = fdopen(fd, "wb");
|
||||
#endif
|
||||
if(fptr){
|
||||
fprintf(fptr, "%s", json_str);
|
||||
free(json_str);
|
||||
|
||||
@@ -611,6 +611,11 @@ int client_opts_set(struct mosquitto *mosq, struct mosq_config *cfg)
|
||||
return 1;
|
||||
}
|
||||
#ifdef WITH_TLS
|
||||
if(cfg->keyform && mosquitto_string_option(mosq, MOSQ_OPT_TLS_KEYFORM, cfg->keyform)){
|
||||
fprintf(stderr, "Error: Problem setting key form, it must be one of 'pem' or 'engine'.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(cfg->cafile || cfg->capath){
|
||||
rc = mosquitto_tls_set(mosq, cfg->cafile, cfg->capath, cfg->certfile, cfg->keyfile, NULL);
|
||||
if(rc){
|
||||
@@ -633,11 +638,6 @@ int client_opts_set(struct mosquitto *mosq, struct mosq_config *cfg)
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(cfg->keyform && mosquitto_string_option(mosq, MOSQ_OPT_TLS_KEYFORM, cfg->keyform)){
|
||||
fprintf(stderr, "Error: Problem setting key form, it must be one of 'pem' or 'engine'.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(cfg->tls_engine_kpass_sha1 && mosquitto_string_option(mosq, MOSQ_OPT_TLS_ENGINE_KPASS_SHA1, cfg->tls_engine_kpass_sha1)){
|
||||
fprintf(stderr, "Error: Problem setting TLS engine key pass sha, is it a 40 character hex string?\n");
|
||||
mosquitto_lib_cleanup();
|
||||
|
||||
@@ -364,15 +364,27 @@ static int copy_contents(FILE *src, FILE *dest)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_backup(const char *backup_file, FILE *fptr)
|
||||
static int create_backup(char *backup_file, FILE *fptr)
|
||||
{
|
||||
FILE *fbackup;
|
||||
|
||||
fbackup = fopen(backup_file, "wt");
|
||||
#ifdef WIN32
|
||||
fbackup = mosquitto__fopen(backup_file, "wt", true);
|
||||
#else
|
||||
int fd;
|
||||
umask(077);
|
||||
fd = mkstemp(backup_file);
|
||||
if(fd < 0){
|
||||
fprintf(stderr, "Error creating backup password file \"%s\", not continuing.\n", backup_file);
|
||||
return 1;
|
||||
}
|
||||
fbackup = fdopen(fd, "wt");
|
||||
#endif
|
||||
if(!fbackup){
|
||||
fprintf(stderr, "Error creating backup password file \"%s\", not continuing.\n", backup_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(copy_contents(fptr, fbackup)){
|
||||
fprintf(stderr, "Error copying data to backup password file \"%s\", not continuing.\n", backup_file);
|
||||
fclose(fbackup);
|
||||
@@ -597,7 +609,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
password_cmd = password;
|
||||
}
|
||||
fptr = fopen(password_file, "wt");
|
||||
fptr = mosquitto__fopen(password_file, "wt", true);
|
||||
if(!fptr){
|
||||
fprintf(stderr, "Error: Unable to open file %s for writing. %s.\n", password_file, strerror(errno));
|
||||
free(password_file);
|
||||
@@ -609,20 +621,21 @@ int main(int argc, char *argv[])
|
||||
fclose(fptr);
|
||||
return rc;
|
||||
}else{
|
||||
fptr = fopen(password_file, "r+t");
|
||||
fptr = mosquitto__fopen(password_file, "r+t", true);
|
||||
if(!fptr){
|
||||
fprintf(stderr, "Error: Unable to open password file %s. %s.\n", password_file, strerror(errno));
|
||||
free(password_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
backup_file = malloc((size_t)strlen(password_file)+5);
|
||||
size_t len = strlen(password_file) + strlen(".backup.XXXXXX") + 1;
|
||||
backup_file = malloc(len);
|
||||
if(!backup_file){
|
||||
fprintf(stderr, "Error: Out of memory.\n");
|
||||
free(password_file);
|
||||
return 1;
|
||||
}
|
||||
snprintf(backup_file, strlen(password_file)+5, "%s.tmp", password_file);
|
||||
snprintf(backup_file, len, "%s.backup.XXXXXX", password_file);
|
||||
free(password_file);
|
||||
password_file = NULL;
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ Contributors:
|
||||
# define PATH_MAX MAX_PATH
|
||||
#else
|
||||
# include <sys/stat.h>
|
||||
# include <pwd.h>
|
||||
# include <grp.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
@@ -149,6 +151,60 @@ FILE *mosquitto__fopen(const char *path, const char *mode, bool restrict_read)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(restrict_read){
|
||||
if(statbuf.st_mode & S_IRWXO){
|
||||
#ifdef WITH_BROKER
|
||||
log__printf(NULL, MOSQ_LOG_WARNING,
|
||||
#else
|
||||
fprintf(stderr,
|
||||
#endif
|
||||
"Warning: File %s has world readable permissions. Future versions will refuse to load this file.",
|
||||
path);
|
||||
#if 0
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
if(statbuf.st_uid != getuid()){
|
||||
char buf[4096];
|
||||
struct passwd pw, *result;
|
||||
|
||||
getpwuid_r(getuid(), &pw, buf, sizeof(buf), &result);
|
||||
if(result){
|
||||
#ifdef WITH_BROKER
|
||||
log__printf(NULL, MOSQ_LOG_WARNING,
|
||||
#else
|
||||
fprintf(stderr,
|
||||
#endif
|
||||
"Warning: File %s owner is not %s. Future versions will refuse to load this file.",
|
||||
path, result->pw_name);
|
||||
}
|
||||
#if 0
|
||||
// Future version
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
if(statbuf.st_gid != getgid()){
|
||||
char buf[4096];
|
||||
struct group grp, *result;
|
||||
|
||||
getgrgid_r(getgid(), &grp, buf, sizeof(buf), &result);
|
||||
if(result){
|
||||
#ifdef WITH_BROKER
|
||||
log__printf(NULL, MOSQ_LOG_WARNING,
|
||||
#else
|
||||
fprintf(stderr,
|
||||
#endif
|
||||
"Warning: File %s group is not %s. Future versions will refuse to load this file.",
|
||||
path, result->gr_name);
|
||||
}
|
||||
#if 0
|
||||
// Future version
|
||||
return NULL
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)){
|
||||
#ifdef WITH_BROKER
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: %s is not a file.", path);
|
||||
|
||||
@@ -124,9 +124,7 @@ int pw__memcmp_const(const void *a, const void *b, size_t len)
|
||||
if(!a || !b) return 1;
|
||||
|
||||
for(i=0; i<len; i++){
|
||||
if( ((char *)a)[i] != ((char *)b)[i] ){
|
||||
rc = 1;
|
||||
}
|
||||
rc |= ((char *)a)[i] ^ ((char *)b)[i];
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,11 @@ time_t mosquitto_time(void)
|
||||
#elif _POSIX_TIMERS>0 && defined(_POSIX_MONOTONIC_CLOCK)
|
||||
struct timespec tp;
|
||||
|
||||
#ifdef CLOCK_BOOTTIME
|
||||
clock_gettime(CLOCK_BOOTTIME, &tp);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
#endif
|
||||
return tp.tv_sec;
|
||||
#elif defined(__APPLE__)
|
||||
static mach_timebase_info_data_t tb;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM alpine:3.14
|
||||
FROM alpine:3.18
|
||||
|
||||
LABEL maintainer="Roger Light <roger@atchoo.org>" \
|
||||
description="Eclipse Mosquitto MQTT Broker"
|
||||
@@ -6,16 +6,19 @@ LABEL maintainer="Roger Light <roger@atchoo.org>" \
|
||||
ENV VERSION=1.5.11 \
|
||||
DOWNLOAD_SHA256=4a3b8a8f5505d27a7a966dd68bfd76f1e69feb51796d1b46b7271d1bb5a1a299 \
|
||||
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
|
||||
LWS_VERSION=2.4.2
|
||||
LWS_VERSION=4.2.1 \
|
||||
LWS_SHA256=842da21f73ccba2be59e680de10a8cce7928313048750eb6ad73b6fa50763c51
|
||||
|
||||
RUN set -x && \
|
||||
apk --no-cache add --virtual build-deps \
|
||||
build-base \
|
||||
cmake \
|
||||
gnupg \
|
||||
linux-headers \
|
||||
openssl-dev \
|
||||
util-linux-dev && \
|
||||
wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \
|
||||
echo "$LWS_SHA256 /tmp/lws.tar.gz" | sha256sum -c - && \
|
||||
mkdir -p /build/lws && \
|
||||
tar --strip=1 -xf /tmp/lws.tar.gz -C /build/lws && \
|
||||
rm /tmp/lws.tar.gz && \
|
||||
@@ -23,11 +26,13 @@ RUN set -x && \
|
||||
cmake . \
|
||||
-DCMAKE_BUILD_TYPE=MinSizeRel \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DDISABLE_WERROR=ON \
|
||||
-DLWS_IPV6=ON \
|
||||
-DLWS_WITHOUT_BUILTIN_GETIFADDRS=ON \
|
||||
-DLWS_WITHOUT_CLIENT=ON \
|
||||
-DLWS_WITHOUT_EXTENSIONS=ON \
|
||||
-DLWS_WITHOUT_TESTAPPS=ON \
|
||||
-DLWS_WITH_EXTERNAL_POLL=ON \
|
||||
-DLWS_WITH_HTTP2=OFF \
|
||||
-DLWS_WITH_SHARED=OFF \
|
||||
-DLWS_WITH_ZIP_FOPS=OFF \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM alpine:3.14
|
||||
FROM alpine:3.18
|
||||
|
||||
LABEL maintainer="Roger Light <roger@atchoo.org>" \
|
||||
description="Eclipse Mosquitto MQTT Broker"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
FROM alpine:3.16
|
||||
FROM alpine:3.18
|
||||
|
||||
LABEL maintainer="Roger Light <roger@atchoo.org>" \
|
||||
description="Eclipse Mosquitto MQTT Broker"
|
||||
|
||||
ENV VERSION=2.0.15 \
|
||||
DOWNLOAD_SHA256=4735b1d32e3f91c7a8896741d88a3022e89730a1ee897946decfa0df27039ac6 \
|
||||
ENV VERSION=2.0.17 \
|
||||
DOWNLOAD_SHA256=3be7a911236567c1a9fbe25baf3e3167004ba4a0c151a448ef1f7fc077dba52f \
|
||||
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
|
||||
LWS_VERSION=4.2.1 \
|
||||
LWS_SHA256=842da21f73ccba2be59e680de10a8cce7928313048750eb6ad73b6fa50763c51
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
FROM alpine:3.16
|
||||
FROM alpine:3.18
|
||||
|
||||
LABEL maintainer="Roger Light <roger@atchoo.org>" \
|
||||
description="Eclipse Mosquitto MQTT Broker"
|
||||
|
||||
ENV VERSION=2.0.15 \
|
||||
DOWNLOAD_SHA256=4735b1d32e3f91c7a8896741d88a3022e89730a1ee897946decfa0df27039ac6 \
|
||||
ENV VERSION=2.0.17 \
|
||||
DOWNLOAD_SHA256=3be7a911236567c1a9fbe25baf3e3167004ba4a0c151a448ef1f7fc077dba52f \
|
||||
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
|
||||
LWS_VERSION=4.2.1 \
|
||||
LWS_SHA256=842da21f73ccba2be59e680de10a8cce7928313048750eb6ad73b6fa50763c51
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM alpine:3.14
|
||||
FROM alpine:3.18
|
||||
|
||||
LABEL maintainer="Roger Light <roger@atchoo.org>" \
|
||||
description="Eclipse Mosquitto MQTT Broker"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM alpine:3.16
|
||||
FROM alpine:3.18
|
||||
|
||||
LABEL maintainer="Roger Light <roger@atchoo.org>" \
|
||||
description="Eclipse Mosquitto MQTT Broker"
|
||||
|
||||
+12
-12
@@ -535,8 +535,8 @@ libmosq_EXPORT int mosquitto_username_pw_set(struct mosquitto *mosq, const char
|
||||
* mosq - a valid mosquitto instance.
|
||||
* host - the hostname or ip address of the broker to connect to.
|
||||
* port - the network port to connect to. Usually 1883.
|
||||
* keepalive - the number of seconds after which the broker should send a PING
|
||||
* message to the client if no other messages have been exchanged
|
||||
* keepalive - the number of seconds after which the client should send a PING
|
||||
* message to the broker if no other messages have been exchanged
|
||||
* in that time.
|
||||
*
|
||||
* Returns:
|
||||
@@ -567,8 +567,8 @@ libmosq_EXPORT int mosquitto_connect(struct mosquitto *mosq, const char *host, i
|
||||
* mosq - a valid mosquitto instance.
|
||||
* host - the hostname or ip address of the broker to connect to.
|
||||
* port - the network port to connect to. Usually 1883.
|
||||
* keepalive - the number of seconds after which the broker should send a PING
|
||||
* message to the client if no other messages have been exchanged
|
||||
* keepalive - the number of seconds after which the client should send a PING
|
||||
* message to the broker if no other messages have been exchanged
|
||||
* in that time.
|
||||
* bind_address - the hostname or ip address of the local network interface to
|
||||
* bind to. If you do not want to bind to a specific interface,
|
||||
@@ -611,8 +611,8 @@ libmosq_EXPORT int mosquitto_connect_bind(struct mosquitto *mosq, const char *ho
|
||||
* mosq - a valid mosquitto instance.
|
||||
* host - the hostname or ip address of the broker to connect to.
|
||||
* port - the network port to connect to. Usually 1883.
|
||||
* keepalive - the number of seconds after which the broker should send a PING
|
||||
* message to the client if no other messages have been exchanged
|
||||
* keepalive - the number of seconds after which the client should send a PING
|
||||
* message to the broker if no other messages have been exchanged
|
||||
* in that time.
|
||||
* bind_address - the hostname or ip address of the local network interface to
|
||||
* bind to. If you do not want to bind to a specific interface,
|
||||
@@ -652,8 +652,8 @@ libmosq_EXPORT int mosquitto_connect_bind_v5(struct mosquitto *mosq, const char
|
||||
* mosq - a valid mosquitto instance.
|
||||
* host - the hostname or ip address of the broker to connect to.
|
||||
* port - the network port to connect to. Usually 1883.
|
||||
* keepalive - the number of seconds after which the broker should send a PING
|
||||
* message to the client if no other messages have been exchanged
|
||||
* keepalive - the number of seconds after which the client should send a PING
|
||||
* message to the broker if no other messages have been exchanged
|
||||
* in that time.
|
||||
*
|
||||
* Returns:
|
||||
@@ -687,8 +687,8 @@ libmosq_EXPORT int mosquitto_connect_async(struct mosquitto *mosq, const char *h
|
||||
* mosq - a valid mosquitto instance.
|
||||
* host - the hostname or ip address of the broker to connect to.
|
||||
* port - the network port to connect to. Usually 1883.
|
||||
* keepalive - the number of seconds after which the broker should send a PING
|
||||
* message to the client if no other messages have been exchanged
|
||||
* keepalive - the number of seconds after which the client should send a PING
|
||||
* message to the broker if no other messages have been exchanged
|
||||
* in that time.
|
||||
* bind_address - the hostname or ip address of the local network interface to
|
||||
* bind to. If you do not want to bind to a specific interface,
|
||||
@@ -726,8 +726,8 @@ libmosq_EXPORT int mosquitto_connect_bind_async(struct mosquitto *mosq, const ch
|
||||
* Parameters:
|
||||
* mosq - a valid mosquitto instance.
|
||||
* host - the hostname to search for an SRV record.
|
||||
* keepalive - the number of seconds after which the broker should send a PING
|
||||
* message to the client if no other messages have been exchanged
|
||||
* keepalive - the number of seconds after which the client should send a PING
|
||||
* message to the broker if no other messages have been exchanged
|
||||
* in that time.
|
||||
* bind_address - the hostname or ip address of the local network interface to
|
||||
* bind to. If you do not want to bind to a specific interface,
|
||||
|
||||
@@ -112,7 +112,7 @@ struct mosquitto_client_msg {
|
||||
uint16_t mid;
|
||||
uint8_t qos;
|
||||
bool retain;
|
||||
bool dup;
|
||||
uint8_t dup;
|
||||
uint8_t direction;
|
||||
uint8_t state;
|
||||
uint8_t padding[5];
|
||||
|
||||
+10
-8
@@ -65,18 +65,20 @@ int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets)
|
||||
if(net__is_connected(mosq)){
|
||||
maxfd = mosq->sock;
|
||||
FD_SET(mosq->sock, &readfds);
|
||||
pthread_mutex_lock(&mosq->out_packet_mutex);
|
||||
if(mosq->out_packet){
|
||||
if(mosq->want_write){
|
||||
FD_SET(mosq->sock, &writefds);
|
||||
}
|
||||
}else{
|
||||
#ifdef WITH_TLS
|
||||
if(mosq->ssl){
|
||||
if(mosq->want_write){
|
||||
FD_SET(mosq->sock, &writefds);
|
||||
if(mosq->ssl == NULL || SSL_is_init_finished(mosq->ssl))
|
||||
#endif
|
||||
{
|
||||
pthread_mutex_lock(&mosq->out_packet_mutex);
|
||||
if(mosq->out_packet){
|
||||
FD_SET(mosq->sock, &writefds);
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->out_packet_mutex);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pthread_mutex_unlock(&mosq->out_packet_mutex);
|
||||
}else{
|
||||
#ifdef WITH_SRV
|
||||
if(mosq->achan){
|
||||
|
||||
+5
-13
@@ -61,8 +61,11 @@ int mosquitto_lib_init(void)
|
||||
srand((unsigned int)GetTickCount64());
|
||||
#elif _POSIX_TIMERS>0 && defined(_POSIX_MONOTONIC_CLOCK)
|
||||
struct timespec tp;
|
||||
|
||||
#ifdef CLOCK_BOOTTIME
|
||||
clock_gettime(CLOCK_BOOTTIME, &tp);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
#endif
|
||||
srand((unsigned int)tp.tv_nsec);
|
||||
#elif defined(__APPLE__)
|
||||
uint64_t ticks;
|
||||
@@ -332,18 +335,7 @@ int mosquitto_socket(struct mosquitto *mosq)
|
||||
|
||||
bool mosquitto_want_write(struct mosquitto *mosq)
|
||||
{
|
||||
bool result = false;
|
||||
if(mosq->out_packet){
|
||||
result = true;
|
||||
}
|
||||
#ifdef WITH_TLS
|
||||
if(mosq->ssl){
|
||||
if (mosq->want_write) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
return mosq->out_packet || mosq->want_write;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -181,6 +181,10 @@ void net__init_tls(void)
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
OpenSSL_add_all_algorithms();
|
||||
# else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS \
|
||||
| OPENSSL_INIT_LOAD_CONFIG, NULL);
|
||||
# endif
|
||||
#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
|
||||
ENGINE_load_builtin_engines();
|
||||
|
||||
+28
-8
@@ -168,14 +168,21 @@ int mosquitto_tls_set(struct mosquitto *mosq, const char *cafile, const char *ca
|
||||
|
||||
mosquitto__FREE(mosq->tls_keyfile);
|
||||
if(keyfile){
|
||||
fptr = mosquitto__fopen(keyfile, "rt", false);
|
||||
if(fptr){
|
||||
fclose(fptr);
|
||||
}else{
|
||||
mosquitto__FREE(mosq->tls_cafile);
|
||||
mosquitto__FREE(mosq->tls_capath);
|
||||
mosquitto__FREE(mosq->tls_certfile);
|
||||
return MOSQ_ERR_INVAL;
|
||||
if(mosq->tls_keyform == mosq_k_pem){
|
||||
fptr = mosquitto__fopen(keyfile, "rt", false);
|
||||
if(fptr){
|
||||
fclose(fptr);
|
||||
}else{
|
||||
mosquitto__FREE(mosq->tls_cafile);
|
||||
mosq->tls_cafile = NULL;
|
||||
|
||||
mosquitto__FREE(mosq->tls_capath);
|
||||
mosq->tls_capath = NULL;
|
||||
|
||||
mosquitto__FREE(mosq->tls_certfile);
|
||||
mosq->tls_certfile = NULL;
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
}
|
||||
mosq->tls_keyfile = mosquitto__strdup(keyfile);
|
||||
if(!mosq->tls_keyfile){
|
||||
@@ -223,6 +230,14 @@ int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tl
|
||||
mosq->tls_version = mosquitto__strdup("tlsv1.2");
|
||||
if(!mosq->tls_version) return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
if(ciphers){
|
||||
mosquitto__FREE(mosq->tls_ciphers);
|
||||
mosq->tls_ciphers = mosquitto__strdup(ciphers);
|
||||
if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM;
|
||||
}else{
|
||||
mosquitto__FREE(mosq->tls_ciphers);
|
||||
mosq->tls_ciphers = NULL;
|
||||
}
|
||||
|
||||
mosquitto__FREE(mosq->tls_ciphers);
|
||||
mosquitto__FREE(mosq->tls_13_ciphers);
|
||||
@@ -278,6 +293,11 @@ int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, cons
|
||||
#if defined(WITH_TLS) && !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
|
||||
mosquitto__FREE(mosq->tls_engine);
|
||||
if(value){
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
/* The "Dynamic" OpenSSL engine is not initialized by default but
|
||||
is required by ENGINE_by_id() to find dynamically loadable engines */
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL);
|
||||
#endif
|
||||
eng = ENGINE_by_id(value);
|
||||
if(!eng){
|
||||
return MOSQ_ERR_INVAL;
|
||||
|
||||
+17
-1
@@ -137,6 +137,20 @@ void packet__cleanup_all(struct mosquitto *mosq)
|
||||
|
||||
static void packet__queue_append(struct mosquitto *mosq, struct mosquitto__packet *packet)
|
||||
{
|
||||
#ifdef WITH_BROKER
|
||||
if(db.config->max_queued_messages > 0 && mosq->out_packet_count >= db.config->max_queued_messages){
|
||||
mosquitto__free(packet);
|
||||
if(mosq->is_dropping == false){
|
||||
mosq->is_dropping = true;
|
||||
log__printf(NULL, MOSQ_LOG_NOTICE,
|
||||
"Outgoing messages are being dropped for client %s.",
|
||||
mosq->id);
|
||||
}
|
||||
metrics__int_inc(mosq_counter_mqtt_publish_dropped, 1);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&mosq->out_packet_mutex);
|
||||
if(mosq->out_packet){
|
||||
mosq->out_packet_last->next = packet;
|
||||
@@ -296,6 +310,8 @@ int packet__write(struct mosquitto *mosq)
|
||||
return MOSQ_ERR_CONN_LOST;
|
||||
case COMPAT_EINTR:
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
case EPROTO:
|
||||
return MOSQ_ERR_TLS;
|
||||
default:
|
||||
return MOSQ_ERR_ERRNO;
|
||||
}
|
||||
@@ -383,7 +399,7 @@ int packet__read(struct mosquitto *mosq)
|
||||
#ifdef WITH_BROKER
|
||||
metrics__int_inc(mosq_counter_bytes_received, 1);
|
||||
/* Clients must send CONNECT as their first command. */
|
||||
if(!(mosq->bridge) && state == mosq_cs_connected && (byte&0xF0) != CMD_CONNECT){
|
||||
if(!(mosq->bridge) && state == mosq_cs_new && (byte&0xF0) != CMD_CONNECT){
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
#endif
|
||||
|
||||
+19
-18
@@ -26,6 +26,7 @@ Contributors:
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "logging_mosq.h"
|
||||
#include "memory_mosq.h"
|
||||
#include "mqtt_protocol.h"
|
||||
#include "packet_mosq.h"
|
||||
@@ -147,6 +148,9 @@ static int property__read(struct mosquitto__packet_in *packet, uint32_t *len, mo
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef WITH_BROKER
|
||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property_identifier);
|
||||
#endif
|
||||
return MOSQ_ERR_MALFORMED_PACKET;
|
||||
}
|
||||
|
||||
@@ -352,6 +356,9 @@ static int property__write(struct mosquitto__packet *packet, const mosquitto_pro
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef WITH_BROKER
|
||||
log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property->identifier);
|
||||
#endif
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
|
||||
@@ -1223,12 +1230,10 @@ BROKER_EXPORT int mosquitto_property_copy_all(mosquitto_property **dest, const m
|
||||
|
||||
case MQTT_PROP_TYPE_STRING:
|
||||
pnew->value.s.len = src->value.s.len;
|
||||
if(src->value.s.v){
|
||||
pnew->value.s.v = strdup(src->value.s.v);
|
||||
if(!pnew->value.s.v){
|
||||
mosquitto_property_free_all(dest);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
pnew->value.s.v = src->value.s.v ? strdup(src->value.s.v) : (char*)calloc(1,1);
|
||||
if(!pnew->value.s.v){
|
||||
mosquitto_property_free_all(dest);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1246,21 +1251,17 @@ BROKER_EXPORT int mosquitto_property_copy_all(mosquitto_property **dest, const m
|
||||
|
||||
case MQTT_PROP_TYPE_STRING_PAIR:
|
||||
pnew->value.s.len = src->value.s.len;
|
||||
if(src->value.s.v){
|
||||
pnew->value.s.v = strdup(src->value.s.v);
|
||||
if(!pnew->value.s.v){
|
||||
mosquitto_property_free_all(dest);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
pnew->value.s.v = src->value.s.v ? strdup(src->value.s.v) : (char*)calloc(1,1);
|
||||
if(!pnew->value.s.v){
|
||||
mosquitto_property_free_all(dest);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
|
||||
pnew->name.len = src->name.len;
|
||||
if(src->name.v){
|
||||
pnew->name.v = strdup(src->name.v);
|
||||
if(!pnew->name.v){
|
||||
mosquitto_property_free_all(dest);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
pnew->name.v = src->name.v ? strdup(src->name.v) : (char*)calloc(1,1);
|
||||
if(!pnew->name.v){
|
||||
mosquitto_property_free_all(dest);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ const char *mosquitto_strerror(int mosq_errno)
|
||||
case MOSQ_ERR_KEEPALIVE:
|
||||
return "Keepalive exceeded";
|
||||
case MOSQ_ERR_LOOKUP:
|
||||
return "Lookup failed";
|
||||
return "DNS Lookup failed";
|
||||
case MOSQ_ERR_MALFORMED_PACKET:
|
||||
return "Malformed packet";
|
||||
case MOSQ_ERR_DUPLICATE_PROPERTY:
|
||||
|
||||
@@ -105,6 +105,17 @@ static int mosquitto__cmp_hostname_wildcard(char *certname, const char *hostname
|
||||
break;
|
||||
}
|
||||
}
|
||||
len = strlen(hostname);
|
||||
int dotcount = 0;
|
||||
for(i=0; i<len-1; i++){
|
||||
if(hostname[i] == '.'){
|
||||
dotcount++;
|
||||
}
|
||||
}
|
||||
if(dotcount < 1){
|
||||
/* Exclude e.g. *.com, allow e.g. *.example.com */
|
||||
return 1;
|
||||
}
|
||||
return strcasecmp(certname, hostname);
|
||||
}else{
|
||||
return strcasecmp(certname, hostname);
|
||||
|
||||
+38
-38
@@ -4,44 +4,44 @@
|
||||
# could not be found, then the man pages will not be built or installed -
|
||||
# because the install is optional.
|
||||
|
||||
if(NOT WIN32)
|
||||
find_program(XSLTPROC xsltproc OPTIONAL)
|
||||
if(XSLTPROC)
|
||||
function(compile_manpage page)
|
||||
add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/man/${page}
|
||||
COMMAND xsltproc ${PROJECT_SOURCE_DIR}/man/${page}.xml -o ${PROJECT_SOURCE_DIR}/man/
|
||||
MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/man/${page}.xml)
|
||||
add_custom_target(${page} ALL DEPENDS ${PROJECT_SOURCE_DIR}/man/${page})
|
||||
endfunction()
|
||||
find_program(XSLTPROC xsltproc OPTIONAL)
|
||||
if(XSLTPROC)
|
||||
function(compile_manpage page)
|
||||
add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/man/${page}
|
||||
COMMAND xsltproc ${PROJECT_SOURCE_DIR}/man/${page}.xml -o ${PROJECT_SOURCE_DIR}/man/
|
||||
MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/man/${page}.xml)
|
||||
add_custom_target(${page} ALL DEPENDS ${PROJECT_SOURCE_DIR}/man/${page})
|
||||
endfunction()
|
||||
|
||||
compile_manpage("libmosquitto.3")
|
||||
compile_manpage("mosquitto-tls.7")
|
||||
compile_manpage("mosquitto.8")
|
||||
compile_manpage("mosquitto.conf.5")
|
||||
compile_manpage("mosquitto_ctrl.1")
|
||||
compile_manpage("mosquitto_ctrl_dynsec.1")
|
||||
compile_manpage("mosquitto_passwd.1")
|
||||
compile_manpage("mosquitto_pub.1")
|
||||
compile_manpage("mosquitto_rr.1")
|
||||
compile_manpage("mosquitto_sub.1")
|
||||
compile_manpage("mqtt.7")
|
||||
else()
|
||||
message(FATAL_ERROR "xsltproc not found: manpages cannot be built")
|
||||
endif()
|
||||
compile_manpage("mosquitto_ctrl.1")
|
||||
compile_manpage("mosquitto_ctrl_dynsec.1")
|
||||
compile_manpage("mosquitto_passwd.1")
|
||||
compile_manpage("mosquitto_pub.1")
|
||||
compile_manpage("mosquitto_sub.1")
|
||||
compile_manpage("mosquitto_rr.1")
|
||||
compile_manpage("libmosquitto.3")
|
||||
compile_manpage("mosquitto.conf.5")
|
||||
compile_manpage("mosquitto-tls.7")
|
||||
compile_manpage("mqtt.7")
|
||||
compile_manpage("mosquitto.8")
|
||||
|
||||
install(FILES
|
||||
mosquitto_ctrl.1
|
||||
mosquitto_ctrl_dynsec.1
|
||||
mosquitto_passwd.1
|
||||
mosquitto_pub.1
|
||||
mosquitto_sub.1
|
||||
mosquitto_rr.1
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
|
||||
OPTIONAL)
|
||||
|
||||
install(FILES libmosquitto.3 DESTINATION ${CMAKE_INSTALL_MANDIR}/man3 OPTIONAL)
|
||||
install(FILES mosquitto.conf.5 DESTINATION ${CMAKE_INSTALL_MANDIR}/man5 OPTIONAL)
|
||||
install(FILES mosquitto-tls.7 mqtt.7 DESTINATION ${CMAKE_INSTALL_MANDIR}/man7 OPTIONAL)
|
||||
install(FILES mosquitto.8 DESTINATION ${CMAKE_INSTALL_MANDIR}/man8 OPTIONAL)
|
||||
|
||||
elseif(WIN32)
|
||||
message(WARNING "xsltproc not found: manpages cannot be built")
|
||||
else()
|
||||
message(FATAL_ERROR "xsltproc not found: manpages cannot be built")
|
||||
endif()
|
||||
|
||||
install(FILES
|
||||
mosquitto_ctrl.1
|
||||
mosquitto_ctrl_dynsec.1
|
||||
mosquitto_passwd.1
|
||||
mosquitto_pub.1
|
||||
mosquitto_rr.1
|
||||
mosquitto_sub.1
|
||||
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1"
|
||||
OPTIONAL)
|
||||
|
||||
install(FILES libmosquitto.3 DESTINATION "${CMAKE_INSTALL_MANDIR}/man3" OPTIONAL)
|
||||
install(FILES mosquitto.conf.5 DESTINATION "${CMAKE_INSTALL_MANDIR}/man5" OPTIONAL)
|
||||
install(FILES mosquitto-tls.7 mqtt.7 DESTINATION "${CMAKE_INSTALL_MANDIR}/man7" OPTIONAL)
|
||||
install(FILES mosquitto.8 DESTINATION "${CMAKE_INSTALL_MANDIR}/man8" OPTIONAL)
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<title>Server</title>
|
||||
<para>Generate a server key.</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>openssl genrsa -des3 -out server.key 2048</para></listitem>
|
||||
<listitem><para>openssl genrsa -aes256 -out server.key 2048</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Generate a server key without encryption.</para>
|
||||
@@ -71,7 +71,7 @@
|
||||
<title>Client</title>
|
||||
<para>Generate a client key.</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>openssl genrsa -des3 -out client.key 2048</para></listitem>
|
||||
<listitem><para>openssl genrsa -aes256 -out client.key 2048</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Generate a certificate signing request to send to the CA.</para>
|
||||
|
||||
@@ -1638,9 +1638,12 @@ openssl dhparam -out dhparam.pem 2048</programlisting>
|
||||
<term><option>keyfile</option> <replaceable>file path</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Path to the PEM encoded server key. This
|
||||
option and <option>certfile</option> must be present
|
||||
to enable certificate based TLS encryption.
|
||||
If <option>tls_keyform</option> equals "pem" this is the
|
||||
path to the PEM encoded server key. This option
|
||||
and <option>certfile</option> must be present
|
||||
to enable certificate based TLS encryption. If
|
||||
<option>tls_keyform</option> is "engine" this represents
|
||||
the engine handle of the private key.
|
||||
</para>
|
||||
<para>
|
||||
The private key pointed to by this option will be
|
||||
|
||||
@@ -319,7 +319,7 @@
|
||||
<listitem>
|
||||
<para>Disable Nagle's algorithm for the socket. This means
|
||||
that latency of sent messages is reduced, which is
|
||||
particularly noticable for small, reasonably infrequent
|
||||
particularly noticeable for small, reasonably infrequent
|
||||
messages. Using this option may result in more packets
|
||||
being sent than would normally be necessary.</para>
|
||||
</listitem>
|
||||
|
||||
@@ -715,6 +715,16 @@
|
||||
Defaults to <option>5</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-W</option></term>
|
||||
<listitem>
|
||||
<para>Provide a timeout as an integer number of seconds.
|
||||
mosquitto_sub will stop processing messages and
|
||||
disconnect after this number of seconds has
|
||||
passed. The timeout starts just after the client has
|
||||
connected to the broker.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--will-payload</option></term>
|
||||
<listitem>
|
||||
|
||||
@@ -1069,7 +1069,6 @@ mosquitto_sub -t 'bbc/#' -T bbc/bbc1 --remove-retained</programlisting>
|
||||
<para>If the payload is not valid JSON, then the error message "Error: Message payload is not valid JSON on topic
|
||||
<topic>" will be printed to stderr.</para></listitem>
|
||||
|
||||
<listitem><para><option>%I</option> ISO-8601 format date and time, e.g. 2016-08-10T09:47:38+0100</para></listitem>
|
||||
<listitem><para><option>%U</option> Unix timestamp with nanoseconds, e.g. 1470818943.786368637</para></listitem>
|
||||
</itemizedlist>
|
||||
</refsect2>
|
||||
|
||||
@@ -17,17 +17,19 @@ MY_DOMAIN=example.com
|
||||
# Set the directory that the certificates will be copied to.
|
||||
CERTIFICATE_DIR=/etc/mosquitto/certs
|
||||
|
||||
if [ "${RENEWED_DOMAINS}" = "${MY_DOMAIN}" ]; then
|
||||
# Copy new certificate to Mosquitto directory
|
||||
cp ${RENEWED_LINEAGE}/fullchain.pem ${CERTIFICATE_DIR}/server.pem
|
||||
cp ${RENEWED_LINEAGE}/privkey.pem ${CERTIFICATE_DIR}/server.key
|
||||
for D in ${RENEWED_DOMAINS}; do
|
||||
if [ "${D}" = "${MY_DOMAIN}" ]; then
|
||||
# Copy new certificate to Mosquitto directory
|
||||
cp ${RENEWED_LINEAGE}/fullchain.pem ${CERTIFICATE_DIR}/server.pem
|
||||
cp ${RENEWED_LINEAGE}/privkey.pem ${CERTIFICATE_DIR}/server.key
|
||||
|
||||
# Set ownership to Mosquitto
|
||||
chown mosquitto: ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key
|
||||
# Set ownership to Mosquitto
|
||||
chown mosquitto: ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key
|
||||
|
||||
# Ensure permissions are restrictive
|
||||
chmod 0600 ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key
|
||||
# Ensure permissions are restrictive
|
||||
chmod 0600 ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key
|
||||
|
||||
# Tell Mosquitto to reload certificates and configuration
|
||||
pkill -HUP -x mosquitto
|
||||
fi
|
||||
# Tell Mosquitto to reload certificates and configuration
|
||||
pkill -HUP -x mosquitto
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -61,7 +61,7 @@ Command:
|
||||
{
|
||||
"commands":[
|
||||
{
|
||||
"command": "getDefaultACLAccess",
|
||||
"command": "getDefaultACLAccess"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -244,7 +244,7 @@ Command:
|
||||
|
||||
mosquitto_ctrl example:
|
||||
```
|
||||
mosquitto_ctrl dynsec setClientPassword username password
|
||||
mosquitto_ctrl dynsec setClientId username clientId
|
||||
```
|
||||
|
||||
## Set Client Password
|
||||
@@ -523,7 +523,7 @@ Command:
|
||||
{
|
||||
"commands":[
|
||||
{
|
||||
"command": "getAnonymousGroup",
|
||||
"command": "getAnonymousGroup"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -42,9 +42,7 @@ static int memcmp_const(const void *a, const void *b, size_t len)
|
||||
if(!a || !b) return 1;
|
||||
|
||||
for(i=0; i<len; i++){
|
||||
if( ((char *)a)[i] != ((char *)b)[i] ){
|
||||
rc = 1;
|
||||
}
|
||||
rc |= ((char *)a)[i] ^ ((char *)b)[i];
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -107,17 +107,12 @@ void dynsec_clients__cleanup(struct dynsec__data *data)
|
||||
|
||||
int dynsec_clients__config_load(struct dynsec__data *data, cJSON *tree)
|
||||
{
|
||||
cJSON *j_clients, *j_client = NULL, *jtmp, *j_roles, *j_role;
|
||||
cJSON *j_clients, *j_client = NULL, *j_roles, *j_role;
|
||||
struct dynsec__client *client;
|
||||
struct dynsec__role *role;
|
||||
unsigned char *buf;
|
||||
unsigned int buf_len;
|
||||
int priority;
|
||||
int iterations;
|
||||
const char *username;
|
||||
size_t username_len;
|
||||
const char *salt;
|
||||
const char *password;
|
||||
|
||||
j_clients = cJSON_GetObjectItem(tree, "clients");
|
||||
if(j_clients == NULL){
|
||||
@@ -130,10 +125,11 @@ int dynsec_clients__config_load(struct dynsec__data *data, cJSON *tree)
|
||||
cJSON_ArrayForEach(j_client, j_clients){
|
||||
if(cJSON_IsObject(j_client) == true){
|
||||
/* Username */
|
||||
const char *username;
|
||||
if(json_get_string(j_client, "username", &username, false) != MOSQ_ERR_SUCCESS){
|
||||
continue;
|
||||
}
|
||||
username_len = strlen(username);
|
||||
size_t username_len = strlen(username);
|
||||
if(username_len == 0){
|
||||
continue;
|
||||
}
|
||||
@@ -147,11 +143,14 @@ int dynsec_clients__config_load(struct dynsec__data *data, cJSON *tree)
|
||||
}
|
||||
strncpy(client->username, username, username_len);
|
||||
|
||||
jtmp = cJSON_GetObjectItem(j_client, "disabled");
|
||||
if(jtmp && cJSON_IsBool(jtmp)){
|
||||
client->disabled = cJSON_IsTrue(jtmp);
|
||||
bool disabled;
|
||||
if(json_get_bool(j_client, "disabled", &disabled, false, false) == MOSQ_ERR_SUCCESS){
|
||||
client->disabled = disabled;
|
||||
}
|
||||
|
||||
int iterations;
|
||||
const char *salt;
|
||||
const char *password;
|
||||
json_get_int(j_client, "iterations", &iterations, 0, true);
|
||||
if(json_get_string(j_client, "salt", &salt, false) == MOSQ_ERR_SUCCESS
|
||||
&& json_get_string(j_client, "password", &password, false) == MOSQ_ERR_SUCCESS
|
||||
|
||||
@@ -195,7 +195,6 @@ int dynsec_groups__config_load(struct dynsec__data *data, cJSON *tree)
|
||||
struct dynsec__group *group;
|
||||
struct dynsec__role *role;
|
||||
int priority;
|
||||
const char *textname, *textdescription;
|
||||
const char *groupname;
|
||||
size_t groupname_len;
|
||||
|
||||
@@ -211,6 +210,7 @@ int dynsec_groups__config_load(struct dynsec__data *data, cJSON *tree)
|
||||
cJSON_ArrayForEach(j_group, j_groups){
|
||||
if(cJSON_IsObject(j_group) == true){
|
||||
/* Group name */
|
||||
const char *groupname;
|
||||
if(json_get_string(j_group, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){
|
||||
continue;
|
||||
}
|
||||
@@ -229,6 +229,7 @@ int dynsec_groups__config_load(struct dynsec__data *data, cJSON *tree)
|
||||
strncpy(group->groupname, groupname, groupname_len+1);
|
||||
|
||||
/* Text name */
|
||||
const char *textname;
|
||||
if(json_get_string(j_group, "textname", &textname, false) == MOSQ_ERR_SUCCESS){
|
||||
if(textname){
|
||||
group->text_name = strdup(textname);
|
||||
@@ -240,6 +241,7 @@ int dynsec_groups__config_load(struct dynsec__data *data, cJSON *tree)
|
||||
}
|
||||
|
||||
/* Text description */
|
||||
const char *textdescription;
|
||||
if(json_get_string(j_group, "textdescription", &textdescription, false) == MOSQ_ERR_SUCCESS){
|
||||
if(textdescription){
|
||||
group->text_description = strdup(textdescription);
|
||||
|
||||
@@ -204,13 +204,14 @@ static int insert_acl_cmp(struct dynsec__acl *a, struct dynsec__acl *b)
|
||||
|
||||
static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec__acl **acllist)
|
||||
{
|
||||
cJSON *j_acl, *jtmp;
|
||||
cJSON *j_acl;
|
||||
struct dynsec__acl *acl;
|
||||
size_t topic_len;
|
||||
const char *acltype;
|
||||
const char *topic;
|
||||
|
||||
cJSON_ArrayForEach(j_acl, j_acls){
|
||||
const char *acltype;
|
||||
const char *topic;
|
||||
size_t topic_len;
|
||||
|
||||
if(json_get_string(j_acl, "acltype", &acltype, false) != MOSQ_ERR_SUCCESS){
|
||||
continue;
|
||||
}
|
||||
@@ -226,6 +227,11 @@ static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec_
|
||||
continue;
|
||||
}
|
||||
|
||||
HASH_FIND(hh, *acllist, topic, strlen(topic), acl);
|
||||
if(acl){
|
||||
continue;
|
||||
}
|
||||
|
||||
acl = mosquitto_calloc(1, sizeof(struct dynsec__acl) + topic_len + 1);
|
||||
if(acl == NULL){
|
||||
return 1;
|
||||
@@ -235,9 +241,9 @@ static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec_
|
||||
json_get_int(j_acl, "priority", &acl->priority, true, 0);
|
||||
json_get_bool(j_acl, "allow", &acl->allow, true, false);
|
||||
|
||||
jtmp = cJSON_GetObjectItem(j_acl, "allow");
|
||||
if(jtmp && cJSON_IsBool(jtmp)){
|
||||
acl->allow = cJSON_IsTrue(jtmp);
|
||||
bool allow;
|
||||
if(json_get_bool(j_acl, "allow", &allow, false, false) == MOSQ_ERR_SUCCESS){
|
||||
acl->allow = allow;
|
||||
}
|
||||
|
||||
HASH_ADD_INORDER(hh, *acllist, topic, topic_len, acl, insert_acl_cmp);
|
||||
@@ -249,7 +255,7 @@ static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec_
|
||||
|
||||
int dynsec_roles__config_load(struct dynsec__data *data, cJSON *tree)
|
||||
{
|
||||
cJSON *j_roles, *j_role, *jtmp, *j_acls;
|
||||
cJSON *j_roles, *j_role, *j_acls;
|
||||
struct dynsec__role *role;
|
||||
size_t rolename_len;
|
||||
|
||||
@@ -305,12 +311,7 @@ int dynsec_roles__config_load(struct dynsec__data *data, cJSON *tree)
|
||||
}
|
||||
|
||||
/* Allow wildcard subs */
|
||||
jtmp = cJSON_GetObjectItem(j_role, "allowwildcardsubs");
|
||||
if(jtmp != NULL && cJSON_IsBool(jtmp)){
|
||||
role->allow_wildcard_subs = cJSON_IsTrue(jtmp);
|
||||
}else{
|
||||
role->allow_wildcard_subs = true;
|
||||
}
|
||||
json_get_bool(j_role, "allowwildcardsubs", &role->allow_wildcard_subs, true, true);
|
||||
|
||||
/* ACLs */
|
||||
j_acls = cJSON_GetObjectItem(j_role, "acls");
|
||||
|
||||
@@ -107,5 +107,5 @@ int mosquitto_plugin_cleanup(void *user_data, struct mosquitto_opt *opts, int op
|
||||
UNUSED(opts);
|
||||
UNUSED(opt_count);
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
return mosquitto_callback_unregister(mosq_pid, MOSQ_EVT_BASIC_AUTH, basic_auth_callback, NULL);
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ static int client_msg_restore(struct mosquitto_sqlite *ms)
|
||||
client_msg.clientid = (const char *)sqlite3_column_text(stmt, 0);
|
||||
client_msg.cmsg_id = (uint64_t)sqlite3_column_int64(stmt, 1);
|
||||
client_msg.store_id = (uint64_t)sqlite3_column_int64(stmt, 2);
|
||||
client_msg.dup = sqlite3_column_int(stmt, 3);
|
||||
client_msg.dup = (uint8_t)sqlite3_column_int(stmt, 3);
|
||||
client_msg.direction = (uint8_t)sqlite3_column_int(stmt, 4);
|
||||
client_msg.mid = (uint16_t)sqlite3_column_int(stmt, 5);
|
||||
client_msg.qos = (uint8_t)sqlite3_column_int(stmt, 6);
|
||||
|
||||
@@ -298,6 +298,7 @@ static void config__init_reload(struct mosquitto__config *config)
|
||||
mosquitto__FREE(config->log_timestamp_format);
|
||||
config->global_max_clients = -1;
|
||||
config->global_max_connections = -1;
|
||||
config->log_timestamp_format = NULL;
|
||||
config->max_keepalive = 0;
|
||||
config->max_packet_size = 0;
|
||||
config->max_inflight_messages = 20;
|
||||
@@ -1859,6 +1860,7 @@ static int config__read_file_core(struct mosquitto__config *config, bool reload,
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
cr->log_dest |= MQTT3_LOG_FILE;
|
||||
}else{
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty \"log_dest file\" value in configuration.");
|
||||
return MOSQ_ERR_INVAL;
|
||||
|
||||
+21
-12
@@ -105,8 +105,8 @@ struct mosquitto *context__init(void)
|
||||
context->address = NULL;
|
||||
context->bridge = NULL;
|
||||
context->msgs_in.inflight_maximum = db.config->max_inflight_messages;
|
||||
context->msgs_out.inflight_maximum = db.config->max_inflight_messages;
|
||||
context->msgs_in.inflight_quota = db.config->max_inflight_messages;
|
||||
context->msgs_out.inflight_maximum = db.config->max_inflight_messages;
|
||||
context->msgs_out.inflight_quota = db.config->max_inflight_messages;
|
||||
context->max_qos = 2;
|
||||
#ifdef WITH_TLS
|
||||
@@ -116,6 +116,24 @@ struct mosquitto *context__init(void)
|
||||
return context;
|
||||
}
|
||||
|
||||
static void context__cleanup_out_packets(struct mosquitto *context)
|
||||
{
|
||||
struct mosquitto__packet *packet;
|
||||
|
||||
if(!context) return;
|
||||
|
||||
while(context->out_packet){
|
||||
packet = context->out_packet;
|
||||
context->out_packet = context->out_packet->next;
|
||||
mosquitto__free(packet);
|
||||
}
|
||||
metrics__int_dec(mosq_gauge_out_packets, context->out_packet_count);
|
||||
metrics__int_dec(mosq_gauge_out_packet_bytes, context->out_packet_bytes);
|
||||
context->out_packet_count = 0;
|
||||
context->out_packet_bytes = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This will result in any outgoing packets going unsent. If we're disconnected
|
||||
* forcefully then it is usually an error condition and shouldn't be a problem,
|
||||
@@ -124,8 +142,6 @@ struct mosquitto *context__init(void)
|
||||
*/
|
||||
void context__cleanup(struct mosquitto *context, bool force_free)
|
||||
{
|
||||
struct mosquitto__packet *packet;
|
||||
|
||||
if(!context) return;
|
||||
|
||||
if(force_free){
|
||||
@@ -140,6 +156,7 @@ void context__cleanup(struct mosquitto *context, bool force_free)
|
||||
|
||||
alias__free_all(context);
|
||||
keepalive__remove(context);
|
||||
context__cleanup_out_packets(context);
|
||||
|
||||
mosquitto__FREE(context->auth_method);
|
||||
mosquitto__FREE(context->username);
|
||||
@@ -160,15 +177,7 @@ void context__cleanup(struct mosquitto *context, bool force_free)
|
||||
mosquitto__FREE(context->id);
|
||||
}
|
||||
packet__cleanup(&(context->in_packet));
|
||||
while(context->out_packet){
|
||||
packet = context->out_packet;
|
||||
context->out_packet = context->out_packet->next;
|
||||
mosquitto__FREE(packet);
|
||||
}
|
||||
metrics__int_dec(mosq_gauge_out_packets, context->out_packet_count);
|
||||
metrics__int_dec(mosq_gauge_out_packet_bytes, context->out_packet_bytes);
|
||||
context->out_packet_count = 0;
|
||||
context->out_packet_bytes = 0;
|
||||
context__cleanup_out_packets(context);
|
||||
#if defined(WITH_BROKER) && defined(__GLIBC__) && defined(WITH_ADNS)
|
||||
if(context->adns){
|
||||
gai_cancel(context->adns);
|
||||
|
||||
+12
-9
@@ -964,23 +964,24 @@ int db__message_store(const struct mosquitto *source, struct mosquitto__base_msg
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int db__message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto__base_msg **base_msg)
|
||||
int db__message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto__client_msg **client_msg)
|
||||
{
|
||||
struct mosquitto__client_msg *client_msg;
|
||||
struct mosquitto__client_msg *cmsg;
|
||||
|
||||
*client_msg = NULL;
|
||||
|
||||
if(!context) return MOSQ_ERR_INVAL;
|
||||
|
||||
*base_msg = NULL;
|
||||
DL_FOREACH(context->msgs_in.inflight, client_msg){
|
||||
if(client_msg->base_msg->data.source_mid == mid){
|
||||
*base_msg = client_msg->base_msg;
|
||||
DL_FOREACH(context->msgs_in.inflight, cmsg){
|
||||
if(cmsg->base_msg->data.source_mid == mid){
|
||||
*client_msg = cmsg;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
DL_FOREACH(context->msgs_in.queued, client_msg){
|
||||
if(client_msg->base_msg->data.source_mid == mid){
|
||||
*base_msg = client_msg->base_msg;
|
||||
DL_FOREACH(context->msgs_in.queued, cmsg){
|
||||
if(cmsg->base_msg->data.source_mid == mid){
|
||||
*client_msg = cmsg;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -1084,6 +1085,7 @@ static int db__message_reconnect_reset_incoming(struct mosquitto *context)
|
||||
}else{
|
||||
/* Message state can be preserved here because it should match
|
||||
* whatever the client has got. */
|
||||
client_msg->data.dup = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1094,6 +1096,7 @@ static int db__message_reconnect_reset_incoming(struct mosquitto *context)
|
||||
* will be sent out of order.
|
||||
*/
|
||||
DL_FOREACH_SAFE(context->msgs_in.queued, client_msg, tmp){
|
||||
client_msg->data.dup = 0;
|
||||
db__msg_add_to_queued_stats(&context->msgs_in, client_msg);
|
||||
if(db__ready_for_flight(context, mosq_md_in, client_msg->data.qos)){
|
||||
switch(client_msg->data.qos){
|
||||
|
||||
@@ -403,6 +403,10 @@ static int will__read(struct mosquitto *context, const char *clientid, struct mo
|
||||
will_struct->msg.topic = will_topic_mount;
|
||||
}
|
||||
|
||||
if(!strncmp(will_struct->msg.topic, "$CONTROL/", strlen("$CONTROL/"))){
|
||||
rc = MOSQ_ERR_ACL_DENIED;
|
||||
goto error_cleanup;
|
||||
}
|
||||
rc = mosquitto_pub_topic_check(will_struct->msg.topic);
|
||||
if(rc) goto error_cleanup;
|
||||
|
||||
@@ -1065,6 +1069,7 @@ handle_connect_error:
|
||||
mosquitto__FREE(context->will->msg.payload);
|
||||
mosquitto__FREE(context->will->msg.topic);
|
||||
mosquitto__FREE(context->will);
|
||||
context->will = NULL;
|
||||
}
|
||||
/* We return an error here which means the client is freed later on. */
|
||||
context->clean_start = true;
|
||||
|
||||
+24
-11
@@ -42,6 +42,7 @@ int handle__publish(struct mosquitto *context)
|
||||
uint8_t header = context->in_packet.command;
|
||||
int res = 0;
|
||||
struct mosquitto__base_msg *base_msg, *stored = NULL;
|
||||
struct mosquitto__client_msg *cmsg_stored = NULL;
|
||||
size_t len;
|
||||
uint16_t slen;
|
||||
char *topic_mount;
|
||||
@@ -300,21 +301,21 @@ int handle__publish(struct mosquitto *context)
|
||||
}
|
||||
|
||||
if(base_msg->data.qos > 0){
|
||||
db__message_store_find(context, base_msg->data.source_mid, &stored);
|
||||
db__message_store_find(context, base_msg->data.source_mid, &cmsg_stored);
|
||||
}
|
||||
|
||||
if(stored && base_msg->data.source_mid != 0 &&
|
||||
(stored->data.qos != base_msg->data.qos
|
||||
|| stored->data.payloadlen != base_msg->data.payloadlen
|
||||
|| strcmp(stored->data.topic, base_msg->data.topic)
|
||||
|| memcmp(stored->data.payload, base_msg->data.payload, base_msg->data.payloadlen) )){
|
||||
if(cmsg_stored && cmsg_stored->base_msg && base_msg->data.source_mid != 0 &&
|
||||
(cmsg_stored->base_msg->data.qos != base_msg->data.qos
|
||||
|| cmsg_stored->base_msg->data.payloadlen != base_msg->data.payloadlen
|
||||
|| strcmp(cmsg_stored->base_msg->data.topic, base_msg->data.topic)
|
||||
|| memcmp(cmsg_stored->base_msg->data.payload, base_msg->data.payload, base_msg->data.payloadlen) )){
|
||||
|
||||
log__printf(NULL, MOSQ_LOG_WARNING, "Reused message ID %u from %s detected. Clearing from storage.", base_msg->data.source_mid, context->id);
|
||||
db__message_remove_incoming(context, base_msg->data.source_mid);
|
||||
stored = NULL;
|
||||
cmsg_stored = NULL;
|
||||
}
|
||||
|
||||
if(!stored){
|
||||
if(!cmsg_stored){
|
||||
if(base_msg->data.qos > 0 && context->msgs_in.inflight_quota == 0){
|
||||
/* Client isn't allowed any more incoming messages, so fail early */
|
||||
db__msg_store_free(base_msg);
|
||||
@@ -323,7 +324,7 @@ int handle__publish(struct mosquitto *context)
|
||||
|
||||
if(base_msg->data.qos == 0
|
||||
|| db__ready_for_flight(context, mosq_md_in, base_msg->data.qos)
|
||||
|| db__ready_for_queue(context, base_msg->data.qos, &context->msgs_in)){
|
||||
){
|
||||
|
||||
dup = 0;
|
||||
rc = db__message_store(context, base_msg, message_expiry_interval, mosq_mo_client);
|
||||
@@ -335,10 +336,13 @@ int handle__publish(struct mosquitto *context)
|
||||
}
|
||||
stored = base_msg;
|
||||
base_msg = NULL;
|
||||
dup = 0;
|
||||
}else{
|
||||
db__msg_store_free(base_msg);
|
||||
base_msg = NULL;
|
||||
dup = 1;
|
||||
stored = cmsg_stored->base_msg;
|
||||
cmsg_stored->data.dup++;
|
||||
dup = cmsg_stored->data.dup;
|
||||
}
|
||||
|
||||
switch(stored->data.qos){
|
||||
@@ -364,11 +368,17 @@ int handle__publish(struct mosquitto *context)
|
||||
}else{
|
||||
res = 0;
|
||||
}
|
||||
|
||||
/* db__message_insert() returns 2 to indicate dropped message
|
||||
* due to queue. This isn't an error so don't disconnect them. */
|
||||
/* FIXME - this is no longer necessary due to failing early above */
|
||||
if(!res){
|
||||
if(send__pubrec(context, stored->data.source_mid, 0, NULL)) rc = 1;
|
||||
if(dup == 0 || dup == 1){
|
||||
rc2 = send__pubrec(context, stored->data.source_mid, 0, NULL);
|
||||
if(rc2) rc = rc2;
|
||||
}else{
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
}else if(res == 1){
|
||||
rc = 1;
|
||||
}
|
||||
@@ -393,5 +403,8 @@ process_bad_message:
|
||||
}
|
||||
db__msg_store_free(base_msg);
|
||||
}
|
||||
if(context->out_packet_count >= db.config->max_queued_messages){
|
||||
rc = MQTT_RC_QUOTA_EXCEEDED;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
+10
-4
@@ -21,6 +21,7 @@ Contributors:
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#ifndef WIN32
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
@@ -135,11 +136,16 @@ int log__init(struct mosquitto__config *config)
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open log file %s for writing.", config->log_file);
|
||||
}
|
||||
}
|
||||
if(log_destinations & MQTT3_LOG_STDOUT){
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
}
|
||||
#ifdef WITH_DLT
|
||||
dlt_fifo_check();
|
||||
if(dlt_allowed){
|
||||
DLT_REGISTER_APP("MQTT","mosquitto log");
|
||||
dlt_register_context(&dltContext, "MQTT", "mosquitto DLT context");
|
||||
if(log_destinations & MQTT3_LOG_DLT){
|
||||
dlt_fifo_check();
|
||||
if(dlt_allowed){
|
||||
DLT_REGISTER_APP("MQTT","mosquitto log");
|
||||
dlt_register_context(&dltContext, "MQTT", "mosquitto DLT context");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
|
||||
+12
-4
@@ -239,9 +239,18 @@ static void mosquitto__daemonise(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(freopen("/dev/null", "r", stdin));
|
||||
assert(freopen("/dev/null", "w", stdout));
|
||||
assert(freopen("/dev/null", "w", stderr));
|
||||
if(!freopen("/dev/null", "r", stdin)){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error whilst daemonising (%s): %s", "stdin", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if(!freopen("/dev/null", "w", stdout)){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error whilst daemonising (%s): %s", "stdout", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if(!freopen("/dev/null", "w", stderr)){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error whilst daemonising (%s): %s", "stderr", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Can't start in daemon mode in Windows.");
|
||||
#endif
|
||||
@@ -342,7 +351,6 @@ int main(int argc, char *argv[])
|
||||
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Unable to increase maximum allowed connections. This session may be limited to 512 connections.");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
memset(&db, 0, sizeof(struct mosquitto_db));
|
||||
|
||||
@@ -720,7 +720,7 @@ int db__messages_delete_incoming(struct mosquitto *context);
|
||||
int db__messages_delete_outgoing(struct mosquitto *context);
|
||||
int db__messages_easy_queue(struct mosquitto *context, const char *topic, uint8_t qos, uint32_t payloadlen, const void *payload, int retain, uint32_t message_expiry_interval, mosquitto_property **properties);
|
||||
int db__message_store(const struct mosquitto *source, struct mosquitto__base_msg *base_msg, uint32_t message_expiry_interval, enum mosquitto_msg_origin origin);
|
||||
int db__message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto__base_msg **base_msg);
|
||||
int db__message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto__client_msg **client_msg);
|
||||
int db__msg_store_add(struct mosquitto__base_msg *base_msg);
|
||||
void db__msg_store_remove(struct mosquitto__base_msg *base_msg, bool notify);
|
||||
void db__msg_store_ref_inc(struct mosquitto__base_msg *base_msg);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user