mirror of
https://github.com/eclipse/mosquitto.git
synced 2025-04-19 10:22:16 +03:00
Initial contribution.
This commit is contained in:
commit
0364bd1be7
39
.gitignore
vendored
Normal file
39
.gitignore
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
*.o
|
||||
*.exe
|
||||
*.db
|
||||
c/*.test
|
||||
cpp/*.test
|
||||
*.pyc
|
||||
|
||||
client/mosquitto_pub
|
||||
client/mosquitto_sub
|
||||
examples/mysql_log/mosquitto_mysql_log
|
||||
examples/temperature_conversion/mqtt_temperature_conversion
|
||||
man/mosquitto.8
|
||||
man/mosquitto-tls.7
|
||||
man/mosquitto.conf.5
|
||||
man/libmosquitto.3
|
||||
man/mosquitto_passwd.1
|
||||
man/mosquitto_pub.1
|
||||
man/mosquitto_sub.1
|
||||
man/mqtt.7
|
||||
src/db_dump/mosquitto_db_dump
|
||||
src/mosquitto
|
||||
src/mosquitto_passwd
|
||||
test/broker/broker.pid
|
||||
test/test_client
|
||||
test/fake_user
|
||||
test/msgsps_pub
|
||||
test/msgsps_sub
|
||||
test/msgsps_pub.dat
|
||||
test/msgsps_sub.dat
|
||||
test/broker/c/auth_plugin.so
|
||||
|
||||
lib/cpp/libmosquittopp.so*
|
||||
lib/libmosquitto.so*
|
||||
lib/libmosquitto.a
|
||||
|
||||
test/ssl/*.csr
|
||||
|
||||
build/
|
||||
dist/
|
74
CMakeLists.txt
Normal file
74
CMakeLists.txt
Normal file
@ -0,0 +1,74 @@
|
||||
# This is a cmake script.
|
||||
|
||||
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
|
||||
|
||||
project(mosquitto)
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
set (VERSION 1.3.1)
|
||||
|
||||
if (WIN32)
|
||||
execute_process(COMMAND cmd /c echo %DATE% %TIME% OUTPUT_VARIABLE TIMESTAMP
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
else (WIN32)
|
||||
execute_process(COMMAND date "+%F %T%z" OUTPUT_VARIABLE TIMESTAMP
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif (WIN32)
|
||||
|
||||
add_definitions (-DCMAKE -DVERSION=\"${VERSION}\" -DTIMESTAMP=\"${TIMESTAMP}\")
|
||||
|
||||
if (WIN32)
|
||||
set (BINDIR .)
|
||||
set (SBINDIR .)
|
||||
set (SYSCONFDIR .)
|
||||
set (LIBDIR .)
|
||||
set (INCLUDEDIR include)
|
||||
set (DATAROOTDIR share)
|
||||
set (MANDIR man)
|
||||
set (SHAREDEST .)
|
||||
add_definitions("-D_CRT_SECURE_NO_WARNINGS")
|
||||
else (WIN32)
|
||||
set (BINDIR bin)
|
||||
set (SBINDIR sbin)
|
||||
if (${CMAKE_INSTALL_PREFIX} STREQUAL /usr)
|
||||
set (SYSCONFDIR /etc/mosquitto)
|
||||
else (${CMAKE_INSTALL_PREFIX} STREQUAL /usr)
|
||||
set (SYSCONFDIR etc/mosquitto)
|
||||
endif (${CMAKE_INSTALL_PREFIX} STREQUAL /usr)
|
||||
|
||||
set (LIBDIR lib${LIB_SUFFIX})
|
||||
set (INCLUDEDIR include)
|
||||
set (DATAROOTDIR share)
|
||||
set (MANDIR ${DATAROOTDIR}/man)
|
||||
set (SHAREDIR ${DATAROOTDIR}/mosquitto)
|
||||
endif (WIN32)
|
||||
|
||||
option(WITH_TLS
|
||||
"Include SSL/TLS support?" ON)
|
||||
option(WITH_TLS_PSK
|
||||
"Include TLS-PSK support (requires WITH_TLS)?" ON)
|
||||
if (${WITH_TLS} STREQUAL ON)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
add_definitions("-DWITH_TLS")
|
||||
if (${WITH_TLS_PSK} STREQUAL ON)
|
||||
add_definitions("-DWITH_TLS_PSK")
|
||||
endif (${WITH_TLS_PSK} STREQUAL ON)
|
||||
else (${WITH_TLS} STREQUAL ON)
|
||||
set (OPENSSL_INCLUDE_DIR "")
|
||||
endif (${WITH_TLS} STREQUAL ON)
|
||||
|
||||
# ========================================
|
||||
# Include projects
|
||||
# ========================================
|
||||
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(client)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(man)
|
||||
|
||||
# ========================================
|
||||
# Install config file
|
||||
# ========================================
|
||||
|
||||
install(FILES mosquitto.conf aclfile.example pskfile.example pwfile.example DESTINATION ${SYSCONFDIR})
|
1093
ChangeLog.txt
Normal file
1093
ChangeLog.txt
Normal file
File diff suppressed because it is too large
Load Diff
2
LICENSE.txt
Normal file
2
LICENSE.txt
Normal file
@ -0,0 +1,2 @@
|
||||
This project is dual licensed under the Eclipse Public License 1.0 and the
|
||||
Eclipse Distribution License 1.0 as described in the epl-v10 and edl-v10 files.
|
70
Makefile
Normal file
70
Makefile
Normal file
@ -0,0 +1,70 @@
|
||||
include config.mk
|
||||
|
||||
DIRS=lib client src
|
||||
DOCDIRS=man
|
||||
DISTDIRS=man
|
||||
|
||||
.PHONY : all mosquitto docs binary clean reallyclean test install uninstall dist sign copy
|
||||
|
||||
all : mosquitto docs
|
||||
|
||||
docs :
|
||||
set -e; for d in ${DOCDIRS}; do $(MAKE) -C $${d}; done
|
||||
|
||||
binary : mosquitto
|
||||
|
||||
mosquitto :
|
||||
set -e; for d in ${DIRS}; do $(MAKE) -C $${d}; done
|
||||
|
||||
clean :
|
||||
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} clean; done
|
||||
set -e; for d in ${DOCDIRS}; do $(MAKE) -C $${d} clean; done
|
||||
$(MAKE) -C test clean
|
||||
|
||||
reallyclean :
|
||||
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} reallyclean; done
|
||||
set -e; for d in ${DOCDIRS}; do $(MAKE) -C $${d} reallyclean; done
|
||||
$(MAKE) -C test reallyclean
|
||||
-rm -f *.orig
|
||||
|
||||
test : mosquitto
|
||||
$(MAKE) -C test test
|
||||
|
||||
install : mosquitto
|
||||
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} install; done
|
||||
set -e; for d in ${DOCDIRS}; do $(MAKE) -C $${d} install; done
|
||||
$(INSTALL) -d ${DESTDIR}/etc/mosquitto
|
||||
$(INSTALL) -m 644 mosquitto.conf ${DESTDIR}/etc/mosquitto/mosquitto.conf.example
|
||||
$(INSTALL) -m 644 aclfile.example ${DESTDIR}/etc/mosquitto/aclfile.example
|
||||
$(INSTALL) -m 644 pwfile.example ${DESTDIR}/etc/mosquitto/pwfile.example
|
||||
$(INSTALL) -m 644 pskfile.example ${DESTDIR}/etc/mosquitto/pskfile.example
|
||||
|
||||
uninstall :
|
||||
set -e; for d in ${DIRS}; do $(MAKE) -C $${d} uninstall; done
|
||||
rm -f ${DESTDIR}/etc/mosquitto/mosquitto.conf
|
||||
rm -f ${DESTDIR}/etc/mosquitto/aclfile.example
|
||||
rm -f ${DESTDIR}/etc/mosquitto/pwfile.example
|
||||
rm -f ${DESTDIR}/etc/mosquitto/pskfile.example
|
||||
|
||||
dist : reallyclean
|
||||
set -e; for d in ${DISTDIRS}; do $(MAKE) -C $${d} dist; done
|
||||
|
||||
echo $$(hg log -r . --template "{node}") > changeset
|
||||
mkdir -p dist/mosquitto-${VERSION}
|
||||
cp -r client changeset examples installer lib logo man misc security service src test ChangeLog.txt CMakeLists.txt LICENSE.txt LICENSE-3rd-party.txt Makefile compiling.txt config.h config.mk readme.txt readme-windows.txt mosquitto.conf aclfile.example pskfile.example pwfile.example dist/mosquitto-${VERSION}/
|
||||
cd dist; tar -zcf mosquitto-${VERSION}.tar.gz mosquitto-${VERSION}/
|
||||
set -e; for m in man/*.xml; \
|
||||
do \
|
||||
hfile=$$(echo $${m} | sed -e 's#man/\(.*\)\.xml#\1#' | sed -e 's/\./-/g'); \
|
||||
$(XSLTPROC) $(DB_HTML_XSL) $${m} > dist/$${hfile}.html; \
|
||||
done
|
||||
|
||||
|
||||
sign : dist
|
||||
cd dist; gpg --detach-sign -a mosquitto-${VERSION}.tar.gz
|
||||
|
||||
copy : sign
|
||||
cd dist; scp mosquitto-${VERSION}.tar.gz mosquitto-${VERSION}.tar.gz.asc mosquitto:site/mosquitto.org/files/source/
|
||||
cd dist; scp *.html mosquitto:site/mosquitto.org/man/
|
||||
scp ChangeLog.txt mosquitto:site/mosquitto.org/
|
||||
|
57
THANKS.txt
Normal file
57
THANKS.txt
Normal file
@ -0,0 +1,57 @@
|
||||
These people have reported bugs / provided patches / done something else to aid
|
||||
the mosquitto project. Thanks to you all!
|
||||
|
||||
If you think I've missed you off the list, please rest assured that it wasn't
|
||||
intentional and get in touch and I'll fix it.
|
||||
|
||||
Adam Rudd
|
||||
Andrew Elwell
|
||||
Andy Piper
|
||||
Andy Stanford-Clark
|
||||
Bart Van Der Meerssche
|
||||
Ben Tobin
|
||||
Brad Stancel
|
||||
Chris Willing
|
||||
Craig Hollabaugh
|
||||
Dan Anderson
|
||||
Dariusz Suchojad
|
||||
David Huang
|
||||
David Monro
|
||||
Dirk O. Kaar
|
||||
Dominik Obermaier
|
||||
Dominik Zajac
|
||||
Ed Morris
|
||||
Frank Hansen
|
||||
Gary Koh
|
||||
Joan Zapata
|
||||
Karl Palsson
|
||||
Larry Lendo
|
||||
Martin Assarsson
|
||||
Marty Lee
|
||||
Matt Daubney
|
||||
Michael C
|
||||
Michael Frisch
|
||||
Michael Rushton
|
||||
Mike Bush
|
||||
Neil Bothwick
|
||||
Nicholas Humfrey
|
||||
Nicholas O'Leary
|
||||
Nithin Kumar
|
||||
Paul Diston
|
||||
Peter George
|
||||
Rob Pridham
|
||||
Robin Gingras
|
||||
Roland de Boo
|
||||
Sebastian Kroll
|
||||
Sharon Ben-Asher
|
||||
sskaje
|
||||
Stefan Hudelmaier
|
||||
Stefano Costa
|
||||
Stephen Woods
|
||||
Steven Lougheed
|
||||
Thomas Hilbig
|
||||
Tobias Assarsson
|
||||
Toby Jaffey
|
||||
Vicente Ruiz
|
||||
Wayne Ingram
|
||||
Yuvraaj Kelkar
|
9
aclfile.example
Normal file
9
aclfile.example
Normal file
@ -0,0 +1,9 @@
|
||||
# This affects access control for clients with no username.
|
||||
topic read $SYS/#
|
||||
|
||||
# This only affects clients with username "roger".
|
||||
user roger
|
||||
topic foo/bar
|
||||
|
||||
# This affects all clients.
|
||||
pattern write $SYS/broker/connection/%c/state
|
12
client/CMakeLists.txt
Normal file
12
client/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
||||
include_directories(${mosquitto_SOURCE_DIR}/lib
|
||||
${STDBOOL_H_PATH} ${STDINT_H_PATH})
|
||||
link_directories(${mosquitto_BINARY_DIR}/lib)
|
||||
|
||||
add_executable(mosquitto_pub pub_client.c)
|
||||
add_executable(mosquitto_sub sub_client.c)
|
||||
|
||||
target_link_libraries(mosquitto_pub mosquitto)
|
||||
target_link_libraries(mosquitto_sub mosquitto)
|
||||
|
||||
install(TARGETS mosquitto_pub RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR})
|
||||
install(TARGETS mosquitto_sub RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR})
|
34
client/Makefile
Normal file
34
client/Makefile
Normal file
@ -0,0 +1,34 @@
|
||||
include ../config.mk
|
||||
|
||||
.PHONY: all install uninstall reallyclean clean
|
||||
|
||||
all : mosquitto_pub mosquitto_sub
|
||||
|
||||
mosquitto_pub : pub_client.o ../lib/libmosquitto.so.${SOVERSION}
|
||||
${CC} $< -o $@ ${CLIENT_LDFLAGS}
|
||||
|
||||
mosquitto_sub : sub_client.o ../lib/libmosquitto.so.${SOVERSION}
|
||||
${CC} $< -o $@ ${CLIENT_LDFLAGS}
|
||||
|
||||
pub_client.o : pub_client.c ../lib/libmosquitto.so.${SOVERSION}
|
||||
${CC} -c $< -o $@ ${CLIENT_CFLAGS}
|
||||
|
||||
sub_client.o : sub_client.c ../lib/libmosquitto.so.${SOVERSION}
|
||||
${CC} -c $< -o $@ ${CLIENT_CFLAGS}
|
||||
|
||||
../lib/libmosquitto.so.${SOVERSION} :
|
||||
$(MAKE) -C ../lib
|
||||
|
||||
install : all
|
||||
$(INSTALL) -d ${DESTDIR}$(prefix)/bin
|
||||
$(INSTALL) -s mosquitto_pub ${DESTDIR}${prefix}/bin/mosquitto_pub
|
||||
$(INSTALL) -s mosquitto_sub ${DESTDIR}${prefix}/bin/mosquitto_sub
|
||||
|
||||
uninstall :
|
||||
-rm -f ${DESTDIR}${prefix}/bin/mosquitto_pub
|
||||
-rm -f ${DESTDIR}${prefix}/bin/mosquitto_sub
|
||||
|
||||
reallyclean : clean
|
||||
|
||||
clean :
|
||||
-rm -f *.o mosquitto_pub mosquitto_sub
|
785
client/pub_client.c
Normal file
785
client/pub_client.c
Normal file
@ -0,0 +1,785 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <process.h>
|
||||
#include <winsock2.h>
|
||||
#define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
#include <mosquitto.h>
|
||||
|
||||
#define MSGMODE_NONE 0
|
||||
#define MSGMODE_CMD 1
|
||||
#define MSGMODE_STDIN_LINE 2
|
||||
#define MSGMODE_STDIN_FILE 3
|
||||
#define MSGMODE_FILE 4
|
||||
#define MSGMODE_NULL 5
|
||||
|
||||
#define STATUS_CONNECTING 0
|
||||
#define STATUS_CONNACK_RECVD 1
|
||||
#define STATUS_WAITING 2
|
||||
|
||||
/* Global variables for use in callbacks. See sub_client.c for an example of
|
||||
* using a struct to hold variables for use in callbacks. */
|
||||
static char *topic = NULL;
|
||||
static char *message = NULL;
|
||||
static long msglen = 0;
|
||||
static int qos = 0;
|
||||
static int retain = 0;
|
||||
static int mode = MSGMODE_NONE;
|
||||
static int status = STATUS_CONNECTING;
|
||||
static int mid_sent = 0;
|
||||
static int last_mid = -1;
|
||||
static int last_mid_sent = -1;
|
||||
static bool connected = true;
|
||||
static char *username = NULL;
|
||||
static char *password = NULL;
|
||||
static bool disconnect_sent = false;
|
||||
static bool quiet = false;
|
||||
|
||||
void my_connect_callback(struct mosquitto *mosq, void *obj, int result)
|
||||
{
|
||||
int rc = MOSQ_ERR_SUCCESS;
|
||||
|
||||
if(!result){
|
||||
switch(mode){
|
||||
case MSGMODE_CMD:
|
||||
case MSGMODE_FILE:
|
||||
case MSGMODE_STDIN_FILE:
|
||||
rc = mosquitto_publish(mosq, &mid_sent, topic, msglen, message, qos, retain);
|
||||
break;
|
||||
case MSGMODE_NULL:
|
||||
rc = mosquitto_publish(mosq, &mid_sent, topic, 0, NULL, qos, retain);
|
||||
break;
|
||||
case MSGMODE_STDIN_LINE:
|
||||
status = STATUS_CONNACK_RECVD;
|
||||
break;
|
||||
}
|
||||
if(rc){
|
||||
if(!quiet){
|
||||
switch(rc){
|
||||
case MOSQ_ERR_INVAL:
|
||||
fprintf(stderr, "Error: Invalid input. Does your topic contain '+' or '#'?\n");
|
||||
break;
|
||||
case MOSQ_ERR_NOMEM:
|
||||
fprintf(stderr, "Error: Out of memory when trying to publish message.\n");
|
||||
break;
|
||||
case MOSQ_ERR_NO_CONN:
|
||||
fprintf(stderr, "Error: Client not connected when trying to publish.\n");
|
||||
break;
|
||||
case MOSQ_ERR_PROTOCOL:
|
||||
fprintf(stderr, "Error: Protocol error when communicating with broker.\n");
|
||||
break;
|
||||
case MOSQ_ERR_PAYLOAD_SIZE:
|
||||
fprintf(stderr, "Error: Message payload is too large.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
mosquitto_disconnect(mosq);
|
||||
}
|
||||
}else{
|
||||
if(result && !quiet){
|
||||
fprintf(stderr, "%s\n", mosquitto_connack_string(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void my_disconnect_callback(struct mosquitto *mosq, void *obj, int rc)
|
||||
{
|
||||
connected = false;
|
||||
}
|
||||
|
||||
void my_publish_callback(struct mosquitto *mosq, void *obj, int mid)
|
||||
{
|
||||
last_mid_sent = mid;
|
||||
if(mode == MSGMODE_STDIN_LINE){
|
||||
if(mid == last_mid){
|
||||
mosquitto_disconnect(mosq);
|
||||
disconnect_sent = true;
|
||||
}
|
||||
}else if(disconnect_sent == false){
|
||||
mosquitto_disconnect(mosq);
|
||||
disconnect_sent = true;
|
||||
}
|
||||
}
|
||||
|
||||
void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str)
|
||||
{
|
||||
printf("%s\n", str);
|
||||
}
|
||||
|
||||
int load_stdin(void)
|
||||
{
|
||||
long pos = 0, rlen;
|
||||
char buf[1024];
|
||||
|
||||
mode = MSGMODE_STDIN_FILE;
|
||||
|
||||
while(!feof(stdin)){
|
||||
rlen = fread(buf, 1, 1024, stdin);
|
||||
message = realloc(message, pos+rlen);
|
||||
if(!message){
|
||||
if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
return 1;
|
||||
}
|
||||
memcpy(&(message[pos]), buf, rlen);
|
||||
pos += rlen;
|
||||
}
|
||||
msglen = pos;
|
||||
|
||||
if(!msglen){
|
||||
if(!quiet) fprintf(stderr, "Error: Zero length input.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_file(const char *filename)
|
||||
{
|
||||
long pos, rlen;
|
||||
FILE *fptr = NULL;
|
||||
|
||||
fptr = fopen(filename, "rb");
|
||||
if(!fptr){
|
||||
if(!quiet) fprintf(stderr, "Error: Unable to open file \"%s\".\n", filename);
|
||||
return 1;
|
||||
}
|
||||
mode = MSGMODE_FILE;
|
||||
fseek(fptr, 0, SEEK_END);
|
||||
msglen = ftell(fptr);
|
||||
if(msglen > 268435455){
|
||||
fclose(fptr);
|
||||
if(!quiet) fprintf(stderr, "Error: File \"%s\" is too large (>268,435,455 bytes).\n", filename);
|
||||
return 1;
|
||||
}else if(msglen == 0){
|
||||
fclose(fptr);
|
||||
if(!quiet) fprintf(stderr, "Error: File \"%s\" is empty.\n", filename);
|
||||
return 1;
|
||||
}else if(msglen < 0){
|
||||
fclose(fptr);
|
||||
if(!quiet) fprintf(stderr, "Error: Unable to determine size of file \"%s\".\n", filename);
|
||||
return 1;
|
||||
}
|
||||
fseek(fptr, 0, SEEK_SET);
|
||||
message = malloc(msglen);
|
||||
if(!message){
|
||||
fclose(fptr);
|
||||
if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
return 1;
|
||||
}
|
||||
pos = 0;
|
||||
while(pos < msglen){
|
||||
rlen = fread(&(message[pos]), sizeof(char), msglen-pos, fptr);
|
||||
pos += rlen;
|
||||
}
|
||||
fclose(fptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_usage(void)
|
||||
{
|
||||
int major, minor, revision;
|
||||
|
||||
mosquitto_lib_version(&major, &minor, &revision);
|
||||
printf("mosquitto_pub is a simple mqtt client that will publish a message on a single topic and exit.\n");
|
||||
printf("mosquitto_pub version %s running on libmosquitto %d.%d.%d.\n\n", VERSION, major, minor, revision);
|
||||
printf("Usage: mosquitto_pub [-h host] [-p port] [-q qos] [-r] {-f file | -l | -n | -m message} -t topic\n");
|
||||
printf(" [-A bind_address] [-S]\n");
|
||||
printf(" [-i id] [-I id_prefix]\n");
|
||||
printf(" [-d] [--quiet]\n");
|
||||
printf(" [-M max_inflight]\n");
|
||||
printf(" [-u username [-P password]]\n");
|
||||
printf(" [--will-topic [--will-payload payload] [--will-qos qos] [--will-retain]]\n");
|
||||
#ifdef WITH_TLS
|
||||
printf(" [{--cafile file | --capath dir} [--cert file] [--key file]\n");
|
||||
printf(" [--ciphers ciphers] [--insecure]]\n");
|
||||
#ifdef WITH_TLS_PSK
|
||||
printf(" [--psk hex-key --psk-identity identity [--ciphers ciphers]]\n");
|
||||
#endif
|
||||
#endif
|
||||
printf(" mosquitto_pub --help\n\n");
|
||||
printf(" -A : bind the outgoing socket to this host/ip address. Use to control which interface\n");
|
||||
printf(" the client communicates over.\n");
|
||||
printf(" -d : enable debug messages.\n");
|
||||
printf(" -f : send the contents of a file as the message.\n");
|
||||
printf(" -h : mqtt host to connect to. Defaults to localhost.\n");
|
||||
printf(" -i : id to use for this client. Defaults to mosquitto_pub_ appended with the process id.\n");
|
||||
printf(" -I : define the client id as id_prefix appended with the process id. Useful for when the\n");
|
||||
printf(" broker is using the clientid_prefixes option.\n");
|
||||
printf(" -l : read messages from stdin, sending a separate message for each line.\n");
|
||||
printf(" -m : message payload to send.\n");
|
||||
printf(" -M : the maximum inflight messages for QoS 1/2..\n");
|
||||
printf(" -n : send a null (zero length) message.\n");
|
||||
printf(" -p : network port to connect to. Defaults to 1883.\n");
|
||||
printf(" -q : quality of service level to use for all messages. Defaults to 0.\n");
|
||||
printf(" -r : message should be retained.\n");
|
||||
printf(" -s : read message from stdin, sending the entire input as a message.\n");
|
||||
printf(" -S : use SRV lookups to determine which host to connect to.\n");
|
||||
printf(" -t : mqtt topic to publish to.\n");
|
||||
printf(" -u : provide a username (requires MQTT 3.1 broker)\n");
|
||||
printf(" -P : provide a password (requires MQTT 3.1 broker)\n");
|
||||
printf(" --help : display this message.\n");
|
||||
printf(" --quiet : don't print error messages.\n");
|
||||
printf(" --will-payload : payload for the client Will, which is sent by the broker in case of\n");
|
||||
printf(" unexpected disconnection. If not given and will-topic is set, a zero\n");
|
||||
printf(" length message will be sent.\n");
|
||||
printf(" --will-qos : QoS level for the client Will.\n");
|
||||
printf(" --will-retain : if given, make the client Will retained.\n");
|
||||
printf(" --will-topic : the topic on which to publish the client Will.\n");
|
||||
#ifdef WITH_TLS
|
||||
printf(" --cafile : path to a file containing trusted CA certificates to enable encrypted\n");
|
||||
printf(" communication.\n");
|
||||
printf(" --capath : path to a directory containing trusted CA certificates to enable encrypted\n");
|
||||
printf(" communication.\n");
|
||||
printf(" --cert : client certificate for authentication, if required by server.\n");
|
||||
printf(" --key : client private key for authentication, if required by server.\n");
|
||||
printf(" --ciphers : openssl compatible list of TLS ciphers to support.\n");
|
||||
printf(" --tls-version : TLS protocol version, can be one of tlsv1.2 tlsv1.1 or tlsv1.\n");
|
||||
printf(" Defaults to tlsv1.2 if available.\n");
|
||||
printf(" --insecure : do not check that the server certificate hostname matches the remote\n");
|
||||
printf(" hostname. Using this option means that you cannot be sure that the\n");
|
||||
printf(" remote host is the server you wish to connect to and so is insecure.\n");
|
||||
printf(" Do not use this option in a production environment.\n");
|
||||
#ifdef WITH_TLS_PSK
|
||||
printf(" --psk : pre-shared-key in hexadecimal (no leading 0x) to enable TLS-PSK mode.\n");
|
||||
printf(" --psk-identity : client identity string for TLS-PSK mode.\n");
|
||||
#endif
|
||||
#endif
|
||||
printf("\nSee http://mosquitto.org/ for more information.\n\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *id = NULL;
|
||||
char *id_prefix = NULL;
|
||||
int i;
|
||||
char *host = "localhost";
|
||||
int port = 1883;
|
||||
char *bind_address = NULL;
|
||||
int keepalive = 60;
|
||||
char buf[1024];
|
||||
bool debug = false;
|
||||
struct mosquitto *mosq = NULL;
|
||||
int rc;
|
||||
int rc2;
|
||||
char hostname[256];
|
||||
char err[1024];
|
||||
int len;
|
||||
unsigned int max_inflight = 20;
|
||||
|
||||
char *will_payload = NULL;
|
||||
long will_payloadlen = 0;
|
||||
int will_qos = 0;
|
||||
bool will_retain = false;
|
||||
char *will_topic = NULL;
|
||||
|
||||
bool insecure = false;
|
||||
char *cafile = NULL;
|
||||
char *capath = NULL;
|
||||
char *certfile = NULL;
|
||||
char *keyfile = NULL;
|
||||
char *tls_version = NULL;
|
||||
|
||||
char *psk = NULL;
|
||||
char *psk_identity = NULL;
|
||||
|
||||
char *ciphers = NULL;
|
||||
|
||||
bool use_srv = false;
|
||||
|
||||
for(i=1; i<argc; i++){
|
||||
if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -p argument given but no port specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
port = atoi(argv[i+1]);
|
||||
if(port<1 || port>65535){
|
||||
fprintf(stderr, "Error: Invalid port given: %d\n", port);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-A")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -A argument given but no address specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
bind_address = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--cafile")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --cafile argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
cafile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--capath")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --capath argument given but no directory specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
capath = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--cert")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --cert argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
certfile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--ciphers")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --ciphers argument given but no ciphers specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ciphers = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")){
|
||||
debug = true;
|
||||
}else if(!strcmp(argv[i], "-f") || !strcmp(argv[i], "--file")){
|
||||
if(mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else if(i==argc-1){
|
||||
fprintf(stderr, "Error: -f argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
if(load_file(argv[i+1])) return 1;
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--help")){
|
||||
print_usage();
|
||||
return 0;
|
||||
}else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--host")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -h argument given but no host specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
host = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--insecure")){
|
||||
insecure = true;
|
||||
}else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--id")){
|
||||
if(id_prefix){
|
||||
fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -i argument given but no id specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
id = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-I") || !strcmp(argv[i], "--id-prefix")){
|
||||
if(id){
|
||||
fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -I argument given but no id prefix specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
id_prefix = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--key")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --key argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
keyfile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--stdin-line")){
|
||||
if(mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
mode = MSGMODE_STDIN_LINE;
|
||||
}
|
||||
}else if(!strcmp(argv[i], "-m") || !strcmp(argv[i], "--message")){
|
||||
if(mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else if(i==argc-1){
|
||||
fprintf(stderr, "Error: -m argument given but no message specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
message = argv[i+1];
|
||||
msglen = strlen(message);
|
||||
mode = MSGMODE_CMD;
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-M")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -M argument given but max_inflight not specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
max_inflight = atoi(argv[i+1]);
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-n") || !strcmp(argv[i], "--null-message")){
|
||||
if(mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
mode = MSGMODE_NULL;
|
||||
}
|
||||
}else if(!strcmp(argv[i], "--psk")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --psk argument given but no key specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
psk = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--psk-identity")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --psk-identity argument given but no identity specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
psk_identity = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-q") || !strcmp(argv[i], "--qos")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -q argument given but no QoS specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
qos = atoi(argv[i+1]);
|
||||
if(qos<0 || qos>2){
|
||||
fprintf(stderr, "Error: Invalid QoS given: %d\n", qos);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--quiet")){
|
||||
quiet = true;
|
||||
}else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--retain")){
|
||||
retain = 1;
|
||||
}else if(!strcmp(argv[i], "-s") || !strcmp(argv[i], "--stdin-file")){
|
||||
if(mode != MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
if(load_stdin()) return 1;
|
||||
}
|
||||
}else if(!strcmp(argv[i], "-S")){
|
||||
use_srv = true;
|
||||
}else if(!strcmp(argv[i], "-t") || !strcmp(argv[i], "--topic")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -t argument given but no topic specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
topic = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--tls-version")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --tls-version argument given but no version specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
tls_version = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-u") || !strcmp(argv[i], "--username")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -u argument given but no username specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
username = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-P") || !strcmp(argv[i], "--pw")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -P argument given but no password specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
password = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-payload")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-payload argument given but no will payload specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_payload = argv[i+1];
|
||||
will_payloadlen = strlen(will_payload);
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-qos")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-qos argument given but no will QoS specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_qos = atoi(argv[i+1]);
|
||||
if(will_qos < 0 || will_qos > 2){
|
||||
fprintf(stderr, "Error: Invalid will QoS %d.\n\n", will_qos);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-retain")){
|
||||
will_retain = true;
|
||||
}else if(!strcmp(argv[i], "--will-topic")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-topic argument given but no will topic specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_topic = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else{
|
||||
fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!topic || mode == MSGMODE_NONE){
|
||||
fprintf(stderr, "Error: Both topic and message must be supplied.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(will_payload && !will_topic){
|
||||
fprintf(stderr, "Error: Will payload given, but no will topic given.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(will_retain && !will_topic){
|
||||
fprintf(stderr, "Error: Will retain given, but no will topic given.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(password && !username){
|
||||
if(!quiet) fprintf(stderr, "Warning: Not using password since username not set.\n");
|
||||
}
|
||||
if((certfile && !keyfile) || (keyfile && !certfile)){
|
||||
fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if((cafile || capath) && psk){
|
||||
if(!quiet) fprintf(stderr, "Error: Only one of --psk or --cafile/--capath may be used at once.\n");
|
||||
return 1;
|
||||
}
|
||||
if(psk && !psk_identity){
|
||||
if(!quiet) fprintf(stderr, "Error: --psk-identity required if --psk used.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
mosquitto_lib_init();
|
||||
|
||||
if(id_prefix){
|
||||
id = malloc(strlen(id_prefix)+10);
|
||||
if(!id){
|
||||
if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
snprintf(id, strlen(id_prefix)+10, "%s%d", id_prefix, getpid());
|
||||
}else if(!id){
|
||||
hostname[0] = '\0';
|
||||
gethostname(hostname, 256);
|
||||
hostname[255] = '\0';
|
||||
len = strlen("mosqpub/-") + 6 + strlen(hostname);
|
||||
id = malloc(len);
|
||||
if(!id){
|
||||
if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
snprintf(id, len, "mosqpub/%d-%s", getpid(), hostname);
|
||||
if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH){
|
||||
/* Enforce maximum client id length of 23 characters */
|
||||
id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
mosq = mosquitto_new(id, true, NULL);
|
||||
if(!mosq){
|
||||
switch(errno){
|
||||
case ENOMEM:
|
||||
if(!quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
break;
|
||||
case EINVAL:
|
||||
if(!quiet) fprintf(stderr, "Error: Invalid id.\n");
|
||||
break;
|
||||
}
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(debug){
|
||||
mosquitto_log_callback_set(mosq, my_log_callback);
|
||||
}
|
||||
if(will_topic && mosquitto_will_set(mosq, will_topic, will_payloadlen, will_payload, will_qos, will_retain)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting will.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(username && mosquitto_username_pw_set(mosq, username, password)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting username and password.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if((cafile || capath) && mosquitto_tls_set(mosq, cafile, capath, certfile, keyfile, NULL)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(insecure && mosquitto_tls_insecure_set(mosq, true)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting TLS insecure option.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(psk && mosquitto_tls_psk_set(mosq, psk, psk_identity, NULL)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting TLS-PSK options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(tls_version && mosquitto_tls_opts_set(mosq, 1, tls_version, ciphers)){
|
||||
if(!quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
mosquitto_max_inflight_messages_set(mosq, max_inflight);
|
||||
mosquitto_connect_callback_set(mosq, my_connect_callback);
|
||||
mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
|
||||
mosquitto_publish_callback_set(mosq, my_publish_callback);
|
||||
|
||||
if(use_srv){
|
||||
rc = mosquitto_connect_srv(mosq, host, keepalive, bind_address);
|
||||
}else{
|
||||
rc = mosquitto_connect_bind(mosq, host, port, keepalive, bind_address);
|
||||
}
|
||||
if(rc){
|
||||
if(!quiet){
|
||||
if(rc == MOSQ_ERR_ERRNO){
|
||||
#ifndef WIN32
|
||||
strerror_r(errno, err, 1024);
|
||||
#else
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errno, 0, (LPTSTR)&err, 1024, NULL);
|
||||
#endif
|
||||
fprintf(stderr, "Error: %s\n", err);
|
||||
}else{
|
||||
fprintf(stderr, "Unable to connect (%d).\n", rc);
|
||||
}
|
||||
}
|
||||
mosquitto_lib_cleanup();
|
||||
return rc;
|
||||
}
|
||||
|
||||
if(mode == MSGMODE_STDIN_LINE){
|
||||
mosquitto_loop_start(mosq);
|
||||
}
|
||||
|
||||
do{
|
||||
if(mode == MSGMODE_STDIN_LINE){
|
||||
if(status == STATUS_CONNACK_RECVD){
|
||||
if(fgets(buf, 1024, stdin)){
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
rc2 = mosquitto_publish(mosq, &mid_sent, topic, strlen(buf), buf, qos, retain);
|
||||
if(rc2){
|
||||
if(!quiet) fprintf(stderr, "Error: Publish returned %d, disconnecting.\n", rc2);
|
||||
mosquitto_disconnect(mosq);
|
||||
}
|
||||
}else if(feof(stdin)){
|
||||
last_mid = mid_sent;
|
||||
status = STATUS_WAITING;
|
||||
}
|
||||
}else if(status == STATUS_WAITING){
|
||||
if(last_mid_sent == last_mid && disconnect_sent == false){
|
||||
mosquitto_disconnect(mosq);
|
||||
disconnect_sent = true;
|
||||
}
|
||||
#ifdef WIN32
|
||||
Sleep(100);
|
||||
#else
|
||||
usleep(100000);
|
||||
#endif
|
||||
}
|
||||
rc = MOSQ_ERR_SUCCESS;
|
||||
}else{
|
||||
rc = mosquitto_loop(mosq, -1, 1);
|
||||
}
|
||||
}while(rc == MOSQ_ERR_SUCCESS && connected);
|
||||
|
||||
if(mode == MSGMODE_STDIN_LINE){
|
||||
mosquitto_loop_stop(mosq, false);
|
||||
}
|
||||
|
||||
if(message && mode == MSGMODE_FILE){
|
||||
free(message);
|
||||
}
|
||||
mosquitto_destroy(mosq);
|
||||
mosquitto_lib_cleanup();
|
||||
|
||||
if(rc){
|
||||
fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc));
|
||||
}
|
||||
return rc;
|
||||
}
|
650
client/sub_client.c
Normal file
650
client/sub_client.c
Normal file
@ -0,0 +1,650 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <process.h>
|
||||
#include <winsock2.h>
|
||||
#define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
#include <mosquitto.h>
|
||||
|
||||
/* This struct is used to pass data to callbacks.
|
||||
* An instance "ud" is created in main() and populated, then passed to
|
||||
* mosquitto_new(). */
|
||||
struct userdata {
|
||||
char **topics;
|
||||
int topic_count;
|
||||
int topic_qos;
|
||||
char **filter_outs;
|
||||
int filter_out_count;
|
||||
char *username;
|
||||
char *password;
|
||||
int verbose;
|
||||
bool quiet;
|
||||
bool no_retain;
|
||||
bool eol;
|
||||
};
|
||||
|
||||
void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
|
||||
{
|
||||
struct userdata *ud;
|
||||
int i;
|
||||
bool res;
|
||||
|
||||
assert(obj);
|
||||
ud = (struct userdata *)obj;
|
||||
|
||||
if(message->retain && ud->no_retain) return;
|
||||
if(ud->filter_outs){
|
||||
for(i=0; i<ud->filter_out_count; i++){
|
||||
mosquitto_topic_matches_sub(ud->filter_outs[i], message->topic, &res);
|
||||
if(res) return;
|
||||
}
|
||||
}
|
||||
|
||||
if(ud->verbose){
|
||||
if(message->payloadlen){
|
||||
printf("%s ", message->topic);
|
||||
fwrite(message->payload, 1, message->payloadlen, stdout);
|
||||
if(ud->eol){
|
||||
printf("\n");
|
||||
}
|
||||
}else{
|
||||
if(ud->eol){
|
||||
printf("%s (null)\n", message->topic);
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
}else{
|
||||
if(message->payloadlen){
|
||||
fwrite(message->payload, 1, message->payloadlen, stdout);
|
||||
if(ud->eol){
|
||||
printf("\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void my_connect_callback(struct mosquitto *mosq, void *obj, int result)
|
||||
{
|
||||
int i;
|
||||
struct userdata *ud;
|
||||
|
||||
assert(obj);
|
||||
ud = (struct userdata *)obj;
|
||||
|
||||
if(!result){
|
||||
for(i=0; i<ud->topic_count; i++){
|
||||
mosquitto_subscribe(mosq, NULL, ud->topics[i], ud->topic_qos);
|
||||
}
|
||||
}else{
|
||||
if(result && !ud->quiet){
|
||||
fprintf(stderr, "%s\n", mosquitto_connack_string(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void my_subscribe_callback(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
|
||||
{
|
||||
int i;
|
||||
struct userdata *ud;
|
||||
|
||||
assert(obj);
|
||||
ud = (struct userdata *)obj;
|
||||
|
||||
if(!ud->quiet) printf("Subscribed (mid: %d): %d", mid, granted_qos[0]);
|
||||
for(i=1; i<qos_count; i++){
|
||||
if(!ud->quiet) printf(", %d", granted_qos[i]);
|
||||
}
|
||||
if(!ud->quiet) printf("\n");
|
||||
}
|
||||
|
||||
void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str)
|
||||
{
|
||||
printf("%s\n", str);
|
||||
}
|
||||
|
||||
void print_usage(void)
|
||||
{
|
||||
int major, minor, revision;
|
||||
|
||||
mosquitto_lib_version(&major, &minor, &revision);
|
||||
printf("mosquitto_sub is a simple mqtt client that will subscribe to a single topic and print all messages it receives.\n");
|
||||
printf("mosquitto_sub version %s running on libmosquitto %d.%d.%d.\n\n", VERSION, major, minor, revision);
|
||||
printf("Usage: mosquitto_sub [-c] [-h host] [-k keepalive] [-p port] [-q qos] [-R] -t topic ...\n");
|
||||
printf(" [-T filter_out]\n");
|
||||
printf(" [-A bind_address] [-S]\n");
|
||||
printf(" [-i id] [-I id_prefix]\n");
|
||||
printf(" [-d] [-N] [--quiet] [-v]\n");
|
||||
printf(" [-u username [-P password]]\n");
|
||||
printf(" [--will-topic [--will-payload payload] [--will-qos qos] [--will-retain]]\n");
|
||||
#ifdef WITH_TLS
|
||||
printf(" [{--cafile file | --capath dir} [--cert file] [--key file]\n");
|
||||
printf(" [--ciphers ciphers] [--insecure]]\n");
|
||||
#ifdef WITH_TLS_PSK
|
||||
printf(" [--psk hex-key --psk-identity identity [--ciphers ciphers]]\n");
|
||||
#endif
|
||||
#endif
|
||||
printf(" mosquitto_sub --help\n\n");
|
||||
printf(" -A : bind the outgoing socket to this host/ip address. Use to control which interface\n");
|
||||
printf(" the client communicates over.\n");
|
||||
printf(" -c : disable 'clean session' (store subscription and pending messages when client disconnects).\n");
|
||||
printf(" -d : enable debug messages.\n");
|
||||
printf(" -h : mqtt host to connect to. Defaults to localhost.\n");
|
||||
printf(" -i : id to use for this client. Defaults to mosquitto_sub_ appended with the process id.\n");
|
||||
printf(" -I : define the client id as id_prefix appended with the process id. Useful for when the\n");
|
||||
printf(" broker is using the clientid_prefixes option.\n");
|
||||
printf(" -k : keep alive in seconds for this client. Defaults to 60.\n");
|
||||
printf(" -N : do not add an end of line character when printing the payload.\n");
|
||||
printf(" -p : network port to connect to. Defaults to 1883.\n");
|
||||
printf(" -q : quality of service level to use for the subscription. Defaults to 0.\n");
|
||||
printf(" -R : do not print stale messages (those with retain set).\n");
|
||||
printf(" -S : use SRV lookups to determine which host to connect to.\n");
|
||||
printf(" -t : mqtt topic to subscribe to. May be repeated multiple times.\n");
|
||||
printf(" -u : provide a username (requires MQTT 3.1 broker)\n");
|
||||
printf(" -v : print published messages verbosely.\n");
|
||||
printf(" -P : provide a password (requires MQTT 3.1 broker)\n");
|
||||
printf(" --help : display this message.\n");
|
||||
printf(" --quiet : don't print error messages.\n");
|
||||
printf(" --will-payload : payload for the client Will, which is sent by the broker in case of\n");
|
||||
printf(" unexpected disconnection. If not given and will-topic is set, a zero\n");
|
||||
printf(" length message will be sent.\n");
|
||||
printf(" --will-qos : QoS level for the client Will.\n");
|
||||
printf(" --will-retain : if given, make the client Will retained.\n");
|
||||
printf(" --will-topic : the topic on which to publish the client Will.\n");
|
||||
#ifdef WITH_TLS
|
||||
printf(" --cafile : path to a file containing trusted CA certificates to enable encrypted\n");
|
||||
printf(" certificate based communication.\n");
|
||||
printf(" --capath : path to a directory containing trusted CA certificates to enable encrypted\n");
|
||||
printf(" communication.\n");
|
||||
printf(" --cert : client certificate for authentication, if required by server.\n");
|
||||
printf(" --key : client private key for authentication, if required by server.\n");
|
||||
printf(" --ciphers : openssl compatible list of TLS ciphers to support.\n");
|
||||
printf(" --tls-version : TLS protocol version, can be one of tlsv1.2 tlsv1.1 or tlsv1.\n");
|
||||
printf(" Defaults to tlsv1.2 if available.\n");
|
||||
printf(" --insecure : do not check that the server certificate hostname matches the remote\n");
|
||||
printf(" hostname. Using this option means that you cannot be sure that the\n");
|
||||
printf(" remote host is the server you wish to connect to and so is insecure.\n");
|
||||
printf(" Do not use this option in a production environment.\n");
|
||||
#ifdef WITH_TLS_PSK
|
||||
printf(" --psk : pre-shared-key in hexadecimal (no leading 0x) to enable TLS-PSK mode.\n");
|
||||
printf(" --psk-identity : client identity string for TLS-PSK mode.\n");
|
||||
#endif
|
||||
#endif
|
||||
printf("\nSee http://mosquitto.org/ for more information.\n\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *id = NULL;
|
||||
char *id_prefix = NULL;
|
||||
int i;
|
||||
char *host = "localhost";
|
||||
int port = 1883;
|
||||
char *bind_address = NULL;
|
||||
int keepalive = 60;
|
||||
bool clean_session = true;
|
||||
bool debug = false;
|
||||
struct mosquitto *mosq = NULL;
|
||||
int rc;
|
||||
char hostname[256];
|
||||
char err[1024];
|
||||
struct userdata ud;
|
||||
int len;
|
||||
|
||||
char *will_payload = NULL;
|
||||
long will_payloadlen = 0;
|
||||
int will_qos = 0;
|
||||
bool will_retain = false;
|
||||
char *will_topic = NULL;
|
||||
|
||||
bool insecure = false;
|
||||
char *cafile = NULL;
|
||||
char *capath = NULL;
|
||||
char *certfile = NULL;
|
||||
char *keyfile = NULL;
|
||||
char *tls_version = NULL;
|
||||
|
||||
char *psk = NULL;
|
||||
char *psk_identity = NULL;
|
||||
|
||||
char *ciphers = NULL;
|
||||
|
||||
bool use_srv = false;
|
||||
|
||||
memset(&ud, 0, sizeof(struct userdata));
|
||||
ud.eol = true;
|
||||
|
||||
for(i=1; i<argc; i++){
|
||||
if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -p argument given but no port specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
port = atoi(argv[i+1]);
|
||||
if(port<1 || port>65535){
|
||||
fprintf(stderr, "Error: Invalid port given: %d\n", port);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-A")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -A argument given but no address specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
bind_address = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--disable-clean-session")){
|
||||
clean_session = false;
|
||||
}else if(!strcmp(argv[i], "--cafile")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --cafile argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
cafile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--capath")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --capath argument given but no directory specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
capath = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--cert")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --cert argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
certfile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--ciphers")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --ciphers argument given but no ciphers specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ciphers = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")){
|
||||
debug = true;
|
||||
}else if(!strcmp(argv[i], "--help")){
|
||||
print_usage();
|
||||
return 0;
|
||||
}else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--host")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -h argument given but no host specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
host = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--insecure")){
|
||||
insecure = true;
|
||||
}else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--id")){
|
||||
if(id_prefix){
|
||||
fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -i argument given but no id specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
id = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-I") || !strcmp(argv[i], "--id-prefix")){
|
||||
if(id){
|
||||
fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -I argument given but no id prefix specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
id_prefix = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-k") || !strcmp(argv[i], "--keepalive")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -k argument given but no keepalive specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
keepalive = atoi(argv[i+1]);
|
||||
if(keepalive>65535){
|
||||
fprintf(stderr, "Error: Invalid keepalive given: %d\n", keepalive);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--key")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --key argument given but no file specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
keyfile = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-N")){
|
||||
ud.eol = false;
|
||||
}else if(!strcmp(argv[i], "--psk")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --psk argument given but no key specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
psk = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--psk-identity")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --psk-identity argument given but no identity specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
psk_identity = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-q") || !strcmp(argv[i], "--qos")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -q argument given but no QoS specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ud.topic_qos = atoi(argv[i+1]);
|
||||
if(ud.topic_qos<0 || ud.topic_qos>2){
|
||||
fprintf(stderr, "Error: Invalid QoS given: %d\n", ud.topic_qos);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--quiet")){
|
||||
ud.quiet = true;
|
||||
}else if(!strcmp(argv[i], "-R")){
|
||||
ud.no_retain = true;
|
||||
}else if(!strcmp(argv[i], "-S")){
|
||||
use_srv = true;
|
||||
}else if(!strcmp(argv[i], "-t") || !strcmp(argv[i], "--topic")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -t argument given but no topic specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ud.topic_count++;
|
||||
ud.topics = realloc(ud.topics, ud.topic_count*sizeof(char *));
|
||||
ud.topics[ud.topic_count-1] = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-T") || !strcmp(argv[i], "--filter-out")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -T argument given but no topic filter specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ud.filter_out_count++;
|
||||
ud.filter_outs = realloc(ud.filter_outs, ud.filter_out_count*sizeof(char *));
|
||||
ud.filter_outs[ud.filter_out_count-1] = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--tls-version")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --tls-version argument given but no version specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
tls_version = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-u") || !strcmp(argv[i], "--username")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -u argument given but no username specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ud.username = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")){
|
||||
ud.verbose = 1;
|
||||
}else if(!strcmp(argv[i], "-P") || !strcmp(argv[i], "--pw")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: -P argument given but no password specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
ud.password = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-payload")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-payload argument given but no will payload specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_payload = argv[i+1];
|
||||
will_payloadlen = strlen(will_payload);
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-qos")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-qos argument given but no will QoS specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_qos = atoi(argv[i+1]);
|
||||
if(will_qos < 0 || will_qos > 2){
|
||||
fprintf(stderr, "Error: Invalid will QoS %d.\n\n", will_qos);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}else if(!strcmp(argv[i], "--will-retain")){
|
||||
will_retain = true;
|
||||
}else if(!strcmp(argv[i], "--will-topic")){
|
||||
if(i==argc-1){
|
||||
fprintf(stderr, "Error: --will-topic argument given but no will topic specified.\n\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}else{
|
||||
will_topic = argv[i+1];
|
||||
}
|
||||
i++;
|
||||
}else{
|
||||
fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(clean_session == false && (id_prefix || !id)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: You must provide a client id if you are using the -c option.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(ud.topic_count == 0){
|
||||
fprintf(stderr, "Error: You must specify a topic to subscribe to.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(will_payload && !will_topic){
|
||||
fprintf(stderr, "Error: Will payload given, but no will topic given.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(will_retain && !will_topic){
|
||||
fprintf(stderr, "Error: Will retain given, but no will topic given.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if(ud.password && !ud.username){
|
||||
if(!ud.quiet) fprintf(stderr, "Warning: Not using password since username not set.\n");
|
||||
}
|
||||
if((certfile && !keyfile) || (keyfile && !certfile)){
|
||||
fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is.\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if((cafile || capath) && psk){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Only one of --psk or --cafile/--capath may be used at once.\n");
|
||||
return 1;
|
||||
}
|
||||
if(psk && !psk_identity){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: --psk-identity required if --psk used.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
mosquitto_lib_init();
|
||||
|
||||
if(id_prefix){
|
||||
id = malloc(strlen(id_prefix)+10);
|
||||
if(!id){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
snprintf(id, strlen(id_prefix)+10, "%s%d", id_prefix, getpid());
|
||||
}else if(!id){
|
||||
hostname[0] = '\0';
|
||||
gethostname(hostname, 256);
|
||||
hostname[255] = '\0';
|
||||
len = strlen("mosqsub/-") + 6 + strlen(hostname);
|
||||
id = malloc(len);
|
||||
if(!id){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
snprintf(id, len, "mosqsub/%d-%s", getpid(), hostname);
|
||||
if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH){
|
||||
/* Enforce maximum client id length of 23 characters */
|
||||
id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
mosq = mosquitto_new(id, clean_session, &ud);
|
||||
if(!mosq){
|
||||
switch(errno){
|
||||
case ENOMEM:
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Out of memory.\n");
|
||||
break;
|
||||
case EINVAL:
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Invalid id and/or clean_session.\n");
|
||||
break;
|
||||
}
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(debug){
|
||||
mosquitto_log_callback_set(mosq, my_log_callback);
|
||||
}
|
||||
if(will_topic && mosquitto_will_set(mosq, will_topic, will_payloadlen, will_payload, will_qos, will_retain)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting will.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(ud.username && mosquitto_username_pw_set(mosq, ud.username, ud.password)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting username and password.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if((cafile || capath) && mosquitto_tls_set(mosq, cafile, capath, certfile, keyfile, NULL)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(insecure && mosquitto_tls_insecure_set(mosq, true)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting TLS insecure option.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(psk && mosquitto_tls_psk_set(mosq, psk, psk_identity, NULL)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting TLS-PSK options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
if(tls_version && mosquitto_tls_opts_set(mosq, 1, tls_version, ciphers)){
|
||||
if(!ud.quiet) fprintf(stderr, "Error: Problem setting TLS options.\n");
|
||||
mosquitto_lib_cleanup();
|
||||
return 1;
|
||||
}
|
||||
mosquitto_connect_callback_set(mosq, my_connect_callback);
|
||||
mosquitto_message_callback_set(mosq, my_message_callback);
|
||||
if(debug){
|
||||
mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);
|
||||
}
|
||||
|
||||
if(use_srv){
|
||||
rc = mosquitto_connect_srv(mosq, host, keepalive, bind_address);
|
||||
}else{
|
||||
rc = mosquitto_connect_bind(mosq, host, port, keepalive, bind_address);
|
||||
}
|
||||
if(rc){
|
||||
if(!ud.quiet){
|
||||
if(rc == MOSQ_ERR_ERRNO){
|
||||
#ifndef WIN32
|
||||
strerror_r(errno, err, 1024);
|
||||
#else
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errno, 0, (LPTSTR)&err, 1024, NULL);
|
||||
#endif
|
||||
fprintf(stderr, "Error: %s\n", err);
|
||||
}else{
|
||||
fprintf(stderr, "Unable to connect (%d).\n", rc);
|
||||
}
|
||||
}
|
||||
mosquitto_lib_cleanup();
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = mosquitto_loop_forever(mosq, -1, 1);
|
||||
|
||||
mosquitto_destroy(mosq);
|
||||
mosquitto_lib_cleanup();
|
||||
|
||||
if(rc){
|
||||
fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
17
compiling.txt
Normal file
17
compiling.txt
Normal file
@ -0,0 +1,17 @@
|
||||
The following packages are required for mosquitto:
|
||||
|
||||
* tcp-wrappers (optional, package name libwrap0-dev)
|
||||
* openssl (version 1.0.0 or greater if TLS-PSK support is needed)
|
||||
* On Windows, the Redhat pthreads library is required if threading support is
|
||||
to be included.
|
||||
|
||||
To compile, run "make", but also see the file config.mk for more details on the
|
||||
various options that can be compiled in.
|
||||
|
||||
Where possible use the Makefiles to compile. This is particularly relevant for
|
||||
the client libraries as symbol information will be included. Use cmake to
|
||||
compile on Windows or Mac.
|
||||
|
||||
If you have any questions, problems or suggestions (particularly related to
|
||||
installing on a more unusual device like a plug-computer) then please get in
|
||||
touch using the details in readme.txt.
|
19
config.h
Normal file
19
config.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* ============================================================
|
||||
* Control compile time options.
|
||||
* ============================================================
|
||||
*
|
||||
* Compile time options have moved to config.mk.
|
||||
*/
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* Compatibility defines
|
||||
*
|
||||
* Generally for Windows native support.
|
||||
* ============================================================ */
|
||||
#ifdef WIN32
|
||||
#define snprintf sprintf_s
|
||||
#define strcasecmp strcmpi
|
||||
#define strtok_r strtok_s
|
||||
#define strerror_r(e, b, l) strerror_s(b, l, e)
|
||||
#endif
|
218
config.mk
Normal file
218
config.mk
Normal file
@ -0,0 +1,218 @@
|
||||
# =============================================================================
|
||||
# User configuration section.
|
||||
#
|
||||
# Largely, these are options that are designed to make mosquitto run more
|
||||
# easily in restrictive environments by removing features.
|
||||
#
|
||||
# Modify the variable below to enable/disable features.
|
||||
#
|
||||
# Can also be overriden at the command line, e.g.:
|
||||
#
|
||||
# make WITH_TLS=no
|
||||
# =============================================================================
|
||||
|
||||
# Uncomment to compile the broker with tcpd/libwrap support.
|
||||
#WITH_WRAP:=yes
|
||||
|
||||
# Comment out to disable SSL/TLS support in the broker and client.
|
||||
# Disabling this will also mean that passwords must be stored in plain text. It
|
||||
# is strongly recommended that you only disable WITH_TLS if you are not using
|
||||
# password authentication at all.
|
||||
WITH_TLS:=yes
|
||||
|
||||
# Comment out to disable TLS/PSK support in the broker and client. Requires
|
||||
# WITH_TLS=yes.
|
||||
# This must be disabled if using openssl < 1.0.
|
||||
WITH_TLS_PSK:=yes
|
||||
|
||||
# Comment out to disable client client threading support.
|
||||
WITH_THREADING:=yes
|
||||
|
||||
# Uncomment to compile the broker with strict protocol support. This means that
|
||||
# both the client library and the broker will be very strict about protocol
|
||||
# compliance on incoming data. Neither of them will return an error on
|
||||
# incorrect "remaining length" values if this is commented out. The old
|
||||
# behaviour (prior to 0.12) is equivalent to compiling with
|
||||
# WITH_STRICT_PROTOCOL defined and means that clients will be immediately
|
||||
# disconnected from the broker on non-compliance.
|
||||
#WITH_STRICT_PROTOCOL:=yes
|
||||
|
||||
# Comment out to remove bridge support from the broker. This allow the broker
|
||||
# to connect to other brokers and subscribe/publish to topics. You probably
|
||||
# want to leave this included unless you want to save a very small amount of
|
||||
# memory size and CPU time.
|
||||
WITH_BRIDGE:=yes
|
||||
|
||||
# Comment out to remove persistent database support from the broker. This
|
||||
# allows the broker to store retained messages and durable subscriptions to a
|
||||
# file periodically and on shutdown. This is usually desirable (and is
|
||||
# suggested by the MQTT spec), but it can be disabled if required.
|
||||
WITH_PERSISTENCE:=yes
|
||||
|
||||
# Comment out to remove memory tracking support from the broker. If disabled,
|
||||
# mosquitto won't track heap memory usage nor export '$SYS/broker/heap/current
|
||||
# size', but will use slightly less memory and CPU time.
|
||||
WITH_MEMORY_TRACKING:=yes
|
||||
|
||||
# Compile with database upgrading support? If disabled, mosquitto won't
|
||||
# automatically upgrade old database versions.
|
||||
# Not currently supported.
|
||||
#WITH_DB_UPGRADE:=yes
|
||||
|
||||
# Comment out to remove publishing of the $SYS topic hierarchy containing
|
||||
# information about the broker state.
|
||||
WITH_SYS_TREE:=yes
|
||||
|
||||
# Build with Python module. Comment out if Python is not installed, or required
|
||||
# Python modules are not available.
|
||||
WITH_PYTHON:=yes
|
||||
|
||||
# Build with SRV lookup support.
|
||||
WITH_SRV:=yes
|
||||
|
||||
# =============================================================================
|
||||
# End of user configuration
|
||||
# =============================================================================
|
||||
|
||||
|
||||
# Also bump lib/mosquitto.h, lib/python/setup.py, CMakeLists.txt,
|
||||
# installer/mosquitto.nsi, installer/mosquitto-cygwin.nsi
|
||||
VERSION=1.3.1
|
||||
TIMESTAMP:=$(shell date "+%F %T%z")
|
||||
|
||||
# Client library SO version. Bump if incompatible API/ABI changes are made.
|
||||
SOVERSION=1
|
||||
|
||||
# Man page generation requires xsltproc and docbook-xsl
|
||||
XSLTPROC=xsltproc
|
||||
# For html generation
|
||||
DB_HTML_XSL=man/html.xsl
|
||||
|
||||
#MANCOUNTRIES=en_GB
|
||||
|
||||
UNAME:=$(shell uname -s)
|
||||
ifeq ($(UNAME),SunOS)
|
||||
ifeq ($(CC),cc)
|
||||
CFLAGS?=-O
|
||||
else
|
||||
CFLAGS?=-Wall -ggdb -O2
|
||||
endif
|
||||
else
|
||||
CFLAGS?=-Wall -ggdb -O2
|
||||
endif
|
||||
|
||||
LIB_CFLAGS:=${CFLAGS} ${CPPFLAGS} -I. -I.. -I../lib
|
||||
LIB_CXXFLAGS:=$(LIB_CFLAGS) ${CPPFLAGS}
|
||||
LIB_LDFLAGS:=${LDFLAGS}
|
||||
|
||||
BROKER_CFLAGS:=${LIB_CFLAGS} ${CPPFLAGS} -DVERSION="\"${VERSION}\"" -DTIMESTAMP="\"${TIMESTAMP}\"" -DWITH_BROKER
|
||||
CLIENT_CFLAGS:=${CFLAGS} ${CPPFLAGS} -I../lib -DVERSION="\"${VERSION}\""
|
||||
|
||||
ifeq ($(UNAME),FreeBSD)
|
||||
BROKER_LIBS:=-lm
|
||||
else
|
||||
BROKER_LIBS:=-ldl -lm
|
||||
endif
|
||||
LIB_LIBS:=
|
||||
PASSWD_LIBS:=
|
||||
|
||||
ifeq ($(UNAME),Linux)
|
||||
BROKER_LIBS:=$(BROKER_LIBS) -lrt
|
||||
LIB_LIBS:=$(LIB_LIBS) -lrt
|
||||
endif
|
||||
|
||||
CLIENT_LDFLAGS:=$(LDFLAGS) -L../lib ../lib/libmosquitto.so.${SOVERSION}
|
||||
|
||||
ifeq ($(UNAME),SunOS)
|
||||
ifeq ($(CC),cc)
|
||||
LIB_CFLAGS:=$(LIB_CFLAGS) -xc99 -KPIC
|
||||
else
|
||||
LIB_CFLAGS:=$(LIB_CFLAGS) -fPIC
|
||||
endif
|
||||
|
||||
ifeq ($(CXX),CC)
|
||||
LIB_CXXFLAGS:=$(LIB_CXXFLAGS) -KPIC
|
||||
else
|
||||
LIB_CXXFLAGS:=$(LIB_CXXFLAGS) -fPIC
|
||||
endif
|
||||
else
|
||||
LIB_CFLAGS:=$(LIB_CFLAGS) -fPIC
|
||||
LIB_CXXFLAGS:=$(LIB_CXXFLAGS) -fPIC
|
||||
endif
|
||||
|
||||
ifneq ($(UNAME),SunOS)
|
||||
LIB_LDFLAGS:=$(LIB_LDFLAGS) -Wl,--version-script=linker.version -Wl,-soname,libmosquitto.so.$(SOVERSION)
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME),QNX)
|
||||
BROKER_LIBS:=$(BROKER_LIBS) -lsocket
|
||||
LIB_LIBS:=$(LIB_LIBS) -lsocket
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_WRAP),yes)
|
||||
BROKER_LIBS:=$(BROKER_LIBS) -lwrap
|
||||
BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_WRAP
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_TLS),yes)
|
||||
BROKER_LIBS:=$(BROKER_LIBS) -lssl -lcrypto
|
||||
LIB_LIBS:=$(LIB_LIBS) -lssl -lcrypto
|
||||
BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_TLS
|
||||
LIB_CFLAGS:=$(LIB_CFLAGS) -DWITH_TLS
|
||||
PASSWD_LIBS:=-lcrypto
|
||||
CLIENT_CFLAGS:=$(CLIENT_CFLAGS) -DWITH_TLS
|
||||
|
||||
ifeq ($(WITH_TLS_PSK),yes)
|
||||
BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_TLS_PSK
|
||||
LIB_CFLAGS:=$(LIB_CFLAGS) -DWITH_TLS_PSK
|
||||
CLIENT_CFLAGS:=$(CLIENT_CFLAGS) -DWITH_TLS_PSK
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_THREADING),yes)
|
||||
LIB_LIBS:=$(LIB_LIBS) -lpthread
|
||||
LIB_CFLAGS:=$(LIB_CFLAGS) -DWITH_THREADING
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_STRICT_PROTOCOL),yes)
|
||||
LIB_CFLAGS:=$(LIB_CFLAGS) -DWITH_STRICT_PROTOCOL
|
||||
BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_STRICT_PROTOCOL
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_BRIDGE),yes)
|
||||
BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_BRIDGE
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_PERSISTENCE),yes)
|
||||
BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_PERSISTENCE
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_MEMORY_TRACKING),yes)
|
||||
ifneq ($(UNAME),SunOS)
|
||||
BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_MEMORY_TRACKING
|
||||
endif
|
||||
endif
|
||||
|
||||
#ifeq ($(WITH_DB_UPGRADE),yes)
|
||||
# BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_DB_UPGRADE
|
||||
#endif
|
||||
|
||||
ifeq ($(WITH_SYS_TREE),yes)
|
||||
BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_SYS_TREE
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_SRV),yes)
|
||||
LIB_CFLAGS:=$(LIB_CFLAGS) -DWITH_SRV
|
||||
LIB_LIBS:=$(LIB_LIBS) -lcares
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME),SunOS)
|
||||
BROKER_LIBS:=$(BROKER_LIBS) -lsocket -lnsl
|
||||
LIB_LIBS:=$(LIB_LIBS) -lsocket -lnsl
|
||||
endif
|
||||
|
||||
|
||||
INSTALL?=install
|
||||
prefix=/usr/local
|
||||
mandir=${prefix}/share/man
|
||||
localedir=${prefix}/share/locale
|
43
doc/historical/old-regex.txt
Normal file
43
doc/historical/old-regex.txt
Normal file
@ -0,0 +1,43 @@
|
||||
This is the description of the regex used previously for topic/subscription
|
||||
matching. It is reproduced here for posterity.
|
||||
|
||||
When a message is ready to be published at the broker, we need to check all
|
||||
of the subscriptions to see which ones the message should be sent to. This
|
||||
would be easy without wildcards, but requires a bit more work with them.
|
||||
|
||||
The regex used to do the matching is of the form below for a topic of a/b/c:
|
||||
|
||||
^(?:(?:(a|\+)(?!$))(?:(?:/(?:(b|\+)(?!$)))(?:(?:/(?:c|\+))|/#)?|/#)?|#)$
|
||||
|
||||
In general, we're matching (a or +) followed by (the next levels of
|
||||
hierarchy or #).
|
||||
More specifically, all the levels of hierarchy must match, unless the last
|
||||
level is #.
|
||||
|
||||
^(?: # Must start at beginning of string
|
||||
(?: # (Level 1 hierarchy)
|
||||
(a|\+)(?!$) # Match a or +, but only if not EOL.
|
||||
) # AND
|
||||
(?:
|
||||
(?: # (Level 2 hierarchy)
|
||||
/ # Match /
|
||||
(?: # AND
|
||||
(b|\+)(?!$) # Match b or +, but only if not EOL.
|
||||
)
|
||||
) # AND
|
||||
(?:
|
||||
(?: # (Level 3 hierarchy)
|
||||
/ # Match /
|
||||
(?: # AND
|
||||
c|\+ # Match c or +.
|
||||
)
|
||||
)
|
||||
| # OR (instead of level 3)
|
||||
/# # Match /# at level 3
|
||||
)? # Level 3 exist 1/0 times
|
||||
| # OR (instead of level 2)
|
||||
/# # Match /# at level 2
|
||||
)? # Level 2 exist 1/0 times
|
||||
| # OR (instead of level 1)
|
||||
# # Match # at level 1
|
||||
)$ # Must end on EOL.
|
7
doc/historical/topic-match.kds
Normal file
7
doc/historical/topic-match.kds
Normal file
@ -0,0 +1,7 @@
|
||||
S'^(?:(?:(a|\\+)(?!$))(?:(?:/(?:(b|\\+)(?!$)))(?:(?:/(?:c|\\+))|/#)?|/#)?|#)$'
|
||||
p1
|
||||
.S'a/#\na/b/c\na/b/+\na/b\na/+\n+\n+/b\n+/+/+\n+/b/c\na/c'
|
||||
p2
|
||||
.I8
|
||||
.S''
|
||||
.
|
31
edl-v10
Normal file
31
edl-v10
Normal file
@ -0,0 +1,31 @@
|
||||
Eclipse Distribution License - v 1.0
|
||||
|
||||
Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Eclipse Foundation, Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
221
epl-v10
Normal file
221
epl-v10
Normal file
@ -0,0 +1,221 @@
|
||||
Eclipse Public License - v 1.0
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
|
||||
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
|
||||
CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
a) in the case of the initial Contributor, the initial code and
|
||||
documentation distributed under this Agreement, and
|
||||
|
||||
b) in the case of each subsequent Contributor:
|
||||
|
||||
i) changes to the Program, and
|
||||
ii) additions to the Program;
|
||||
|
||||
where such changes and/or additions to the Program originate from and are
|
||||
distributed by that particular Contributor. A Contribution 'originates' from a
|
||||
Contributor if it was added to the Program by such Contributor itself or anyone
|
||||
acting on such Contributor's behalf. Contributions do not include additions to
|
||||
the Program which: (i) are separate modules of software distributed in
|
||||
conjunction with the Program under their own license agreement, and (ii) are
|
||||
not derivative works of the Program.
|
||||
|
||||
"Contributor" means any person or entity that distributes the Program.
|
||||
|
||||
"Licensed Patents " mean patent claims licensable by a Contributor which are
|
||||
necessarily infringed by the use or sale of its Contribution alone or when
|
||||
combined with the Program.
|
||||
|
||||
"Program" means the Contributions distributed in accordance with this Agreement.
|
||||
|
||||
"Recipient" means anyone who receives the Program under this Agreement,
|
||||
including all Contributors.
|
||||
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a) Subject to the terms of this Agreement, each Contributor hereby grants
|
||||
Recipient a non-exclusive, worldwide, royalty-free copyright license to
|
||||
reproduce, prepare derivative works of, publicly display, publicly
|
||||
perform, distribute and sublicense the Contribution of such Contributor,
|
||||
if any, and such derivative works, in source code and object code form.
|
||||
|
||||
b) Subject to the terms of this Agreement, each Contributor hereby grants
|
||||
Recipient a non-exclusive, worldwide, royalty-free patent license under
|
||||
Licensed Patents to make, use, sell, offer to sell, import and otherwise
|
||||
transfer the Contribution of such Contributor, if any, in source code and
|
||||
object code form. This patent license shall apply to the combination of the
|
||||
Contribution and the Program if, at the time the Contribution is added by the
|
||||
Contributor, such addition of the Contribution causes such combination to be
|
||||
covered by the Licensed Patents. The patent license shall not apply to any
|
||||
other combinations which include the Contribution. No hardware per se is
|
||||
licensed hereunder.
|
||||
|
||||
c) Recipient understands that although each Contributor grants the licenses
|
||||
to its Contributions set forth herein, no assurances are provided by any
|
||||
Contributor that the Program does not infringe the patent or other
|
||||
intellectual property rights of any other entity. Each Contributor disclaims
|
||||
any liability to Recipient for claims brought by any other entity based on
|
||||
infringement of intellectual property rights or otherwise. As a condition to
|
||||
exercising the rights and licenses granted hereunder, each Recipient hereby
|
||||
assumes sole responsibility to secure any other intellectual property rights
|
||||
needed, if any. For example, if a third party patent license is required to
|
||||
allow Recipient to distribute the Program, it is Recipient's responsibility
|
||||
to acquire that license before distributing the Program.
|
||||
|
||||
d) Each Contributor represents that to its knowledge it has sufficient
|
||||
copyright rights in its Contribution, if any, to grant the copyright license
|
||||
set forth in this Agreement.
|
||||
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
A Contributor may choose to distribute the Program in object code form under
|
||||
its own license agreement, provided that:
|
||||
|
||||
a) it complies with the terms and conditions of this Agreement; and
|
||||
|
||||
b) its license agreement:
|
||||
|
||||
i) effectively disclaims on behalf of all Contributors all warranties and
|
||||
conditions, express and implied, including warranties or conditions of
|
||||
title and non-infringement, and implied warranties or conditions of
|
||||
merchantability and fitness for a particular purpose;
|
||||
|
||||
ii) effectively excludes on behalf of all Contributors all liability for
|
||||
damages, including direct, indirect, special, incidental and consequential
|
||||
damages, such as lost profits;
|
||||
|
||||
iii) states that any provisions which differ from this Agreement are offered
|
||||
by that Contributor alone and not by any other party; and
|
||||
|
||||
iv) states that source code for the Program is available from such
|
||||
Contributor, and informs licensees how to obtain it in a reasonable manner
|
||||
on or through a medium customarily used for software exchange.
|
||||
|
||||
When the Program is made available in source code form:
|
||||
|
||||
a) it must be made available under this Agreement; and
|
||||
|
||||
b) a copy of this Agreement must be included with each copy of the Program.
|
||||
|
||||
Contributors may not remove or alter any copyright notices contained within
|
||||
the Program.
|
||||
|
||||
Each Contributor must identify itself as the originator of its Contribution,
|
||||
if any, in a manner that reasonably allows subsequent Recipients to identify
|
||||
the originator of the Contribution.
|
||||
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain responsibilities with
|
||||
respect to end users, business partners and the like. While this license is
|
||||
intended to facilitate the commercial use of the Program, the Contributor who
|
||||
includes the Program in a commercial product offering should do so in a
|
||||
manner which does not create potential liability for other Contributors.
|
||||
Therefore, if a Contributor includes the Program in a commercial product
|
||||
offering, such Contributor ("Commercial Contributor") hereby agrees to defend
|
||||
and indemnify every other Contributor ("Indemnified Contributor") against any
|
||||
losses, damages and costs (collectively "Losses") arising from claims,
|
||||
lawsuits and other legal actions brought by a third party against the
|
||||
Indemnified Contributor to the extent caused by the acts or omissions of such
|
||||
Commercial Contributor in connection with its distribution of the Program in
|
||||
a commercial product offering. The obligations in this section do not apply
|
||||
to any claims or Losses relating to any actual or alleged intellectual
|
||||
property infringement. In order to qualify, an Indemnified Contributor must:
|
||||
a) promptly notify the Commercial Contributor in writing of such claim, and
|
||||
b) allow the Commercial Contributor to control, and cooperate with the
|
||||
Commercial Contributor in, the defense and any related settlement
|
||||
negotiations. The Indemnified Contributor may participate in any such claim
|
||||
at its own expense.
|
||||
|
||||
For example, a Contributor might include the Program in a commercial product
|
||||
offering, Product X. That Contributor is then a Commercial Contributor. If
|
||||
that Commercial Contributor then makes performance claims, or offers
|
||||
warranties related to Product X, those performance claims and warranties are
|
||||
such Commercial Contributor's responsibility alone. Under this section, the
|
||||
Commercial Contributor would have to defend claims against the other
|
||||
Contributors related to those performance claims and warranties, and if a
|
||||
court requires any other Contributor to pay any damages as a result, the
|
||||
Commercial Contributor must pay those damages.
|
||||
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON
|
||||
AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
|
||||
EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
|
||||
CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A
|
||||
PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the
|
||||
appropriateness of using and distributing the Program and assumes all risks
|
||||
associated with its exercise of rights under this Agreement , including but
|
||||
not limited to the risks and costs of program errors, compliance with
|
||||
applicable laws, damage to or loss of data, programs or equipment, and
|
||||
unavailability or interruption of operations.
|
||||
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
|
||||
CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
|
||||
LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
|
||||
EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGES.
|
||||
|
||||
|
||||
7. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under
|
||||
applicable law, it shall not affect the validity or enforceability of the
|
||||
remainder of the terms of this Agreement, and without further action by the
|
||||
parties hereto, such provision shall be reformed to the minimum extent
|
||||
necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Program itself
|
||||
(excluding combinations of the Program with other software or hardware)
|
||||
infringes such Recipient's patent(s), then such Recipient's rights granted
|
||||
under Section 2(b) shall terminate as of the date such litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it fails to
|
||||
comply with any of the material terms or conditions of this Agreement and
|
||||
does not cure such failure in a reasonable period of time after becoming
|
||||
aware of such noncompliance. If all Recipient's rights under this Agreement
|
||||
terminate, Recipient agrees to cease use and distribution of the Program as
|
||||
soon as reasonably practicable. However, Recipient's obligations under this
|
||||
Agreement and any licenses granted by Recipient relating to the Program shall
|
||||
continue and survive.
|
||||
|
||||
Everyone is permitted to copy and distribute copies of this Agreement, but in
|
||||
order to avoid inconsistency the Agreement is copyrighted and may only be
|
||||
modified in the following manner. The Agreement Steward reserves the right to
|
||||
publish new versions (including revisions) of this Agreement from time to
|
||||
time. No one other than the Agreement Steward has the right to modify this
|
||||
Agreement. The Eclipse Foundation is the initial Agreement Steward. The
|
||||
Eclipse Foundation may assign the responsibility to serve as the Agreement
|
||||
Steward to a suitable separate entity. Each new version of the Agreement will
|
||||
be given a distinguishing version number. The Program (including
|
||||
Contributions) may always be distributed subject to the version of the
|
||||
Agreement under which it was received. In addition, after a new version of
|
||||
the Agreement is published, Contributor may elect to distribute the Program
|
||||
(including its Contributions) under the new version. Except as expressly
|
||||
stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
|
||||
licenses to the intellectual property of any Contributor under this
|
||||
Agreement, whether expressly, by implication, estoppel or otherwise. All
|
||||
rights in the Program not expressly granted under this Agreement are
|
||||
reserved.
|
||||
|
||||
This Agreement is governed by the laws of the State of New York and the
|
||||
intellectual property laws of the United States of America. No party to this
|
||||
Agreement will bring a legal action under this Agreement more than one year
|
||||
after the cause of action arose. Each party waives its rights to a jury trial
|
||||
in any resulting litigation.
|
||||
|
15
examples/mysql_log/Makefile
Normal file
15
examples/mysql_log/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
CFLAGS=-Wall -ggdb
|
||||
LDFLAGS=../../lib/libmosquitto.so.1 -lmysqlclient
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all : mosquitto_mysql_log
|
||||
|
||||
mosquitto_mysql_log : mysql_log.o
|
||||
${CC} $^ -o $@ ${LDFLAGS}
|
||||
|
||||
mysql_log.o : mysql_log.c
|
||||
${CC} -c $^ -o $@ ${CFLAGS} -I../../lib
|
||||
|
||||
clean :
|
||||
-rm -f *.o mosquitto_mysql_log
|
118
examples/mysql_log/mysql_log.c
Normal file
118
examples/mysql_log/mysql_log.c
Normal file
@ -0,0 +1,118 @@
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# include <process.h>
|
||||
# define snprintf sprintf_s
|
||||
#endif
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
#define db_host "localhost"
|
||||
#define db_username "mqtt_log"
|
||||
#define db_password "password"
|
||||
#define db_database "mqtt_log"
|
||||
#define db_port 3306
|
||||
|
||||
#define db_query "INSERT INTO mqtt_log (topic, payload) VALUES (?,?)"
|
||||
|
||||
#define mqtt_host "localhost"
|
||||
#define mqtt_port 1883
|
||||
|
||||
static int run = 1;
|
||||
static MYSQL_STMT *stmt = NULL;
|
||||
|
||||
void handle_signal(int s)
|
||||
{
|
||||
run = 0;
|
||||
}
|
||||
|
||||
void connect_callback(struct mosquitto *mosq, void *obj, int result)
|
||||
{
|
||||
}
|
||||
|
||||
void message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
|
||||
{
|
||||
MYSQL_BIND bind[2];
|
||||
|
||||
memset(bind, 0, sizeof(bind));
|
||||
|
||||
bind[0].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[0].buffer = message->topic;
|
||||
bind[1].buffer_type = MYSQL_TYPE_STRING;
|
||||
bind[1].buffer = message->payload;
|
||||
|
||||
mysql_stmt_bind_param(stmt, bind);
|
||||
mysql_stmt_execute(stmt);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
MYSQL *connection;
|
||||
my_bool reconnect = true;
|
||||
char clientid[24];
|
||||
struct mosquitto *mosq;
|
||||
int rc = 0;
|
||||
|
||||
signal(SIGINT, handle_signal);
|
||||
signal(SIGTERM, handle_signal);
|
||||
|
||||
mysql_library_init(0, NULL, NULL);
|
||||
mosquitto_lib_init();
|
||||
|
||||
connection = mysql_init(NULL);
|
||||
|
||||
if(connection){
|
||||
mysql_options(connection, MYSQL_OPT_RECONNECT, &reconnect);
|
||||
|
||||
connection = mysql_real_connect(connection, db_host, db_username, db_password, db_database, db_port, NULL, 0);
|
||||
|
||||
if(connection){
|
||||
stmt = mysql_stmt_init(connection);
|
||||
|
||||
mysql_stmt_prepare(stmt, db_query, strlen(db_query));
|
||||
|
||||
memset(clientid, 0, 24);
|
||||
snprintf(clientid, 23, "mysql_log_%d", getpid());
|
||||
mosq = mosquitto_new(clientid, true, connection);
|
||||
if(mosq){
|
||||
mosquitto_connect_callback_set(mosq, connect_callback);
|
||||
mosquitto_message_callback_set(mosq, message_callback);
|
||||
|
||||
|
||||
rc = mosquitto_connect(mosq, mqtt_host, mqtt_port, 60);
|
||||
|
||||
mosquitto_subscribe(mosq, NULL, "#", 0);
|
||||
|
||||
while(run){
|
||||
rc = mosquitto_loop(mosq, -1, 1);
|
||||
if(run && rc){
|
||||
sleep(20);
|
||||
mosquitto_reconnect(mosq);
|
||||
}
|
||||
}
|
||||
mosquitto_destroy(mosq);
|
||||
}
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
mysql_close(connection);
|
||||
}else{
|
||||
fprintf(stderr, "Error: Unable to connect to database.\n");
|
||||
printf("%s\n", mysql_error(connection));
|
||||
rc = 1;
|
||||
}
|
||||
}else{
|
||||
fprintf(stderr, "Error: Unable to start mysql.\n");
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
mysql_library_end();
|
||||
mosquitto_lib_cleanup();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
18
examples/temperature_conversion/Makefile
Normal file
18
examples/temperature_conversion/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
CFLAGS=-Wall -ggdb -I../../lib -I../../lib/cpp
|
||||
LDFLAGS=-L../../lib ../../lib/cpp/libmosquittopp.so.1 ../../lib/libmosquitto.so.1
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all : mqtt_temperature_conversion
|
||||
|
||||
mqtt_temperature_conversion : main.o temperature_conversion.o
|
||||
${CXX} $^ -o $@ ${LDFLAGS}
|
||||
|
||||
main.o : main.cpp
|
||||
${CXX} -c $^ -o $@ ${CFLAGS}
|
||||
|
||||
temperature_conversion.o : temperature_conversion.cpp
|
||||
${CXX} -c $^ -o $@ ${CFLAGS}
|
||||
|
||||
clean :
|
||||
-rm -f *.o mqtt_temperature_conversion
|
23
examples/temperature_conversion/main.cpp
Normal file
23
examples/temperature_conversion/main.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "temperature_conversion.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
class mqtt_tempconv *tempconv;
|
||||
int rc;
|
||||
|
||||
mosqpp::lib_init();
|
||||
|
||||
tempconv = new mqtt_tempconv("tempconv", "localhost", 1883);
|
||||
|
||||
while(1){
|
||||
rc = tempconv->loop();
|
||||
if(rc){
|
||||
tempconv->reconnect();
|
||||
}
|
||||
}
|
||||
|
||||
mosqpp::lib_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
6
examples/temperature_conversion/readme.txt
Normal file
6
examples/temperature_conversion/readme.txt
Normal file
@ -0,0 +1,6 @@
|
||||
This is a simple example of the C++ library mosquittopp.
|
||||
|
||||
It is a client that subscribes to the topic temperature/celsius which should
|
||||
have temperature data in text form being published to it. It reads this data as
|
||||
a Celsius temperature, converts to Farenheit and republishes on
|
||||
temperature/farenheit.
|
45
examples/temperature_conversion/temperature_conversion.cpp
Normal file
45
examples/temperature_conversion/temperature_conversion.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "temperature_conversion.h"
|
||||
#include <mosquittopp.h>
|
||||
|
||||
mqtt_tempconv::mqtt_tempconv(const char *id, const char *host, int port) : mosquittopp(id)
|
||||
{
|
||||
int keepalive = 60;
|
||||
|
||||
/* Connect immediately. This could also be done by calling
|
||||
* mqtt_tempconv->connect(). */
|
||||
connect(host, port, keepalive);
|
||||
};
|
||||
|
||||
void mqtt_tempconv::on_connect(int rc)
|
||||
{
|
||||
printf("Connected with code %d.\n", rc);
|
||||
if(rc == 0){
|
||||
/* Only attempt to subscribe on a successful connect. */
|
||||
subscribe(NULL, "temperature/celsius");
|
||||
}
|
||||
}
|
||||
|
||||
void mqtt_tempconv::on_message(const struct mosquitto_message *message)
|
||||
{
|
||||
double temp_celsius, temp_farenheit;
|
||||
char buf[51];
|
||||
|
||||
if(!strcmp(message->topic, "temperature/celsius")){
|
||||
memset(buf, 0, 51*sizeof(char));
|
||||
/* Copy N-1 bytes to ensure always 0 terminated. */
|
||||
memcpy(buf, message->payload, 50*sizeof(char));
|
||||
temp_celsius = atof(buf);
|
||||
temp_farenheit = temp_celsius*9.0/5.0 + 32.0;
|
||||
snprintf(buf, 50, "%f", temp_farenheit);
|
||||
publish(NULL, "temperature/farenheit", strlen(buf), buf);
|
||||
}
|
||||
}
|
||||
|
||||
void mqtt_tempconv::on_subscribe(int mid, int qos_count, const int *granted_qos)
|
||||
{
|
||||
printf("Subscription succeeded.\n");
|
||||
}
|
||||
|
17
examples/temperature_conversion/temperature_conversion.h
Normal file
17
examples/temperature_conversion/temperature_conversion.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef TEMPERATURE_CONVERSION_H
|
||||
#define TEMPERATURE_CONVERSION_H
|
||||
|
||||
#include <mosquittopp.h>
|
||||
|
||||
class mqtt_tempconv : public mosqpp::mosquittopp
|
||||
{
|
||||
public:
|
||||
mqtt_tempconv(const char *id, const char *host, int port);
|
||||
~mqtt_tempconv();
|
||||
|
||||
void on_connect(int rc);
|
||||
void on_message(const struct mosquitto_message *message);
|
||||
void on_subscribe(int mid, int qos_count, const int *granted_qos);
|
||||
};
|
||||
|
||||
#endif
|
144
installer/mosquitto-cygwin.nsi
Normal file
144
installer/mosquitto-cygwin.nsi
Normal file
@ -0,0 +1,144 @@
|
||||
; NSIS installer script for mosquitto
|
||||
|
||||
!include "MUI.nsh"
|
||||
|
||||
; For environment variable code
|
||||
!include "WinMessages.nsh"
|
||||
!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
||||
|
||||
Name "mosquitto"
|
||||
!define VERSION 1.3.1
|
||||
OutFile "mosquitto-${VERSION}-install-cygwin.exe"
|
||||
|
||||
InstallDir "$PROGRAMFILES\mosquitto"
|
||||
|
||||
;--------------------------------
|
||||
; Installer pages
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_COMPONENTS
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
|
||||
;--------------------------------
|
||||
; Uninstaller pages
|
||||
!insertmacro MUI_UNPAGE_WELCOME
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
;--------------------------------
|
||||
; Languages
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
|
||||
;--------------------------------
|
||||
; Installer sections
|
||||
|
||||
Section "Files" SecInstall
|
||||
SectionIn RO
|
||||
SetOutPath "$INSTDIR"
|
||||
File "c:\cygwin\bin\cygwin1.dll"
|
||||
File "c:\cygwin\bin\cyggcc_s-1.dll"
|
||||
File "c:\cygwin\bin\cygcrypto-1.0.0.dll"
|
||||
File "c:\cygwin\bin\cygssl-1.0.0.dll"
|
||||
File "c:\cygwin\bin\cygz.dll"
|
||||
File "..\src\mosquitto.exe"
|
||||
File "..\build\src\Release\mosquitto_passwd.exe"
|
||||
File "..\build\client\Release\mosquitto_pub.exe"
|
||||
File "..\build\client\Release\mosquitto_sub.exe"
|
||||
File "..\build\lib\Release\mosquitto.dll"
|
||||
File "..\build\lib\cpp\Release\mosquittopp.dll"
|
||||
File "..\aclfile.example"
|
||||
File "..\ChangeLog.txt"
|
||||
File "..\mosquitto.conf"
|
||||
File "..\pwfile.example"
|
||||
File "..\readme.txt"
|
||||
File "..\readme-windows.txt"
|
||||
File "C:\pthreads\Pre-built.2\dll\x86\pthreadVC2.dll"
|
||||
File "C:\OpenSSL-Win32\libeay32.dll"
|
||||
File "C:\OpenSSL-Win32\ssleay32.dll"
|
||||
File "..\LICENSE.txt"
|
||||
File "..\LICENSE-3rd-party.txt"
|
||||
|
||||
SetOutPath "$INSTDIR\devel"
|
||||
File "..\lib\mosquitto.h"
|
||||
File "..\build\lib\Release\mosquitto.lib"
|
||||
File "..\lib\cpp\mosquittopp.h"
|
||||
File "..\build\lib\cpp\Release\mosquittopp.lib"
|
||||
File "..\src\mosquitto_plugin.h"
|
||||
|
||||
SetOutPath "$INSTDIR\python"
|
||||
File "..\lib\python\mosquitto.py"
|
||||
File "..\lib\python\setup.py"
|
||||
File "..\lib\python\sub.py"
|
||||
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "DisplayName" "Mosquitto MQTT broker"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "QuietUninstallString" "$\"$INSTDIR\Uninstall.exe$\" /S"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "HelpLink" "http://mosquitto.org/"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "URLInfoAbout" "http://mosquitto.org/"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "DisplayVersion" "${VERSION}"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "NoModify" "1"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "NoRepair" "1"
|
||||
|
||||
WriteRegExpandStr ${env_hklm} MOSQUITTO_DIR $INSTDIR
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
SectionEnd
|
||||
|
||||
Section "Service" SecService
|
||||
ExecWait '"$INSTDIR\mosquitto.exe" install'
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
ExecWait '"$INSTDIR\mosquitto.exe" uninstall'
|
||||
Delete "$INSTDIR\cygwin1.dll"
|
||||
Delete "$INSTDIR\cyggcc_s-1.dll"
|
||||
Delete "$INSTDIR\cygcrypto-1.0.0.dll"
|
||||
Delete "$INSTDIR\cygssl-1.0.0.dll"
|
||||
Delete "$INSTDIR\cygz.dll"
|
||||
Delete "$INSTDIR\mosquitto.exe"
|
||||
Delete "$INSTDIR\mosquitto_passwd.exe"
|
||||
Delete "$INSTDIR\mosquitto_pub.exe"
|
||||
Delete "$INSTDIR\mosquitto_sub.exe"
|
||||
Delete "$INSTDIR\mosquitto.dll"
|
||||
Delete "$INSTDIR\mosquittopp.dll"
|
||||
Delete "$INSTDIR\aclfile.example"
|
||||
Delete "$INSTDIR\ChangeLog.txt"
|
||||
Delete "$INSTDIR\mosquitto.conf"
|
||||
Delete "$INSTDIR\pwfile.example"
|
||||
Delete "$INSTDIR\readme.txt"
|
||||
Delete "$INSTDIR\readme-windows.txt"
|
||||
Delete "$INSTDIR\pthreadVC2.dll"
|
||||
Delete "$INSTDIR\libeay32.dll"
|
||||
Delete "$INSTDIR\ssleay32.dll"
|
||||
Delete "$INSTDIR\LICENSE.txt"
|
||||
Delete "$INSTDIR\LICENSE-3rd-party.txt"
|
||||
|
||||
Delete "$INSTDIR\devel\mosquitto.h"
|
||||
Delete "$INSTDIR\devel\mosquitto.lib"
|
||||
Delete "$INSTDIR\devel\mosquittopp.h"
|
||||
Delete "$INSTDIR\devel\mosquittopp.lib"
|
||||
Delete "$INSTDIR\devel\mosquitto_plugin.h"
|
||||
|
||||
Delete "$INSTDIR\python\mosquitto.py"
|
||||
Delete "$INSTDIR\python\setup.py"
|
||||
Delete "$INSTDIR\python\sub.py"
|
||||
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
RMDir "$INSTDIR"
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto"
|
||||
|
||||
DeleteRegValue ${env_hklm} MOSQUITTO_DIR
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
SectionEnd
|
||||
|
||||
LangString DESC_SecInstall ${LANG_ENGLISH} "The main installation."
|
||||
LangString DESC_SecService ${LANG_ENGLISH} "Install mosquitto as a Windows service?"
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SecInstall} $(DESC_SecInstall)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SecService} $(DESC_SecService)
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||
|
134
installer/mosquitto.nsi
Normal file
134
installer/mosquitto.nsi
Normal file
@ -0,0 +1,134 @@
|
||||
; NSIS installer script for mosquitto
|
||||
|
||||
!include "MUI.nsh"
|
||||
|
||||
; For environment variable code
|
||||
!include "WinMessages.nsh"
|
||||
!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
||||
|
||||
Name "mosquitto"
|
||||
!define VERSION 1.3.1
|
||||
OutFile "mosquitto-${VERSION}-install-win32.exe"
|
||||
|
||||
InstallDir "$PROGRAMFILES\mosquitto"
|
||||
|
||||
;--------------------------------
|
||||
; Installer pages
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_COMPONENTS
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
|
||||
;--------------------------------
|
||||
; Uninstaller pages
|
||||
!insertmacro MUI_UNPAGE_WELCOME
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
;--------------------------------
|
||||
; Languages
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
|
||||
;--------------------------------
|
||||
; Installer sections
|
||||
|
||||
Section "Files" SecInstall
|
||||
SectionIn RO
|
||||
SetOutPath "$INSTDIR"
|
||||
File "..\build\src\Release\mosquitto.exe"
|
||||
File "..\build\src\Release\mosquitto_passwd.exe"
|
||||
File "..\build\client\Release\mosquitto_pub.exe"
|
||||
File "..\build\client\Release\mosquitto_sub.exe"
|
||||
File "..\build\lib\Release\mosquitto.dll"
|
||||
File "..\build\lib\cpp\Release\mosquittopp.dll"
|
||||
File "..\aclfile.example"
|
||||
File "..\ChangeLog.txt"
|
||||
File "..\mosquitto.conf"
|
||||
File "..\pwfile.example"
|
||||
File "..\readme.txt"
|
||||
File "..\readme-windows.txt"
|
||||
File "C:\pthreads\Pre-built.2\dll\x86\pthreadVC2.dll"
|
||||
File "C:\OpenSSL-Win32\libeay32.dll"
|
||||
File "C:\OpenSSL-Win32\ssleay32.dll"
|
||||
File "..\LICENSE.txt"
|
||||
File "..\LICENSE-3rd-party.txt"
|
||||
|
||||
SetOutPath "$INSTDIR\devel"
|
||||
File "..\lib\mosquitto.h"
|
||||
File "..\build\lib\Release\mosquitto.lib"
|
||||
File "..\lib\cpp\mosquittopp.h"
|
||||
File "..\build\lib\cpp\Release\mosquittopp.lib"
|
||||
File "..\src\mosquitto_plugin.h"
|
||||
|
||||
SetOutPath "$INSTDIR\python"
|
||||
File "..\lib\python\mosquitto.py"
|
||||
File "..\lib\python\setup.py"
|
||||
File "..\lib\python\sub.py"
|
||||
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "DisplayName" "Mosquitto MQTT broker"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "QuietUninstallString" "$\"$INSTDIR\Uninstall.exe$\" /S"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "HelpLink" "http://mosquitto.org/"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "URLInfoAbout" "http://mosquitto.org/"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "DisplayVersion" "${VERSION}"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "NoModify" "1"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto" "NoRepair" "1"
|
||||
|
||||
WriteRegExpandStr ${env_hklm} MOSQUITTO_DIR $INSTDIR
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
SectionEnd
|
||||
|
||||
Section "Service" SecService
|
||||
ExecWait '"$INSTDIR\mosquitto.exe" install'
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
ExecWait '"$INSTDIR\mosquitto.exe" uninstall'
|
||||
Delete "$INSTDIR\mosquitto.exe"
|
||||
Delete "$INSTDIR\mosquitto_passwd.exe"
|
||||
Delete "$INSTDIR\mosquitto_pub.exe"
|
||||
Delete "$INSTDIR\mosquitto_sub.exe"
|
||||
Delete "$INSTDIR\mosquitto.dll"
|
||||
Delete "$INSTDIR\mosquittopp.dll"
|
||||
Delete "$INSTDIR\aclfile.example"
|
||||
Delete "$INSTDIR\ChangeLog.txt"
|
||||
Delete "$INSTDIR\mosquitto.conf"
|
||||
Delete "$INSTDIR\pwfile.example"
|
||||
Delete "$INSTDIR\readme.txt"
|
||||
Delete "$INSTDIR\readme-windows.txt"
|
||||
Delete "$INSTDIR\pthreadVC2.dll"
|
||||
Delete "$INSTDIR\libeay32.dll"
|
||||
Delete "$INSTDIR\ssleay32.dll"
|
||||
Delete "$INSTDIR\LICENSE.txt"
|
||||
Delete "$INSTDIR\LICENSE-3rd-party.txt"
|
||||
|
||||
Delete "$INSTDIR\devel\mosquitto.h"
|
||||
Delete "$INSTDIR\devel\mosquitto.lib"
|
||||
Delete "$INSTDIR\devel\mosquittopp.h"
|
||||
Delete "$INSTDIR\devel\mosquittopp.lib"
|
||||
Delete "$INSTDIR\devel\mosquitto_plugin.h"
|
||||
|
||||
Delete "$INSTDIR\python\mosquitto.py"
|
||||
Delete "$INSTDIR\python\setup.py"
|
||||
Delete "$INSTDIR\python\sub.py"
|
||||
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
RMDir "$INSTDIR"
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Mosquitto"
|
||||
|
||||
DeleteRegValue ${env_hklm} MOSQUITTO_DIR
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
SectionEnd
|
||||
|
||||
LangString DESC_SecInstall ${LANG_ENGLISH} "The main installation."
|
||||
LangString DESC_SecService ${LANG_ENGLISH} "Install mosquitto as a Windows service?"
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SecInstall} $(DESC_SecInstall)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SecService} $(DESC_SecService)
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||
|
71
lib/CMakeLists.txt
Normal file
71
lib/CMakeLists.txt
Normal file
@ -0,0 +1,71 @@
|
||||
add_subdirectory(cpp)
|
||||
|
||||
option(WITH_THREADING "Include client library threading support?" ON)
|
||||
if (${WITH_THREADING} STREQUAL ON)
|
||||
add_definitions("-DWITH_THREADING")
|
||||
if (WIN32)
|
||||
set (PTHREAD_LIBRARIES C:\\pthreads\\Pre-built.2\\lib\\x86\\pthreadVC2.lib)
|
||||
set (PTHREAD_INCLUDE_DIR C:\\pthreads\\Pre-built.2\\include)
|
||||
else (WIN32)
|
||||
set (PTHREAD_LIBRARIES pthread)
|
||||
set (PTHREAD_INCLUDE_DIR "")
|
||||
endif (WIN32)
|
||||
else (${WITH_THREADING} STREQUAL ON)
|
||||
set (PTHREAD_LIBRARIES "")
|
||||
set (PTHREAD_INCLUDE_DIR "")
|
||||
endif (${WITH_THREADING} STREQUAL ON)
|
||||
|
||||
include_directories(${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/lib
|
||||
${STDBOOL_H_PATH} ${STDINT_H_PATH}
|
||||
${OPENSSL_INCLUDE_DIR} ${PTHREAD_INCLUDE_DIR})
|
||||
link_directories(${mosquitto_SOURCE_DIR}/lib)
|
||||
|
||||
add_library(libmosquitto SHARED
|
||||
logging_mosq.c logging_mosq.h
|
||||
memory_mosq.c memory_mosq.h
|
||||
messages_mosq.c messages_mosq.h
|
||||
mosquitto.c mosquitto.h
|
||||
mosquitto_internal.h
|
||||
mqtt3_protocol.h
|
||||
net_mosq.c net_mosq.h
|
||||
read_handle.c read_handle.h
|
||||
read_handle_client.c
|
||||
read_handle_shared.c
|
||||
send_client_mosq.c
|
||||
send_mosq.c send_mosq.h
|
||||
srv_mosq.c
|
||||
thread_mosq.c
|
||||
time_mosq.c
|
||||
tls_mosq.c
|
||||
util_mosq.c util_mosq.h
|
||||
will_mosq.c will_mosq.h)
|
||||
|
||||
set (LIBRARIES ${OPENSSL_LIBRARIES} ${PTHREAD_LIBRARIES})
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
set (LIBRARIES ${LIBRARIES} rt)
|
||||
endif (UNIX AND NOT APPLE)
|
||||
|
||||
if (WIN32)
|
||||
set (LIBRARIES ${LIBRARIES} ws2_32)
|
||||
endif (WIN32)
|
||||
|
||||
option(WITH_SRV "Include SRV lookup support?" ON)
|
||||
if (${WITH_SRV} STREQUAL ON)
|
||||
set (LIBRARIES ${LIBRARIES} cares)
|
||||
endif (${WITH_SRV} STREQUAL ON)
|
||||
|
||||
target_link_libraries(libmosquitto ${LIBRARIES})
|
||||
|
||||
set_target_properties(libmosquitto PROPERTIES
|
||||
OUTPUT_NAME mosquitto
|
||||
VERSION ${VERSION}
|
||||
SOVERSION 1
|
||||
)
|
||||
|
||||
install(TARGETS libmosquitto RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR})
|
||||
install(FILES mosquitto.h DESTINATION ${INCLUDEDIR})
|
||||
|
||||
if (UNIX)
|
||||
install(CODE "EXEC_PROGRAM(/sbin/ldconfig)")
|
||||
endif (UNIX)
|
96
lib/Makefile
Normal file
96
lib/Makefile
Normal file
@ -0,0 +1,96 @@
|
||||
include ../config.mk
|
||||
|
||||
.PHONY : really clean install
|
||||
|
||||
MOSQ_OBJS=mosquitto.o \
|
||||
logging_mosq.o \
|
||||
memory_mosq.o \
|
||||
messages_mosq.o \
|
||||
net_mosq.o \
|
||||
read_handle.o \
|
||||
read_handle_client.o \
|
||||
read_handle_shared.o \
|
||||
send_mosq.o \
|
||||
send_client_mosq.o \
|
||||
srv_mosq.o \
|
||||
thread_mosq.o \
|
||||
time_mosq.o \
|
||||
tls_mosq.o \
|
||||
util_mosq.o \
|
||||
will_mosq.o
|
||||
|
||||
all : libmosquitto.so.${SOVERSION} libmosquitto.a
|
||||
$(MAKE) -C cpp
|
||||
|
||||
install : all
|
||||
$(INSTALL) -d ${DESTDIR}$(prefix)/lib${LIB_SUFFIX}/
|
||||
$(INSTALL) -s libmosquitto.so.${SOVERSION} ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so.${SOVERSION}
|
||||
ln -sf libmosquitto.so.${SOVERSION} ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so
|
||||
$(INSTALL) -d ${DESTDIR}${prefix}/include/
|
||||
$(INSTALL) mosquitto.h ${DESTDIR}${prefix}/include/mosquitto.h
|
||||
$(MAKE) -C cpp install
|
||||
|
||||
uninstall :
|
||||
-rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so.${SOVERSION}
|
||||
-rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so
|
||||
-rm -f ${DESTDIR}${prefix}/include/mosquitto.h
|
||||
|
||||
reallyclean : clean
|
||||
|
||||
clean :
|
||||
-rm -f *.o libmosquitto.so.${SOVERSION} libmosquitto.so libmosquitto.a
|
||||
$(MAKE) -C cpp clean
|
||||
|
||||
libmosquitto.so.${SOVERSION} : ${MOSQ_OBJS}
|
||||
$(CC) -shared $(LIB_LDFLAGS) $^ -o $@ ${LIB_LIBS}
|
||||
|
||||
libmosquitto.a : ${MOSQ_OBJS}
|
||||
$(AR) cr $@ $^
|
||||
mosquitto.o : mosquitto.c mosquitto.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
logging_mosq.o : logging_mosq.c logging_mosq.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
messages_mosq.o : messages_mosq.c messages_mosq.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
memory_mosq.o : memory_mosq.c memory_mosq.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
net_mosq.o : net_mosq.c net_mosq.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
read_handle.o : read_handle.c read_handle.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
read_handle_client.o : read_handle_client.c read_handle.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
read_handle_shared.o : read_handle_shared.c read_handle.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
send_mosq.o : send_mosq.c send_mosq.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
send_client_mosq.o : send_client_mosq.c send_mosq.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
srv_mosq.o : srv_mosq.c
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
thread_mosq.o : thread_mosq.c
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
time_mosq.o : time_mosq.c
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
tls_mosq.o : tls_mosq.c
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
util_mosq.o : util_mosq.c util_mosq.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
||||
will_mosq.o : will_mosq.c will_mosq.h
|
||||
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||
|
18
lib/cpp/CMakeLists.txt
Normal file
18
lib/cpp/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
include_directories(${mosquitto_SOURCE_DIR}/lib ${mosquitto_SOURCE_DIR}/lib/cpp
|
||||
${STDBOOL_H_PATH} ${STDINT_H_PATH})
|
||||
link_directories(${mosquitto_BINARY_DIR}/lib)
|
||||
|
||||
add_library(mosquittopp SHARED
|
||||
mosquittopp.cpp mosquittopp.h)
|
||||
|
||||
target_link_libraries(mosquittopp mosquitto)
|
||||
set_target_properties(mosquittopp PROPERTIES
|
||||
VERSION ${VERSION}
|
||||
SOVERSION 1
|
||||
)
|
||||
install(TARGETS mosquittopp RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR})
|
||||
install(FILES mosquittopp.h DESTINATION ${INCLUDEDIR})
|
||||
|
||||
if (UNIX)
|
||||
install(CODE "EXEC_PROGRAM(/sbin/ldconfig)")
|
||||
endif (UNIX)
|
31
lib/cpp/Makefile
Normal file
31
lib/cpp/Makefile
Normal file
@ -0,0 +1,31 @@
|
||||
include ../../config.mk
|
||||
|
||||
ifneq ($(UNAME),SunOS)
|
||||
LIB_LDFLAGS:=$(LDFLAGS) -Wl,-soname,libmosquittopp.so.${SOVERSION}
|
||||
endif
|
||||
|
||||
.PHONY : clean install
|
||||
|
||||
all : libmosquittopp.so.${SOVERSION}
|
||||
|
||||
install : all
|
||||
$(INSTALL) -d ${DESTDIR}$(prefix)/lib${LIB_SUFFIX}/
|
||||
$(INSTALL) -s libmosquittopp.so.${SOVERSION} ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquittopp.so.${SOVERSION}
|
||||
ln -sf libmosquittopp.so.${SOVERSION} ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquittopp.so
|
||||
$(INSTALL) -d ${DESTDIR}${prefix}/include/
|
||||
$(INSTALL) mosquittopp.h ${DESTDIR}${prefix}/include/mosquittopp.h
|
||||
|
||||
uninstall :
|
||||
-rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquittopp.so.${SOVERSION}
|
||||
-rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquittopp.so
|
||||
-rm -f ${DESTDIR}${prefix}/include/mosquittopp.h
|
||||
|
||||
clean :
|
||||
-rm -f *.o libmosquittopp.so.${SOVERSION}
|
||||
|
||||
libmosquittopp.so.${SOVERSION} : mosquittopp.o
|
||||
$(CXX) -shared $(LIB_LDFLAGS) $< -o $@ ../libmosquitto.so.${SOVERSION}
|
||||
|
||||
mosquittopp.o : mosquittopp.cpp mosquittopp.h
|
||||
$(CXX) $(LIB_CXXFLAGS) -c $< -o $@
|
||||
|
292
lib/cpp/mosquittopp.cpp
Normal file
292
lib/cpp/mosquittopp.cpp
Normal file
@ -0,0 +1,292 @@
|
||||
/*
|
||||
Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <mosquitto.h>
|
||||
#include <mosquittopp.h>
|
||||
|
||||
namespace mosqpp {
|
||||
|
||||
static void on_connect_wrapper(struct mosquitto *mosq, void *userdata, int rc)
|
||||
{
|
||||
class mosquittopp *m = (class mosquittopp *)userdata;
|
||||
m->on_connect(rc);
|
||||
}
|
||||
|
||||
static void on_disconnect_wrapper(struct mosquitto *mosq, void *userdata, int rc)
|
||||
{
|
||||
class mosquittopp *m = (class mosquittopp *)userdata;
|
||||
m->on_disconnect(rc);
|
||||
}
|
||||
|
||||
static void on_publish_wrapper(struct mosquitto *mosq, void *userdata, int mid)
|
||||
{
|
||||
class mosquittopp *m = (class mosquittopp *)userdata;
|
||||
m->on_publish(mid);
|
||||
}
|
||||
|
||||
static void on_message_wrapper(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
|
||||
{
|
||||
class mosquittopp *m = (class mosquittopp *)userdata;
|
||||
m->on_message(message);
|
||||
}
|
||||
|
||||
static void on_subscribe_wrapper(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos)
|
||||
{
|
||||
class mosquittopp *m = (class mosquittopp *)userdata;
|
||||
m->on_subscribe(mid, qos_count, granted_qos);
|
||||
}
|
||||
|
||||
static void on_unsubscribe_wrapper(struct mosquitto *mosq, void *userdata, int mid)
|
||||
{
|
||||
class mosquittopp *m = (class mosquittopp *)userdata;
|
||||
m->on_unsubscribe(mid);
|
||||
}
|
||||
|
||||
|
||||
static void on_log_wrapper(struct mosquitto *mosq, void *userdata, int level, const char *str)
|
||||
{
|
||||
class mosquittopp *m = (class mosquittopp *)userdata;
|
||||
m->on_log(level, str);
|
||||
}
|
||||
|
||||
int lib_version(int *major, int *minor, int *revision)
|
||||
{
|
||||
if(major) *major = LIBMOSQUITTO_MAJOR;
|
||||
if(minor) *minor = LIBMOSQUITTO_MINOR;
|
||||
if(revision) *revision = LIBMOSQUITTO_REVISION;
|
||||
return LIBMOSQUITTO_VERSION_NUMBER;
|
||||
}
|
||||
|
||||
int lib_init()
|
||||
{
|
||||
return mosquitto_lib_init();
|
||||
}
|
||||
|
||||
int lib_cleanup()
|
||||
{
|
||||
return mosquitto_lib_cleanup();
|
||||
}
|
||||
|
||||
const char* strerror(int mosq_errno)
|
||||
{
|
||||
return mosquitto_strerror(mosq_errno);
|
||||
}
|
||||
|
||||
const char* connack_string(int connack_code)
|
||||
{
|
||||
return mosquitto_connack_string(connack_code);
|
||||
}
|
||||
|
||||
int sub_topic_tokenise(const char *subtopic, char ***topics, int *count)
|
||||
{
|
||||
return mosquitto_sub_topic_tokenise(subtopic, topics, count);
|
||||
}
|
||||
|
||||
int sub_topic_tokens_free(char ***topics, int count)
|
||||
{
|
||||
return mosquitto_sub_topic_tokens_free(topics, count);
|
||||
}
|
||||
|
||||
int topic_matches_sub(const char *sub, const char *topic, bool *result)
|
||||
{
|
||||
return mosquitto_topic_matches_sub(sub, topic, result);
|
||||
}
|
||||
|
||||
mosquittopp::mosquittopp(const char *id, bool clean_session)
|
||||
{
|
||||
m_mosq = mosquitto_new(id, clean_session, this);
|
||||
mosquitto_connect_callback_set(m_mosq, on_connect_wrapper);
|
||||
mosquitto_disconnect_callback_set(m_mosq, on_disconnect_wrapper);
|
||||
mosquitto_publish_callback_set(m_mosq, on_publish_wrapper);
|
||||
mosquitto_message_callback_set(m_mosq, on_message_wrapper);
|
||||
mosquitto_subscribe_callback_set(m_mosq, on_subscribe_wrapper);
|
||||
mosquitto_unsubscribe_callback_set(m_mosq, on_unsubscribe_wrapper);
|
||||
mosquitto_log_callback_set(m_mosq, on_log_wrapper);
|
||||
}
|
||||
|
||||
mosquittopp::~mosquittopp()
|
||||
{
|
||||
mosquitto_destroy(m_mosq);
|
||||
}
|
||||
|
||||
int mosquittopp::reinitialise(const char *id, bool clean_session)
|
||||
{
|
||||
int rc;
|
||||
rc = mosquitto_reinitialise(m_mosq, id, clean_session, this);
|
||||
if(rc == MOSQ_ERR_SUCCESS){
|
||||
mosquitto_connect_callback_set(m_mosq, on_connect_wrapper);
|
||||
mosquitto_disconnect_callback_set(m_mosq, on_disconnect_wrapper);
|
||||
mosquitto_publish_callback_set(m_mosq, on_publish_wrapper);
|
||||
mosquitto_message_callback_set(m_mosq, on_message_wrapper);
|
||||
mosquitto_subscribe_callback_set(m_mosq, on_subscribe_wrapper);
|
||||
mosquitto_unsubscribe_callback_set(m_mosq, on_unsubscribe_wrapper);
|
||||
mosquitto_log_callback_set(m_mosq, on_log_wrapper);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int mosquittopp::connect(const char *host, int port, int keepalive)
|
||||
{
|
||||
return mosquitto_connect(m_mosq, host, port, keepalive);
|
||||
}
|
||||
|
||||
int mosquittopp::connect(const char *host, int port, int keepalive, const char *bind_address)
|
||||
{
|
||||
return mosquitto_connect_bind(m_mosq, host, port, keepalive, bind_address);
|
||||
}
|
||||
|
||||
int mosquittopp::connect_async(const char *host, int port, int keepalive)
|
||||
{
|
||||
return mosquitto_connect_async(m_mosq, host, port, keepalive);
|
||||
}
|
||||
|
||||
int mosquittopp::connect_async(const char *host, int port, int keepalive, const char *bind_address)
|
||||
{
|
||||
return mosquitto_connect_bind_async(m_mosq, host, port, keepalive, bind_address);
|
||||
}
|
||||
|
||||
int mosquittopp::reconnect()
|
||||
{
|
||||
return mosquitto_reconnect(m_mosq);
|
||||
}
|
||||
|
||||
int mosquittopp::reconnect_async()
|
||||
{
|
||||
return mosquitto_reconnect_async(m_mosq);
|
||||
}
|
||||
|
||||
int mosquittopp::disconnect()
|
||||
{
|
||||
return mosquitto_disconnect(m_mosq);
|
||||
}
|
||||
|
||||
int mosquittopp::socket()
|
||||
{
|
||||
return mosquitto_socket(m_mosq);
|
||||
}
|
||||
|
||||
int mosquittopp::will_set(const char *topic, int payloadlen, const void *payload, int qos, bool retain)
|
||||
{
|
||||
return mosquitto_will_set(m_mosq, topic, payloadlen, payload, qos, retain);
|
||||
}
|
||||
|
||||
int mosquittopp::will_clear()
|
||||
{
|
||||
return mosquitto_will_clear(m_mosq);
|
||||
}
|
||||
|
||||
int mosquittopp::username_pw_set(const char *username, const char *password)
|
||||
{
|
||||
return mosquitto_username_pw_set(m_mosq, username, password);
|
||||
}
|
||||
|
||||
int mosquittopp::publish(int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain)
|
||||
{
|
||||
return mosquitto_publish(m_mosq, mid, topic, payloadlen, payload, qos, retain);
|
||||
}
|
||||
|
||||
void mosquittopp::reconnect_delay_set(unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff)
|
||||
{
|
||||
mosquitto_reconnect_delay_set(m_mosq, reconnect_delay, reconnect_delay_max, reconnect_exponential_backoff);
|
||||
}
|
||||
|
||||
int mosquittopp::max_inflight_messages_set(unsigned int max_inflight_messages)
|
||||
{
|
||||
return mosquitto_max_inflight_messages_set(m_mosq, max_inflight_messages);
|
||||
}
|
||||
|
||||
void mosquittopp::message_retry_set(unsigned int message_retry)
|
||||
{
|
||||
mosquitto_message_retry_set(m_mosq, message_retry);
|
||||
}
|
||||
|
||||
int mosquittopp::subscribe(int *mid, const char *sub, int qos)
|
||||
{
|
||||
return mosquitto_subscribe(m_mosq, mid, sub, qos);
|
||||
}
|
||||
|
||||
int mosquittopp::unsubscribe(int *mid, const char *sub)
|
||||
{
|
||||
return mosquitto_unsubscribe(m_mosq, mid, sub);
|
||||
}
|
||||
|
||||
int mosquittopp::loop(int timeout, int max_packets)
|
||||
{
|
||||
return mosquitto_loop(m_mosq, timeout, max_packets);
|
||||
}
|
||||
|
||||
int mosquittopp::loop_misc()
|
||||
{
|
||||
return mosquitto_loop_misc(m_mosq);
|
||||
}
|
||||
|
||||
int mosquittopp::loop_read(int max_packets)
|
||||
{
|
||||
return mosquitto_loop_read(m_mosq, max_packets);
|
||||
}
|
||||
|
||||
int mosquittopp::loop_write(int max_packets)
|
||||
{
|
||||
return mosquitto_loop_write(m_mosq, max_packets);
|
||||
}
|
||||
|
||||
int mosquittopp::loop_forever(int timeout, int max_packets)
|
||||
{
|
||||
return mosquitto_loop_forever(m_mosq, timeout, max_packets);
|
||||
}
|
||||
|
||||
int mosquittopp::loop_start()
|
||||
{
|
||||
return mosquitto_loop_start(m_mosq);
|
||||
}
|
||||
|
||||
int mosquittopp::loop_stop(bool force)
|
||||
{
|
||||
return mosquitto_loop_stop(m_mosq, force);
|
||||
}
|
||||
|
||||
bool mosquittopp::want_write()
|
||||
{
|
||||
return mosquitto_want_write(m_mosq);
|
||||
}
|
||||
|
||||
void mosquittopp::user_data_set(void *userdata)
|
||||
{
|
||||
mosquitto_user_data_set(m_mosq, userdata);
|
||||
}
|
||||
|
||||
int mosquittopp::tls_set(const char *cafile, const char *capath, const char *certfile, const char *keyfile, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata))
|
||||
{
|
||||
return mosquitto_tls_set(m_mosq, cafile, capath, certfile, keyfile, pw_callback);
|
||||
}
|
||||
|
||||
int mosquittopp::tls_opts_set(int cert_reqs, const char *tls_version, const char *ciphers)
|
||||
{
|
||||
return mosquitto_tls_opts_set(m_mosq, cert_reqs, tls_version, ciphers);
|
||||
}
|
||||
|
||||
int mosquittopp::tls_insecure_set(bool value)
|
||||
{
|
||||
return mosquitto_tls_insecure_set(m_mosq, value);
|
||||
}
|
||||
|
||||
int mosquittopp::tls_psk_set(const char *psk, const char *identity, const char *ciphers)
|
||||
{
|
||||
return mosquitto_tls_psk_set(m_mosq, psk, identity, ciphers);
|
||||
}
|
||||
|
||||
}
|
102
lib/cpp/mosquittopp.h
Normal file
102
lib/cpp/mosquittopp.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifndef _MOSQUITTOPP_H_
|
||||
#define _MOSQUITTOPP_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef mosquittopp_EXPORTS
|
||||
# define mosqpp_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define mosqpp_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define mosqpp_EXPORT
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <time.h>
|
||||
#include <mosquitto.h>
|
||||
|
||||
namespace mosqpp {
|
||||
|
||||
mosqpp_EXPORT const char *strerror(int mosq_errno);
|
||||
mosqpp_EXPORT const char *connack_string(int connack_code);
|
||||
mosqpp_EXPORT int sub_topic_tokenise(const char *subtopic, char ***topics, int *count);
|
||||
mosqpp_EXPORT int sub_topic_tokens_free(char ***topics, int count);
|
||||
mosqpp_EXPORT int lib_version(int *major, int *minor, int *revision);
|
||||
mosqpp_EXPORT int lib_init();
|
||||
mosqpp_EXPORT int lib_cleanup();
|
||||
mosqpp_EXPORT int topic_matches_sub(const char *sub, const char *topic, bool *result);
|
||||
|
||||
/*
|
||||
* Class: mosquittopp
|
||||
*
|
||||
* A mosquitto client class. This is a C++ wrapper class for the mosquitto C
|
||||
* library. Please see mosquitto.h for details of the functions.
|
||||
*/
|
||||
class mosqpp_EXPORT mosquittopp {
|
||||
private:
|
||||
struct mosquitto *m_mosq;
|
||||
public:
|
||||
mosquittopp(const char *id=NULL, bool clean_session=true);
|
||||
~mosquittopp();
|
||||
|
||||
int reinitialise(const char *id, bool clean_session);
|
||||
int socket();
|
||||
int will_set(const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
|
||||
int will_clear();
|
||||
int username_pw_set(const char *username, const char *password=NULL);
|
||||
int connect(const char *host, int port=1883, int keepalive=60);
|
||||
int connect_async(const char *host, int port=1883, int keepalive=60);
|
||||
int connect(const char *host, int port, int keepalive, const char *bind_address);
|
||||
int connect_async(const char *host, int port, int keepalive, const char *bind_address);
|
||||
int reconnect();
|
||||
int reconnect_async();
|
||||
int disconnect();
|
||||
int publish(int *mid, const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
|
||||
int subscribe(int *mid, const char *sub, int qos=0);
|
||||
int unsubscribe(int *mid, const char *sub);
|
||||
void reconnect_delay_set(unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff);
|
||||
int max_inflight_messages_set(unsigned int max_inflight_messages);
|
||||
void message_retry_set(unsigned int message_retry);
|
||||
void user_data_set(void *userdata);
|
||||
int tls_set(const char *cafile, const char *capath=NULL, const char *certfile=NULL, const char *keyfile=NULL, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)=NULL);
|
||||
int tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL);
|
||||
int tls_insecure_set(bool value);
|
||||
int tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL);
|
||||
|
||||
int loop(int timeout=-1, int max_packets=1);
|
||||
int loop_misc();
|
||||
int loop_read(int max_packets=1);
|
||||
int loop_write(int max_packets=1);
|
||||
int loop_forever(int timeout=-1, int max_packets=1);
|
||||
int loop_start();
|
||||
int loop_stop(bool force=false);
|
||||
bool want_write();
|
||||
|
||||
virtual void on_connect(int rc) {return;};
|
||||
virtual void on_disconnect(int rc) {return;};
|
||||
virtual void on_publish(int mid) {return;};
|
||||
virtual void on_message(const struct mosquitto_message *message) {return;};
|
||||
virtual void on_subscribe(int mid, int qos_count, const int *granted_qos) {return;};
|
||||
virtual void on_unsubscribe(int mid) {return;};
|
||||
virtual void on_log(int level, const char *str) {return;};
|
||||
virtual void on_error() {return;};
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
13
lib/dummypthread.h
Normal file
13
lib/dummypthread.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef _DUMMYPTHREAD_H_
|
||||
#define _DUMMYPTHREAD_H_
|
||||
|
||||
#define pthread_create(A, B, C, D)
|
||||
#define pthread_join(A, B)
|
||||
#define pthread_cancel(A)
|
||||
|
||||
#define pthread_mutex_init(A, B)
|
||||
#define pthread_mutex_destroy(A)
|
||||
#define pthread_mutex_lock(A)
|
||||
#define pthread_mutex_unlock(A)
|
||||
|
||||
#endif
|
363
lib/jsws/mosquitto.js
Normal file
363
lib/jsws/mosquitto.js
Normal file
@ -0,0 +1,363 @@
|
||||
/*
|
||||
Copyright (c) 2012 Roger Light <roger@atchoo.org>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of mosquitto nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Mosquitto MQTT Javascript/Websocket client */
|
||||
/* Provides complete support for QoS 0.
|
||||
* Will not cause an error on QoS 1/2 packets.
|
||||
*/
|
||||
|
||||
var CONNECT = 0x10;
|
||||
var CONNACK = 0x20;
|
||||
var PUBLISH = 0x30;
|
||||
var PUBACK = 0x40;
|
||||
var PUBREC = 0x50;
|
||||
var PUBREL = 0x60;
|
||||
var PUBCOMP = 0x70;
|
||||
var SUBSCRIBE = 0x80;
|
||||
var SUBACK = 0x90;
|
||||
var UNSUBSCRIBE = 0xA0;
|
||||
var UNSUBACK = 0xB0;
|
||||
var PINGREQ = 0xC0;
|
||||
var PINGRESP = 0xD0;
|
||||
var DISCONNECT = 0xE0;
|
||||
|
||||
function AB2S(buffer) {
|
||||
var binary = '';
|
||||
var bytes = new Uint8Array(buffer);
|
||||
var len = bytes.byteLength;
|
||||
for(var i=0; i<len; i++){
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
return binary;
|
||||
}
|
||||
|
||||
function Mosquitto()
|
||||
{
|
||||
this.ws = null;
|
||||
this.onconnect = null;
|
||||
this.ondisconnect = null;
|
||||
this.onmessage = null;
|
||||
}
|
||||
|
||||
Mosquitto.prototype = {
|
||||
mqtt_ping : function()
|
||||
{
|
||||
var buffer = new ArrayBuffer(2);
|
||||
var i8V = new Int8Array(buffer);
|
||||
i8V[0] = PINGREQ;
|
||||
i8V[1] = 0;
|
||||
if(this.ws.readyState == 1){
|
||||
this.ws.send(buffer);
|
||||
}else{
|
||||
this.queue(buffer);
|
||||
}
|
||||
setTimeout(function(_this){_this.mqtt_ping();}, 60000, this);
|
||||
},
|
||||
|
||||
connect : function(url, keepalive){
|
||||
|
||||
this.url = url;
|
||||
this.keepalive = keepalive;
|
||||
this.mid = 1;
|
||||
this.out_queue = new Array();
|
||||
|
||||
this.ws = new WebSocket(url, 'mqttv3.1');
|
||||
this.ws.binaryType = "arraybuffer";
|
||||
this.ws.onopen = this.ws_onopen;
|
||||
this.ws.onclose = this.ws_onclose;
|
||||
this.ws.onmessage = this.ws_onmessage;
|
||||
this.ws.m = this;
|
||||
this.ws.onerror = function(evt){
|
||||
alert(evt.data);
|
||||
}
|
||||
},
|
||||
|
||||
disconnect : function(){
|
||||
if(this.ws.readyState == 1){
|
||||
var buffer = new ArrayBuffer(2);
|
||||
var i8V = new Int8Array(buffer);
|
||||
|
||||
i8V[0] = DISCONNECT;
|
||||
i8V[1] = 0;
|
||||
this.ws.send(buffer);
|
||||
this.ws.close();
|
||||
}
|
||||
},
|
||||
|
||||
ws_onopen : function(evt) {
|
||||
var buffer = new ArrayBuffer(1+1+12+2+20);
|
||||
var i8V = new Int8Array(buffer);
|
||||
|
||||
i=0;
|
||||
i8V[i++] = CONNECT;
|
||||
i8V[i++] = 12+2+20;
|
||||
i8V[i++] = 0;
|
||||
i8V[i++] = 6;
|
||||
str = "MQIsdp";
|
||||
for(var j=0; j<str.length; j++){
|
||||
i8V[i++] = str.charCodeAt(j);
|
||||
}
|
||||
i8V[i++] = 3;
|
||||
i8V[i++] = 2;
|
||||
i8V[i++] = 0;
|
||||
i8V[i++] = 60;
|
||||
i8V[i++] = 0;
|
||||
i8V[i++] = 20;
|
||||
var str = "mjsws/";
|
||||
for(var j=0; j<str.length; j++){
|
||||
i8V[i++] = str.charCodeAt(j);
|
||||
}
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
for(var j=0; j<14; j++){
|
||||
i8V[i++] = chars.charCodeAt(Math.floor(Math.random()*chars.length));
|
||||
}
|
||||
|
||||
this.send(buffer);
|
||||
while(this.m.out_queue.length > 0){
|
||||
this.send(this.m.out_queue.pop());
|
||||
}
|
||||
setTimeout(function(_this){_this.mqtt_ping();}, 60000, this.m);
|
||||
},
|
||||
|
||||
ws_onclose : function(evt) {
|
||||
if(this.m.ondisconnect){
|
||||
this.m.ondisconnect(evt.data);
|
||||
}
|
||||
},
|
||||
|
||||
ws_onmessage : function(evt) {
|
||||
var i8V = new Int8Array(evt.data);
|
||||
buffer = evt.data;
|
||||
var q=0;
|
||||
while(i8V.length > 0 && q < 1000){
|
||||
q++;
|
||||
switch(i8V[0] & 0xF0){
|
||||
case CONNACK:
|
||||
var rl = i8V[1];
|
||||
var rc = i8V[2];
|
||||
if(this.m.onconnect){
|
||||
this.m.onconnect(rc);
|
||||
}
|
||||
buffer = buffer.slice(rl+2);
|
||||
i8V = new Int8Array(buffer);
|
||||
break;
|
||||
case PUBLISH:
|
||||
var i=1;
|
||||
var mult = 1;
|
||||
var rl = 0;
|
||||
var count = 0;
|
||||
var digit;
|
||||
var qos = (i8V[0] & 0x06) >> 1;
|
||||
var retain = (i8V[0] & 0x01);
|
||||
var mid = 0;
|
||||
do{
|
||||
count++;
|
||||
digit = i8V[i++];
|
||||
rl += (digit & 127)*mult;
|
||||
mult *= 128;
|
||||
}while((digit & 128) != 0);
|
||||
|
||||
var topiclen = i8V[i++]*256 + i8V[i++];
|
||||
var atopic = buffer.slice(i, i+topiclen);
|
||||
i+=topiclen;
|
||||
var topic = AB2S(atopic);
|
||||
if(qos > 0){
|
||||
mid = i8V[i++]*256 + i8V[i++];
|
||||
}
|
||||
var apayload = buffer.slice(i, rl+count+1);
|
||||
var payload = AB2S(apayload);
|
||||
|
||||
buffer = buffer.slice(rl+1+count);
|
||||
i8V = new Int8Array(buffer);
|
||||
|
||||
if(this.m.onmessage){
|
||||
this.m.onmessage(topic, payload, qos, retain);
|
||||
}
|
||||
break;
|
||||
case PUBREC:
|
||||
case PUBREL:
|
||||
case PUBACK:
|
||||
case PUBCOMP:
|
||||
case SUBACK:
|
||||
case UNSUBACK:
|
||||
case PINGRESP:
|
||||
var rl = i8V[1];
|
||||
buffer = buffer.slice(rl+2);
|
||||
i8V = new Int8Array(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get_remaining_count : function(remaining_length)
|
||||
{
|
||||
if(remaining_length >= 0 && remaining_length < 128){
|
||||
return 1;
|
||||
}else if(remaining_length >= 128 && remaining_length < 16384){
|
||||
return 2;
|
||||
}else if(remaining_length >= 16384 && remaining_length < 2097152){
|
||||
return 3;
|
||||
}else if(remaining_length >= 2097152 && remaining_length < 268435456){
|
||||
return 4;
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
},
|
||||
|
||||
generate_mid : function()
|
||||
{
|
||||
var mid = this.mid;
|
||||
this.mid++;
|
||||
if(this.mid == 256) this.mid = 0;
|
||||
return mid;
|
||||
},
|
||||
|
||||
queue : function(buffer)
|
||||
{
|
||||
this.out_queue.push(buffer);
|
||||
},
|
||||
|
||||
send_cmd_with_mid : function(cmd, mid)
|
||||
{
|
||||
var buffer = new ArrayBuffer(4);
|
||||
var i8V = new Int8Array(buffer);
|
||||
i8V[0] = cmd;
|
||||
i8V[1] = 2;
|
||||
i8V[2] = mid%128;
|
||||
i8V[3] = mid/128;
|
||||
if(this.ws.readyState == 1){
|
||||
this.ws.send(buffer);
|
||||
}else{
|
||||
this.queue(buffer);
|
||||
}
|
||||
},
|
||||
|
||||
unsubscribe : function(topic)
|
||||
{
|
||||
var rl = 2+2+topic.length;
|
||||
var remaining_count = this.get_remaining_count(rl);
|
||||
var buffer = new ArrayBuffer(1+remaining_count+rl);
|
||||
var i8V = new Int8Array(buffer);
|
||||
|
||||
var i=0;
|
||||
i8V[i++] = UNSUBSCRIBE | 0x02;
|
||||
do{
|
||||
digit = Math.floor(rl % 128);
|
||||
rl = Math.floor(rl / 128);
|
||||
if(rl > 0){
|
||||
digit = digit | 0x80;
|
||||
}
|
||||
i8V[i++] = digit;
|
||||
}while(rl > 0);
|
||||
i8V[i++] = 0;
|
||||
i8V[i++] = this.generate_mid();
|
||||
i8V[i++] = 0;
|
||||
i8V[i++] = topic.length;
|
||||
for(var j=0; j<topic.length; j++){
|
||||
i8V[i++] = topic.charCodeAt(j);
|
||||
}
|
||||
|
||||
if(this.ws.readyState == 1){
|
||||
this.ws.send(buffer);
|
||||
}else{
|
||||
this.queue(buffer);
|
||||
}
|
||||
},
|
||||
|
||||
subscribe : function(topic, qos)
|
||||
{
|
||||
if(qos != 0){
|
||||
return 1;
|
||||
}
|
||||
var rl = 2+2+topic.length+1;
|
||||
var remaining_count = this.get_remaining_count(rl);
|
||||
var buffer = new ArrayBuffer(1+remaining_count+rl);
|
||||
var i8V = new Int8Array(buffer);
|
||||
|
||||
var i=0;
|
||||
i8V[i++] = SUBSCRIBE | 0x02;
|
||||
do{
|
||||
digit = Math.floor(rl % 128);
|
||||
rl = Math.floor(rl / 128);
|
||||
if(rl > 0){
|
||||
digit = digit | 0x80;
|
||||
}
|
||||
i8V[i++] = digit;
|
||||
}while(rl > 0);
|
||||
i8V[i++] = 0;
|
||||
i8V[i++] = this.generate_mid();
|
||||
i8V[i++] = 0;
|
||||
i8V[i++] = topic.length;
|
||||
for(var j=0; j<topic.length; j++){
|
||||
i8V[i++] = topic.charCodeAt(j);
|
||||
}
|
||||
i8V[i++] = qos;
|
||||
|
||||
if(this.ws.readyState == 1){
|
||||
this.ws.send(buffer);
|
||||
}else{
|
||||
this.queue(buffer);
|
||||
}
|
||||
},
|
||||
|
||||
publish : function(topic, payload, qos, retain){
|
||||
if(qos != 0) return 1;
|
||||
var rl = 2+topic.length+payload.length;
|
||||
var remaining_count = this.get_remaining_count(rl);
|
||||
var buffer = new ArrayBuffer(1+remaining_count+rl);
|
||||
var i8V = new Int8Array(buffer);
|
||||
|
||||
var i=0;
|
||||
retain = retain?1:0;
|
||||
i8V[i++] = PUBLISH | (qos<<1) | retain;
|
||||
do{
|
||||
digit = Math.floor(rl % 128);
|
||||
rl = Math.floor(rl / 128);
|
||||
if(rl > 0){
|
||||
digit = digit | 0x80;
|
||||
}
|
||||
i8V[i++] = digit;
|
||||
}while(rl > 0);
|
||||
i8V[i++] = 0;
|
||||
i8V[i++] = topic.length;
|
||||
for(var j=0; j<topic.length; j++){
|
||||
i8V[i++] = topic.charCodeAt(j);
|
||||
}
|
||||
for(var j=0; j<payload.length; j++){
|
||||
i8V[i++] = payload.charCodeAt(j);
|
||||
}
|
||||
|
||||
if(this.ws.readyState == 1){
|
||||
this.ws.send(buffer);
|
||||
}else{
|
||||
this.queue(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
71
lib/linker.version
Normal file
71
lib/linker.version
Normal file
@ -0,0 +1,71 @@
|
||||
/* Linker version script - currently used here primarily to control which
|
||||
* symbols are exported.
|
||||
*/
|
||||
|
||||
MOSQ_1.0 {
|
||||
global:
|
||||
mosquitto_lib_version;
|
||||
mosquitto_lib_init;
|
||||
mosquitto_lib_cleanup;
|
||||
mosquitto_new;
|
||||
mosquitto_destroy;
|
||||
mosquitto_reinitialise;
|
||||
mosquitto_will_set;
|
||||
mosquitto_will_clear;
|
||||
mosquitto_username_pw_set;
|
||||
mosquitto_connect;
|
||||
mosquitto_connect_async;
|
||||
mosquitto_reconnect;
|
||||
mosquitto_disconnect;
|
||||
mosquitto_publish;
|
||||
mosquitto_subscribe;
|
||||
mosquitto_unsubscribe;
|
||||
mosquitto_message_copy;
|
||||
mosquitto_message_free;
|
||||
mosquitto_loop;
|
||||
mosquitto_socket;
|
||||
mosquitto_loop_start;
|
||||
mosquitto_loop_stop;
|
||||
mosquitto_loop_read;
|
||||
mosquitto_loop_write;
|
||||
mosquitto_loop_misc;
|
||||
mosquitto_connect_callback_set;
|
||||
mosquitto_disconnect_callback_set;
|
||||
mosquitto_publish_callback_set;
|
||||
mosquitto_message_callback_set;
|
||||
mosquitto_subscribe_callback_set;
|
||||
mosquitto_unsubscribe_callback_set;
|
||||
mosquitto_log_callback_set;
|
||||
mosquitto_message_retry_set;
|
||||
mosquitto_want_write;
|
||||
mosquitto_user_data_set;
|
||||
mosquitto_strerror;
|
||||
mosquitto_connack_string;
|
||||
mosquitto_tls_set;
|
||||
mosquitto_tls_opts_set;
|
||||
mosquitto_tls_psk_set;
|
||||
mosquitto_sub_topic_tokenise;
|
||||
mosquitto_sub_topic_tokens_free;
|
||||
mosquitto_topic_matches_sub;
|
||||
local: *;
|
||||
};
|
||||
|
||||
MOSQ_1.1 {
|
||||
global:
|
||||
mosquitto_loop_forever;
|
||||
} MOSQ_1.0;
|
||||
|
||||
MOSQ_1.2 {
|
||||
global:
|
||||
mosquitto_connect_bind;
|
||||
mosquitto_connect_bind_async;
|
||||
mosquitto_max_inflight_messages_set;
|
||||
mosquitto_reconnect_delay_set;
|
||||
mosquitto_reconnect_async;
|
||||
mosquitto_tls_insecure_set;
|
||||
} MOSQ_1.1;
|
||||
|
||||
MOSQ_1.3 {
|
||||
global:
|
||||
mosquitto_connect_srv;
|
||||
} MOSQ_1.2;
|
56
lib/logging_mosq.c
Normal file
56
lib/logging_mosq.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mosquitto_internal.h>
|
||||
#include <mosquitto.h>
|
||||
#include <memory_mosq.h>
|
||||
|
||||
int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
char *s;
|
||||
int len;
|
||||
|
||||
assert(mosq);
|
||||
assert(fmt);
|
||||
|
||||
pthread_mutex_lock(&mosq->log_callback_mutex);
|
||||
if(mosq->on_log){
|
||||
len = strlen(fmt) + 500;
|
||||
s = _mosquitto_malloc(len*sizeof(char));
|
||||
if(!s){
|
||||
pthread_mutex_unlock(&mosq->log_callback_mutex);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
|
||||
va_start(va, fmt);
|
||||
vsnprintf(s, len, fmt, va);
|
||||
va_end(va);
|
||||
s[len-1] = '\0'; /* Ensure string is null terminated. */
|
||||
|
||||
mosq->on_log(mosq, mosq->userdata, priority, s);
|
||||
|
||||
_mosquitto_free(s);
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->log_callback_mutex);
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
23
lib/logging_mosq.h
Normal file
23
lib/logging_mosq.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
#ifndef _LOGGING_MOSQ_H_
|
||||
#define _LOGGING_MOSQ_H_
|
||||
|
||||
#include <mosquitto.h>
|
||||
|
||||
int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...);
|
||||
|
||||
#endif
|
121
lib/memory_mosq.c
Normal file
121
lib/memory_mosq.c
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <memory_mosq.h>
|
||||
|
||||
#ifdef REAL_WITH_MEMORY_TRACKING
|
||||
# if defined(__APPLE__)
|
||||
# include <malloc/malloc.h>
|
||||
# define malloc_usable_size malloc_size
|
||||
# elif defined(__FreeBSD__)
|
||||
# include <malloc_np.h>
|
||||
# else
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef REAL_WITH_MEMORY_TRACKING
|
||||
static unsigned long memcount = 0;
|
||||
static unsigned long max_memcount = 0;
|
||||
#endif
|
||||
|
||||
void *_mosquitto_calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *mem = calloc(nmemb, size);
|
||||
|
||||
#ifdef REAL_WITH_MEMORY_TRACKING
|
||||
memcount += malloc_usable_size(mem);
|
||||
if(memcount > max_memcount){
|
||||
max_memcount = memcount;
|
||||
}
|
||||
#endif
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
void _mosquitto_free(void *mem)
|
||||
{
|
||||
#ifdef REAL_WITH_MEMORY_TRACKING
|
||||
memcount -= malloc_usable_size(mem);
|
||||
#endif
|
||||
free(mem);
|
||||
}
|
||||
|
||||
void *_mosquitto_malloc(size_t size)
|
||||
{
|
||||
void *mem = malloc(size);
|
||||
|
||||
#ifdef REAL_WITH_MEMORY_TRACKING
|
||||
memcount += malloc_usable_size(mem);
|
||||
if(memcount > max_memcount){
|
||||
max_memcount = memcount;
|
||||
}
|
||||
#endif
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
#ifdef REAL_WITH_MEMORY_TRACKING
|
||||
unsigned long _mosquitto_memory_used(void)
|
||||
{
|
||||
return memcount;
|
||||
}
|
||||
|
||||
unsigned long _mosquitto_max_memory_used(void)
|
||||
{
|
||||
return max_memcount;
|
||||
}
|
||||
#endif
|
||||
|
||||
void *_mosquitto_realloc(void *ptr, size_t size)
|
||||
{
|
||||
void *mem;
|
||||
#ifdef REAL_WITH_MEMORY_TRACKING
|
||||
if(ptr){
|
||||
memcount -= malloc_usable_size(ptr);
|
||||
}
|
||||
#endif
|
||||
mem = realloc(ptr, size);
|
||||
|
||||
#ifdef REAL_WITH_MEMORY_TRACKING
|
||||
memcount += malloc_usable_size(mem);
|
||||
if(memcount > max_memcount){
|
||||
max_memcount = memcount;
|
||||
}
|
||||
#endif
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
char *_mosquitto_strdup(const char *s)
|
||||
{
|
||||
char *str = strdup(s);
|
||||
|
||||
#ifdef REAL_WITH_MEMORY_TRACKING
|
||||
memcount += malloc_usable_size(str);
|
||||
if(memcount > max_memcount){
|
||||
max_memcount = memcount;
|
||||
}
|
||||
#endif
|
||||
|
||||
return str;
|
||||
}
|
||||
|
37
lib/memory_mosq.h
Normal file
37
lib/memory_mosq.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifndef _MEMORY_MOSQ_H_
|
||||
#define _MEMORY_MOSQ_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(WITH_MEMORY_TRACKING) && defined(WITH_BROKER) && !defined(WIN32) && !defined(__SYMBIAN32__)
|
||||
#define REAL_WITH_MEMORY_TRACKING
|
||||
#endif
|
||||
|
||||
void *_mosquitto_calloc(size_t nmemb, size_t size);
|
||||
void _mosquitto_free(void *mem);
|
||||
void *_mosquitto_malloc(size_t size);
|
||||
#ifdef REAL_WITH_MEMORY_TRACKING
|
||||
unsigned long _mosquitto_memory_used(void);
|
||||
unsigned long _mosquitto_max_memory_used(void);
|
||||
#endif
|
||||
void *_mosquitto_realloc(void *ptr, size_t size);
|
||||
char *_mosquitto_strdup(const char *s);
|
||||
|
||||
#endif
|
387
lib/messages_mosq.c
Normal file
387
lib/messages_mosq.c
Normal file
@ -0,0 +1,387 @@
|
||||
/*
|
||||
Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mosquitto_internal.h>
|
||||
#include <mosquitto.h>
|
||||
#include <memory_mosq.h>
|
||||
#include <messages_mosq.h>
|
||||
#include <send_mosq.h>
|
||||
#include <time_mosq.h>
|
||||
|
||||
void _mosquitto_message_cleanup(struct mosquitto_message_all **message)
|
||||
{
|
||||
struct mosquitto_message_all *msg;
|
||||
|
||||
if(!message || !*message) return;
|
||||
|
||||
msg = *message;
|
||||
|
||||
if(msg->msg.topic) _mosquitto_free(msg->msg.topic);
|
||||
if(msg->msg.payload) _mosquitto_free(msg->msg.payload);
|
||||
_mosquitto_free(msg);
|
||||
}
|
||||
|
||||
void _mosquitto_message_cleanup_all(struct mosquitto *mosq)
|
||||
{
|
||||
struct mosquitto_message_all *tmp;
|
||||
|
||||
assert(mosq);
|
||||
|
||||
while(mosq->in_messages){
|
||||
tmp = mosq->in_messages->next;
|
||||
_mosquitto_message_cleanup(&mosq->in_messages);
|
||||
mosq->in_messages = tmp;
|
||||
}
|
||||
while(mosq->out_messages){
|
||||
tmp = mosq->out_messages->next;
|
||||
_mosquitto_message_cleanup(&mosq->out_messages);
|
||||
mosq->out_messages = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
int mosquitto_message_copy(struct mosquitto_message *dst, const struct mosquitto_message *src)
|
||||
{
|
||||
if(!dst || !src) return MOSQ_ERR_INVAL;
|
||||
|
||||
dst->mid = src->mid;
|
||||
dst->topic = _mosquitto_strdup(src->topic);
|
||||
if(!dst->topic) return MOSQ_ERR_NOMEM;
|
||||
dst->qos = src->qos;
|
||||
dst->retain = src->retain;
|
||||
if(src->payloadlen){
|
||||
dst->payload = _mosquitto_malloc(src->payloadlen);
|
||||
if(!dst->payload){
|
||||
_mosquitto_free(dst->topic);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
memcpy(dst->payload, src->payload, src->payloadlen);
|
||||
dst->payloadlen = src->payloadlen;
|
||||
}else{
|
||||
dst->payloadlen = 0;
|
||||
dst->payload = NULL;
|
||||
}
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int _mosquitto_message_delete(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir)
|
||||
{
|
||||
struct mosquitto_message_all *message;
|
||||
int rc;
|
||||
assert(mosq);
|
||||
|
||||
rc = _mosquitto_message_remove(mosq, mid, dir, &message);
|
||||
if(rc == MOSQ_ERR_SUCCESS){
|
||||
_mosquitto_message_cleanup(&message);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void mosquitto_message_free(struct mosquitto_message **message)
|
||||
{
|
||||
struct mosquitto_message *msg;
|
||||
|
||||
if(!message || !*message) return;
|
||||
|
||||
msg = *message;
|
||||
|
||||
if(msg->topic) _mosquitto_free(msg->topic);
|
||||
if(msg->payload) _mosquitto_free(msg->payload);
|
||||
_mosquitto_free(msg);
|
||||
}
|
||||
|
||||
void _mosquitto_message_queue(struct mosquitto *mosq, struct mosquitto_message_all *message, enum mosquitto_msg_direction dir)
|
||||
{
|
||||
/* mosq->*_message_mutex should be locked before entering this function */
|
||||
assert(mosq);
|
||||
assert(message);
|
||||
|
||||
if(dir == mosq_md_out){
|
||||
mosq->out_queue_len++;
|
||||
message->next = NULL;
|
||||
if(mosq->out_messages_last){
|
||||
mosq->out_messages_last->next = message;
|
||||
}else{
|
||||
mosq->out_messages = message;
|
||||
}
|
||||
mosq->out_messages_last = message;
|
||||
}else{
|
||||
mosq->in_queue_len++;
|
||||
if(message->msg.qos > 0 && (mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages)){
|
||||
mosq->inflight_messages++;
|
||||
}
|
||||
message->next = NULL;
|
||||
if(mosq->in_messages_last){
|
||||
mosq->in_messages_last->next = message;
|
||||
}else{
|
||||
mosq->in_messages = message;
|
||||
}
|
||||
mosq->in_messages_last = message;
|
||||
}
|
||||
}
|
||||
|
||||
void _mosquitto_messages_reconnect_reset(struct mosquitto *mosq)
|
||||
{
|
||||
struct mosquitto_message_all *message;
|
||||
struct mosquitto_message_all *prev = NULL;
|
||||
assert(mosq);
|
||||
|
||||
pthread_mutex_lock(&mosq->in_message_mutex);
|
||||
message = mosq->in_messages;
|
||||
mosq->in_queue_len = 0;
|
||||
while(message){
|
||||
mosq->in_queue_len++;
|
||||
message->timestamp = 0;
|
||||
if(message->msg.qos != 2){
|
||||
if(prev){
|
||||
prev->next = message->next;
|
||||
_mosquitto_message_cleanup(&message);
|
||||
message = prev;
|
||||
}else{
|
||||
mosq->in_messages = message->next;
|
||||
_mosquitto_message_cleanup(&message);
|
||||
message = mosq->in_messages;
|
||||
}
|
||||
}else{
|
||||
/* Message state can be preserved here because it should match
|
||||
* whatever the client has got. */
|
||||
}
|
||||
prev = message;
|
||||
message = message->next;
|
||||
}
|
||||
mosq->in_messages_last = prev;
|
||||
pthread_mutex_unlock(&mosq->in_message_mutex);
|
||||
|
||||
|
||||
pthread_mutex_lock(&mosq->out_message_mutex);
|
||||
mosq->inflight_messages = 0;
|
||||
message = mosq->out_messages;
|
||||
mosq->out_queue_len = 0;
|
||||
while(message){
|
||||
mosq->out_queue_len++;
|
||||
message->timestamp = 0;
|
||||
|
||||
if(message->msg.qos > 0){
|
||||
mosq->inflight_messages++;
|
||||
}
|
||||
if(mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages){
|
||||
if(message->msg.qos == 1){
|
||||
message->state = mosq_ms_wait_for_puback;
|
||||
}else if(message->msg.qos == 2){
|
||||
/* Should be able to preserve state. */
|
||||
}
|
||||
}else{
|
||||
message->state = mosq_ms_invalid;
|
||||
}
|
||||
prev = message;
|
||||
message = message->next;
|
||||
}
|
||||
mosq->out_messages_last = prev;
|
||||
pthread_mutex_unlock(&mosq->out_message_mutex);
|
||||
}
|
||||
|
||||
int _mosquitto_message_remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, struct mosquitto_message_all **message)
|
||||
{
|
||||
struct mosquitto_message_all *cur, *prev = NULL;
|
||||
bool found = false;
|
||||
int rc;
|
||||
assert(mosq);
|
||||
assert(message);
|
||||
|
||||
if(dir == mosq_md_out){
|
||||
pthread_mutex_lock(&mosq->out_message_mutex);
|
||||
cur = mosq->out_messages;
|
||||
while(cur){
|
||||
if(cur->msg.mid == mid){
|
||||
if(prev){
|
||||
prev->next = cur->next;
|
||||
}else{
|
||||
mosq->out_messages = cur->next;
|
||||
}
|
||||
*message = cur;
|
||||
mosq->out_queue_len--;
|
||||
if(cur->next == NULL){
|
||||
mosq->out_messages_last = prev;
|
||||
}else if(!mosq->out_messages){
|
||||
mosq->out_messages_last = NULL;
|
||||
}
|
||||
if(cur->msg.qos > 0){
|
||||
mosq->inflight_messages--;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if(found){
|
||||
cur = mosq->out_messages;
|
||||
while(cur){
|
||||
if(mosq->max_inflight_messages == 0 || mosq->inflight_messages < mosq->max_inflight_messages){
|
||||
if(cur->msg.qos > 0 && cur->state == mosq_ms_invalid){
|
||||
mosq->inflight_messages++;
|
||||
if(cur->msg.qos == 1){
|
||||
cur->state = mosq_ms_wait_for_puback;
|
||||
}else if(cur->msg.qos == 2){
|
||||
cur->state = mosq_ms_wait_for_pubrec;
|
||||
}
|
||||
rc = _mosquitto_send_publish(mosq, cur->msg.mid, cur->msg.topic, cur->msg.payloadlen, cur->msg.payload, cur->msg.qos, cur->msg.retain, cur->dup);
|
||||
if(rc){
|
||||
pthread_mutex_unlock(&mosq->out_message_mutex);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
pthread_mutex_unlock(&mosq->out_message_mutex);
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->out_message_mutex);
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else{
|
||||
pthread_mutex_unlock(&mosq->out_message_mutex);
|
||||
return MOSQ_ERR_NOT_FOUND;
|
||||
}
|
||||
}else{
|
||||
pthread_mutex_lock(&mosq->in_message_mutex);
|
||||
cur = mosq->in_messages;
|
||||
while(cur){
|
||||
if(cur->msg.mid == mid){
|
||||
if(prev){
|
||||
prev->next = cur->next;
|
||||
}else{
|
||||
mosq->in_messages = cur->next;
|
||||
}
|
||||
*message = cur;
|
||||
mosq->in_queue_len--;
|
||||
if(cur->next == NULL){
|
||||
mosq->in_messages_last = prev;
|
||||
}else if(!mosq->in_messages){
|
||||
mosq->in_messages_last = NULL;
|
||||
}
|
||||
if(cur->msg.qos == 2){
|
||||
mosq->inflight_messages--;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mosq->in_message_mutex);
|
||||
if(found){
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else{
|
||||
return MOSQ_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_THREADING
|
||||
void _mosquitto_message_retry_check_actual(struct mosquitto *mosq, struct mosquitto_message_all *messages, pthread_mutex_t mutex)
|
||||
#else
|
||||
void _mosquitto_message_retry_check_actual(struct mosquitto *mosq, struct mosquitto_message_all *messages)
|
||||
#endif
|
||||
{
|
||||
time_t now = mosquitto_time();
|
||||
assert(mosq);
|
||||
|
||||
#ifdef WITH_THREADING
|
||||
pthread_mutex_lock(&mutex);
|
||||
#endif
|
||||
|
||||
while(messages){
|
||||
if(messages->timestamp + mosq->message_retry < now){
|
||||
switch(messages->state){
|
||||
case mosq_ms_wait_for_puback:
|
||||
case mosq_ms_wait_for_pubrec:
|
||||
messages->timestamp = now;
|
||||
messages->dup = true;
|
||||
_mosquitto_send_publish(mosq, messages->msg.mid, messages->msg.topic, messages->msg.payloadlen, messages->msg.payload, messages->msg.qos, messages->msg.retain, messages->dup);
|
||||
break;
|
||||
case mosq_ms_wait_for_pubrel:
|
||||
messages->timestamp = now;
|
||||
messages->dup = true;
|
||||
_mosquitto_send_pubrec(mosq, messages->msg.mid);
|
||||
break;
|
||||
case mosq_ms_wait_for_pubcomp:
|
||||
messages->timestamp = now;
|
||||
messages->dup = true;
|
||||
_mosquitto_send_pubrel(mosq, messages->msg.mid, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
messages = messages->next;
|
||||
}
|
||||
#ifdef WITH_THREADING
|
||||
pthread_mutex_unlock(&mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void _mosquitto_message_retry_check(struct mosquitto *mosq)
|
||||
{
|
||||
#ifdef WITH_THREADING
|
||||
_mosquitto_message_retry_check_actual(mosq, mosq->out_messages, mosq->out_message_mutex);
|
||||
_mosquitto_message_retry_check_actual(mosq, mosq->in_messages, mosq->in_message_mutex);
|
||||
#else
|
||||
_mosquitto_message_retry_check_actual(mosq, mosq->out_messages);
|
||||
_mosquitto_message_retry_check_actual(mosq, mosq->in_messages);
|
||||
#endif
|
||||
}
|
||||
|
||||
void mosquitto_message_retry_set(struct mosquitto *mosq, unsigned int message_retry)
|
||||
{
|
||||
assert(mosq);
|
||||
if(mosq) mosq->message_retry = message_retry;
|
||||
}
|
||||
|
||||
int _mosquitto_message_out_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_state state)
|
||||
{
|
||||
struct mosquitto_message_all *message;
|
||||
assert(mosq);
|
||||
|
||||
pthread_mutex_lock(&mosq->out_message_mutex);
|
||||
message = mosq->out_messages;
|
||||
while(message){
|
||||
if(message->msg.mid == mid){
|
||||
message->state = state;
|
||||
message->timestamp = mosquitto_time();
|
||||
pthread_mutex_unlock(&mosq->out_message_mutex);
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
message = message->next;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->out_message_mutex);
|
||||
return MOSQ_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
int mosquitto_max_inflight_messages_set(struct mosquitto *mosq, unsigned int max_inflight_messages)
|
||||
{
|
||||
if(!mosq) return MOSQ_ERR_INVAL;
|
||||
|
||||
mosq->max_inflight_messages = max_inflight_messages;
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
31
lib/messages_mosq.h
Normal file
31
lib/messages_mosq.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
#ifndef _MESSAGES_MOSQ_H_
|
||||
#define _MESSAGES_MOSQ_H_
|
||||
|
||||
#include <mosquitto_internal.h>
|
||||
#include <mosquitto.h>
|
||||
|
||||
void _mosquitto_message_cleanup_all(struct mosquitto *mosq);
|
||||
void _mosquitto_message_cleanup(struct mosquitto_message_all **message);
|
||||
int _mosquitto_message_delete(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir);
|
||||
void _mosquitto_message_queue(struct mosquitto *mosq, struct mosquitto_message_all *message, enum mosquitto_msg_direction dir);
|
||||
void _mosquitto_messages_reconnect_reset(struct mosquitto *mosq);
|
||||
int _mosquitto_message_remove(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, struct mosquitto_message_all **message);
|
||||
void _mosquitto_message_retry_check(struct mosquitto *mosq);
|
||||
int _mosquitto_message_out_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_state state);
|
||||
|
||||
#endif
|
1293
lib/mosquitto.c
Normal file
1293
lib/mosquitto.c
Normal file
File diff suppressed because it is too large
Load Diff
1409
lib/mosquitto.h
Normal file
1409
lib/mosquitto.h
Normal file
File diff suppressed because it is too large
Load Diff
230
lib/mosquitto_internal.h
Normal file
230
lib/mosquitto_internal.h
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifndef _MOSQUITTO_INTERNAL_H_
|
||||
#define _MOSQUITTO_INTERNAL_H_
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef WIN32
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_TLS
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(WITH_THREADING) && !defined(WITH_BROKER)
|
||||
# include <pthread.h>
|
||||
#else
|
||||
# include <dummypthread.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SRV
|
||||
# include <ares.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# if _MSC_VER < 1600
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
# else
|
||||
# include <stdint.h>
|
||||
# endif
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "mosquitto.h"
|
||||
#include "time_mosq.h"
|
||||
#ifdef WITH_BROKER
|
||||
struct mosquitto_client_msg;
|
||||
#endif
|
||||
|
||||
enum mosquitto_msg_direction {
|
||||
mosq_md_in = 0,
|
||||
mosq_md_out = 1
|
||||
};
|
||||
|
||||
enum mosquitto_msg_state {
|
||||
mosq_ms_invalid = 0,
|
||||
mosq_ms_publish_qos0 = 1,
|
||||
mosq_ms_publish_qos1 = 2,
|
||||
mosq_ms_wait_for_puback = 3,
|
||||
mosq_ms_publish_qos2 = 4,
|
||||
mosq_ms_wait_for_pubrec = 5,
|
||||
mosq_ms_resend_pubrel = 6,
|
||||
mosq_ms_wait_for_pubrel = 7,
|
||||
mosq_ms_resend_pubcomp = 8,
|
||||
mosq_ms_wait_for_pubcomp = 9,
|
||||
mosq_ms_send_pubrec = 10,
|
||||
mosq_ms_queued = 11
|
||||
};
|
||||
|
||||
enum mosquitto_client_state {
|
||||
mosq_cs_new = 0,
|
||||
mosq_cs_connected = 1,
|
||||
mosq_cs_disconnecting = 2,
|
||||
mosq_cs_connect_async = 3,
|
||||
mosq_cs_connect_pending = 4,
|
||||
mosq_cs_connect_srv = 5
|
||||
};
|
||||
|
||||
enum _mosquitto_protocol {
|
||||
mosq_p_invalid = 0,
|
||||
mosq_p_mqtt31 = 1,
|
||||
mosq_p_mqtt311 = 2,
|
||||
mosq_p_mqtts = 3
|
||||
};
|
||||
|
||||
enum _mosquitto_transport {
|
||||
mosq_t_invalid = 0,
|
||||
mosq_t_tcp = 1,
|
||||
mosq_t_ws = 2,
|
||||
mosq_t_sctp = 3
|
||||
};
|
||||
|
||||
struct _mosquitto_packet{
|
||||
uint8_t command;
|
||||
uint8_t have_remaining;
|
||||
uint8_t remaining_count;
|
||||
uint16_t mid;
|
||||
uint32_t remaining_mult;
|
||||
uint32_t remaining_length;
|
||||
uint32_t packet_length;
|
||||
uint32_t to_process;
|
||||
uint32_t pos;
|
||||
uint8_t *payload;
|
||||
struct _mosquitto_packet *next;
|
||||
};
|
||||
|
||||
struct mosquitto_message_all{
|
||||
struct mosquitto_message_all *next;
|
||||
time_t timestamp;
|
||||
//enum mosquitto_msg_direction direction;
|
||||
enum mosquitto_msg_state state;
|
||||
bool dup;
|
||||
struct mosquitto_message msg;
|
||||
};
|
||||
|
||||
struct mosquitto {
|
||||
#ifndef WIN32
|
||||
int sock;
|
||||
# ifndef WITH_BROKER
|
||||
int sockpairR, sockpairW;
|
||||
# endif
|
||||
#else
|
||||
SOCKET sock;
|
||||
# ifndef WITH_BROKER
|
||||
SOCKET sockpairR, sockpairW;
|
||||
# endif
|
||||
#endif
|
||||
enum _mosquitto_protocol protocol;
|
||||
char *address;
|
||||
char *id;
|
||||
char *username;
|
||||
char *password;
|
||||
uint16_t keepalive;
|
||||
bool clean_session;
|
||||
enum mosquitto_client_state state;
|
||||
time_t last_msg_in;
|
||||
time_t last_msg_out;
|
||||
time_t ping_t;
|
||||
uint16_t last_mid;
|
||||
struct _mosquitto_packet in_packet;
|
||||
struct _mosquitto_packet *current_out_packet;
|
||||
struct _mosquitto_packet *out_packet;
|
||||
struct mosquitto_message *will;
|
||||
#ifdef WITH_TLS
|
||||
SSL *ssl;
|
||||
SSL_CTX *ssl_ctx;
|
||||
char *tls_cafile;
|
||||
char *tls_capath;
|
||||
char *tls_certfile;
|
||||
char *tls_keyfile;
|
||||
int (*tls_pw_callback)(char *buf, int size, int rwflag, void *userdata);
|
||||
int tls_cert_reqs;
|
||||
char *tls_version;
|
||||
char *tls_ciphers;
|
||||
char *tls_psk;
|
||||
char *tls_psk_identity;
|
||||
bool tls_insecure;
|
||||
#endif
|
||||
bool want_write;
|
||||
#if defined(WITH_THREADING) && !defined(WITH_BROKER)
|
||||
pthread_mutex_t callback_mutex;
|
||||
pthread_mutex_t log_callback_mutex;
|
||||
pthread_mutex_t msgtime_mutex;
|
||||
pthread_mutex_t out_packet_mutex;
|
||||
pthread_mutex_t current_out_packet_mutex;
|
||||
pthread_mutex_t state_mutex;
|
||||
pthread_mutex_t in_message_mutex;
|
||||
pthread_mutex_t out_message_mutex;
|
||||
pthread_t thread_id;
|
||||
#endif
|
||||
#ifdef WITH_BROKER
|
||||
bool is_bridge;
|
||||
struct _mqtt3_bridge *bridge;
|
||||
struct mosquitto_client_msg *msgs;
|
||||
struct mosquitto_client_msg *last_msg;
|
||||
int msg_count;
|
||||
int msg_count12;
|
||||
struct _mosquitto_acl_user *acl_list;
|
||||
struct _mqtt3_listener *listener;
|
||||
time_t disconnect_t;
|
||||
int pollfd_index;
|
||||
int db_index;
|
||||
struct _mosquitto_packet *out_packet_last;
|
||||
bool is_dropping;
|
||||
#else
|
||||
void *userdata;
|
||||
bool in_callback;
|
||||
unsigned int message_retry;
|
||||
time_t last_retry_check;
|
||||
struct mosquitto_message_all *in_messages;
|
||||
struct mosquitto_message_all *in_messages_last;
|
||||
struct mosquitto_message_all *out_messages;
|
||||
struct mosquitto_message_all *out_messages_last;
|
||||
void (*on_connect)(struct mosquitto *, void *userdata, int rc);
|
||||
void (*on_disconnect)(struct mosquitto *, void *userdata, int rc);
|
||||
void (*on_publish)(struct mosquitto *, void *userdata, int mid);
|
||||
void (*on_message)(struct mosquitto *, void *userdata, const struct mosquitto_message *message);
|
||||
void (*on_subscribe)(struct mosquitto *, void *userdata, int mid, int qos_count, const int *granted_qos);
|
||||
void (*on_unsubscribe)(struct mosquitto *, void *userdata, int mid);
|
||||
void (*on_log)(struct mosquitto *, void *userdata, int level, const char *str);
|
||||
//void (*on_error)();
|
||||
char *host;
|
||||
int port;
|
||||
int in_queue_len;
|
||||
int out_queue_len;
|
||||
char *bind_address;
|
||||
unsigned int reconnect_delay;
|
||||
unsigned int reconnect_delay_max;
|
||||
bool reconnect_exponential_backoff;
|
||||
bool threaded;
|
||||
struct _mosquitto_packet *out_packet_last;
|
||||
int inflight_messages;
|
||||
int max_inflight_messages;
|
||||
# ifdef WITH_SRV
|
||||
ares_channel achan;
|
||||
# endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
53
lib/mqtt3_protocol.h
Normal file
53
lib/mqtt3_protocol.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifndef _MQTT3_PROTOCOL_H_
|
||||
#define _MQTT3_PROTOCOL_H_
|
||||
|
||||
/* For version 3 of the MQTT protocol */
|
||||
|
||||
#define PROTOCOL_NAME_v31 "MQIsdp"
|
||||
#define PROTOCOL_VERSION_v31 3
|
||||
|
||||
#define PROTOCOL_NAME_v311 "MQTT"
|
||||
#define PROTOCOL_VERSION_v311 4
|
||||
|
||||
/* Message types */
|
||||
#define CONNECT 0x10
|
||||
#define CONNACK 0x20
|
||||
#define PUBLISH 0x30
|
||||
#define PUBACK 0x40
|
||||
#define PUBREC 0x50
|
||||
#define PUBREL 0x60
|
||||
#define PUBCOMP 0x70
|
||||
#define SUBSCRIBE 0x80
|
||||
#define SUBACK 0x90
|
||||
#define UNSUBSCRIBE 0xA0
|
||||
#define UNSUBACK 0xB0
|
||||
#define PINGREQ 0xC0
|
||||
#define PINGRESP 0xD0
|
||||
#define DISCONNECT 0xE0
|
||||
|
||||
#define CONNACK_ACCEPTED 0
|
||||
#define CONNACK_REFUSED_PROTOCOL_VERSION 1
|
||||
#define CONNACK_REFUSED_IDENTIFIER_REJECTED 2
|
||||
#define CONNACK_REFUSED_SERVER_UNAVAILABLE 3
|
||||
#define CONNACK_REFUSED_BAD_USERNAME_PASSWORD 4
|
||||
#define CONNACK_REFUSED_NOT_AUTHORIZED 5
|
||||
|
||||
#define MQTT_MAX_PAYLOAD 268435455
|
||||
|
||||
#endif
|
1116
lib/net_mosq.c
Normal file
1116
lib/net_mosq.c
Normal file
File diff suppressed because it is too large
Load Diff
91
lib/net_mosq.h
Normal file
91
lib/net_mosq.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
#ifndef _NET_MOSQ_H_
|
||||
#define _NET_MOSQ_H_
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
|
||||
#include <mosquitto_internal.h>
|
||||
#include <mosquitto.h>
|
||||
|
||||
#ifdef WITH_BROKER
|
||||
struct mosquitto_db;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# define COMPAT_CLOSE(a) closesocket(a)
|
||||
# define COMPAT_ECONNRESET WSAECONNRESET
|
||||
# define COMPAT_EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#else
|
||||
# define COMPAT_CLOSE(a) close(a)
|
||||
# define COMPAT_ECONNRESET ECONNRESET
|
||||
# define COMPAT_EWOULDBLOCK EWOULDBLOCK
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#else
|
||||
#endif
|
||||
|
||||
/* For when not using winsock libraries. */
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET -1
|
||||
#endif
|
||||
|
||||
/* Macros for accessing the MSB and LSB of a uint16_t */
|
||||
#define MOSQ_MSB(A) (uint8_t)((A & 0xFF00) >> 8)
|
||||
#define MOSQ_LSB(A) (uint8_t)(A & 0x00FF)
|
||||
|
||||
void _mosquitto_net_init(void);
|
||||
void _mosquitto_net_cleanup(void);
|
||||
|
||||
void _mosquitto_packet_cleanup(struct _mosquitto_packet *packet);
|
||||
int _mosquitto_packet_queue(struct mosquitto *mosq, struct _mosquitto_packet *packet);
|
||||
int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking);
|
||||
int _mosquitto_socket_close(struct mosquitto *mosq);
|
||||
int _mosquitto_try_connect(const char *host, uint16_t port, int *sock, const char *bind_address, bool blocking);
|
||||
int _mosquitto_socket_nonblock(int sock);
|
||||
int _mosquitto_socketpair(int *sp1, int *sp2);
|
||||
|
||||
int _mosquitto_read_byte(struct _mosquitto_packet *packet, uint8_t *byte);
|
||||
int _mosquitto_read_bytes(struct _mosquitto_packet *packet, void *bytes, uint32_t count);
|
||||
int _mosquitto_read_string(struct _mosquitto_packet *packet, char **str);
|
||||
int _mosquitto_read_uint16(struct _mosquitto_packet *packet, uint16_t *word);
|
||||
|
||||
void _mosquitto_write_byte(struct _mosquitto_packet *packet, uint8_t byte);
|
||||
void _mosquitto_write_bytes(struct _mosquitto_packet *packet, const void *bytes, uint32_t count);
|
||||
void _mosquitto_write_string(struct _mosquitto_packet *packet, const char *str, uint16_t length);
|
||||
void _mosquitto_write_uint16(struct _mosquitto_packet *packet, uint16_t word);
|
||||
|
||||
ssize_t _mosquitto_net_read(struct mosquitto *mosq, void *buf, size_t count);
|
||||
ssize_t _mosquitto_net_write(struct mosquitto *mosq, void *buf, size_t count);
|
||||
|
||||
int _mosquitto_packet_write(struct mosquitto *mosq);
|
||||
#ifdef WITH_BROKER
|
||||
int _mosquitto_packet_read(struct mosquitto_db *db, struct mosquitto *mosq);
|
||||
#else
|
||||
int _mosquitto_packet_read(struct mosquitto *mosq);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_TLS
|
||||
int _mosquitto_socket_apply_tls(struct mosquitto *mosq);
|
||||
#endif
|
||||
|
||||
#endif
|
155
lib/read_handle.c
Normal file
155
lib/read_handle.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include <logging_mosq.h>
|
||||
#include <memory_mosq.h>
|
||||
#include <messages_mosq.h>
|
||||
#include <mqtt3_protocol.h>
|
||||
#include <net_mosq.h>
|
||||
#include <read_handle.h>
|
||||
#include <send_mosq.h>
|
||||
#include <time_mosq.h>
|
||||
#include <util_mosq.h>
|
||||
|
||||
int _mosquitto_packet_handle(struct mosquitto *mosq)
|
||||
{
|
||||
assert(mosq);
|
||||
|
||||
switch((mosq->in_packet.command)&0xF0){
|
||||
case PINGREQ:
|
||||
return _mosquitto_handle_pingreq(mosq);
|
||||
case PINGRESP:
|
||||
return _mosquitto_handle_pingresp(mosq);
|
||||
case PUBACK:
|
||||
return _mosquitto_handle_pubackcomp(mosq, "PUBACK");
|
||||
case PUBCOMP:
|
||||
return _mosquitto_handle_pubackcomp(mosq, "PUBCOMP");
|
||||
case PUBLISH:
|
||||
return _mosquitto_handle_publish(mosq);
|
||||
case PUBREC:
|
||||
return _mosquitto_handle_pubrec(mosq);
|
||||
case PUBREL:
|
||||
return _mosquitto_handle_pubrel(NULL, mosq);
|
||||
case CONNACK:
|
||||
return _mosquitto_handle_connack(mosq);
|
||||
case SUBACK:
|
||||
return _mosquitto_handle_suback(mosq);
|
||||
case UNSUBACK:
|
||||
return _mosquitto_handle_unsuback(mosq);
|
||||
default:
|
||||
/* If we don't recognise the command, return an error straight away. */
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unrecognised command %d\n", (mosq->in_packet.command)&0xF0);
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
}
|
||||
|
||||
int _mosquitto_handle_publish(struct mosquitto *mosq)
|
||||
{
|
||||
uint8_t header;
|
||||
struct mosquitto_message_all *message;
|
||||
int rc = 0;
|
||||
uint16_t mid;
|
||||
|
||||
assert(mosq);
|
||||
|
||||
message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all));
|
||||
if(!message) return MOSQ_ERR_NOMEM;
|
||||
|
||||
header = mosq->in_packet.command;
|
||||
|
||||
message->dup = (header & 0x08)>>3;
|
||||
message->msg.qos = (header & 0x06)>>1;
|
||||
message->msg.retain = (header & 0x01);
|
||||
|
||||
rc = _mosquitto_read_string(&mosq->in_packet, &message->msg.topic);
|
||||
if(rc){
|
||||
_mosquitto_message_cleanup(&message);
|
||||
return rc;
|
||||
}
|
||||
if(!strlen(message->msg.topic)){
|
||||
_mosquitto_message_cleanup(&message);
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
|
||||
if(message->msg.qos > 0){
|
||||
rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
|
||||
if(rc){
|
||||
_mosquitto_message_cleanup(&message);
|
||||
return rc;
|
||||
}
|
||||
message->msg.mid = (int)mid;
|
||||
}
|
||||
|
||||
message->msg.payloadlen = mosq->in_packet.remaining_length - mosq->in_packet.pos;
|
||||
if(message->msg.payloadlen){
|
||||
message->msg.payload = _mosquitto_calloc(message->msg.payloadlen+1, sizeof(uint8_t));
|
||||
if(!message->msg.payload){
|
||||
_mosquitto_message_cleanup(&message);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
rc = _mosquitto_read_bytes(&mosq->in_packet, message->msg.payload, message->msg.payloadlen);
|
||||
if(rc){
|
||||
_mosquitto_message_cleanup(&message);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG,
|
||||
"Client %s received PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))",
|
||||
mosq->id, message->dup, message->msg.qos, message->msg.retain,
|
||||
message->msg.mid, message->msg.topic,
|
||||
(long)message->msg.payloadlen);
|
||||
|
||||
message->timestamp = mosquitto_time();
|
||||
switch(message->msg.qos){
|
||||
case 0:
|
||||
pthread_mutex_lock(&mosq->callback_mutex);
|
||||
if(mosq->on_message){
|
||||
mosq->in_callback = true;
|
||||
mosq->on_message(mosq, mosq->userdata, &message->msg);
|
||||
mosq->in_callback = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->callback_mutex);
|
||||
_mosquitto_message_cleanup(&message);
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
case 1:
|
||||
rc = _mosquitto_send_puback(mosq, message->msg.mid);
|
||||
pthread_mutex_lock(&mosq->callback_mutex);
|
||||
if(mosq->on_message){
|
||||
mosq->in_callback = true;
|
||||
mosq->on_message(mosq, mosq->userdata, &message->msg);
|
||||
mosq->in_callback = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->callback_mutex);
|
||||
_mosquitto_message_cleanup(&message);
|
||||
return rc;
|
||||
case 2:
|
||||
rc = _mosquitto_send_pubrec(mosq, message->msg.mid);
|
||||
pthread_mutex_lock(&mosq->in_message_mutex);
|
||||
message->state = mosq_ms_wait_for_pubrel;
|
||||
_mosquitto_message_queue(mosq, message, mosq_md_in);
|
||||
pthread_mutex_unlock(&mosq->in_message_mutex);
|
||||
return rc;
|
||||
default:
|
||||
_mosquitto_message_cleanup(&message);
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
}
|
||||
|
34
lib/read_handle.h
Normal file
34
lib/read_handle.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
#ifndef _READ_HANDLE_H_
|
||||
#define _READ_HANDLE_H_
|
||||
|
||||
#include <mosquitto.h>
|
||||
struct mosquitto_db;
|
||||
|
||||
int _mosquitto_packet_handle(struct mosquitto *mosq);
|
||||
int _mosquitto_handle_connack(struct mosquitto *mosq);
|
||||
int _mosquitto_handle_pingreq(struct mosquitto *mosq);
|
||||
int _mosquitto_handle_pingresp(struct mosquitto *mosq);
|
||||
int _mosquitto_handle_pubackcomp(struct mosquitto *mosq, const char *type);
|
||||
int _mosquitto_handle_publish(struct mosquitto *mosq);
|
||||
int _mosquitto_handle_pubrec(struct mosquitto *mosq);
|
||||
int _mosquitto_handle_pubrel(struct mosquitto_db *db, struct mosquitto *mosq);
|
||||
int _mosquitto_handle_suback(struct mosquitto *mosq);
|
||||
int _mosquitto_handle_unsuback(struct mosquitto *mosq);
|
||||
|
||||
|
||||
#endif
|
63
lib/read_handle_client.c
Normal file
63
lib/read_handle_client.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include <logging_mosq.h>
|
||||
#include <memory_mosq.h>
|
||||
#include <net_mosq.h>
|
||||
#include <read_handle.h>
|
||||
|
||||
int _mosquitto_handle_connack(struct mosquitto *mosq)
|
||||
{
|
||||
uint8_t byte;
|
||||
uint8_t result;
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
#ifdef WITH_STRICT_PROTOCOL
|
||||
if(mosq->in_packet.remaining_length != 2){
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
#endif
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received CONNACK", mosq->id);
|
||||
rc = _mosquitto_read_byte(&mosq->in_packet, &byte); // Reserved byte, not used
|
||||
if(rc) return rc;
|
||||
rc = _mosquitto_read_byte(&mosq->in_packet, &result);
|
||||
if(rc) return rc;
|
||||
pthread_mutex_lock(&mosq->callback_mutex);
|
||||
if(mosq->on_connect){
|
||||
mosq->in_callback = true;
|
||||
mosq->on_connect(mosq, mosq->userdata, result);
|
||||
mosq->in_callback = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->callback_mutex);
|
||||
switch(result){
|
||||
case 0:
|
||||
mosq->state = mosq_cs_connected;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
return MOSQ_ERR_CONN_REFUSED;
|
||||
default:
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
}
|
||||
|
258
lib/read_handle_shared.c
Normal file
258
lib/read_handle_shared.c
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include <logging_mosq.h>
|
||||
#include <memory_mosq.h>
|
||||
#include <messages_mosq.h>
|
||||
#include <mqtt3_protocol.h>
|
||||
#include <net_mosq.h>
|
||||
#include <read_handle.h>
|
||||
#include <send_mosq.h>
|
||||
#include <util_mosq.h>
|
||||
#ifdef WITH_BROKER
|
||||
#include <mosquitto_broker.h>
|
||||
#endif
|
||||
|
||||
int _mosquitto_handle_pingreq(struct mosquitto *mosq)
|
||||
{
|
||||
assert(mosq);
|
||||
#ifdef WITH_STRICT_PROTOCOL
|
||||
if(mosq->in_packet.remaining_length != 0){
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_BROKER
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PINGREQ from %s", mosq->id);
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PINGREQ", mosq->id);
|
||||
#endif
|
||||
return _mosquitto_send_pingresp(mosq);
|
||||
}
|
||||
|
||||
int _mosquitto_handle_pingresp(struct mosquitto *mosq)
|
||||
{
|
||||
assert(mosq);
|
||||
#ifdef WITH_STRICT_PROTOCOL
|
||||
if(mosq->in_packet.remaining_length != 0){
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
#endif
|
||||
mosq->ping_t = 0; /* No longer waiting for a PINGRESP. */
|
||||
#ifdef WITH_BROKER
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PINGRESP from %s", mosq->id);
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PINGRESP", mosq->id);
|
||||
#endif
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int _mosquitto_handle_pubackcomp(struct mosquitto *mosq, const char *type)
|
||||
{
|
||||
uint16_t mid;
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
#ifdef WITH_STRICT_PROTOCOL
|
||||
if(mosq->in_packet.remaining_length != 2){
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
#endif
|
||||
rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
|
||||
if(rc) return rc;
|
||||
#ifdef WITH_BROKER
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received %s from %s (Mid: %d)", type, mosq->id, mid);
|
||||
|
||||
if(mid){
|
||||
rc = mqtt3_db_message_delete(mosq, mid, mosq_md_out);
|
||||
if(rc) return rc;
|
||||
}
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received %s (Mid: %d)", mosq->id, type, mid);
|
||||
|
||||
if(!_mosquitto_message_delete(mosq, mid, mosq_md_out)){
|
||||
/* Only inform the client the message has been sent once. */
|
||||
pthread_mutex_lock(&mosq->callback_mutex);
|
||||
if(mosq->on_publish){
|
||||
mosq->in_callback = true;
|
||||
mosq->on_publish(mosq, mosq->userdata, mid);
|
||||
mosq->in_callback = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->callback_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int _mosquitto_handle_pubrec(struct mosquitto *mosq)
|
||||
{
|
||||
uint16_t mid;
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
#ifdef WITH_STRICT_PROTOCOL
|
||||
if(mosq->in_packet.remaining_length != 2){
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
#endif
|
||||
rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
|
||||
if(rc) return rc;
|
||||
#ifdef WITH_BROKER
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREC from %s (Mid: %d)", mosq->id, mid);
|
||||
|
||||
rc = mqtt3_db_message_update(mosq, mid, mosq_md_out, mosq_ms_wait_for_pubcomp);
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREC (Mid: %d)", mosq->id, mid);
|
||||
|
||||
rc = _mosquitto_message_out_update(mosq, mid, mosq_ms_wait_for_pubcomp);
|
||||
#endif
|
||||
if(rc) return rc;
|
||||
rc = _mosquitto_send_pubrel(mosq, mid, false);
|
||||
if(rc) return rc;
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int _mosquitto_handle_pubrel(struct mosquitto_db *db, struct mosquitto *mosq)
|
||||
{
|
||||
uint16_t mid;
|
||||
#ifndef WITH_BROKER
|
||||
struct mosquitto_message_all *message = NULL;
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
#ifdef WITH_STRICT_PROTOCOL
|
||||
if(mosq->in_packet.remaining_length != 2){
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
#endif
|
||||
if(mosq->protocol == mosq_p_mqtt311){
|
||||
if((mosq->in_packet.command&0x0F) != 0x02){
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
}
|
||||
rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
|
||||
if(rc) return rc;
|
||||
#ifdef WITH_BROKER
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PUBREL from %s (Mid: %d)", mosq->id, mid);
|
||||
|
||||
if(mqtt3_db_message_release(db, mosq, mid, mosq_md_in)){
|
||||
/* Message not found. Still send a PUBCOMP anyway because this could be
|
||||
* due to a repeated PUBREL after a client has reconnected. */
|
||||
}
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received PUBREL (Mid: %d)", mosq->id, mid);
|
||||
|
||||
if(!_mosquitto_message_remove(mosq, mid, mosq_md_in, &message)){
|
||||
/* Only pass the message on if we have removed it from the queue - this
|
||||
* prevents multiple callbacks for the same message. */
|
||||
pthread_mutex_lock(&mosq->callback_mutex);
|
||||
if(mosq->on_message){
|
||||
mosq->in_callback = true;
|
||||
mosq->on_message(mosq, mosq->userdata, &message->msg);
|
||||
mosq->in_callback = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->callback_mutex);
|
||||
_mosquitto_message_cleanup(&message);
|
||||
}
|
||||
#endif
|
||||
rc = _mosquitto_send_pubcomp(mosq, mid);
|
||||
if(rc) return rc;
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int _mosquitto_handle_suback(struct mosquitto *mosq)
|
||||
{
|
||||
uint16_t mid;
|
||||
uint8_t qos;
|
||||
int *granted_qos;
|
||||
int qos_count;
|
||||
int i = 0;
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
#ifdef WITH_BROKER
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received SUBACK from %s", mosq->id);
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received SUBACK", mosq->id);
|
||||
#endif
|
||||
rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
|
||||
if(rc) return rc;
|
||||
|
||||
qos_count = mosq->in_packet.remaining_length - mosq->in_packet.pos;
|
||||
granted_qos = _mosquitto_malloc(qos_count*sizeof(int));
|
||||
if(!granted_qos) return MOSQ_ERR_NOMEM;
|
||||
while(mosq->in_packet.pos < mosq->in_packet.remaining_length){
|
||||
rc = _mosquitto_read_byte(&mosq->in_packet, &qos);
|
||||
if(rc){
|
||||
_mosquitto_free(granted_qos);
|
||||
return rc;
|
||||
}
|
||||
granted_qos[i] = (int)qos;
|
||||
i++;
|
||||
}
|
||||
#ifndef WITH_BROKER
|
||||
pthread_mutex_lock(&mosq->callback_mutex);
|
||||
if(mosq->on_subscribe){
|
||||
mosq->in_callback = true;
|
||||
mosq->on_subscribe(mosq, mosq->userdata, mid, qos_count, granted_qos);
|
||||
mosq->in_callback = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->callback_mutex);
|
||||
#endif
|
||||
_mosquitto_free(granted_qos);
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int _mosquitto_handle_unsuback(struct mosquitto *mosq)
|
||||
{
|
||||
uint16_t mid;
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
#ifdef WITH_STRICT_PROTOCOL
|
||||
if(mosq->in_packet.remaining_length != 2){
|
||||
return MOSQ_ERR_PROTOCOL;
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_BROKER
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received UNSUBACK from %s", mosq->id);
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s received UNSUBACK", mosq->id);
|
||||
#endif
|
||||
rc = _mosquitto_read_uint16(&mosq->in_packet, &mid);
|
||||
if(rc) return rc;
|
||||
#ifndef WITH_BROKER
|
||||
pthread_mutex_lock(&mosq->callback_mutex);
|
||||
if(mosq->on_unsubscribe){
|
||||
mosq->in_callback = true;
|
||||
mosq->on_unsubscribe(mosq, mosq->userdata, mid);
|
||||
mosq->in_callback = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->callback_mutex);
|
||||
#endif
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
214
lib/send_client_mosq.c
Normal file
214
lib/send_client_mosq.c
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include <logging_mosq.h>
|
||||
#include <memory_mosq.h>
|
||||
#include <mqtt3_protocol.h>
|
||||
#include <net_mosq.h>
|
||||
#include <send_mosq.h>
|
||||
#include <util_mosq.h>
|
||||
|
||||
#ifdef WITH_BROKER
|
||||
#include <mosquitto_broker.h>
|
||||
#endif
|
||||
|
||||
int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session)
|
||||
{
|
||||
struct _mosquitto_packet *packet = NULL;
|
||||
int payloadlen;
|
||||
uint8_t will = 0;
|
||||
uint8_t byte;
|
||||
int rc;
|
||||
uint8_t version = PROTOCOL_VERSION_v31;
|
||||
|
||||
assert(mosq);
|
||||
assert(mosq->id);
|
||||
|
||||
packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
|
||||
if(!packet) return MOSQ_ERR_NOMEM;
|
||||
|
||||
payloadlen = 2+strlen(mosq->id);
|
||||
if(mosq->will){
|
||||
will = 1;
|
||||
assert(mosq->will->topic);
|
||||
|
||||
payloadlen += 2+strlen(mosq->will->topic) + 2+mosq->will->payloadlen;
|
||||
}
|
||||
if(mosq->username){
|
||||
payloadlen += 2+strlen(mosq->username);
|
||||
if(mosq->password){
|
||||
payloadlen += 2+strlen(mosq->password);
|
||||
}
|
||||
}
|
||||
|
||||
packet->command = CONNECT;
|
||||
packet->remaining_length = 12+payloadlen;
|
||||
rc = _mosquitto_packet_alloc(packet);
|
||||
if(rc){
|
||||
_mosquitto_free(packet);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Variable header */
|
||||
_mosquitto_write_string(packet, PROTOCOL_NAME_v31, strlen(PROTOCOL_NAME_v31));
|
||||
#if defined(WITH_BROKER) && defined(WITH_BRIDGE)
|
||||
if(mosq->bridge && mosq->bridge->try_private && mosq->bridge->try_private_accepted){
|
||||
version |= 0x80;
|
||||
}else{
|
||||
}
|
||||
#endif
|
||||
_mosquitto_write_byte(packet, version);
|
||||
byte = (clean_session&0x1)<<1;
|
||||
if(will){
|
||||
byte = byte | ((mosq->will->retain&0x1)<<5) | ((mosq->will->qos&0x3)<<3) | ((will&0x1)<<2);
|
||||
}
|
||||
if(mosq->username){
|
||||
byte = byte | 0x1<<7;
|
||||
if(mosq->password){
|
||||
byte = byte | 0x1<<6;
|
||||
}
|
||||
}
|
||||
_mosquitto_write_byte(packet, byte);
|
||||
_mosquitto_write_uint16(packet, keepalive);
|
||||
|
||||
/* Payload */
|
||||
_mosquitto_write_string(packet, mosq->id, strlen(mosq->id));
|
||||
if(will){
|
||||
_mosquitto_write_string(packet, mosq->will->topic, strlen(mosq->will->topic));
|
||||
_mosquitto_write_string(packet, (const char *)mosq->will->payload, mosq->will->payloadlen);
|
||||
}
|
||||
if(mosq->username){
|
||||
_mosquitto_write_string(packet, mosq->username, strlen(mosq->username));
|
||||
if(mosq->password){
|
||||
_mosquitto_write_string(packet, mosq->password, strlen(mosq->password));
|
||||
}
|
||||
}
|
||||
|
||||
mosq->keepalive = keepalive;
|
||||
#ifdef WITH_BROKER
|
||||
# ifdef WITH_BRIDGE
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending CONNECT", mosq->id);
|
||||
# endif
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending CONNECT", mosq->id);
|
||||
#endif
|
||||
return _mosquitto_packet_queue(mosq, packet);
|
||||
}
|
||||
|
||||
int _mosquitto_send_disconnect(struct mosquitto *mosq)
|
||||
{
|
||||
assert(mosq);
|
||||
#ifdef WITH_BROKER
|
||||
# ifdef WITH_BRIDGE
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending DISCONNECT", mosq->id);
|
||||
# endif
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending DISCONNECT", mosq->id);
|
||||
#endif
|
||||
return _mosquitto_send_simple_command(mosq, DISCONNECT);
|
||||
}
|
||||
|
||||
int _mosquitto_send_subscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic, uint8_t topic_qos)
|
||||
{
|
||||
/* FIXME - only deals with a single topic */
|
||||
struct _mosquitto_packet *packet = NULL;
|
||||
uint32_t packetlen;
|
||||
uint16_t local_mid;
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
assert(topic);
|
||||
|
||||
packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
|
||||
if(!packet) return MOSQ_ERR_NOMEM;
|
||||
|
||||
packetlen = 2 + 2+strlen(topic) + 1;
|
||||
|
||||
packet->command = SUBSCRIBE | (dup<<3) | (1<<1);
|
||||
packet->remaining_length = packetlen;
|
||||
rc = _mosquitto_packet_alloc(packet);
|
||||
if(rc){
|
||||
_mosquitto_free(packet);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Variable header */
|
||||
local_mid = _mosquitto_mid_generate(mosq);
|
||||
if(mid) *mid = (int)local_mid;
|
||||
_mosquitto_write_uint16(packet, local_mid);
|
||||
|
||||
/* Payload */
|
||||
_mosquitto_write_string(packet, topic, strlen(topic));
|
||||
_mosquitto_write_byte(packet, topic_qos);
|
||||
|
||||
#ifdef WITH_BROKER
|
||||
# ifdef WITH_BRIDGE
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d)", mosq->id, local_mid, topic, topic_qos);
|
||||
# endif
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending SUBSCRIBE (Mid: %d, Topic: %s, QoS: %d)", mosq->id, local_mid, topic, topic_qos);
|
||||
#endif
|
||||
|
||||
return _mosquitto_packet_queue(mosq, packet);
|
||||
}
|
||||
|
||||
|
||||
int _mosquitto_send_unsubscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic)
|
||||
{
|
||||
/* FIXME - only deals with a single topic */
|
||||
struct _mosquitto_packet *packet = NULL;
|
||||
uint32_t packetlen;
|
||||
uint16_t local_mid;
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
assert(topic);
|
||||
|
||||
packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
|
||||
if(!packet) return MOSQ_ERR_NOMEM;
|
||||
|
||||
packetlen = 2 + 2+strlen(topic);
|
||||
|
||||
packet->command = UNSUBSCRIBE | (dup<<3) | (1<<1);
|
||||
packet->remaining_length = packetlen;
|
||||
rc = _mosquitto_packet_alloc(packet);
|
||||
if(rc){
|
||||
_mosquitto_free(packet);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Variable header */
|
||||
local_mid = _mosquitto_mid_generate(mosq);
|
||||
if(mid) *mid = (int)local_mid;
|
||||
_mosquitto_write_uint16(packet, local_mid);
|
||||
|
||||
/* Payload */
|
||||
_mosquitto_write_string(packet, topic, strlen(topic));
|
||||
|
||||
#ifdef WITH_BROKER
|
||||
# ifdef WITH_BRIDGE
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending UNSUBSCRIBE (Mid: %d, Topic: %s)", mosq->id, local_mid, topic);
|
||||
# endif
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending UNSUBSCRIBE (Mid: %d, Topic: %s)", mosq->id, local_mid, topic);
|
||||
#endif
|
||||
return _mosquitto_packet_queue(mosq, packet);
|
||||
}
|
||||
|
276
lib/send_mosq.c
Normal file
276
lib/send_mosq.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include <mosquitto_internal.h>
|
||||
#include <logging_mosq.h>
|
||||
#include <mqtt3_protocol.h>
|
||||
#include <memory_mosq.h>
|
||||
#include <net_mosq.h>
|
||||
#include <send_mosq.h>
|
||||
#include <time_mosq.h>
|
||||
#include <util_mosq.h>
|
||||
|
||||
#ifdef WITH_BROKER
|
||||
#include <mosquitto_broker.h>
|
||||
# ifdef WITH_SYS_TREE
|
||||
extern uint64_t g_pub_bytes_sent;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
int _mosquitto_send_pingreq(struct mosquitto *mosq)
|
||||
{
|
||||
int rc;
|
||||
assert(mosq);
|
||||
#ifdef WITH_BROKER
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGREQ to %s", mosq->id);
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGREQ", mosq->id);
|
||||
#endif
|
||||
rc = _mosquitto_send_simple_command(mosq, PINGREQ);
|
||||
if(rc == MOSQ_ERR_SUCCESS){
|
||||
mosq->ping_t = mosquitto_time();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int _mosquitto_send_pingresp(struct mosquitto *mosq)
|
||||
{
|
||||
#ifdef WITH_BROKER
|
||||
if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PINGRESP to %s", mosq->id);
|
||||
#else
|
||||
if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PINGRESP", mosq->id);
|
||||
#endif
|
||||
return _mosquitto_send_simple_command(mosq, PINGRESP);
|
||||
}
|
||||
|
||||
int _mosquitto_send_puback(struct mosquitto *mosq, uint16_t mid)
|
||||
{
|
||||
#ifdef WITH_BROKER
|
||||
if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBACK to %s (Mid: %d)", mosq->id, mid);
|
||||
#else
|
||||
if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBACK (Mid: %d)", mosq->id, mid);
|
||||
#endif
|
||||
return _mosquitto_send_command_with_mid(mosq, PUBACK, mid, false);
|
||||
}
|
||||
|
||||
int _mosquitto_send_pubcomp(struct mosquitto *mosq, uint16_t mid)
|
||||
{
|
||||
#ifdef WITH_BROKER
|
||||
if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBCOMP to %s (Mid: %d)", mosq->id, mid);
|
||||
#else
|
||||
if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBCOMP (Mid: %d)", mosq->id, mid);
|
||||
#endif
|
||||
return _mosquitto_send_command_with_mid(mosq, PUBCOMP, mid, false);
|
||||
}
|
||||
|
||||
int _mosquitto_send_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup)
|
||||
{
|
||||
#ifdef WITH_BROKER
|
||||
size_t len;
|
||||
#ifdef WITH_BRIDGE
|
||||
int i;
|
||||
struct _mqtt3_bridge_topic *cur_topic;
|
||||
bool match;
|
||||
int rc;
|
||||
char *mapped_topic = NULL;
|
||||
char *topic_temp = NULL;
|
||||
#endif
|
||||
#endif
|
||||
assert(mosq);
|
||||
assert(topic);
|
||||
|
||||
if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN;
|
||||
#ifdef WITH_BROKER
|
||||
if(mosq->listener && mosq->listener->mount_point){
|
||||
len = strlen(mosq->listener->mount_point);
|
||||
if(len < strlen(topic)){
|
||||
topic += len;
|
||||
}else{
|
||||
/* Invalid topic string. Should never happen, but silently swallow the message anyway. */
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
#ifdef WITH_BRIDGE
|
||||
if(mosq->bridge && mosq->bridge->topics && mosq->bridge->topic_remapping){
|
||||
for(i=0; i<mosq->bridge->topic_count; i++){
|
||||
cur_topic = &mosq->bridge->topics[i];
|
||||
if((cur_topic->direction == bd_both || cur_topic->direction == bd_out)
|
||||
&& (cur_topic->remote_prefix || cur_topic->local_prefix)){
|
||||
/* Topic mapping required on this topic if the message matches */
|
||||
|
||||
rc = mosquitto_topic_matches_sub(cur_topic->local_topic, topic, &match);
|
||||
if(rc){
|
||||
return rc;
|
||||
}
|
||||
if(match){
|
||||
mapped_topic = _mosquitto_strdup(topic);
|
||||
if(!mapped_topic) return MOSQ_ERR_NOMEM;
|
||||
if(cur_topic->local_prefix){
|
||||
/* This prefix needs removing. */
|
||||
if(!strncmp(cur_topic->local_prefix, mapped_topic, strlen(cur_topic->local_prefix))){
|
||||
topic_temp = _mosquitto_strdup(mapped_topic+strlen(cur_topic->local_prefix));
|
||||
_mosquitto_free(mapped_topic);
|
||||
if(!topic_temp){
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
mapped_topic = topic_temp;
|
||||
}
|
||||
}
|
||||
|
||||
if(cur_topic->remote_prefix){
|
||||
/* This prefix needs adding. */
|
||||
len = strlen(mapped_topic) + strlen(cur_topic->remote_prefix)+1;
|
||||
topic_temp = _mosquitto_calloc(len+1, sizeof(char));
|
||||
if(!topic_temp){
|
||||
_mosquitto_free(mapped_topic);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
snprintf(topic_temp, len, "%s%s", cur_topic->remote_prefix, mapped_topic);
|
||||
_mosquitto_free(mapped_topic);
|
||||
mapped_topic = topic_temp;
|
||||
}
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBLISH to %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, mapped_topic, (long)payloadlen);
|
||||
#ifdef WITH_SYS_TREE
|
||||
g_pub_bytes_sent += payloadlen;
|
||||
#endif
|
||||
rc = _mosquitto_send_real_publish(mosq, mid, mapped_topic, payloadlen, payload, qos, retain, dup);
|
||||
_mosquitto_free(mapped_topic);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBLISH to %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, topic, (long)payloadlen);
|
||||
# ifdef WITH_SYS_TREE
|
||||
g_pub_bytes_sent += payloadlen;
|
||||
# endif
|
||||
#else
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", mosq->id, dup, qos, retain, mid, topic, (long)payloadlen);
|
||||
#endif
|
||||
|
||||
return _mosquitto_send_real_publish(mosq, mid, topic, payloadlen, payload, qos, retain, dup);
|
||||
}
|
||||
|
||||
int _mosquitto_send_pubrec(struct mosquitto *mosq, uint16_t mid)
|
||||
{
|
||||
#ifdef WITH_BROKER
|
||||
if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREC to %s (Mid: %d)", mosq->id, mid);
|
||||
#else
|
||||
if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREC (Mid: %d)", mosq->id, mid);
|
||||
#endif
|
||||
return _mosquitto_send_command_with_mid(mosq, PUBREC, mid, false);
|
||||
}
|
||||
|
||||
int _mosquitto_send_pubrel(struct mosquitto *mosq, uint16_t mid, bool dup)
|
||||
{
|
||||
#ifdef WITH_BROKER
|
||||
if(mosq) _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending PUBREL to %s (Mid: %d)", mosq->id, mid);
|
||||
#else
|
||||
if(mosq) _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending PUBREL (Mid: %d)", mosq->id, mid);
|
||||
#endif
|
||||
return _mosquitto_send_command_with_mid(mosq, PUBREL|2, mid, dup);
|
||||
}
|
||||
|
||||
/* For PUBACK, PUBCOMP, PUBREC, and PUBREL */
|
||||
int _mosquitto_send_command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup)
|
||||
{
|
||||
struct _mosquitto_packet *packet = NULL;
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
|
||||
if(!packet) return MOSQ_ERR_NOMEM;
|
||||
|
||||
packet->command = command;
|
||||
if(dup){
|
||||
packet->command |= 8;
|
||||
}
|
||||
packet->remaining_length = 2;
|
||||
rc = _mosquitto_packet_alloc(packet);
|
||||
if(rc){
|
||||
_mosquitto_free(packet);
|
||||
return rc;
|
||||
}
|
||||
|
||||
packet->payload[packet->pos+0] = MOSQ_MSB(mid);
|
||||
packet->payload[packet->pos+1] = MOSQ_LSB(mid);
|
||||
|
||||
return _mosquitto_packet_queue(mosq, packet);
|
||||
}
|
||||
|
||||
/* For DISCONNECT, PINGREQ and PINGRESP */
|
||||
int _mosquitto_send_simple_command(struct mosquitto *mosq, uint8_t command)
|
||||
{
|
||||
struct _mosquitto_packet *packet = NULL;
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
|
||||
if(!packet) return MOSQ_ERR_NOMEM;
|
||||
|
||||
packet->command = command;
|
||||
packet->remaining_length = 0;
|
||||
|
||||
rc = _mosquitto_packet_alloc(packet);
|
||||
if(rc){
|
||||
_mosquitto_free(packet);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return _mosquitto_packet_queue(mosq, packet);
|
||||
}
|
||||
|
||||
int _mosquitto_send_real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup)
|
||||
{
|
||||
struct _mosquitto_packet *packet = NULL;
|
||||
int packetlen;
|
||||
int rc;
|
||||
|
||||
assert(mosq);
|
||||
assert(topic);
|
||||
|
||||
packetlen = 2+strlen(topic) + payloadlen;
|
||||
if(qos > 0) packetlen += 2; /* For message id */
|
||||
packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet));
|
||||
if(!packet) return MOSQ_ERR_NOMEM;
|
||||
|
||||
packet->mid = mid;
|
||||
packet->command = PUBLISH | ((dup&0x1)<<3) | (qos<<1) | retain;
|
||||
packet->remaining_length = packetlen;
|
||||
rc = _mosquitto_packet_alloc(packet);
|
||||
if(rc){
|
||||
_mosquitto_free(packet);
|
||||
return rc;
|
||||
}
|
||||
/* Variable header (topic string) */
|
||||
_mosquitto_write_string(packet, topic, strlen(topic));
|
||||
if(qos > 0){
|
||||
_mosquitto_write_uint16(packet, mid);
|
||||
}
|
||||
|
||||
/* Payload */
|
||||
if(payloadlen){
|
||||
_mosquitto_write_bytes(packet, payload, payloadlen);
|
||||
}
|
||||
|
||||
return _mosquitto_packet_queue(mosq, packet);
|
||||
}
|
37
lib/send_mosq.h
Normal file
37
lib/send_mosq.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
#ifndef _SEND_MOSQ_H_
|
||||
#define _SEND_MOSQ_H_
|
||||
|
||||
#include <mosquitto.h>
|
||||
|
||||
int _mosquitto_send_simple_command(struct mosquitto *mosq, uint8_t command);
|
||||
int _mosquitto_send_command_with_mid(struct mosquitto *mosq, uint8_t command, uint16_t mid, bool dup);
|
||||
int _mosquitto_send_real_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup);
|
||||
|
||||
int _mosquitto_send_connect(struct mosquitto *mosq, uint16_t keepalive, bool clean_session);
|
||||
int _mosquitto_send_disconnect(struct mosquitto *mosq);
|
||||
int _mosquitto_send_pingreq(struct mosquitto *mosq);
|
||||
int _mosquitto_send_pingresp(struct mosquitto *mosq);
|
||||
int _mosquitto_send_puback(struct mosquitto *mosq, uint16_t mid);
|
||||
int _mosquitto_send_pubcomp(struct mosquitto *mosq, uint16_t mid);
|
||||
int _mosquitto_send_publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup);
|
||||
int _mosquitto_send_pubrec(struct mosquitto *mosq, uint16_t mid);
|
||||
int _mosquitto_send_pubrel(struct mosquitto *mosq, uint16_t mid, bool dup);
|
||||
int _mosquitto_send_subscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic, uint8_t topic_qos);
|
||||
int _mosquitto_send_unsubscribe(struct mosquitto *mosq, int *mid, bool dup, const char *topic);
|
||||
|
||||
#endif
|
93
lib/srv_mosq.c
Normal file
93
lib/srv_mosq.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright (c) 2013,2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifdef WITH_SRV
|
||||
# include <ares.h>
|
||||
|
||||
# include <arpa/nameser.h>
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#include "logging_mosq.h"
|
||||
#include "memory_mosq.h"
|
||||
#include "mosquitto_internal.h"
|
||||
#include "mosquitto.h"
|
||||
|
||||
#ifdef WITH_SRV
|
||||
static void srv_callback(void *arg, int status, int timeouts, unsigned char *abuf, int alen)
|
||||
{
|
||||
struct mosquitto *mosq = arg;
|
||||
struct ares_srv_reply *reply = NULL;
|
||||
if(status == ARES_SUCCESS){
|
||||
status = ares_parse_srv_reply(abuf, alen, &reply);
|
||||
if(status == ARES_SUCCESS){
|
||||
// FIXME - choose which answer to use based on rfc2782 page 3. */
|
||||
mosquitto_connect(mosq, reply->host, reply->port, mosq->keepalive);
|
||||
}
|
||||
}else{
|
||||
_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: SRV lookup failed (%d).", status);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int mosquitto_connect_srv(struct mosquitto *mosq, const char *host, int keepalive, const char *bind_address)
|
||||
{
|
||||
#ifdef WITH_SRV
|
||||
char *h;
|
||||
int rc;
|
||||
if(!mosq) return MOSQ_ERR_INVAL;
|
||||
|
||||
rc = ares_init(&mosq->achan);
|
||||
if(rc != ARES_SUCCESS){
|
||||
return MOSQ_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
if(!host){
|
||||
// get local domain
|
||||
}else{
|
||||
#ifdef WITH_TLS
|
||||
if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
|
||||
h = _mosquitto_malloc(strlen(host) + strlen("_secure-mqtt._tcp.") + 1);
|
||||
if(!h) return MOSQ_ERR_NOMEM;
|
||||
sprintf(h, "_secure-mqtt._tcp.%s", host);
|
||||
}else{
|
||||
#endif
|
||||
h = _mosquitto_malloc(strlen(host) + strlen("_mqtt._tcp.") + 1);
|
||||
if(!h) return MOSQ_ERR_NOMEM;
|
||||
sprintf(h, "_mqtt._tcp.%s", host);
|
||||
#ifdef WITH_TLS
|
||||
}
|
||||
#endif
|
||||
ares_search(mosq->achan, h, ns_c_in, ns_t_srv, srv_callback, mosq);
|
||||
_mosquitto_free(h);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mosq->state_mutex);
|
||||
mosq->state = mosq_cs_connect_srv;
|
||||
pthread_mutex_unlock(&mosq->state_mutex);
|
||||
|
||||
mosq->keepalive = keepalive;
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
|
||||
#else
|
||||
return MOSQ_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
101
lib/thread_mosq.c
Normal file
101
lib/thread_mosq.c
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (c) 2011-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <mosquitto_internal.h>
|
||||
#include <net_mosq.h>
|
||||
|
||||
void *_mosquitto_thread_main(void *obj);
|
||||
|
||||
int mosquitto_loop_start(struct mosquitto *mosq)
|
||||
{
|
||||
#ifdef WITH_THREADING
|
||||
if(!mosq || mosq->threaded) return MOSQ_ERR_INVAL;
|
||||
|
||||
mosq->threaded = true;
|
||||
pthread_create(&mosq->thread_id, NULL, _mosquitto_thread_main, mosq);
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
#else
|
||||
return MOSQ_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
int mosquitto_loop_stop(struct mosquitto *mosq, bool force)
|
||||
{
|
||||
#ifdef WITH_THREADING
|
||||
# ifndef WITH_BROKER
|
||||
char sockpair_data = 0;
|
||||
# endif
|
||||
|
||||
if(!mosq || !mosq->threaded) return MOSQ_ERR_INVAL;
|
||||
|
||||
|
||||
/* Write a single byte to sockpairW (connected to sockpairR) to break out
|
||||
* of select() if in threaded mode. */
|
||||
if(mosq->sockpairW != INVALID_SOCKET){
|
||||
#ifndef WIN32
|
||||
if(write(mosq->sockpairW, &sockpair_data, 1)){
|
||||
}
|
||||
#else
|
||||
send(mosq->sockpairW, &sockpair_data, 1, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(force){
|
||||
pthread_cancel(mosq->thread_id);
|
||||
}
|
||||
pthread_join(mosq->thread_id, NULL);
|
||||
mosq->thread_id = pthread_self();
|
||||
mosq->threaded = false;
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
#else
|
||||
return MOSQ_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_THREADING
|
||||
void *_mosquitto_thread_main(void *obj)
|
||||
{
|
||||
struct mosquitto *mosq = obj;
|
||||
|
||||
if(!mosq) return NULL;
|
||||
|
||||
pthread_mutex_lock(&mosq->state_mutex);
|
||||
if(mosq->state == mosq_cs_connect_async){
|
||||
pthread_mutex_unlock(&mosq->state_mutex);
|
||||
mosquitto_reconnect(mosq);
|
||||
}else{
|
||||
pthread_mutex_unlock(&mosq->state_mutex);
|
||||
}
|
||||
|
||||
if(!mosq->keepalive){
|
||||
/* Sleep for a day if keepalive disabled. */
|
||||
mosquitto_loop_forever(mosq, mosq->keepalive*1000*86400, 1);
|
||||
}else{
|
||||
/* Sleep for our keepalive value. publish() etc. will wake us up. */
|
||||
mosquitto_loop_forever(mosq, mosq->keepalive*1000, 1);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
#endif
|
||||
|
82
lib/time_mosq.c
Normal file
82
lib/time_mosq.c
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (c) 2013,2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# define _WIN32_WINNT _WIN32_WINNT_VISTA
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#include "mosquitto.h"
|
||||
#include "time_mosq.h"
|
||||
|
||||
#ifdef WIN32
|
||||
static bool tick64 = false;
|
||||
|
||||
void _windows_time_version_check(void)
|
||||
{
|
||||
OSVERSIONINFO vi;
|
||||
|
||||
tick64 = false;
|
||||
|
||||
memset(&vi, 0, sizeof(OSVERSIONINFO));
|
||||
vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
if(GetVersionEx(&vi)){
|
||||
if(vi.dwMajorVersion > 5){
|
||||
tick64 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
time_t mosquitto_time(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if(tick64){
|
||||
return GetTickCount64()/1000;
|
||||
}else{
|
||||
return GetTickCount()/1000; /* FIXME - need to deal with overflow. */
|
||||
}
|
||||
#elif _POSIX_TIMERS>0 && defined(_POSIX_MONOTONIC_CLOCK)
|
||||
struct timespec tp;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
return tp.tv_sec;
|
||||
#elif defined(__APPLE__)
|
||||
static mach_timebase_info_data_t tb;
|
||||
uint64_t ticks;
|
||||
uint64_t sec;
|
||||
|
||||
ticks = mach_absolute_time();
|
||||
|
||||
if(tb.denom == 0){
|
||||
mach_timebase_info(&tb);
|
||||
}
|
||||
sec = ticks*tb.numer/tb.denom/1000000000;
|
||||
|
||||
return (time_t)sec;
|
||||
#else
|
||||
return time(NULL);
|
||||
#endif
|
||||
}
|
||||
|
22
lib/time_mosq.h
Normal file
22
lib/time_mosq.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright (c) 2013,2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifndef _TIME_MOSQ_H_
|
||||
#define _TIME_MOSQ_H_
|
||||
|
||||
time_t mosquitto_time(void);
|
||||
|
||||
#endif
|
134
lib/tls_mosq.c
Normal file
134
lib/tls_mosq.c
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright (c) 2013,2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifdef WITH_TLS
|
||||
|
||||
#ifdef WIN32
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
#else
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#ifdef WITH_BROKER
|
||||
# include "mosquitto_broker.h"
|
||||
#endif
|
||||
#include "mosquitto_internal.h"
|
||||
#include "tls_mosq.h"
|
||||
|
||||
extern int tls_ex_index_mosq;
|
||||
|
||||
int _mosquitto_server_certificate_verify(int preverify_ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
/* Preverify should have already checked expiry, revocation.
|
||||
* We need to verify the hostname. */
|
||||
struct mosquitto *mosq;
|
||||
SSL *ssl;
|
||||
X509 *cert;
|
||||
|
||||
/* Always reject if preverify_ok has failed. */
|
||||
if(!preverify_ok) return 0;
|
||||
|
||||
ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
mosq = SSL_get_ex_data(ssl, tls_ex_index_mosq);
|
||||
if(!mosq) return 0;
|
||||
|
||||
if(mosq->tls_insecure == false){
|
||||
if(X509_STORE_CTX_get_error_depth(ctx) == 0){
|
||||
/* FIXME - use X509_check_host() etc. for sufficiently new openssl (>=1.1.x) */
|
||||
cert = X509_STORE_CTX_get_current_cert(ctx);
|
||||
/* This is the peer certificate, all others are upwards in the chain. */
|
||||
#if defined(WITH_BROKER)
|
||||
return _mosquitto_verify_certificate_hostname(cert, mosq->bridge->addresses[mosq->bridge->cur_address].address);
|
||||
#else
|
||||
return _mosquitto_verify_certificate_hostname(cert, mosq->host);
|
||||
#endif
|
||||
}else{
|
||||
return preverify_ok;
|
||||
}
|
||||
}else{
|
||||
return preverify_ok;
|
||||
}
|
||||
}
|
||||
|
||||
/* This code is based heavily on the example provided in "Secure Programming
|
||||
* Cookbook for C and C++".
|
||||
*/
|
||||
int _mosquitto_verify_certificate_hostname(X509 *cert, const char *hostname)
|
||||
{
|
||||
int i;
|
||||
char name[256];
|
||||
X509_NAME *subj;
|
||||
bool have_san_dns = false;
|
||||
STACK_OF(GENERAL_NAME) *san;
|
||||
const GENERAL_NAME *nval;
|
||||
const unsigned char *data;
|
||||
unsigned char ipv6_addr[16];
|
||||
unsigned char ipv4_addr[4];
|
||||
int ipv6_ok;
|
||||
int ipv4_ok;
|
||||
|
||||
#ifdef WIN32
|
||||
ipv6_ok = InetPton(AF_INET6, hostname, &ipv6_addr);
|
||||
ipv4_ok = InetPton(AF_INET, hostname, &ipv4_addr);
|
||||
#else
|
||||
ipv6_ok = inet_pton(AF_INET6, hostname, &ipv6_addr);
|
||||
ipv4_ok = inet_pton(AF_INET, hostname, &ipv4_addr);
|
||||
#endif
|
||||
|
||||
san = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
|
||||
if(san){
|
||||
for(i=0; i<sk_GENERAL_NAME_num(san); i++){
|
||||
nval = sk_GENERAL_NAME_value(san, i);
|
||||
if(nval->type == GEN_DNS){
|
||||
data = ASN1_STRING_data(nval->d.dNSName);
|
||||
if(data && !strcasecmp((char *)data, hostname)){
|
||||
return 1;
|
||||
}
|
||||
have_san_dns = true;
|
||||
}else if(nval->type == GEN_IPADD){
|
||||
data = ASN1_STRING_data(nval->d.iPAddress);
|
||||
if(nval->d.iPAddress->length == 4 && ipv4_ok){
|
||||
if(!memcmp(ipv4_addr, data, 4)){
|
||||
return 1;
|
||||
}
|
||||
}else if(nval->d.iPAddress->length == 16 && ipv6_ok){
|
||||
if(!memcmp(ipv6_addr, data, 16)){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(have_san_dns){
|
||||
/* Only check CN if subjectAltName DNS entry does not exist. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
subj = X509_get_subject_name(cert);
|
||||
if(X509_NAME_get_text_by_NID(subj, NID_commonName, name, sizeof(name)) > 0){
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
if (!strcasecmp(name, hostname)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
36
lib/tls_mosq.h
Normal file
36
lib/tls_mosq.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (c) 2013,2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifndef _TLS_MOSQ_H_
|
||||
#define _TLS_MOSQ_H_
|
||||
|
||||
#ifdef WITH_TLS
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#ifdef WITH_TLS_PSK
|
||||
# if OPENSSL_VERSION_NUMBER >= 0x10000000
|
||||
# define REAL_WITH_TLS_PSK
|
||||
# else
|
||||
# warning "TLS-PSK not supported, openssl too old."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
int _mosquitto_server_certificate_verify(int preverify_ok, X509_STORE_CTX *ctx);
|
||||
int _mosquitto_verify_certificate_hostname(X509 *cert, const char *hostname);
|
||||
|
||||
#endif /* WITH_TLS */
|
||||
|
||||
#endif
|
307
lib/util_mosq.c
Normal file
307
lib/util_mosq.c
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include <memory_mosq.h>
|
||||
#include <net_mosq.h>
|
||||
#include <send_mosq.h>
|
||||
#include <time_mosq.h>
|
||||
#include <tls_mosq.h>
|
||||
#include <util_mosq.h>
|
||||
|
||||
#ifdef WITH_BROKER
|
||||
#include <mosquitto_broker.h>
|
||||
#endif
|
||||
|
||||
int _mosquitto_packet_alloc(struct _mosquitto_packet *packet)
|
||||
{
|
||||
uint8_t remaining_bytes[5], byte;
|
||||
uint32_t remaining_length;
|
||||
int i;
|
||||
|
||||
assert(packet);
|
||||
|
||||
remaining_length = packet->remaining_length;
|
||||
packet->payload = NULL;
|
||||
packet->remaining_count = 0;
|
||||
do{
|
||||
byte = remaining_length % 128;
|
||||
remaining_length = remaining_length / 128;
|
||||
/* If there are more digits to encode, set the top bit of this digit */
|
||||
if(remaining_length > 0){
|
||||
byte = byte | 0x80;
|
||||
}
|
||||
remaining_bytes[packet->remaining_count] = byte;
|
||||
packet->remaining_count++;
|
||||
}while(remaining_length > 0 && packet->remaining_count < 5);
|
||||
if(packet->remaining_count == 5) return MOSQ_ERR_PAYLOAD_SIZE;
|
||||
packet->packet_length = packet->remaining_length + 1 + packet->remaining_count;
|
||||
packet->payload = _mosquitto_malloc(sizeof(uint8_t)*packet->packet_length);
|
||||
if(!packet->payload) return MOSQ_ERR_NOMEM;
|
||||
|
||||
packet->payload[0] = packet->command;
|
||||
for(i=0; i<packet->remaining_count; i++){
|
||||
packet->payload[i+1] = remaining_bytes[i];
|
||||
}
|
||||
packet->pos = 1 + packet->remaining_count;
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
void _mosquitto_check_keepalive(struct mosquitto *mosq)
|
||||
{
|
||||
time_t last_msg_out;
|
||||
time_t last_msg_in;
|
||||
time_t now = mosquitto_time();
|
||||
#ifndef WITH_BROKER
|
||||
int rc;
|
||||
#endif
|
||||
|
||||
assert(mosq);
|
||||
#if defined(WITH_BROKER) && defined(WITH_BRIDGE)
|
||||
/* Check if a lazy bridge should be timed out due to idle. */
|
||||
if(mosq->bridge && mosq->bridge->start_type == bst_lazy
|
||||
&& mosq->sock != INVALID_SOCKET
|
||||
&& now - mosq->last_msg_out >= mosq->bridge->idle_timeout){
|
||||
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Bridge connection %s has exceeded idle timeout, disconnecting.", mosq->id);
|
||||
_mosquitto_socket_close(mosq);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
pthread_mutex_lock(&mosq->msgtime_mutex);
|
||||
last_msg_out = mosq->last_msg_out;
|
||||
last_msg_in = mosq->last_msg_in;
|
||||
pthread_mutex_unlock(&mosq->msgtime_mutex);
|
||||
if(mosq->keepalive && mosq->sock != INVALID_SOCKET &&
|
||||
(now - last_msg_out >= mosq->keepalive || now - last_msg_in >= mosq->keepalive)){
|
||||
|
||||
if(mosq->state == mosq_cs_connected && mosq->ping_t == 0){
|
||||
_mosquitto_send_pingreq(mosq);
|
||||
/* Reset last msg times to give the server time to send a pingresp */
|
||||
pthread_mutex_lock(&mosq->msgtime_mutex);
|
||||
mosq->last_msg_in = now;
|
||||
mosq->last_msg_out = now;
|
||||
pthread_mutex_unlock(&mosq->msgtime_mutex);
|
||||
}else{
|
||||
#ifdef WITH_BROKER
|
||||
if(mosq->listener){
|
||||
mosq->listener->client_count--;
|
||||
assert(mosq->listener->client_count >= 0);
|
||||
}
|
||||
mosq->listener = NULL;
|
||||
#endif
|
||||
_mosquitto_socket_close(mosq);
|
||||
#ifndef WITH_BROKER
|
||||
pthread_mutex_lock(&mosq->state_mutex);
|
||||
if(mosq->state == mosq_cs_disconnecting){
|
||||
rc = MOSQ_ERR_SUCCESS;
|
||||
}else{
|
||||
rc = 1;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->state_mutex);
|
||||
pthread_mutex_lock(&mosq->callback_mutex);
|
||||
if(mosq->on_disconnect){
|
||||
mosq->in_callback = true;
|
||||
mosq->on_disconnect(mosq, mosq->userdata, rc);
|
||||
mosq->in_callback = false;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->callback_mutex);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t _mosquitto_mid_generate(struct mosquitto *mosq)
|
||||
{
|
||||
assert(mosq);
|
||||
|
||||
mosq->last_mid++;
|
||||
if(mosq->last_mid == 0) mosq->last_mid++;
|
||||
|
||||
return mosq->last_mid;
|
||||
}
|
||||
|
||||
/* Search for + or # in a topic. Return MOSQ_ERR_INVAL if found.
|
||||
* Also returns MOSQ_ERR_INVAL if the topic string is too long.
|
||||
* Returns MOSQ_ERR_SUCCESS if everything is fine.
|
||||
*/
|
||||
int _mosquitto_topic_wildcard_len_check(const char *str)
|
||||
{
|
||||
int len = 0;
|
||||
while(str && str[0]){
|
||||
if(str[0] == '+' || str[0] == '#'){
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
len++;
|
||||
str = &str[1];
|
||||
}
|
||||
if(len > 65535) return MOSQ_ERR_INVAL;
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Search for + or # in a topic, check they aren't in invalid positions such as foo/#/bar, foo/+bar or foo/bar#.
|
||||
* Return MOSQ_ERR_INVAL if invalid position found.
|
||||
* Also returns MOSQ_ERR_INVAL if the topic string is too long.
|
||||
* Returns MOSQ_ERR_SUCCESS if everything is fine.
|
||||
*/
|
||||
int _mosquitto_topic_wildcard_pos_check(const char *str)
|
||||
{
|
||||
char c = '\0';
|
||||
int len = 0;
|
||||
while(str && str[0]){
|
||||
if(str[0] == '+'){
|
||||
if((c != '\0' && c != '/') || (str[1] != '\0' && str[1] != '/')){
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
}else if(str[0] == '#'){
|
||||
if((c != '\0' && c != '/') || str[1] != '\0'){
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
}
|
||||
len++;
|
||||
c = str[0];
|
||||
str = &str[1];
|
||||
}
|
||||
if(len > 65535) return MOSQ_ERR_INVAL;
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Does a topic match a subscription? */
|
||||
int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result)
|
||||
{
|
||||
int slen, tlen;
|
||||
int spos, tpos;
|
||||
bool multilevel_wildcard = false;
|
||||
|
||||
if(!sub || !topic || !result) return MOSQ_ERR_INVAL;
|
||||
|
||||
slen = strlen(sub);
|
||||
tlen = strlen(topic);
|
||||
|
||||
if(slen && tlen){
|
||||
if((sub[0] == '$' && topic[0] != '$')
|
||||
|| (topic[0] == '$' && sub[0] != '$')){
|
||||
|
||||
*result = false;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
spos = 0;
|
||||
tpos = 0;
|
||||
|
||||
while(spos < slen && tpos < tlen){
|
||||
if(sub[spos] == topic[tpos]){
|
||||
spos++;
|
||||
tpos++;
|
||||
if(spos == slen && tpos == tlen){
|
||||
*result = true;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else if(tpos == tlen && spos == slen-1 && sub[spos] == '+'){
|
||||
spos++;
|
||||
*result = true;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
}else{
|
||||
if(sub[spos] == '+'){
|
||||
spos++;
|
||||
while(tpos < tlen && topic[tpos] != '/'){
|
||||
tpos++;
|
||||
}
|
||||
if(tpos == tlen && spos == slen){
|
||||
*result = true;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
}else if(sub[spos] == '#'){
|
||||
multilevel_wildcard = true;
|
||||
if(spos+1 != slen){
|
||||
*result = false;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else{
|
||||
*result = true;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
}else{
|
||||
*result = false;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
if(tpos == tlen-1){
|
||||
/* Check for e.g. foo matching foo/# */
|
||||
if(spos == slen-3
|
||||
&& sub[spos+1] == '/'
|
||||
&& sub[spos+2] == '#'){
|
||||
*result = true;
|
||||
multilevel_wildcard = true;
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(multilevel_wildcard == false && (tpos < tlen || spos < slen)){
|
||||
*result = false;
|
||||
}
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef REAL_WITH_TLS_PSK
|
||||
int _mosquitto_hex2bin(const char *hex, unsigned char *bin, int bin_max_len)
|
||||
{
|
||||
BIGNUM *bn = NULL;
|
||||
int len;
|
||||
|
||||
if(BN_hex2bn(&bn, hex) == 0){
|
||||
if(bn) BN_free(bn);
|
||||
return 0;
|
||||
}
|
||||
if(BN_num_bytes(bn) > bin_max_len){
|
||||
BN_free(bn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = BN_bn2bin(bn, bin);
|
||||
BN_free(bn);
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
FILE *_mosquitto_fopen(const char *path, const char *mode)
|
||||
{
|
||||
#ifdef WIN32
|
||||
char buf[MAX_PATH];
|
||||
int rc;
|
||||
rc = ExpandEnvironmentStrings(path, buf, MAX_PATH);
|
||||
if(rc == 0 || rc == MAX_PATH){
|
||||
return NULL;
|
||||
}else{
|
||||
return fopen(buf, mode);
|
||||
}
|
||||
#else
|
||||
return fopen(path, mode);
|
||||
#endif
|
||||
}
|
||||
|
35
lib/util_mosq.h
Normal file
35
lib/util_mosq.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
#ifndef _UTIL_MOSQ_H_
|
||||
#define _UTIL_MOSQ_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "tls_mosq.h"
|
||||
#include "mosquitto.h"
|
||||
|
||||
int _mosquitto_packet_alloc(struct _mosquitto_packet *packet);
|
||||
void _mosquitto_check_keepalive(struct mosquitto *mosq);
|
||||
uint16_t _mosquitto_mid_generate(struct mosquitto *mosq);
|
||||
int _mosquitto_topic_wildcard_len_check(const char *str);
|
||||
int _mosquitto_topic_wildcard_pos_check(const char *str);
|
||||
FILE *_mosquitto_fopen(const char *path, const char *mode);
|
||||
|
||||
#ifdef REAL_WITH_TLS_PSK
|
||||
int _mosquitto_hex2bin(const char *hex, unsigned char *bin, int bin_max_len);
|
||||
#endif
|
||||
|
||||
#endif
|
117
lib/will_mosq.c
Normal file
117
lib/will_mosq.c
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <sys/select.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include <mosquitto_internal.h>
|
||||
#include <logging_mosq.h>
|
||||
#include <messages_mosq.h>
|
||||
#include <memory_mosq.h>
|
||||
#include <mqtt3_protocol.h>
|
||||
#include <net_mosq.h>
|
||||
#include <read_handle.h>
|
||||
#include <send_mosq.h>
|
||||
#include <util_mosq.h>
|
||||
|
||||
int _mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain)
|
||||
{
|
||||
int rc = MOSQ_ERR_SUCCESS;
|
||||
|
||||
if(!mosq || !topic) return MOSQ_ERR_INVAL;
|
||||
if(payloadlen < 0 || payloadlen > MQTT_MAX_PAYLOAD) return MOSQ_ERR_PAYLOAD_SIZE;
|
||||
if(payloadlen > 0 && !payload) return MOSQ_ERR_INVAL;
|
||||
|
||||
if(_mosquitto_topic_wildcard_pos_check(topic)) return MOSQ_ERR_INVAL;
|
||||
|
||||
if(mosq->will){
|
||||
if(mosq->will->topic){
|
||||
_mosquitto_free(mosq->will->topic);
|
||||
mosq->will->topic = NULL;
|
||||
}
|
||||
if(mosq->will->payload){
|
||||
_mosquitto_free(mosq->will->payload);
|
||||
mosq->will->payload = NULL;
|
||||
}
|
||||
_mosquitto_free(mosq->will);
|
||||
mosq->will = NULL;
|
||||
}
|
||||
|
||||
mosq->will = _mosquitto_calloc(1, sizeof(struct mosquitto_message));
|
||||
if(!mosq->will) return MOSQ_ERR_NOMEM;
|
||||
mosq->will->topic = _mosquitto_strdup(topic);
|
||||
if(!mosq->will->topic){
|
||||
rc = MOSQ_ERR_NOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
mosq->will->payloadlen = payloadlen;
|
||||
if(mosq->will->payloadlen > 0){
|
||||
if(!payload){
|
||||
rc = MOSQ_ERR_INVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
mosq->will->payload = _mosquitto_malloc(sizeof(char)*mosq->will->payloadlen);
|
||||
if(!mosq->will->payload){
|
||||
rc = MOSQ_ERR_NOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memcpy(mosq->will->payload, payload, payloadlen);
|
||||
}
|
||||
mosq->will->qos = qos;
|
||||
mosq->will->retain = retain;
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
if(mosq->will){
|
||||
if(mosq->will->topic) _mosquitto_free(mosq->will->topic);
|
||||
if(mosq->will->payload) _mosquitto_free(mosq->will->payload);
|
||||
}
|
||||
_mosquitto_free(mosq->will);
|
||||
mosq->will = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int _mosquitto_will_clear(struct mosquitto *mosq)
|
||||
{
|
||||
if(!mosq->will) return MOSQ_ERR_SUCCESS;
|
||||
|
||||
if(mosq->will->topic){
|
||||
_mosquitto_free(mosq->will->topic);
|
||||
mosq->will->topic = NULL;
|
||||
}
|
||||
if(mosq->will->payload){
|
||||
_mosquitto_free(mosq->will->payload);
|
||||
mosq->will->payload = NULL;
|
||||
}
|
||||
_mosquitto_free(mosq->will);
|
||||
mosq->will = NULL;
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
26
lib/will_mosq.h
Normal file
26
lib/will_mosq.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright (c) 2010-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifndef _WILL_MOSQ_H_
|
||||
#define _WILL_MOSQ_H_
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include <mosquitto_internal.h>
|
||||
|
||||
int _mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain);
|
||||
int _mosquitto_will_clear(struct mosquitto *mosq);
|
||||
|
||||
#endif
|
BIN
logo/mosquitto-14x14.png
Normal file
BIN
logo/mosquitto-14x14.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 513 B |
BIN
logo/mosquitto-16x16.png
Normal file
BIN
logo/mosquitto-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 566 B |
182
logo/mosquitto.svg
Normal file
182
logo/mosquitto.svg
Normal file
@ -0,0 +1,182 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:docname="mosquitto.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
inkscape:export-filename="mosquitto-14x14.png"
|
||||
inkscape:export-xdpi="4.6700001"
|
||||
inkscape:export-ydpi="4.6700001">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="37.857143 : 544.03823 : 1"
|
||||
inkscape:vp_y="6.1230318e-14 : 1000 : 0"
|
||||
inkscape:vp_z="213.38019 : 572.60967 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective10" />
|
||||
<inkscape:perspective
|
||||
id="perspective3301"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
gridtolerance="10000"
|
||||
guidetolerance="10"
|
||||
objecttolerance="10"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="251.61096"
|
||||
inkscape:cy="634.88337"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1272"
|
||||
inkscape:window-height="753"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="197"
|
||||
inkscape:snap-global="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3203"
|
||||
visible="true"
|
||||
enabled="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="opacity:1;fill:#b4b4b4;fill-rule:evenodd;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
|
||||
d="M 260.86695,304.28645 C 344.54685,263.18666 363.31847,267.21909 373.94821,272.53203 C 384.57796,277.84498 400.64729,294.03063 384.36356,296.59165 C 368.07984,299.1527 261.4914,304.19501 260.86695,304.28645 z"
|
||||
id="path3615"
|
||||
inkscape:export-xdpi="5.4099998"
|
||||
inkscape:export-ydpi="5.4099998"
|
||||
sodipodi:nodetypes="cssc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 216.51521,335.41733 C 206.51521,350.41733 206.51521,350.41733 206.51521,350.41733"
|
||||
id="path3333" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#505050;fill-opacity:1;stroke:#000000;stroke-width:0.84779656;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path3317"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="170"
|
||||
sodipodi:cy="187.36218"
|
||||
sodipodi:r1="26.140701"
|
||||
sodipodi:r2="22.638512"
|
||||
sodipodi:arg1="0.29650661"
|
||||
sodipodi:arg2="0.92482514"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0.5"
|
||||
inkscape:randomized="0"
|
||||
d="M 195,195 C 190.5106,209.69463 185.82415,213.22759 170.46143,213.49881 C 155.0987,213.77003 150.29047,210.4047 145.28518,195.87769 C 140.27989,181.35068 141.99469,175.73783 154.26397,166.48843 C 166.53326,157.23902 172.4013,157.13542 184.98942,165.94598 C 197.57755,174.75655 199.4894,180.30537 195,195 z"
|
||||
transform="matrix(2.9181354,2.0819086,-0.5735856,0.4947199,-53.062566,-63.281872)" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#505050;fill-opacity:1;stroke:#000000;stroke-width:1.8490361;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path3311"
|
||||
sodipodi:sides="6"
|
||||
sodipodi:cx="135"
|
||||
sodipodi:cy="217.36218"
|
||||
sodipodi:r1="45.199375"
|
||||
sodipodi:r2="6.9935298"
|
||||
sodipodi:arg1="1.2325185"
|
||||
sodipodi:arg2="1.7561173"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0.5"
|
||||
inkscape:randomized="0"
|
||||
d="M 150,260 C 128.68109,267.5 122.72921,266.38419 105.57457,251.67147 C 88.419922,236.95876 86.410303,231.24637 90.574566,209.03366 C 94.73883,186.82094 98.68109,182.22437 120,174.72436 C 141.31891,167.22436 147.27079,168.34018 164.42543,183.05289 C 181.58008,197.76561 183.5897,203.47799 179.42543,225.69071 C 175.26117,247.90343 171.31891,252.5 150,260 z"
|
||||
transform="matrix(0.2815869,-0.5987297,0.9000736,0.4233112,18.341889,318.68209)"
|
||||
inkscape:transform-center-x="-1.6537315"
|
||||
inkscape:transform-center-y="-28.100021" />
|
||||
<path
|
||||
style="fill:#b4b4b4;fill-rule:evenodd;stroke:#000000;stroke-width:8.14260196999999941;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
|
||||
d="M 270.92519,324.92602 C 386.31832,308.51079 405.06276,321.40568 414.0446,332.49728 C 423.02642,343.58891 427.12695,353.77886 407.60172,350.17225 C 388.0765,346.56566 271.67029,325.07279 270.92519,324.92602 z"
|
||||
id="path3335" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 265.35024,357.10581 C 279.69288,380.33932 285.91337,387.36181 292.21826,395.18703 C 298.52314,403.01225 331.37829,432.56303 332.82486,445.99412"
|
||||
id="path3331"
|
||||
sodipodi:nodetypes="czz" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 235.85531,350.03474 C 222.4213,369.32661 223.69512,395.95703 226.41115,404.58043 C 229.17655,413.36058 231.09933,438.2798 229.34008,450.53982"
|
||||
id="path2397"
|
||||
sodipodi:nodetypes="czz" />
|
||||
<g
|
||||
id="g2393"
|
||||
transform="translate(-65.154839,-78.286822)">
|
||||
<path
|
||||
id="path3211"
|
||||
d="M 244.63358,463.84281 L 221.90526,527.9398 L 255.64196,465.79613 L 244.63358,463.84281"
|
||||
style="fill:#505050;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
transform="matrix(1.0318345,0.7670587,-0.7670587,1.0318345,311.26509,-19.08815)"
|
||||
d="M 200,314.86218 A 17.5,17.5 0 1 1 165,314.86218 A 17.5,17.5 0 1 1 200,314.86218 z"
|
||||
sodipodi:ry="17.5"
|
||||
sodipodi:rx="17.5"
|
||||
sodipodi:cy="314.86218"
|
||||
sodipodi:cx="182.5"
|
||||
id="path3207"
|
||||
style="fill:#505050;fill-opacity:1;stroke:#000000;stroke-width:1.16666663;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="translate(-5,0)"
|
||||
d="M 260,447.36218 A 5,5 0 1 1 250,447.36218 A 5,5 0 1 1 260,447.36218 z"
|
||||
sodipodi:ry="5"
|
||||
sodipodi:rx="5"
|
||||
sodipodi:cy="447.36218"
|
||||
sodipodi:cx="255"
|
||||
id="path3169"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.79999995;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
sodipodi:type="arc" />
|
||||
<rect
|
||||
y="448.10907"
|
||||
x="249.32576"
|
||||
height="0.36382446"
|
||||
width="0.23755538"
|
||||
id="rect3179"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.64632809;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 250.36808,354.60187 C 252.08382,378.84553 262.04352,388.50653 265.11426,398.23893 C 268.22732,408.10542 280.46706,426.82267 279.96198,447.53079"
|
||||
id="path3170"
|
||||
sodipodi:nodetypes="czz" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.6 KiB |
5
man/CMakeLists.txt
Normal file
5
man/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
install(FILES mosquitto_passwd.1 mosquitto_pub.1 mosquitto_sub.1 DESTINATION $(MANDIR)/man1)
|
||||
install(FILES libmosquitto.3 DESTINATION $(MANDIR)/man3)
|
||||
install(FILES mosquitto.conf.5 DESTINATION $(MANDIR)/man5)
|
||||
install(FILES mosquitto-tls.7 mqtt.7 DESTINATION $(MANDIR)/man7)
|
||||
install(FILES mosquitto.8 DESTINATION $(MANDIR)/man8)
|
74
man/Makefile
Normal file
74
man/Makefile
Normal file
@ -0,0 +1,74 @@
|
||||
include ../config.mk
|
||||
|
||||
.PHONY : all clean install uninstall dist
|
||||
|
||||
all : mosquitto.8 mosquitto-tls.7 mosquitto.conf.5 mosquitto_passwd.1 mosquitto_pub.1 mosquitto_sub.1 mqtt.7 libmosquitto.3
|
||||
|
||||
clean :
|
||||
|
||||
reallyclean : clean
|
||||
-rm -f *.orig
|
||||
|
||||
dist : mosquitto.8 mosquitto-tls.7 mosquitto.conf.5 mosquitto_passwd.1 mosquitto_pub.1 mosquitto_sub.1 mqtt.7 libmosquitto.3
|
||||
|
||||
install :
|
||||
$(INSTALL) -d ${DESTDIR}$(mandir)/man8
|
||||
$(INSTALL) -m 644 mosquitto.8 ${DESTDIR}${mandir}/man8/mosquitto.8
|
||||
$(INSTALL) -d ${DESTDIR}$(mandir)/man5
|
||||
$(INSTALL) -m 644 mosquitto.conf.5 ${DESTDIR}${mandir}/man5/mosquitto.conf.5
|
||||
$(INSTALL) -d ${DESTDIR}$(mandir)/man1
|
||||
$(INSTALL) -m 644 mosquitto_passwd.1 ${DESTDIR}${mandir}/man1/mosquitto_passwd.1
|
||||
$(INSTALL) -m 644 mosquitto_pub.1 ${DESTDIR}${mandir}/man1/mosquitto_pub.1
|
||||
$(INSTALL) -m 644 mosquitto_sub.1 ${DESTDIR}${mandir}/man1/mosquitto_sub.1
|
||||
$(INSTALL) -d ${DESTDIR}$(mandir)/man7
|
||||
$(INSTALL) -m 644 mqtt.7 ${DESTDIR}${mandir}/man7/mqtt.7
|
||||
$(INSTALL) -m 644 mosquitto-tls.7 ${DESTDIR}${mandir}/man7/mosquitto-tls.7
|
||||
$(INSTALL) -d ${DESTDIR}$(mandir)/man3
|
||||
$(INSTALL) -m 644 libmosquitto.3 ${DESTDIR}${mandir}/man3/libmosquitto.3
|
||||
|
||||
uninstall :
|
||||
-rm -f ${DESTDIR}${mandir}/man8/mosquitto.8
|
||||
-rm -f ${DESTDIR}${mandir}/man5/mosquitto.conf.5
|
||||
-rm -f ${DESTDIR}${mandir}/man1/mosquitto_passwd.1
|
||||
-rm -f ${DESTDIR}${mandir}/man1/mosquitto_pub.1
|
||||
-rm -f ${DESTDIR}${mandir}/man1/mosquitto_sub.1
|
||||
-rm -f ${DESTDIR}${mandir}/man7/mqtt.7
|
||||
-rm -f ${DESTDIR}${mandir}/man7/mosquitto-tls.7
|
||||
-rm -f ${DESTDIR}${mandir}/man3/libmosquitto.3
|
||||
|
||||
mosquitto.8 : mosquitto.8.xml
|
||||
$(XSLTPROC) $^
|
||||
|
||||
mosquitto.conf.5 : mosquitto.conf.5.xml manpage.xsl
|
||||
$(XSLTPROC) $<
|
||||
|
||||
mosquitto_passwd.1 : mosquitto_passwd.1.xml
|
||||
$(XSLTPROC) $^
|
||||
|
||||
mosquitto_pub.1 : mosquitto_pub.1.xml
|
||||
$(XSLTPROC) $^
|
||||
|
||||
mosquitto_sub.1 : mosquitto_sub.1.xml
|
||||
$(XSLTPROC) $^
|
||||
|
||||
mqtt.7 : mqtt.7.xml
|
||||
$(XSLTPROC) $^
|
||||
|
||||
mosquitto-tls.7 : mosquitto-tls.7.xml
|
||||
$(XSLTPROC) $^
|
||||
|
||||
libmosquitto.3 : libmosquitto.3.xml
|
||||
$(XSLTPROC) $^
|
||||
|
||||
potgen :
|
||||
xml2po -o po/mosquitto/mosquitto.8.pot mosquitto.8.xml
|
||||
xml2po -o po/mosquitto.conf/mosquitto.conf.5.pot mosquitto.conf.5.xml
|
||||
xml2po -o po/mosquitto_passwd/mosquitto_passwd.1.pot mosquitto_passwd.1.xml
|
||||
xml2po -o po/mosquitto_pub/mosquitto_pub.1.pot mosquitto_pub.1.xml
|
||||
xml2po -o po/mosquitto_sub/mosquitto_sub.1.pot mosquitto_sub.1.xml
|
||||
xml2po -o po/mqtt/mqtt.7.pot mqtt.7.xml
|
||||
xml2po -o po/mosquitto-tls/mosquitto-tls.7.pot mosquitto-tls.7.xml
|
||||
xml2po -o po/libmosquitto/libmosquitto.3.pot libmosquitto.3.xml
|
||||
|
||||
# To merge new translations do:
|
||||
# /usr/bin/xml2po -p de.po chapter1.xml > chapter1.de.xml
|
7
man/html.xsl
Normal file
7
man/html.xsl
Normal file
@ -0,0 +1,7 @@
|
||||
<!-- Set parameters for manpage xsl -->
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:import href="/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl"/>
|
||||
<xsl:param name="html.stylesheet">man.css</xsl:param>
|
||||
<!-- Generate ansi style function synopses. -->
|
||||
<xsl:param name="man.funcsynopsis.style">ansi</xsl:param>
|
||||
</xsl:stylesheet>
|
487
man/libmosquitto.3.xml
Normal file
487
man/libmosquitto.3.xml
Normal file
@ -0,0 +1,487 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml-stylesheet type="text/xsl" href="manpage.xsl"?>
|
||||
|
||||
<refentry xml:id="libmosquitto" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<refmeta>
|
||||
<refentrytitle>libmosquitto</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
<refmiscinfo class="source">Mosquitto Project</refmiscinfo>
|
||||
<refmiscinfo class="manual">Library calls</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>libmosquitto</refname>
|
||||
<refpurpose>MQTT version 3.1 client library</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para>This is an overview of how to use libmosquitto to create MQTT
|
||||
aware client programs. There may be separate man pages on each of the
|
||||
functions described here in the future. There is also a binding for
|
||||
libmosquitto for C++ and a Python implementation. They are not
|
||||
documented here but operate in a similar way.</para>
|
||||
<para>This is fairly incomplete, please see mosquitto.h for a better
|
||||
description of the functions.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>libmosquitto symbol names</title>
|
||||
<para>All public functions in libmosquitto have the prefix
|
||||
"mosquitto_". Any other functions defined in the source code are to be
|
||||
treated as private functions and may change between any release. Do not
|
||||
use these functions!</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Functions</title>
|
||||
|
||||
<refsect2>
|
||||
<title>Library version</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_lib_version</function></funcdef>
|
||||
<paramdef>int *<parameter>major</parameter></paramdef>
|
||||
<paramdef>int *<parameter>minor</parameter></paramdef>
|
||||
<paramdef>int *<parameter>revision</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
<para>Obtain version information about the library. If any of
|
||||
major, minor or revision are not NULL they will return the
|
||||
corresponding version numbers. The return value is an integer
|
||||
representation of the complete version number (e.g. 1009001 for 1.9.1)
|
||||
that can be used for comparisons.</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Library initialisation and cleanup</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_lib_init</function></funcdef>
|
||||
<void/></funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_lib_cleanup</function></funcdef>
|
||||
<void/></funcprototype></funcsynopsis>
|
||||
<para>Call mosquitto_lib_init() before using any of the other
|
||||
library functions and mosquitto_lib_cleanup() after finishing
|
||||
with the library.</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Client constructor/destructor</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>struct mosquitto *<function>mosquitto_new</function></funcdef>
|
||||
<paramdef>const char *<parameter>id</parameter></paramdef>
|
||||
<paramdef>bool <parameter>clean_session</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
<para>Create a new mosquitto client instance.</para>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>void <function>mosquitto_destroy</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
<para>Use to free memory associated with a mosquitto client instance.</para>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_reinitialise</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>id</parameter></paramdef>
|
||||
<paramdef>bool <parameter>clean_session</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Authentication and encryption</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_username_pw_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>username</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>password</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_tls_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>cafile</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>capath</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>certfile</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>keyfile</parameter></paramdef>
|
||||
<paramdef>int <parameter>(*pw_callback)(char *buf, int size, int rwflag, void *userdata)</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_tls_opts_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>int <parameter>cert_reqs</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>tls_version</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>ciphers</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_tls_insecure_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>bool <parameter>value</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_tls_psk_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>psk</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>identity</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>ciphers</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Wills</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_will_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>topic</parameter></paramdef>
|
||||
<paramdef>int <parameter>payloadlen</parameter></paramdef>
|
||||
<paramdef>const void *<parameter>payload</parameter></paramdef>
|
||||
<paramdef>int <parameter>qos</parameter></paramdef>
|
||||
<paramdef>bool <parameter>retain</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_will_clear</function></funcdef>
|
||||
<paramdef><parameter>struct mosquitto *mosq</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Connect/disconnect</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_connect</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>host</parameter></paramdef>
|
||||
<paramdef>int <parameter>port</parameter></paramdef>
|
||||
<paramdef>int <parameter>keepalive</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_connect_bind</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>host</parameter></paramdef>
|
||||
<paramdef>int <parameter>port</parameter></paramdef>
|
||||
<paramdef>int <parameter>keepalive</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>bind_address</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_connect_async</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>host</parameter></paramdef>
|
||||
<paramdef>int <parameter>port</parameter></paramdef>
|
||||
<paramdef>int <parameter>keepalive</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_connect_bind_async</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>host</parameter></paramdef>
|
||||
<paramdef>int <parameter>port</parameter></paramdef>
|
||||
<paramdef>int <parameter>keepalive</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>bind_address</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_reconnect</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_reconnect_async</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_disconnect</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Publish</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_publish</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>int *<parameter>mid</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>topic</parameter></paramdef>
|
||||
<paramdef>int <parameter>payloadlen</parameter></paramdef>
|
||||
<paramdef>const void *<parameter>payload</parameter></paramdef>
|
||||
<paramdef>int <parameter>qos</parameter></paramdef>
|
||||
<paramdef>bool <parameter>retain</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Subscribe/unsubscribe</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_subscribe</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>int *<parameter>mid</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>sub</parameter></paramdef>
|
||||
<paramdef>int <parameter>qos</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_unsubscribe</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>int *<parameter>mid</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>sub</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Network loop</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_loop</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>int <parameter>timeout</parameter></paramdef>
|
||||
<paramdef>int <parameter>max_packets</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_loop_read</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>int <parameter>max_packets</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_loop_write</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>int <parameter>max_packets</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_loop_misc</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_loop_forever</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>int <parameter>timeout</parameter></paramdef>
|
||||
<paramdef>int <parameter>max_packets</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_socket</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>bool <function>mosquitto_want_write</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Threaded network loop</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_loop_start</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_loop_stop</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>bool <parameter>force</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Misc client functions</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_max_inflight_messages_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>unsigned int <parameter>max_inflight_messages</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_message_retry_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>unsigned int <parameter>message_retry</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_reconnect_delay_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>unsigned int <parameter>reconnect_delay</parameter></paramdef>
|
||||
<paramdef>unsigned int <parameter>reconnect_delay_max</parameter></paramdef>
|
||||
<paramdef>bool <parameter>reconnect_exponential_backoff</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_user_data_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Callbacks</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_connect_callback_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>void <parameter>(*on_connect)(struct mosquitto *, void *, int)</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_disconnect_callback_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>void <parameter>(*on_disconnect)(struct mosquitto *, void *, int)</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_publish_callback_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>void <parameter>(*on_publish)(struct mosquitto *, void *, int)</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_message_callback_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>void <parameter>(*on_message)(struct mosquitto *, void *, const struct mosquitto_message *)</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_subscribe_callback_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>void <parameter>(*on_subscribe)(struct mosquitto *, void *, int, int, const int *)</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_unsubscribe_callback_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>void <parameter>(*on_unsubscribe)(struct mosquitto *, void *, int)</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_log_callback_set</function></funcdef>
|
||||
<paramdef>struct mosquitto *<parameter>mosq</parameter></paramdef>
|
||||
<paramdef>void <parameter>(*on_unsubscribe)(struct mosquitto *, void *, int, const char *)</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Utility functions</title>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>const char *<function>mosquitto_connack_string</function></funcdef>
|
||||
<paramdef>int <parameter>connack_code</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_message_copy</function></funcdef>
|
||||
<paramdef>struct mosquitto_message *<parameter>dst</parameter></paramdef>
|
||||
<paramdef>const struct mosquitto_message *<parameter>src</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_message_free</function></funcdef>
|
||||
<paramdef>struct mosquitto_message **<parameter>message</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>const char *<function>mosquitto_strerror</function></funcdef>
|
||||
<paramdef>int <parameter>mosq_errno</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_sub_topic_tokenise</function></funcdef>
|
||||
<paramdef>const char *<parameter>subtopic</parameter></paramdef>
|
||||
<paramdef>char ***<parameter>topics</parameter></paramdef>
|
||||
<paramdef>int *<parameter>count</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_sub_topic_tokens_free</function></funcdef>
|
||||
<paramdef>char ***<parameter>topics</parameter></paramdef>
|
||||
<paramdef>int <parameter>count</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
|
||||
<funcsynopsis><funcprototype><funcdef>int <function>mosquitto_topic_matches_sub</function></funcdef>
|
||||
<paramdef>const char *<parameter>sub</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>topic</parameter></paramdef>
|
||||
<paramdef>bool *<parameter>result</parameter></paramdef>
|
||||
</funcprototype></funcsynopsis>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
<para><programlisting language="C">
|
||||
#include <stdio.h>
|
||||
#include <mosquitto.h>
|
||||
|
||||
void my_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
|
||||
{
|
||||
if(message->payloadlen){
|
||||
printf("%s %s\n", message->topic, message->payload);
|
||||
}else{
|
||||
printf("%s (null)\n", message->topic);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void my_connect_callback(struct mosquitto *mosq, void *userdata, int result)
|
||||
{
|
||||
int i;
|
||||
if(!result){
|
||||
/* Subscribe to broker information topics on successful connect. */
|
||||
mosquitto_subscribe(mosq, NULL, "$SYS/#", 2);
|
||||
}else{
|
||||
fprintf(stderr, "Connect failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void my_subscribe_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("Subscribed (mid: %d): %d", mid, granted_qos[0]);
|
||||
for(i=1; i<qos_count; i++){
|
||||
printf(", %d", granted_qos[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void my_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str)
|
||||
{
|
||||
/* Pring all log messages regardless of level. */
|
||||
printf("%s\n", str);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char id[30];
|
||||
int i;
|
||||
char *host = "localhost";
|
||||
int port = 1883;
|
||||
int keepalive = 60;
|
||||
bool clean_session = true;
|
||||
struct mosquitto *mosq = NULL;
|
||||
|
||||
mosquitto_lib_init();
|
||||
mosq = mosquitto_new(id, clean_session, NULL);
|
||||
if(!mosq){
|
||||
fprintf(stderr, "Error: Out of memory.\n");
|
||||
return 1;
|
||||
}
|
||||
mosquitto_log_callback_set(mosq, my_log_callback);
|
||||
|
||||
mosquitto_connect_callback_set(mosq, my_connect_callback);
|
||||
mosquitto_message_callback_set(mosq, my_message_callback);
|
||||
mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);
|
||||
|
||||
if(mosquitto_connect(mosq, host, port, keepalive)){
|
||||
fprintf(stderr, "Unable to connect.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(!mosquitto_loop(mosq, -1)){
|
||||
}
|
||||
mosquitto_destroy(mosq);
|
||||
mosquitto_lib_cleanup();
|
||||
return 0;
|
||||
}
|
||||
</programlisting></para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<simplelist type="inline">
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-8.html">mosquitto</link></refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mqtt-7.html">mqtt</link></refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Acknowledgements</title>
|
||||
<para>This product includes software developed by the OpenSSL Project
|
||||
for use in the OpenSSL Toolkit. (http://www.openssl.org/)</para>
|
||||
<para>This product includes cryptographic software written by Eric
|
||||
Young (eay@cryptsoft.com)</para>
|
||||
<para>This product includes software written by Tim Hudson
|
||||
(tjh@cryptsoft.com)</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Author</title>
|
||||
<para>Roger Light <email>roger@atchoo.org</email></para>
|
||||
</refsect1>
|
||||
</refentry>
|
14
man/manpage.xsl
Normal file
14
man/manpage.xsl
Normal file
@ -0,0 +1,14 @@
|
||||
<!-- Set parameters for manpage xsl -->
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:import href="/usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl"/>
|
||||
<xsl:strip-space elements="member"/>
|
||||
<!-- Don't display notes list of link urls. -->
|
||||
<xsl:param name="man.endnotes.list.enabled">0</xsl:param>
|
||||
<xsl:param name="man.endnotes.are.numbered">0</xsl:param>
|
||||
<!-- But if we do, set a base url for the relative links. -->
|
||||
<xsl:param name="man.base.url.for.relative.links">http://mosquitto.org/man/</xsl:param>
|
||||
<!-- Don't output filename when generating. -->
|
||||
<xsl:param name="man.output.quietly" select="1"></xsl:param>
|
||||
<!-- Generate ansi style function synopses. -->
|
||||
<xsl:param name="man.funcsynopsis.style">ansi</xsl:param>
|
||||
</xsl:stylesheet>
|
100
man/mosquitto-tls.7.xml
Normal file
100
man/mosquitto-tls.7.xml
Normal file
@ -0,0 +1,100 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml-stylesheet type="text/xsl" href="manpage.xsl"?>
|
||||
|
||||
<refentry xml:id="mosquitto-tls" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<refmeta>
|
||||
<refentrytitle>mosquitto-tls</refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
<refmiscinfo class="source">Mosquitto Project</refmiscinfo>
|
||||
<refmiscinfo class="manual">Conventions and miscellaneous</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>mosquitto-tls</refname>
|
||||
<refpurpose>Configure SSL/TLS support for Mosquitto</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para><command>mosquitto</command> provides SSL support for encrypted
|
||||
network connections and authentication. This manual describes how
|
||||
to create the files needed.</para>
|
||||
<note><para>It is important to use different certificate subject
|
||||
parameters for your CA, server and clients. If the certificates
|
||||
appear identical, even though generated separately, the
|
||||
broker/client will not be able to distinguish between them and
|
||||
you will experience difficult to diagnose errors.</para></note>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Certificate Authority</title>
|
||||
<para>Generate a certificate authority certificate and key.</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>openssl req -new -x509 -days <duration> -extensions v3_ca -keyout ca.key -out ca.crt</para></listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Server</title>
|
||||
<para>Generate a server key.</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>openssl genrsa -des3 -out server.key 2048</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Generate a server key without encryption.</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>openssl genrsa -out server.key 2048</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Generate a certificate signing request to send to the CA.</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>openssl req -out server.csr -key server.key -new</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Send the CSR to the CA, or sign it with your CA key:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days <duration></para></listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Client</title>
|
||||
<para>Generate a client key.</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>openssl genrsa -des3 -out client.key 2048</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Generate a certificate signing request to send to the CA.</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>openssl req -out client.csr -key client.key -new</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Send the CSR to the CA, or sign it with your CA key:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days <duration></para></listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<simplelist type="inline">
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-8.html">mosquitto</link></refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-conf-5.html">mosquitto-conf</link></refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Author</title>
|
||||
<para>Roger Light <email>roger@atchoo.org</email></para>
|
||||
</refsect1>
|
||||
</refentry>
|
559
man/mosquitto.8.xml
Normal file
559
man/mosquitto.8.xml
Normal file
@ -0,0 +1,559 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml-stylesheet type="text/xsl" href="manpage.xsl"?>
|
||||
|
||||
<refentry xml:id="mosquitto" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<refmeta>
|
||||
<refentrytitle>mosquitto</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
<refmiscinfo class="source">Mosquitto Project</refmiscinfo>
|
||||
<refmiscinfo class="manual">System management commands</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>mosquitto</refname>
|
||||
<refpurpose>an MQTT broker</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>mosquitto</command>
|
||||
<arg>-c <replaceable>config file</replaceable></arg>
|
||||
<group>
|
||||
<arg choice='plain'>-d</arg>
|
||||
<arg choice='plain'>--daemon</arg>
|
||||
</group>
|
||||
<arg>-p <replaceable>port number</replaceable></arg>
|
||||
<arg>-v</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para><command>mosquitto</command> is a broker for the MQTT protocol version 3.1.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-c</option></term>
|
||||
<term><option>--config-file</option></term>
|
||||
<listitem>
|
||||
<para>Load configuration from a file. If not given, the default values as described in <citerefentry><refentrytitle>mosquitto.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> are used.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-d</option></term>
|
||||
<term><option>--daemon</option></term>
|
||||
<listitem>
|
||||
<para>Run <command>mosquitto</command> in the background as a daemon. All other behaviour remains the same.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-p</option></term>
|
||||
<term><option>--port</option></term>
|
||||
<listitem>
|
||||
<para>Listen on the port specified instead of the default 1883. This acts in addition to the port setting in the config file. May be specified multiple times to open multiple sockets listening on different ports. This socket will be bound to all network interfaces.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-v</option></term>
|
||||
<term><option>--verbose</option></term>
|
||||
<listitem>
|
||||
<para>Use verbose logging. This is equivalent to setting
|
||||
<option>log_type</option> to <option>all</option> in
|
||||
the configuration file. This overrides and logging
|
||||
options given in the configuration file.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Configuration</title>
|
||||
<para>The broker can be configured using a configuration file as
|
||||
described in
|
||||
<citerefentry><refentrytitle>mosquitto.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
and this is the main point of information for mosquitto.
|
||||
The files required for SSL/TLS support are described in
|
||||
<citerefentry><refentrytitle>mosquitto-tls</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Broker Status</title>
|
||||
<para>Clients can find information about the broker by subscribing to
|
||||
topics in the $SYS hierarchy as follows. Topics marked as static are
|
||||
only sent once per client on subscription. All other topics are updated
|
||||
every <option>sys_interval</option> seconds. If
|
||||
<option>sys_interval</option> is 0, then updates are not sent.</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/bytes/received</option></term>
|
||||
<listitem>
|
||||
<para>The total number of bytes received since the broker
|
||||
started.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/bytes/sent</option></term>
|
||||
<listitem>
|
||||
<para>The total number of bytes sent since the broker
|
||||
started.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/changeset</option></term>
|
||||
<listitem>
|
||||
<para>The repository changeset (revision) associated with
|
||||
this build. Static.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/clients/active</option></term>
|
||||
<listitem>
|
||||
<para>The number of currently connected clients</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/clients/expired</option></term>
|
||||
<listitem>
|
||||
<para>The number of disconnected persistent clients that
|
||||
have been expired and removed through the
|
||||
persistent_client_expiration option.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/clients/inactive</option></term>
|
||||
<listitem>
|
||||
<para>The total number of persistent clients (with clean
|
||||
session disabled) that are registered at the broker but are
|
||||
currently disconnected.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/clients/maximum</option></term>
|
||||
<listitem>
|
||||
<para>The maximum number of active clients that have been
|
||||
connected to the broker. This is only calculated when the
|
||||
$SYS topic tree is updated, so short lived client
|
||||
connections may not be counted.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/clients/total</option></term>
|
||||
<listitem>
|
||||
<para>The total number of active and inactive clients
|
||||
currently connected and registered on the
|
||||
broker.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/connection/#</option></term>
|
||||
<listitem>
|
||||
<para>When bridges are configured to/from the broker,
|
||||
common practice is to provide a status topic that
|
||||
indicates the state of the connection. This is provided
|
||||
within $SYS/broker/connection/ by default. If the value
|
||||
of the topic is 1 the connection is active, if 0 then
|
||||
it is not active. See the Bridges section below for
|
||||
more information on bridges.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/heap/current size</option></term>
|
||||
<listitem>
|
||||
<para>The current size of the heap memory in use by
|
||||
mosquitto. Note that this topic may be unavailable
|
||||
depending on compile time options.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/heap/maximum size</option></term>
|
||||
<listitem>
|
||||
<para>The largest amount of heap memory used by
|
||||
mosquitto. Note that this topic may be unavailable
|
||||
depending on compile time options.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/load/connections/+</option></term>
|
||||
<listitem>
|
||||
<para>The moving average of the number of CONNECT packets
|
||||
received by the broker over different time intervals.
|
||||
The final "+" of the hierarchy can be 1min, 5min or
|
||||
15min. The value returned represents the number of
|
||||
connections received in 1 minute, averaged over 1, 5 or
|
||||
15 minutes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/load/bytes/received/+</option></term>
|
||||
<listitem>
|
||||
<para>The moving average of the number of bytes received by
|
||||
the broker over different time intervals. The final "+"
|
||||
of the hierarchy can be 1min, 5min or 15min. The value
|
||||
returned represents the number of bytes received in 1
|
||||
minute, averaged over 1, 5 or 15 minutes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/load/bytes/sent/+</option></term>
|
||||
<listitem>
|
||||
<para>The moving average of the number of bytes sent by the
|
||||
broker over different time intervals. The final "+" of
|
||||
the hierarchy can be 1min, 5min or 15min. The value
|
||||
returned represents the number of bytes sent in 1
|
||||
minute, averaged over 1, 5 or 15 minutes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/load/messages/received/+</option></term>
|
||||
<listitem>
|
||||
<para>The moving average of the number of all types of MQTT
|
||||
messages received by the broker over different time
|
||||
intervals. The final "+" of the hierarchy can be 1min,
|
||||
5min or 15min. The value returned represents the number
|
||||
of messages received in 1 minute, averaged over 1, 5 or
|
||||
15 minutes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/load/messages/sent/+</option></term>
|
||||
<listitem>
|
||||
<para>The moving average of the number of all types of MQTT
|
||||
messages sent by the broker over different time
|
||||
intervals. The final "+" of the hierarchy can be 1min,
|
||||
5min or 15min. The value returned represents the number
|
||||
of messages send in 1 minute, averaged over 1, 5 or 15
|
||||
minutes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/load/publish/dropped/+</option></term>
|
||||
<listitem>
|
||||
<para>The moving average of the number of publish messages
|
||||
dropped by the broker over different time intervals.
|
||||
This shows the rate at which durable clients that are
|
||||
disconnected are losing messages. The final "+" of the
|
||||
hierarchy can be 1min, 5min or 15min. The value
|
||||
returned represents the number of messages dropped in 1
|
||||
minute, averaged over 1, 5 or 15 minutes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/load/publish/received/+</option></term>
|
||||
<listitem>
|
||||
<para>The moving average of the number of publish messages
|
||||
received by the broker over different time intervals.
|
||||
The final "+" of the hierarchy can be 1min, 5min or
|
||||
15min. The value returned represents the number of
|
||||
publish messages received in 1 minute, averaged over 1,
|
||||
5 or 15 minutes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/load/publish/sent/+</option></term>
|
||||
<listitem>
|
||||
<para>The moving average of the number of publish messages
|
||||
sent by the broker over different time intervals. The
|
||||
final "+" of the hierarchy can be 1min, 5min or 15min.
|
||||
The value returned represents the number of publish
|
||||
messages sent in 1 minute, averaged over 1, 5 or 15
|
||||
minutes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/load/sockets/+</option></term>
|
||||
<listitem>
|
||||
<para>The moving average of the number of socket
|
||||
connections opened to the broker over different time
|
||||
intervals. The final "+" of the hierarchy can be 1min,
|
||||
5min or 15min. The value returned represents the number
|
||||
of socket connections in 1 minute, averaged over 1, 5
|
||||
or 15 minutes.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/messages/inflight</option></term>
|
||||
<listitem>
|
||||
<para>The number of messages with QoS>0 that are awaiting
|
||||
acknowledgments.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/messages/received</option></term>
|
||||
<listitem>
|
||||
<para>The total number of messages of any type received since the broker started.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/messages/sent</option></term>
|
||||
<listitem>
|
||||
<para>The total number of messages of any type sent since the broker started.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/messages/stored</option></term>
|
||||
<listitem>
|
||||
<para>The number of messages currently held in the message
|
||||
store. This includes retained messages and messages
|
||||
queued for durable clients.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/publish/messages/dropped</option></term>
|
||||
<listitem>
|
||||
<para>The total number of publish messages that have been
|
||||
dropped due to inflight/queuing limits. See the
|
||||
max_inflight_messages and max_queued_messages options
|
||||
in
|
||||
<citerefentry><refentrytitle>mosquitto.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for more information.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/publish/messages/received</option></term>
|
||||
<listitem>
|
||||
<para>The total number of PUBLISH messages received since the broker started.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/publish/messages/sent</option></term>
|
||||
<listitem>
|
||||
<para>The total number of PUBLISH messages sent since the broker started.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/retained messages/count</option></term>
|
||||
<listitem>
|
||||
<para>The total number of retained messages active on the broker.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/subscriptions/count</option></term>
|
||||
<listitem>
|
||||
<para>The total number of subscriptions active on the broker.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/timestamp</option></term>
|
||||
<listitem>
|
||||
<para>The timestamp at which this particular build of the broker was made. Static.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/uptime</option></term>
|
||||
<listitem>
|
||||
<para>The amount of time in seconds the broker has been online.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>$SYS/broker/version</option></term>
|
||||
<listitem>
|
||||
<para>The version of the broker. Static.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Wildcard Topic Subscriptions</title>
|
||||
<para>In addition to allowing clients to subscribe to specific topics,
|
||||
mosquitto also allows the use of two wildcards in subscriptions.
|
||||
<option>+</option> is the wildcard used to match a single level of
|
||||
hierarchy. For example, for a topic of "a/b/c/d", the following example
|
||||
subscriptions will match:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>a/b/c/d</para></listitem>
|
||||
<listitem><para>+/b/c/d</para></listitem>
|
||||
<listitem><para>a/+/c/d</para></listitem>
|
||||
<listitem><para>a/+/+/d</para></listitem>
|
||||
<listitem><para>+/+/+/+</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>The following subscriptions will not match:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>a/b/c</para></listitem>
|
||||
<listitem><para>b/+/c/d</para></listitem>
|
||||
<listitem><para>+/+/+</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>The second wildcard is <option>#</option> and is used to match
|
||||
all subsequent levels of hierarchy. With a topic of "a/b/c/d", the
|
||||
following example subscriptions will match:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>a/b/c/d</para></listitem>
|
||||
<listitem><para>#</para></listitem>
|
||||
<listitem><para>a/#</para></listitem>
|
||||
<listitem><para>a/b/#</para></listitem>
|
||||
<listitem><para>a/b/c/#</para></listitem>
|
||||
<listitem><para>+/b/c/#</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>The $SYS hierarchy does not match a subscription of
|
||||
"#". If you want to observe the entire $SYS hierarchy, subscribe to
|
||||
$SYS/#.</para>
|
||||
<para>Note that the wildcards must be only ever used on their own, so a
|
||||
subscription of "a/b+/c" is not valid use of a wildcard. The
|
||||
<option>#</option> wildcard must only ever be used as the final
|
||||
character of a subscription.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Bridges</title>
|
||||
<para>Multiple brokers can be connected together with the bridging
|
||||
functionality. This is useful where it is desirable to share
|
||||
information between locations, but where not all of the information
|
||||
needs to be shared. An example could be where a number of users are
|
||||
running a broker to help record power usage and for a number of other
|
||||
reasons. The power usage could be shared through bridging all of the
|
||||
user brokers to a common broker, allowing the power usage of all
|
||||
users to be collected and compared. The other information would remain
|
||||
local to each
|
||||
broker.</para>
|
||||
<para>For information on configuring bridges, see
|
||||
<citerefentry><refentrytitle>mosquitto.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Signals</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>SIGHUP</term>
|
||||
<listitem>
|
||||
<para>Upon receiving the SIGHUP signal, mosquitto will
|
||||
attempt to reload configuration file data, assuming that
|
||||
the <option>-c</option> argument was provided when
|
||||
mosquitto was started. Not all configuration parameters can
|
||||
be reloaded without restarting. See
|
||||
<citerefentry><refentrytitle>mosquitto.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>SIGUSR1</term>
|
||||
<listitem>
|
||||
<para>Upon receiving the SIGUSR1 signal, mosquitto will
|
||||
write the persistence database to disk. This signal is only
|
||||
acted upon if persistence is enabled.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>SIGUSR2</term>
|
||||
<listitem>
|
||||
<para>The SIGUSR2 signal causes mosquitto to print out the
|
||||
current subscription tree, along with information about
|
||||
where retained messages exist. This is intended as a
|
||||
testing feature only and may be removed at any time.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Files</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><filename>/etc/mosquitto/mosquitto.conf</filename></term>
|
||||
<listitem>
|
||||
<para>Configuration file. See <citerefentry><refentrytitle>mosquitto.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>/var/lib/mosquitto/mosquitto.db</filename></term>
|
||||
<listitem>
|
||||
<para>Persistent message data storage location if persist enabled.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>/etc/hosts.allow</filename></term>
|
||||
<term><filename>/etc/hosts.deny</filename></term>
|
||||
<listitem>
|
||||
<para>Host access control via tcp-wrappers as described in <citerefentry><refentrytitle>hosts_access</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Bugs</title>
|
||||
<para><command>mosquitto</command> bug information can be found at <uri type="webpage">http://launchpad.net/mosquitto</uri></para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<simplelist type="inline">
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mqtt-7.html">mqtt</link></refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-tls-7.html">mosquitto-tls</link></refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-conf-5.html">mosquitto.conf</link></refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="http://www.linuxmanpages.com/man5/hosts_access.5.php">hosts_access</link></refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto_passwd-1.html">mosquitto_passwd</link></refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto_pub-1.html">mosquitto_pub</link></refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto_sub-1.html">mosquitto_sub</link></refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="libmosquitto-3.html">libmosquitto</link></refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Thanks</title>
|
||||
<para>Thanks to Andy Stanford-Clark for being one of the people who
|
||||
came up with MQTT in the first place. Thanks to Andy and Nicholas
|
||||
O'Leary for providing clarifications of the protocol.</para>
|
||||
<para>Thanks also to everybody at the Ubuntu UK Podcast and Linux
|
||||
Outlaws for organising OggCamp, where Andy gave a talk that
|
||||
inspired mosquitto.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Acknowledgements</title>
|
||||
<para>This product includes software developed by the OpenSSL Project
|
||||
for use in the OpenSSL Toolkit. (http://www.openssl.org/)</para>
|
||||
<para>This product includes cryptographic software written by Eric
|
||||
Young (eay@cryptsoft.com)</para>
|
||||
<para>This product includes software written by Tim Hudson
|
||||
(tjh@cryptsoft.com)</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Author</title>
|
||||
<para>Roger Light <email>roger@atchoo.org</email></para>
|
||||
</refsect1>
|
||||
</refentry>
|
1283
man/mosquitto.conf.5.xml
Normal file
1283
man/mosquitto.conf.5.xml
Normal file
File diff suppressed because it is too large
Load Diff
145
man/mosquitto_passwd.1.xml
Normal file
145
man/mosquitto_passwd.1.xml
Normal file
@ -0,0 +1,145 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml-stylesheet type="text/xsl" href="manpage.xsl"?>
|
||||
|
||||
<refentry xml:id="mosquitto_passwd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<refmeta>
|
||||
<refentrytitle>mosquitto_passwd</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Mosquitto Project</refmiscinfo>
|
||||
<refmiscinfo class="manual">Commands</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>mosquitto_passwd</refname>
|
||||
<refpurpose>manage password files for mosquitto</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>mosquitto_passwd</command>
|
||||
<group>
|
||||
<arg choice='plain'><option>-c</option></arg>
|
||||
<arg choice='plain'><option>-D</option></arg>
|
||||
</group>
|
||||
<arg choice='plain'><replaceable>passwordfile</replaceable></arg>
|
||||
<arg choice='plain'><replaceable>username</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>mosquitto_passwd</command>
|
||||
<arg choice='plain'><option>-U</option></arg>
|
||||
<arg choice='plain'><replaceable>passwordfile</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para><command>mosquitto_passwd</command> is a tool for managing
|
||||
password files the the mosquitto MQTT broker.</para>
|
||||
<para>Usernames must not contain ":". Passwords are stored in a similar
|
||||
format to
|
||||
<citerefentry><refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-c</option></term>
|
||||
<listitem>
|
||||
<para>Create a new password file. If the file already
|
||||
exists, it will be overwritten.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-D</option></term>
|
||||
<listitem>
|
||||
<para>Delete the specified user from the password
|
||||
file.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-U</option></term>
|
||||
<listitem>
|
||||
<para>This option can be used to upgrade/convert a password
|
||||
file with plain text passwords into one using hashed
|
||||
passwords. It will modify the specified file. It does
|
||||
not detect whether passwords are already hashed, so
|
||||
using it on a password file that already contains
|
||||
hashed passwords will generate new hashes based on the
|
||||
old hashes and render the password file
|
||||
unusable.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>passwordfile</option></term>
|
||||
<listitem>
|
||||
<para>The password file to modify.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>username</option></term>
|
||||
<listitem>
|
||||
<para>The username to add/update/delete.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
<para>Add a user to a new password file:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>mosquitto_passwd <literal>-c</literal> /etc/mosquitto/passwd <literal>ral</literal></para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Delete a user from a password file</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>mosquitto_passwd <literal>-D</literal> /etc/mosquitto/passwd <literal>ral</literal></para></listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Bugs</title>
|
||||
<para><command>mosquitto_passwd</command> bug information can be found at
|
||||
<uri type="webpage">http://launchpad.net/mosquitto</uri></para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<simplelist type="inline">
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-8.html">mosquitto</link></refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-conf-5.html">mosquitto.conf</link></refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mqtt-7.html">mqtt</link></refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Acknowledgements</title>
|
||||
<para>This product includes software developed by the OpenSSL Project
|
||||
for use in the OpenSSL Toolkit. (http://www.openssl.org/)</para>
|
||||
<para>This product includes cryptographic software written by Eric
|
||||
Young (eay@cryptsoft.com)</para>
|
||||
<para>This product includes software written by Tim Hudson
|
||||
(tjh@cryptsoft.com)</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Author</title>
|
||||
<para>Roger Light <email>roger@atchoo.org</email></para>
|
||||
</refsect1>
|
||||
</refentry>
|
461
man/mosquitto_pub.1.xml
Normal file
461
man/mosquitto_pub.1.xml
Normal file
@ -0,0 +1,461 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml-stylesheet type="text/xsl" href="manpage.xsl"?>
|
||||
|
||||
<refentry xml:id="mosquitto_pub" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<refmeta>
|
||||
<refentrytitle>mosquitto_pub</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Mosquitto Project</refmiscinfo>
|
||||
<refmiscinfo class="manual">Commands</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>mosquitto_pub</refname>
|
||||
<refpurpose>an MQTT version 3.1 client for publishing simple messages</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>mosquitto_pub</command>
|
||||
<arg><option>-A</option> <replaceable>bind_address</replaceable></arg>
|
||||
<arg><option>-d</option></arg>
|
||||
<arg><option>-h</option> <replaceable>hostname</replaceable></arg>
|
||||
<arg><option>-i</option> <replaceable>client_id</replaceable></arg>
|
||||
<arg><option>-I</option> <replaceable>client id prefix</replaceable></arg>
|
||||
<arg><option>-p</option> <replaceable>port number</replaceable></arg>
|
||||
<arg><option>-q</option> <replaceable>message QoS</replaceable></arg>
|
||||
<arg><option>--quiet</option></arg>
|
||||
<arg><option>-r</option></arg>
|
||||
<arg><option>-S</option></arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>-f</option> <replaceable>file</replaceable></arg>
|
||||
<arg choice='plain'><option>-l</option></arg>
|
||||
<arg choice='plain'><option>-m</option> <replaceable>message</replaceable></arg>
|
||||
<arg choice='plain'><option>-n</option></arg>
|
||||
<arg choice='plain'><option>-s</option></arg>
|
||||
</group>
|
||||
<arg>
|
||||
<arg><option>-u</option> <replaceable>username</replaceable></arg>
|
||||
<arg><option>-P</option> <replaceable>password</replaceable></arg>
|
||||
</arg>
|
||||
<arg>
|
||||
<option>--will-topic</option> <replaceable>topic</replaceable>
|
||||
<arg><option>--will-payload</option> <replaceable>payload</replaceable></arg>
|
||||
<arg><option>--will-qos</option> <replaceable>qos</replaceable></arg>
|
||||
<arg><option>--will-retain</option></arg>
|
||||
</arg>
|
||||
<group>
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--cafile</option> <replaceable>file</replaceable></arg>
|
||||
<arg choice='plain'><option>--capath</option> <replaceable>dir</replaceable></arg>
|
||||
</group>
|
||||
<arg><option>--cert</option> <replaceable>file</replaceable></arg>
|
||||
<arg><option>--key</option> <replaceable>file</replaceable></arg>
|
||||
<arg><option>--ciphers</option> <replaceable>ciphers</replaceable></arg>
|
||||
<arg><option>--tls-version</option> <replaceable>version</replaceable></arg>
|
||||
<arg><option>--insecure</option></arg>
|
||||
</arg>
|
||||
<arg>
|
||||
<arg choice='plain'><option>--psk</option> <replaceable>hex-key</replaceable></arg>
|
||||
<arg choice='plain'><option>--psk-identity</option> <replaceable>identity</replaceable></arg>
|
||||
<arg><option>--ciphers</option> <replaceable>ciphers</replaceable></arg>
|
||||
<arg><option>--tls-version</option> <replaceable>version</replaceable></arg>
|
||||
</arg>
|
||||
</group>
|
||||
<arg choice='plain'><option>-t</option> <replaceable>message-topic</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>mosquitto_pub</command>
|
||||
<group choice='plain'>
|
||||
<arg><option>--help</option></arg>
|
||||
</group>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para><command>mosquitto_pub</command> is a simple MQTT version 3.1 client that will publish a single message on a topic and exit.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-A</option></term>
|
||||
<listitem>
|
||||
<para>Bind the outgoing connection to a local ip
|
||||
address/hostname. Use this argument if you need to
|
||||
restrict network communication to a particular
|
||||
interface.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--cafile</option></term>
|
||||
<listitem>
|
||||
<para>Define the path to a file containing PEM encoded CA
|
||||
certificates that are trusted. Used to enable SSL
|
||||
communication.</para>
|
||||
<para>See also <option>--capath</option></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--capath</option></term>
|
||||
<listitem>
|
||||
<para>Define the path to a directory containing PEM encoded CA
|
||||
certificates that are trusted. Used to enable SSL
|
||||
communication.</para>
|
||||
<para>For <option>--capath</option> to work correctly, the
|
||||
certificate files must have ".crt" as the file ending
|
||||
and you must run "c_rehash <path to capath>" each
|
||||
time you add/remove a certificate.</para>
|
||||
<para>See also <option>--cafile</option></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--cert</option></term>
|
||||
<listitem>
|
||||
<para>Define the path to a file containing a PEM encoded
|
||||
certificate for this client, if required by the
|
||||
server.</para>
|
||||
<para>See also <option>--key</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--ciphers</option></term>
|
||||
<listitem>
|
||||
<para>An openssl compatible list of TLS ciphers to support
|
||||
in the client. See
|
||||
<citerefentry><refentrytitle>ciphers</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
for more information.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-d</option></term>
|
||||
<term><option>--debug</option></term>
|
||||
<listitem>
|
||||
<para>Enable debug messages.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-f</option></term>
|
||||
<term><option>--file</option></term>
|
||||
<listitem>
|
||||
<para>Send the contents of a file as the message.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--help</option></term>
|
||||
<listitem>
|
||||
<para>Display usage information.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-h</option></term>
|
||||
<term><option>--host</option></term>
|
||||
<listitem>
|
||||
<para>Specify the host to connect to. Defaults to localhost.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-i</option></term>
|
||||
<term><option>--id</option></term>
|
||||
<listitem>
|
||||
<para>The id to use for this client. If not given, defaults
|
||||
to mosquitto_pub_ appended with the process id of the
|
||||
client. Cannot be used at the same time as the
|
||||
<option>--id-prefix</option> argument.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-I</option></term>
|
||||
<term><option>--id-prefix</option></term>
|
||||
<listitem>
|
||||
<para>Provide a prefix that the client id will be built
|
||||
from by appending the process id of the client. This is
|
||||
useful where the broker is using the clientid_prefixes
|
||||
option. Cannot be used at the same time as the
|
||||
<option>--id</option> argument.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--insecure</option></term>
|
||||
<listitem>
|
||||
<para>When using certificate based encryption, this option
|
||||
disables verification of the server hostname in the
|
||||
server certificate. This can be useful when testing
|
||||
initial server configurations but makes it possible for
|
||||
a malicious third party to impersonate your server
|
||||
through DNS spoofing, for example. Use this option in
|
||||
testing <emphasis>only</emphasis>. If you need to
|
||||
resort to using this option in a production
|
||||
environment, your setup is at fault and there is no
|
||||
point using encryption.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--key</option></term>
|
||||
<listitem>
|
||||
<para>Define the path to a file containing a PEM encoded
|
||||
private key for this client, if required by the
|
||||
server.</para>
|
||||
<para>See also <option>--cert</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-l</option></term>
|
||||
<term><option>--stdin-line</option></term>
|
||||
<listitem>
|
||||
<para>Send messages read from stdin, splitting separate lines into separate messages. Note that blank lines won't be sent.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-m</option></term>
|
||||
<term><option>--message</option></term>
|
||||
<listitem>
|
||||
<para>Send a single message from the command line.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-n</option></term>
|
||||
<term><option>--null-message</option></term>
|
||||
<listitem>
|
||||
<para>Send a null (zero length) message.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-p</option></term>
|
||||
<term><option>--port</option></term>
|
||||
<listitem>
|
||||
<para>Connect to the port specified instead of the default 1883.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-P</option></term>
|
||||
<term><option>--pw</option></term>
|
||||
<listitem>
|
||||
<para>Provide a password to be used for authenticating with
|
||||
the broker. Using this argument without also specifying a
|
||||
username is invalid. This requires a broker that supports
|
||||
MQTT v3.1. See also the <option>--username</option> option.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--psk</option></term>
|
||||
<listitem>
|
||||
<para>Provide the hexadecimal (no leading 0x)
|
||||
pre-shared-key matching the one used on the broker to
|
||||
use TLS-PSK encryption support.
|
||||
<option>--psk-identity</option> must also be provided
|
||||
to enable TLS-PSK.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--psk-identity</option></term>
|
||||
<listitem>
|
||||
<para>The client identity to use with TLS-PSK support. This
|
||||
may be used instead of a username if the broker is
|
||||
configured to do so.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-q</option></term>
|
||||
<term><option>--qos</option></term>
|
||||
<listitem>
|
||||
<para>Specify the quality of service to use for the message, from 0, 1 and 2. Defaults to 0.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--quiet</option></term>
|
||||
<listitem>
|
||||
<para>If this argument is given, no runtime errors will be
|
||||
printed. This excludes any error messages given in case of
|
||||
invalid user input (e.g. using <option>--port</option> without a
|
||||
port).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-r</option></term>
|
||||
<term><option>--retain</option></term>
|
||||
<listitem>
|
||||
<para>If retain is given, the message will be retained as a "last known good" value on the broker. See <citerefentry><refentrytitle>mqtt</refentrytitle><manvolnum>7</manvolnum></citerefentry> for more information.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-s</option></term>
|
||||
<term><option>--stdin-file</option></term>
|
||||
<listitem>
|
||||
<para>Send a message read from stdin, sending the entire content as a single message.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-S</option></term>
|
||||
<listitem>
|
||||
<para>Use SRV lookups to determine which host to connect
|
||||
to. Performs lookups to
|
||||
<option>_mqtt._tcp.<host></option> when used in
|
||||
conjunction with <option>-h</option>, otherwise uses
|
||||
<option>_mqtt._tcp.<local dns
|
||||
domain></option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-t</option></term>
|
||||
<term><option>--topic</option></term>
|
||||
<listitem>
|
||||
<para>The MQTT topic on which to publish the message. See <citerefentry><refentrytitle>mqtt</refentrytitle><manvolnum>7</manvolnum></citerefentry> for more information on MQTT topics.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--tls-version</option></term>
|
||||
<listitem>
|
||||
<para>Choose which TLS protocol version to use when
|
||||
communicating with the broker. Valid options are
|
||||
<option>tlsv1.2</option>, <option>tlsv1.1</option> and
|
||||
<option>tlsv1</option>. The default value is
|
||||
<option>tlsv1.2</option>. If the installed version of
|
||||
openssl is too old, only <option>tlsv1</option> will be
|
||||
available. Must match the protocol version used by the
|
||||
broker.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-u</option></term>
|
||||
<term><option>--username</option></term>
|
||||
<listitem>
|
||||
<para>Provide a username to be used for authenticating with
|
||||
the broker. This requires a broker that supports MQTT v3.1.
|
||||
See also the <option>--pw</option> argument.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--will-payload</option></term>
|
||||
<listitem>
|
||||
<para>Specify a message that will be stored by the broker
|
||||
and sent out if this client disconnects unexpectedly. This
|
||||
must be used in conjunction with <option>--will-topic</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--will-qos</option></term>
|
||||
<listitem>
|
||||
<para>The QoS to use for the Will. Defaults to 0. This must
|
||||
be used in conjunction with <option>--will-topic</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--will-retain</option></term>
|
||||
<listitem>
|
||||
<para>If given, if the client disconnects unexpectedly the
|
||||
message sent out will be treated as a retained message.
|
||||
This must be used in conjunction with <option>--will-topic</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--will-topic</option></term>
|
||||
<listitem>
|
||||
<para>The topic on which to send a Will, in the event that
|
||||
the client disconnects unexpectedly.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Wills</title>
|
||||
<para>mosquitto_sub can register a message with the broker that will be
|
||||
sent out if it disconnects unexpectedly. See
|
||||
<citerefentry><refentrytitle>mqtt</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for more information.</para>
|
||||
<para>The minimum requirement for this is to use <option>--will-topic</option> to
|
||||
specify which topic the will should be sent out on. This will result in
|
||||
a non-retained, zero length message with QoS 0.</para>
|
||||
<para>Use the <option>--will-retain</option>,
|
||||
<option>--will-payload</option> and <option>--will-qos</option>
|
||||
arguments to modify the other will parameters.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
<para>Publish temperature information to localhost with QoS 1:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>mosquitto_pub <literal>-t</literal> sensors/temperature <literal>-m</literal> 32 <literal>-q</literal> 1</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Publish timestamp and temperature information to a remote host on a non-standard port and QoS 0:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>mosquitto_pub <literal>-h</literal> 192.168.1.1
|
||||
<literal>-p</literal> 1885 <literal>-t</literal>
|
||||
sensors/temperature <literal>-m</literal> "1266193804
|
||||
32"</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Publish light switch status. Message is set to retained because there may be a long period of time between light switch events:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>mosquitto_pub <literal>-r</literal> <literal>-t</literal> switches/kitchen_lights/status <literal>-m</literal> "on"</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Send the contents of a file in two ways:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>mosquitto_pub <literal>-t</literal> my/topic <literal>-f</literal> ./data</para></listitem>
|
||||
<listitem><para>mosquitto_pub <literal>-t</literal> my/topic <literal>-s</literal> < ./data</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Send parsed electricity usage data from a Current Cost meter, reading from stdin with one line/reading as one message:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>read_cc128.pl | mosquitto_pub <literal>-t</literal> sensors/cc128 <literal>-l</literal></para></listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Bugs</title>
|
||||
<para><command>mosquitto_pub</command> bug information can be found at <uri type="webpage">http://launchpad.net/mosquitto</uri></para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<simplelist type="inline">
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mqtt-7.html">mqtt</link></refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto_sub-1.html">mosquitto_sub</link></refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-8.html">mosquitto</link></refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="libmosquitto-3.html">libmosquitto</link></refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-tls-7.html">mosquitto-tls</link></refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Acknowledgements</title>
|
||||
<para>This product includes software developed by the OpenSSL Project
|
||||
for use in the OpenSSL Toolkit. (http://www.openssl.org/)</para>
|
||||
<para>This product includes cryptographic software written by Eric
|
||||
Young (eay@cryptsoft.com)</para>
|
||||
<para>This product includes software written by Tim Hudson
|
||||
(tjh@cryptsoft.com)</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Author</title>
|
||||
<para>Roger Light <email>roger@atchoo.org</email></para>
|
||||
</refsect1>
|
||||
</refentry>
|
491
man/mosquitto_sub.1.xml
Normal file
491
man/mosquitto_sub.1.xml
Normal file
@ -0,0 +1,491 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml-stylesheet type="text/xsl" href="manpage.xsl"?>
|
||||
|
||||
<refentry xml:id="mosquitto_sub" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<refmeta>
|
||||
<refentrytitle>mosquitto_sub</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
<refmiscinfo class="source">Mosquitto Project</refmiscinfo>
|
||||
<refmiscinfo class="manual">Commands</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>mosquitto_sub</refname>
|
||||
<refpurpose>an MQTT version 3.1 client for subscribing to topics</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>mosquitto_sub</command>
|
||||
<arg><option>-A</option> <replaceable>bind_address</replaceable></arg>
|
||||
<arg><option>-c</option></arg>
|
||||
<arg><option>-d</option></arg>
|
||||
<arg><option>-h</option> <replaceable>hostname</replaceable></arg>
|
||||
<arg><option>-i</option> <replaceable>client_id</replaceable></arg>
|
||||
<arg><option>-I</option> <replaceable>client id prefix</replaceable></arg>
|
||||
<arg><option>-k</option> <replaceable>keepalive time</replaceable></arg>
|
||||
<arg><option>-p</option> <replaceable>port number</replaceable></arg>
|
||||
<arg><option>-q</option> <replaceable>message QoS</replaceable></arg>
|
||||
<arg><option>-R</option></arg>
|
||||
<arg><option>-S</option></arg>
|
||||
<arg><option>-N</option></arg>
|
||||
<arg><option>--quiet</option></arg>
|
||||
<arg><option>-v</option></arg>
|
||||
<arg>
|
||||
<arg><option>-u</option> <replaceable>username</replaceable></arg>
|
||||
<arg><option>-P</option> <replaceable>password</replaceable></arg>
|
||||
</arg>
|
||||
<arg>
|
||||
<option>--will-topic</option> <replaceable>topic</replaceable>
|
||||
<arg><option>--will-payload</option> <replaceable>payload</replaceable></arg>
|
||||
<arg><option>--will-qos</option> <replaceable>qos</replaceable></arg>
|
||||
<arg><option>--will-retain</option></arg>
|
||||
</arg>
|
||||
<group>
|
||||
<arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'><option>--cafile</option> <replaceable>file</replaceable></arg>
|
||||
<arg choice='plain'><option>--capath</option> <replaceable>dir</replaceable></arg>
|
||||
</group>
|
||||
<arg><option>--cert</option> <replaceable>file</replaceable></arg>
|
||||
<arg><option>--key</option> <replaceable>file</replaceable></arg>
|
||||
<arg><option>--tls-version</option> <replaceable>version</replaceable></arg>
|
||||
<arg><option>--insecure</option></arg>
|
||||
</arg>
|
||||
<arg>
|
||||
<arg choice='plain'><option>--psk</option> <replaceable>hex-key</replaceable></arg>
|
||||
<arg choice='plain'><option>--psk-identity</option> <replaceable>identity</replaceable></arg>
|
||||
<arg><option>--tls-version</option> <replaceable>version</replaceable></arg>
|
||||
</arg>
|
||||
</group>
|
||||
<arg choice='opt' rep='repeat'><option>-T</option> <replaceable>filter-out</replaceable></arg>
|
||||
<arg choice='plain' rep='repeat'><option>-t</option> <replaceable>message-topic</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>mosquitto_sub</command>
|
||||
<group choice='plain'>
|
||||
<arg><option>--help</option></arg>
|
||||
</group>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para><command>mosquitto_sub</command> is a simple MQTT version 3.1
|
||||
client that will subscribe to a topic and print the messages that it
|
||||
receives.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-A</option></term>
|
||||
<listitem>
|
||||
<para>Bind the outgoing connection to a local ip
|
||||
address/hostname. Use this argument if you need to
|
||||
restrict network communication to a particular
|
||||
interface.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-c</option></term>
|
||||
<term><option>--disable-clean-session</option></term>
|
||||
<listitem>
|
||||
<para>Disable the 'clean session' flag. This means that all
|
||||
of the subscriptions for the client will be maintained
|
||||
after it disconnects, along with subsequent QoS 1 and QoS 2
|
||||
messages that arrive. When the client reconnects, it will
|
||||
receive all of the queued messages.</para>
|
||||
<para>If using this option, it is recommended that the
|
||||
client id is set manually with <option>--id</option></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--cafile</option></term>
|
||||
<listitem>
|
||||
<para>Define the path to a file containing PEM encoded CA
|
||||
certificates that are trusted. Used to enable SSL
|
||||
communication.</para>
|
||||
<para>See also <option>--capath</option></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--capath</option></term>
|
||||
<listitem>
|
||||
<para>Define the path to a directory containing PEM encoded CA
|
||||
certificates that are trusted. Used to enable SSL
|
||||
communication.</para>
|
||||
<para>For <option>--capath</option> to work correctly, the
|
||||
certificate files must have ".crt" as the file ending
|
||||
and you must run "c_rehash <path to capath>" each
|
||||
time you add/remove a certificate.</para>
|
||||
<para>See also <option>--cafile</option></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--cert</option></term>
|
||||
<listitem>
|
||||
<para>Define the path to a file containing a PEM encoded
|
||||
certificate for this client, if required by the
|
||||
server.</para>
|
||||
<para>See also <option>--key</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--ciphers</option></term>
|
||||
<listitem>
|
||||
<para>An openssl compatible list of TLS ciphers to support
|
||||
in the client. See
|
||||
<citerefentry><refentrytitle>ciphers</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
for more information.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-d</option></term>
|
||||
<term><option>--debug</option></term>
|
||||
<listitem>
|
||||
<para>Enable debug messages.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--help</option></term>
|
||||
<listitem>
|
||||
<para>Display usage information.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-h</option></term>
|
||||
<term><option>--host</option></term>
|
||||
<listitem>
|
||||
<para>Specify the host to connect to. Defaults to localhost.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-i</option></term>
|
||||
<term><option>--id</option></term>
|
||||
<listitem>
|
||||
<para>The id to use for this client. If not given, defaults
|
||||
to mosquitto_sub_ appended with the process id of the
|
||||
client. Cannot be used at the same time as the
|
||||
<option>--id-prefix</option> argument.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-I</option></term>
|
||||
<term><option>--id-prefix</option></term>
|
||||
<listitem>
|
||||
<para>Provide a prefix that the client id will be built
|
||||
from by appending the process id of the client. This is
|
||||
useful where the broker is using the clientid_prefixes
|
||||
option. Cannot be used at the same time as the
|
||||
<option>--id</option> argument.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--insecure</option></term>
|
||||
<listitem>
|
||||
<para>When using certificate based encryption, this option
|
||||
disables verification of the server hostname in the
|
||||
server certificate. This can be useful when testing
|
||||
initial server configurations but makes it possible for
|
||||
a malicious third party to impersonate your server
|
||||
through DNS spoofing, for example. Use this option in
|
||||
testing <emphasis>only</emphasis>. If you need to
|
||||
resort to using this option in a production
|
||||
environment, your setup is at fault and there is no
|
||||
point using encryption.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-k</option></term>
|
||||
<term><option>--keepalive</option></term>
|
||||
<listitem>
|
||||
<para>The number of seconds between sending PING commands
|
||||
to the broker for the purposes of informing it we are still
|
||||
connected and functioning. Defaults to 60 seconds.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--key</option></term>
|
||||
<listitem>
|
||||
<para>Define the path to a file containing a PEM encoded
|
||||
private key for this client, if required by the
|
||||
server.</para>
|
||||
<para>See also <option>--cert</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-N</option></term>
|
||||
<listitem>
|
||||
<para>Do not append an end of line character to the payload
|
||||
when printing. This allows streaming of payload data
|
||||
from multiple messages directly to another application
|
||||
unmodified. Only really makes sense when not using
|
||||
<option>-v</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-p</option></term>
|
||||
<term><option>--port</option></term>
|
||||
<listitem>
|
||||
<para>Connect to the port specified instead of the default 1883.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-P</option></term>
|
||||
<term><option>--pw</option></term>
|
||||
<listitem>
|
||||
<para>Provide a password to be used for authenticating with
|
||||
the broker. Using this argument without also specifying a
|
||||
username is invalid. This requires a broker that supports
|
||||
MQTT v3.1. See also the <option>--username</option> option.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--psk</option></term>
|
||||
<listitem>
|
||||
<para>Provide the hexadecimal (no leading 0x)
|
||||
pre-shared-key matching the one used on the broker to
|
||||
use TLS-PSK encryption support.
|
||||
<option>--psk-identity</option> must also be provided
|
||||
to enable TLS-PSK.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--psk-identity</option></term>
|
||||
<listitem>
|
||||
<para>The client identity to use with TLS-PSK support. This
|
||||
may be used instead of a username if the broker is
|
||||
configured to do so.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-q</option></term>
|
||||
<term><option>--qos</option></term>
|
||||
<listitem>
|
||||
<para>Specify the quality of service desired for the
|
||||
incoming messages, from 0, 1 and 2. Defaults to 0. See
|
||||
<citerefentry><refentrytitle>mqtt</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for more information on QoS.</para>
|
||||
<para>The QoS is identical for all topics subscribed to in
|
||||
a single instance of mosquitto_sub.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--quiet</option></term>
|
||||
<listitem>
|
||||
<para>If this argument is given, no runtime errors will be
|
||||
printed. This excludes any error messages given in case of
|
||||
invalid user input (e.g. using <option>--port</option> without a
|
||||
port).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-R</option></term>
|
||||
<listitem>
|
||||
<para>If this argument is given, messages that are received
|
||||
that have the retain bit set will not be printed.
|
||||
Messages with retain set are "stale", in that it is not
|
||||
known when they were originally published. When
|
||||
subscribing to a wildcard topic there may be a large
|
||||
number of retained messages. This argument suppresses
|
||||
their display.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-S</option></term>
|
||||
<listitem>
|
||||
<para>Use SRV lookups to determine which host to connect
|
||||
to. Performs lookups to
|
||||
<option>_mqtt._tcp.<host></option> when used in
|
||||
conjunction with <option>-h</option>, otherwise uses
|
||||
<option>_mqtt._tcp.<local dns
|
||||
domain></option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-t</option></term>
|
||||
<term><option>--topic</option></term>
|
||||
<listitem>
|
||||
<para>The MQTT topic to subscribe to. See
|
||||
<citerefentry><refentrytitle>mqtt</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for more information on MQTT topics.</para>
|
||||
<para>This option may be repeated to subscribe to multiple topics.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-T</option></term>
|
||||
<term><option>--filter-out</option></term>
|
||||
<listitem>
|
||||
<para>Suppress printing of topics that match the filter.
|
||||
This allows subscribing to a wildcard topic and only
|
||||
printing a partial set of the wildcard
|
||||
hierarchy.</para>
|
||||
<para>For example, subscribe to the BBC tree, but suppress output from Radio 3:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>mosquitto_sub <literal>-t</literal>
|
||||
bbc/# <literal>-T</literal>
|
||||
bbc/radio3</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>This option may be repeated to filter out multiple
|
||||
topics or topic trees.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--tls-version</option></term>
|
||||
<listitem>
|
||||
<para>Choose which TLS protocol version to use when
|
||||
communicating with the broker. Valid options are
|
||||
<option>tlsv1.2</option>, <option>tlsv1.1</option> and
|
||||
<option>tlsv1</option>. The default value is
|
||||
<option>tlsv1.2</option>. If the installed version of
|
||||
openssl is too old, only <option>tlsv1</option> will be
|
||||
available. Must match the protocol version used by the
|
||||
broker.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-u</option></term>
|
||||
<term><option>--username</option></term>
|
||||
<listitem>
|
||||
<para>Provide a username to be used for authenticating with
|
||||
the broker. This requires a broker that supports MQTT v3.1.
|
||||
See also the <option>--pw</option> argument.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-v</option></term>
|
||||
<term><option>--verbose</option></term>
|
||||
<listitem>
|
||||
<para>Print received messages verbosely. With this
|
||||
argument, messages will be printed as "topic payload". When
|
||||
this argument is not given, the messages are printed as
|
||||
"payload".</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--will-payload</option></term>
|
||||
<listitem>
|
||||
<para>Specify a message that will be stored by the broker
|
||||
and sent out if this client disconnects unexpectedly. This
|
||||
must be used in conjunction with <option>--will-topic</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--will-qos</option></term>
|
||||
<listitem>
|
||||
<para>The QoS to use for the Will. Defaults to 0. This must
|
||||
be used in conjunction with <option>--will-topic</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--will-retain</option></term>
|
||||
<listitem>
|
||||
<para>If given, if the client disconnects unexpectedly the
|
||||
message sent out will be treated as a retained message.
|
||||
This must be used in conjunction with <option>--will-topic</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>--will-topic</option></term>
|
||||
<listitem>
|
||||
<para>The topic on which to send a Will, in the event that
|
||||
the client disconnects unexpectedly.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Wills</title>
|
||||
<para>mosquitto_sub can register a message with the broker that will be
|
||||
sent out if it disconnects unexpectedly. See
|
||||
<citerefentry><refentrytitle>mqtt</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for more information.</para>
|
||||
<para>The minimum requirement for this is to use <option>--will-topic</option> to
|
||||
specify which topic the will should be sent out on. This will result in
|
||||
a non-retained, zero length message with QoS 0.</para>
|
||||
<para>Use the <option>--will-retain</option>, <option>--will-payload</option> and <option>--will-qos</option> arguments to
|
||||
modify the other will parameters.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
<para>Note that these really are examples - the subscriptions will work
|
||||
if you run them as shown, but there must be something publishing
|
||||
messages on those topics for you to receive anything.</para>
|
||||
<para>Subscribe to temperature information on localhost with QoS 1:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>mosquitto_sub <literal>-t</literal> sensors/temperature <literal>-q</literal> 1</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Subscribe to hard drive temperature updates on multiple
|
||||
machines/hard drives. This expects each machine to be publishing its
|
||||
hard drive temperature to
|
||||
sensors/machines/HOSTNAME/temperature/HD_NAME.</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>mosquitto_sub <literal>-t</literal> sensors/machines/+/temperature/+</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Subscribe to all broker status messages:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>mosquitto_sub <literal>-v</literal> <literal>-t</literal> \$SYS/#</para></listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Bugs</title>
|
||||
<para><command>mosquitto_sub</command> bug information can be found at
|
||||
<uri type="webpage">http://launchpad.net/mosquitto</uri></para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<simplelist type="inline">
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mqtt-7.html">mqtt</link></refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto_pub-1.html">mosquitto_pub</link></refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-8.html">mosquitto</link></refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="libmosquitto-3.html">libmosquitto</link></refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-tls-7.html">mosquitto-tls</link></refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Acknowledgements</title>
|
||||
<para>This product includes software developed by the OpenSSL Project
|
||||
for use in the OpenSSL Toolkit. (http://www.openssl.org/)</para>
|
||||
<para>This product includes cryptographic software written by Eric
|
||||
Young (eay@cryptsoft.com)</para>
|
||||
<para>This product includes software written by Tim Hudson
|
||||
(tjh@cryptsoft.com)</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Author</title>
|
||||
<para>Roger Light <email>roger@atchoo.org</email></para>
|
||||
</refsect1>
|
||||
</refentry>
|
187
man/mqtt.7.xml
Normal file
187
man/mqtt.7.xml
Normal file
@ -0,0 +1,187 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<?xml-stylesheet type="text/xsl" href="manpage.xsl"?>
|
||||
|
||||
<refentry xml:id="mqtt" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<refmeta>
|
||||
<refentrytitle>mqtt</refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
<refmiscinfo class="source">Mosquitto Project</refmiscinfo>
|
||||
<refmiscinfo class="manual">Conventions and miscellaneous</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>mqtt</refname>
|
||||
<refpurpose>MQ Telemetry Transport</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>MQTT</command>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
<para><command>MQTT</command> is a lightweight publish/subscribe
|
||||
messaging protocol. It is useful for use with low power sensors, but
|
||||
is applicable to many scenarios.</para> <para>This manual describes
|
||||
some of the features of MQTT version 3.1, to assist end users in
|
||||
getting the most out of the protocol. For more complete information on
|
||||
MQTT, see <uri type="webpage">http://mqtt.org/</uri>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Publish/Subscribe</title>
|
||||
<para>The MQTT protocol is based on the principle of publishing
|
||||
messages and subscribing to topics, or "pub/sub". Multiple clients
|
||||
connect to a broker and subscribe to topics that they are interested
|
||||
in. Clients also connect to the broker and publish messages to topics.
|
||||
Many clients may subscribe to the same topics and do with the
|
||||
information as they please. The broker and MQTT act as a simple, common
|
||||
interface for everything to connect to. This means that you if you have
|
||||
clients that dump subscribed messages to a database, to Twitter,
|
||||
Cosm or even a simple text file, then it becomes very simple to add
|
||||
new sensors or other data input to a database, Twitter or so on.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Topics/Subscriptions</title>
|
||||
<para>Messages in MQTT are published on topics. There is no need to
|
||||
configure a topic, publishing on it is enough. Topics are treated as a
|
||||
hierarchy, using a slash (/) as a separator. This allows sensible
|
||||
arrangement of common themes to be created, much in the same way as a
|
||||
filesystem. For example, multiple computers may all publish their
|
||||
hard drive temperature information on the following topic, with their
|
||||
own computer and hard drive name being replaced as appropriate:</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>sensors/COMPUTER_NAME/temperature/HARDDRIVE_NAME</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Clients can receive messages by creating subscriptions. A
|
||||
subscription may be to an explicit topic, in which case only messages
|
||||
to that topic will be received, or it may include wildcards. Two
|
||||
wildcards are available, <option>+</option> or <option>#</option>.</para>
|
||||
<para><option>+</option> can be used as a wildcard for a single level
|
||||
of hierarchy. It could be used with the topic above to get information
|
||||
on all computers and hard drives as follows:</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>sensors/+/temperature/+</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>As another example, for a topic of "a/b/c/d", the following
|
||||
example subscriptions will match:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>a/b/c/d</para></listitem>
|
||||
<listitem><para>+/b/c/d</para></listitem>
|
||||
<listitem><para>a/+/c/d</para></listitem>
|
||||
<listitem><para>a/+/+/d</para></listitem>
|
||||
<listitem><para>+/+/+/+</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>The following subscriptions will not match:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>a/b/c</para></listitem>
|
||||
<listitem><para>b/+/c/d</para></listitem>
|
||||
<listitem><para>+/+/+</para></listitem>
|
||||
</itemizedlist>
|
||||
<para><option>#</option> can be used as a wildcard for all remaining levels of
|
||||
hierarchy. This means that it must be the final character in a
|
||||
subscription. With a topic of "a/b/c/d", the following example
|
||||
subscriptions will match:</para>
|
||||
<itemizedlist mark="circle">
|
||||
<listitem><para>a/b/c/d</para></listitem>
|
||||
<listitem><para>#</para></listitem>
|
||||
<listitem><para>a/#</para></listitem>
|
||||
<listitem><para>a/b/#</para></listitem>
|
||||
<listitem><para>a/b/c/#</para></listitem>
|
||||
<listitem><para>+/b/c/#</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Zero length topic levels are valid, which can lead to some
|
||||
slightly non-obvious behaviour. For example, a topic of "a//topic"
|
||||
would correctly match against a subscription of "a/+/topic".
|
||||
Likewise, zero length topic levels can exist at both the beginning
|
||||
and the end of a topic string, so "/a/topic" would match against a
|
||||
subscription of "+/a/topic", "#" or "/#", and a topic "a/topic/"
|
||||
would match against a subscription of "a/topic/+" or
|
||||
"a/topic/#".</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Quality of Service</title>
|
||||
<para>MQTT defines three levels of Quality of Service (QoS). The QoS
|
||||
defines how hard the broker/client will try to ensure that a message is
|
||||
received. Messages may be sent at any QoS level, and clients may
|
||||
attempt to subscribe to topics at any QoS level. This means that the
|
||||
client chooses the maximum QoS it will receive. For example, if a
|
||||
message is published at QoS 2 and a client is subscribed with QoS 0,
|
||||
the message will be delivered to that client with QoS 0. If a second
|
||||
client is also subscribed to the same topic, but with QoS 2, then it
|
||||
will receive the same message but with QoS 2. For a second example, if
|
||||
a client is subscribed with QoS 2 and a message is published on QoS 0,
|
||||
the client will receive it on QoS 0.</para>
|
||||
<para>Higher levels of QoS are more reliable, but involve higher
|
||||
latency and have higher bandwidth requirements.</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>0: The broker/client will deliver the message once, with no confirmation.</para></listitem>
|
||||
<listitem><para>1: The broker/client will deliver the message at least once, with confirmation required.</para></listitem>
|
||||
<listitem><para>2: The broker/client will deliver the message exactly once by using a four step handshake.</para></listitem>
|
||||
</itemizedlist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Retained Messages</title>
|
||||
<para>All messages may be set to be retained. This means that the
|
||||
broker will keep the message even after sending it to all current
|
||||
subscribers. If a new subscription is made that matches the topic of
|
||||
the retained message, then the message will be sent to the client. This
|
||||
is useful as a "last known good" mechanism. If a topic is only updated
|
||||
infrequently, then without a retained message, a newly subscribed
|
||||
client may have to wait a long time to receive an update. With a
|
||||
retained message, the client will receive an instant update.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Clean session / Durable connections</title>
|
||||
<para>On connection, a client sets the "clean session" flag, which is
|
||||
sometimes also known as the "clean start" flag. If clean session is set
|
||||
to false, then the connection is treated as durable. This means that
|
||||
when the client disconnects, any subscriptions it has will remain and
|
||||
any subsequent QoS 1 or 2 messages will be stored until it connects
|
||||
again in the future. If clean session is true, then all subscriptions
|
||||
will be removed for the client when it disconnects.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Wills</title>
|
||||
<para>When a client connects to a broker, it may inform the broker that
|
||||
it has a will. This is a message that it wishes the broker to send when
|
||||
the client disconnects unexpectedly. The will message has a topic,
|
||||
QoS and retain status just the same as any other message.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<simplelist type="inline">
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto-8.html">mosquitto</link></refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto_pub-1.html">mosquitto_pub</link></refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
<member>
|
||||
<citerefentry>
|
||||
<refentrytitle><link xlink:href="mosquitto_sub-1.html">mosquitto_sub</link></refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>
|
||||
</member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Author</title>
|
||||
<para>Roger Light <email>roger@atchoo.org</email></para>
|
||||
</refsect1>
|
||||
</refentry>
|
55
misc/currentcost/cc128_log_mysql.pl
Executable file
55
misc/currentcost/cc128_log_mysql.pl
Executable file
@ -0,0 +1,55 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Log CurrentCost power meter data to a mysql database.
|
||||
# Assumes data is coming in on MQTT topic sensors/cc128
|
||||
# and in format timestamp,temperature,ch1_data
|
||||
# e.g. 1276605752,12.7,86
|
||||
|
||||
# To create database, table and user:
|
||||
#
|
||||
# CREATE DATABASE powermeter;
|
||||
# USE 'powermeter';
|
||||
# CREATE TABLE powermeter (
|
||||
# `id` INT NOT NULL auto_increment,
|
||||
# `timestamp` INT NOT NULL,
|
||||
# `temperature` FLOAT NOT NULL DEFAULT 0.0,
|
||||
# `ch1` INT NOT NULL DEFAULT 0,
|
||||
# PRIMARY KEY (`id`),
|
||||
# UNIQUE KEY `timestamp` (`timestamp`)
|
||||
# ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
#
|
||||
# CREATE USER 'powermeter'@'localhost' IDENTIFIED BY '<your password>';
|
||||
# GRANT ALL ON powermeter.* to 'powermeter'@'localhost';
|
||||
|
||||
use strict;
|
||||
use DBI();
|
||||
use FileHandle;
|
||||
|
||||
local $| = 1;
|
||||
|
||||
my $dbname = "powermeter";
|
||||
my $dbhost = "localhost";
|
||||
my $dbusername = "powermeter";
|
||||
my $dbpassword = "password";
|
||||
my $dbtable = "powermeter";
|
||||
|
||||
my $subclient = "/usr/bin/mosquitto_sub -t sensors/cc128";
|
||||
open(SUB, "$subclient|");
|
||||
SUB->autoflush(1);
|
||||
|
||||
my $dbh = DBI->connect("DBI:mysql:database=$dbname;host=$dbhost",
|
||||
"$dbusername", "$dbpassword", {'RaiseError' => 1});
|
||||
|
||||
my $query = "INSERT INTO powermeter (timestamp, temperature, ch1) VALUES (?,?,?)";
|
||||
|
||||
my @vals;
|
||||
my ($timestamp, $temperature, $ch1);
|
||||
while (my $line = <SUB>) {
|
||||
@vals = split(/,/, $line);
|
||||
$timestamp = @vals[0];
|
||||
$temperature = @vals[1];
|
||||
$ch1 = @vals[2];
|
||||
$dbh->do($query, undef, $timestamp, $temperature, $ch1);
|
||||
}
|
||||
$dbh->disconnect();
|
||||
|
45
misc/currentcost/cc128_parse.pl
Executable file
45
misc/currentcost/cc128_parse.pl
Executable file
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# Read raw cc128 data and republish without xml.
|
||||
# Probably only works if you have a single channel.
|
||||
|
||||
use strict;
|
||||
use HTTP::Date "str2time";
|
||||
use FileHandle;
|
||||
|
||||
local $| = 1;
|
||||
|
||||
my $subclient = "/usr/bin/mosquitto_sub -t sensors/cc128/raw -q 2";
|
||||
my $pubclient = "/usr/bin/mosquitto_pub -t sensors/cc128 -q 2 -l";
|
||||
my $pubclient_ch1 = "/usr/bin/mosquitto_pub -t sensors/cc128/ch1 -q 2 -l";
|
||||
|
||||
open(SUB, "$subclient|");
|
||||
open(PUB, "|$pubclient");
|
||||
open(PUB_CH1, "|$pubclient_ch1");
|
||||
|
||||
SUB->autoflush(1);
|
||||
PUB->autoflush(1);
|
||||
PUB_CH1->autoflush(1);
|
||||
|
||||
while (my $line = <SUB>) {
|
||||
#<msg><src>CC128-v0.12</src><dsb>00002</dsb><time>00:02:12</time><tmpr>15.7</tmpr><sensor>0</sensor><id>03112</id><type>1</type><ch1><watts>00108</watts></ch1></msg>
|
||||
if ($line =~ m#<time>(.*)</time><tmpr> *([\-\d.]+)</tmpr><sensor>0</sensor><id>[0-9]*</id><type>1</type><ch1><watts>0*(\d+)</watts></ch1></msg#){
|
||||
my $reading_time = $1;
|
||||
my $temp = $2;
|
||||
my $watts = $3;
|
||||
|
||||
my $now = time;
|
||||
my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst,$r_stamp);
|
||||
|
||||
($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime($now);
|
||||
$year += 1900;
|
||||
$month += 1;
|
||||
$r_stamp = str2time("$year-$month-$mday $reading_time");
|
||||
if($r_stamp > $now){
|
||||
$r_stamp -= 86400;
|
||||
}
|
||||
|
||||
print PUB "$r_stamp,$temp,$watts\n";
|
||||
print PUB_CH1 "$r_stamp $watts\n";
|
||||
}
|
||||
}
|
23
misc/currentcost/cc128_read.pl
Executable file
23
misc/currentcost/cc128_read.pl
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# Reads data from a Current Cost device via serial port.
|
||||
# Spawns
|
||||
|
||||
use strict;
|
||||
use Device::SerialPort qw( :PARAM :STAT 0.07 );
|
||||
|
||||
my $pubclient = "mosquitto_pub -t sensors/cc128/raw -q 2 -l";
|
||||
my $PORT = "/dev/ttyUSB0";
|
||||
local $| = 1;
|
||||
|
||||
my $ob = Device::SerialPort->new($PORT);
|
||||
$ob->baudrate(57600);
|
||||
$ob->write_settings;
|
||||
|
||||
open(SERIAL, "+<$PORT");
|
||||
open(MQTT, "|$pubclient");
|
||||
while (my $line = <SERIAL>) {
|
||||
print(MQTT "$line");
|
||||
}
|
||||
|
||||
close(MQTT);
|
22
misc/currentcost/cc128_read.py
Executable file
22
misc/currentcost/cc128_read.py
Executable file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/python -u
|
||||
|
||||
import mosquitto
|
||||
import serial
|
||||
|
||||
usb = serial.Serial(port='/dev/ttyUSB0', baudrate=57600)
|
||||
|
||||
mosq = mosquitto.Mosquitto()
|
||||
mosq.connect("localhost")
|
||||
mosq.loop_start()
|
||||
|
||||
running = True
|
||||
try:
|
||||
while running:
|
||||
line = usb.readline()
|
||||
mosq.publish("cc128/raw", line)
|
||||
except usb.SerialException, e:
|
||||
running = False
|
||||
|
||||
mosq.disconnect()
|
||||
mosq.loop_stop()
|
||||
|
69
misc/currentcost/gnome-panel/CurrentCostMQTT.py
Executable file
69
misc/currentcost/gnome-panel/CurrentCostMQTT.py
Executable file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import gnomeapplet
|
||||
import gobject
|
||||
import gtk
|
||||
import mosquitto
|
||||
import os
|
||||
import platform
|
||||
import pygtk
|
||||
import sys
|
||||
|
||||
class CurrentCostMQTT(gnomeapplet.Applet):
|
||||
def on_message(self, mosq, obj, msg):
|
||||
# Message format is "power"
|
||||
self.label.set_text(msg.payload+"W")
|
||||
|
||||
def set_label(self, val):
|
||||
self.label.set_text(val)
|
||||
|
||||
def on_change_background(self, applet, type, color, pixmap):
|
||||
applet.set_style(None)
|
||||
applet.modify_style(gtk.RcStyle())
|
||||
|
||||
if type == gnomeapplet.COLOR_BACKGROUND:
|
||||
applet.modify_bg(gtk.STATE_NORMAL, color)
|
||||
elif type == gnomeapplet.PIXMAP_BACKGROUND:
|
||||
style = applet.get_style().copy()
|
||||
style.bg_pixmap[gtk.STATE_NORMAL] = pixmap
|
||||
applet.set_style(style)
|
||||
|
||||
def show_menu(self, widget, event):
|
||||
print "menu"
|
||||
|
||||
def __init__(self, applet, iid):
|
||||
self.applet = applet
|
||||
self.label = gtk.Label("0W")
|
||||
self.event_box = gtk.EventBox()
|
||||
self.event_box.add(self.label)
|
||||
self.event_box.set_events(gtk.gdk.BUTTON_PRESS_MASK)
|
||||
self.event_box.connect("button_press_event", self.show_menu)
|
||||
self.applet.add(self.event_box)
|
||||
self.applet.set_background_widget(applet)
|
||||
self.applet.show_all()
|
||||
self.mosq = mosquitto.Mosquitto()
|
||||
self.mosq.on_message = self.on_message
|
||||
self.mosq.connect("localhost")
|
||||
self.mosq.loop_start()
|
||||
self.mosq.subscribe("sensors/cc128/ch1", 0)
|
||||
self.applet.connect('change-background', self.on_change_background)
|
||||
|
||||
def CurrentCostMQTT_factory(applet, iid):
|
||||
CurrentCostMQTT(applet, iid)
|
||||
return gtk.TRUE
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1] == "-d": #Debug mode
|
||||
main_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
main_window.set_title("Python Applet")
|
||||
main_window.connect("destroy", gtk.main_quit)
|
||||
app = gnomeapplet.Applet()
|
||||
CurrentCostMQTT_factory(app,None)
|
||||
app.reparent(main_window)
|
||||
main_window.show_all()
|
||||
gtk.main()
|
||||
sys.exit()
|
||||
|
||||
if __name__ == '__main__':
|
||||
gnomeapplet.bonobo_factory("OAFIID:CurrentCostMQTT_Factory", gnomeapplet.Applet.__gtype__, "MQTT", "0", CurrentCostMQTT_factory)
|
||||
|
28
misc/currentcost/gnome-panel/CurrentCostMQTT.server
Normal file
28
misc/currentcost/gnome-panel/CurrentCostMQTT.server
Normal file
@ -0,0 +1,28 @@
|
||||
<oaf_info>
|
||||
<oaf_server iid="OAFIID:CurrentCostMQTT_Factory"
|
||||
type="exe"
|
||||
location="CurrentCostMQTT.py">
|
||||
|
||||
<oaf_attribute name="repo_ids" type="stringv">
|
||||
<item value="IDL:Bonobo/GenericFactory:1.0"/>
|
||||
<item value="IDL:Bonobo/Unknown:1.0"/>
|
||||
</oaf_attribute>
|
||||
<oaf_attribute name="name" type="string" value="CurrentCost MQTT display"/>
|
||||
<oaf_attribute name="description" type="string" value="Display energy usage published over MQTT"/>
|
||||
</oaf_server>
|
||||
|
||||
<oaf_server iid="OAFIID:CurrentCostMQTT"
|
||||
type="factory"
|
||||
location="OAFIID:CurrentCostMQTT_Factory">
|
||||
|
||||
<oaf_attribute name="repo_ids" type="stringv">
|
||||
<item value="IDL:GNOME/Vertigo/PanelAppletShell:1.0"/>
|
||||
<item value="IDL:Bonobo/Control:1.0"/>
|
||||
<item value="IDL:Bonobo/Unknown:1.0"/>
|
||||
</oaf_attribute>
|
||||
<oaf_attribute name="name" type="string" value="CurrentCost MQTT display"/>
|
||||
<oaf_attribute name="description" type="string" value="Display energy usage published over MQTT"/>
|
||||
<oaf_attribute name="panel:category" type="string" value="Utility"/>
|
||||
<oaf_attribute name="panel:icon" type="string" value="currentcost.png"/>
|
||||
</oaf_server>
|
||||
</oaf_info>
|
BIN
misc/currentcost/gnome-panel/currentcost.png
Normal file
BIN
misc/currentcost/gnome-panel/currentcost.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
745
mosquitto.conf
Normal file
745
mosquitto.conf
Normal file
@ -0,0 +1,745 @@
|
||||
# Config file for mosquitto
|
||||
#
|
||||
# See mosquitto.conf(5) for more information.
|
||||
#
|
||||
# Default values are shown, uncomment to change.
|
||||
#
|
||||
# Use the # character to indicate a comment, but only if it is the
|
||||
# very first character on the line.
|
||||
|
||||
# =================================================================
|
||||
# General configuration
|
||||
# =================================================================
|
||||
|
||||
# Time in seconds to wait before resending an outgoing QoS=1 or
|
||||
# QoS=2 message.
|
||||
#retry_interval 20
|
||||
|
||||
# Time in seconds between updates of the $SYS tree.
|
||||
# Set to 0 to disable the publishing of the $SYS tree.
|
||||
#sys_interval 10
|
||||
|
||||
# Time in seconds between cleaning the internal message store of
|
||||
# unreferenced messages. Lower values will result in lower memory
|
||||
# usage but more processor time, higher values will have the
|
||||
# opposite effect.
|
||||
# Setting a value of 0 means the unreferenced messages will be
|
||||
# disposed of as quickly as possible.
|
||||
#store_clean_interval 10
|
||||
|
||||
# Write process id to a file. Default is a blank string which means
|
||||
# a pid file shouldn't be written.
|
||||
# This should be set to /var/run/mosquitto.pid if mosquitto is
|
||||
# being run automatically on boot with an init script and
|
||||
# start-stop-daemon or similar.
|
||||
#pid_file
|
||||
|
||||
# When run as root, drop privileges to this user and its primary
|
||||
# group.
|
||||
# Leave blank to stay as root, but this is not recommended.
|
||||
# If run as a non-root user, this setting has no effect.
|
||||
# Note that on Windows this has no effect and so mosquitto should
|
||||
# be started by the user you wish it to run as.
|
||||
#user mosquitto
|
||||
|
||||
# The maximum number of QoS 1 and 2 messages currently inflight per
|
||||
# client.
|
||||
# This includes messages that are partway through handshakes and
|
||||
# those that are being retried. Defaults to 20. Set to 0 for no
|
||||
# maximum. Setting to 1 will guarantee in-order delivery of QoS 1
|
||||
# and 2 messages.
|
||||
#max_inflight_messages 20
|
||||
|
||||
# The maximum number of QoS 1 and 2 messages to hold in a queue
|
||||
# above those that are currently in-flight. Defaults to 100. Set
|
||||
# to 0 for no maximum (not recommended).
|
||||
# See also queue_qos0_messages.
|
||||
#max_queued_messages 100
|
||||
|
||||
# Set to true to queue messages with QoS 0 when a persistent client is
|
||||
# disconnected. These messages are included in the limit imposed by
|
||||
# max_queued_messages.
|
||||
# Defaults to false.
|
||||
# This is a non-standard option for the MQTT v3.1 spec but is allowed in
|
||||
# v3.1.1.
|
||||
#queue_qos0_messages false
|
||||
|
||||
# This option sets the maximum publish payload size that the broker will allow.
|
||||
# Received messages that exceed this size will not be accepted by the broker.
|
||||
# The default value is 0, which means that all valid MQTT messages are
|
||||
# accepted. MQTT imposes a maximum payload size of 268435455 bytes.
|
||||
#message_size_limit 0
|
||||
|
||||
# This option controls whether a client is allowed to connect with a zero
|
||||
# length client id or not. This option only affects clients using MQTT v3.1.1
|
||||
# and later. If set to false, clients connecting with a zero length client id
|
||||
# are disconnected. If set to true, clients will be allocated a client id by
|
||||
# the broker. This means it is only useful for clients with clean session set
|
||||
# to true.
|
||||
#allow_zero_length_clientid true
|
||||
|
||||
# If allow_zero_length_clientid is true, this option allows you to set a prefix
|
||||
# to automatically generated client ids to aid visibility in logs.
|
||||
#auto_id_prefix
|
||||
|
||||
# This option allows persistent clients (those with clean session set to false)
|
||||
# to be removed if they do not reconnect within a certain time frame.
|
||||
#
|
||||
# This is a non-standard option in MQTT V3.1 but allowed in MQTT v3.1.1.
|
||||
#
|
||||
# Badly designed clients may set clean session to false whilst using a randomly
|
||||
# generated client id. This leads to persistent clients that will never
|
||||
# reconnect. This option allows these clients to be removed.
|
||||
#
|
||||
# The expiration period should be an integer followed by one of d w m y for
|
||||
# day, week, month and year respectively. For example
|
||||
#
|
||||
# persistent_client_expiration 2m
|
||||
# persistent_client_expiration 14d
|
||||
# persistent_client_expiration 1y
|
||||
#
|
||||
# The default if not set is to never expire persistent clients.
|
||||
#persistent_client_expiration
|
||||
|
||||
# If a client is subscribed to multiple subscriptions that overlap, e.g. foo/#
|
||||
# and foo/+/baz , then MQTT expects that when the broker receives a message on
|
||||
# a topic that matches both subscriptions, such as foo/bar/baz, then the client
|
||||
# should only receive the message once.
|
||||
# Mosquitto keeps track of which clients a message has been sent to in order to
|
||||
# meet this requirement. The allow_duplicate_messages option allows this
|
||||
# behaviour to be disabled, which may be useful if you have a large number of
|
||||
# clients subscribed to the same set of topics and are very concerned about
|
||||
# minimising memory usage.
|
||||
# It can be safely set to true if you know in advance that your clients will
|
||||
# never have overlapping subscriptions, otherwise your clients must be able to
|
||||
# correctly deal with duplicate messages even when then have QoS=2.
|
||||
#allow_duplicate_messages false
|
||||
|
||||
# The MQTT specification requires that the QoS of a message delivered to a
|
||||
# subscriber is never upgraded to match the QoS of the subscription. Enabling
|
||||
# this option changes this behaviour. If upgrade_outgoing_qos is set true,
|
||||
# messages sent to a subscriber will always match the QoS of its subscription.
|
||||
# This is a non-standard option explicitly disallowed by the spec.
|
||||
#upgrade_outgoing_qos false
|
||||
|
||||
# =================================================================
|
||||
# Default listener
|
||||
# =================================================================
|
||||
|
||||
# IP address/hostname to bind the default listener to. If not
|
||||
# given, the default listener will not be bound to a specific
|
||||
# address and so will be accessible to all network interfaces.
|
||||
# bind_address ip-address/host name
|
||||
#bind_address
|
||||
|
||||
# Port to use for the default listener.
|
||||
#port 1883
|
||||
|
||||
# The maximum number of client connections to allow. This is
|
||||
# a per listener setting.
|
||||
# Default is -1, which means unlimited connections.
|
||||
# Note that other process limits mean that unlimited connections
|
||||
# are not really possible. Typically the default maximum number of
|
||||
# connections possible is around 1024.
|
||||
#max_connections -1
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Certificate based SSL/TLS support
|
||||
# -----------------------------------------------------------------
|
||||
# The following options can be used to enable SSL/TLS support for
|
||||
# this listener. Note that the recommended port for MQTT over TLS
|
||||
# is 8883, but this must be set manually.
|
||||
#
|
||||
# See also the mosquitto-tls man page.
|
||||
|
||||
# At least one of cafile or capath must be defined. They both
|
||||
# define methods of accessing the PEM encoded Certificate
|
||||
# Authority certificates that have signed your server certificate
|
||||
# and that you wish to trust.
|
||||
# cafile defines the path to a file containing the CA certificates.
|
||||
# capath defines a directory that will be searched for files
|
||||
# containing the CA certificates. For capath to work correctly, the
|
||||
# certificate files must have ".crt" as the file ending and you must run
|
||||
# "c_rehash <path to capath>" each time you add/remove a certificate.
|
||||
#cafile
|
||||
#capath
|
||||
|
||||
# Path to the PEM encoded server certificate.
|
||||
#certfile
|
||||
|
||||
# Path to the PEM encoded keyfile.
|
||||
#keyfile
|
||||
|
||||
# This option defines the version of the TLS protocol to use for this listener.
|
||||
# The default value will always be the highest version that is available for
|
||||
# the version of openssl that the broker was compiled against. For openssl >=
|
||||
# 1.0.1 the valid values are tlsv1.2 tlsv1.1 and tlsv1. For openssl < 1.0.1 the
|
||||
# valid values are tlsv1.
|
||||
#tls_version
|
||||
|
||||
# By default a TLS enabled listener will operate in a similar fashion to a
|
||||
# https enabled web server, in that the server has a certificate signed by a CA
|
||||
# and the client will verify that it is a trusted certificate. The overall aim
|
||||
# is encryption of the network traffic. By setting require_certificate to true,
|
||||
# the client must provide a valid certificate in order for the network
|
||||
# connection to proceed. This allows access to the broker to be controlled
|
||||
# outside of the mechanisms provided by MQTT.
|
||||
#require_certificate false
|
||||
|
||||
# If require_certificate is true, you may set use_identity_as_username to true
|
||||
# to use the CN value from the client certificate as a username. If this is
|
||||
# true, the password_file option will not be used for this listener.
|
||||
#use_identity_as_username false
|
||||
|
||||
# If you have require_certificate set to true, you can create a certificate
|
||||
# revocation list file to revoke access to particular client certificates. If
|
||||
# you have done this, use crlfile to point to the PEM encoded revocation file.
|
||||
#crlfile
|
||||
|
||||
# If you wish to control which encryption ciphers are used, use the ciphers
|
||||
# option. The list of available ciphers can be optained using the "openssl
|
||||
# ciphers" command and should be provided in the same format as the output of
|
||||
# that command.
|
||||
# If unset defaults to DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:@STRENGTH
|
||||
#ciphers DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:@STRENGTH
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Pre-shared-key based SSL/TLS support
|
||||
# -----------------------------------------------------------------
|
||||
# The following options can be used to enable PSK based SSL/TLS support for
|
||||
# this listener. Note that the recommended port for MQTT over TLS is 8883, but
|
||||
# this must be set manually.
|
||||
#
|
||||
# See also the mosquitto-tls man page and the "Certificate based SSL/TLS
|
||||
# support" section. Only one of certificate or PSK encryption support can be
|
||||
# enabled for any listener.
|
||||
|
||||
# The psk_hint option enables pre-shared-key support for this listener and also
|
||||
# acts as an identifier for this listener. The hint is sent to clients and may
|
||||
# be used locally to aid authentication. The hint is a free form string that
|
||||
# doesn't have much meaning in itself, so feel free to be creative.
|
||||
# If this option is provided, see psk_file to define the pre-shared keys to be
|
||||
# used or create a security plugin to handle them.
|
||||
#psk_hint
|
||||
|
||||
# Set use_identity_as_username to have the psk identity sent by the client used
|
||||
# as its username. Authentication will be carried out using the PSK rather than
|
||||
# the MQTT username/password and so password_file will not be used for this
|
||||
# listener.
|
||||
#use_identity_as_username false
|
||||
|
||||
# When using PSK, the encryption ciphers used will be chosen from the list of
|
||||
# available PSK ciphers. If you want to control which ciphers are available,
|
||||
# use the "ciphers" option. The list of available ciphers can be optained
|
||||
# using the "openssl ciphers" command and should be provided in the same format
|
||||
# as the output of that command.
|
||||
#ciphers
|
||||
|
||||
# =================================================================
|
||||
# Extra listeners
|
||||
# =================================================================
|
||||
|
||||
# Listen on a port/ip address combination. By using this variable
|
||||
# multiple times, mosquitto can listen on more than one port. If
|
||||
# this variable is used and neither bind_address nor port given,
|
||||
# then the default listener will not be started.
|
||||
# The port number to listen on must be given. Optionally, an ip
|
||||
# address or host name may be supplied as a second argument. In
|
||||
# this case, mosquitto will attempt to bind the listener to that
|
||||
# address and so restrict access to the associated network and
|
||||
# interface. By default, mosquitto will listen on all interfaces.
|
||||
# listener port-number [ip address/host name]
|
||||
#listener
|
||||
|
||||
# The maximum number of client connections to allow. This is
|
||||
# a per listener setting.
|
||||
# Default is -1, which means unlimited connections.
|
||||
# Note that other process limits mean that unlimited connections
|
||||
# are not really possible. Typically the default maximum number of
|
||||
# connections possible is around 1024.
|
||||
#max_connections -1
|
||||
|
||||
# The listener can be restricted to operating within a topic hierarchy using
|
||||
# the mount_point option. This is achieved be prefixing the mount_point string
|
||||
# to all topics for any clients connected to this listener. This prefixing only
|
||||
# happens internally to the broker; the client will not see the prefix.
|
||||
#mount_point
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Certificate based SSL/TLS support
|
||||
# -----------------------------------------------------------------
|
||||
# The following options can be used to enable certificate based SSL/TLS support
|
||||
# for this listener. Note that the recommended port for MQTT over TLS is 8883,
|
||||
# but this must be set manually.
|
||||
#
|
||||
# See also the mosquitto-tls man page and the "Pre-shared-key based SSL/TLS
|
||||
# support" section. Only one of certificate or PSK encryption support can be
|
||||
# enabled for any listener.
|
||||
|
||||
# At least one of cafile or capath must be defined to enable certificate based
|
||||
# TLS encryption. They both define methods of accessing the PEM encoded
|
||||
# Certificate Authority certificates that have signed your server certificate
|
||||
# and that you wish to trust.
|
||||
# cafile defines the path to a file containing the CA certificates.
|
||||
# capath defines a directory that will be searched for files
|
||||
# containing the CA certificates. For capath to work correctly, the
|
||||
# certificate files must have ".crt" as the file ending and you must run
|
||||
# "c_rehash <path to capath>" each time you add/remove a certificate.
|
||||
#cafile
|
||||
#capath
|
||||
|
||||
# Path to the PEM encoded server certificate.
|
||||
#certfile
|
||||
|
||||
# Path to the PEM encoded keyfile.
|
||||
#keyfile
|
||||
|
||||
# By default an TLS enabled listener will operate in a similar fashion to a
|
||||
# https enabled web server, in that the server has a certificate signed by a CA
|
||||
# and the client will verify that it is a trusted certificate. The overall aim
|
||||
# is encryption of the network traffic. By setting require_certificate to true,
|
||||
# the client must provide a valid certificate in order for the network
|
||||
# connection to proceed. This allows access to the broker to be controlled
|
||||
# outside of the mechanisms provided by MQTT.
|
||||
#require_certificate false
|
||||
|
||||
# If require_certificate is true, you may set use_identity_as_username to true
|
||||
# to use the CN value from the client certificate as a username. If this is
|
||||
# true, the password_file option will not be used for this listener.
|
||||
#use_identity_as_username false
|
||||
|
||||
# If you have require_certificate set to true, you can create a certificate
|
||||
# revocation list file to revoke access to particular client certificates. If
|
||||
# you have done this, use crlfile to point to the PEM encoded revocation file.
|
||||
#crlfile
|
||||
|
||||
# If you wish to control which encryption ciphers are used, use the ciphers
|
||||
# option. The list of available ciphers can be optained using the "openssl
|
||||
# ciphers" command and should be provided in the same format as the output of
|
||||
# that command.
|
||||
#ciphers
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Pre-shared-key based SSL/TLS support
|
||||
# -----------------------------------------------------------------
|
||||
# The following options can be used to enable PSK based SSL/TLS support for
|
||||
# this listener. Note that the recommended port for MQTT over TLS is 8883, but
|
||||
# this must be set manually.
|
||||
#
|
||||
# See also the mosquitto-tls man page and the "Certificate based SSL/TLS
|
||||
# support" section. Only one of certificate or PSK encryption support can be
|
||||
# enabled for any listener.
|
||||
|
||||
# The psk_hint option enables pre-shared-key support for this listener and also
|
||||
# acts as an identifier for this listener. The hint is sent to clients and may
|
||||
# be used locally to aid authentication. The hint is a free form string that
|
||||
# doesn't have much meaning in itself, so feel free to be creative.
|
||||
# If this option is provided, see psk_file to define the pre-shared keys to be
|
||||
# used or create a security plugin to handle them.
|
||||
#psk_hint
|
||||
|
||||
# Set use_identity_as_username to have the psk identity sent by the client used
|
||||
# as its username. Authentication will be carried out using the PSK rather than
|
||||
# the MQTT username/password and so password_file will not be used for this
|
||||
# listener.
|
||||
#use_identity_as_username false
|
||||
|
||||
# When using PSK, the encryption ciphers used will be chosen from the list of
|
||||
# available PSK ciphers. If you want to control which ciphers are available,
|
||||
# use the "ciphers" option. The list of available ciphers can be optained
|
||||
# using the "openssl ciphers" command and should be provided in the same format
|
||||
# as the output of that command.
|
||||
#ciphers
|
||||
|
||||
# =================================================================
|
||||
# Persistence
|
||||
# =================================================================
|
||||
|
||||
# If persistence is enabled, save the in-memory database to disk
|
||||
# every autosave_interval seconds. If set to 0, the persistence
|
||||
# database will only be written when mosquitto exits. See also
|
||||
# autosave_on_changes.
|
||||
# Note that writing of the persistence database can be forced by
|
||||
# sending mosquitto a SIGUSR1 signal.
|
||||
#autosave_interval 1800
|
||||
|
||||
# If true, mosquitto will count the number of subscription changes, retained
|
||||
# messages received and queued messages and if the total exceeds
|
||||
# autosave_interval then the in-memory database will be saved to disk.
|
||||
# If false, mosquitto will save the in-memory database to disk by treating
|
||||
# autosave_interval as a time in seconds.
|
||||
#autosave_on_changes false
|
||||
|
||||
# Save persistent message data to disk (true/false).
|
||||
# This saves information about all messages, including
|
||||
# subscriptions, currently in-flight messages and retained
|
||||
# messages.
|
||||
# retained_persistence is a synonym for this option.
|
||||
#persistence false
|
||||
|
||||
# The filename to use for the persistent database, not including
|
||||
# the path.
|
||||
#persistence_file mosquitto.db
|
||||
|
||||
# Location for persistent database. Must include trailing /
|
||||
# Default is an empty string (current directory).
|
||||
# Set to e.g. /var/lib/mosquitto/ if running as a proper service on Linux or
|
||||
# similar.
|
||||
#persistence_location
|
||||
|
||||
# =================================================================
|
||||
# Logging
|
||||
# =================================================================
|
||||
|
||||
# Places to log to. Use multiple log_dest lines for multiple
|
||||
# logging destinations.
|
||||
# Possible destinations are: stdout stderr syslog topic file
|
||||
#
|
||||
# stdout and stderr log to the console on the named output.
|
||||
#
|
||||
# syslog uses the userspace syslog facility which usually ends up
|
||||
# in /var/log/messages or similar.
|
||||
#
|
||||
# topic logs to the broker topic '$SYS/broker/log/<severity>',
|
||||
# where severity is one of D, E, W, N, I, M which are debug, error,
|
||||
# warning, notice, information and message. Message type severity is used by
|
||||
# the subscribe/unsubscribe log_types and publishes log messages to
|
||||
# $SYS/broker/log/M/susbcribe or $SYS/broker/log/M/unsubscribe.
|
||||
#
|
||||
# The file destination requires an additional parameter which is the file to be
|
||||
# logged to, e.g. "log_dest file /var/log/mosquitto.log". The file will be
|
||||
# closed and reopened when the broker receives a HUP signal. Only a single file
|
||||
# destination may be configured.
|
||||
#
|
||||
# Note that if the broker is running as a Windows service it will default to
|
||||
# "log_dest none" and neither stdout nor stderr logging is available.
|
||||
# Use "log_dest none" if you wish to disable logging.
|
||||
#log_dest stderr
|
||||
|
||||
# Types of messages to log. Use multiple log_type lines for logging
|
||||
# multiple types of messages.
|
||||
# Possible types are: debug, error, warning, notice, information,
|
||||
# none, subscribe, unsubscribe, all.
|
||||
# Note that debug type messages are for decoding the incoming/outgoing
|
||||
# network packets. They are not logged in "topics".
|
||||
#log_type error
|
||||
#log_type warning
|
||||
#log_type notice
|
||||
#log_type information
|
||||
|
||||
# If set to true, client connection and disconnection messages will be included
|
||||
# in the log.
|
||||
#connection_messages true
|
||||
|
||||
# If set to true, add a timestamp value to each log message.
|
||||
#log_timestamp true
|
||||
|
||||
# =================================================================
|
||||
# Security
|
||||
# =================================================================
|
||||
|
||||
# If set, only clients that have a matching prefix on their
|
||||
# clientid will be allowed to connect to the broker. By default,
|
||||
# all clients may connect.
|
||||
# For example, setting "secure-" here would mean a client "secure-
|
||||
# client" could connect but another with clientid "mqtt" couldn't.
|
||||
#clientid_prefixes
|
||||
|
||||
# Boolean value that determines whether clients that connect
|
||||
# without providing a username are allowed to connect. If set to
|
||||
# false then a password file should be created (see the
|
||||
# password_file option) to control authenticated client access.
|
||||
# Defaults to true.
|
||||
#allow_anonymous true
|
||||
|
||||
# In addition to the clientid_prefixes, allow_anonymous and TLS
|
||||
# authentication options, username based authentication is also
|
||||
# possible. The default support is described in "Default
|
||||
# authentication and topic access control" below. The auth_plugin
|
||||
# allows another authentication method to be used.
|
||||
# Specify the path to the loadable plugin and see the
|
||||
# "Authentication and topic access plugin options" section below.
|
||||
#auth_plugin
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Default authentication and topic access control
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
# Control access to the broker using a password file. This file can be
|
||||
# generated using the mosquitto_passwd utility. If TLS support is not compiled
|
||||
# into mosquitto (it is recommended that TLS support should be included) then
|
||||
# plain text passwords are used, in which case the file should be a text file
|
||||
# with lines in the format:
|
||||
# username:password
|
||||
# The password (and colon) may be omitted if desired, although this
|
||||
# offers very little in the way of security.
|
||||
#
|
||||
# See the TLS client require_certificate and use_identity_as_username options
|
||||
# for alternative authentication options.
|
||||
#password_file
|
||||
|
||||
# Access may also be controlled using a pre-shared-key file. This requires
|
||||
# TLS-PSK support and a listener configured to use it. The file should be text
|
||||
# lines in the format:
|
||||
# identity:key
|
||||
# The key should be in hexadecimal format without a leading "0x".
|
||||
#psk_file
|
||||
|
||||
# Control access to topics on the broker using an access control list
|
||||
# file. If this parameter is defined then only the topics listed will
|
||||
# have access.
|
||||
# If the first character of a line of the ACL file is a # it is treated as a
|
||||
# comment.
|
||||
# Topic access is added with lines of the format:
|
||||
#
|
||||
# topic [read|write] <topic>
|
||||
#
|
||||
# The access type is controlled using "read" or "write". This parameter
|
||||
# is optional - if not given then the access is read/write.
|
||||
# <topic> can contain the + or # wildcards as in subscriptions.
|
||||
#
|
||||
# The first set of topics are applied to anonymous clients, assuming
|
||||
# allow_anonymous is true. User specific topic ACLs are added after a
|
||||
# user line as follows:
|
||||
#
|
||||
# user <username>
|
||||
#
|
||||
# The username referred to here is the same as in password_file. It is
|
||||
# not the clientid.
|
||||
#
|
||||
#
|
||||
# If is also possible to define ACLs based on pattern substitution within the
|
||||
# topic. The patterns available for substition are:
|
||||
#
|
||||
# %c to match the client id of the client
|
||||
# %u to match the username of the client
|
||||
#
|
||||
# The substitution pattern must be the only text for that level of hierarchy.
|
||||
#
|
||||
# The form is the same as for the topic keyword, but using pattern as the
|
||||
# keyword.
|
||||
# Pattern ACLs apply to all users even if the "user" keyword has previously
|
||||
# been given.
|
||||
#
|
||||
# If using bridges with usernames and ACLs, connection messages can be allowed
|
||||
# with the following pattern:
|
||||
# pattern write $SYS/broker/connection/%c/state
|
||||
#
|
||||
# pattern [read|write] <topic>
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# pattern write sensor/%u/data
|
||||
#
|
||||
#acl_file
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Authentication and topic access plugin options
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
# If the auth_plugin option above is used, define options to pass to the
|
||||
# plugin here as described by the plugin instructions. All options named
|
||||
# using the format auth_opt_* will be passed to the plugin, for example:
|
||||
#
|
||||
# auth_opt_db_host
|
||||
# auth_opt_db_port
|
||||
# auth_opt_db_username
|
||||
# auth_opt_db_password
|
||||
|
||||
|
||||
# =================================================================
|
||||
# Bridges
|
||||
# =================================================================
|
||||
|
||||
# A bridge is a way of connecting multiple MQTT brokers together.
|
||||
# Create a new bridge using the "connection" option as described below. Set
|
||||
# options for the bridges using the remaining parameters. You must specify the
|
||||
# address and at least one topic to subscribe to.
|
||||
# Each connection must have a unique name.
|
||||
# The address line may have multiple host address and ports specified. See
|
||||
# below in the round_robin description for more details on bridge behaviour if
|
||||
# multiple addresses are used.
|
||||
# The direction that the topic will be shared can be chosen by
|
||||
# specifying out, in or both, where the default value is out.
|
||||
# The QoS level of the bridged communication can be specified with the next
|
||||
# topic option. The default QoS level is 0, to change the QoS the topic
|
||||
# direction must also be given.
|
||||
# The local and remote prefix options allow a topic to be remapped when it is
|
||||
# bridged to/from the remote broker. This provides the ability to place a topic
|
||||
# tree in an appropriate location.
|
||||
# For more details see the mosquitto.conf man page.
|
||||
# Multiple topics can be specified per connection, but be careful
|
||||
# not to create any loops.
|
||||
# If you are using bridges with cleansession set to false (the default), then
|
||||
# you may get unexpected behaviour from incoming topics if you change what
|
||||
# topics you are subscribing to. This is because the remote broker keeps the
|
||||
# subscription for the old topic. If you have this problem, connect your bridge
|
||||
# with cleansession set to true, then reconnect with cleansession set to false
|
||||
# as normal.
|
||||
#connection <name>
|
||||
#address <host>[:<port>] [<host>[:<port>]]
|
||||
#topic <topic> [[[out | in | both] qos-level] local-prefix remote-prefix]
|
||||
|
||||
# If the bridge has more than one address given in the address/addresses
|
||||
# configuration, the round_robin option defines the behaviour of the bridge on
|
||||
# a failure of the bridge connection. If round_robin is false, the default
|
||||
# value, then the first address is treated as the main bridge connection. If
|
||||
# the connection fails, the other secondary addresses will be attempted in
|
||||
# turn. Whilst connected to a secondary bridge, the bridge will periodically
|
||||
# attempt to reconnect to the main bridge until successful.
|
||||
# If round_robin is true, then all addresses are treated as equals. If a
|
||||
# connection fails, the next address will be tried and if successful will
|
||||
# remain connected until it fails
|
||||
#round_robin false
|
||||
|
||||
# Set the client id for this bridge connection. If not defined,
|
||||
# this defaults to 'name.hostname' where name is the connection
|
||||
# name and hostname is the hostname of this computer.
|
||||
#clientid
|
||||
|
||||
# Set the clean session variable for this bridge.
|
||||
# When set to true, when the bridge disconnects for any reason, all
|
||||
# messages and subscriptions will be cleaned up on the remote
|
||||
# broker. Note that with cleansession set to true, there may be a
|
||||
# significant amount of retained messages sent when the bridge
|
||||
# reconnects after losing its connection.
|
||||
# When set to false, the subscriptions and messages are kept on the
|
||||
# remote broker, and delivered when the bridge reconnects.
|
||||
#cleansession false
|
||||
|
||||
# If set to true, publish notification messages to the local and remote brokers
|
||||
# giving information about the state of the bridge connection. Retained
|
||||
# messages are published to the topic $SYS/broker/connection/<clientid>/state
|
||||
# unless the notification_topic option is used.
|
||||
# If the message is 1 then the connection is active, or 0 if the connection has
|
||||
# failed.
|
||||
#notifications true
|
||||
|
||||
# Choose the topic on which notification messages for this bridge are
|
||||
# published. If not set, messages are published on the topic
|
||||
# $SYS/broker/connection/<clientid>/state
|
||||
#notification_topic
|
||||
|
||||
# Set the keepalive interval for this bridge connection, in
|
||||
# seconds.
|
||||
#keepalive_interval 60
|
||||
|
||||
# Set the start type of the bridge. This controls how the bridge starts and
|
||||
# can be one of three types: automatic, lazy and once. Note that RSMB provides
|
||||
# a fourth start type "manual" which isn't currently supported by mosquitto.
|
||||
#
|
||||
# "automatic" is the default start type and means that the bridge connection
|
||||
# will be started automatically when the broker starts and also restarted
|
||||
# after a short delay (30 seconds) if the connection fails.
|
||||
#
|
||||
# Bridges using the "lazy" start type will be started automatically when the
|
||||
# number of queued messages exceeds the number set with the "threshold"
|
||||
# parameter. It will be stopped automatically after the time set by the
|
||||
# "idle_timeout" parameter. Use this start type if you wish the connection to
|
||||
# only be active when it is needed.
|
||||
#
|
||||
# A bridge using the "once" start type will be started automatically when the
|
||||
# broker starts but will not be restarted if the connection fails.
|
||||
#start_type automatic
|
||||
|
||||
# Set the amount of time a bridge using the automatic start type will wait
|
||||
# until attempting to reconnect. Defaults to 30 seconds.
|
||||
#restart_timeout 30
|
||||
|
||||
# Set the amount of time a bridge using the lazy start type must be idle before
|
||||
# it will be stopped. Defaults to 60 seconds.
|
||||
#idle_timeout 60
|
||||
|
||||
# Set the number of messages that need to be queued for a bridge with lazy
|
||||
# start type to be restarted. Defaults to 10 messages.
|
||||
# Must be less than max_queued_messages.
|
||||
#threshold 10
|
||||
|
||||
# If try_private is set to true, the bridge will attempt to indicate to the
|
||||
# remote broker that it is a bridge not an ordinary client. If successful, this
|
||||
# means that loop detection will be more effective and that retained messages
|
||||
# will be propagated correctly. Not all brokers support this feature so it may
|
||||
# be necessary to set try_private to false if your bridge does not connect
|
||||
# properly.
|
||||
#try_private true
|
||||
|
||||
# Set the username to use when connecting to an MQTT v3.1 broker
|
||||
# that requires authentication.
|
||||
#username
|
||||
|
||||
# Set the password to use when connecting to an MQTT v3.1 broker
|
||||
# that requires authentication. This option is only used if
|
||||
# username is also set.
|
||||
#password
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Certificate based SSL/TLS support
|
||||
# -----------------------------------------------------------------
|
||||
# Either bridge_cafile or bridge_capath must be defined to enable TLS support
|
||||
# for this bridge.
|
||||
# bridge_cafile defines the path to a file containing the
|
||||
# Certificate Authority certificates that have signed the remote broker
|
||||
# certificate.
|
||||
# bridge_capath defines a directory that will be searched for files containing
|
||||
# the CA certificates. For bridge_capath to work correctly, the certificate
|
||||
# files must have ".crt" as the file ending and you must run "c_rehash <path to
|
||||
# capath>" each time you add/remove a certificate.
|
||||
#bridge_cafile
|
||||
#bridge_capath
|
||||
|
||||
# Path to the PEM encoded client certificate, if required by the remote broker.
|
||||
#bridge_certfile
|
||||
|
||||
# Path to the PEM encoded client private key, if required by the remote broker.
|
||||
#bridge_keyfile
|
||||
|
||||
# When using certificate based encryption, bridge_insecure disables
|
||||
# verification of the server hostname in the server certificate. This can be
|
||||
# useful when testing initial server configurations, but makes it possible for
|
||||
# a malicious third party to impersonate your server through DNS spoofing, for
|
||||
# example. Use this option in testing only. If you need to resort to using this
|
||||
# option in a production environment, your setup is at fault and there is no
|
||||
# point using encryption.
|
||||
#bridge_insecure false
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# PSK based SSL/TLS support
|
||||
# -----------------------------------------------------------------
|
||||
# Pre-shared-key encryption provides an alternative to certificate based
|
||||
# encryption. A bridge can be configured to use PSK with the bridge_identity
|
||||
# and bridge_psk options. These are the client PSK identity, and pre-shared-key
|
||||
# in hexadecimal format with no "0x". Only one of certificate and PSK based
|
||||
# encryption can be used on one
|
||||
# bridge at once.
|
||||
#bridge_identity
|
||||
#bridge_psk
|
||||
|
||||
|
||||
# =================================================================
|
||||
# External config files
|
||||
# =================================================================
|
||||
|
||||
# External configuration files may be included by using the
|
||||
# include_dir option. This defines a directory that will be searched
|
||||
# for config files. All files that end in '.conf' will be loaded as
|
||||
# a configuration file. It is best to have this as the last option
|
||||
# in the main file. This option will only be processed from the main
|
||||
# configuration file. The directory specified must not contain the
|
||||
# main configuration file.
|
||||
#include_dir
|
||||
|
||||
# =================================================================
|
||||
# Unsupported rsmb options - for the future
|
||||
# =================================================================
|
||||
|
||||
#addresses
|
||||
#round_robin
|
||||
|
||||
# =================================================================
|
||||
# rsmb options - unlikely to ever be supported
|
||||
# =================================================================
|
||||
|
||||
#ffdc_output
|
||||
#max_log_entries
|
||||
#trace_level
|
||||
#trace_output
|
2
pskfile.example
Normal file
2
pskfile.example
Normal file
@ -0,0 +1,2 @@
|
||||
id:deadbeef
|
||||
easy:12345
|
3
pwfile.example
Normal file
3
pwfile.example
Normal file
@ -0,0 +1,3 @@
|
||||
roger:$6$clQ4Ocu312S0qWgl$Cv2wUxgEN73c6C6jlBkswqR4AkHsvDLWvtEXZZ8NpsBLgP1WAo/qA+WXcmEN/mjDNgdUwcxRAveqNMs2xUVQYA==
|
||||
sub_client:$6$U+qg0/32F0g2Fh+n$fBPSkq/rfNyEQ/TkEjRgwGTTVBpvNhKSyGShovH9KHewsvJ731tD5Zx26IHhR5RYCICt0L9qBW0/KK31UkCliw==
|
||||
pub_client:$6$vxQ89y+7WrsnL2yn$fSPMmEZn9TSrC8s/jaPmxJ9NijWpkP2e7bMJLz78JXR1vW2x8+T3FZ23byJA6xs5Mt+LeOybAHwcUv0OCl40rA==
|
5
readme-windows.txt
Normal file
5
readme-windows.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Mosquitto is now installed as a Windows service. You can start/stop it from
|
||||
the control panel as well as running it as a normal executable.
|
||||
|
||||
When running as a service, the configuration in mosquitto.conf in the
|
||||
installation directory is used so modify this to your needs.
|
20
readme.txt
Normal file
20
readme.txt
Normal file
@ -0,0 +1,20 @@
|
||||
Mosquitto
|
||||
=========
|
||||
|
||||
Mosquitto is an open source implementation of a server for version 3.1 of the
|
||||
MQTT protocol.
|
||||
|
||||
See the following links for more information on MQTT:
|
||||
|
||||
http://mqtt.org/
|
||||
http://www.ibm.com/developerworks/webservices/library/ws-mqtt/index.html
|
||||
|
||||
Mosquitto project information is available at the following locations:
|
||||
|
||||
http://mosquitto.org/ (main homepage)
|
||||
http://launchpad.net/mosquitto (bug tracking, translations)
|
||||
http://bitbucket.org/oojah/mosquitto (hg source code repository)
|
||||
|
||||
There is also a public test server available at http://test.mosquitto.org/
|
||||
|
||||
Mosquitto was written by Roger Light <roger@atchoo.org>
|
27
security/mosquitto.apparmor
Normal file
27
security/mosquitto.apparmor
Normal file
@ -0,0 +1,27 @@
|
||||
/usr/sbin/mosquitto {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
|
||||
/usr/sbin/mosquitto r,
|
||||
/etc/mosquitto/mosquitto.conf r,
|
||||
/etc/mosquitto/ca_certificates/* r,
|
||||
/etc/mosquitto/cert/* r,
|
||||
/etc/mosquitto/conf.d/* r,
|
||||
/var/lib/mosquitto/ r,
|
||||
/var/lib/mosquitto/mosquitto.db rwk,
|
||||
/var/run/mosquitto.pid rw,
|
||||
|
||||
network inet stream,
|
||||
network inet6 stream,
|
||||
network inet dgram,
|
||||
network inet6 dgram,
|
||||
|
||||
# For drop privileges
|
||||
capability setgid,
|
||||
capability setuid,
|
||||
|
||||
# For tcp-wrappers
|
||||
/lib{,32,64}/libwrap.so* rm,
|
||||
/etc/hosts.allow r,
|
||||
/etc/hosts.deny r,
|
||||
}
|
4
service/monit/mosquitto.monit
Normal file
4
service/monit/mosquitto.monit
Normal file
@ -0,0 +1,4 @@
|
||||
check process mosquitto with pidfile /var/run/mosquitto.pid
|
||||
start = "/etc/init.d/mosquitto start"
|
||||
stop = "/etc/init.d/mosquitto stop"
|
||||
|
3
service/svscan/run
Executable file
3
service/svscan/run
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
|
8
service/upstart/mosquitto.conf
Normal file
8
service/upstart/mosquitto.conf
Normal file
@ -0,0 +1,8 @@
|
||||
description "Mosquitto MQTTv3.1 broker"
|
||||
author "Roger Light <roger@atchoo.org>"
|
||||
|
||||
start on net-device-up
|
||||
|
||||
respawn
|
||||
|
||||
exec /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
|
105
src/CMakeLists.txt
Normal file
105
src/CMakeLists.txt
Normal file
@ -0,0 +1,105 @@
|
||||
include_directories(${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/src
|
||||
${mosquitto_SOURCE_DIR}/lib ${OPENSSL_INCLUDE_DIR}
|
||||
${STDBOOL_H_PATH} ${STDINT_H_PATH})
|
||||
|
||||
set (MOSQ_SRCS
|
||||
conf.c
|
||||
context.c
|
||||
database.c
|
||||
lib_load.h
|
||||
logging.c
|
||||
loop.c
|
||||
../lib/memory_mosq.c ../lib/memory_mosq.h
|
||||
mosquitto.c
|
||||
mosquitto_broker.h
|
||||
net.c
|
||||
../lib/net_mosq.c ../lib/net_mosq.h
|
||||
persist.c persist.h
|
||||
read_handle.c read_handle_client.c read_handle_server.c
|
||||
../lib/read_handle_shared.c ../lib/read_handle.h
|
||||
subs.c
|
||||
security.c security_default.c
|
||||
../lib/send_client_mosq.c ../lib/send_mosq.h
|
||||
../lib/send_mosq.c ../lib/send_mosq.h
|
||||
send_server.c
|
||||
sys_tree.c
|
||||
../lib/time_mosq.c
|
||||
../lib/tls_mosq.c
|
||||
../lib/util_mosq.c ../lib/util_mosq.h
|
||||
../lib/will_mosq.c ../lib/will_mosq.h)
|
||||
|
||||
option(INC_BRIDGE_SUPPORT
|
||||
"Include bridge support for connecting to other brokers?" ON)
|
||||
if (${INC_BRIDGE_SUPPORT} STREQUAL ON)
|
||||
set (MOSQ_SRCS ${MOSQ_SRCS} bridge.c)
|
||||
add_definitions("-DWITH_BRIDGE")
|
||||
endif (${INC_BRIDGE_SUPPORT} STREQUAL ON)
|
||||
|
||||
|
||||
option(USE_LIBWRAP
|
||||
"Include tcp-wrappers support?" OFF)
|
||||
|
||||
if (${USE_LIBWRAP} STREQUAL ON)
|
||||
set (MOSQ_LIBS ${MOSQ_LIBS} wrap)
|
||||
add_definitions("-DWITH_WRAP")
|
||||
endif (${USE_LIBWRAP} STREQUAL ON)
|
||||
|
||||
option(INC_DB_UPGRADE
|
||||
"Include database upgrade support? (recommended)" ON)
|
||||
|
||||
option(INC_MEMTRACK
|
||||
"Include memory tracking support?" ON)
|
||||
if (${INC_MEMTRACK} STREQUAL ON)
|
||||
add_definitions("-DWITH_MEMORY_TRACKING")
|
||||
endif (${INC_MEMTRACK} STREQUAL ON)
|
||||
|
||||
option(WITH_PERSISTENCE
|
||||
"Include persistence support?" ON)
|
||||
if (${WITH_PERSISTENCE} STREQUAL ON)
|
||||
add_definitions("-DWITH_PERSISTENCE")
|
||||
endif (${WITH_PERSISTENCE} STREQUAL ON)
|
||||
|
||||
option(WITH_SYS_TREE
|
||||
"Include $SYS tree support?" ON)
|
||||
if (${WITH_SYS_TREE} STREQUAL ON)
|
||||
add_definitions("-DWITH_SYS_TREE")
|
||||
endif (${WITH_SYS_TREE} STREQUAL ON)
|
||||
|
||||
if (WIN32 OR CYGWIN)
|
||||
set (MOSQ_SRCS ${MOSQ_SRCS} service.c)
|
||||
endif (WIN32 OR CYGWIN)
|
||||
|
||||
add_definitions (-DWITH_BROKER)
|
||||
|
||||
add_executable(mosquitto ${MOSQ_SRCS})
|
||||
|
||||
set (MOSQ_LIBS ${OPENSSL_LIBRARIES})
|
||||
|
||||
if (UNIX)
|
||||
if (APPLE)
|
||||
set (MOSQ_LIBS ${MOSQ_LIBS} dl m)
|
||||
else (APPLE)
|
||||
set (MOSQ_LIBS ${MOSQ_LIBS} rt dl m)
|
||||
endif (APPLE)
|
||||
endif (UNIX)
|
||||
|
||||
if (WIN32)
|
||||
set (MOSQ_LIBS ${MOSQ_LIBS} ws2_32)
|
||||
endif (WIN32)
|
||||
|
||||
target_link_libraries(mosquitto ${MOSQ_LIBS})
|
||||
|
||||
install(TARGETS mosquitto RUNTIME DESTINATION ${SBINDIR} LIBRARY DESTINATION ${LIBDIR})
|
||||
install(FILES mosquitto_plugin.h DESTINATION ${INCLUDEDIR})
|
||||
|
||||
|
||||
if (${WITH_TLS} STREQUAL ON)
|
||||
add_executable(mosquitto_passwd mosquitto_passwd.c)
|
||||
target_link_libraries(mosquitto_passwd ${OPENSSL_LIBRARIES})
|
||||
install(TARGETS mosquitto_passwd RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR})
|
||||
endif (${WITH_TLS} STREQUAL ON)
|
||||
|
||||
if (UNIX)
|
||||
install(CODE "EXEC_PROGRAM(/sbin/ldconfig)")
|
||||
endif (UNIX)
|
||||
|
118
src/Makefile
Normal file
118
src/Makefile
Normal file
@ -0,0 +1,118 @@
|
||||
include ../config.mk
|
||||
|
||||
.PHONY: all install uninstall clean reallyclean
|
||||
|
||||
ifeq ($(WITH_TLS),yes)
|
||||
all : mosquitto mosquitto_passwd
|
||||
else
|
||||
all : mosquitto
|
||||
endif
|
||||
|
||||
mosquitto : mosquitto.o bridge.o conf.o context.o database.o logging.o loop.o memory_mosq.o persist.o net.o net_mosq.o read_handle.o read_handle_client.o read_handle_server.o read_handle_shared.o security.o security_default.o send_client_mosq.o send_mosq.o send_server.o service.o subs.o sys_tree.o time_mosq.o tls_mosq.o util_mosq.o will_mosq.o
|
||||
${CC} $^ -o $@ ${LDFLAGS} $(BROKER_LIBS)
|
||||
|
||||
mosquitto.o : mosquitto.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@ -DCHANGESET=\"$$(cat ../changeset)\"
|
||||
|
||||
bridge.o : bridge.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
conf.o : conf.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
context.o : context.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
database.o : database.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
logging.o : logging.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
loop.o : loop.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
memory_mosq.o : ../lib/memory_mosq.c ../lib/memory_mosq.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
net.o : net.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
net_mosq.o : ../lib/net_mosq.c ../lib/net_mosq.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
persist.o : persist.c persist.h mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
read_handle.o : read_handle.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
read_handle_client.o : read_handle_client.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
read_handle_server.o : read_handle_server.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
read_handle_shared.o : ../lib/read_handle_shared.c ../lib/read_handle.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
security.o : security.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
security_default.o : security_default.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
send_client_mosq.o : ../lib/send_client_mosq.c ../lib/send_mosq.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
send_mosq.o : ../lib/send_mosq.c ../lib/send_mosq.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
send_server.o : send_server.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
service.o : service.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
subs.o : subs.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
sys_tree.o : sys_tree.c mosquitto_broker.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
time_mosq.o : ../lib/time_mosq.c ../lib/time_mosq.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
tls_mosq.o : ../lib/tls_mosq.c
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
util_mosq.o : ../lib/util_mosq.c ../lib/util_mosq.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
will_mosq.o : ../lib/will_mosq.c ../lib/will_mosq.h
|
||||
${CC} $(BROKER_CFLAGS) -c $< -o $@
|
||||
|
||||
mosquitto_passwd : mosquitto_passwd.o
|
||||
${CC} $^ -o $@ ${LDFLAGS} $(PASSWD_LIBS)
|
||||
|
||||
mosquitto_passwd.o : mosquitto_passwd.c
|
||||
${CC} $(CFLAGS) ${CPPFLAGS} -c $< -o $@
|
||||
|
||||
install : all
|
||||
$(INSTALL) -d ${DESTDIR}$(prefix)/sbin
|
||||
$(INSTALL) -s mosquitto ${DESTDIR}${prefix}/sbin/mosquitto
|
||||
$(INSTALL) mosquitto_plugin.h ${DESTDIR}${prefix}/include/mosquitto_plugin.h
|
||||
ifeq ($(WITH_TLS),yes)
|
||||
$(INSTALL) -s mosquitto_passwd ${DESTDIR}${prefix}/bin/mosquitto_passwd
|
||||
endif
|
||||
|
||||
uninstall :
|
||||
-rm -f ${DESTDIR}${prefix}/sbin/mosquitto
|
||||
-rm -f ${DESTDIR}${prefix}/include/mosquitto_plugin.h
|
||||
-rm -f ${DESTDIR}${prefix}/bin/mosquitto_passwd
|
||||
|
||||
clean :
|
||||
-rm -f *.o mosquitto mosquitto_passwd
|
||||
|
||||
reallyclean : clean
|
||||
-rm -rf *.orig *.db
|
249
src/bridge.c
Normal file
249
src/bridge.c
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
Copyright (c) 2009-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <mosquitto.h>
|
||||
#include <mosquitto_broker.h>
|
||||
#include <mosquitto_internal.h>
|
||||
#include <net_mosq.h>
|
||||
#include <memory_mosq.h>
|
||||
#include <send_mosq.h>
|
||||
#include <time_mosq.h>
|
||||
#include <tls_mosq.h>
|
||||
#include <util_mosq.h>
|
||||
#include <will_mosq.h>
|
||||
|
||||
#ifdef WITH_BRIDGE
|
||||
|
||||
int mqtt3_bridge_new(struct mosquitto_db *db, struct _mqtt3_bridge *bridge)
|
||||
{
|
||||
int i;
|
||||
struct mosquitto *new_context = NULL;
|
||||
int null_index = -1;
|
||||
struct mosquitto **tmp_contexts;
|
||||
char hostname[256];
|
||||
int len;
|
||||
char *id;
|
||||
|
||||
assert(db);
|
||||
assert(bridge);
|
||||
|
||||
if(bridge->clientid){
|
||||
id = _mosquitto_strdup(bridge->clientid);
|
||||
}else{
|
||||
if(!gethostname(hostname, 256)){
|
||||
len = strlen(hostname) + strlen(bridge->name) + 2;
|
||||
id = _mosquitto_malloc(len);
|
||||
if(!id){
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
snprintf(id, len, "%s.%s", hostname, bridge->name);
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(!id){
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
|
||||
/* Search for existing id (possible from persistent db) and also look for a
|
||||
* gap in the db->contexts[] array in case the id isn't found. */
|
||||
for(i=0; i<db->context_count; i++){
|
||||
if(db->contexts[i]){
|
||||
if(!strcmp(db->contexts[i]->id, id)){
|
||||
new_context = db->contexts[i];
|
||||
break;
|
||||
}
|
||||
}else if(db->contexts[i] == NULL && null_index == -1){
|
||||
null_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!new_context){
|
||||
/* id wasn't found, so generate a new context */
|
||||
new_context = mqtt3_context_init(-1);
|
||||
if(!new_context){
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
if(null_index == -1){
|
||||
/* There were no gaps in the db->contexts[] array, so need to append. */
|
||||
db->context_count++;
|
||||
tmp_contexts = _mosquitto_realloc(db->contexts, sizeof(struct mosquitto*)*db->context_count);
|
||||
if(tmp_contexts){
|
||||
db->contexts = tmp_contexts;
|
||||
db->contexts[db->context_count-1] = new_context;
|
||||
}else{
|
||||
_mosquitto_free(new_context);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}else{
|
||||
db->contexts[null_index] = new_context;
|
||||
}
|
||||
new_context->id = id;
|
||||
}else{
|
||||
/* id was found, so context->id already in memory. */
|
||||
_mosquitto_free(id);
|
||||
}
|
||||
new_context->bridge = bridge;
|
||||
new_context->is_bridge = true;
|
||||
|
||||
new_context->username = new_context->bridge->username;
|
||||
new_context->password = new_context->bridge->password;
|
||||
|
||||
#ifdef WITH_TLS
|
||||
new_context->tls_cafile = new_context->bridge->tls_cafile;
|
||||
new_context->tls_capath = new_context->bridge->tls_capath;
|
||||
new_context->tls_certfile = new_context->bridge->tls_certfile;
|
||||
new_context->tls_keyfile = new_context->bridge->tls_keyfile;
|
||||
new_context->tls_version = new_context->bridge->tls_version;
|
||||
new_context->tls_insecure = new_context->bridge->tls_insecure;
|
||||
#ifdef REAL_WITH_TLS_PSK
|
||||
new_context->tls_psk_identity = new_context->bridge->tls_psk_identity;
|
||||
new_context->tls_psk = new_context->bridge->tls_psk;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bridge->try_private_accepted = true;
|
||||
|
||||
return mqtt3_bridge_connect(db, new_context);
|
||||
}
|
||||
|
||||
int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
char *notification_topic;
|
||||
int notification_topic_len;
|
||||
uint8_t notification_payload;
|
||||
|
||||
if(!context || !context->bridge) return MOSQ_ERR_INVAL;
|
||||
|
||||
context->state = mosq_cs_new;
|
||||
context->sock = -1;
|
||||
context->last_msg_in = mosquitto_time();
|
||||
context->last_msg_out = mosquitto_time();
|
||||
context->keepalive = context->bridge->keepalive;
|
||||
context->clean_session = context->bridge->clean_session;
|
||||
context->in_packet.payload = NULL;
|
||||
context->ping_t = 0;
|
||||
context->bridge->lazy_reconnect = false;
|
||||
mqtt3_bridge_packet_cleanup(context);
|
||||
mqtt3_db_message_reconnect_reset(context);
|
||||
|
||||
if(context->clean_session){
|
||||
mqtt3_db_messages_delete(context);
|
||||
}
|
||||
|
||||
/* Delete all local subscriptions even for clean_session==false. We don't
|
||||
* remove any messages and the next loop carries out the resubscription
|
||||
* anyway. This means any unwanted subs will be removed.
|
||||
*/
|
||||
mqtt3_subs_clean_session(db, context, &db->subs);
|
||||
|
||||
for(i=0; i<context->bridge->topic_count; i++){
|
||||
if(context->bridge->topics[i].direction == bd_out || context->bridge->topics[i].direction == bd_both){
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Bridge %s doing local SUBSCRIBE on topic %s", context->id, context->bridge->topics[i].local_topic);
|
||||
if(mqtt3_sub_add(db, context, context->bridge->topics[i].local_topic, context->bridge->topics[i].qos, &db->subs)) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(context->bridge->notifications){
|
||||
notification_payload = '0';
|
||||
if(context->bridge->notification_topic){
|
||||
mqtt3_db_messages_easy_queue(db, context, context->bridge->notification_topic, 1, 1, ¬ification_payload, 1);
|
||||
rc = _mosquitto_will_set(context, context->bridge->notification_topic, 1, ¬ification_payload, 1, true);
|
||||
if(rc != MOSQ_ERR_SUCCESS){
|
||||
return rc;
|
||||
}
|
||||
}else{
|
||||
notification_topic_len = strlen(context->id)+strlen("$SYS/broker/connection//state");
|
||||
notification_topic = _mosquitto_malloc(sizeof(char)*(notification_topic_len+1));
|
||||
if(!notification_topic) return MOSQ_ERR_NOMEM;
|
||||
|
||||
snprintf(notification_topic, notification_topic_len+1, "$SYS/broker/connection/%s/state", context->id);
|
||||
mqtt3_db_messages_easy_queue(db, context, notification_topic, 1, 1, ¬ification_payload, 1);
|
||||
rc = _mosquitto_will_set(context, notification_topic, 1, ¬ification_payload, 1, true);
|
||||
if(rc != MOSQ_ERR_SUCCESS){
|
||||
_mosquitto_free(notification_topic);
|
||||
return rc;
|
||||
}
|
||||
_mosquitto_free(notification_topic);
|
||||
}
|
||||
}
|
||||
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Connecting bridge %s (%s:%d)", context->bridge->name, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port);
|
||||
rc = _mosquitto_socket_connect(context, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port, NULL, true);
|
||||
if(rc != MOSQ_ERR_SUCCESS){
|
||||
if(rc == MOSQ_ERR_TLS){
|
||||
return rc; /* Error already printed */
|
||||
}else if(rc == MOSQ_ERR_ERRNO){
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno));
|
||||
}else if(rc == MOSQ_ERR_EAI){
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno));
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = _mosquitto_send_connect(context, context->keepalive, context->clean_session);
|
||||
if(rc == MOSQ_ERR_SUCCESS){
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else if(rc == MOSQ_ERR_ERRNO && errno == ENOTCONN){
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else{
|
||||
if(rc == MOSQ_ERR_TLS){
|
||||
return rc; /* Error already printed */
|
||||
}else if(rc == MOSQ_ERR_ERRNO){
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno));
|
||||
}else if(rc == MOSQ_ERR_EAI){
|
||||
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno));
|
||||
}
|
||||
_mosquitto_socket_close(context);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
void mqtt3_bridge_packet_cleanup(struct mosquitto *context)
|
||||
{
|
||||
struct _mosquitto_packet *packet;
|
||||
if(!context) return;
|
||||
|
||||
_mosquitto_packet_cleanup(context->current_out_packet);
|
||||
while(context->out_packet){
|
||||
_mosquitto_packet_cleanup(context->out_packet);
|
||||
packet = context->out_packet;
|
||||
context->out_packet = context->out_packet->next;
|
||||
_mosquitto_free(packet);
|
||||
}
|
||||
|
||||
_mosquitto_packet_cleanup(&(context->in_packet));
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user