1
0
mirror of https://github.com/eclipse/mosquitto.git synced 2025-04-19 10:22:16 +03:00

Initial contribution.

This commit is contained in:
Roger Light 2014-05-07 23:27:00 +01:00
commit 0364bd1be7
372 changed files with 39627 additions and 0 deletions

39
.gitignore vendored Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

2
LICENSE.txt Normal file
View 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
View 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
View 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
View 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

1
changeset Normal file
View File

@ -0,0 +1 @@
b216c4246a7e9ff2be360ca2a7d102c5ea101f04

12
client/CMakeLists.txt Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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.

View 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
View 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
View 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.

View 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

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

View 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

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

View 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.

View 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");
}

View 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

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

File diff suppressed because it is too large Load Diff

1409
lib/mosquitto.h Normal file

File diff suppressed because it is too large Load Diff

230
lib/mosquitto_internal.h Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

91
lib/net_mosq.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

BIN
logo/mosquitto-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

182
logo/mosquitto.svg Normal file
View 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
View 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
View 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
View 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
View 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 &lt;stdio.h&gt;
#include &lt;mosquitto.h&gt;
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&lt;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
View 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
View 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 &lt;duration&gt; -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 &lt;duration&gt;</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 &lt;duration&gt;</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
View 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

File diff suppressed because it is too large Load Diff

145
man/mosquitto_passwd.1.xml Normal file
View 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
View 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 &lt;path to capath&gt;" 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.&lt;host&gt;</option> when used in
conjunction with <option>-h</option>, otherwise uses
<option>_mqtt._tcp.&lt;local dns
domain&gt;</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> &lt; ./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
View 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 &lt;path to capath&gt;" 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.&lt;host&gt;</option> when used in
conjunction with <option>-h</option>, otherwise uses
<option>_mqtt._tcp.&lt;local dns
domain&gt;</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
View 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>

View 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
View 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
View 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
View 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()

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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

745
mosquitto.conf Normal file
View 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
View File

@ -0,0 +1,2 @@
id:deadbeef
easy:12345

3
pwfile.example Normal file
View 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
View 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
View 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>

View 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,
}

View 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
View File

@ -0,0 +1,3 @@
#!/bin/sh
/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf

View 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
View 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
View 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
View 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, &notification_payload, 1);
rc = _mosquitto_will_set(context, context->bridge->notification_topic, 1, &notification_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, &notification_payload, 1);
rc = _mosquitto_will_set(context, notification_topic, 1, &notification_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