mosquitto-0.15/0000775000175000017500000000000011713444064012527 5ustar rogerrogermosquitto-0.15/config.h0000664000175000017500000000541211713444064014147 0ustar rogerroger/* ============================================================ * Control compile time options. * * Largely, these are options that are designed to make mosquitto run more * easily in restrictive environments by removing features. * ============================================================ */ #ifndef CMAKE /* Only use the compile time options defined here from the standard Makefile. */ /* Uncomment to compile with tcpd/libwrap support. */ //#define WITH_WRAP /* Compile with database upgrading support? If disabled, mosquitto won't * automatically upgrade old database versions. */ //#define WITH_DB_UPGRADE /* Compile with memory tracking support? 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. */ #define WITH_MEMORY_TRACKING /* Compile with persistent database support. 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 by commenting out this define if required. */ #define WITH_PERSISTENCE /* Compile with bridge support included. 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. */ #define WITH_BRIDGE /* Compile 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. */ //#define WITH_STRICT_PROTOCOL /* Use the username/password and ACL checks defined in security_external.c * This is empty by default, but gives a more straightforward way of adding * support for existing username/password databases to mosquitto. * Uncommenting without adding your own code to security_external.c will * result in all access being denied. * It also enables the db_* config options in mosquitto.conf. * Get in touch with the authors if you need help adding support for your * system. */ //#define WITH_EXTERNAL_SECURITY_CHECKS #endif /* ============================================================ * 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 mosquitto-0.15/logo/0000775000175000017500000000000011713444064013467 5ustar rogerrogermosquitto-0.15/logo/mosquitto-16x16.png0000664000175000017500000000106611713444064017027 0ustar rogerrogerPNG  IHDRh6sRGBbKGDPPPƇ pHYs tIME :4IDAT(ϵ?P}$J h!XJ,,l? XWYYhaao/` DD%hPT޻Dz,X:3)f J)7LUh0 !r 7ZVTt:e2vK)EwHRH$r<~n81>~*n{β,x^<,d2zXg1!Xy>vFNS>7M3je#$Ir(fl?>??UU\.$qgFZ%0 s8t]NSEAV+v8 jD"1LfۍFBn_MS0  uCQeB޲,,{4E)tz8l6PJ5M4 {IKcBIENDB`mosquitto-0.15/logo/mosquitto.svg0000664000175000017500000002112711713444064016257 0ustar rogerroger image/svg+xml mosquitto-0.15/logo/mosquitto-14x14.png0000664000175000017500000000100111713444064017010 0ustar rogerrogerPNG  IHDR*sRGBbKGD pHYs0 tIME ~5IDAT(ϵP3&Yq Te` .ڴhY˅Ap )\6|۸{t8|p0I@cx<өmۂ xt7jYrD"t:P("TU?vBl6[B1) 7` X,h4H$dY$i0$Inw]7Ns Zipn1Mzhx9?X,nE4 j(0RTTmq4,J"I>PJzn6ۍRl ˡh:z hZ,c!p>)d]W'/ pEIENDB`mosquitto-0.15/CMakeLists.txt0000664000175000017500000000264611713444064015277 0ustar rogerroger# This is a cmake script. # It is intended to be the default means of building mosquitto, but isn't # quite ready for all cases yet. set(CMAKE_LEGACY_CYGWIN_WIN32 0) project(mosquitto) cmake_minimum_required(VERSION 2.6) set (VERSION 0.15) if (WIN32) execute_process(COMMAND 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) set (SYSCONFDIR etc/mosquitto) set (LIBDIR lib${LIB_SUFFIX}) set (INCLUDEDIR include) set (DATAROOTDIR share) set (MANDIR ${DATAROOTDIR}/man) set (SHAREDIR ${DATAROOTDIR}/mosquitto) endif (WIN32) # ======================================== # Include projects # ======================================== add_subdirectory(lib) add_subdirectory(client) add_subdirectory(src) add_subdirectory(man) # ======================================== # Install config file # ======================================== install(FILES mosquitto.conf aclfile.example pwfile.example DESTINATION ${SYSCONFDIR}) mosquitto-0.15/ChangeLog.txt0000664000175000017500000005513711713444064015132 0ustar rogerroger0.15 - 20120205 =============== - Add support for $SYS/broker/clients/maximum and $SYS/broker/clients/active topics. - Add support for $SYS messages/byte per second received/sent topics. - Updated mosquitto man page - $SYS hierarchy and signal support were out of date. - Auto generated pub/sub client ids now include the hostname. - Tool for dumping persistent DB contents is available in src/db_dump. It isn't installed by default. - Enforce topic length checks in client library. - Implement "once" and "lazy" bridge start types. - Add new return type MOSQ_ERR_ERRNO to indicate that the errno variable should be checked for the real error code. - Add support for connection_messages config option. - mosquitto_sub will now refuse to run if the -c option (disable clean session) is given and no client id is provided. - mosquitto_pub now gives more useful error messages on invalid input or other error conditions. - Fix Python will_set() true/True typo. - Fix messages to topic "a/b" incorrectly matching on a subscription "a" if another subscription "a/#" exists. 0.14.4 - 20120106 ================= - Fix local bridge notification messages. - Fix return values for more internal library calls. - Fix incorrect out of memory checks in library and broker. - Never time out local bridge connections. 0.14.3 - 20111210 ================= - Fix potential crash when client connects with an invalid CONNECT packet. - Fix incorrect invalid socket comparison on Windows. - Server shouldn't crash when a message is published to foo/ when a subscription to foo/# exists (bug #901697). - SO_REUSEADDR doesn't work the same on Windows, so don't use it. - Cygwin builds now support Windows service features. - Fix $SYS/broker/bytes/sent reporting. 0.14.2 - 20111123 ================= - Add uninstall target for libs. - Don't try to write packet whilst in a callback. 0.14.1 - 20111117 ================= - Fix Python sytax errors (bug #891673). 0.14 - 20111116 =============== - Add support for matching ACLs based on client id and username. - Add a Windows installer file (NSIS based). - Add native support for running the broker as a Windows service. This is the default when installed using the new installer. - Fix client count for listeners. When clients disconnect, decrement the count. Allow max_connections to work again. - Attempt to send all packets immediately upon being queued. This will result in more immediate network communication in many cases. - Log IP address when reporting CONNACK packets if the client id isn't yet known. - Fix payload length calculation in python will_set function. - Fix Python publish and will_set functions for payload=None. - Fix keepalive value being lost when reconnecting a client (bug #880863). - Persistence file writing now uses portable file functions, so the Cygwin broker build should no longer be necessary. - Duplicate code between the client and broker side has been reduced. - Queued messages for clients reconnecting with clean_session=false set were not being sent until the next message for that client was received. This has been fixed (bug #890724). - Fix subscriptions to # incorrectly matching against topics beginning with / 0.13 - 20110920 =============== - Implement bridge state notification messages. - Save client last used mid in persistent database (DB version number bumped). - Expose message id in Python MosquittoMessage. - It is now possible to set the topic QoS level for bridges. - Python MosquittoMessage payload parameter is now a Python string, not a ctypes object which makes it much easier to use. - Fix queueing of messages for disconnected clients. The max_queued_messages option is now obeyed. - C++ library is now in its own namespace, mosquittopp. - Add support for adding log message timestamps in the broker. - Fix missing mosquitto_username_pw_set() python binding. - Fix keepalive timeout for reconnecting non clean-session clients. Prevents immediate disconnection on reconnection. - Fix subscription wildcard matching - a subscription of +/+ will now match against /foo - Fix subscription wildcard matching - a subscription of foo/# will now match against foo - When restoring persistent database, clients should be set to non clean-session or their subscriptions will be immediately removed. - Fix SUBACK payload for multiple topic subscriptions. - Don't send retained messages when a client subscribes to a topic it is already subscribed to. 0.12 - 20110725 =============== - Reload (most) configuration on SIGHUP. - Memory tracking is no longer compiled in the client library. - Add --help option to mosquitto to display usage. - Add --id-prefix option to clients to allow easier use with brokers that are using the clientid_prefix option. - Fix compilation on QNX. - Add -P as a synonym argument for --pw in the clients. - Fix python MosquittoMessage payload parameter. This is now returned as a pointer to an array of c_uint8 values so binary data is handled correctly. If a string is needed, use msg.payload_str - Fix memory leaks on client authentication. - If password_file is not defined then clients can now connect even if they use a username/password. - Add mosquitto_reconnect() to the client library. - Add option for compiling with liberal protocol compliance support (enabled by default). - Fix problems with clients reconnecting and old messages remaining in the message store. - Display both ip and client id in the log message when a client connects. Change the socket connection message to make it more obvious that it is just a socket connection being made (bug #801135). - Fix retained message delivery where a subscription contains a +. - Be more lenient when reloading persistent database to reduce errors with empty retained messages. 0.11.3 - 20110707 ================= - Don't complain and quit if persistence_file option is given (bug #802423). - Initialise listeners correctly when clients with duplicate client ids connect. Bug #801678. - Memory tracking is now disabled for Symbian builds due to lack of malloc.h. - Fix memory tracking compilation for kFreeBSD. - Python callbacks can now be used with class member functions. - Fix persistent database writing of client message chunks which caused errors when restoring (bug #798164). 0.11.2 - 20110626 ================= - Don't free contexts in mqtt3_context_disconnect() (bug #799688 / #801678). - Only free will if present when freeing a client context. 0.11.1 - 20110620 ================= - Fix buffer overrun when checking for + and # in topics (bug #799688). - Pub client now quits if publish fails. 0.11 - 20110619 =============== - Removed all old sqlite code. - Remove client id limit in clients. - Implemented $SYS/broker/heap/maximum size - Implemented $SYS/broker/clients/inactive to show the number of disconnected non-clean session clients. - $SYS/broker/heap/current size and maximum size messages now include "bytes" to match rsmb message format. - Implemented the retained_persistence config file option - a synonym of the "persistence" option. - Added security_external.c to broker source to make it easier for third parties to add support for their existing username/password and ACL database for security checks. See external_security_checks.txt. - $SYS messages are now only republished when their value changes. - Windows native broker now responds to command line arguments. - Simplify client disconnecting so wills gets sent in all cases (bug #792468). - Clients now have a --quiet option. - The on_disconnect() callback will always be called now, even if the client has disconnected unexpectedly. - Always close persistent DB file after restoring. - Return error code when exiting the clients. - mosquitto_publish() now returns MOSQ_ERR_INVAL if the topic contains + or # - mosquitto now silently rejects published messages with + or # in the topic. - max_connections is now a per-listener setting instead of global. - Connection count is now reduced when clients disconnect (bug #797983). 0.10.2 - 20110106 ================= - Don't abort when connecting if the first connection fails. This is important on e.g. Windows 7, where IPV6 is offered as the first choice but may not be available. - Deal with long logging messages properly (bug #785882). - Fix library compilation on Symbian - no pselect() available. - Don't stop processing subscriptions on received messages after a subscription with # matches. (bug #791206). 0.10.1 - 20110512 ================= - Fix Windows compilation. - Fix mosquitto.py on Windows - call lib init/cleanup. - Don't abort when connecting if given an unknown address type (assuming an IPv4 or IPv6 address is given). 0.10 - 20110429 =============== - Implement support for the password_file option and accompanying authentication requirements in the broker. - Implement topic Access Control Lists. - mosquitto_will_set() and mosquitto_publish() now return MOSQ_ERR_PAYLOAD_SIZE if the payload is too large (>268,435,455 bytes). - Bridge support can now be disabled at compile time. - Group together network writes for outgoing packets - don't send single byte writes! - Add support for clientid_prefixes variable. - Add support for the clientid config variable for controlling bridge client ids. - Remove 32-bit database ID support because htobe64() no longer used. - Multiple client subscriptions to the same topic result in only a single subscription. Bug #744077. 0.9.3 - 20110310 ================ - Set retained message status for QoS 2 messages (bug #726535). - Only abort with an error when opening listening sockets if no address family is available, rather than aborting when any address family is not available. - Don't clean queued messages when a non clean session client reconnects. - Make mosquitto.py compatible with Python <2.6. - Fix mosquitto.h header includes for Windows. 0.9.2 - 20110208 ================ - Only send a single DISCONNECT command when using -l in the pub client. - Set QoS=1 on PUBREL commands to meet protocol spec. - Don't leak sockets on connection failure in the library. - Install man pages when building under cmake. - Fix crash bug on malformed CONNECT message. - Clients are now rejected if their socket peer name cannot be obtained on connection. - Fix a number of potential problems caused when a client with a duplicate id connects. - Install mosquitto.conf under cmake. 0.9.1 - 20101203 ================ - Add missing code for parsing the "bind_address" configuration option. - Fix missing include when compiling with tcp-wrappers support. - Add linker version script for C library to control exported functions. 0.9 - 20101114 ============== - Client and message data is now stored in memory with custom routines rather than a sqlite database. This removes the dependencies on sqlite, pcre and sqlite3-pcre. It also means that the persistent database format has had to be reimplemented in a custom format. Optional support for importing old sqlite databases is provided. - Added IPv6 support for mosquitto and the clients. - Provide username and password support for the clients and client libraries. This is part of the new MQTT v3.1 spec. - The broker supports the username and password connection flags, but will not do anything with the username and password. - Python callback functions now optionally take an extra argument which will return the user object passed to the Mosquitto() constructor, or the calling python object itself if nothing was given to Mosquitto(). - Remove the mosquitto command line option "-i interface". - Remove the mosquitto.conf "interface" variable. - Add support for the listener config variable (replaces the interface variable) - Add support for the bind_address config variable. - Change the port config variable behaviour to match that of rsmb (applies to the default listener only, can be given just once). - Fix QoS 2 protocol compliance - stop sending duplicate messages and handle timeouts correctly. Fixes bug #598290. - Set retain flag correctly for outgoing messages. It should only be set for messages sent in response to a subscribe command (ie. stale data). - Fix bug in returning correct CONNACK result to on_connect client callback. - Don't send client will if it is disconnected for exceeding its keepalive timer. - Fix client library unsubscribe function incorrectly sending a SUBSCRIBE command when it should be UNSUBSCRIBE. - Fix max_inflight_messages and max_queued_messages operation. These parameters now apply only to QoS 1 and 2 messages and are used regardless of the client connection state. - mosquitto.conf now installed to /etc/mosquitto/mosquitto.conf instead of /etc/mosquitto.conf. The /etc/mosquitto/ directory will be used for password and access control files in the future. - Give the compile time option of using 32-bit integers for the database IDs instead of 64-bit integers. This is useful where htobe64()/be64toh() are not available or for embedded systems for example. - The DUP bit is now set correctly when resending PUBREL messages. - A port to Windows native has been partially completed. This currently drops a number of features, including the ability to change configuration parameters and persistent storage. 0.8.3 - 20101004 ================ - Fix QoS 2 protocol compliance - stop sending duplicate messages and handle timeouts correctly. Fixes bug #598290. (backported from future 0.9 code) 0.8.2 - 20100815 ================ - Fix default loop() timeout value in mosquitto.py. Previous value was 0, causing high cpu load. - Fix message handling problem in client library when more than one message was in the client queue. - Fix the logic used to determine whether a QoS>0 message needs to be retried. - Fix the Python sub.py example so that it quits on error. 0.8.1 - 20100812 ================ - Improve python interface - Fix incorrect return value from message delete function - Use logging function to print error messages in clients. - Fix python installation script DESTDIR. - Fix library destination path for 64-bit machines. 0.8 - 20100807 ============== - Topics starting with a / are treated as distinct to those not starting with a /. For example, /topic/path is different to topic/path. This matches the behaviour of rsmb. - Correctly calculate the will QoS on a new client connection (bug #597451). - Add "addresses" configuration file variable as an alias of "address", for better rsmb compatibility. - Bridge clean_session setting is now false, to give more sensible behaviour and be more compatible with rsmb. - Add cleansession variable for configuring bridges. - Add keepalive_interval variable for bridges. - Remove default topic subscription for mosquitto_sub because the old behaviour was too confusing. - Added a C client library, which the pub and sub clients now use. - Added a C++ client library (bound to the C library). - Added a Python client library (bound to the C library). - Added CMake build scripts to allow the library and clients (not the broker) to be compiled natively on Windows. 0.7 - 20100615 ============== - mosquitto_pub can now send null (zero length) messages. - Don't store QoS=0 messages for disconnected clients with subscriptions of QoS>0. - accept() all available sockets when new clients are connecting, rather than just one. - Add option to print debug messages in pub and sub clients. - hg revision is now exported via $SYS/broker/changeset - Send Will when client exceeds keepalive timer and is disconnected. - Check to see if a client has a will before sending it. - Correctly deal with clients connecting with the same id multiple times. - Add compile time option to disable heap memory tracking. - Use poll() instead of select() to allow >1024 clients. - Implement max_connections. - Run VACUUM on in-memory database on receiving SIGUSR2. - Fix bridge keepalive timeouts and reconnects. - Don't attempt to drop root privileges when running on Windows as this isn't well supported (bug #586231). 0.6.1 - 20100506 ================ - Fix DB auto upgrade for messages table. 0.6 - 20100505 ============== - Basic support for connecting multiple MQTT brokers together (bridging). - mosquitto_sub can now subscribe to multiple topics (limited to a global QoS). - mosquitto_pub can now send a file as a message. - mosquitto_pub can now read all of stdin and send it as a message. - mosquitto_pub can now read stdin and send each line as a message. - mosquitto will now correctly run VACUUM on the persistent database on exit. - Implement a more efficient database design, so that only one copy of each message is held in the database, rather than one per subscribed client. - Add the store_cleanup_interval config option for dealing with the internal message store. - Add support for disabling "clean session" for the sub client. - Add support for automatic upgrading of the mosquitto DB from v1 to v2. - Add persistence_file config option to allow changing the filename of the persistence database. This allows multiple mosquitto DBs to be stored in the same location whilst keeping persistence_location compatible with rsmb. - Don't store QoS=0 messages for disconnected clients. Fixes bug #572608. This wasn't correctly fixed in version 0.5. - Don't disconnect clients if they send a PUBLISH with zero length payload (bug #573610). - If a retained message is received with a zero length payload, the retained message for that topic is deleted. - Send through zero length messages. - Produce a warning on unsupported rsmb options instead of quitting. - Describe clean session flag in the mqtt man page. - Implement the max_inflight_messages and max_queued_messages features in the broker. 0.5.4 - 20100311 ================ - Fix memory allocation in mqtt3_fix_sub_topic() (bug #531861). - Remove accidental limit of 100 client connections. - Fix mosquitto_pub handling of messages with QoS>0 (bug #537061). 0.5.3 - 20100303 ================ - Will messages are now only sent when a client disconnects unexpectedly. - Fix all incoming topics/subscriptions that start with a / or contain multiple / in a row (//). - Do actually disconnect client when it sends an empty subscription/topic string. - Add missing $SYS/broker/clients/total to man page. 0.5.2 - 20100302 ================ - Always update last backup time, so that the backup doesn't run every time through the main loop once autosave_interval has been reached. - Report $SYS/broker/uptime in the same format as rsmb. - Make mandatory options obvious in usage output and man page of mosquitto_pub. Fixes bug #529990. - Treat subscriptions with a trailing slash correctly. This should fix bugs #530369 and #530099. 0.5.1 - 20100227 ================ - Must daemonise before pid file is written. 0.5 - 20100227 ============== - No longer store QoS=0 messages for disconnected clients that do not have clean start set. - Rename msg_timeout option to retry_interval for better rsmb compatibility. - Change persistence behaviour. The database is now stored in memory even if persistence is enabled. It is written to disk when mosquitto exits and also at periodic intervals as defined by the new autosave_interval option. - The writing of the persistence database may be forced by sending mosquitto the SIGUSR1 signal. - Clients that do not send CONNECT as their first command are now disconnected. - Boolean configuration values may now be specified with true/false as well as 1/0. - Log message on CONNECT with invalid protocol or protocol version. - Default sqlite3-pcre path on Linux is now /usr/lib/sqlite3/pcre.so to match future sqlite3-pcre packages. - Add mosquitto_sub and mosquitto_pub, simple clients for subscribe/publish. - Add man pages for clients. - Add general man page on mqtt. - Root privileges are now dropped only after attempting to write a pid file (if configured). This means that the pid file can be written to /var/run/ directly and should fix bug #523183. 0.4.2 - 20100203 ================ - Fix segfault on client connect with invalid protocol name/version. 0.4.1 - 20100112 =============== - Fix regex used for finding retained messages to send on new subscription. 0.4 - 20100105 ============== - Added support for wildcard subscriptions using + and #. - All network operations are now non-blocking and can cope with partial packets, meaning that networking should be a lot more reliable. - Total messsages/bytes sent/received are now available in $SYS. - Improved logging information - use client ip address and id instead of socket number. - Broker build timestamp is available in $SYS. - Keepalive==0 is now correctly treated as "never disconnect". - Fixed manpage installation. - Fixed incorrect $SYS hierarchy locations in documentation and code. - Debug type log messages are no longer sent to "topics". - Default logging destination no longer includes "topics" to prevent possible error logging to the db before it is initialised. - Periodic $SYS messages can now be disabled. - stdout and stderr are flushed when logging to them to give more timely updates. - dup is now set correctly when resending messages. - Database format bumped due to topic column naming fix. 0.3 - 20091217 ============== - The port option in the configuration file and --port command line argument may now be given any number of times to make mosquitto listen on multiple sockets. - Add new config file and command line option "interface" to specify an interface to listen on, rather than all interfaces. - Added host access control through tcp-wrappers support. - Set SO_REUSEADDR on the listening socket so restart is much quicker. - Added support for tracking current heap memory usage - this is published on the topic "$SYS/broker/heap/current size" - Added code for logging to stderr, stdout, syslog and topics. - Added logging to numerous places - still plenty of scope for more. 0.2 - 20091204 ============== - Replaced the command line option --foreground with --daemon, swapping the default behaviour. - Added the command line option --config-file, to specify a config file to load. If this is not given, no config file is load and the default options are used. - Added the command line option --port for specifying the port to listen on. This overrides values in the config file. - Don't use persistence by default. - Default behaviour is now more sane when run by a normal user with no command line options (combination of above changes). - Added option user to config file, defaulting to a value of mosquitto. If this value isn't blank and mosquitto is started by root, then it will drop privileges by changing to the user and its primary group. This replaces the current behaviour of refusing to start if run by root. - Fix non-persistent mode, which would never work in the previous release. - Added information on default values of msg_timeout and sys_interval to the mosquitto.conf man page. (closes bug #492045). mosquitto-0.15/compiling.txt0000664000175000017500000000100011713444064015240 0ustar rogerrogerAdd a very brief blurb on packages needed for compiling The following packages are required for mosquitto: tcp-wrappers (optional, package name libwrap0-dev) To compile, run "make". tcp-wrappers support can be added by editing config.h to comment out the appropriate #define lines. Use cmake to compile on Windows. 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. mosquitto-0.15/service/0000775000175000017500000000000011713444064014167 5ustar rogerrogermosquitto-0.15/service/monit/0000775000175000017500000000000011713444064015315 5ustar rogerrogermosquitto-0.15/service/monit/mosquitto.monit0000664000175000017500000000021111713444064020423 0ustar rogerrogercheck process mosquitto with pidfile /var/run/mosquitto.pid start = "/etc/init.d/mosquitto start" stop = "/etc/init.d/mosquitto stop" mosquitto-0.15/service/svscan/0000775000175000017500000000000011713444064015464 5ustar rogerrogermosquitto-0.15/service/svscan/run0000775000175000017500000000010011713444064016205 0ustar rogerroger#!/bin/sh /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf mosquitto-0.15/service/upstart/0000775000175000017500000000000011713444064015671 5ustar rogerrogermosquitto-0.15/service/upstart/mosquitto.conf0000664000175000017500000000025411713444064020605 0ustar rogerrogerdescription "Mosquitto MQTTv3.1 broker" author "Roger Light " start on net-device-up respawn exec /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf mosquitto-0.15/COPYING0000664000175000017500000000274211713444064013567 0ustar rogerrogerCopyright (c) 2009-2012 Roger Light 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-0.15/mosquitto.conf0000664000175000017500000003236611713444064015454 0ustar rogerroger# 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. #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 10. Set to 0 for no # maximum. Setting to 1 will guarantee in-order delivery of QoS 1 # and 2 messages. #max_inflight_messages 10 # 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). #max_queued_messages 100 # ================================================================= # 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 # ================================================================= # 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 # ================================================================= # 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. # Note that writing of the persistence database can be forced by # sending mosquitto a SIGUSR1 signal. #autosave_interval 1800 # 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 /var/lib/mosquitto/ if running as a proper service. #persistence_location # ================================================================= # Logging # ================================================================= # Places to log to. Use multiple log_dest lines for multiple # logging destinations. # Possible destinations are: stdout stderr syslog topic # 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/', # where severity is one of D, E, W, N, I which are debug, error, # warning, notice and information. # 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. # Note that debug type messages are for decoding the incoming # network packets. # They are not logged in syslog. #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 # Control access to the broker using a password file. The file is a # text file # of 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. #password_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. # Topic access is added with lines of the format: # # topic [read|write] # # The access type is controlled using "read" or "write". This parameter # is optional - if not given then the access is read/write. # 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 # # 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. # # pattern [read|write] # # Example: # # pattern write sensor/%u/data # #acl_file # ================================================================= # Bridges # ================================================================= # Experimental support for connecting multiple MQTT brokers # together. # Specify multiple sets of connection, address and topic # configurations. # Each connection must have a unique name. # Only a single address per configuration is currently supported, # unlike in rsmb. # 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 final # topic option. The default QoS level is 2, to change the QoS the topic # direction must also be given. # Multiple topics can be specified per connection, but be careful # not to create any loops. #connection #address [:] #topic [[out | in | both] qos-level] # 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/bridge/connection//state. # If the message is 1 then the connection is active, or 0 if the connection has # failed. #notifications true # 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 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 # 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 # ================================================================= # External security checks # ================================================================= # This section defines options for potential use with external # databases. # They are intended to make it easier to add external security # checks along with WITH_EXT_SECURITY_CHECKS. If you haven't written # code to support another database and compiled support in, you are # unlikely to need to change anything here. # Database hostname. #db_host # Database port. #db_port # Database name. #db_name # Database username. #db_username # Database password. #db_password # ================================================================= # Unsupported rsmb options - for the future # ================================================================= #autosave_on_changes #addresses #notification_topic #round_robin # ================================================================= # rsmb options - unlikely to ever be supported # ================================================================= #ffdc_output #max_log_entries #trace_level #trace_output #try_private mosquitto-0.15/src/0000775000175000017500000000000011713444064013316 5ustar rogerrogermosquitto-0.15/src/service.c0000664000175000017500000001132311713444064015122 0ustar rogerroger/* Copyright (c) 2011 Roger Light 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. */ #if defined(WIN32) || defined(__CYGWIN__) #include #include extern int run; static SERVICE_STATUS_HANDLE service_handle; static SERVICE_STATUS service_status; int main(int argc, char *argv[]); /* Service control callback */ void __stdcall service_handler(DWORD fdwControl) { switch(fdwControl){ case SERVICE_CONTROL_CONTINUE: /* Continue from Paused state. */ break; case SERVICE_CONTROL_PAUSE: /* Pause service. */ break; case SERVICE_CONTROL_SHUTDOWN: /* System is shutting down. */ case SERVICE_CONTROL_STOP: /* Service should stop. */ service_status.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus(service_handle, &service_status); run = 0; break; } } /* Function called when started as a service. */ void __stdcall service_main(DWORD dwArgc, LPTSTR *lpszArgv) { char **argv; int argc = 1; char conf_path[MAX_PATH + 20]; int rc; service_handle = RegisterServiceCtrlHandler("mosquitto", service_handler); if(service_handle){ rc = GetEnvironmentVariable("MOSQUITTO_DIR", conf_path, MAX_PATH); if(!rc || rc == MAX_PATH){ service_status.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(service_handle, &service_status); return; } strcat(conf_path, "/mosquitto.conf"); argv = _mosquitto_malloc(sizeof(char *)*3); argv[0] = "mosquitto"; argv[1] = "-c"; argv[2] = conf_path; argc = 3; service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; service_status.dwCurrentState = SERVICE_RUNNING; service_status.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP; service_status.dwWin32ExitCode = NO_ERROR; service_status.dwCheckPoint = 0; SetServiceStatus(service_handle, &service_status); main(argc, argv); _mosquitto_free(argv); service_status.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(service_handle, &service_status); } } void service_install(void) { SC_HANDLE sc_manager, svc_handle; char exe_path[MAX_PATH + 5]; SERVICE_DESCRIPTION svc_desc; GetModuleFileName(NULL, exe_path, MAX_PATH); strcat(exe_path, " run"); sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if(sc_manager){ svc_handle = CreateService(sc_manager, "mosquitto", "Mosquitto Broker", SERVICE_START | SERVICE_STOP | SERVICE_CHANGE_CONFIG, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, exe_path, NULL, NULL, NULL, NULL, NULL); if(svc_handle){ svc_desc.lpDescription = "MQTT v3.1 broker"; ChangeServiceConfig2(svc_handle, SERVICE_CONFIG_DESCRIPTION, &svc_desc); CloseServiceHandle(svc_handle); } CloseServiceHandle(sc_manager); } } void service_uninstall(void) { SC_HANDLE sc_manager, svc_handle; SERVICE_STATUS status; sc_manager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); if(sc_manager){ svc_handle = OpenService(sc_manager, "mosquitto", SERVICE_QUERY_STATUS | DELETE); if(svc_handle){ if(QueryServiceStatus(svc_handle, &status)){ if(status.dwCurrentState == SERVICE_STOPPED){ DeleteService(svc_handle); } } CloseServiceHandle(svc_handle); } CloseServiceHandle(sc_manager); } } void service_run(void) { SERVICE_TABLE_ENTRY ste[] = { { "mosquitto", service_main }, { NULL, NULL } }; StartServiceCtrlDispatcher(ste); } #endif mosquitto-0.15/src/CMakeLists.txt0000664000175000017500000000441311713444064016060 0ustar rogerrogerinclude_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 logging.c loop.c ../lib/memory_mosq.c ../lib/memory_mosq.h mosquitto.c mqtt3.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_external.c ../lib/send_client_mosq.c ../lib/send_mosq.h ../lib/send_mosq.c ../lib/send_mosq.h send_server.c ../lib/util_mosq.c ../lib/util_mosq.h ../lib/will_mosq.c ../lib/will_mosq.h) set (MOSQ_LIBS ${OPENSSL_LIBRARIES}) 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) if (WIN32 OR CYGWIN) set (MOSQ_SRCS ${MOSQ_SRCS} service.c) endif (WIN32 OR CYGWIN) option(WITH_EXTERNAL_SECURITY_CHECKS "Use external security checks (needs additional code)?" OFF) if (${WITH_EXTERNAL_SECURITY_CHECKS} STREQUAL ON) add_definitions("-DWITH_EXTERNAL_SECURITY_CHECKS") endif (${WITH_EXTERNAL_SECURITY_CHECKS} STREQUAL ON) add_definitions (-DWITH_BROKER) add_executable(mosquitto ${MOSQ_SRCS}) if (NOT WIN32) target_link_libraries(mosquitto ${MOSQ_LIBS}) else (NOT WIN32) target_link_libraries(mosquitto ws2_32 ${MOSQ_LIBS}) endif (NOT WIN32) install(TARGETS mosquitto RUNTIME DESTINATION ${SBINDIR} LIBRARY DESTINATION ${LIBDIR}) if (UNIX) install(CODE "EXEC_PROGRAM(/sbin/ldconfig)") endif (UNIX) mosquitto-0.15/src/loop.c0000664000175000017500000002161411713444064014437 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #ifndef WIN32 #include #else #include #include #include #endif #include #include #include #include #include #include extern bool flag_reload; #ifdef WITH_PERSISTENCE extern bool flag_db_backup; #endif extern bool flag_tree_print; extern int run; static void loop_handle_errors(mosquitto_db *db, struct pollfd *pollfds); static void loop_handle_reads_writes(mosquitto_db *db, struct pollfd *pollfds); int mosquitto_main_loop(mosquitto_db *db, int *listensock, int listensock_count, int listener_max) { time_t start_time = time(NULL); time_t last_backup = time(NULL); time_t last_store_clean = time(NULL); time_t now; int fdcount; #ifndef WIN32 sigset_t sigblock, origsig; #endif int i; struct pollfd *pollfds = NULL; unsigned int pollfd_count = 0; int client_max = 0; unsigned int sock_max = 0; #ifndef WIN32 sigemptyset(&sigblock); sigaddset(&sigblock, SIGINT); #endif while(run){ mqtt3_db_sys_update(db, db->config->sys_interval, start_time); client_max = -1; for(i=0; icontext_count; i++){ if(db->contexts[i] && db->contexts[i]->sock != INVALID_SOCKET && db->contexts[i]->sock > client_max){ client_max = db->contexts[i]->sock; } } if(client_max > listener_max){ sock_max = client_max; }else{ sock_max = listener_max; } if(sock_max+1 > pollfd_count){ pollfd_count = sock_max+1; pollfds = _mosquitto_realloc(pollfds, sizeof(struct pollfd)*pollfd_count); if(!pollfds){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } } memset(pollfds, -1, sizeof(struct pollfd)*pollfd_count); for(i=0; icontext_count; i++){ if(db->contexts[i]){ if(db->contexts[i]->sock != INVALID_SOCKET){ if(db->contexts[i]->sock > sock_max){ sock_max = db->contexts[i]->sock; } #ifdef WITH_BRIDGE if(db->contexts[i]->bridge){ _mosquitto_check_keepalive(db->contexts[i]); } #endif /* Local bridges never time out in this fashion. */ if(!(db->contexts[i]->keepalive) || db->contexts[i]->bridge || now - db->contexts[i]->last_msg_in < (time_t)(db->contexts[i]->keepalive)*3/2){ if(mqtt3_db_message_write(db->contexts[i]) == MOSQ_ERR_SUCCESS){ if(db->contexts[i]->sock < pollfd_count){ pollfds[db->contexts[i]->sock].fd = db->contexts[i]->sock; pollfds[db->contexts[i]->sock].events = POLLIN; pollfds[db->contexts[i]->sock].revents = 0; if(db->contexts[i]->out_packet){ pollfds[db->contexts[i]->sock].events |= POLLOUT; } } }else{ mqtt3_context_disconnect(db, i); } }else{ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client %s has exceeded timeout, disconnecting.", db->contexts[i]->id); } /* Client has exceeded keepalive*1.5 */ mqtt3_context_disconnect(db, i); } }else{ #ifdef WITH_BRIDGE if(db->contexts[i]->bridge){ /* Want to try to restart the bridge connection */ if(!db->contexts[i]->bridge->restart_t){ db->contexts[i]->bridge->restart_t = time(NULL)+30; }else{ if(db->contexts[i]->bridge->start_type == bst_automatic && time(NULL) > db->contexts[i]->bridge->restart_t){ db->contexts[i]->bridge->restart_t = 0; mqtt3_bridge_connect(db, db->contexts[i]); } } }else{ #endif if(db->contexts[i]->clean_session == true){ mqtt3_context_cleanup(db, db->contexts[i], true); db->contexts[i] = NULL; } #ifdef WITH_BRIDGE } #endif } } } mqtt3_db_message_timeout_check(db, db->config->retry_interval); #ifndef WIN32 sigprocmask(SIG_SETMASK, &sigblock, &origsig); fdcount = poll(pollfds, pollfd_count, 1000); sigprocmask(SIG_SETMASK, &origsig, NULL); #else fdcount = WSAPoll(pollfds, pollfd_count, 1000); #endif if(fdcount == -1){ loop_handle_errors(db, pollfds); }else{ loop_handle_reads_writes(db, pollfds); for(i=0; iconfig->persistence && db->config->autosave_interval){ if(last_backup + db->config->autosave_interval < now){ mqtt3_db_backup(db, false, false); last_backup = time(NULL); } } #endif if(!db->config->store_clean_interval || last_store_clean + db->config->store_clean_interval < now){ mqtt3_db_store_clean(db); last_store_clean = time(NULL); } #ifdef WITH_PERSISTENCE if(flag_db_backup){ mqtt3_db_backup(db, false, false); flag_db_backup = false; } #endif if(flag_reload){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Reloading config."); mqtt3_config_read(db->config, true); mosquitto_security_cleanup(db); mosquitto_security_init(db); mosquitto_security_apply(db); flag_reload = false; } if(flag_tree_print){ mqtt3_sub_tree_print(&db->subs, 0); flag_tree_print = false; } } if(pollfds) _mosquitto_free(pollfds); return MOSQ_ERR_SUCCESS; } /* Error ocurred, probably an fd has been closed. * Loop through and check them all. */ static void loop_handle_errors(mosquitto_db *db, struct pollfd *pollfds) { int i; for(i=0; icontext_count; i++){ if(db->contexts[i] && db->contexts[i]->sock != INVALID_SOCKET){ if(pollfds[db->contexts[i]->sock].revents & POLLHUP){ if(db->config->connection_messages == true){ if(db->contexts[i]->state != mosq_cs_disconnecting){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Socket error on client %s, disconnecting.", db->contexts[i]->id); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client %s disconnected.", db->contexts[i]->id); } } mqtt3_context_disconnect(db, i); } } } } static void loop_handle_reads_writes(mosquitto_db *db, struct pollfd *pollfds) { int i; for(i=0; icontext_count; i++){ if(db->contexts[i] && db->contexts[i]->sock != INVALID_SOCKET){ if(pollfds[db->contexts[i]->sock].revents & POLLOUT){ if(_mosquitto_packet_write(db->contexts[i])){ if(db->config->connection_messages == true){ if(db->contexts[i]->state != mosq_cs_disconnecting){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Socket write error on client %s, disconnecting.", db->contexts[i]->id); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client %s disconnected.", db->contexts[i]->id); } } /* Write error or other that means we should disconnect */ mqtt3_context_disconnect(db, i); } } } if(db->contexts[i] && db->contexts[i]->sock != INVALID_SOCKET){ if(pollfds[db->contexts[i]->sock].revents & POLLIN){ if(_mosquitto_packet_read(db, i)){ if(db->config->connection_messages == true){ if(db->contexts[i]->state != mosq_cs_disconnecting){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Socket read error on client %s, disconnecting.", db->contexts[i]->id); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client %s disconnected.", db->contexts[i]->id); } } /* Read error or other that means we should disconnect */ mqtt3_context_disconnect(db, i); } } } } } mosquitto-0.15/src/net.c0000664000175000017500000001630011713444064014250 0ustar rogerroger/* Copyright (c) 2009-2011 Roger Light Copyright (c) 2011 Yuvraaj Kelkar 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. */ #include #ifndef WIN32 #include #include #else #include #include #endif #include #include #include #include #include #ifdef WITH_WRAP #include #endif #ifdef __QNX__ #include #include #include #endif #include #include #include #include uint64_t bytes_received = 0; uint64_t bytes_sent = 0; unsigned long msgs_received = 0; unsigned long msgs_sent = 0; int mqtt3_socket_accept(struct _mosquitto_db *db, int listensock) { int i; int j; int new_sock = -1; struct mosquitto **tmp_contexts = NULL; struct mosquitto *new_context; int opt = 1; #ifdef WITH_WRAP struct request_info wrap_req; #endif new_sock = accept(listensock, NULL, 0); if(new_sock == INVALID_SOCKET) return -1; #ifndef WIN32 /* Set non-blocking */ opt = fcntl(new_sock, F_GETFL, 0); if(opt == -1 || fcntl(new_sock, F_SETFL, opt | O_NONBLOCK) == -1){ /* If either fcntl fails, don't want to allow this client to connect. */ close(new_sock); return -1; } #else if(ioctlsocket(new_sock, FIONBIO, &opt)){ closesocket(new_sock); return INVALID_SOCKET; } #endif #ifdef WITH_WRAP /* Use tcpd / libwrap to determine whether a connection is allowed. */ request_init(&wrap_req, RQ_FILE, new_sock, RQ_DAEMON, "mosquitto", 0); fromhost(&wrap_req); if(!hosts_access(&wrap_req)){ /* Access is denied */ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client connection denied access by tcpd."); COMPAT_CLOSE(new_sock); return -1; }else{ #endif new_context = mqtt3_context_init(new_sock); if(!new_context){ COMPAT_CLOSE(new_sock); return -1; } for(i=0; iconfig->listener_count; i++){ for(j=0; jconfig->listeners[i].sock_count; j++){ if(db->config->listeners[i].socks[j] == listensock){ new_context->listener = &db->config->listeners[i]; break; } } } if(!new_context->listener){ COMPAT_CLOSE(new_sock); return -1; } if(new_context->listener->max_connections > 0 && new_context->listener->client_count >= new_context->listener->max_connections){ COMPAT_CLOSE(new_sock); return -1; } _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "New connection from %s.", new_context->address); for(i=0; icontext_count; i++){ if(db->contexts[i] == NULL){ db->contexts[i] = new_context; break; } } if(i==db->context_count){ tmp_contexts = _mosquitto_realloc(db->contexts, sizeof(struct mosquitto*)*(db->context_count+1)); if(tmp_contexts){ db->context_count++; db->contexts = tmp_contexts; db->contexts[db->context_count-1] = new_context; }else{ mqtt3_context_cleanup(NULL, new_context, true); } } new_context->listener->client_count++; #ifdef WITH_WRAP } #endif return new_sock; } /* Creates a socket and listens on port 'port'. * Returns 1 on failure * Returns 0 on success. */ int mqtt3_socket_listen(struct _mqtt3_listener *listener) { int sock = -1; struct addrinfo hints; struct addrinfo *ainfo, *rp; char service[10]; int opt = 1; #ifndef WIN32 int ss_opt = 1; #else char ss_opt = 1; #endif if(!listener) return MOSQ_ERR_INVAL; snprintf(service, 10, "%d", listener->port); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; if(getaddrinfo(listener->host, service, &hints, &ainfo)) return INVALID_SOCKET; listener->sock_count = 0; listener->socks = NULL; for(rp = ainfo; rp; rp = rp->ai_next){ if(rp->ai_family == AF_INET){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Opening ipv4 listen socket on port %d.", ntohs(((struct sockaddr_in *)rp->ai_addr)->sin_port)); }else if(rp->ai_family == AF_INET6){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Opening ipv6 listen socket on port %d.", ntohs(((struct sockaddr_in6 *)rp->ai_addr)->sin6_port)); }else{ continue; } sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if(sock == -1){ _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: %s", strerror(errno)); continue; } listener->sock_count++; listener->socks = _mosquitto_realloc(listener->socks, sizeof(int)*listener->sock_count); if(!listener->socks){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } listener->socks[listener->sock_count-1] = sock; #ifndef WIN32 ss_opt = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &ss_opt, sizeof(ss_opt)); #endif ss_opt = 1; setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ss_opt, sizeof(ss_opt)); #ifndef WIN32 /* Set non-blocking */ opt = fcntl(sock, F_GETFL, 0); if(opt == -1 || fcntl(sock, F_SETFL, opt | O_NONBLOCK) == -1){ /* If either fcntl fails, don't want to allow this client to connect. */ COMPAT_CLOSE(sock); return 1; } #else if(ioctlsocket(sock, FIONBIO, &opt)){ COMPAT_CLOSE(sock); return 1; } #endif if(bind(sock, rp->ai_addr, rp->ai_addrlen) == -1){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s", strerror(errno)); COMPAT_CLOSE(sock); return 1; } if(listen(sock, 100) == -1){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s", strerror(errno)); COMPAT_CLOSE(sock); return 1; } } freeaddrinfo(ainfo); /* We need to have at least one working socket. */ if(listener->sock_count > 0){ return 0; }else{ return 1; } } uint64_t mqtt3_net_bytes_total_received(void) { return bytes_received; } uint64_t mqtt3_net_bytes_total_sent(void) { return bytes_sent; } unsigned long mqtt3_net_msgs_total_received(void) { return msgs_received; } unsigned long mqtt3_net_msgs_total_sent(void) { return msgs_sent; } mosquitto-0.15/src/send_server.c0000664000175000017500000000600311713444064016000 0ustar rogerroger/* Copyright (c) 2009-2011 Roger Light 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. */ #include #include #include #include #include int _mosquitto_send_connack(struct mosquitto *context, uint8_t result) { struct _mosquitto_packet *packet = NULL; int rc; if(context){ if(context->id){ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending CONNACK to %s (%d)", context->id, result); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending CONNACK to %s (%d)", context->address, result); } } packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet)); if(!packet) return MOSQ_ERR_NOMEM; packet->command = CONNACK; packet->remaining_length = 2; rc = _mosquitto_packet_alloc(packet); if(rc){ _mosquitto_free(packet); return rc; } packet->payload[packet->pos+0] = 0; packet->payload[packet->pos+1] = result; return _mosquitto_packet_queue(context, packet); } int _mosquitto_send_suback(struct mosquitto *context, uint16_t mid, uint32_t payloadlen, const uint8_t *payload) { struct _mosquitto_packet *packet = NULL; int rc; _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Sending SUBACK to %s", context->id); packet = _mosquitto_calloc(1, sizeof(struct _mosquitto_packet)); if(!packet) return MOSQ_ERR_NOMEM; packet->command = SUBACK; packet->remaining_length = 2+payloadlen; rc = _mosquitto_packet_alloc(packet); if(rc){ _mosquitto_free(packet); return rc; } _mosquitto_write_uint16(packet, mid); if(payloadlen){ _mosquitto_write_bytes(packet, payload, payloadlen); } return _mosquitto_packet_queue(context, packet); } mosquitto-0.15/src/context.c0000664000175000017500000001264711713444064015160 0ustar rogerroger/* Copyright (c) 2009-2011 Roger Light 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. */ #include #ifndef WIN32 #include #include #else #include #endif #include #include #include struct mosquitto *mqtt3_context_init(int sock) { struct mosquitto *context; struct sockaddr_storage addr; socklen_t addrlen; char address[1024]; context = _mosquitto_malloc(sizeof(struct mosquitto)); if(!context) return NULL; context->state = mosq_cs_new; context->sock = sock; context->last_msg_in = time(NULL); context->last_msg_out = time(NULL); context->keepalive = 60; /* Default to 60s */ context->clean_session = true; context->id = NULL; context->last_mid = 0; context->will = NULL; context->username = NULL; context->password = NULL; context->listener = NULL; context->acl_list = NULL; context->in_packet.payload = NULL; _mosquitto_packet_cleanup(&context->in_packet); context->out_packet = NULL; addrlen = sizeof(addr); context->address = NULL; if(!getpeername(sock, (struct sockaddr *)&addr, &addrlen)){ if(addr.ss_family == AF_INET){ if(inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr.s_addr, address, 1024)){ context->address = _mosquitto_strdup(address); } }else if(addr.ss_family == AF_INET6){ if(inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr.s6_addr, address, 1024)){ context->address = _mosquitto_strdup(address); } } } if(!context->address && sock != -1){ /* getpeername and inet_ntop failed and not a bridge */ _mosquitto_free(context); return NULL; } context->bridge = NULL; context->msgs = NULL; #ifdef WITH_SSL context->ssl = NULL; #endif return context; } /* * This will result in any outgoing packets going unsent. If we're disconnected * forcefully then it is usually an error condition and shouldn't be a problem, * but it will mean that CONNACK messages will never get sent for bad protocol * versions for example. */ void mqtt3_context_cleanup(mosquitto_db *db, struct mosquitto *context, bool do_free) { struct _mosquitto_packet *packet; mosquitto_client_msg *msg, *next; if(!context) return; if(context->username){ _mosquitto_free(context->username); context->username = NULL; } if(context->password){ _mosquitto_free(context->password); context->password = NULL; } if(context->sock != -1){ if(context->listener){ context->listener->client_count--; assert(context->listener->client_count >= 0); } _mosquitto_socket_close(context); context->listener = NULL; } if(context->clean_session && db){ mqtt3_subs_clean_session(context, &db->subs); mqtt3_db_messages_delete(context); } if(context->address){ _mosquitto_free(context->address); context->address = NULL; } if(context->id){ _mosquitto_free(context->id); context->id = NULL; } _mosquitto_packet_cleanup(&(context->in_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); } if(context->will){ if(context->will->topic) _mosquitto_free(context->will->topic); if(context->will->payload) _mosquitto_free(context->will->payload); _mosquitto_free(context->will); } if(do_free || context->clean_session){ msg = context->msgs; while(msg){ next = msg->next; msg->store->ref_count--; _mosquitto_free(msg); msg = next; } context->msgs = NULL; } if(do_free){ _mosquitto_free(context); } } void mqtt3_context_disconnect(mosquitto_db *db, int context_index) { struct mosquitto *ctxt; ctxt = db->contexts[context_index]; if(ctxt->state != mosq_cs_disconnecting && ctxt->will){ /* Unexpected disconnect, queue the client will. */ mqtt3_db_messages_easy_queue(db, ctxt, ctxt->will->topic, ctxt->will->qos, ctxt->will->payloadlen, ctxt->will->payload, ctxt->will->retain); } if(ctxt->listener){ ctxt->listener->client_count--; assert(ctxt->listener->client_count >= 0); ctxt->listener = NULL; } _mosquitto_socket_close(ctxt); } mosquitto-0.15/src/read_handle_server.c0000664000175000017500000003216511713444064017305 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #include #include #include #include #include #include #include int mqtt3_handle_connect(mosquitto_db *db, int context_index) { char *protocol_name; uint8_t protocol_version; uint8_t connect_flags; char *client_id; char *will_message = NULL, *will_topic = NULL; struct mosquitto_message *will_struct = NULL; uint8_t will, will_retain, will_qos, clean_session; uint8_t username_flag, password_flag; char *username, *password = NULL; int i; int rc; struct _mosquitto_acl_user *acl_tail; struct mosquitto *context; context = db->contexts[context_index]; /* Don't accept multiple CONNECT commands. */ if(context->state != mosq_cs_new){ mqtt3_context_disconnect(db, context_index); return MOSQ_ERR_PROTOCOL; } if(_mosquitto_read_string(&context->in_packet, &protocol_name)){ mqtt3_context_disconnect(db, context_index); return 1; } if(!protocol_name){ mqtt3_context_disconnect(db, context_index); return 3; } if(strcmp(protocol_name, PROTOCOL_NAME)){ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid protocol \"%s\" in CONNECT from %s.", protocol_name, context->address); } _mosquitto_free(protocol_name); mqtt3_context_disconnect(db, context_index); return MOSQ_ERR_PROTOCOL; } _mosquitto_free(protocol_name); if(_mosquitto_read_byte(&context->in_packet, &protocol_version)){ mqtt3_context_disconnect(db, context_index); return 1; } if(protocol_version != PROTOCOL_VERSION){ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid protocol version %d in CONNECT from %s.", protocol_version, context->address); } _mosquitto_free(protocol_name); _mosquitto_send_connack(context, 1); mqtt3_context_disconnect(db, context_index); return MOSQ_ERR_PROTOCOL; } if(_mosquitto_read_byte(&context->in_packet, &connect_flags)){ mqtt3_context_disconnect(db, context_index); return 1; } clean_session = connect_flags & 0x02; will = connect_flags & 0x04; will_qos = (connect_flags & 0x18) >> 3; will_retain = connect_flags & 0x20; password_flag = connect_flags & 0x40; username_flag = connect_flags & 0x80; if(_mosquitto_read_uint16(&context->in_packet, &(context->keepalive))){ mqtt3_context_disconnect(db, context_index); return 1; } if(_mosquitto_read_string(&context->in_packet, &client_id)){ mqtt3_context_disconnect(db, context_index); return 1; } /* clientid_prefixes check */ if(db->config->clientid_prefixes){ if(strncmp(db->config->clientid_prefixes, client_id, strlen(db->config->clientid_prefixes))){ _mosquitto_free(client_id); _mosquitto_send_connack(context, 2); mqtt3_context_disconnect(db, context_index); return MOSQ_ERR_SUCCESS; } } if(will){ will_struct = _mosquitto_calloc(1, sizeof(struct mosquitto_message)); if(!will_struct){ _mosquitto_free(client_id); mqtt3_context_disconnect(db, context_index); return MOSQ_ERR_NOMEM; } if(_mosquitto_read_string(&context->in_packet, &will_topic)){ _mosquitto_free(client_id); mqtt3_context_disconnect(db, context_index); return 1; } if(_mosquitto_read_string(&context->in_packet, &will_message)){ _mosquitto_free(client_id); mqtt3_context_disconnect(db, context_index); return 1; } } if(username_flag){ rc = _mosquitto_read_string(&context->in_packet, &username); if(rc == MOSQ_ERR_SUCCESS){ if(password_flag){ rc = _mosquitto_read_string(&context->in_packet, &password); if(rc == MOSQ_ERR_NOMEM){ _mosquitto_free(username); _mosquitto_free(client_id); return MOSQ_ERR_NOMEM; }else if(rc == MOSQ_ERR_PROTOCOL){ /* Password flag given, but no password. Ignore. */ password_flag = 0; } } rc = mosquitto_unpwd_check(db, username, password); context->username = username; context->password = password; if(rc == MOSQ_ERR_AUTH){ _mosquitto_send_connack(context, 2); mqtt3_context_disconnect(db, context_index); _mosquitto_free(client_id); return MOSQ_ERR_SUCCESS; }else if(rc == MOSQ_ERR_INVAL){ _mosquitto_free(client_id); return MOSQ_ERR_INVAL; } }else if(rc == MOSQ_ERR_NOMEM){ _mosquitto_free(client_id); return MOSQ_ERR_NOMEM; }else{ /* Username flag given, but no username. Ignore. */ username_flag = 0; } } if(!username_flag && db->config->allow_anonymous == false){ _mosquitto_send_connack(context, 2); mqtt3_context_disconnect(db, context_index); _mosquitto_free(client_id); return MOSQ_ERR_SUCCESS; } /* Find if this client already has an entry. This must be done *after* any security checks. */ for(i=0; icontext_count; i++){ if(db->contexts[i] && db->contexts[i]->id && !strcmp(db->contexts[i]->id, client_id)){ /* Client does match. */ if(db->contexts[i]->sock == -1){ /* Client is reconnecting after a disconnect */ /* FIXME - does anything else need to be done here? */ }else{ /* Client is already connected, disconnect old version */ if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Client %s already connected, closing old connection.", client_id); } } db->contexts[i]->clean_session = clean_session; mqtt3_context_cleanup(db, db->contexts[i], false); db->contexts[i]->state = mosq_cs_connected; db->contexts[i]->address = _mosquitto_strdup(context->address); db->contexts[i]->sock = context->sock; db->contexts[i]->listener = context->listener; db->contexts[i]->last_msg_in = time(NULL); db->contexts[i]->last_msg_out = time(NULL); db->contexts[i]->keepalive = context->keepalive; context->sock = -1; context->state = mosq_cs_disconnecting; context = db->contexts[i]; if(context->msgs){ /* Messages received when the client was disconnected are put * in the ms_queued state. If we don't change them to the * appropriate "publish" state, then the queued messages won't * get sent until the client next receives a message - and they * will be sent out of order. * This only sets a single message up to be published, but once * it is sent the full max_inflight amount of messages will be * queued up for sending. */ if(context->msgs->state == ms_queued && context->msgs->direction == mosq_md_out){ switch(context->msgs->qos){ case 0: context->msgs->state = ms_publish; break; case 1: context->msgs->state = ms_publish_puback; break; case 2: context->msgs->state = ms_publish_pubrec; break; } } } break; } } context->id = client_id; context->clean_session = clean_session; context->will = will_struct; if(context->will){ context->will->topic = will_topic; if(will_message){ context->will->payload = (uint8_t *)will_message; context->will->payloadlen = strlen(will_message); }else{ context->will->payload = NULL; context->will->payloadlen = 0; } context->will->qos = will_qos; context->will->retain = will_retain; } /* Associate user with its ACL, assuming we have ACLs loaded. */ if(db->acl_list){ acl_tail = db->acl_list; while(acl_tail){ if(context->username){ if(acl_tail->username && !strcmp(context->username, acl_tail->username)){ context->acl_list = acl_tail; break; } }else{ if(acl_tail->username == NULL){ context->acl_list = acl_tail; break; } } acl_tail = acl_tail->next; } }else{ context->acl_list = NULL; } if(db->config->connection_messages == true){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "New client connected from %s as %s.", context->address, client_id); } context->state = mosq_cs_connected; return _mosquitto_send_connack(context, 0); } int mqtt3_handle_disconnect(mosquitto_db *db, int context_index) { struct mosquitto *context; context = db->contexts[context_index]; if(!context){ return MOSQ_ERR_INVAL; } if(context->in_packet.remaining_length != 0){ return MOSQ_ERR_PROTOCOL; } _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received DISCONNECT from %s", context->id); context->state = mosq_cs_disconnecting; mqtt3_context_disconnect(db, context_index); return MOSQ_ERR_SUCCESS; } int mqtt3_handle_subscribe(mosquitto_db *db, struct mosquitto *context) { int rc = 0; int rc2; uint16_t mid; char *sub; uint8_t qos; uint8_t *payload = NULL, *tmp_payload; uint32_t payloadlen = 0; int len; char *sub_mount; if(!context) return MOSQ_ERR_INVAL; _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received SUBSCRIBE from %s", context->id); /* FIXME - plenty of potential for memory leaks here */ if(_mosquitto_read_uint16(&context->in_packet, &mid)) return 1; while(context->in_packet.pos < context->in_packet.remaining_length){ sub = NULL; if(_mosquitto_read_string(&context->in_packet, &sub)){ if(payload) _mosquitto_free(payload); return 1; } if(sub){ if(_mosquitto_read_byte(&context->in_packet, &qos)){ _mosquitto_free(sub); if(payload) _mosquitto_free(payload); return 1; } if(qos > 2){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Invalid QoS in subscription command from %s, disconnecting.", context->address); _mosquitto_free(sub); if(payload) _mosquitto_free(payload); return 1; } if(_mosquitto_fix_sub_topic(&sub)){ _mosquitto_free(sub); if(payload) _mosquitto_free(payload); return 1; } if(!strlen(sub)){ _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Empty subscription string from %s, disconnecting.", context->address); _mosquitto_free(sub); if(payload) _mosquitto_free(payload); return 1; } if(context->listener && context->listener->mount_point){ len = strlen(context->listener->mount_point) + strlen(sub) + 1; sub_mount = _mosquitto_calloc(len, sizeof(char)); if(!sub_mount){ _mosquitto_free(sub); if(payload) _mosquitto_free(payload); return MOSQ_ERR_NOMEM; } snprintf(sub_mount, len, "%s%s", context->listener->mount_point, sub); _mosquitto_free(sub); sub = sub_mount; } _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "\t%s (QoS %d)", sub, qos); /* FIXME - need to deny access to retained messages. */ #if 0 /* Check for topic access */ rc2 = mqtt3_acl_check(db, context, sub, MOSQ_ACL_READ); if(rc2 == MOSQ_ERR_SUCCESS){ mqtt3_sub_add(context, sub, qos, &db->subs); if(mqtt3_retain_queue(db, context, sub, qos)) rc = 1; }else if(rc2 != MOSQ_ERR_ACL_DENIED){ rc = 1; } #else rc2 = mqtt3_sub_add(context, sub, qos, &db->subs); if(rc2 == MOSQ_ERR_SUCCESS){ if(mqtt3_retain_queue(db, context, sub, qos)) rc = 1; }else if(rc2 != -1){ rc = rc2; } #endif _mosquitto_free(sub); tmp_payload = _mosquitto_realloc(payload, payloadlen + 1); if(tmp_payload){ payload = tmp_payload; payload[payloadlen] = qos; payloadlen++; }else{ if(payload) _mosquitto_free(payload); return MOSQ_ERR_NOMEM; } } } if(_mosquitto_send_suback(context, mid, payloadlen, payload)) rc = 1; _mosquitto_free(payload); return rc; } int mqtt3_handle_unsubscribe(mosquitto_db *db, struct mosquitto *context) { uint16_t mid; char *sub; if(!context) return MOSQ_ERR_INVAL; _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received UNSUBSCRIBE from %s", context->id); if(_mosquitto_read_uint16(&context->in_packet, &mid)) return 1; while(context->in_packet.pos < context->in_packet.remaining_length){ sub = NULL; if(_mosquitto_read_string(&context->in_packet, &sub)){ return 1; } if(sub){ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "\t%s", sub); mqtt3_sub_remove(context, sub, &db->subs); _mosquitto_free(sub); } } return _mosquitto_send_command_with_mid(context, UNSUBACK, mid, false); } mosquitto-0.15/src/read_handle_client.c0000664000175000017500000000744611713444064017261 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #include #include #include #include #include #include int mqtt3_handle_connack(mosquitto_db *db, struct mosquitto *context) { uint8_t byte; uint8_t rc; int i; char *notification_topic; int notification_topic_len; uint8_t notification_payload[2]; if(!context){ return MOSQ_ERR_INVAL; } #ifdef WITH_STRICT_PROTOCOL if(context->in_packet.remaining_length != 2){ return MOSQ_ERR_PROTOCOL; } #endif _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received CONNACK on connection %s.", context->id); if(_mosquitto_read_byte(&context->in_packet, &byte)) return 1; // Reserved byte, not used if(_mosquitto_read_byte(&context->in_packet, &rc)) return 1; switch(rc){ case 0: if(context->bridge){ if(context->bridge->notifications){ 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); notification_payload[0] = '1'; notification_payload[1] = '\0'; if(_mosquitto_send_real_publish(context, _mosquitto_mid_generate(context), notification_topic, 2, (uint8_t *)¬ification_payload, 1, true, 0)){ _mosquitto_free(notification_topic); return 1; } mqtt3_db_messages_easy_queue(db, context, notification_topic, 1, 2, (uint8_t *)¬ification_payload, 1); _mosquitto_free(notification_topic); } for(i=0; ibridge->topic_count; i++){ if(context->bridge->topics[i].direction == bd_in || context->bridge->topics[i].direction == bd_both){ if(_mosquitto_send_subscribe(context, NULL, false, context->bridge->topics[i].topic, 2)){ return 1; } } } } context->state = mosq_cs_connected; return MOSQ_ERR_SUCCESS; case 1: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Connection Refused: unacceptable protocol version"); return 1; case 2: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Connection Refused: identifier rejected"); return 1; case 3: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Connection Refused: broker unavailable"); return 1; } return 1; } mosquitto-0.15/src/security.c0000664000175000017500000004447711713444064015351 0ustar rogerroger/* Copyright (c) 2011,2012 Roger Light 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. */ #include #include #include #include #include int mosquitto_security_init(mosquitto_db *db) { int rc; #ifdef WITH_EXTERNAL_SECURITY_CHECKS rc = mosquitto_unpwd_init(db); if(rc){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error initialising passwords."); return rc; } rc = mosquitto_acl_init(db); if(rc){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error initialising ACLs."); return rc; } #else /* Load username/password data if required. */ if(db->config->password_file){ rc = mqtt3_pwfile_parse(db); if(rc){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error opening password file."); return rc; } } /* Load acl data if required. */ if(db->config->acl_file){ rc = mqtt3_aclfile_parse(db); if(rc){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error opening acl file."); return rc; } } #endif return MOSQ_ERR_SUCCESS; } void mosquitto_security_cleanup(mosquitto_db *db) { mosquitto_acl_cleanup(db); mosquitto_unpwd_cleanup(db); } #ifndef WITH_EXTERNAL_SECURITY_CHECKS int _add_acl(struct _mosquitto_db *db, const char *user, const char *topic, int access) { struct _mosquitto_acl_user *acl_user=NULL, *user_tail; struct _mosquitto_acl *acl, *acl_root=NULL, *acl_tail=NULL; char *local_topic; char *token = NULL; bool new_user = false; if(!db || !topic) return MOSQ_ERR_INVAL; local_topic = _mosquitto_strdup(topic); if(!local_topic){ return MOSQ_ERR_NOMEM; } if(db->acl_list){ user_tail = db->acl_list; while(user_tail){ if(user == NULL){ if(user_tail->username == NULL){ acl_user = user_tail; break; } }else if(user_tail->username && !strcmp(user_tail->username, user)){ acl_user = user_tail; break; } user_tail = user_tail->next; } } if(!acl_user){ acl_user = _mosquitto_malloc(sizeof(struct _mosquitto_acl_user)); if(!acl_user){ _mosquitto_free(local_topic); return MOSQ_ERR_NOMEM; } new_user = true; if(user){ acl_user->username = _mosquitto_strdup(user); if(!acl_user->username){ _mosquitto_free(local_topic); _mosquitto_free(acl_user); return MOSQ_ERR_NOMEM; } }else{ acl_user->username = NULL; } acl_user->next = NULL; acl_user->acl = NULL; } /* Tokenise topic */ if(local_topic[0] == '/'){ acl_root = _mosquitto_malloc(sizeof(struct _mosquitto_acl)); if(!acl_root) return MOSQ_ERR_NOMEM; acl_tail = acl_root; acl_root->child = NULL; acl_root->next = NULL; acl_root->access = MOSQ_ACL_NONE; acl_root->topic = _mosquitto_strdup("/"); if(!acl_root->topic) return MOSQ_ERR_NOMEM; token = strtok(local_topic+1, "/"); }else{ token = strtok(local_topic, "/"); } while(token){ acl = _mosquitto_malloc(sizeof(struct _mosquitto_acl)); if(!acl) return MOSQ_ERR_NOMEM; acl->child = NULL; acl->next = NULL; acl->access = MOSQ_ACL_NONE; acl->topic = _mosquitto_strdup(token); if(!acl->topic) return MOSQ_ERR_NOMEM; if(acl_root){ acl_tail->child = acl; acl_tail = acl; }else{ acl_root = acl; acl_tail = acl; } token = strtok(NULL, "/"); } if(acl_root){ acl_tail = acl_root; while(acl_tail->child){ acl_tail = acl_tail->child; } acl_tail->access = access; }else{ return MOSQ_ERR_INVAL; } /* Add acl to user acl list */ if(acl_user->acl){ acl_tail = acl_user->acl; while(acl_tail->next){ acl_tail = acl_tail->next; } acl_tail->next = acl_root; }else{ acl_user->acl = acl_root; } if(new_user){ /* Add to end of list */ if(db->acl_list){ user_tail = db->acl_list; while(user_tail->next){ user_tail = user_tail->next; } user_tail->next = acl_user; }else{ db->acl_list = acl_user; } } _mosquitto_free(local_topic); return MOSQ_ERR_SUCCESS; } int _add_acl_pattern(struct _mosquitto_db *db, const char *topic, int access) { struct _mosquitto_acl *acl, *acl_root=NULL, *acl_tail=NULL; char *local_topic; char *token = NULL; if(!db || !topic) return MOSQ_ERR_INVAL; local_topic = _mosquitto_strdup(topic); if(!local_topic){ return MOSQ_ERR_NOMEM; } /* Tokenise topic */ if(local_topic[0] == '/'){ acl_root = _mosquitto_malloc(sizeof(struct _mosquitto_acl)); if(!acl_root) return MOSQ_ERR_NOMEM; acl_tail = acl_root; acl_root->child = NULL; acl_root->next = NULL; acl_root->access = MOSQ_ACL_NONE; acl_root->topic = _mosquitto_strdup("/"); if(!acl_root->topic) return MOSQ_ERR_NOMEM; token = strtok(local_topic+1, "/"); }else{ token = strtok(local_topic, "/"); } while(token){ acl = _mosquitto_malloc(sizeof(struct _mosquitto_acl)); if(!acl) return MOSQ_ERR_NOMEM; acl->child = NULL; acl->next = NULL; acl->access = MOSQ_ACL_NONE; acl->topic = _mosquitto_strdup(token); if(!acl->topic) return MOSQ_ERR_NOMEM; if(acl_root){ acl_tail->child = acl; acl_tail = acl; }else{ acl_root = acl; acl_tail = acl; } token = strtok(NULL, "/"); } if(acl_root){ acl_tail = acl_root; while(acl_tail->child){ acl_tail = acl_tail->child; } acl_tail->access = access; if(db->acl_patterns){ acl_tail = db->acl_patterns; while(acl_tail->next){ acl_tail = acl_tail->next; } acl_tail->next = acl_root; }else{ db->acl_patterns = acl_root; } }else{ return MOSQ_ERR_INVAL; } _mosquitto_free(local_topic); return MOSQ_ERR_SUCCESS; } int mosquitto_acl_check(struct _mosquitto_db *db, struct mosquitto *context, const char *topic, int access) { char *local_topic; char *token; struct _mosquitto_acl *acl_root, *acl_tail; if(!db || !context || !topic) return MOSQ_ERR_INVAL; if(!db->acl_list) return MOSQ_ERR_SUCCESS; if(!context->acl_list && !db->acl_patterns) return MOSQ_ERR_ACL_DENIED; if(context->acl_list){ acl_root = context->acl_list->acl; }else{ acl_root = NULL; } /* Loop through all ACLs for this client. */ while(acl_root){ local_topic = _mosquitto_strdup(topic); if(!local_topic) return MOSQ_ERR_NOMEM; acl_tail = acl_root; if(local_topic[0] == '/'){ if(strcmp(acl_tail->topic, "/")){ acl_root = acl_root->next; continue; } acl_tail = acl_tail->child; } token = strtok(local_topic, "/"); /* Loop through the topic looking for matches to this ACL. */ while(token){ if(acl_tail){ if(!strcmp(acl_tail->topic, "#") && acl_tail->child == NULL){ /* We have a match */ if(access & acl_tail->access){ /* And access is allowed. */ _mosquitto_free(local_topic); return MOSQ_ERR_SUCCESS; }else{ break; } }else if(!strcmp(acl_tail->topic, token) || !strcmp(acl_tail->topic, "+")){ token = strtok(NULL, "/"); if(!token && acl_tail->child == NULL){ /* We have a match */ if(access & acl_tail->access){ /* And access is allowed. */ _mosquitto_free(local_topic); return MOSQ_ERR_SUCCESS; }else{ break; } } }else{ break; } acl_tail = acl_tail->child; }else{ break; } } _mosquitto_free(local_topic); acl_root = acl_root->next; } acl_root = db->acl_patterns; /* Loop through all pattern ACLs. */ while(acl_root){ local_topic = _mosquitto_strdup(topic); if(!local_topic) return MOSQ_ERR_NOMEM; acl_tail = acl_root; if(local_topic[0] == '/'){ if(strcmp(acl_tail->topic, "/")){ acl_root = acl_root->next; continue; } acl_tail = acl_tail->child; } token = strtok(local_topic, "/"); /* Loop through the topic looking for matches to this ACL. */ while(token){ if(acl_tail){ if(!strcmp(acl_tail->topic, "#") && acl_tail->child == NULL){ /* We have a match */ if(access & acl_tail->access){ /* And access is allowed. */ _mosquitto_free(local_topic); return MOSQ_ERR_SUCCESS; }else{ break; } }else if(!strcmp(acl_tail->topic, "%c")){ if(!context->id || strcmp(token, context->id)){ /* No access */ break; } token = strtok(NULL, "/"); if(!token && acl_tail->child == NULL){ /* We have a match */ if(access & acl_tail->access){ /* And access is allowed. */ _mosquitto_free(local_topic); return MOSQ_ERR_SUCCESS; }else{ break; } } }else if(!strcmp(acl_tail->topic, "%u")){ if(!context->username || strcmp(token, context->username)){ /* No access */ break; } token = strtok(NULL, "/"); if(!token && acl_tail->child == NULL){ /* We have a match */ if(access & acl_tail->access){ /* And access is allowed. */ _mosquitto_free(local_topic); return MOSQ_ERR_SUCCESS; }else{ break; } } }else if(!strcmp(acl_tail->topic, token) || !strcmp(acl_tail->topic, "+")){ token = strtok(NULL, "/"); if(!token && acl_tail->child == NULL){ /* We have a match */ if(access & acl_tail->access){ /* And access is allowed. */ _mosquitto_free(local_topic); return MOSQ_ERR_SUCCESS; }else{ break; } } }else{ break; } acl_tail = acl_tail->child; }else{ break; } } _mosquitto_free(local_topic); acl_root = acl_root->next; } return MOSQ_ERR_ACL_DENIED; } int mqtt3_aclfile_parse(struct _mosquitto_db *db) { FILE *aclfile; char buf[1024]; char *token; char *user = NULL; char *topic; char *access_s; int access; int rc; int slen; int topic_pattern; if(!db || !db->config) return MOSQ_ERR_INVAL; if(!db->config->acl_file) return MOSQ_ERR_SUCCESS; aclfile = fopen(db->config->acl_file, "rt"); if(!aclfile) return 1; // topic [read|write] // user while(fgets(buf, 1024, aclfile)){ slen = strlen(buf); while(slen > 0 && (buf[slen-1] == 10 || buf[slen-1] == 13)){ buf[slen-1] = '\0'; slen = strlen(buf); } token = strtok(buf, " "); if(token){ if(!strcmp(token, "topic") || !strcmp(token, "pattern")){ if(!strcmp(token, "topic")){ topic_pattern = 0; }else{ topic_pattern = 1; } access_s = strtok(NULL, " "); if(!access_s){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty topic in acl_file."); if(user) _mosquitto_free(user); fclose(aclfile); return MOSQ_ERR_INVAL; } token = strtok(NULL, " "); if(token){ topic = token; }else{ topic = access_s; access_s = NULL; } if(access_s){ if(!strcmp(access_s, "read")){ access = MOSQ_ACL_READ; }else if(!strcmp(access_s, "write")){ access = MOSQ_ACL_WRITE; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty invalid topic access type in acl_file."); if(user) _mosquitto_free(user); fclose(aclfile); return MOSQ_ERR_INVAL; } }else{ access = MOSQ_ACL_READ | MOSQ_ACL_WRITE; } if(topic_pattern == 0){ rc = _add_acl(db, user, topic, access); }else{ rc = _add_acl_pattern(db, topic, access); } if(rc) return rc; }else if(!strcmp(token, "user")){ token = strtok(NULL, " "); if(token){ if(user) _mosquitto_free(user); user = _mosquitto_strdup(token); if(!user){ fclose(aclfile); return MOSQ_ERR_NOMEM; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Missing username in acl_file."); if(user) _mosquitto_free(user); fclose(aclfile); return 1; } } } } if(user) _mosquitto_free(user); fclose(aclfile); return MOSQ_ERR_SUCCESS; } static void _free_acl(struct _mosquitto_acl *acl) { if(!acl) return; if(acl->child){ _free_acl(acl->child); } if(acl->next){ _free_acl(acl->next); } if(acl->topic){ _mosquitto_free(acl->topic); } _mosquitto_free(acl); } void mosquitto_acl_cleanup(struct _mosquitto_db *db) { int i; struct _mosquitto_acl_user *user_tail; if(!db || !db->acl_list) return; /* As we're freeing ACLs, we must clear context->acl_list to ensure no * invalid memory accesses take place later. * This *requires* the ACLs to be reapplied after mosquitto_acl_cleanup() * is called if we are reloading the config. If this is not done, all * access will be denied to currently connected clients. */ if(db->contexts){ for(i=0; icontext_count; i++){ if(db->contexts[i] && db->contexts[i]->acl_list){ db->contexts[i]->acl_list = NULL; } } } while(db->acl_list){ user_tail = db->acl_list->next; _free_acl(db->acl_list->acl); if(db->acl_list->username){ _mosquitto_free(db->acl_list->username); } _mosquitto_free(db->acl_list); db->acl_list = user_tail; } if(db->acl_patterns){ _free_acl(db->acl_patterns); } } int mqtt3_pwfile_parse(struct _mosquitto_db *db) { FILE *pwfile; struct _mosquitto_unpwd *unpwd; char buf[256]; char *username, *password; int len; if(!db || !db->config) return MOSQ_ERR_INVAL; if(!db->config->password_file) return MOSQ_ERR_SUCCESS; pwfile = fopen(db->config->password_file, "rt"); if(!pwfile) return 1; while(!feof(pwfile)){ if(fgets(buf, 256, pwfile)){ username = strtok(buf, ":"); if(username){ unpwd = _mosquitto_calloc(1, sizeof(struct _mosquitto_unpwd)); if(!unpwd) return MOSQ_ERR_NOMEM; unpwd->username = _mosquitto_strdup(username); if(!unpwd->username) return MOSQ_ERR_NOMEM; len = strlen(unpwd->username); while(unpwd->username[len-1] == 10 || unpwd->username[len-1] == 13){ unpwd->username[len-1] = '\0'; len = strlen(unpwd->username); } password = strtok(NULL, ":"); if(password){ unpwd->password = _mosquitto_strdup(password); if(!unpwd->password) return MOSQ_ERR_NOMEM; len = strlen(unpwd->password); while(unpwd->password[len-1] == 10 || unpwd->password[len-1] == 13){ unpwd->password[len-1] = '\0'; len = strlen(unpwd->password); } } unpwd->next = db->unpwd; db->unpwd = unpwd; } } } fclose(pwfile); return MOSQ_ERR_SUCCESS; } int mosquitto_unpwd_check(struct _mosquitto_db *db, const char *username, const char *password) { struct _mosquitto_unpwd *tail; if(!db || !username) return MOSQ_ERR_INVAL; if(!db->unpwd) return MOSQ_ERR_SUCCESS; tail = db->unpwd; while(tail){ if(!strcmp(tail->username, username)){ if(tail->password){ if(password){ if(!strcmp(tail->password, password)){ return MOSQ_ERR_SUCCESS; } }else{ return MOSQ_ERR_AUTH; } }else{ return MOSQ_ERR_SUCCESS; } } tail = tail->next; } return MOSQ_ERR_AUTH; } int mosquitto_unpwd_cleanup(struct _mosquitto_db *db) { struct _mosquitto_unpwd *tail; if(!db) return MOSQ_ERR_INVAL; while(db->unpwd){ tail = db->unpwd->next; if(db->unpwd->password) _mosquitto_free(db->unpwd->password); if(db->unpwd->username) _mosquitto_free(db->unpwd->username); _mosquitto_free(db->unpwd); db->unpwd = tail; } return MOSQ_ERR_SUCCESS; } /* Apply security settings after a reload. * Includes: * - Disconnecting anonymous users if appropriate * - Disconnecting users with invalid passwords * - Reapplying ACLs */ int mosquitto_security_apply(struct _mosquitto_db *db) { struct _mosquitto_acl_user *acl_user_tail; struct _mosquitto_unpwd *unpwd_tail; bool allow_anonymous; int i; bool unpwd_ok; if(!db) return MOSQ_ERR_INVAL; allow_anonymous = db->config->allow_anonymous; if(db->contexts){ for(i=0; icontext_count; i++){ if(db->contexts[i]){ /* Check for anonymous clients when allow_anonymous is false */ if(!allow_anonymous && !db->contexts[i]->username){ db->contexts[i]->state = mosq_cs_disconnecting; _mosquitto_socket_close(db->contexts[i]); continue; } /* Check for connected clients that are no longer authorised */ if(db->unpwd && db->contexts[i]->username){ unpwd_ok = false; unpwd_tail = db->unpwd; while(unpwd_tail){ if(!strcmp(db->contexts[i]->username, unpwd_tail->username)){ if(unpwd_tail->password){ if(!db->contexts[i]->password || strcmp(db->contexts[i]->password, unpwd_tail->password)){ /* Non matching password to username. */ db->contexts[i]->state = mosq_cs_disconnecting; _mosquitto_socket_close(db->contexts[i]); continue; }else{ /* Username matches, password matches. */ unpwd_ok = true; } }else{ /* Username matches, password not in password file. */ unpwd_ok = true; } } unpwd_tail = unpwd_tail->next; } if(!unpwd_ok){ db->contexts[i]->state = mosq_cs_disconnecting; _mosquitto_socket_close(db->contexts[i]); continue; } } /* Check for ACLs and apply to user. */ if(db->acl_list){ acl_user_tail = db->acl_list; while(acl_user_tail){ if(acl_user_tail->username){ if(db->contexts[i]->username){ if(!strcmp(acl_user_tail->username, db->contexts[i]->username)){ db->contexts[i]->acl_list = acl_user_tail; break; } } }else{ if(!db->contexts[i]->username){ db->contexts[i]->acl_list = acl_user_tail; break; } } acl_user_tail = acl_user_tail->next; } } } } } return MOSQ_ERR_SUCCESS; } #endif mosquitto-0.15/src/mqtt3.h0000664000175000017500000003144711713444064014550 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #ifndef MQTT3_H #define MQTT3_H #include #include #include #include #ifndef __GNUC__ #define __attribute__(attrib) #endif /* Database macros */ #define MOSQ_DB_VERSION 2 /* Log destinations */ #define MQTT3_LOG_NONE 0x00 #define MQTT3_LOG_SYSLOG 0x01 #define MQTT3_LOG_FILE 0x02 #define MQTT3_LOG_STDOUT 0x04 #define MQTT3_LOG_STDERR 0x08 #define MQTT3_LOG_TOPIC 0x10 #define MQTT3_LOG_ALL 0xFF #define MOSQ_ACL_NONE 0x00 #define MOSQ_ACL_READ 0x01 #define MOSQ_ACL_WRITE 0x02 typedef uint64_t dbid_t; enum mqtt3_msg_state { ms_invalid = 0, ms_publish = 1, ms_publish_puback = 2, ms_wait_puback = 3, ms_publish_pubrec = 4, ms_wait_pubrec = 5, ms_resend_pubrel = 6, ms_wait_pubrel = 7, ms_resend_pubcomp = 8, ms_wait_pubcomp = 9, ms_resend_pubrec = 10, ms_queued = 11 }; struct _mqtt3_listener { int fd; char *host; uint16_t port; int max_connections; char *mount_point; int *socks; int sock_count; int client_count; }; typedef struct { char *config_file; char *acl_file; bool allow_anonymous; int autosave_interval; char *clientid_prefixes; bool connection_messages; bool daemon; struct _mqtt3_listener default_listener; struct _mqtt3_listener *listeners; int listener_count; int log_dest; int log_type; bool log_timestamp; char *password_file; bool persistence; char *persistence_location; char *persistence_file; char *persistence_filepath; int retry_interval; int store_clean_interval; int sys_interval; char *pid_file; char *user; #ifdef WITH_BRIDGE struct _mqtt3_bridge *bridges; int bridge_count; #endif #ifdef WITH_EXTERNAL_SECURITY_CHECKS char *db_host; int db_port; char *db_name; char *db_username; char *db_password; #endif } mqtt3_config; struct _mosquitto_subleaf { struct _mosquitto_subleaf *prev; struct _mosquitto_subleaf *next; struct mosquitto *context; int qos; }; struct _mosquitto_subhier { struct _mosquitto_subhier *children; struct _mosquitto_subhier *next; struct _mosquitto_subleaf *subs; char *topic; struct mosquitto_msg_store *retained; }; struct mosquitto_msg_store{ struct mosquitto_msg_store *next; dbid_t db_id; int ref_count; char *source_id; uint16_t source_mid; struct mosquitto_message msg; }; typedef struct _mosquitto_client_msg{ struct _mosquitto_client_msg *next; struct mosquitto_msg_store *store; uint16_t mid; int qos; bool retain; time_t timestamp; enum mosquitto_msg_direction direction; enum mqtt3_msg_state state; bool dup; } mosquitto_client_msg; struct _mosquitto_unpwd{ struct _mosquitto_unpwd *next; char *username; char *password; }; struct _mosquitto_acl{ struct _mosquitto_acl *child; struct _mosquitto_acl *next; char *topic; int access; }; struct _mosquitto_acl_user{ struct _mosquitto_acl_user *next; char *username; struct _mosquitto_acl *acl; }; typedef struct _mosquitto_db{ dbid_t last_db_id; struct _mosquitto_subhier subs; struct _mosquitto_unpwd *unpwd; struct _mosquitto_acl_user *acl_list; struct _mosquitto_acl *acl_patterns; struct mosquitto **contexts; int context_count; struct mosquitto_msg_store *msg_store; int msg_store_count; mqtt3_config *config; } mosquitto_db; enum mqtt3_bridge_direction{ bd_out = 0, bd_in = 1, bd_both = 2 }; enum mosquitto_bridge_start_type{ bst_automatic = 0, bst_lazy = 1, bst_manual = 2, bst_once = 3 }; struct _mqtt3_bridge_topic{ char *topic; int qos; enum mqtt3_bridge_direction direction; }; struct _mqtt3_bridge{ char *name; char *address; char *clientid; uint16_t port; int keepalive; bool clean_session; struct _mqtt3_bridge_topic *topics; int topic_count; time_t restart_t; char *username; char *password; bool notifications; enum mosquitto_bridge_start_type start_type; int idle_timeout; int threshold; }; #include /* ============================================================ * Main functions * ============================================================ */ int mosquitto_main_loop(mosquitto_db *db, int *listensock, int listensock_count, int listener_max); /* ============================================================ * Config functions * ============================================================ */ /* Initialise config struct to default values. */ void mqtt3_config_init(mqtt3_config *config); /* Parse command line options into config. */ int mqtt3_config_parse_args(mqtt3_config *config, int argc, char *argv[]); /* Read configuration data from config->config_file into config. * If reload is true, don't process config options that shouldn't be reloaded (listeners etc) * Returns 0 on success, 1 if there is a configuration error or if a file cannot be opened. */ int mqtt3_config_read(mqtt3_config *config, bool reload); /* Free all config data. */ void mqtt3_config_cleanup(mqtt3_config *config); /* ============================================================ * Server send functions * ============================================================ */ int _mosquitto_send_connack(struct mosquitto *context, uint8_t result); int _mosquitto_send_suback(struct mosquitto *context, uint16_t mid, uint32_t payloadlen, const uint8_t *payload); /* ============================================================ * Network functions * ============================================================ */ int mqtt3_socket_accept(struct _mosquitto_db *db, int listensock); int mqtt3_socket_listen(struct _mqtt3_listener *listener); uint64_t mqtt3_net_bytes_total_received(void); uint64_t mqtt3_net_bytes_total_sent(void); unsigned long mqtt3_net_msgs_total_received(void); unsigned long mqtt3_net_msgs_total_sent(void); /* ============================================================ * Read handling functions * ============================================================ */ int mqtt3_packet_handle(mosquitto_db *db, int context_index); int mqtt3_handle_connack(mosquitto_db *db, struct mosquitto *context); int mqtt3_handle_connect(mosquitto_db *db, int context_index); int mqtt3_handle_disconnect(mosquitto_db *db, int context_index); int mqtt3_handle_publish(mosquitto_db *db, struct mosquitto *context); int mqtt3_handle_subscribe(mosquitto_db *db, struct mosquitto *context); int mqtt3_handle_unsubscribe(mosquitto_db *db, struct mosquitto *context); /* ============================================================ * Database handling * ============================================================ */ int mqtt3_db_open(mqtt3_config *config, mosquitto_db *db); int mqtt3_db_close(mosquitto_db *db); #ifdef WITH_PERSISTENCE int mqtt3_db_backup(mosquitto_db *db, bool cleanup, bool shutdown); int mqtt3_db_restore(mosquitto_db *db); #endif int mqtt3_db_client_count(mosquitto_db *db, int *count, int *inactive_count); void mqtt3_db_limits_set(int inflight, int queued); /* Return the number of in-flight messages in count. */ int mqtt3_db_message_count(int *count); int mqtt3_db_message_delete(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir); int mqtt3_db_message_insert(mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, int qos, bool retain, struct mosquitto_msg_store *stored); int mqtt3_db_message_release(mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir); int mqtt3_db_message_update(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, enum mqtt3_msg_state state); int mqtt3_db_message_write(struct mosquitto *context); int mqtt3_db_messages_delete(struct mosquitto *context); int mqtt3_db_messages_easy_queue(mosquitto_db *db, struct mosquitto *context, const char *topic, int qos, uint32_t payloadlen, const uint8_t *payload, int retain); int mqtt3_db_messages_queue(mosquitto_db *db, const char *source_id, const char *topic, int qos, int retain, struct mosquitto_msg_store *stored); int mqtt3_db_message_store(mosquitto_db *db, const char *source, uint16_t source_mid, const char *topic, int qos, uint32_t payloadlen, const uint8_t *payload, int retain, struct mosquitto_msg_store **stored, dbid_t store_id); int mqtt3_db_message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto_msg_store **stored); /* Check all messages waiting on a client reply and resend if timeout has been exceeded. */ int mqtt3_db_message_timeout_check(mosquitto_db *db, unsigned int timeout); int mqtt3_retain_queue(mosquitto_db *db, struct mosquitto *context, const char *sub, int sub_qos); void mqtt3_db_store_clean(mosquitto_db *db); void mqtt3_db_sys_update(mosquitto_db *db, int interval, time_t start_time); void mqtt3_db_vacuum(void); /* ============================================================ * Subscription functions * ============================================================ */ int mqtt3_sub_add(struct mosquitto *context, const char *sub, int qos, struct _mosquitto_subhier *root); int mqtt3_sub_remove(struct mosquitto *context, const char *sub, struct _mosquitto_subhier *root); int mqtt3_sub_search(struct _mosquitto_db *db, struct _mosquitto_subhier *root, const char *source_id, const char *topic, int qos, int retain, struct mosquitto_msg_store *stored); void mqtt3_sub_tree_print(struct _mosquitto_subhier *root, int level); int mqtt3_subs_clean_session(struct mosquitto *context, struct _mosquitto_subhier *root); /* ============================================================ * Context functions * ============================================================ */ struct mosquitto *mqtt3_context_init(int sock); void mqtt3_context_cleanup(mosquitto_db *db, struct mosquitto *context, bool do_free); void mqtt3_context_disconnect(mosquitto_db *db, int context_index); /* ============================================================ * Logging functions * ============================================================ */ int mqtt3_log_init(int level, int destinations); int mqtt3_log_close(void); int _mosquitto_log_printf(struct mosquitto *mosq, int level, const char *fmt, ...) __attribute__((format(printf, 3, 4))); /* ============================================================ * Bridge functions * ============================================================ */ #ifdef WITH_BRIDGE int mqtt3_bridge_new(mosquitto_db *db, struct _mqtt3_bridge *bridge); int mqtt3_bridge_connect(mosquitto_db *db, struct mosquitto *context); void mqtt3_bridge_packet_cleanup(struct mosquitto *context); #endif /* ============================================================ * Security related functions * ============================================================ */ int mosquitto_security_init(mosquitto_db *db); void mosquitto_security_cleanup(mosquitto_db *db); #ifdef WITH_EXTERNAL_SECURITY_CHECKS int mosquitto_unpwd_init(struct _mosquitto_db *db); int mosquitto_acl_init(struct _mosquitto_db *db); #else int mqtt3_aclfile_parse(struct _mosquitto_db *db); int mqtt3_pwfile_parse(struct _mosquitto_db *db); int mosquitto_security_apply(struct _mosquitto_db *db); #endif int mosquitto_acl_check(struct _mosquitto_db *db, struct mosquitto *context, const char *topic, int access); void mosquitto_acl_cleanup(struct _mosquitto_db *db); int mosquitto_unpwd_check(struct _mosquitto_db *db, const char *username, const char *password); int mosquitto_unpwd_cleanup(struct _mosquitto_db *db); /* ============================================================ * Window service related functions * ============================================================ */ #ifdef WIN32 void service_install(void); void service_uninstall(void); void service_run(void); #endif #endif mosquitto-0.15/src/logging.c0000664000175000017500000001244211713444064015113 0ustar rogerroger/* Copyright (c) 2009-2011 Roger Light 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. */ #include #include #include #ifndef WIN32 #include #endif #ifndef CMAKE #include #endif #include #include extern mosquitto_db int_db; #ifdef WIN32 HANDLE syslog_h; #endif /* Options for logging should be: * * A combination of: * Via syslog * To a file * To stdout/stderr * To topics */ /* Give option of logging timestamp. * Logging pid. */ static int log_destinations = MQTT3_LOG_STDERR; static int log_priorities = MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE | MOSQ_LOG_INFO; int mqtt3_log_init(int priorities, int destinations) { int rc = 0; log_priorities = priorities; log_destinations = destinations; if(log_destinations & MQTT3_LOG_SYSLOG){ #ifndef WIN32 openlog("mosquitto", LOG_PID, LOG_DAEMON); #else syslog_h = OpenEventLog(NULL, "mosquitto"); #endif } return rc; } int mqtt3_log_close(void) { if(log_destinations & MQTT3_LOG_SYSLOG){ #ifndef WIN32 closelog(); #else CloseEventLog(syslog_h); #endif } /* FIXME - do something for all destinations! */ return MOSQ_ERR_SUCCESS; } int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...) { va_list va; char *s; char *st; int len; #ifdef WIN32 char *sp; #endif const char *topic; int syslog_priority; time_t now = time(NULL); if((log_priorities & priority) && log_destinations != MQTT3_LOG_NONE){ switch(priority){ case MOSQ_LOG_DEBUG: topic = "$SYS/broker/log/D"; #ifndef WIN32 syslog_priority = LOG_DEBUG; #else syslog_priority = EVENTLOG_INFORMATION_TYPE; #endif break; case MOSQ_LOG_ERR: topic = "$SYS/broker/log/E"; #ifndef WIN32 syslog_priority = LOG_ERR; #else syslog_priority = EVENTLOG_ERROR_TYPE; #endif break; case MOSQ_LOG_WARNING: topic = "$SYS/broker/log/W"; #ifndef WIN32 syslog_priority = LOG_WARNING; #else syslog_priority = EVENTLOG_WARNING_TYPE; #endif break; case MOSQ_LOG_NOTICE: topic = "$SYS/broker/log/N"; #ifndef WIN32 syslog_priority = LOG_NOTICE; #else syslog_priority = EVENTLOG_INFORMATION_TYPE; #endif break; case MOSQ_LOG_INFO: topic = "$SYS/broker/log/I"; #ifndef WIN32 syslog_priority = LOG_INFO; #else syslog_priority = EVENTLOG_INFORMATION_TYPE; #endif break; default: topic = "$SYS/broker/log/E"; #ifndef WIN32 syslog_priority = LOG_ERR; #else syslog_priority = EVENTLOG_ERROR_TYPE; #endif } len = strlen(fmt) + 500; s = _mosquitto_malloc(len*sizeof(char)); if(!s) 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. */ if(log_destinations & MQTT3_LOG_STDOUT){ if(int_db.config && int_db.config->log_timestamp){ fprintf(stdout, "%d: %s\n", (int)now, s); }else{ fprintf(stdout, "%s\n", s); } fflush(stdout); } if(log_destinations & MQTT3_LOG_STDERR){ if(int_db.config && int_db.config->log_timestamp){ fprintf(stderr, "%d: %s\n", (int)now, s); }else{ fprintf(stderr, "%s\n", s); } fflush(stderr); } if(log_destinations & MQTT3_LOG_SYSLOG){ #ifndef WIN32 syslog(syslog_priority, "%s", s); #else sp = (char *)s; ReportEvent(syslog_h, syslog_priority, 0, 0, NULL, 1, 0, &sp, NULL); #endif } if(log_destinations & MQTT3_LOG_TOPIC && priority != MOSQ_LOG_DEBUG){ if(int_db.config && int_db.config->log_timestamp){ len += 30; st = _mosquitto_malloc(len*sizeof(char)); if(!st){ _mosquitto_free(s); return MOSQ_ERR_NOMEM; } snprintf(st, len, "%d: %s", (int)now, s); mqtt3_db_messages_easy_queue(&int_db, NULL, topic, 2, strlen(st), (uint8_t *)st, 0); _mosquitto_free(st); }else{ mqtt3_db_messages_easy_queue(&int_db, NULL, topic, 2, strlen(s), (uint8_t *)s, 0); } } _mosquitto_free(s); } return MOSQ_ERR_SUCCESS; } mosquitto-0.15/src/read_handle.c0000664000175000017500000001361711713444064015720 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #include #include #include #include #include #include #include #include int mqtt3_packet_handle(mosquitto_db *db, int context_index) { struct mosquitto *context; if(context_index < 0 || context_index >= db->context_count) return MOSQ_ERR_INVAL; context = db->contexts[context_index]; if(!context) return MOSQ_ERR_INVAL; switch((context->in_packet.command)&0xF0){ case PINGREQ: return _mosquitto_handle_pingreq(context); case PINGRESP: return _mosquitto_handle_pingresp(context); case PUBACK: return _mosquitto_handle_pubackcomp(context, "PUBACK"); case PUBCOMP: return _mosquitto_handle_pubackcomp(context, "PUBCOMP"); case PUBLISH: return mqtt3_handle_publish(db, context); case PUBREC: return _mosquitto_handle_pubrec(context); case PUBREL: return _mosquitto_handle_pubrel(db, context); case CONNECT: return mqtt3_handle_connect(db, context_index); case DISCONNECT: return mqtt3_handle_disconnect(db, context_index); case SUBSCRIBE: return mqtt3_handle_subscribe(db, context); case UNSUBSCRIBE: return mqtt3_handle_unsubscribe(db, context); #ifdef WITH_BRIDGE case CONNACK: return mqtt3_handle_connack(db, context); case SUBACK: return _mosquitto_handle_suback(context); case UNSUBACK: return _mosquitto_handle_unsuback(context); #endif default: /* If we don't recognise the command, return an error straight away. */ return MOSQ_ERR_PROTOCOL; } } int mqtt3_handle_publish(mosquitto_db *db, struct mosquitto *context) { char *topic; uint8_t *payload = NULL; uint32_t payloadlen; uint8_t dup, qos, retain; uint16_t mid = 0; int rc = 0; uint8_t header = context->in_packet.command; int res = 0; struct mosquitto_msg_store *stored = NULL; int len; char *topic_mount; dup = (header & 0x08)>>3; qos = (header & 0x06)>>1; retain = (header & 0x01); if(_mosquitto_read_string(&context->in_packet, &topic)) return 1; if(_mosquitto_fix_sub_topic(&topic)) return 1; if(!strlen(topic)){ return 1; } if(_mosquitto_topic_wildcard_len_check(topic) != MOSQ_ERR_SUCCESS){ /* Invalid publish topic, just swallow it. */ _mosquitto_free(topic); return MOSQ_ERR_SUCCESS; } if(qos > 0){ if(_mosquitto_read_uint16(&context->in_packet, &mid)){ _mosquitto_free(topic); return 1; } } payloadlen = context->in_packet.remaining_length - context->in_packet.pos; if(context->listener && context->listener->mount_point){ len = strlen(context->listener->mount_point) + strlen(topic) + 1; topic_mount = _mosquitto_calloc(len, sizeof(char)); if(!topic_mount){ _mosquitto_free(topic); return MOSQ_ERR_NOMEM; } snprintf(topic_mount, len, "%s%s", context->listener->mount_point, topic); _mosquitto_free(topic); topic = topic_mount; } _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PUBLISH from %s (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", context->id, dup, qos, retain, mid, topic, (long)payloadlen); if(payloadlen){ payload = _mosquitto_calloc(payloadlen+1, sizeof(uint8_t)); if(_mosquitto_read_bytes(&context->in_packet, payload, payloadlen)){ _mosquitto_free(topic); return 1; } } /* Check for topic access */ rc = mosquitto_acl_check(db, context, topic, MOSQ_ACL_WRITE); if(rc == MOSQ_ERR_ACL_DENIED){ _mosquitto_free(topic); if(payload) _mosquitto_free(payload); return MOSQ_ERR_SUCCESS; }else if(rc != MOSQ_ERR_SUCCESS){ _mosquitto_free(topic); if(payload) _mosquitto_free(payload); return rc; } if(qos > 0){ mqtt3_db_message_store_find(context, mid, &stored); } if(!stored){ dup = 0; if(mqtt3_db_message_store(db, context->id, mid, topic, qos, payloadlen, payload, retain, &stored, 0)){ _mosquitto_free(topic); if(payload) _mosquitto_free(payload); return 1; } }else{ dup = 1; } switch(qos){ case 0: if(mqtt3_db_messages_queue(db, context->id, topic, qos, retain, stored)) rc = 1; break; case 1: if(mqtt3_db_messages_queue(db, context->id, topic, qos, retain, stored)) rc = 1; if(_mosquitto_send_puback(context, mid)) rc = 1; break; case 2: if(!dup){ res = mqtt3_db_message_insert(db, context, mid, mosq_md_in, qos, retain, stored); }else{ res = 0; } if(!res){ if(_mosquitto_send_pubrec(context, mid)) rc = 1; }else if(res == 1){ rc = 1; } break; } _mosquitto_free(topic); if(payload) _mosquitto_free(payload); return rc; } mosquitto-0.15/src/database.c0000664000175000017500000005710311713444064015234 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ /* A note on matching topic subscriptions. * * Topics can be up to 32767 characters in length. The / character is used as a * hierarchy delimiter. Messages are published to a particular topic. * Clients may subscribe to particular topics directly, but may also use * wildcards in subscriptions. The + and # characters are used as wildcards. * The # wildcard can be used at the end of a subscription only, and is a * wildcard for the level of hierarchy at which it is placed and all subsequent * levels. * The + wildcard may be used at any point within the subscription and is a * wildcard for only the level of hierarchy at which it is placed. * Neither wildcard may be used as part of a substring. * Valid: * a/b/+ * a/+/c * a/# * a/b/# * # * +/b/c * +/+/+ * Invalid: * a/#/c * a+/b/c * Valid but non-matching: * a/b * a/+ * +/b * b/c/a * a/b/d */ #include #include #include #include #include #include #include #include #include #include #include #include static int max_inflight = 20; static int max_queued = 100; static int _mqtt3_db_cleanup(mosquitto_db *db); int mqtt3_db_open(mqtt3_config *config, mosquitto_db *db) { int rc = 0; struct _mosquitto_subhier *child; if(!config || !db) return MOSQ_ERR_INVAL; db->last_db_id = 0; db->context_count = 1; db->contexts = _mosquitto_malloc(sizeof(struct mosquitto*)*db->context_count); if(!db->contexts) return MOSQ_ERR_NOMEM; db->contexts[0] = NULL; db->subs.next = NULL; db->subs.subs = NULL; db->subs.topic = ""; child = _mosquitto_malloc(sizeof(struct _mosquitto_subhier)); if(!child){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } child->next = NULL; child->topic = _mosquitto_strdup(""); if(!child->topic){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } child->subs = NULL; child->children = NULL; child->retained = NULL; db->subs.children = child; child = _mosquitto_malloc(sizeof(struct _mosquitto_subhier)); if(!child){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } child->next = NULL; child->topic = _mosquitto_strdup("$SYS"); if(!child->topic){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } child->subs = NULL; child->children = NULL; child->retained = NULL; db->subs.children->next = child; db->unpwd = NULL; #ifdef WITH_PERSISTENCE if(config->persistence && config->persistence_filepath){ if(mqtt3_db_restore(db)) return 1; } #endif if(_mqtt3_db_cleanup(db)) return 1; return rc; } static void subhier_clean(struct _mosquitto_subhier *subhier) { struct _mosquitto_subhier *next; struct _mosquitto_subleaf *leaf, *nextleaf; while(subhier){ next = subhier->next; leaf = subhier->subs; while(leaf){ nextleaf = leaf->next; _mosquitto_free(leaf); leaf = nextleaf; } if(subhier->retained){ subhier->retained->ref_count--; } subhier_clean(subhier->children); if(subhier->topic) _mosquitto_free(subhier->topic); _mosquitto_free(subhier); subhier = next; } } int mqtt3_db_close(mosquitto_db *db) { subhier_clean(db->subs.children); mqtt3_db_store_clean(db); return MOSQ_ERR_SUCCESS; } /* Returns the number of client currently in the database. * This includes inactive clients. * Returns 1 on failure (count is NULL) * Returns 0 on success. */ int mqtt3_db_client_count(mosquitto_db *db, int *count, int *inactive_count) { int i; if(!db || !count || !inactive_count) return MOSQ_ERR_INVAL; *count = 0; *inactive_count = 0; for(i=0; icontext_count; i++){ if(db->contexts[i]){ (*count)++; if(db->contexts[i]->sock == INVALID_SOCKET){ (*inactive_count)++; } } } return MOSQ_ERR_SUCCESS; } /* Internal function. * Set all stored sockets to -1 (invalid) when starting mosquitto. * Also removes any stray clients and subcriptions that may be around from a prior crash. * Returns 1 on failure (db is NULL) * Returns 0 on success. */ static int _mqtt3_db_cleanup(mosquitto_db *db) { int rc = 0; if(!db) return MOSQ_ERR_INVAL; // FIXME - reimplement for new db #if 0 query = sqlite3_mprintf("UPDATE clients SET sock=-1"); /* Remove any stray clients that have clean session set. */ query = sqlite3_mprintf("DELETE FROM clients WHERE sock=-1 AND clean_session=1"); /* Remove any subs with no client. */ query = sqlite3_mprintf("DELETE FROM subs WHERE client_id NOT IN (SELECT id FROM clients)"); /* Remove any messages with no client. */ query = sqlite3_mprintf("DELETE FROM messages WHERE client_id NOT IN (SELECT id FROM clients)"); #endif return rc; } int mqtt3_db_message_delete(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir) { mosquitto_client_msg *tail, *last = NULL; int msg_index = 0; bool deleted = false; if(!context) return MOSQ_ERR_INVAL; tail = context->msgs; while(tail){ msg_index++; if(tail->state == ms_queued && msg_index <= max_inflight){ tail->timestamp = time(NULL); if(tail->direction == mosq_md_out){ switch(tail->qos){ case 0: tail->state = ms_publish; break; case 1: tail->state = ms_publish_puback; break; case 2: tail->state = ms_publish_pubrec; break; } }else{ if(tail->qos == 2){ tail->state = ms_wait_pubrec; } } } if(tail->mid == mid && tail->direction == dir){ msg_index--; /* FIXME - it would be nice to be able to remove the stored message here if ref_count==0 */ tail->store->ref_count--; if(last){ last->next = tail->next; }else{ context->msgs = tail->next; } _mosquitto_free(tail); if(last){ tail = last->next; }else{ tail = context->msgs; } deleted = true; }else{ last = tail; tail = tail->next; } if(msg_index > max_inflight && deleted){ return MOSQ_ERR_SUCCESS; } } return MOSQ_ERR_SUCCESS; } int mqtt3_db_message_insert(mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, int qos, bool retain, struct mosquitto_msg_store *stored) { mosquitto_client_msg *msg, *tail = NULL; enum mqtt3_msg_state state = ms_invalid; int msg_count = 0; int rc = 0; assert(stored); if(!context) return MOSQ_ERR_INVAL; if(context->sock == INVALID_SOCKET){ /* Client is not connected only queue messages with QoS>0. */ if(qos == 0){ if(!context->bridge){ return 2; }else{ if(context->bridge->start_type != bst_lazy){ return 2; } } } } if(context->msgs){ tail = context->msgs; msg_count = 1; while(tail && tail->next){ if(tail->qos > 0){ msg_count++; } tail = tail->next; } } if(context->sock != INVALID_SOCKET){ if(qos == 0 || max_inflight == 0 || msg_count < max_inflight){ if(dir == mosq_md_out){ switch(qos){ case 0: state = ms_publish; break; case 1: state = ms_publish_puback; break; case 2: state = ms_publish_pubrec; break; } }else{ if(qos == 2){ state = ms_wait_pubrec; }else{ return 1; } } }else if(max_queued == 0 || msg_count-max_inflight < max_queued){ state = ms_queued; rc = 2; }else{ /* Dropping message due to full queue. * FIXME - should this be logged? */ return 2; } }else{ if(msg_count >= max_queued){ return 2; }else{ state = ms_queued; } } assert(state != ms_invalid); msg = _mosquitto_malloc(sizeof(mosquitto_client_msg)); if(!msg) return MOSQ_ERR_NOMEM; msg->next = NULL; msg->store = stored; msg->store->ref_count++; msg->mid = mid; msg->timestamp = time(NULL); msg->direction = dir; msg->state = state; msg->dup = false; msg->qos = qos; msg->retain = retain; if(tail){ tail->next = msg; }else{ context->msgs = msg; } #ifdef WITH_BRIDGE msg_count++; /* We've just added a message to the list */ if(context->bridge && context->bridge->start_type == bst_lazy && context->sock == INVALID_SOCKET && msg_count >= context->bridge->threshold){ context->state = mosq_cs_new; mqtt3_bridge_connect(db, context); } #endif return rc; } int mqtt3_db_message_update(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, enum mqtt3_msg_state state) { mosquitto_client_msg *tail; tail = context->msgs; while(tail){ if(tail->mid == mid && tail->direction == dir){ tail->state = state; tail->timestamp = time(NULL); return MOSQ_ERR_SUCCESS; } tail = tail->next; } return 1; } int mqtt3_db_messages_delete(struct mosquitto *context) { mosquitto_client_msg *tail, *next; if(!context) return MOSQ_ERR_INVAL; tail = context->msgs; while(tail){ /* FIXME - it would be nice to be able to remove the stored message here if rec_count==0 */ tail->store->ref_count--; next = tail->next; _mosquitto_free(tail); tail = next; } context->msgs = NULL; return MOSQ_ERR_SUCCESS; } int mqtt3_db_messages_easy_queue(mosquitto_db *db, struct mosquitto *context, const char *topic, int qos, uint32_t payloadlen, const uint8_t *payload, int retain) { struct mosquitto_msg_store *stored; char *source_id; assert(db); if(!topic) return MOSQ_ERR_INVAL; if(context){ source_id = context->id; }else{ source_id = ""; } if(mqtt3_db_message_store(db, source_id, 0, topic, qos, payloadlen, payload, retain, &stored, 0)) return 1; return mqtt3_db_messages_queue(db, source_id, topic, qos, retain, stored); } int mqtt3_db_message_store(mosquitto_db *db, const char *source, uint16_t source_mid, const char *topic, int qos, uint32_t payloadlen, const uint8_t *payload, int retain, struct mosquitto_msg_store **stored, dbid_t store_id) { struct mosquitto_msg_store *temp; assert(db); assert(stored); if(!topic) return MOSQ_ERR_INVAL; temp = _mosquitto_malloc(sizeof(struct mosquitto_msg_store)); if(!temp) return MOSQ_ERR_NOMEM; temp->next = db->msg_store; temp->ref_count = 0; if(source){ temp->source_id = _mosquitto_strdup(source); }else{ temp->source_id = _mosquitto_strdup(""); } if(!temp->source_id){ _mosquitto_free(temp); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } temp->source_mid = source_mid; temp->msg.mid = 0; temp->msg.qos = qos; temp->msg.retain = retain; temp->msg.topic = _mosquitto_strdup(topic); if(!temp->msg.topic){ _mosquitto_free(temp); _mosquitto_free(temp->source_id); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } temp->msg.payloadlen = payloadlen; if(payloadlen){ temp->msg.payload = _mosquitto_malloc(sizeof(uint8_t)*payloadlen); if(!temp->msg.payload){ if(temp->source_id) _mosquitto_free(temp->source_id); if(temp->msg.topic) _mosquitto_free(temp->msg.topic); if(temp->msg.payload) _mosquitto_free(temp->msg.payload); _mosquitto_free(temp); return MOSQ_ERR_NOMEM; } memcpy(temp->msg.payload, payload, sizeof(uint8_t)*payloadlen); }else{ temp->msg.payload = NULL; } if(!temp->source_id || !temp->msg.topic || (payloadlen && !temp->msg.payload)){ if(temp->source_id) _mosquitto_free(temp->source_id); if(temp->msg.topic) _mosquitto_free(temp->msg.topic); if(temp->msg.payload) _mosquitto_free(temp->msg.payload); _mosquitto_free(temp); return 1; } db->msg_store_count++; db->msg_store = temp; (*stored) = temp; if(!store_id){ temp->db_id = ++db->last_db_id; }else{ temp->db_id = store_id; } return MOSQ_ERR_SUCCESS; } int mqtt3_db_message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto_msg_store **stored) { mosquitto_client_msg *tail; if(!context) return MOSQ_ERR_INVAL; *stored = NULL; tail = context->msgs; while(tail){ if(tail->store->source_mid == mid && tail->direction == mosq_md_in){ *stored = tail->store; return MOSQ_ERR_SUCCESS; } tail = tail->next; } return 1; } int mqtt3_db_message_timeout_check(mosquitto_db *db, unsigned int timeout) { int i; time_t threshold = time(NULL) - timeout; enum mqtt3_msg_state new_state = ms_invalid; struct mosquitto *context; mosquitto_client_msg *msg; for(i=0; icontext_count; i++){ context = db->contexts[i]; if(!context) continue; msg = context->msgs; while(msg){ if(msg->timestamp < threshold && msg->state != ms_queued){ switch(msg->state){ case ms_wait_puback: new_state = ms_publish_puback; break; case ms_wait_pubrec: new_state = ms_publish_pubrec; break; case ms_wait_pubrel: new_state = ms_resend_pubrec; break; case ms_wait_pubcomp: new_state = ms_resend_pubrel; break; default: break; } if(new_state != ms_invalid){ msg->timestamp = time(NULL); msg->state = new_state; msg->dup = true; } } msg = msg->next; } } return MOSQ_ERR_SUCCESS; } int mqtt3_db_message_release(mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir) { mosquitto_client_msg *tail, *last = NULL; int qos; int retain; char *topic; char *source_id; if(!context) return MOSQ_ERR_INVAL; tail = context->msgs; while(tail){ if(tail->mid == mid && tail->direction == dir){ qos = tail->store->msg.qos; topic = tail->store->msg.topic; retain = tail->retain; source_id = tail->store->source_id; if(!mqtt3_db_messages_queue(db, source_id, topic, qos, retain, tail->store)){ tail->store->ref_count--; if(last){ last->next = tail->next; }else{ context->msgs = tail->next; } _mosquitto_free(tail); return MOSQ_ERR_SUCCESS; }else{ return 1; } } last = tail; tail = tail->next; } return 1; } int mqtt3_db_message_write(struct mosquitto *context) { int rc; mosquitto_client_msg *tail, *last = NULL; uint16_t mid; int retries; int retain; const char *topic; int qos; uint32_t payloadlen; const uint8_t *payload; if(!context || context->sock == -1 || (context->state == mosq_cs_connected && !context->id)){ return MOSQ_ERR_INVAL; } tail = context->msgs; while(tail){ if(tail->direction == mosq_md_out && tail->state != ms_queued){ mid = tail->mid; retries = tail->dup; retain = tail->retain; topic = tail->store->msg.topic; qos = tail->qos; payloadlen = tail->store->msg.payloadlen; payload = tail->store->msg.payload; switch(tail->state){ case ms_publish: rc = _mosquitto_send_publish(context, mid, topic, payloadlen, payload, qos, retain, retries); if(!rc){ if(last){ last->next = tail->next; tail->store->ref_count--; _mosquitto_free(tail); tail = last->next; }else{ context->msgs = tail->next; tail->store->ref_count--; _mosquitto_free(tail); tail = context->msgs; } }else{ return rc; } break; case ms_publish_puback: rc = _mosquitto_send_publish(context, mid, topic, payloadlen, payload, qos, retain, retries); if(!rc){ tail->state = ms_wait_puback; }else{ return rc; } last = tail; tail = tail->next; break; case ms_publish_pubrec: rc = _mosquitto_send_publish(context, mid, topic, payloadlen, payload, qos, retain, retries); if(!rc){ tail->state = ms_wait_pubrec; }else{ return rc; } last = tail; tail = tail->next; break; case ms_resend_pubrec: rc = _mosquitto_send_pubrec(context, mid); if(!rc){ tail->state = ms_wait_pubrel; }else{ return rc; } last = tail; tail = tail->next; break; case ms_resend_pubrel: rc = _mosquitto_send_pubrel(context, mid, true); if(!rc){ tail->state = ms_wait_pubcomp; }else{ return rc; } last = tail; tail = tail->next; break; case ms_resend_pubcomp: rc = _mosquitto_send_pubcomp(context, mid); if(!rc){ tail->state = ms_wait_pubrel; }else{ return rc; } last = tail; tail = tail->next; break; default: last = tail; tail = tail->next; break; } }else{ last = tail; tail = tail->next; } } return MOSQ_ERR_SUCCESS; } void mqtt3_db_store_clean(mosquitto_db *db) { /* FIXME - this may not be necessary if checks are made when messages are removed. */ struct mosquitto_msg_store *tail, *last = NULL; assert(db); tail = db->msg_store; while(tail){ if(tail->ref_count == 0){ if(tail->source_id) _mosquitto_free(tail->source_id); if(tail->msg.topic) _mosquitto_free(tail->msg.topic); if(tail->msg.payload) _mosquitto_free(tail->msg.payload); if(last){ last->next = tail->next; _mosquitto_free(tail); tail = last->next; }else{ db->msg_store = tail->next; _mosquitto_free(tail); tail = db->msg_store; } db->msg_store_count--; }else{ last = tail; tail = tail->next; } } } /* Send messages for the $SYS hierarchy if the last update is longer than * 'interval' seconds ago. * 'interval' is the amount of seconds between updates. If 0, then no periodic * messages are sent for the $SYS hierarchy. * 'start_time' is the result of time() that the broker was started at. */ void mqtt3_db_sys_update(mosquitto_db *db, int interval, time_t start_time) { static time_t last_update = 0; time_t now = time(NULL); time_t uptime; char buf[100]; int value; int inactive; int active; unsigned long value_ul; unsigned long long value_ull; static int msg_store_count = -1; static int client_count = -1; static int client_max = -1; static int inactive_count = -1; static int active_count = -1; #ifdef REAL_WITH_MEMORY_TRACKING static unsigned long current_heap = -1; static unsigned long max_heap = -1; #endif static unsigned long msgs_received = -1; static unsigned long msgs_sent = -1; static unsigned int msgsps_received = -1; static unsigned int msgsps_sent = -1; static unsigned long long bytes_received = -1; static unsigned long long bytes_sent = -1; static unsigned int bytesps_received = -1; static unsigned int bytesps_sent = -1; if(interval && now - interval > last_update){ uptime = now - start_time; snprintf(buf, 100, "%d seconds", (int)uptime); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/uptime", 2, strlen(buf), (uint8_t *)buf, 1); if(db->msg_store_count != msg_store_count){ msg_store_count = db->msg_store_count; snprintf(buf, 100, "%d", msg_store_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/messages/stored", 2, strlen(buf), (uint8_t *)buf, 1); } if(!mqtt3_db_client_count(db, &value, &inactive)){ if(client_count != value){ client_count = value; snprintf(buf, 100, "%d", client_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/total", 2, strlen(buf), (uint8_t *)buf, 1); } if(inactive_count != inactive){ inactive_count = inactive; snprintf(buf, 100, "%d", inactive_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/inactive", 2, strlen(buf), (uint8_t *)buf, 1); } active = client_count - inactive; if(active_count != active){ active_count = active; snprintf(buf, 100, "%d", active_count); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/active", 2, strlen(buf), (uint8_t *)buf, 1); } if(value > client_max){ client_max = value; snprintf(buf, 100, "%d", client_max); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/clients/maximum", 2, strlen(buf), (uint8_t *)buf, 1); } } #ifdef REAL_WITH_MEMORY_TRACKING value_ul = _mosquitto_memory_used(); if(current_heap != value_ul){ current_heap = value_ul; snprintf(buf, 100, "%lu bytes", current_heap); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/heap/current size", 2, strlen(buf), (uint8_t *)buf, 1); } value_ul =_mosquitto_max_memory_used(); if(max_heap != value_ul){ max_heap = value_ul; snprintf(buf, 100, "%lu bytes", max_heap); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/heap/maximum size", 2, strlen(buf), (uint8_t *)buf, 1); } #endif value_ul = mqtt3_net_msgs_total_received(); if(msgs_received != value_ul){ msgs_received = value_ul; snprintf(buf, 100, "%lu", msgs_received); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/messages/received", 2, strlen(buf), (uint8_t *)buf, 1); } value_ul = mqtt3_net_msgs_total_sent(); if(msgs_sent != value_ul){ msgs_sent = value_ul; snprintf(buf, 100, "%lu", msgs_sent); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/messages/sent", 2, strlen(buf), (uint8_t *)buf, 1); } value_ull = (unsigned long long)mqtt3_net_bytes_total_received(); if(bytes_received != value_ull){ bytes_received = value_ull; snprintf(buf, 100, "%llu", bytes_received); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/bytes/received", 2, strlen(buf), (uint8_t *)buf, 1); } value_ull = (unsigned long long)mqtt3_net_bytes_total_sent(); if(bytes_sent != value_ull){ bytes_sent = value_ull; snprintf(buf, 100, "%llu", bytes_sent); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/bytes/sent", 2, strlen(buf), (uint8_t *)buf, 1); } if(uptime){ value = msgs_received/uptime; if(msgsps_received != value){ msgsps_received = value; snprintf(buf, 100, "%u", msgsps_received); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/messages/per second/received", 2, strlen(buf), (uint8_t *)buf, 1); } value = msgs_sent/uptime; if(msgsps_sent != value){ msgsps_sent = value; snprintf(buf, 100, "%u", msgsps_sent); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/messages/per second/sent", 2, strlen(buf), (uint8_t *)buf, 1); } value = bytes_received/uptime; if(bytesps_received != value){ bytesps_received = value; snprintf(buf, 100, "%u", bytesps_received); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/bytes/per second/received", 2, strlen(buf), (uint8_t *)buf, 1); } value = bytes_sent/uptime; if(bytesps_sent != value){ bytesps_sent = value; snprintf(buf, 100, "%u", bytesps_sent); mqtt3_db_messages_easy_queue(db, NULL, "$SYS/broker/bytes/per second/sent", 2, strlen(buf), (uint8_t *)buf, 1); } } last_update = time(NULL); } } void mqtt3_db_limits_set(int inflight, int queued) { max_inflight = inflight; max_queued = queued; } void mqtt3_db_vacuum(void) { /* FIXME - reimplement? */ } mosquitto-0.15/src/persist.c0000664000175000017500000005204711713444064015163 0ustar rogerroger/* Copyright (c) 2010,2011 Roger Light 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. */ #include #ifdef WITH_PERSISTENCE #ifndef WIN32 #include #endif #include #include #include #include #include #include #include #include #include static int _db_restore_sub(mosquitto_db *db, const char *client_id, const char *sub, int qos); static struct mosquitto *_db_find_or_add_context(mosquitto_db *db, const char *client_id, uint16_t last_mid) { struct mosquitto *context; struct mosquitto **tmp_contexts; int i; context = NULL; for(i=0; icontext_count; i++){ if(db->contexts[i] && !strcmp(db->contexts[i]->id, client_id)){ context = db->contexts[i]; break; } } if(!context){ context = mqtt3_context_init(-1); context->clean_session = false; for(i=0; icontext_count; i++){ if(!db->contexts[i]){ db->contexts[i] = context; break; } } if(i==db->context_count){ 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] = context; }else{ return NULL; } } context->id = _mosquitto_strdup(client_id); } if(last_mid){ context->last_mid = last_mid; } return context; } static int mqtt3_db_client_messages_write(mosquitto_db *db, FILE *db_fptr, struct mosquitto *context) { uint32_t length; dbid_t i64temp; uint16_t i16temp, slen; uint8_t i8temp; mosquitto_client_msg *cmsg; assert(db); assert(db_fptr); assert(context); cmsg = context->msgs; while(cmsg){ slen = strlen(context->id); length = htonl(sizeof(dbid_t) + sizeof(uint16_t) + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint8_t) + 2+slen); i16temp = htons(DB_CHUNK_CLIENT_MSG); write_e(db_fptr, &i16temp, sizeof(uint16_t)); write_e(db_fptr, &length, sizeof(uint32_t)); i16temp = htons(slen); write_e(db_fptr, &i16temp, sizeof(uint16_t)); write_e(db_fptr, context->id, slen); i64temp = cmsg->store->db_id; write_e(db_fptr, &i64temp, sizeof(dbid_t)); i16temp = htons(cmsg->mid); write_e(db_fptr, &i16temp, sizeof(uint16_t)); i8temp = (uint8_t )cmsg->qos; write_e(db_fptr, &i8temp, sizeof(uint8_t)); i8temp = (uint8_t )cmsg->retain; write_e(db_fptr, &i8temp, sizeof(uint8_t)); i8temp = (uint8_t )cmsg->direction; write_e(db_fptr, &i8temp, sizeof(uint8_t)); i8temp = (uint8_t )cmsg->state; write_e(db_fptr, &i8temp, sizeof(uint8_t)); i8temp = (uint8_t )cmsg->dup; write_e(db_fptr, &i8temp, sizeof(uint8_t)); cmsg = cmsg->next; } return MOSQ_ERR_SUCCESS; error: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); return 1; } static int mqtt3_db_message_store_write(mosquitto_db *db, FILE *db_fptr) { uint32_t length; dbid_t i64temp; uint32_t i32temp; uint16_t i16temp, slen; uint8_t i8temp; struct mosquitto_msg_store *stored; assert(db); assert(db_fptr); stored = db->msg_store; while(stored){ length = htonl(sizeof(dbid_t) + 2+strlen(stored->source_id) + sizeof(uint16_t) + sizeof(uint16_t) + 2+strlen(stored->msg.topic) + sizeof(uint32_t) + stored->msg.payloadlen + sizeof(uint8_t) + sizeof(uint8_t)); i16temp = htons(DB_CHUNK_MSG_STORE); write_e(db_fptr, &i16temp, sizeof(uint16_t)); write_e(db_fptr, &length, sizeof(uint32_t)); i64temp = stored->db_id; write_e(db_fptr, &i64temp, sizeof(dbid_t)); slen = strlen(stored->source_id); i16temp = htons(slen); write_e(db_fptr, &i16temp, sizeof(uint16_t)); if(slen){ write_e(db_fptr, stored->source_id, slen); } i16temp = htons(stored->source_mid); write_e(db_fptr, &i16temp, sizeof(uint16_t)); i16temp = htons(stored->msg.mid); write_e(db_fptr, &i16temp, sizeof(uint16_t)); slen = strlen(stored->msg.topic); i16temp = htons(slen); write_e(db_fptr, &i16temp, sizeof(uint16_t)); write_e(db_fptr, stored->msg.topic, slen); i8temp = (uint8_t )stored->msg.qos; write_e(db_fptr, &i8temp, sizeof(uint8_t)); i8temp = (uint8_t )stored->msg.retain; write_e(db_fptr, &i8temp, sizeof(uint8_t)); i32temp = htonl(stored->msg.payloadlen); write_e(db_fptr, &i32temp, sizeof(uint32_t)); if(stored->msg.payloadlen){ write_e(db_fptr, stored->msg.payload, stored->msg.payloadlen); } stored = stored->next; } return MOSQ_ERR_SUCCESS; error: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); return 1; } static int mqtt3_db_client_write(mosquitto_db *db, FILE *db_fptr) { int i; struct mosquitto *context; uint16_t i16temp, slen; uint32_t length; assert(db); assert(db_fptr); for(i=0; icontext_count; i++){ context = db->contexts[i]; if(context && context->clean_session == false){ length = htonl(2+strlen(context->id) + sizeof(uint16_t)); i16temp = htons(DB_CHUNK_CLIENT); write_e(db_fptr, &i16temp, sizeof(uint16_t)); write_e(db_fptr, &length, sizeof(uint32_t)); slen = strlen(context->id); i16temp = htons(slen); write_e(db_fptr, &i16temp, sizeof(uint16_t)); write_e(db_fptr, context->id, slen); i16temp = htons(context->last_mid); write_e(db_fptr, &i16temp, sizeof(uint16_t)); if(mqtt3_db_client_messages_write(db, db_fptr, context)) return 1; } } return MOSQ_ERR_SUCCESS; error: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); return 1; } static int _db_subs_retain_write(mosquitto_db *db, FILE *db_fptr, struct _mosquitto_subhier *node, const char *topic) { struct _mosquitto_subhier *subhier; struct _mosquitto_subleaf *sub; char *thistopic; uint32_t length; uint16_t i16temp; dbid_t i64temp; int slen; slen = strlen(topic) + strlen(node->topic) + 2; thistopic = _mosquitto_malloc(sizeof(char)*slen); if(!thistopic) return MOSQ_ERR_NOMEM; if(strlen(topic)){ snprintf(thistopic, slen, "%s/%s", topic, node->topic); }else{ snprintf(thistopic, slen, "%s", node->topic); } sub = node->subs; while(sub){ if(sub->context->clean_session == false){ length = htonl(2+strlen(sub->context->id) + 2+strlen(thistopic) + sizeof(uint8_t)); i16temp = htons(DB_CHUNK_SUB); write_e(db_fptr, &i16temp, sizeof(uint16_t)); write_e(db_fptr, &length, sizeof(uint32_t)); slen = strlen(sub->context->id); i16temp = htons(slen); write_e(db_fptr, &i16temp, sizeof(uint16_t)); write_e(db_fptr, sub->context->id, slen); slen = strlen(thistopic); i16temp = htons(slen); write_e(db_fptr, &i16temp, sizeof(uint16_t)); write_e(db_fptr, thistopic, slen); write_e(db_fptr, &sub->qos, sizeof(uint8_t)); } sub = sub->next; } if(node->retained){ length = htonl(sizeof(dbid_t)); i16temp = htons(DB_CHUNK_RETAIN); write_e(db_fptr, &i16temp, sizeof(uint16_t)); write_e(db_fptr, &length, sizeof(uint32_t)); i64temp = node->retained->db_id; write_e(db_fptr, &i64temp, sizeof(dbid_t)); } subhier = node->children; while(subhier){ _db_subs_retain_write(db, db_fptr, subhier, thistopic); subhier = subhier->next; } _mosquitto_free(thistopic); return MOSQ_ERR_SUCCESS; error: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); return 1; } static int mqtt3_db_subs_retain_write(mosquitto_db *db, FILE *db_fptr) { struct _mosquitto_subhier *subhier; subhier = db->subs.children; while(subhier){ _db_subs_retain_write(db, db_fptr, subhier, ""); subhier = subhier->next; } return MOSQ_ERR_SUCCESS; } int mqtt3_db_backup(mosquitto_db *db, bool cleanup, bool shutdown) { int rc = 0; FILE *db_fptr = NULL; uint32_t db_version = htonl(MOSQ_DB_VERSION); uint32_t crc = htonl(0); dbid_t i64temp; uint32_t i32temp; uint16_t i16temp; uint8_t i8temp; if(!db || !db->config || !db->config->persistence_filepath) return MOSQ_ERR_INVAL; _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "Saving in-memory database to %s.", db->config->persistence_filepath); if(cleanup){ mqtt3_db_store_clean(db); } db_fptr = fopen(db->config->persistence_filepath, "wb"); if(db_fptr == NULL){ goto error; } /* Header */ write_e(db_fptr, magic, 15); write_e(db_fptr, &crc, sizeof(uint32_t)); write_e(db_fptr, &db_version, sizeof(uint32_t)); /* DB config */ i16temp = htons(DB_CHUNK_CFG); write_e(db_fptr, &i16temp, sizeof(uint16_t)); /* chunk length */ i32temp = htonl(sizeof(dbid_t) + sizeof(uint8_t) + sizeof(uint8_t)); write_e(db_fptr, &i32temp, sizeof(uint32_t)); /* db written at broker shutdown or not */ i8temp = shutdown; write_e(db_fptr, &i8temp, sizeof(uint8_t)); i8temp = sizeof(dbid_t); write_e(db_fptr, &i8temp, sizeof(uint8_t)); /* last db mid */ i64temp = db->last_db_id; write_e(db_fptr, &i64temp, sizeof(dbid_t)); if(mqtt3_db_message_store_write(db, db_fptr)){ goto error; } mqtt3_db_client_write(db, db_fptr); mqtt3_db_subs_retain_write(db, db_fptr); fclose(db_fptr); return rc; error: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); if(db_fptr) fclose(db_fptr); return 1; } static int _db_client_msg_restore(mosquitto_db *db, const char *client_id, uint16_t mid, uint8_t qos, uint8_t retain, uint8_t direction, uint8_t state, uint8_t dup, uint64_t store_id) { mosquitto_client_msg *cmsg, *tail; struct mosquitto_msg_store *store; struct mosquitto *context; cmsg = _mosquitto_calloc(1, sizeof(mosquitto_client_msg)); if(!cmsg){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } cmsg->store = NULL; cmsg->mid = mid; cmsg->qos = qos; cmsg->retain = retain; cmsg->direction = direction; cmsg->state = state; cmsg->dup = dup; store = db->msg_store; while(store){ if(store->db_id == store_id){ cmsg->store = store; cmsg->store->ref_count++; break; } store = store->next; } if(!cmsg->store){ _mosquitto_free(cmsg); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error restoring persistent database, message store corrupt."); return 1; } context = _db_find_or_add_context(db, client_id, 0); if(!context){ _mosquitto_free(cmsg); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error restoring persistent database, message store corrupt."); return 1; } if(context->msgs){ tail = context->msgs; while(tail->next){ tail = tail->next; } tail->next = cmsg; }else{ context->msgs = cmsg; } cmsg->next = NULL; return MOSQ_ERR_SUCCESS; } static int _db_client_chunk_restore(mosquitto_db *db, FILE *db_fptr) { uint16_t i16temp, slen, last_mid; char *client_id = NULL; int rc = 0; struct mosquitto *context; read_e(db_fptr, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); if(!slen){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Corrupt persistent database."); fclose(db_fptr); return 1; } client_id = _mosquitto_calloc(slen+1, sizeof(char)); if(!client_id){ fclose(db_fptr); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } read_e(db_fptr, client_id, slen); read_e(db_fptr, &i16temp, sizeof(uint16_t)); last_mid = ntohs(i16temp); context = _db_find_or_add_context(db, client_id, last_mid); if(!context) rc = 1; _mosquitto_free(client_id); return rc; error: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); if(db_fptr) fclose(db_fptr); if(client_id) _mosquitto_free(client_id); return 1; } static int _db_client_msg_chunk_restore(mosquitto_db *db, FILE *db_fptr) { dbid_t i64temp, store_id; uint16_t i16temp, slen, mid; uint8_t qos, retain, direction, state, dup; char *client_id = NULL; int rc; read_e(db_fptr, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); if(!slen){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Corrupt persistent database."); fclose(db_fptr); return 1; } client_id = _mosquitto_calloc(slen+1, sizeof(char)); if(!client_id){ fclose(db_fptr); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } read_e(db_fptr, client_id, slen); read_e(db_fptr, &i64temp, sizeof(dbid_t)); store_id = i64temp; read_e(db_fptr, &i16temp, sizeof(uint16_t)); mid = ntohs(i16temp); read_e(db_fptr, &qos, sizeof(uint8_t)); read_e(db_fptr, &retain, sizeof(uint8_t)); read_e(db_fptr, &direction, sizeof(uint8_t)); read_e(db_fptr, &state, sizeof(uint8_t)); read_e(db_fptr, &dup, sizeof(uint8_t)); rc = _db_client_msg_restore(db, client_id, mid, qos, retain, direction, state, dup, store_id); _mosquitto_free(client_id); return rc; error: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); if(db_fptr) fclose(db_fptr); if(client_id) _mosquitto_free(client_id); return 1; } static int _db_msg_store_chunk_restore(mosquitto_db *db, FILE *db_fptr) { dbid_t i64temp, store_id; uint32_t i32temp, payloadlen; uint16_t i16temp, slen, source_mid, mid; uint8_t qos, retain, *payload = NULL; char *source_id = NULL; char *topic = NULL; int rc = 0; struct mosquitto_msg_store *stored = NULL; read_e(db_fptr, &i64temp, sizeof(dbid_t)); store_id = i64temp; read_e(db_fptr, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); if(slen){ source_id = _mosquitto_calloc(slen+1, sizeof(char)); if(!source_id){ fclose(db_fptr); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } if(fread(source_id, 1, slen, db_fptr) != slen){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); fclose(db_fptr); _mosquitto_free(source_id); return 1; } } read_e(db_fptr, &i16temp, sizeof(uint16_t)); source_mid = ntohs(i16temp); read_e(db_fptr, &i16temp, sizeof(uint16_t)); mid = ntohs(i16temp); read_e(db_fptr, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); if(slen){ topic = _mosquitto_calloc(slen+1, sizeof(char)); if(!topic){ fclose(db_fptr); _mosquitto_free(source_id); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } if(fread(topic, 1, slen, db_fptr) != slen){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); fclose(db_fptr); _mosquitto_free(source_id); _mosquitto_free(topic); return 1; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid msg_store chunk when restoring persistent database."); fclose(db_fptr); _mosquitto_free(source_id); return 1; } read_e(db_fptr, &qos, sizeof(uint8_t)); read_e(db_fptr, &retain, sizeof(uint8_t)); read_e(db_fptr, &i32temp, sizeof(uint32_t)); payloadlen = ntohl(i32temp); if(payloadlen){ payload = _mosquitto_malloc(payloadlen); if(!payload){ fclose(db_fptr); _mosquitto_free(source_id); _mosquitto_free(topic); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } if(fread(payload, 1, payloadlen, db_fptr) != payloadlen){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); fclose(db_fptr); _mosquitto_free(source_id); _mosquitto_free(topic); _mosquitto_free(payload); return 1; } } rc = mqtt3_db_message_store(db, source_id, source_mid, topic, qos, payloadlen, payload, retain, &stored, store_id); _mosquitto_free(source_id); _mosquitto_free(topic); _mosquitto_free(payload); return rc; error: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); if(db_fptr) fclose(db_fptr); if(source_id) _mosquitto_free(source_id); if(topic) _mosquitto_free(topic); return 1; } static int _db_retain_chunk_restore(mosquitto_db *db, FILE *db_fptr) { dbid_t i64temp, store_id; struct mosquitto_msg_store *store; if(fread(&i64temp, 1, sizeof(dbid_t), db_fptr) != sizeof(dbid_t)){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); fclose(db_fptr); return 1; } store_id = i64temp; store = db->msg_store; while(store){ if(store->db_id == store_id){ mqtt3_db_messages_queue(db, NULL, store->msg.topic, store->msg.qos, store->msg.retain, store); break; } store = store->next; } return MOSQ_ERR_SUCCESS; } static int _db_sub_chunk_restore(mosquitto_db *db, FILE *db_fptr) { uint16_t i16temp, slen; uint8_t qos; char *client_id; char *topic; int rc = 0; read_e(db_fptr, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); client_id = _mosquitto_calloc(slen+1, sizeof(char)); if(!client_id){ fclose(db_fptr); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } read_e(db_fptr, client_id, slen); read_e(db_fptr, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); topic = _mosquitto_calloc(slen+1, sizeof(char)); if(!topic){ fclose(db_fptr); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); _mosquitto_free(client_id); return MOSQ_ERR_NOMEM; } read_e(db_fptr, topic, slen); read_e(db_fptr, &qos, sizeof(uint8_t)); if(_db_restore_sub(db, client_id, topic, qos)){ rc = 1; } _mosquitto_free(client_id); _mosquitto_free(topic); return rc; error: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); if(db_fptr) fclose(db_fptr); return 1; } int mqtt3_db_restore(mosquitto_db *db) { FILE *fptr; char header[15]; int rc = 0; uint32_t crc, db_version; dbid_t i64temp; uint32_t i32temp, length; uint16_t i16temp, chunk; uint8_t i8temp; ssize_t rlen; assert(db); assert(db->config); assert(db->config->persistence_filepath); fptr = fopen(db->config->persistence_filepath, "rb"); if(fptr == NULL) return MOSQ_ERR_SUCCESS; read_e(fptr, &header, 15); if(!memcmp(header, magic, 15)){ // Restore DB as normal read_e(fptr, &crc, sizeof(uint32_t)); read_e(fptr, &i32temp, sizeof(uint32_t)); db_version = ntohl(i32temp); /* IMPORTANT - this is where compatibility checks are made. * Is your DB change still compatible with previous versions? */ if(db_version > MOSQ_DB_VERSION && db_version != 0){ fclose(fptr); _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unsupported persistent database format version %d (need version %d).", db_version, MOSQ_DB_VERSION); return 1; } while(rlen = fread(&i16temp, 1, sizeof(uint16_t), fptr), rlen == sizeof(uint16_t)){ chunk = ntohs(i16temp); read_e(fptr, &i32temp, sizeof(uint32_t)); length = ntohl(i32temp); switch(chunk){ case DB_CHUNK_CFG: read_e(fptr, &i8temp, sizeof(uint8_t)); // shutdown read_e(fptr, &i8temp, sizeof(uint8_t)); // sizeof(dbid_t) if(i8temp != sizeof(dbid_t)){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Incompatible database configuration (dbid size is %d bytes, expected %d)", i8temp, sizeof(dbid_t)); fclose(fptr); return 1; } read_e(fptr, &i64temp, sizeof(dbid_t)); db->last_db_id = i64temp; break; case DB_CHUNK_MSG_STORE: if(_db_msg_store_chunk_restore(db, fptr)) return 1; break; case DB_CHUNK_CLIENT_MSG: if(_db_client_msg_chunk_restore(db, fptr)) return 1; break; case DB_CHUNK_RETAIN: if(_db_retain_chunk_restore(db, fptr)) return 1; break; case DB_CHUNK_SUB: if(_db_sub_chunk_restore(db, fptr)) return 1; break; case DB_CHUNK_CLIENT: if(_db_client_chunk_restore(db, fptr)) return 1; break; default: _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Unsupported chunk \"%d\" in persistent database file. Ignoring.", chunk); fseek(fptr, length, SEEK_CUR); break; } } if(rlen < 0) goto error; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to restore persistent database. Unrecognised file format."); rc = 1; } fclose(fptr); return rc; error: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); if(fptr) fclose(fptr); return 1; } static int _db_restore_sub(mosquitto_db *db, const char *client_id, const char *sub, int qos) { struct mosquitto *context; assert(db); assert(client_id); assert(sub); context = _db_find_or_add_context(db, client_id, 0); if(!context) return 1; return mqtt3_sub_add(context, sub, qos, &db->subs); } #endif mosquitto-0.15/src/subs.c0000664000175000017500000003704411713444064014446 0ustar rogerroger/* Copyright (c) 2010-2012 Roger Light 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. */ #include #include #include #include #include #include #include struct _sub_token { struct _sub_token *next; char *topic; }; static int _subs_process(struct _mosquitto_db *db, struct _mosquitto_subhier *hier, const char *source_id, const char *topic, int qos, int retain, struct mosquitto_msg_store *stored) { int rc = 0; int rc2; int client_qos, msg_qos; uint16_t mid; struct _mosquitto_subleaf *leaf; leaf = hier->subs; if(retain){ if(hier->retained){ hier->retained->ref_count--; /* FIXME - it would be nice to be able to remove the message from the store at this point if ref_count == 0 */ } if(stored->msg.payloadlen){ hier->retained = stored; hier->retained->ref_count++; }else{ hier->retained = NULL; } } while(source_id && leaf){ if(leaf->context->bridge && !strcmp(leaf->context->id, source_id)){ leaf = leaf->next; continue; } /* Check for ACL topic access. */ rc2 = mosquitto_acl_check(db, leaf->context, topic, MOSQ_ACL_READ); if(rc2 == MOSQ_ERR_ACL_DENIED){ leaf = leaf->next; continue; }else if(rc2 == MOSQ_ERR_SUCCESS){ client_qos = leaf->qos; if(qos > client_qos){ msg_qos = client_qos; }else{ msg_qos = qos; } if(msg_qos){ mid = _mosquitto_mid_generate(leaf->context); }else{ mid = 0; } if(mqtt3_db_message_insert(db, leaf->context, mid, mosq_md_out, msg_qos, false, stored) == 1) rc = 1; }else{ rc = 1; } leaf = leaf->next; } return rc; } static int _sub_topic_tokenise(const char *subtopic, struct _sub_token **topics) { struct _sub_token *new_topic, *tail = NULL; char *token; char *local_subtopic = NULL; char *real_subtopic; assert(subtopic); assert(topics); local_subtopic = _mosquitto_strdup(subtopic); if(!local_subtopic) return MOSQ_ERR_NOMEM; real_subtopic = local_subtopic; if(local_subtopic[0] == '/'){ new_topic = _mosquitto_malloc(sizeof(struct _sub_token)); if(!new_topic) goto cleanup; new_topic->next = NULL; new_topic->topic = _mosquitto_strdup("/"); if(!new_topic->topic) goto cleanup; *topics = new_topic; tail = new_topic; local_subtopic++; } token = strtok(local_subtopic, "/"); while(token){ new_topic = _mosquitto_malloc(sizeof(struct _sub_token)); if(!new_topic) goto cleanup; new_topic->next = NULL; new_topic->topic = _mosquitto_strdup(token); if(!new_topic->topic) goto cleanup; if(tail){ tail->next = new_topic; tail = tail->next; }else{ tail = new_topic; *topics = tail; } token = strtok(NULL, "/"); } _mosquitto_free(real_subtopic); return MOSQ_ERR_SUCCESS; cleanup: _mosquitto_free(real_subtopic); tail = *topics; *topics = NULL; while(tail){ if(tail->topic) _mosquitto_free(tail->topic); new_topic = tail->next; _mosquitto_free(tail); tail = new_topic; } return 1; } static int _sub_add(struct mosquitto *context, int qos, struct _mosquitto_subhier *subhier, struct _sub_token *tokens) { struct _mosquitto_subhier *branch, *last = NULL; struct _mosquitto_subleaf *leaf, *last_leaf; if(!tokens){ if(context){ leaf = subhier->subs; last_leaf = NULL; while(leaf){ if(!strcmp(leaf->context->id, context->id)){ /* Client making a second subscription to same topic. Only * need to update QoS. Return -1 to indicate this to the * calling function. */ leaf->qos = qos; return -1; } last_leaf = leaf; leaf = leaf->next; } leaf = _mosquitto_malloc(sizeof(struct _mosquitto_subleaf)); if(!leaf) return MOSQ_ERR_NOMEM; leaf->next = NULL; leaf->context = context; leaf->qos = qos; if(last_leaf){ last_leaf->next = leaf; leaf->prev = last_leaf; }else{ subhier->subs = leaf; leaf->prev = NULL; } } return MOSQ_ERR_SUCCESS; } branch = subhier->children; while(branch){ if(!strcmp(branch->topic, tokens->topic)){ return _sub_add(context, qos, branch, tokens->next); } last = branch; branch = branch->next; } /* Not found */ branch = _mosquitto_calloc(1, sizeof(struct _mosquitto_subhier)); if(!branch) return MOSQ_ERR_NOMEM; branch->topic = _mosquitto_strdup(tokens->topic); if(!branch->topic) return MOSQ_ERR_NOMEM; if(!last){ subhier->children = branch; }else{ last->next = branch; } return _sub_add(context, qos, branch, tokens->next); } static int _sub_remove(struct mosquitto *context, struct _mosquitto_subhier *subhier, struct _sub_token *tokens) { struct _mosquitto_subhier *branch, *last = NULL; struct _mosquitto_subleaf *leaf; if(!tokens){ leaf = subhier->subs; while(leaf){ if(leaf->context==context){ if(leaf->prev){ leaf->prev->next = leaf->next; }else{ subhier->subs = leaf->next; } if(leaf->next){ leaf->next->prev = leaf->prev; } _mosquitto_free(leaf); return MOSQ_ERR_SUCCESS; } leaf = leaf->next; } return MOSQ_ERR_SUCCESS; } branch = subhier->children; while(branch){ if(!strcmp(branch->topic, tokens->topic)){ _sub_remove(context, branch, tokens->next); if(!branch->children && !branch->subs && !branch->retained){ if(last){ last->next = branch->next; }else{ subhier->children = branch->next; } _mosquitto_free(branch->topic); _mosquitto_free(branch); } return MOSQ_ERR_SUCCESS; } last = branch; branch = branch->next; } return MOSQ_ERR_SUCCESS; } static int _sub_search(struct _mosquitto_db *db, struct _mosquitto_subhier *subhier, struct _sub_token *tokens, const char *source_id, const char *topic, int qos, int retain, struct mosquitto_msg_store *stored) { /* FIXME - need to take into account source_id if the client is a bridge */ struct _mosquitto_subhier *branch; int flag = 0; branch = subhier->children; while(branch){ if(tokens && tokens->topic && (!strcmp(branch->topic, tokens->topic) || !strcmp(branch->topic, "+"))){ /* The topic matches this subscription. * Doesn't include # wildcards */ _sub_search(db, branch, tokens->next, source_id, topic, qos, retain, stored); if(!tokens->next){ _subs_process(db, branch, source_id, topic, qos, retain, stored); } }else if(!strcmp(branch->topic, "#") && !branch->children && (!tokens || strcmp(tokens->topic, "/"))){ /* The topic matches due to a # wildcard - process the * subscriptions but *don't* return. Although this branch has ended * there may still be other subscriptions to deal with. */ _subs_process(db, branch, source_id, topic, qos, retain, stored); flag = -1; } branch = branch->next; } return flag; } int mqtt3_sub_add(struct mosquitto *context, const char *sub, int qos, struct _mosquitto_subhier *root) { int tree; int rc = 0; struct _mosquitto_subhier *subhier; struct _sub_token *tokens = NULL, *tail; assert(root); assert(sub); if(!strncmp(sub, "$SYS/", 5)){ tree = 2; if(strlen(sub+5) == 0) return MOSQ_ERR_SUCCESS; if(_sub_topic_tokenise(sub+5, &tokens)) return 1; }else{ tree = 0; if(strlen(sub) == 0) return MOSQ_ERR_SUCCESS; if(_sub_topic_tokenise(sub, &tokens)) return 1; } subhier = root->children; while(subhier){ if(!strcmp(subhier->topic, "") && tree == 0){ rc = _sub_add(context, qos, subhier, tokens); break; }else if(!strcmp(subhier->topic, "$SYS") && tree == 2){ rc = _sub_add(context, qos, subhier, tokens); break; } subhier = subhier->next; } while(tokens){ tail = tokens->next; _mosquitto_free(tokens->topic); _mosquitto_free(tokens); tokens = tail; } /* We aren't worried about -1 (already subscribed) return codes. */ if(rc == -1) rc = MOSQ_ERR_SUCCESS; return rc; } int mqtt3_sub_remove(struct mosquitto *context, const char *sub, struct _mosquitto_subhier *root) { int rc = 0; int tree; struct _mosquitto_subhier *subhier; struct _sub_token *tokens = NULL, *tail; assert(root); assert(sub); if(!strncmp(sub, "$SYS/", 5)){ tree = 2; if(_sub_topic_tokenise(sub+5, &tokens)) return 1; }else{ tree = 0; if(_sub_topic_tokenise(sub, &tokens)) return 1; } subhier = root->children; while(subhier){ if(!strcmp(subhier->topic, "") && tree == 0){ rc = _sub_remove(context, subhier, tokens); break; }else if(!strcmp(subhier->topic, "$SYS") && tree == 2){ rc = _sub_remove(context, subhier, tokens); break; } subhier = subhier->next; } while(tokens){ tail = tokens->next; _mosquitto_free(tokens->topic); _mosquitto_free(tokens); tokens = tail; } return rc; } int mqtt3_db_messages_queue(struct _mosquitto_db *db, const char *source_id, const char *topic, int qos, int retain, struct mosquitto_msg_store *stored) { int rc = 0; int tree; struct _mosquitto_subhier *subhier; struct _sub_token *tokens = NULL, *tail; assert(db); assert(topic); if(!strncmp(topic, "$SYS/", 5)){ tree = 2; if(_sub_topic_tokenise(topic+5, &tokens)) return 1; }else{ tree = 0; if(_sub_topic_tokenise(topic, &tokens)) return 1; } subhier = db->subs.children; while(subhier){ if(!strcmp(subhier->topic, "") && tree == 0){ if(retain){ /* We have a message that needs to be retained, so ensure that the subscription * tree for its topic exists. */ _sub_add(NULL, 0, subhier, tokens); } rc = _sub_search(db, subhier, tokens, source_id, topic, qos, retain, stored); if(rc == -1){ _subs_process(db, subhier, source_id, topic, qos, retain, stored); rc = 0; } }else if(!strcmp(subhier->topic, "$SYS") && tree == 2){ if(retain){ /* We have a message that needs to be retained, so ensure that the subscription * tree for its topic exists. */ _sub_add(NULL, 0, subhier, tokens); } rc = _sub_search(db, subhier, tokens, source_id, topic, qos, retain, stored); if(rc == -1){ _subs_process(db, subhier, source_id, topic, qos, retain, stored); rc = 0; } } subhier = subhier->next; } while(tokens){ tail = tokens->next; _mosquitto_free(tokens->topic); _mosquitto_free(tokens); tokens = tail; } return rc; } static int _subs_clean_session(struct mosquitto *context, struct _mosquitto_subhier *root) { int rc = 0; struct _mosquitto_subhier *child, *last = NULL; struct _mosquitto_subleaf *leaf, *next; if(!root) return MOSQ_ERR_SUCCESS; leaf = root->subs; while(leaf){ if(leaf->context == context){ if(leaf->prev){ leaf->prev->next = leaf->next; }else{ root->subs = leaf->next; } if(leaf->next){ leaf->next->prev = leaf->prev; } next = leaf->next; _mosquitto_free(leaf); leaf = next; }else{ leaf = leaf->next; } } child = root->children; while(child){ _subs_clean_session(context, child); if(!child->children && !child->subs && !child->retained){ if(last){ last->next = child->next; }else{ root->children = child->next; } _mosquitto_free(child->topic); _mosquitto_free(child); if(last){ child = last->next; }else{ child = root->children; } }else{ last = child; child = child->next; } } return rc; } /* Remove all subscriptions for a client. */ int mqtt3_subs_clean_session(struct mosquitto *context, struct _mosquitto_subhier *root) { struct _mosquitto_subhier *child; child = root->children; while(child){ _subs_clean_session(context, child); child = child->next; } return MOSQ_ERR_SUCCESS; } void mqtt3_sub_tree_print(struct _mosquitto_subhier *root, int level) { int i; struct _mosquitto_subhier *branch; struct _mosquitto_subleaf *leaf; for(i=0; itopic); leaf = root->subs; while(leaf){ printf(" (%s, %d)", "", leaf->qos); leaf = leaf->next; } if(root->retained){ printf(" (r)"); } printf("\n"); branch = root->children; while(branch){ mqtt3_sub_tree_print(branch, level+1); branch = branch->next; } } static int _retain_process(struct _mosquitto_db *db, struct mosquitto_msg_store *retained, struct mosquitto *context, const char *sub, int sub_qos) { int rc = 0; int qos; uint16_t mid; rc = mosquitto_acl_check(db, context, retained->msg.topic, MOSQ_ACL_READ); if(rc == MOSQ_ERR_ACL_DENIED){ return MOSQ_ERR_SUCCESS; }else if(rc != MOSQ_ERR_SUCCESS){ return rc; } qos = retained->msg.qos; if(qos > sub_qos) qos = sub_qos; if(qos > 0){ mid = _mosquitto_mid_generate(context); }else{ mid = 0; } return mqtt3_db_message_insert(db, context, mid, mosq_md_out, qos, true, retained); } static int _retain_search(struct _mosquitto_db *db, struct _mosquitto_subhier *subhier, struct _sub_token *tokens, struct mosquitto *context, const char *sub, int sub_qos) { struct _mosquitto_subhier *branch; branch = subhier->children; while(branch){ /* Subscriptions with wildcards in aren't really valid topics to publish to * so they can't have retained messages. */ if(_mosquitto_topic_wildcard_len_check(branch->topic) == MOSQ_ERR_SUCCESS){ if(!strcmp(tokens->topic, "#") && !tokens->next){ if(branch->retained){ _retain_process(db, branch->retained, context, sub, sub_qos); } _retain_search(db, branch, tokens, context, sub, sub_qos); }else if(!strcmp(branch->topic, tokens->topic) || !strcmp(tokens->topic, "+")){ if(tokens->next){ _retain_search(db, branch, tokens->next, context, sub, sub_qos); }else{ if(branch->retained){ _retain_process(db, branch->retained, context, sub, sub_qos); } } } } branch = branch->next; } return MOSQ_ERR_SUCCESS; } int mqtt3_retain_queue(mosquitto_db *db, struct mosquitto *context, const char *sub, int sub_qos) { int rc = 0; int tree; struct _mosquitto_subhier *subhier; struct _sub_token *tokens = NULL, *tail; assert(db); assert(context); assert(sub); if(!strncmp(sub, "$SYS/", 5)){ tree = 2; if(_sub_topic_tokenise(sub+5, &tokens)) return 1; }else{ tree = 0; if(_sub_topic_tokenise(sub, &tokens)) return 1; } subhier = db->subs.children; while(subhier){ if(!strcmp(subhier->topic, "") && tree == 0){ rc = _retain_search(db, subhier, tokens, context, sub, sub_qos); break; }else if(!strcmp(subhier->topic, "$SYS") && tree == 2){ rc = _retain_search(db, subhier, tokens, context, sub, sub_qos); break; } subhier = subhier->next; } while(tokens){ tail = tokens->next; _mosquitto_free(tokens->topic); _mosquitto_free(tokens); tokens = tail; } return rc; } mosquitto-0.15/src/mosquitto.c0000664000175000017500000002204711713444064015533 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #ifndef WIN32 #include #else #include #include #include #endif #include #include #include #include #ifdef WITH_WRAP #include #endif #include #include mosquitto_db int_db; bool flag_reload = false; #ifdef WITH_PERSISTENCE bool flag_db_backup = false; #endif bool flag_tree_print = false; int run; #ifdef WITH_WRAP #include int allow_severity = LOG_INFO; int deny_severity = LOG_INFO; #endif int drop_privileges(mqtt3_config *config); void handle_sigint(int signal); void handle_sigusr1(int signal); void handle_sigusr2(int signal); /* mosquitto shouldn't run as root. * This function will attempt to change to an unprivileged user and group if * running as root. The user is given in config->user. * Returns 1 on failure (unknown user, setuid/setgid failure) * Returns 0 on success. * Note that setting config->user to "root" does not produce an error, but it * strongly discouraged. */ int drop_privileges(mqtt3_config *config) { #if !defined(__CYGWIN__) && !defined(WIN32) struct passwd *pwd; if(geteuid() == 0){ if(config->user){ pwd = getpwnam(config->user); if(!pwd){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid user '%s'.", config->user); return 1; } if(setgid(pwd->pw_gid) == -1){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); return 1; } if(setuid(pwd->pw_uid) == -1){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: %s.", strerror(errno)); return 1; } } if(geteuid() == 0 || getegid() == 0){ _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Mosquitto should not be run as root/administrator."); } } #endif return MOSQ_ERR_SUCCESS; } #ifdef SIGHUP /* Signal handler for SIGHUP - flag a config reload. */ void handle_sighup(int signal) { flag_reload = true; } #endif /* Signal handler for SIGINT and SIGTERM - just stop gracefully. */ void handle_sigint(int signal) { run = 0; } /* Signal handler for SIGUSR1 - backup the db. */ void handle_sigusr1(int signal) { #ifdef WITH_PERSISTENCE flag_db_backup = true; #endif } /* Signal handler for SIGUSR2 - vacuum the db. */ void handle_sigusr2(int signal) { flag_tree_print = true; } int main(int argc, char *argv[]) { int *listensock = NULL; int listensock_count = 0; int listensock_index = 0; mqtt3_config config; char buf[1024]; int i, j; FILE *pid; int listener_max; int rc; #if defined(WIN32) || defined(__CYGWIN__) if(argc == 2){ if(!strcmp(argv[1], "run")){ service_run(); return 0; }else if(!strcmp(argv[1], "install")){ service_install(); return 0; }else if(!strcmp(argv[1], "uninstall")){ service_uninstall(); return 0; } } #endif memset(&int_db, 0, sizeof(mosquitto_db)); _mosquitto_net_init(); mqtt3_config_init(&config); rc = mqtt3_config_parse_args(&config, argc, argv); if(rc != MOSQ_ERR_SUCCESS) return rc; int_db.config = &config; if(config.daemon){ #ifndef WIN32 switch(fork()){ case 0: break; case -1: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error in fork: %s", strerror(errno)); return 1; default: return MOSQ_ERR_SUCCESS; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Can't start in daemon mode in Windows."); #endif } if(config.daemon && config.pid_file){ pid = fopen(config.pid_file, "wt"); if(pid){ fprintf(pid, "%d", getpid()); fclose(pid); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to write pid file."); return 1; } } rc = drop_privileges(&config); if(rc != MOSQ_ERR_SUCCESS) return rc; rc = mqtt3_db_open(&config, &int_db); if(rc != MOSQ_ERR_SUCCESS){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Couldn't open database."); return rc; } /* Initialise logging only after initialising the database in case we're * logging to topics */ mqtt3_log_init(config.log_type, config.log_dest); _mosquitto_log_printf(NULL, MOSQ_LOG_INFO, "mosquitto version %s (build date %s) starting", VERSION, TIMESTAMP); rc = mosquitto_security_init(&int_db); if(rc) return rc; /* Set static $SYS messages */ snprintf(buf, 1024, "mosquitto version %s", VERSION); mqtt3_db_messages_easy_queue(&int_db, NULL, "$SYS/broker/version", 2, strlen(buf), (uint8_t *)buf, 1); snprintf(buf, 1024, "%s", TIMESTAMP); mqtt3_db_messages_easy_queue(&int_db, NULL, "$SYS/broker/timestamp", 2, strlen(buf), (uint8_t *)buf, 1); snprintf(buf, 1024, "%s", "$Revision: e745e1ab5007 $"); // Requires hg keyword extension. mqtt3_db_messages_easy_queue(&int_db, NULL, "$SYS/broker/changeset", 2, strlen(buf), (uint8_t *)buf, 1); listener_max = -1; listensock_index = 0; for(i=0; i listener_max){ listener_max = listensock[listensock_index]; } listensock_index++; } } signal(SIGINT, handle_sigint); signal(SIGTERM, handle_sigint); #ifdef SIGHUP signal(SIGHUP, handle_sighup); #endif #ifndef WIN32 signal(SIGUSR1, handle_sigusr1); signal(SIGUSR2, handle_sigusr2); signal(SIGPIPE, SIG_IGN); #endif #ifdef WITH_BRIDGE for(i=0; i 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WITH_BRIDGE int mqtt3_bridge_new(mosquitto_db *db, struct _mqtt3_bridge *bridge) { int i; struct mosquitto *new_context = NULL; struct mosquitto **tmp_contexts; char hostname[256]; int len; assert(db); assert(bridge); new_context = mqtt3_context_init(-1); if(!new_context){ return MOSQ_ERR_NOMEM; } new_context->bridge = bridge; for(i=0; icontext_count; i++){ if(db->contexts[i] == NULL){ db->contexts[i] = new_context; break; } } if(i==db->context_count){ 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; } } /* FIXME - need to check that this name isn't already in use. */ if(bridge->clientid){ new_context->id = _mosquitto_strdup(bridge->clientid); }else{ if(!gethostname(hostname, 256)){ len = strlen(hostname) + strlen(bridge->name) + 2; new_context->id = _mosquitto_malloc(len); if(!new_context->id){ return MOSQ_ERR_NOMEM; } snprintf(new_context->id, len, "%s.%s", hostname, bridge->name); }else{ return 1; } } if(!new_context->id){ _mosquitto_free(new_context); return MOSQ_ERR_NOMEM; } new_context->username = new_context->bridge->username; new_context->password = new_context->bridge->password; return mqtt3_bridge_connect(db, new_context); } int mqtt3_bridge_connect(mosquitto_db *db, struct mosquitto *context) { int rc; int i; char *notification_topic; int notification_topic_len; uint8_t notification_payload[2]; if(!context || !context->bridge) return MOSQ_ERR_INVAL; context->state = mosq_cs_new; context->sock = -1; context->last_msg_in = time(NULL); context->last_msg_out = time(NULL); context->keepalive = context->bridge->keepalive; context->clean_session = context->bridge->clean_session; context->in_packet.payload = NULL; mqtt3_bridge_packet_cleanup(context); for(i=0; ibridge->topic_count; i++){ if(context->bridge->topics[i].direction == bd_out || context->bridge->topics[i].direction == bd_both){ if(mqtt3_sub_add(context, context->bridge->topics[i].topic, context->bridge->topics[i].qos, &db->subs)) return 1; } } _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Connecting bridge %s", context->bridge->name); rc = _mosquitto_socket_connect(context, context->bridge->address, context->bridge->port); if(rc != MOSQ_ERR_SUCCESS){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge."); return rc; } if(context->bridge->notifications){ 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); notification_payload[0] = '0'; notification_payload[1] = '\0'; mqtt3_db_messages_easy_queue(db, context, notification_topic, 1, 2, (uint8_t *)¬ification_payload, 1); rc = _mosquitto_will_set(context, true, notification_topic, 2, (uint8_t *)¬ification_payload, 1, true); if(rc != MOSQ_ERR_SUCCESS){ _mosquitto_free(notification_topic); return rc; } _mosquitto_free(notification_topic); } return _mosquitto_send_connect(context, context->keepalive, context->clean_session); } void mqtt3_bridge_packet_cleanup(struct mosquitto *context) { struct _mosquitto_packet *packet; if(!context) return; 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 mosquitto-0.15/src/db_dump/0000775000175000017500000000000011713444064014730 5ustar rogerrogermosquitto-0.15/src/db_dump/db_dump.c0000664000175000017500000002451011713444064016510 0ustar rogerroger/* Copyright (c) 2010-2012 Roger Light 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. */ #include #include #include #include #include #include #include #include #include #include #include static int _db_client_chunk_restore(mosquitto_db *db, FILE *db_fd) { uint16_t i16temp, slen, last_mid; char *client_id = NULL; int rc = 0; read_e(db_fd, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); if(!slen){ fprintf(stderr, "Error: Corrupt persistent database."); fclose(db_fd); return 1; } client_id = calloc(slen+1, sizeof(char)); if(!client_id){ fclose(db_fd); fprintf(stderr, "Error: Out of memory."); return 1; } read_e(db_fd, client_id, slen); printf("\tClient ID: %s\n", client_id); read_e(db_fd, &i16temp, sizeof(uint16_t)); last_mid = ntohs(i16temp); printf("\tLast MID: %d\n", last_mid); free(client_id); return rc; error: fprintf(stderr, "Error: %s.", strerror(errno)); if(db_fd >= 0) fclose(db_fd); if(client_id) free(client_id); return 1; } static int _db_client_msg_chunk_restore(mosquitto_db *db, FILE *db_fd) { dbid_t i64temp, store_id; uint16_t i16temp, slen, mid; uint8_t qos, retain, direction, state, dup; char *client_id = NULL; read_e(db_fd, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); if(!slen){ fprintf(stderr, "Error: Corrupt persistent database."); fclose(db_fd); return 1; } client_id = calloc(slen+1, sizeof(char)); if(!client_id){ fclose(db_fd); fprintf(stderr, "Error: Out of memory."); return 1; } read_e(db_fd, client_id, slen); printf("\tClient ID: %s\n", client_id); read_e(db_fd, &i64temp, sizeof(dbid_t)); store_id = i64temp; printf("\tStore ID: %ld\n", (long )store_id); read_e(db_fd, &i16temp, sizeof(uint16_t)); mid = ntohs(i16temp); printf("\tMID: %d\n", mid); read_e(db_fd, &qos, sizeof(uint8_t)); printf("\tQoS: %d\n", mid); read_e(db_fd, &retain, sizeof(uint8_t)); printf("\tRetain: %d\n", mid); read_e(db_fd, &direction, sizeof(uint8_t)); printf("\tDirection: %d\n", mid); read_e(db_fd, &state, sizeof(uint8_t)); printf("\tState: %d\n", mid); read_e(db_fd, &dup, sizeof(uint8_t)); printf("\tDup: %d\n", mid); free(client_id); return 0; error: fprintf(stderr, "Error: %s.", strerror(errno)); if(db_fd >= 0) fclose(db_fd); if(client_id) free(client_id); return 1; } static int _db_msg_store_chunk_restore(mosquitto_db *db, FILE *db_fd) { dbid_t i64temp, store_id; uint32_t i32temp, payloadlen; uint16_t i16temp, slen, source_mid, mid; uint8_t qos, retain, *payload = NULL; char *source_id = NULL; char *topic = NULL; int rc = 0; bool binary; int i; read_e(db_fd, &i64temp, sizeof(dbid_t)); store_id = i64temp; printf("\tStore ID: %ld\n", (long)store_id); read_e(db_fd, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); if(slen){ source_id = calloc(slen+1, sizeof(char)); if(!source_id){ fclose(db_fd); fprintf(stderr, "Error: Out of memory."); return 1; } if(fread(source_id, 1, slen, db_fd) != slen){ fprintf(stderr, "Error: %s.", strerror(errno)); fclose(db_fd); free(source_id); return 1; } printf("\tSource ID: %s\n", source_id); free(source_id); } read_e(db_fd, &i16temp, sizeof(uint16_t)); source_mid = ntohs(i16temp); printf("\tSource MID: %d\n", source_mid); read_e(db_fd, &i16temp, sizeof(uint16_t)); mid = ntohs(i16temp); printf("\tMID: %d\n", source_mid); read_e(db_fd, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); if(slen){ topic = calloc(slen+1, sizeof(char)); if(!topic){ fclose(db_fd); free(source_id); fprintf(stderr, "Error: Out of memory."); return 1; } if(fread(topic, 1, slen, db_fd) != slen){ fprintf(stderr, "Error: %s.", strerror(errno)); fclose(db_fd); free(source_id); free(topic); return 1; } printf("\tTopic: %s\n", topic); free(topic); }else{ fprintf(stderr, "Error: Invalid msg_store chunk when restoring persistent database."); fclose(db_fd); free(source_id); return 1; } read_e(db_fd, &qos, sizeof(uint8_t)); printf("\tQoS: %d\n", qos); read_e(db_fd, &retain, sizeof(uint8_t)); printf("\tRetain: %d\n", retain); read_e(db_fd, &i32temp, sizeof(uint32_t)); payloadlen = ntohl(i32temp); printf("\tPayload Length: %d\n", payloadlen); if(payloadlen){ payload = malloc(payloadlen+1); if(!payload){ fclose(db_fd); free(source_id); free(topic); fprintf(stderr, "Error: Out of memory."); return 1; } memset(payload, 0, payloadlen+1); if(fread(payload, 1, payloadlen, db_fd) != payloadlen){ fprintf(stderr, "Error: %s.", strerror(errno)); fclose(db_fd); free(source_id); free(topic); free(payload); return 1; } binary = false; for(i=0; i= 0) fclose(db_fd); if(source_id) free(source_id); if(topic) free(topic); return 1; } static int _db_retain_chunk_restore(mosquitto_db *db, FILE *db_fd) { dbid_t i64temp, store_id; if(fread(&i64temp, sizeof(dbid_t), 1, db_fd) != sizeof(dbid_t)){ fprintf(stderr, "Error: %s.", strerror(errno)); fclose(db_fd); return 1; } store_id = i64temp; printf("\tStore ID: %ld\n", (long int)store_id); return 0; } static int _db_sub_chunk_restore(mosquitto_db *db, FILE *db_fd) { uint16_t i16temp, slen; uint8_t qos; char *client_id; char *topic; int rc = 0; read_e(db_fd, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); client_id = calloc(slen+1, sizeof(char)); if(!client_id){ fclose(db_fd); fprintf(stderr, "Error: Out of memory."); return 1; } read_e(db_fd, client_id, slen); printf("\tClient ID: %s\n", client_id); read_e(db_fd, &i16temp, sizeof(uint16_t)); slen = ntohs(i16temp); topic = calloc(slen+1, sizeof(char)); if(!topic){ fclose(db_fd); fprintf(stderr, "Error: Out of memory."); free(client_id); return 1; } read_e(db_fd, topic, slen); printf("\tTopic: %s\n", client_id); read_e(db_fd, &qos, sizeof(uint8_t)); printf("\tQoS: %d\n", qos); free(client_id); free(topic); return rc; error: fprintf(stderr, "Error: %s.", strerror(errno)); if(db_fd >= 0) fclose(db_fd); return 1; } int main(int argc, char *argv[]) { FILE *fd; char header[15]; int rc = 0; uint32_t crc, db_version; dbid_t i64temp; uint32_t i32temp, length; uint16_t i16temp, chunk; uint8_t i8temp; ssize_t rlen; mosquitto_db db; if(argc != 2){ fprintf(stderr, "Usage: db_dump \n"); return 1; } memset(&db, 0, sizeof(mosquitto_db)); fd = fopen(argv[1], "rb"); if(!fd) return 0; read_e(fd, &header, 15); if(!memcmp(header, magic, 15)){ printf("Mosquitto DB dump\n"); // Restore DB as normal read_e(fd, &crc, sizeof(uint32_t)); printf("CRC: %d\n", crc); read_e(fd, &i32temp, sizeof(uint32_t)); db_version = ntohl(i32temp); printf("DB version: %d\n", db_version); while(rlen = fread(&i16temp, sizeof(uint16_t), 1, fd), rlen == 1){ chunk = ntohs(i16temp); read_e(fd, &i32temp, sizeof(uint32_t)); length = ntohl(i32temp); switch(chunk){ case DB_CHUNK_CFG: printf("DB_CHUNK_CFG:\n"); printf("\tLength: %d\n", length); read_e(fd, &i8temp, sizeof(uint8_t)); // shutdown printf("\tShutdown: %d\n", i8temp); read_e(fd, &i8temp, sizeof(uint8_t)); // sizeof(dbid_t) printf("\tDB ID size: %d\n", i8temp); if(i8temp != sizeof(dbid_t)){ fprintf(stderr, "Error: Incompatible database configuration (dbid size is %d bytes, expected %d)", i8temp, sizeof(dbid_t)); fclose(fd); return 1; } read_e(fd, &i64temp, sizeof(dbid_t)); printf("\tLast DB ID: %ld\n", (long)i64temp); break; case DB_CHUNK_MSG_STORE: printf("DB_CHUNK_MSG_STORE:\n"); printf("\tLength: %d\n", length); if(_db_msg_store_chunk_restore(&db, fd)) return 1; break; case DB_CHUNK_CLIENT_MSG: printf("DB_CHUNK_CLIENT_MSG:\n"); printf("\tLength: %d\n", length); if(_db_client_msg_chunk_restore(&db, fd)) return 1; break; case DB_CHUNK_RETAIN: printf("DB_CHUNK_RETAIN:\n"); printf("\tLength: %d\n", length); if(_db_retain_chunk_restore(&db, fd)) return 1; break; case DB_CHUNK_SUB: printf("DB_CHUNK_SUB:\n"); printf("\tLength: %d\n", length); if(_db_sub_chunk_restore(&db, fd)) return 1; break; case DB_CHUNK_CLIENT: printf("DB_CHUNK_CLIENT:\n"); printf("\tLength: %d\n", length); if(_db_client_chunk_restore(&db, fd)) return 1; break; default: fprintf(stderr, "Warning: Unsupported chunk \"%d\" in persistent database file. Ignoring.", chunk); fseek(fd, length, SEEK_CUR); break; } } if(rlen < 0) goto error; }else{ fprintf(stderr, "Error: Unrecognised file format."); rc = 1; } fclose(fd); return rc; error: fprintf(stderr, "Error: %s.", strerror(errno)); if(fd >= 0) fclose(fd); return 1; } mosquitto-0.15/src/db_dump/Makefile0000664000175000017500000000046211713444064016372 0ustar rogerrogerinclude ../../config.mk CFLAGS_FINAL=${CFLAGS} -I.. -I../../lib -I../.. .PHONY: all clean reallyclean all : mosquitto_db_dump mosquitto_db_dump : db_dump.o ${CC} $^ -o $@ ${LDFLAGS} ${LIBS} db_dump.o : db_dump.c ../persist.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ clean : -rm -f *.o mosquitto_db_dump mosquitto-0.15/src/conf.c0000664000175000017500000010627311713444064014420 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #include #include #include #include #include static int _conf_parse_bool(char **token, const char *name, bool *value); static int _conf_parse_int(char **token, const char *name, int *value); static int _conf_parse_string(char **token, const char *name, char **value); static void _config_init_reload(mqtt3_config *config) { /* Set defaults */ if(config->acl_file) _mosquitto_free(config->acl_file); config->acl_file = NULL; config->allow_anonymous = true; config->autosave_interval = 1800; if(config->clientid_prefixes) _mosquitto_free(config->clientid_prefixes); config->connection_messages = true; config->clientid_prefixes = NULL; #ifndef WIN32 config->log_dest = MQTT3_LOG_STDERR; config->log_type = MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE | MOSQ_LOG_INFO; #else config->log_dest = MQTT3_LOG_SYSLOG; config->log_type = MOSQ_LOG_ERR | MOSQ_LOG_WARNING; #endif config->log_timestamp = true; if(config->password_file) _mosquitto_free(config->password_file); config->password_file = NULL; config->persistence = false; if(config->persistence_location) _mosquitto_free(config->persistence_location); config->persistence_location = NULL; if(config->persistence_file) _mosquitto_free(config->persistence_file); config->persistence_file = NULL; config->retry_interval = 20; config->store_clean_interval = 10; config->sys_interval = 10; #ifdef WITH_EXTERNAL_SECURITY_CHECKS if(config->db_host) _mosquitto_free(config->db_host); config->db_host = NULL; config->db_port = 0; if(config->db_name) _mosquitto_free(config->db_name); config->db_name = NULL; if(config->db_username) _mosquitto_free(config->db_username); config->db_username = NULL; if(config->db_password) _mosquitto_free(config->db_password); config->db_password = NULL; #endif } void mqtt3_config_init(mqtt3_config *config) { memset(config, 0, sizeof(mqtt3_config)); _config_init_reload(config); config->config_file = NULL; config->daemon = false; config->default_listener.host = NULL; config->default_listener.port = 0; config->default_listener.max_connections = -1; config->default_listener.mount_point = NULL; config->default_listener.socks = NULL; config->default_listener.sock_count = 0; config->default_listener.client_count = 0; config->listeners = NULL; config->listener_count = 0; config->pid_file = NULL; config->user = NULL; #ifdef WITH_BRIDGE config->bridges = NULL; config->bridge_count = 0; #endif } void mqtt3_config_cleanup(mqtt3_config *config) { int i, j; if(config->acl_file) _mosquitto_free(config->acl_file); if(config->clientid_prefixes) _mosquitto_free(config->clientid_prefixes); if(config->config_file) _mosquitto_free(config->config_file); if(config->password_file) _mosquitto_free(config->password_file); if(config->persistence_location) _mosquitto_free(config->persistence_location); if(config->persistence_file) _mosquitto_free(config->persistence_file); if(config->persistence_filepath) _mosquitto_free(config->persistence_filepath); if(config->listeners){ for(i=0; ilistener_count; i++){ if(config->listeners[i].host) _mosquitto_free(config->listeners[i].host); if(config->listeners[i].mount_point) _mosquitto_free(config->listeners[i].mount_point); if(config->listeners[i].socks) _mosquitto_free(config->listeners[i].socks); } _mosquitto_free(config->listeners); } #ifdef WITH_BRIDGE if(config->bridges){ for(i=0; ibridge_count; i++){ if(config->bridges[i].name) _mosquitto_free(config->bridges[i].name); if(config->bridges[i].address) _mosquitto_free(config->bridges[i].address); if(config->bridges[i].clientid) _mosquitto_free(config->bridges[i].clientid); if(config->bridges[i].username) _mosquitto_free(config->bridges[i].username); if(config->bridges[i].password) _mosquitto_free(config->bridges[i].password); if(config->bridges[i].topics){ for(j=0; jbridges[i].topic_count; j++){ if(config->bridges[i].topics[j].topic) _mosquitto_free(config->bridges[i].topics[j].topic); } _mosquitto_free(config->bridges[i].topics); } } _mosquitto_free(config->bridges); } #endif #ifdef WITH_EXTERNAL_SECURITY_CHECKS if(config->db_host) _mosquitto_free(config->db_host); if(config->db_name) _mosquitto_free(config->db_name); if(config->db_username) _mosquitto_free(config->db_username); if(config->db_password) _mosquitto_free(config->db_password); #endif } static void print_usage(void) { printf("mosquitto is an MQTT v3.1 broker.\n\n"); printf("Usage: mosquitto [-c config_file] [-d] [-h] [-p port]\n\n"); printf(" -c : specify the broker config file.\n"); printf(" -d : put the broker into the background after starting.\n"); printf(" -h : display this help.\n"); printf(" -p : start the broker listening on the specified port.\n"); printf(" Not recommended in conjunction with the -c option.\n"); printf("\nSee http://mosquitto.org/ for more information.\n\n"); } int mqtt3_config_parse_args(mqtt3_config *config, int argc, char *argv[]) { int i; int port_tmp; for(i=1; iconfig_file = _mosquitto_strdup(argv[i+1]); if(!config->config_file){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } if(mqtt3_config_read(config, false)){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open configuration file."); return MOSQ_ERR_INVAL; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: -c argument given, but no config file specified."); return MOSQ_ERR_INVAL; } i++; }else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--daemon")){ config->daemon = true; }else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")){ print_usage(); return MOSQ_ERR_INVAL; }else if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port")){ if(i65535){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid port specified (%d).", port_tmp); return MOSQ_ERR_INVAL; }else{ if(config->default_listener.port){ _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Default listener port specified multiple times. Only the latest will be used."); } config->default_listener.port = port_tmp; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: -p argument given, but no port specified."); return MOSQ_ERR_INVAL; } i++; }else{ fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]); print_usage(); return MOSQ_ERR_INVAL; } } if(config->listener_count == 0 || config->default_listener.host || config->default_listener.port){ config->listener_count++; config->listeners = _mosquitto_realloc(config->listeners, sizeof(struct _mqtt3_listener)*config->listener_count); if(!config->listeners){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } if(config->default_listener.port){ config->listeners[config->listener_count-1].port = config->default_listener.port; }else{ config->listeners[config->listener_count-1].port = 1883; } if(config->default_listener.host){ config->listeners[config->listener_count-1].host = config->default_listener.host; }else{ config->listeners[config->listener_count-1].host = NULL; } if(config->default_listener.mount_point){ config->listeners[config->listener_count-1].mount_point = config->default_listener.host; }else{ config->listeners[config->listener_count-1].mount_point = NULL; } config->listeners[config->listener_count-1].max_connections = config->default_listener.max_connections; config->listeners[config->listener_count-1].client_count = 0; config->listeners[config->listener_count-1].socks = NULL; config->listeners[config->listener_count-1].sock_count = 0; config->listeners[config->listener_count-1].client_count = 0; } return MOSQ_ERR_SUCCESS; } int mqtt3_config_read(mqtt3_config *config, bool reload) { int rc = MOSQ_ERR_SUCCESS; FILE *fptr = NULL; char buf[1024]; char *token; int port_tmp; int log_dest = MQTT3_LOG_NONE; int log_dest_set = 0; int log_type = MOSQ_LOG_NONE; int log_type_set = 0; int i; #ifdef WITH_BRIDGE struct _mqtt3_bridge *cur_bridge = NULL; #endif int max_inflight_messages = 20; int max_queued_messages = 100; if(!config->config_file) return 0; if(reload){ /* Re-initialise appropriate config vars to default for reload. */ _config_init_reload(config); } fptr = fopen(config->config_file, "rt"); if(!fptr) return 1; while(fgets(buf, 1024, fptr)){ if(buf[0] != '#' && buf[0] != 10 && buf[0] != 13){ while(buf[strlen(buf)-1] == 10 || buf[strlen(buf)-1] == 13){ buf[strlen(buf)-1] = 0; } token = strtok(buf, " "); if(token){ if(!strcmp(token, "acl_file")){ if(reload){ if(config->acl_file){ _mosquitto_free(config->acl_file); config->acl_file = NULL; } } if(_conf_parse_string(&token, "acl_file", &config->acl_file)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "address") || !strcmp(token, "addresses")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge || cur_bridge->address){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } token = strtok(NULL, " "); if(token){ token = strtok(token, ":"); if(token){ cur_bridge->address = _mosquitto_strdup(token); if(!cur_bridge->address){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } token = strtok(NULL, ":"); if(token){ port_tmp = atoi(token); if(port_tmp < 1 || port_tmp > 65535){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid port value (%d).", port_tmp); return MOSQ_ERR_INVAL; } cur_bridge->port = port_tmp; }else{ cur_bridge->port = 1883; } } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty address value in configuration."); return MOSQ_ERR_INVAL; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "allow_anonymous")){ if(_conf_parse_bool(&token, "allow_anonymous", &config->allow_anonymous)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "autosave_interval")){ if(_conf_parse_int(&token, "autosave_interval", &config->autosave_interval)) return MOSQ_ERR_INVAL; if(config->autosave_interval < 0) config->autosave_interval = 0; }else if(!strcmp(token, "bind_address")){ if(reload) continue; // Listener not valid for reloading. if(_conf_parse_string(&token, "default listener bind_address", &config->default_listener.host)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "clientid")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } token = strtok(NULL, " "); if(token){ if(cur_bridge->clientid){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Duplicate clientid value in bridge configuration."); return MOSQ_ERR_INVAL; } cur_bridge->clientid = _mosquitto_strdup(token); if(!cur_bridge->clientid){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory"); return MOSQ_ERR_NOMEM; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty clientid value in configuration."); return MOSQ_ERR_INVAL; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "cleansession")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } if(_conf_parse_bool(&token, "cleansession", &cur_bridge->clean_session)) return MOSQ_ERR_INVAL; #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "clientid_prefixes")){ if(reload){ if(config->clientid_prefixes){ _mosquitto_free(config->clientid_prefixes); config->clientid_prefixes = NULL; } } if(_conf_parse_string(&token, "clientid_prefixes", &config->clientid_prefixes)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "connection")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME token = strtok(NULL, " "); if(token){ config->bridge_count++; config->bridges = _mosquitto_realloc(config->bridges, config->bridge_count*sizeof(struct _mqtt3_bridge)); if(!config->bridges){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } cur_bridge = &(config->bridges[config->bridge_count-1]); cur_bridge->name = _mosquitto_strdup(token); cur_bridge->address = NULL; cur_bridge->keepalive = 60; cur_bridge->clean_session = false; cur_bridge->clientid = NULL; cur_bridge->port = 0; cur_bridge->topics = NULL; cur_bridge->topic_count = 0; cur_bridge->restart_t = 0; cur_bridge->username = NULL; cur_bridge->password = NULL; cur_bridge->notifications = true; cur_bridge->start_type = bst_automatic; cur_bridge->idle_timeout = 60; cur_bridge->threshold = 10; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty connection value in configuration."); return MOSQ_ERR_INVAL; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "connection_messages")){ if(_conf_parse_bool(&token, token, &config->connection_messages)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "idle_timeout")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } if(_conf_parse_int(&token, "idle_timeout", &cur_bridge->idle_timeout)) return MOSQ_ERR_INVAL; if(cur_bridge->idle_timeout < 1){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "idle_timeout interval too low, using 1 second."); cur_bridge->idle_timeout = 1; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "keepalive_interval")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } if(_conf_parse_int(&token, "keepalive_interval", &cur_bridge->keepalive)) return MOSQ_ERR_INVAL; if(cur_bridge->keepalive < 5){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "keepalive interval too low, using 5 seconds."); cur_bridge->keepalive = 5; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "listener")){ if(reload) continue; // Listeners not valid for reloading. token = strtok(NULL, " "); if(token){ config->listener_count++; config->listeners = _mosquitto_realloc(config->listeners, sizeof(struct _mqtt3_listener)*config->listener_count); if(!config->listeners){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return MOSQ_ERR_NOMEM; } port_tmp = atoi(token); if(port_tmp < 1 || port_tmp > 65535){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid port value (%d).", port_tmp); return MOSQ_ERR_INVAL; } config->listeners[config->listener_count-1].mount_point = NULL; config->listeners[config->listener_count-1].port = port_tmp; config->listeners[config->listener_count-1].socks = NULL; config->listeners[config->listener_count-1].sock_count = 0; config->listeners[config->listener_count-1].client_count = 0; token = strtok(NULL, " "); if(token){ config->listeners[config->listener_count-1].host = _mosquitto_strdup(token); }else{ config->listeners[config->listener_count-1].host = NULL; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty listener value in configuration."); return MOSQ_ERR_INVAL; } }else if(!strcmp(token, "log_dest")){ token = strtok(NULL, " "); if(token){ log_dest_set = 1; if(!strcmp(token, "none")){ log_dest = MQTT3_LOG_NONE; }else if(!strcmp(token, "syslog")){ log_dest |= MQTT3_LOG_SYSLOG; }else if(!strcmp(token, "stdout")){ log_dest |= MQTT3_LOG_STDOUT; }else if(!strcmp(token, "stderr")){ log_dest |= MQTT3_LOG_STDERR; }else if(!strcmp(token, "topic")){ log_dest |= MQTT3_LOG_TOPIC; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid log_dest value (%s).", token); return MOSQ_ERR_INVAL; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty log_dest value in configuration."); return MOSQ_ERR_INVAL; } }else if(!strcmp(token, "log_timestamp")){ if(_conf_parse_bool(&token, token, &config->log_timestamp)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "log_type")){ token = strtok(NULL, " "); if(token){ log_type_set = 1; if(!strcmp(token, "none")){ log_type = MOSQ_LOG_NONE; }else if(!strcmp(token, "information")){ log_type |= MOSQ_LOG_INFO; }else if(!strcmp(token, "notice")){ log_type |= MOSQ_LOG_NOTICE; }else if(!strcmp(token, "warning")){ log_type |= MOSQ_LOG_WARNING; }else if(!strcmp(token, "error")){ log_type |= MOSQ_LOG_ERR; }else if(!strcmp(token, "debug")){ log_type |= MOSQ_LOG_DEBUG; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid log_type value (%s).", token); return MOSQ_ERR_INVAL; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty log_type value in configuration."); } }else if(!strcmp(token, "max_connections")){ if(reload) continue; // Listeners not valid for reloading. token = strtok(NULL, " "); if(token){ if(config->listener_count > 0){ config->listeners[config->listener_count-1].max_connections = atoi(token); if(config->listeners[config->listener_count-1].max_connections < 0) config->listeners[config->listener_count-1].max_connections = -1; }else{ config->default_listener.max_connections = atoi(token); if(config->default_listener.max_connections < 0) config->default_listener.max_connections = -1; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty max_connections value in configuration."); } }else if(!strcmp(token, "max_inflight_messages")){ token = strtok(NULL, " "); if(token){ max_inflight_messages = atoi(token); if(max_inflight_messages < 0) max_inflight_messages = 0; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty max_inflight_messages value in configuration."); } }else if(!strcmp(token, "max_queued_messages")){ token = strtok(NULL, " "); if(token){ max_queued_messages = atoi(token); if(max_queued_messages < 0) max_queued_messages = 0; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty max_queued_messages value in configuration."); } }else if(!strcmp(token, "mount_point")){ if(reload) continue; // Listeners not valid for reloading. if(config->listener_count == 0){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: You must use create a listener before using the mount_point option in the configuration file."); return MOSQ_ERR_INVAL; } if(_conf_parse_string(&token, "mount_point", &config->listeners[config->listener_count-1].mount_point)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "notifications")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } if(_conf_parse_bool(&token, "notifications", &cur_bridge->notifications)) return MOSQ_ERR_INVAL; #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "password")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } token = strtok(NULL, " "); if(token){ if(cur_bridge->password){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Duplicate password value in bridge configuration."); return MOSQ_ERR_INVAL; } cur_bridge->password = _mosquitto_strdup(token); if(!cur_bridge->password){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory"); return MOSQ_ERR_NOMEM; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty password value in configuration."); return MOSQ_ERR_INVAL; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "password_file")){ if(reload){ if(config->password_file){ _mosquitto_free(config->password_file); config->password_file = NULL; } } if(_conf_parse_string(&token, "password_file", &config->password_file)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "persistence") || !strcmp(token, "retained_persistence")){ if(_conf_parse_bool(&token, token, &config->persistence)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "persistence_file")){ if(reload) continue; // FIXME if(_conf_parse_string(&token, "persistence_file", &config->persistence_file)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "persistence_location")){ if(reload) continue; // FIXME if(_conf_parse_string(&token, "persistence_location", &config->persistence_location)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "pid_file")){ if(reload) continue; // pid file not valid for reloading. if(_conf_parse_string(&token, "pid_file", &config->pid_file)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "port")){ if(reload) continue; // Listener not valid for reloading. if(config->default_listener.port){ _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Default listener port specified multiple times. Only the latest will be used."); } if(_conf_parse_int(&token, "port", &port_tmp)) return MOSQ_ERR_INVAL; if(port_tmp < 1 || port_tmp > 65535){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid port value (%d).", port_tmp); return MOSQ_ERR_INVAL; } config->default_listener.port = port_tmp; }else if(!strcmp(token, "retry_interval")){ if(_conf_parse_int(&token, "retry_interval", &config->retry_interval)) return MOSQ_ERR_INVAL; if(config->retry_interval < 1 || config->retry_interval > 3600){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid retry_interval value (%d).", config->retry_interval); return MOSQ_ERR_INVAL; } }else if(!strcmp(token, "start_type")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } token = strtok(NULL, " "); if(token){ if(!strcmp(token, "automatic")){ cur_bridge->start_type = bst_automatic; }else if(!strcmp(token, "lazy")){ cur_bridge->start_type = bst_lazy; }else if(!strcmp(token, "manual")){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Manual start_type not supported."); return MOSQ_ERR_INVAL; }else if(!strcmp(token, "once")){ cur_bridge->start_type = bst_once; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid start_type value in configuration (%s).", token); return MOSQ_ERR_INVAL; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty start_type value in configuration."); return MOSQ_ERR_INVAL; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "store_clean_interval")){ if(_conf_parse_int(&token, "store_clean_interval", &config->store_clean_interval)) return MOSQ_ERR_INVAL; if(config->store_clean_interval < 0 || config->store_clean_interval > 65535){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid store_clean_interval value (%d).", config->store_clean_interval); return MOSQ_ERR_INVAL; } }else if(!strcmp(token, "sys_interval")){ if(_conf_parse_int(&token, "sys_interval", &config->sys_interval)) return MOSQ_ERR_INVAL; if(config->sys_interval < 1 || config->sys_interval > 65535){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid sys_interval value (%d).", config->sys_interval); return MOSQ_ERR_INVAL; } }else if(!strcmp(token, "threshold")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } if(_conf_parse_int(&token, "threshold", &cur_bridge->threshold)) return MOSQ_ERR_INVAL; if(cur_bridge->threshold < 1){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "threshold too low, using 1 message."); cur_bridge->threshold = 1; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "topic")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } token = strtok(NULL, " "); if(token){ cur_bridge->topic_count++; cur_bridge->topics = _mosquitto_realloc(cur_bridge->topics, sizeof(struct _mqtt3_bridge_topic)*cur_bridge->topic_count); if(!cur_bridge->topics){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory"); return MOSQ_ERR_NOMEM; } cur_bridge->topics[cur_bridge->topic_count-1].topic = _mosquitto_strdup(token); if(!cur_bridge->topics[cur_bridge->topic_count-1].topic){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory"); return MOSQ_ERR_NOMEM; } cur_bridge->topics[cur_bridge->topic_count-1].direction = bd_out; cur_bridge->topics[cur_bridge->topic_count-1].qos = 2; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty topic value in configuration."); return MOSQ_ERR_INVAL; } token = strtok(NULL, " "); if(token){ if(!strcasecmp(token, "out")){ cur_bridge->topics[cur_bridge->topic_count-1].direction = bd_out; }else if(!strcasecmp(token, "in")){ cur_bridge->topics[cur_bridge->topic_count-1].direction = bd_in; }else if(!strcasecmp(token, "both")){ cur_bridge->topics[cur_bridge->topic_count-1].direction = bd_both; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge topic direction '%s'.", token); return MOSQ_ERR_INVAL; } token = strtok(NULL, " "); if(token){ cur_bridge->topics[cur_bridge->topic_count-1].qos = atoi(token); if(cur_bridge->topics[cur_bridge->topic_count-1].qos < 0 || cur_bridge->topics[cur_bridge->topic_count-1].qos > 2){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge QoS level '%s'.", token); return MOSQ_ERR_INVAL; } } } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif }else if(!strcmp(token, "user")){ if(reload) continue; // Drop privileges user not valid for reloading. if(_conf_parse_string(&token, "user", &config->user)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "username")){ #ifdef WITH_BRIDGE if(reload) continue; // FIXME if(!cur_bridge){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } token = strtok(NULL, " "); if(token){ if(cur_bridge->username){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Duplicate username value in bridge configuration."); return MOSQ_ERR_INVAL; } cur_bridge->username = _mosquitto_strdup(token); if(!cur_bridge->username){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory"); return MOSQ_ERR_NOMEM; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty username value in configuration."); return MOSQ_ERR_INVAL; } #else _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); #endif #ifdef WITH_EXTERNAL_SECURITY_CHECKS }else if(!strcmp(token, "db_host")){ if(reload){ if(config->db_host){ _mosquitto_free(config->db_host); config->db_host = NULL; } } if(_conf_parse_string(&token, "db_host", &config->db_host)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "db_name")){ if(reload){ if(config->db_name){ _mosquitto_free(config->db_name); config->db_name = NULL; } } if(_conf_parse_string(&token, "db_name", &config->db_name)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "db_username")){ if(reload){ if(config->db_username){ _mosquitto_free(config->db_username); config->db_username = NULL; } } if(_conf_parse_string(&token, "db_username", &config->db_username)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "db_password")){ if(reload){ if(config->db_password){ _mosquitto_free(config->db_password); config->db_password = NULL; } } if(_conf_parse_string(&token, "db_password", &config->db_password)) return MOSQ_ERR_INVAL; }else if(!strcmp(token, "db_port")){ if(_conf_parse_int(&token, "db_port", &config->db_port)) return MOSQ_ERR_INVAL; #endif }else if(!strcmp(token, "autosave_on_changes") || !strcmp(token, "connection_messages") || !strcmp(token, "trace_level") || !strcmp(token, "addresses") || !strcmp(token, "idle_timeout") || !strcmp(token, "notification_topic") || !strcmp(token, "round_robin") || !strcmp(token, "threshold") || !strcmp(token, "try_private") || !strcmp(token, "ffdc_output") || !strcmp(token, "max_log_entries") || !strcmp(token, "trace_output")){ _mosquitto_log_printf(NULL, MOSQ_LOG_WARNING, "Warning: Unsupported rsmb configuration option \"%s\".", token); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Unknown configuration variable \"%s\".", token); return MOSQ_ERR_INVAL; } } } } fclose(fptr); #ifdef WITH_PERSISTENCE if(config->persistence){ if(!config->persistence_file){ config->persistence_file = _mosquitto_strdup("mosquitto.db"); if(!config->persistence_file) return MOSQ_ERR_NOMEM; } if(config->persistence_filepath){ _mosquitto_free(config->persistence_filepath); } if(config->persistence_location && strlen(config->persistence_location)){ config->persistence_filepath = _mosquitto_malloc(strlen(config->persistence_location) + strlen(config->persistence_file) + 1); if(!config->persistence_filepath) return MOSQ_ERR_NOMEM; sprintf(config->persistence_filepath, "%s%s", config->persistence_location, config->persistence_file); }else{ config->persistence_filepath = _mosquitto_strdup(config->persistence_file); if(!config->persistence_filepath) return MOSQ_ERR_NOMEM; } } #endif if(!config->user){ config->user = "mosquitto"; } mqtt3_db_limits_set(max_inflight_messages, max_queued_messages); #ifdef WITH_BRIDGE for(i=0; ibridge_count; i++){ if(!config->bridges[i].name || !config->bridges[i].address || !config->bridges[i].port || !config->bridges[i].topic_count){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration."); return MOSQ_ERR_INVAL; } } #endif if(log_dest_set){ config->log_dest = log_dest; } if(log_type_set){ config->log_type = log_type; } return rc; } static int _conf_parse_bool(char **token, const char *name, bool *value) { *token = strtok(NULL, " "); if(*token){ if(!strcmp(*token, "false") || !strcmp(*token, "0")){ *value = false; }else if(!strcmp(*token, "true") || !strcmp(*token, "1")){ *value = true; }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid %s value (%s).", name, *token); } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty %s value in configuration.", name); return MOSQ_ERR_INVAL; } return MOSQ_ERR_SUCCESS; } static int _conf_parse_int(char **token, const char *name, int *value) { *token = strtok(NULL, " "); if(*token){ *value = atoi(*token); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty %s value in configuration.", name); return MOSQ_ERR_INVAL; } return MOSQ_ERR_SUCCESS; } static int _conf_parse_string(char **token, const char *name, char **value) { *token = strtok(NULL, " "); if(*token){ if(*value){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Duplicate %s value in configuration.", name); return MOSQ_ERR_INVAL; } *value = _mosquitto_strdup(*token); if(!*value){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory"); return MOSQ_ERR_NOMEM; } }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Empty %s value in configuration.", name); return MOSQ_ERR_INVAL; } return MOSQ_ERR_SUCCESS; } mosquitto-0.15/src/Makefile0000664000175000017500000000510611713444064014760 0ustar rogerrogerinclude ../config.mk CFLAGS_FINAL=${CFLAGS} -I. -DVERSION="\"${VERSION}\"" -DTIMESTAMP="\"${TIMESTAMP}\"" -DWITH_BROKER .PHONY: all install uninstall clean reallyclean all : mosquitto 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_external.o send_client_mosq.o send_mosq.o send_server.o service.o subs.o util_mosq.o will_mosq.o ${CC} $^ -o $@ ${LDFLAGS} ${LIBS} mosquitto.o : mosquitto.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ bridge.o : bridge.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ conf.o : conf.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ context.o : context.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ database.o : database.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ logging.o : logging.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ loop.o : loop.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ memory_mosq.o : ../lib/memory_mosq.c ../lib/memory_mosq.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ net.o : net.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ net_mosq.o : ../lib/net_mosq.c ../lib/net_mosq.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ persist.o : persist.c persist.h mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ read_handle.o : read_handle.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ read_handle_client.o : read_handle_client.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ read_handle_server.o : read_handle_server.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ read_handle_shared.o : ../lib/read_handle_shared.c ../lib/read_handle.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ security.o : security.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ security_external.o : security_external.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ send_client_mosq.o : ../lib/send_client_mosq.c ../lib/send_mosq.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ send_mosq.o : ../lib/send_mosq.c ../lib/send_mosq.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ send_server.o : send_server.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ service.o : service.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ subs.o : subs.c mqtt3.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ util_mosq.o : ../lib/util_mosq.c ../lib/util_mosq.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ will_mosq.o : ../lib/will_mosq.c ../lib/will_mosq.h ${CC} $(CFLAGS_FINAL) -c $< -o $@ install : all $(INSTALL) -d ${DESTDIR}$(prefix)/sbin $(INSTALL) -s mosquitto ${DESTDIR}${prefix}/sbin/mosquitto uninstall : -rm -f ${DESTDIR}${prefix}/sbin/mosquitto clean : -rm -f *.o mosquitto reallyclean : clean -rm -rf *.orig *.db mosquitto-0.15/src/security_external.c0000664000175000017500000000432011713444064017232 0ustar rogerroger/* Copyright (c) 2011,2012 Roger Light 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. */ #ifndef CMAKE #include #endif #include #include #include #include #ifdef WITH_EXTERNAL_SECURITY_CHECKS int mosquitto_acl_init(struct _mosquitto_db *db) { return MOSQ_ERR_SUCCESS; } int mosquitto_acl_check(struct _mosquitto_db *db, struct mosquitto *context, const char *topic, int access) { return MOSQ_ERR_ACL_DENIED; } void mosquitto_acl_cleanup(struct _mosquitto_db *db) { } int mosquitto_unpwd_init(struct _mosquitto_db *db) { return MOSQ_ERR_SUCCESS; } int mosquitto_unpwd_check(struct _mosquitto_db *db, const char *username, const char *password) { return MOSQ_ERR_AUTH; } int mosquitto_unpwd_cleanup(struct _mosquitto_db *db) { return MOSQ_ERR_SUCCESS; } #endif mosquitto-0.15/src/persist.h0000664000175000017500000000371311713444064015164 0ustar rogerroger/* Copyright (c) 2010,2011 Roger Light 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. */ #ifndef PERSIST_H #define PERSIST_H /* DB read/write */ const unsigned char magic[15] = {0x00, 0xB5, 0x00, 'm','o','s','q','u','i','t','t','o',' ','d','b'}; #define DB_CHUNK_CFG 1 #define DB_CHUNK_MSG_STORE 2 #define DB_CHUNK_CLIENT_MSG 3 #define DB_CHUNK_RETAIN 4 #define DB_CHUNK_SUB 5 #define DB_CHUNK_CLIENT 6 /* End DB read/write */ #define read_e(f, b, c) if(fread(b, 1, c, f) != c){ goto error; } #define write_e(f, b, c) if(fwrite(b, 1, c, f) != c){ goto error; } #endif mosquitto-0.15/misc/0000775000175000017500000000000011713444064013462 5ustar rogerrogermosquitto-0.15/misc/currentcost/0000775000175000017500000000000011713444064016035 5ustar rogerrogermosquitto-0.15/misc/currentcost/cc128_read.py0000775000175000017500000000067711713444064020237 0ustar rogerroger#!/usr/bin/python -u import serial import shlex import subprocess pub_cmd = "mosquitto_pub -t cc128/raw -l -q 2" pub_args = shlex.split(pub_cmd) pub = subprocess.Popen(pub_args, stdin=subprocess.PIPE) usb = serial.Serial(port='/dev/ttyUSB0', baudrate=57600) running = True try: while running: line = usb.readline() pub.stdin.write(line) pub.stdin.flush() except usb.SerialException, e: running = False pub.stdin.close() pub.wait() mosquitto-0.15/misc/currentcost/cc128_read.pl0000775000175000017500000000071711713444064020215 0ustar rogerroger#!/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 = ) { print(MQTT "$line"); } close(MQTT); mosquitto-0.15/misc/currentcost/cc128_log_mysql.pl0000775000175000017500000000267011713444064021310 0ustar rogerroger#!/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 ''; # 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 = ) { @vals = split(/,/, $line); $timestamp = @vals[0]; $temperature = @vals[1]; $ch1 = @vals[2]; $dbh->do($query, undef, $timestamp, $temperature, $ch1); } $dbh->disconnect(); mosquitto-0.15/misc/currentcost/cc128_parse.pl0000775000175000017500000000250011713444064020404 0ustar rogerroger#!/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 = ) { #CC128-v0.120000215.7003112100108 if ($line =~ m# *([\-\d.]+)0[0-9]*10*(\d+) $now){ $r_stamp -= 86400; } print PUB "$r_stamp,$temp,$watts\n"; print PUB_CH1 "$r_stamp $watts\n"; } } mosquitto-0.15/misc/currentcost/gnome-panel/0000775000175000017500000000000011713444064020237 5ustar rogerrogermosquitto-0.15/misc/currentcost/gnome-panel/currentcost.png0000664000175000017500000001230411713444064023320 0ustar rogerrogerPNG  IHDR00WsRGBbKGD pHYs ftIME m,tEXtCommentCreated with GIMPWIDAThޭk$uz{z;;"wK.IEG l  LcH,0A r DKb `ǰ2 7AEe>fv=ﮪ{ɇ]1< (TssFxiVNcrv-SՕA.z^ !<霻+@bEv(VFdDx^7Z^nF%֣kOMx̙v% B#,^'d2PAdxE hP1VRj^,};I?Y<ųÉYiT{:p:ܘLǽ_L&{8F# +J{g2`D *jQk?M;]t0F6ky0I^= j8ջPζAy$1F$!c+@%Mi[+nk:RVY/7G3wl`w?}t|\GQX9D֖<B@‰s,ϘfyNARUI8mnm_?o|<j=ywN'r]UQ3oux웍I*;OGƫbUCpbU1:1LVj8ZÓO>/:G'@INpZxڱUm}Ν;cm4&Iypzh93<<~؇+ޣjqLףsZM=GV*daLͿ\[VUED 'Da-[{.~h[RȳdV]Z͖ 'h6A 4=-T*"xʊ;9!6aooϤi\A"'o IRL8K)z7ݴF)FC`gy&+7]4$Ϧ"B`n*G3 aJ<N#L&M&VmUzeFb3'ZƙvTJِ2ɊReՔZu !3 !W(PUEAfIb8d6Som8<@=P3e`^t$">E^}j`ueRݏVU1 tc v(O&5.GGGNck5QܯE^V%ix<&21ưBZ)qxL1Ȼ93~(Q @ 6"ɳ\888޳n5$˦X1+&ςh4Tk ,XɊ`I!3^ $! Zk++gi[2qn5 ;T*)׮>ƕK1w ZƗ@imm8d!Ld;'J,^0޹c(p͓b… TR3M9>d: kkkji>t@Ze9VVɳ cM |ys~ܡޮc,]`6899;7R}cȋe($8d фh\r$jG* BP<ˉίR#\rJ\1rwNseϳzRyW\\B) ce3E#X 9.l[ۻg9KV8>:PUiƀDxXW9z?6έr~c7߾CT~1]k^bX_Y%#;s$Ke̼!:viѐmjCEt5@Ygփ#DZfcE:-ȲIN_{|Ρl3NԈ-z)ZP,G1Qs҅~dݭTVOOy.,gOdc1 ޳O\RZsrpp@$[_΍ڵLjr=X[.Pc 4x,(t>k$T]{Oei7h5f޾6A X1~~lc-8&ZʹՎ^v#1%xp}{}B1B~V;F,JjMⓓSvvwKb-W"OCvVhpZԳ`xL$8x{qw7x\(kA T\i(K(^TU1jİO|QD_wMg +p~V>rۈEޕVJ*q=a0`ELm0J|G<ua:ɸ,^Z"" xSGk DB]B\๛?="`<^"jA5Kj1N؅ x2xѯ3a8b#KN?G3D,'8+\)j.:>̫"e/\SO i0o>uO?''=ob z&fKhe;歧{[ Fc$lO*Ad.vPpyfW;ܳ^oR"B%1j`Z\⹕O{&Grm1zeZv)CDNx&b>,c7Ixң"5x2a%Ix,+m{߽OdeIVJ\^x+~Mݮ^p lVv\R# w^?V*xPΈHyQ@8Q~<rɳO?+/_訫X޽G̥֛_[bl_ zL&u2*\N%w3fJ-+r5& b} 1"jQ ̲}gϾܫ [^m}ORL\>v[}uwgr8bmm-lllH2 :f(5jZs4(zfŸ*˝֋|,lΓO=E=[җoX_wwÃse{f3<JY,T4#DQk ,ԫKϷj|Sq^zyp0O+?ճ޼K?9=]ZQIH̚2o8J} ERINKzsy.+wyxpt*:_7?:>?=̈ (zG,)d^QrIY_~鿊ޛo37{+z/u։Wf/*ս^ _WIgDg`9GvjO*ieV1Oo~wG}U[?xn*SOK:4/_/RowkvtyN^sO\/wg?Ddq}?Pb} }aQӾZhIENDB`mosquitto-0.15/misc/currentcost/gnome-panel/CurrentCostMQTT.py0000775000175000017500000000416311713444064023601 0ustar rogerroger#!/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 loop(self): self.mosq.loop(1) return True def on_message(self, 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("ccpanel-"+platform.node()+"-"+str(os.getpid())) self.mosq.on_message = self.on_message self.mosq.connect("10.90.100.4", 1883, 60, True) self.mosq.subscribe("sensors/cc128/ch1", 0) self.applet.connect('change-background', self.on_change_background) gobject.timeout_add(100, self.loop) 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) mosquitto-0.15/misc/currentcost/gnome-panel/CurrentCostMQTT.server0000664000175000017500000000217611713444064024456 0ustar rogerroger mosquitto-0.15/misc/pachube_update.pl0000775000175000017500000000133511713444064016775 0ustar rogerroger#!/usr/bin/perl use strict; use Net::Pachube; # Update a pachube feed. # Run as "pachube_update.pl ", where is the id of your feed, # e.g. xxxx from http://www.pachube.com/api/feeds/xxxx.xml # Your pachube api key should be set in the environment variable # PACHUBE_API_KEY # # Use with mosquitto_sub like: # # mosquitto_sub -h -i -t | pachube_update.pl # # Needs Net::Pachube installing from CPAN. if($#ARGV != 0){ print "Usage: pachube_update.pl \n"; exit } my $feed_id = $ARGV[0]; my $pachube = Net::Pachube->new(); my $feed = $pachube->feed($feed_id); #print $feed->title, " ", $feed->status, "\n"; while(){ chomp; $_ += 0; $feed->update(data => $_); } mosquitto-0.15/config.mk0000664000175000017500000000107111713444064014324 0ustar rogerroger# Also bump lib/mosquitto.h, lib/python/setup.py, CMakeLists.txt, # installer/mosquitto.nsi, installer/mosquitto-cygwin.nsi VERSION=0.15 TIMESTAMP:=$(shell date "+%F %T%z") #MANCOUNTRIES=en_GB CFLAGS=-I. -I.. -ggdb -Wall -O2 -I../lib UNAME:=$(shell uname -s) ifeq ($(UNAME),QNX) LIBS=-lsocket else LIBS= endif LDFLAGS= # Add -lwrap to LDFLAGS if compiling with tcp wrappers support. CC=gcc INSTALL=install XGETTEXT=xgettext MSGMERGE=msgmerge MSGFMT=msgfmt DOCBOOK2MAN=docbook2man.pl prefix=/usr/local mandir=${prefix}/share/man localedir=${prefix}/share/locale mosquitto-0.15/pwfile.example0000664000175000017500000000006311713444064015371 0ustar rogerrogerroger:password sub_client:reader pub_client:writer mosquitto-0.15/readme.txt0000664000175000017500000000130411713444064014523 0ustar rogerrogerMosquitto ========= Mosquitto is an open source implementation of a server for version 3.1 of the mqtt protocol. IBM have a closed source version of this server, known as Really Small Message Broker (rsmb). The plan is to make this a more or less drop in replacement. 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) Mosquitto was written by Roger Light mosquitto-0.15/security/0000775000175000017500000000000011713444064014376 5ustar rogerrogermosquitto-0.15/security/mosquitto.apparmor0000664000175000017500000000074611713444064020214 0ustar rogerroger/usr/sbin/mosquitto { #include #include /usr/sbin/mosquitto r, /etc/mosquitto/mosquitto.conf 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, } mosquitto-0.15/external_security_checks.txt0000664000175000017500000000604711713444064020370 0ustar rogerrogerMosquitto is now easier to integrate with existing username/password databases. It doesn't do any of this for you, but it does provide access points to help. At the moment mosquitto doesn't support encrypted network connections so you should be wary of exposing your existing username/passwords. If you wish to do this, uncomment the WITH_EXTERNAL_SECURITY_CHECKS line in config.h, or enable the option when configuring the build options with cmake. You should now edit src/security_external.c to fit your system. If you need to link extra libraries, add them to src/Makefile or src/CMakeLists.txt. All functions below have access to the additional config variables db_host, db_port, db_name, db_username and db_password. They can be accessed via db->config->db_*. The functions you need to implement are: int mosquitto_unpwd_init(struct _mosquitto_db *db) * Called at mosquitto startup. This is used to open database connections/files * or anything else that needs to be done once and is related to username and * password checks. * Should return MOSQ_ERR_SUCCESS on success, or anything else on error. See * lib/mosquitto.h for currently defined errors, or use MOSQ_ERR_UNKNOWN. int mosquitto_unpwd_cleanup(struct _mosquitto_db *db) * Called when the broker is shutting down. This is used to close database * connections/files or anything else that needs to be done onc and is related * to username and password checks. * Should return MOSQ_ERR_SUCCESS on success, or anything else on error. See * lib/mosquitto.h for currently defined errors, or use MOSQ_ERR_UNKNOWN. int mosquitto_unpwd_check(struct _mosquitto_db *db, const char *username, const char *password) * Called each time a username and/or password needs to be checked. * Should return MOSQ_ERR_SUCCESS on success, MOSQ_ERR_AUTH for authentication * errors (username/password invalid) or anything else for other errors. See * lib/mosquitto.h for currently defined errors, or use MOSQ_ERR_UNKNOWN. int mosquitto_acl_init(struct _mosquitto_db *db) * Called at mosquitto startup. This is used to open database connections/files * or anything else that needs to be done once and is related to access control * list checks. * Should return MOSQ_ERR_SUCCESS on success, or anything else on error. See * lib/mosquitto.h for currently defined errors, or use MOSQ_ERR_UNKNOWN. void mosquitto_acl_cleanup(struct _mosquitto_db *db) * Called when the broker is shutting down. This is used to close database * connections/files or anything else that needs to be done onc and is related * to username and password checks. * Should return MOSQ_ERR_SUCCESS on success, or anything else on error. See * lib/mosquitto.h for currently defined errors, or use MOSQ_ERR_UNKNOWN. int mosquitto_acl_check(struct _mosquitto_db *db, mqtt3_context *context, const char *topic, int access) * Called each time a topic access control list should be checked. * Should return MOSQ_ERR_SUCCESS on success, MOSQ_ERR_ACL_DENIED for ACL * denials or anything else for other errors. See lib/mosquitto.h for currently * defined errors, or use MOSQ_ERR_UNKNOWN. mosquitto-0.15/lib/0000775000175000017500000000000011713444064013275 5ustar rogerrogermosquitto-0.15/lib/CMakeLists.txt0000664000175000017500000000203011713444064016030 0ustar rogerrogeradd_subdirectory(cpp) include_directories(${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/lib ${STDBOOL_H_PATH} ${STDINT_H_PATH} ${OPENSSL_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 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 util_mosq.c util_mosq.h will_mosq.c will_mosq.h) if (WIN32) target_link_libraries(libmosquitto ws2_32 ${OPENSSL_LIBRARIES}) else (WIN32) target_link_libraries(libmosquitto ${OPENSSL_LIBRARIES}) endif (WIN32) set_target_properties(libmosquitto PROPERTIES OUTPUT_NAME mosquitto VERSION ${VERSION} SOVERSION 0 ) 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) mosquitto-0.15/lib/net_mosq.h0000664000175000017500000000667711713444064015313 0ustar rogerroger/* Copyright (c) 2010,2011 Roger Light 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. */ #ifndef _NET_MOSQ_H_ #define _NET_MOSQ_H_ #ifndef WIN32 #include #else #include typedef int ssize_t; #endif #include #include #ifdef WITH_BROKER struct _mosquitto_db; #endif #ifdef WIN32 # define COMPAT_CLOSE(a) closesocket(a) #else # define COMPAT_CLOSE(a) close(a) #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); int _mosquitto_socket_close(struct mosquitto *mosq); int _mosquitto_read_byte(struct _mosquitto_packet *packet, uint8_t *byte); int _mosquitto_read_bytes(struct _mosquitto_packet *packet, uint8_t *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 uint8_t *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, int context_index); #else int _mosquitto_packet_read(struct mosquitto *mosq); #endif #endif mosquitto-0.15/lib/will_mosq.c0000664000175000017500000000654411713444064015460 0ustar rogerroger/* Copyright (c) 2010,2011 Roger Light 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. */ #include #include #include #include #ifndef WIN32 #include #include #else #include typedef int ssize_t; #endif #include #include #include #include #include #include #include #include #include #include int _mosquitto_will_set(struct mosquitto *mosq, bool will, const char *topic, uint32_t payloadlen, const uint8_t *payload, int qos, bool retain) { int rc = MOSQ_ERR_SUCCESS; if(!mosq || (will && !topic)) return MOSQ_ERR_INVAL; if(payloadlen > 268435455) return MOSQ_ERR_PAYLOAD_SIZE; 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; } if(will){ 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(uint8_t)*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; } mosquitto-0.15/lib/mosquitto.h0000664000175000017500000006207411713444064015523 0ustar rogerroger/* Copyright (c) 2010-2012 Roger Light 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. */ #ifndef _MOSQUITTO_H_ #define _MOSQUITTO_H_ #ifdef __cplusplus extern "C" { #endif #ifdef _WIN32 # ifdef libmosquitto_EXPORTS # define libmosq_EXPORT __declspec(dllexport) # else # define libmosq_EXPORT __declspec(dllimport) # endif #else # define libmosq_EXPORT #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 # endif # ifndef __cplusplus # define bool char # define true 1 # define false 0 # endif #else # include # include #endif #define LIBMOSQUITTO_MAJOR 0 #define LIBMOSQUITTO_MINOR 15 #define LIBMOSQUITTO_REVISION 0 #define LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION) /* Log destinations */ #define MOSQ_LOG_NONE 0x00 #define MOSQ_LOG_STDOUT 0x04 #define MOSQ_LOG_STDERR 0x08 /* Log types */ #define MOSQ_LOG_INFO 0x01 #define MOSQ_LOG_NOTICE 0x02 #define MOSQ_LOG_WARNING 0x04 #define MOSQ_LOG_ERR 0x08 #define MOSQ_LOG_DEBUG 0x10 #define MOSQ_LOG_ALL 0xFF /* Error values */ #define MOSQ_ERR_SUCCESS 0 #define MOSQ_ERR_NOMEM 1 #define MOSQ_ERR_PROTOCOL 2 #define MOSQ_ERR_INVAL 3 #define MOSQ_ERR_NO_CONN 4 #define MOSQ_ERR_CONN_REFUSED 5 #define MOSQ_ERR_NOT_FOUND 6 #define MOSQ_ERR_CONN_LOST 7 #define MOSQ_ERR_SSL 8 #define MOSQ_ERR_PAYLOAD_SIZE 9 #define MOSQ_ERR_NOT_SUPPORTED 10 #define MOSQ_ERR_AUTH 11 #define MOSQ_ERR_ACL_DENIED 12 #define MOSQ_ERR_UNKNOWN 13 #define MOSQ_ERR_ERRNO 14 struct mosquitto_message{ uint16_t mid; char *topic; uint8_t *payload; uint32_t payloadlen; int qos; bool retain; }; struct mosquitto; /*************************************************** * Important note * * The following functions that deal with network operations will return * MOSQ_ERR_SUCCESS on success, but this does not mean that the operation has * taken place. An attempt will be made to write the network data, but if the * socket is not available for writing at that time then the packet will not be * sent. To ensure the packet is sent, call mosquitto_loop() (which must also * be called to process incoming network data). * This is especially important when disconnecting a client that has a will. If * the broker does not receive the DISCONNECT command, it will assume that the * client has disconnected unexpectedly and send the will. * * mosquitto_connect() * mosquitto_disconnect() * mosquitto_subscribe() * mosquitto_unsubscribe() * mosquitto_publish() ***************************************************/ /* * Function: mosquitto_lib_version * * Can be used to obtain version information for the phasecapture library. * This allows the application to compare the library version against the * version it was compiled against by using the LIBMOSQUITTO_MAJOR, * LIBMOSQUITTO_MINOR and LIBMOSQUITTO_REVISION defines. * * Parameters: * major - an integer pointer. If not NULL, the major version of the * library will be returned in this variable. * minor - an integer pointer. If not NULL, the minor version of the * library will be returned in this variable. * revision - an integer pointer. If not NULL, the revision of the library will * be returned in this variable. * * See Also: * , */ libmosq_EXPORT void mosquitto_lib_version(int *major, int *minor, int *revision); /* * Function: mosquitto_lib_init * * Must be called before any other mosquitto functions. * * Returns: * MOSQ_ERR_SUCCESS - always * * See Also: * , */ libmosq_EXPORT int mosquitto_lib_init(void); /* * Function: mosquitto_lib_cleanup * * Call to free resources associated with the library. * * Returns: * MOSQ_ERR_SUCCESS - always * * See Also: * , */ libmosq_EXPORT int mosquitto_lib_cleanup(void); /* * Function: mosquitto_new * * Create a new mosquitto client instance. * * Parameters: * id - String to use as the client id. Must not be NULL or zero length. * obj - A user pointer that will be passed as an argument to any callbacks * that are specified. * * Returns: * Pointer to a struct mosquitto on success. * NULL on failure. * * See Also: * */ libmosq_EXPORT struct mosquitto *mosquitto_new(const char *id, void *obj); /* * Function: mosquitto_destroy * * Use to free memory associated with a mosquitto client instance. * * Parameters: * mosq - a struct mosquitto pointer to free. * * See Also: * */ libmosq_EXPORT void mosquitto_destroy(struct mosquitto *mosq); /* * Function: mosquitto_log_init * * Configure logging options for a client instance. May be called at any point. * * Log priorities controls which types of messages are output. OR together * values from: * * * MOSQ_LOG_INFO * * MOSQ_LOG_NOTICE * * MOSQ_LOG_WARNING * * MOSQ_LOG_ERR * * MOSQ_LOG_DEBUG * * MOSQ_LOG_ALL * * Log destinations controls where the log messages are sent. OR together * values from: * * * MOSQ_LOG_NONE * * MOSQ_LOG_STDOUT * * MOSQ_LOG_STDERR * * Parameters: * mosq - a valid mosquitto instance. * priorities - an integer bit mask of the log types to output. * destinations - an integer bit mask of log destinations. * * Returns: * MOSQ_ERR_SUCCESS - always */ libmosq_EXPORT int mosquitto_log_init(struct mosquitto *mosq, int priorities, int destinations); /* * Function: mosquitto_will_set * * Configure will information for a mosquitto instance. By default, clients do * not have a will. This must be called before calling . * * Parameters: * mosq - a valid mosquitto instance. * will - set to true to enable a will, false to disable. If set to true, * at least "topic" but also be valid. * topic - the topic on which to publish the will. * payloadlen - the size of the payload (bytes). Valid values are between 0 and * 268,435,455. * payload - pointer to the data to send. If payloadlen > 0 this must be a * valid memory location. * qos - integer value 0, 1 or 2 indicating the Quality of Service to be * used for the will. * retain - set to true to make the will a retained message. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. * MOSQ_ERR_PAYLOAD_SIZE - if payloadlen is too large. */ libmosq_EXPORT int mosquitto_will_set(struct mosquitto *mosq, bool will, const char *topic, uint32_t payloadlen, const uint8_t *payload, int qos, bool retain); /* * Function: mosquitto_username_pw_set * * Configure username and password for a mosquitton instance. This is only * supported by brokers that implement the MQTT spec v3.1. By default, no * username or password will be sent. * If username is NULL, the password argument is ignored. * This must be called before calling mosquitto_connect(). * * This is must be called before calling . * * Parameters: * mosq - a valid mosquitto instance. * username - the username to send as a string, or NULL to disable * authentication. * password - the password to send as a string. Set to NULL when username is * valid in order to send just a username. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. */ libmosq_EXPORT int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password); /* * Function: mosquitto_connect * * Connect to an MQTT broker. * * Parameters: * mosq - a valid mosquitto instance. * host - the hostname or ip address of the broker to connect to. * port - the network port to connect to. Usually 1883. * keepalive - the number of seconds after which the broker should send a * PING message to the client if no other messages have been * exchanged in that time. * clean_session - set to true to instruct the broker to clean all messages * and subscriptions on disconnect, false to instruct it to * keep them. See the man page mqtt(7) for more details. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno * contains the error code, even on Windows. * Use strerror_r() where available or FormatMessage() on * Windows. * * See Also: * , */ libmosq_EXPORT int mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive, bool clean_session); /* * Function: mosquitto_reconnect * * Reconnect to a broker. * * This function provides an easy way of reconnecting to a broker after a * connection has been lost. It uses the values provided in the * call and so must not be called before * . * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno * contains the error code, even on Windows. * Use strerror_r() where available or FormatMessage() on * Windows. * * See Also: * , */ libmosq_EXPORT int mosquitto_reconnect(struct mosquitto *mosq); /* * Function: mosquitto_disconnect * * Disconnect from the broker. * * Parameters: * mosq - a valid mosquitto instance. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. */ libmosq_EXPORT int mosquitto_disconnect(struct mosquitto *mosq); /* * Function: mosquitto_publish * * Publish a message on a given topic. * * Parameters: * mosq - a valid mosquitto instance. * mid - pointer to a uint16_t. If not NULL, the function will set this * to the message id of this particular message. This can be then * used with the publish callback to determine when the message * has been sent. * Note that although the MQTT protocol doesn't use message ids * for messages with QoS=0, libmosquitto assigns them message ids * so they can be tracked with this parameter. * topic - the topic to publish the message on. Must not contain the * wildcard characters + or # * payloadlen - the size of the payload (bytes). Valid values are between 0 and * 268,435,455. * payload - pointer to the data to send. If payloadlen > 0 this must be a * valid memory location. * qos - integer value 0, 1 or 2 indicating the Quality of Service to be * used for the message. * retain - set to true to make the message retained. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the * broker. * MOSQ_ERR_PAYLOAD_SIZE - if payloadlen is too large. */ libmosq_EXPORT int mosquitto_publish(struct mosquitto *mosq, uint16_t *mid, const char *topic, uint32_t payloadlen, const uint8_t *payload, int qos, bool retain); /* * Function: mosquitto_subscribe * * Subscribe to a topic. * * Parameters: * mosq - a valid mosquitto instance. * mid - a pointer to a uint16_t. If not NULL, the function will set this to * the message id of this particular message. This can be then used * with the subscribe callback to determine when the message has been * sent. * sub - the subscription pattern. * qos - the requested Quality of Service for this subscription. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. */ libmosq_EXPORT int mosquitto_subscribe(struct mosquitto *mosq, uint16_t *mid, const char *sub, int qos); /* * Function: mosquitto_unsubscribe * * Unsubscribe from a topic. * * Parameters: * mosq - a valid mosquitto instance. * mid - a pointer to a uint16_t. If not NULL, the function will set this to * the message id of this particular message. This can be then used * with the unsubscribe callback to determine when the message has been * sent. * sub - the unsubscription pattern. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. */ libmosq_EXPORT int mosquitto_unsubscribe(struct mosquitto *mosq, uint16_t *mid, const char *sub); /* * Function: mosquitto_message_copy * * Copy the contents of a mosquitto message to another message. * Useful for preserving a message received in the on_message() callback. * * Parameters: * dst - a pointer to a valid mosquitto_message struct to copy to. * src - a pointer to a valid mosquitto_message struct to copy from. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. * * See Also: * */ libmosq_EXPORT int mosquitto_message_copy(struct mosquitto_message *dst, const struct mosquitto_message *src); /* * Function: mosquitto_message_free * * Completely free a mosquitto_message struct. * * Parameters: * message - pointer to a mosquitto_message pointer to free. * * See Also: * */ libmosq_EXPORT void mosquitto_message_free(struct mosquitto_message **message); /* * Function: mosquitto_loop * * The main network loop for the client. You must call this frequently in order * to keep communications between the client and broker working. * * This calls select() to monitor the client network socket. If you want to * integrate mosquitto client operation with your own select() call, use * , , and * . * * Parameters: * mosq - a valid mosquitto instance. * timeout - Maximum number of milliseconds to wait for network activity in * the select() call before timing out. Set to 0 for instant return. * Set negative to use the default of 1000ms. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost. * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the * broker. * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno * contains the error code, even on Windows. * Use strerror_r() where available or FormatMessage() on * Windows. */ libmosq_EXPORT int mosquitto_loop(struct mosquitto *mosq, int timeout); /* * Function: mosquitto_socket * * Return the socket handle for a mosquitto instance. Useful if you want to * include a mosquitto client in your own select() calls. * * Parameters: * mosq - a valid mosquitto instance. * * Returns: * The socket for the mosquitto client or -1 on failure. */ libmosq_EXPORT int mosquitto_socket(struct mosquitto *mosq); /* * Function: mosquitto_loop_read * * Carry out network read operations. * This should only be used if you are not using mosquitto_loop() and are * monitoring the client network socket for activity yourself. * * Parameters: * mosq - a valid mosquitto instance. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost. * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the * broker. * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno * contains the error code, even on Windows. * Use strerror_r() where available or FormatMessage() on * Windows. * * See Also: * , , */ libmosq_EXPORT int mosquitto_loop_read(struct mosquitto *mosq); /* * Function: mosquitto_loop_write * * Carry out network write operations. * This should only be used if you are not using mosquitto_loop() and are * monitoring the client network socket for activity yourself. * * Parameters: * mosq - a valid mosquitto instance. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * MOSQ_ERR_NOMEM - if an out of memory condition occurred. * MOSQ_ERR_NO_CONN - if the client isn't connected to a broker. * MOSQ_ERR_CONN_LOST - if the connection to the broker was lost. * MOSQ_ERR_PROTOCOL - if there is a protocol error communicating with the * broker. * MOSQ_ERR_ERRNO - if a system call returned an error. The variable errno * contains the error code, even on Windows. * Use strerror_r() where available or FormatMessage() on * Windows. * * See Also: * , , */ libmosq_EXPORT int mosquitto_loop_write(struct mosquitto *mosq); /* * Function: mosquitto_loop_misc * * Carry out miscellaneous operations required as part of the network loop. * This should only be used if you are not using mosquitto_loop() and are * monitoring the client network socket for activity yourself. * * This function deals with handling PINGs and checking whether messages need * to be retried, so should be called fairly frequently. * * Parameters: * mosq - a valid mosquitto instance. * * Returns: * MOSQ_ERR_SUCCESS - on success. * MOSQ_ERR_INVAL - if the input parameters were invalid. * * See Also: * , , */ libmosq_EXPORT int mosquitto_loop_misc(struct mosquitto *mosq); /* * Function: mosquitto_connect_callback_set * * Set the connect callback. This is called when the broker sends a CONNACK * message in response to a connection. * * Parameters: * mosq - a valid mosquitto instance. * on_connect - a callback function in the following form: * void callback(void *obj, int rc) * * Callback Parameters: * obj - the user data provided in * rc - the return code of the connection response, one of: * * * 0 - success * * 1 - connection refused (unacceptable protocol version) * * 2 - connection refused (identifier rejected) * * 3 - connection refused (broker unavailable) * * 4-255 - reserved for future use */ libmosq_EXPORT void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(void *, int)); /* * Function: mosquitto_disconnect_callback_set * * Set the disconnect callback. This is called when the broker has received the * DISCONNECT command and has disconnected the client. * * Parameters: * mosq - a valid mosquitto instance. * on_disconnect - a callback function in the following form: * void callback(void *obj) * * Callback Parameters: * obj - the user data provided in */ libmosq_EXPORT void mosquitto_disconnect_callback_set(struct mosquitto *mosq, void (*on_disconnect)(void *)); /* * Function: mosquitto_publish_callback_set * * Set the publish callback. This is called when a message initiated with * has been sent to the broker successfully. * * Parameters: * mosq - a valid mosquitto instance. * on_publish - a callback function in the following form: * void callback(void *obj, uint16_t mid) * * Callback Parameters: * obj - the user data provided in * mid - the message id of the sent message. */ libmosq_EXPORT void mosquitto_publish_callback_set(struct mosquitto *mosq, void (*on_publish)(void *, uint16_t)); /* * Function: mosquitto_message_callback_set * * Set the message callback. This is called when a message is received from the * broker. * * Parameters: * mosq - a valid mosquitto instance. * on_message - a callback function in the following form: * void callback(void *obj, const struct mosquitto_message *message) * * Callback Parameters: * obj - the user data provided in * message - the message data. This variable and associated memory will be * freed by the library after the callback completes. The client * should make copies of any of the data it requires. * * See Also: * */ libmosq_EXPORT void mosquitto_message_callback_set(struct mosquitto *mosq, void (*on_message)(void *, const struct mosquitto_message *)); /* * Function: mosquitto_subscribe_callback_set * * Set the subscribe callback. This is called when the broker responds to a * subscription request. * * Parameters: * mosq - a valid mosquitto instance. * on_subscribe - a callback function in the following form: * void callback(void *obj, uint16_t mid, int qos_count, const uint8_t *granted_qos) * * Callback Parameters: * obj - the user data provided in * mid - the message id of the subscribe message. * qos_count - the number of granted subscriptions (size of granted_qos). * granted_qos - an array of integers indicating the granted QoS for each of * the subscriptions. */ libmosq_EXPORT void mosquitto_subscribe_callback_set(struct mosquitto *mosq, void (*on_subscribe)(void *, uint16_t, int, const uint8_t *)); /* * Function: mosquitto_unsubscribe_callback_set * * Set the unsubscribe callback. This is called when the broker responds to a * unsubscription request. * * Parameters: * mosq - a valid mosquitto instance. * on_unsubscribe - a callback function in the following form: * void callback(void *obj, uint16_t mid) * * Callback Parameters: * obj - the user data provided in * mid - the message id of the unsubscribe message. */ libmosq_EXPORT void mosquitto_unsubscribe_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(void *, uint16_t)); /* * Function: mosquitto_message_retry_set * * Set the number of seconds to wait before retrying messages. This applies to * publish messages with QoS>0. May be called at any time. * * Parameters: * mosq - a valid mosquitto instance. * message_retry - the number of seconds to wait for a response before * retrying. Defaults to 60. */ libmosq_EXPORT void mosquitto_message_retry_set(struct mosquitto *mosq, unsigned int message_retry); #ifdef __cplusplus } #endif #endif mosquitto-0.15/lib/read_handle_client.c0000664000175000017500000000463511713444064017235 0ustar rogerroger/* Copyright (c) 2009,2010, Roger Light 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. */ #include #include #include #include #include #include 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, "Received CONNACK"); 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; if(mosq->on_connect){ mosq->in_callback = true; mosq->on_connect(mosq->obj, result); mosq->in_callback = false; } 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; } } mosquitto-0.15/lib/python/0000775000175000017500000000000011713444064014616 5ustar rogerrogermosquitto-0.15/lib/python/sub.py0000775000175000017500000000406711713444064015773 0ustar rogerroger#!/usr/bin/python # Copyright (c) 2010,2011 Roger Light # 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. import mosquitto def on_connect(rc): print "rc: ", rc def on_message(msg): print msg.topic,msg.qos,msg.payload def on_publish(mid): print "mid:", mid def on_subscribe(mid, granted_qos): print "Subscribed:",mid,granted_qos mqttc = mosquitto.Mosquitto("python_sub") mqttc.on_message = on_message mqttc.on_connect = on_connect mqttc.on_publish = on_publish mqttc.on_subscribe = on_subscribe mqttc.connect("127.0.0.1", 1883, 60, True) mqttc.subscribe("$SYS/#", 0) rc = 0 while rc == 0: rc = mqttc.loop() print "rc:", rc mosquitto-0.15/lib/python/mosquitto.py0000775000175000017500000004637311713444064017254 0ustar rogerroger# Copyright (c) 2010-2012 Roger Light # 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. import sys from ctypes import * from ctypes.util import find_library if sys.version_info < (2,6,0): c_bool = c_int # Log destinations MOSQ_LOG_NONE=0x00 MOSQ_LOG_STDOUT=0x04 MOSQ_LOG_STDERR=0x08 # Log types MOSQ_LOG_INFO=0x01 MOSQ_LOG_NOTICE=0x02 MOSQ_LOG_WARNING=0x04 MOSQ_LOG_ERR=0x08 MOSQ_LOG_DEBUG=0x10 class Mosquitto: """MQTT version 3.1 client class. This is the main class for use communicating with an MQTT broker. General usage flow: * Use connect() to connect to a broker * Call loop() frequently to maintain network traffic flow with the broker * Use subscribe() to subscribe to a topic and receive messages * Use publish() to send messages * Use disconnect() to disconnect from the broker Data returned from the broker is made available with the use of callback functions as described below. Callbacks ========= A number of callback functions are available to receive data back from the broker. To use a callback, define a function and then assign it to the client. The callback function may be a class member if desired. All of the callbacks as described below have an "obj" argument. This variable corresponds directly to the obj argument passed when creating the client instance. It is however optional when defining the callback functions, so the on connect callback function can be defined as on_connect(obj, rc) or on_connect(rc) for example. The callbacks: on_connect(obj, rc): called when the broker responds to our connection request. The value of rc determines success or not: 0: Connection successful 1: Connection refused - incorrect protocol version 2: Connection refused - invalid client identifier 3: Connection refused - server unavailable 4: Connection refused - bad username or password 5: Connection refused - not authorised 6-255: Currently unused. on_disconnect(obj): called when the client disconnects from the broker, but only after having sent a disconnection message to the broker. This will not be called if the client is disconnected unexpectedly. on_message(obj, message): called when a message has been received on a topic that the client subscribes to. The message variable is a MosquittoMessage that describs all of the message parameters. on_publish(obj, mid): called when a message that was to be sent using the publish() call has completed transmission to the broker. For messages with QoS levels 1 and 2, this means that the appropriate handshakes have completed. For QoS 0, this simply means that the message has left the client. The mid variable matches the mid variable returned from the corresponding publish() call, to allow outgoing messages to be tracked. This callback is important because even if the publish() call returns success, it does not means that the message has been sent. on_subscribe(obj, mid, granted_qos): called when the broker responds to a subscribe request. The mid variable matches the mid variable returned from the corresponding subscribe() call. The granted_qos variable is a list of integers that give the QoS level the broker has granted for each of the different subscription requests. on_unsubscribe(obj, mid): called when the broker responds to an unsubscribe request. The mid variable matches the mid variable returned from the corresponding unsubscribe() call. Example: def on_connect(rc): if rc == 0: print "Connected ok" client = mosquitto.Mosquitto("id") client.on_connect = on_connect ... """ def __init__(self, id, obj=None): """Constructor id: The 23 character or less client id used to identify this client to the broker. This must be unique on the broker. obj: An optional object of any type that will be passed to any of the callback function when they are called. If not set, or set to None, this instance of the Mosquitto class will be passed to the callback functions. """ if obj==None: self.obj = self else: self.obj = obj _mosquitto_lib_init() self._mosq = _mosquitto_new(id, None) #================================================== # Configure callbacks #================================================== self._internal_on_connect_cast = _MOSQ_CONNECT_FUNC(self._internal_on_connect) _mosquitto_connect_callback_set(self._mosq, self._internal_on_connect_cast) self.on_connect = None self._internal_on_disconnect_cast = _MOSQ_DISCONNECT_FUNC(self._internal_on_disconnect) _mosquitto_disconnect_callback_set(self._mosq, self._internal_on_disconnect_cast) self.on_disconnect = None self._internal_on_message_cast = _MOSQ_MESSAGE_FUNC(self._internal_on_message) _mosquitto_message_callback_set(self._mosq, self._internal_on_message_cast) self.on_message = None self._internal_on_publish_cast = _MOSQ_PUBLISH_FUNC(self._internal_on_publish) _mosquitto_publish_callback_set(self._mosq, self._internal_on_publish_cast) self.on_publish = None self._internal_on_subscribe_cast = _MOSQ_SUBSCRIBE_FUNC(self._internal_on_subscribe) _mosquitto_subscribe_callback_set(self._mosq, self._internal_on_subscribe_cast) self.on_subscribe = None self._internal_on_unsubscribe_cast = _MOSQ_UNSUBSCRIBE_FUNC(self._internal_on_unsubscribe) _mosquitto_unsubscribe_callback_set(self._mosq, self._internal_on_unsubscribe_cast) self.on_unsubscribe = None #================================================== # End configure callbacks #================================================== def __del__(self): _mosquitto_lib_cleanup() def __del__(self): if self._mosq: _mosquitto_destroy(self._mosq) def connect(self, hostname="localhost", port=1883, keepalive=60, clean_session=True): """Connect the client to an MQTT broker. hostname: The hostname or ip address of the broker. Defaults to localhost. port: The network port of the server host to connect to. Defaults to 1883. keepalive: Maximum period in seconds between communications with the broker. If no other messages are being exchanged, this controls the rate at which the client will send ping messages to the broker. clean_session: If set to True, the broker will clean any previous information about this client on connection, and will also not store anything after disconnect. If set to False, the broker will store all of the client subscriptions even after the client disconnects, and will also queue messages with QoS 1 and 2 until the client reconnects. Returns 0 on success (note that this just means a network connection has been established between the broker and client, and the connection request sent. To monitor the success of the connection request, use the on_connect() callback) Returns >0 on error. """ return _mosquitto_connect(self._mosq, hostname, port, keepalive, clean_session) def reconnect(self): """Reconnect to a broker. This uses the saved parameters from the connect() call to reconnect to a broker after a disconnect.""" return _mosquitto_reconnect(self._mosq) def disconnect(self): """Disconnect a connected client from the broker.""" return _mosquitto_disconnect(self._mosq) def log_init(self, priorities, destinations): """Set the logging preferences for this client. Set priorities to a logically OR'd combination of: MOSQ_LOG_INFO MOSQ_LOG_NOTICE MOSQ_LOG_WARNING MOSQ_LOG_ERR MOSQ_LOG_DEBUG Set destinations to either MOSQ_LOG_NONE or a logically OR'd combination of: MOSQ_LOG_STDOUT=0x04 MOSQ_LOG_STDERR=0x08 """ return _mosquitto_log_init(self._mosq, priorities, destinations) def loop(self, timeout=-1): """Process network events. This function must be called regularly to ensure communication with the broker is carried out. timeout: The time in milliseconds to wait for incoming/outgoing network traffic before timing out and returning. If set to -1 or not given, the default value of 1000 (1 second) will be used. Returns 0 on success. Returns >0 on error.""" return _mosquitto_loop(self._mosq, timeout) def subscribe(self, sub, qos=0): """Subscribe the client to a topic. sub: The subscription topic to subscribe to. qos: The desired quality of service level for the subscription. Returns a tuple (result, mid), where result being 0 indicates success and mid is the message ID for the subscribe request. The mid value can be used to track the subscribe request by checking against the mid argument in the on_subscribe() callback if it is defined.""" mid = c_uint16(0) result = _mosquitto_subscribe(self._mosq, mid, sub, qos) return result, mid.value def unsubscribe(self, sub): """Unsubscribe the client from a topic. sub: The subscription topic to unsubscribe from. Returns a tuple (result, mid), where result being 0 indicates success and mid is the message ID for the unsubscribe request. The mid value can be used to track the unsubscribe request by checking against the mid argument in the on_unsubscribe() callback if it is defined.""" mid = c_uint16(0) result = _mosquitto_unsubscribe(self._mosq, mid, sub) return result, mid.value def publish(self, topic, payload=None, qos=0, retain=False): """Publish a message on a topic. This causes a message to be sent to the broker and subsequently from the broker to any clients subscribing to matching topics. topic: The topic that the message should be published on. payload: The actual message to send. If not given, or set to None a zero length message will be used. qos: The quality of service level to use. retain: If set to true, the message will be set as the "last known good"/retained message for the topic. Returns a tuple (result, mid), where result being 0 indicates success and mid is the message ID for the publish request. The mid value can be used to track the publish request by checking against the mid argument in the on_publish() callback if it is defined.""" mid = c_uint16(0) if payload == None: payloadlen = 0 else: payloadlen = len(payload) result = _mosquitto_publish(self._mosq, mid, topic, payloadlen, cast(payload, POINTER(c_uint8)), qos, retain) return result, mid.value def will_set(self, topic, payload=None, qos=0, retain=False): """Set a Will to be sent by the broker in case the client disconnects unexpectedly. This must be called before connect() to have any effect. topic: The topic that the will message should be published on. payload: The message to send as a will. If not given, or set to None a zero length message will be used as the will. qos: The quality of service level to use for the will. retain: If set to true, the will message will be set as the "last known good"/retained message for the topic. Returns 0 on success. Returns >1 on error.""" if payload == None: payloadlen = 0 else: payloadlen = len(payload) return _mosquitto_will_set(self._mosq, True, topic, payloadlen, cast(payload, POINTER(c_uint8)), qos, retain) def will_clear(self): """Clear a Will that was previously set with the will_set() call. This must be called before connect() to have any effect.""" return _mosquitto_will_set(self._mosq, false, "", 0, cast(None, POINTER(c_uint8)), 0, 0) def username_pw_set(self, username, password=None): """Set a username and optionally a password for broker authentication. Must be called before connect() to have any effect. Requires a broker that supports MQTT v3.1. username: The username to authenticate with. Need have no relationship to the client id. password: The password to authenticate with. Optional. Returns 0 on success. Returns >0 on error.""" return _mosquitto_username_pw_set(self._mosq, username, password) def _internal_on_connect(self, obj, rc): if self.on_connect: argcount = self.on_connect.func_code.co_argcount if argcount == 1: self.on_connect(rc) elif argcount == 2 or argcount == 3: self.on_connect(self.obj, rc) def _internal_on_disconnect(self, obj): if self.on_disconnect: argcount = self.on_disconnect.func_code.co_argcount if argcount == 0: self.on_disconnect() elif argcount == 1 or argcount == 2: self.on_disconnect(self.obj) def _internal_on_message(self, obj, message): if self.on_message: mid = message.contents.mid topic = message.contents.topic payloadlen = message.contents.payloadlen payload = message.contents.payload qos = message.contents.qos retain = message.contents.retain msg = MosquittoMessage(mid, topic, payloadlen, payload, qos, retain) argcount = self.on_message.func_code.co_argcount if argcount == 1: self.on_message(msg) elif argcount == 2 or argcount == 3: self.on_message(self.obj, msg) def _internal_on_publish(self, obj, mid): if self.on_publish: argcount = self.on_publish.func_code.co_argcount if argcount == 1: self.on_publish(mid) elif argcount == 2 or argcount == 3: self.on_publish(self.obj, mid) def _internal_on_subscribe(self, obj, mid, qos_count, granted_qos): if self.on_subscribe: qos_list = [] for i in range(qos_count): qos_list.append(granted_qos[i]) argcount = self.on_subscribe.func_code.co_argcount if argcount == 2: self.on_subscribe(mid, qos_list) elif argcount == 3 or argcount == 4: self.on_subscribe(self.obj, mid, qos_list) def _internal_on_unsubscribe(self, obj, mid): if self.on_unsubscribe: argcount = self.on_unsubscribe.func_code.co_argcount if argcount == 1: self.on_unsubscribe(mid) elif argcount == 2 or argcount == 3: self.on_unsubscribe(self.obj, mid) class c_MosquittoMessage(Structure): """Internal message class used for communicating with C library. Don't use.""" _fields_ = [("mid", c_uint16), ("topic", c_char_p), ("payload", POINTER(c_uint8)), ("payloadlen", c_uint32), ("qos", c_int), ("retain", c_bool)] class MosquittoMessage: """MQTT message class""" def __init__(self, mid, topic, payloadlen, payload, qos, retain): self.mid = mid self.topic = topic self.payload = string_at(payload, payloadlen) self.qos = qos self.retain = retain #================================================== # Library loading #================================================== _libmosq = cdll.LoadLibrary(find_library("mosquitto")) _mosquitto_lib_init = _libmosq.mosquitto_lib_init _mosquitto_lib_init.argtypes = None _mosquitto_lib_init.restype = c_int _mosquitto_lib_cleanup = _libmosq.mosquitto_lib_cleanup _mosquitto_lib_cleanup.argtypes = None _mosquitto_lib_cleanup.restype = c_int _mosquitto_new = _libmosq.mosquitto_new _mosquitto_new.argtypes = [c_char_p, c_void_p] _mosquitto_new.restype = c_void_p _mosquitto_destroy = _libmosq.mosquitto_destroy _mosquitto_destroy.argtypes = [c_void_p] _mosquitto_destroy.restype = None _mosquitto_connect = _libmosq.mosquitto_connect _mosquitto_connect.argtypes = [c_void_p, c_char_p, c_int, c_int, c_bool] _mosquitto_connect.restype = c_int _mosquitto_reconnect = _libmosq.mosquitto_reconnect _mosquitto_reconnect.argtypes = [c_void_p] _mosquitto_reconnect.restype = c_int _mosquitto_disconnect = _libmosq.mosquitto_disconnect _mosquitto_disconnect.argtypes = [c_void_p] _mosquitto_disconnect.restype = c_int _mosquitto_publish = _libmosq.mosquitto_publish _mosquitto_publish.argtypes = [c_void_p, POINTER(c_uint16), c_char_p, c_uint32, POINTER(c_uint8), c_int, c_bool] _mosquitto_publish.restype = c_int _mosquitto_subscribe = _libmosq.mosquitto_subscribe _mosquitto_subscribe.argtypes = [c_void_p, POINTER(c_uint16), c_char_p, c_int] _mosquitto_subscribe.restype = c_int _mosquitto_unsubscribe = _libmosq.mosquitto_unsubscribe _mosquitto_unsubscribe.argtypes = [c_void_p, POINTER(c_uint16), c_char_p] _mosquitto_unsubscribe.restype = c_int _mosquitto_loop = _libmosq.mosquitto_loop _mosquitto_loop.argtypes = [c_void_p, c_int] _mosquitto_loop.restype = c_int _mosquitto_username_pw_set = _libmosq.mosquitto_username_pw_set _mosquitto_username_pw_set.argtypes = [c_void_p, c_char_p, c_char_p] _mosquitto_username_pw_set.restype = c_int _mosquitto_will_set = _libmosq.mosquitto_will_set _mosquitto_will_set.argtypes = [c_void_p, c_bool, c_char_p, c_uint32, POINTER(c_uint8), c_int, c_bool] _mosquitto_will_set.restype = c_int _mosquitto_log_init = _libmosq.mosquitto_log_init _mosquitto_log_init.argtypes = [c_void_p, c_int, c_int] _mosquitto_log_init.restype = c_int _mosquitto_connect_callback_set = _libmosq.mosquitto_connect_callback_set _mosquitto_connect_callback_set.argtypes = [c_void_p, c_void_p] _mosquitto_connect_callback_set.restype = None _mosquitto_disconnect_callback_set = _libmosq.mosquitto_disconnect_callback_set _mosquitto_disconnect_callback_set.argtypes = [c_void_p, c_void_p] _mosquitto_disconnect_callback_set.restype = None _mosquitto_publish_callback_set = _libmosq.mosquitto_publish_callback_set _mosquitto_publish_callback_set.argtypes = [c_void_p, c_void_p] _mosquitto_publish_callback_set.restype = None _mosquitto_message_callback_set = _libmosq.mosquitto_message_callback_set _mosquitto_message_callback_set.argtypes = [c_void_p, c_void_p] _mosquitto_message_callback_set.restype = None _mosquitto_subscribe_callback_set = _libmosq.mosquitto_subscribe_callback_set _mosquitto_subscribe_callback_set.argtypes = [c_void_p, c_void_p] _mosquitto_subscribe_callback_set.restype = None _mosquitto_unsubscribe_callback_set = _libmosq.mosquitto_unsubscribe_callback_set _mosquitto_unsubscribe_callback_set.argtypes = [c_void_p, c_void_p] _mosquitto_unsubscribe_callback_set.restype = None _MOSQ_CONNECT_FUNC = CFUNCTYPE(None, c_void_p, c_int) _MOSQ_DISCONNECT_FUNC = CFUNCTYPE(None, c_void_p) _MOSQ_PUBLISH_FUNC = CFUNCTYPE(None, c_void_p, c_uint16) _MOSQ_MESSAGE_FUNC = CFUNCTYPE(None, c_void_p, POINTER(c_MosquittoMessage)) _MOSQ_SUBSCRIBE_FUNC = CFUNCTYPE(None, c_void_p, c_uint16, c_int, POINTER(c_uint8)) _MOSQ_UNSUBSCRIBE_FUNC = CFUNCTYPE(None, c_void_p, c_uint16) #================================================== # End library loading #================================================== mosquitto-0.15/lib/python/setup.py0000664000175000017500000000046111713444064016331 0ustar rogerrogerfrom distutils.core import setup setup(name='mosquitto', version='0.15', description='MQTT version 3.1 client class', author='Roger Light', author_email='roger@atchoo.org', url='http://mosquitto.org/', download_url='http://mosquitto.org/files/', license='BSD License', py_modules=['mosquitto'] ) mosquitto-0.15/lib/python/readme.txt0000664000175000017500000000026511713444064016617 0ustar rogerrogerThis is my first attempt at a python wrapper. I'm not a python programmer so it works, but ain't pretty. If you can make it more pythonic I'd love to hear from you! Thanks, Roger mosquitto-0.15/lib/python/Makefile0000664000175000017500000000044111713444064016255 0ustar rogerrogerinclude ../../config.mk # Set DESTDIR if it isn't given DESTDIR?=/ .PHONY : all clean install all : mosquitto.pyc install : all python ./setup.py install --prefix=${prefix} --root=${DESTDIR} mosquitto.pyc : mosquitto.py python ./setup.py build clean : -rm -rf build mosquitto.pyc mosquitto-0.15/lib/send_mosq.c0000664000175000017500000001563111713444064015437 0ustar rogerroger/* Copyright (c) 2009-2011 Roger Light 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. */ #include #include #include #include #include #include #include #include #include #include #ifdef WITH_BROKER #include #endif int _mosquitto_send_pingreq(struct mosquitto *mosq) { 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, "Sending PINGREQ"); #endif return _mosquitto_send_simple_command(mosq, PINGREQ); } 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, "Sending PINGRESP"); #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, "Sending PUBACK (Mid: %d)", 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, "Sending PUBCOMP (Mid: %d)", 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 uint8_t *payload, int qos, bool retain, bool dup) { #ifdef WITH_BROKER int len; #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 += strlen(mosq->listener->mount_point); }else{ /* Invalid topic string. Should never happen, but silently swallow the message anyway. */ return MOSQ_ERR_SUCCESS; } } _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); #else _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Sending PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", 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, "Sending PUBREC (Mid: %d)", 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, "Sending PUBREL (Mid: %d)", 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 uint8_t *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); } mosquitto-0.15/lib/util_mosq.h0000664000175000017500000000352011713444064015462 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #ifndef _UTIL_MOSQ_H_ #define _UTIL_MOSQ_H_ #include int _mosquitto_packet_alloc(struct _mosquitto_packet *packet); void _mosquitto_check_keepalive(struct mosquitto *mosq); int _mosquitto_fix_sub_topic(char **subtopic); uint16_t _mosquitto_mid_generate(struct mosquitto *mosq); int _mosquitto_topic_wildcard_len_check(const char *str); #endif mosquitto-0.15/lib/messages_mosq.h0000664000175000017500000000436711713444064016326 0ustar rogerroger/* Copyright (c) 2010, Roger Light 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. */ #ifndef _MESSAGES_MOSQ_H_ #define _MESSAGES_MOSQ_H_ #include #include 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); 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_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, enum mosquitto_msg_state state); #endif mosquitto-0.15/lib/net_mosq.c0000664000175000017500000003616411713444064015300 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #include #include #include #include #ifndef WIN32 #include #include #include #else #include #include #endif #ifdef __SYMBIAN32__ #include #endif #ifdef __QNX__ #ifndef AI_ADDRCONFIG #define AI_ADDRCONFIG 0 #endif #include #include #endif #ifdef WITH_BROKER # include extern uint64_t bytes_received; extern uint64_t bytes_sent; extern unsigned long msgs_received; extern unsigned long msgs_sent; #else # include #endif #ifndef WIN32 # define COMPAT_ECONNRESET ECONNRESET # define COMPAT_EWOULDBLOCK EWOULDBLOCK #else # define COMPAT_EWOULDBLOCK WSAEWOULDBLOCK #endif #include #include #include void _mosquitto_net_init(void) { #ifdef WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); #endif #ifdef WITH_SSL SSL_library_init(); OpenSSL_add_all_algorithms(); #endif } void _mosquitto_net_cleanup(void) { #ifdef WIN32 WSACleanup(); #endif } void _mosquitto_packet_cleanup(struct _mosquitto_packet *packet) { if(!packet) return; /* Free data and reset values */ packet->command = 0; packet->have_remaining = 0; packet->remaining_count = 0; packet->remaining_mult = 1; packet->remaining_length = 0; if(packet->payload) _mosquitto_free(packet->payload); packet->payload = NULL; packet->to_process = 0; packet->pos = 0; } int _mosquitto_packet_queue(struct mosquitto *mosq, struct _mosquitto_packet *packet) { struct _mosquitto_packet *tail; assert(mosq); assert(packet); packet->pos = 0; packet->to_process = packet->packet_length; packet->next = NULL; if(mosq->out_packet){ tail = mosq->out_packet; while(tail->next){ tail = tail->next; } tail->next = packet; }else{ mosq->out_packet = packet; } #ifdef WITH_BROKER return _mosquitto_packet_write(mosq); #else if(mosq->in_callback == false){ return _mosquitto_packet_write(mosq); }else{ return MOSQ_ERR_SUCCESS; } #endif } /* Close a socket associated with a context and set it to -1. * Returns 1 on failure (context is NULL) * Returns 0 on success. */ int _mosquitto_socket_close(struct mosquitto *mosq) { int rc = 0; assert(mosq); /* FIXME - need to shutdown SSL here. */ if(mosq->sock != INVALID_SOCKET){ rc = COMPAT_CLOSE(mosq->sock); mosq->sock = INVALID_SOCKET; } return rc; } /* Create a socket and connect it to 'ip' on port 'port'. * Returns -1 on failure (ip is NULL, socket creation/connection error) * Returns sock number on success. */ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port) { int sock = INVALID_SOCKET; int opt; struct addrinfo hints; struct addrinfo *ainfo, *rp; int s; #ifdef WIN32 uint32_t val = 1; #endif #ifdef WITH_SSL int ret; #endif if(!mosq || !host || !port) return MOSQ_ERR_INVAL; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; s = getaddrinfo(host, NULL, &hints, &ainfo); if(s) return MOSQ_ERR_UNKNOWN; for(rp = ainfo; rp != NULL; rp = rp->ai_next){ sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if(sock == INVALID_SOCKET) continue; if(rp->ai_family == PF_INET){ ((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port); }else if(rp->ai_family == PF_INET6){ ((struct sockaddr_in6 *)rp->ai_addr)->sin6_port = htons(port); }else{ continue; } if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1){ break; } #ifdef WIN32 errno = WSAGetLastError(); #endif COMPAT_CLOSE(sock); } if(!rp){ return MOSQ_ERR_ERRNO; } freeaddrinfo(ainfo); #ifdef WITH_SSL if(mosq->ssl){ mosq->ssl->bio = BIO_new_socket(sock, BIO_NOCLOSE); if(!mosq->ssl->bio){ COMPAT_CLOSE(sock); return MOSQ_ERR_SSL; } SSL_set_bio(mosq->ssl->ssl, mosq->ssl->bio, mosq->ssl->bio); ret = SSL_connect(mosq->ssl->ssl); if(ret != 1){ COMPAT_CLOSE(sock); return MOSQ_ERR_SSL; } } #endif /* Set non-blocking */ #ifndef WIN32 opt = fcntl(sock, F_GETFL, 0); if(opt == -1 || fcntl(sock, F_SETFL, opt | O_NONBLOCK) == -1){ #ifdef WITH_SSL if(mosq->ssl){ _mosquitto_free(mosq->ssl); mosq->ssl = NULL; } #endif COMPAT_CLOSE(sock); return MOSQ_ERR_ERRNO; } #else if(ioctlsocket(sock, FIONBIO, &val)){ errno = WSAGetLastError(); #ifdef WITH_SSL if(mosq->ssl){ _mosquitto_free(mosq->ssl); mosq->ssl = NULL; } #endif COMPAT_CLOSE(sock); return MOSQ_ERR_ERRNO; } #endif mosq->sock = sock; return MOSQ_ERR_SUCCESS; } int _mosquitto_read_byte(struct _mosquitto_packet *packet, uint8_t *byte) { assert(packet); if(packet->pos+1 > packet->remaining_length) return MOSQ_ERR_PROTOCOL; *byte = packet->payload[packet->pos]; packet->pos++; return MOSQ_ERR_SUCCESS; } void _mosquitto_write_byte(struct _mosquitto_packet *packet, uint8_t byte) { assert(packet); assert(packet->pos+1 <= packet->packet_length); packet->payload[packet->pos] = byte; packet->pos++; } int _mosquitto_read_bytes(struct _mosquitto_packet *packet, uint8_t *bytes, uint32_t count) { assert(packet); if(packet->pos+count > packet->remaining_length) return MOSQ_ERR_PROTOCOL; memcpy(bytes, &(packet->payload[packet->pos]), count); packet->pos += count; return MOSQ_ERR_SUCCESS; } void _mosquitto_write_bytes(struct _mosquitto_packet *packet, const uint8_t *bytes, uint32_t count) { assert(packet); assert(packet->pos+count <= packet->packet_length); memcpy(&(packet->payload[packet->pos]), bytes, count); packet->pos += count; } int _mosquitto_read_string(struct _mosquitto_packet *packet, char **str) { uint16_t len; int rc; assert(packet); rc = _mosquitto_read_uint16(packet, &len); if(rc) return rc; if(packet->pos+len > packet->remaining_length) return MOSQ_ERR_PROTOCOL; *str = _mosquitto_calloc(len+1, sizeof(char)); if(*str){ memcpy(*str, &(packet->payload[packet->pos]), len); packet->pos += len; }else{ return MOSQ_ERR_NOMEM; } return MOSQ_ERR_SUCCESS; } void _mosquitto_write_string(struct _mosquitto_packet *packet, const char *str, uint16_t length) { assert(packet); _mosquitto_write_uint16(packet, length); _mosquitto_write_bytes(packet, (uint8_t *)str, length); } int _mosquitto_read_uint16(struct _mosquitto_packet *packet, uint16_t *word) { uint8_t msb, lsb; assert(packet); if(packet->pos+2 > packet->remaining_length) return MOSQ_ERR_PROTOCOL; msb = packet->payload[packet->pos]; packet->pos++; lsb = packet->payload[packet->pos]; packet->pos++; *word = (msb<<8) + lsb; return MOSQ_ERR_SUCCESS; } void _mosquitto_write_uint16(struct _mosquitto_packet *packet, uint16_t word) { _mosquitto_write_byte(packet, MOSQ_MSB(word)); _mosquitto_write_byte(packet, MOSQ_LSB(word)); } ssize_t _mosquitto_net_read(struct mosquitto *mosq, void *buf, size_t count) { #ifdef WITH_SSL int ret; int err; #endif assert(mosq); #ifdef WITH_SSL if(mosq->ssl){ ret = SSL_read(mosq->ssl->ssl, buf, count); if(ret < 0){ err = SSL_get_error(mosq->ssl->ssl, ret); if(err == SSL_ERROR_WANT_READ){ ret = -1; mosq->ssl->want_read = true; errno = EAGAIN; }else if(err == SSL_ERROR_WANT_WRITE){ ret = -1; mosq->ssl->want_write = true; errno = EAGAIN; } } return (ssize_t )ret; }else{ /* Call normal read/recv */ #endif #ifndef WIN32 return read(mosq->sock, buf, count); #else return recv(mosq->sock, buf, count, 0); #endif #ifdef WITH_SSL } #endif } ssize_t _mosquitto_net_write(struct mosquitto *mosq, void *buf, size_t count) { #ifdef WITH_SSL int ret; int err; #endif assert(mosq); #ifdef WITH_SSL if(mosq->ssl){ ret = SSL_write(mosq->ssl->ssl, buf, count); if(ret < 0){ err = SSL_get_error(mosq->ssl->ssl, ret); if(err == SSL_ERROR_WANT_READ){ ret = -1; mosq->ssl->want_read = true; }else if(err == SSL_ERROR_WANT_WRITE){ ret = -1; mosq->ssl->want_write = true; } } return (ssize_t )ret; }else{ /* Call normal write/send */ #endif #ifndef WIN32 return write(mosq->sock, buf, count); #else return send(mosq->sock, buf, count, 0); #endif #ifdef WITH_SSL } #endif } int _mosquitto_packet_write(struct mosquitto *mosq) { ssize_t write_length; struct _mosquitto_packet *packet; if(!mosq) return MOSQ_ERR_INVAL; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; while(mosq->out_packet){ packet = mosq->out_packet; while(packet->to_process > 0){ write_length = _mosquitto_net_write(mosq, &(packet->payload[packet->pos]), packet->to_process); if(write_length > 0){ #ifdef WITH_BROKER bytes_sent += write_length; #endif packet->to_process -= write_length; packet->pos += write_length; }else{ #ifdef WIN32 errno = WSAGetLastError(); #endif if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ return MOSQ_ERR_SUCCESS; }else{ switch(errno){ case COMPAT_ECONNRESET: return MOSQ_ERR_CONN_LOST; default: return MOSQ_ERR_ERRNO; } } } } #ifdef WITH_BROKER msgs_sent++; #else if(((packet->command)&0xF6) == PUBLISH && mosq->on_publish){ /* This is a QoS=0 message */ mosq->in_callback = true; mosq->on_publish(mosq->obj, packet->mid); mosq->in_callback = false; } #endif /* Free data and reset values */ mosq->out_packet = packet->next; _mosquitto_packet_cleanup(packet); _mosquitto_free(packet); mosq->last_msg_out = time(NULL); } return MOSQ_ERR_SUCCESS; } #ifdef WITH_BROKER int _mosquitto_packet_read(mosquitto_db *db, int context_index) #else int _mosquitto_packet_read(struct mosquitto *mosq) #endif { uint8_t byte; ssize_t read_length; int rc = 0; #ifdef WITH_BROKER struct mosquitto *mosq; if(context_index < 0 || context_index >= db->context_count) return MOSQ_ERR_INVAL; mosq = db->contexts[context_index]; #endif if(!mosq) return MOSQ_ERR_INVAL; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; /* This gets called if pselect() indicates that there is network data * available - ie. at least one byte. What we do depends on what data we * already have. * If we've not got a command, attempt to read one and save it. This should * always work because it's only a single byte. * Then try to read the remaining length. This may fail because it is may * be more than one byte - will need to save data pending next read if it * does fail. * Then try to read the remaining payload, where 'payload' here means the * combined variable header and actual payload. This is the most likely to * fail due to longer length, so save current data and current position. * After all data is read, send to _mosquitto_handle_packet() to deal with. * Finally, free the memory and reset everything to starting conditions. */ if(!mosq->in_packet.command){ read_length = _mosquitto_net_read(mosq, &byte, 1); if(read_length == 1){ mosq->in_packet.command = byte; #ifdef WITH_BROKER bytes_received++; /* Clients must send CONNECT as their first command. */ if(!(mosq->bridge) && mosq->state == mosq_cs_new && (byte&0xF0) != CONNECT) return MOSQ_ERR_PROTOCOL; #endif }else{ if(read_length == 0) return MOSQ_ERR_CONN_LOST; /* EOF */ #ifdef WIN32 errno = WSAGetLastError(); #endif if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ return MOSQ_ERR_SUCCESS; }else{ switch(errno){ case COMPAT_ECONNRESET: return MOSQ_ERR_CONN_LOST; default: return MOSQ_ERR_ERRNO; } } } } if(!mosq->in_packet.have_remaining){ /* Read remaining * Algorithm for decoding taken from pseudo code at * http://publib.boulder.ibm.com/infocenter/wmbhelp/v6r0m0/topic/com.ibm.etools.mft.doc/ac10870_.htm */ do{ read_length = _mosquitto_net_read(mosq, &byte, 1); if(read_length == 1){ mosq->in_packet.remaining_count++; /* Max 4 bytes length for remaining length as defined by protocol. * Anything more likely means a broken/malicious client. */ if(mosq->in_packet.remaining_count > 4) return MOSQ_ERR_PROTOCOL; #ifdef WITH_BROKER bytes_received++; #endif mosq->in_packet.remaining_length += (byte & 127) * mosq->in_packet.remaining_mult; mosq->in_packet.remaining_mult *= 128; }else{ if(read_length == 0) return MOSQ_ERR_CONN_LOST; /* EOF */ #ifdef WIN32 errno = WSAGetLastError(); #endif if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ return MOSQ_ERR_SUCCESS; }else{ switch(errno){ case COMPAT_ECONNRESET: return MOSQ_ERR_CONN_LOST; default: return MOSQ_ERR_ERRNO; } } } }while((byte & 128) != 0); if(mosq->in_packet.remaining_length > 0){ mosq->in_packet.payload = _mosquitto_malloc(mosq->in_packet.remaining_length*sizeof(uint8_t)); if(!mosq->in_packet.payload) return MOSQ_ERR_NOMEM; mosq->in_packet.to_process = mosq->in_packet.remaining_length; } mosq->in_packet.have_remaining = 1; } while(mosq->in_packet.to_process>0){ read_length = _mosquitto_net_read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process); if(read_length > 0){ #ifdef WITH_BROKER bytes_received += read_length; #endif mosq->in_packet.to_process -= read_length; mosq->in_packet.pos += read_length; }else{ #ifdef WIN32 errno = WSAGetLastError(); #endif if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ return MOSQ_ERR_SUCCESS; }else{ switch(errno){ case COMPAT_ECONNRESET: return MOSQ_ERR_CONN_LOST; default: return MOSQ_ERR_ERRNO; } } } } /* All data for this packet is read. */ mosq->in_packet.pos = 0; #ifdef WITH_BROKER msgs_received++; rc = mqtt3_packet_handle(db, context_index); #else rc = _mosquitto_packet_handle(mosq); #endif /* Free data and reset values */ _mosquitto_packet_cleanup(&mosq->in_packet); mosq->last_msg_in = time(NULL); return rc; } mosquitto-0.15/lib/cpp/0000775000175000017500000000000011713444064014057 5ustar rogerrogermosquitto-0.15/lib/cpp/CMakeLists.txt0000664000175000017500000000107411713444064016621 0ustar rogerrogerinclude_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 libmosquitto) set_target_properties(mosquittopp PROPERTIES VERSION ${VERSION} SOVERSION 0 ) 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) mosquitto-0.15/lib/cpp/mosquittopp.cpp0000664000175000017500000001164711713444064017200 0ustar rogerroger/* Copyright (c) 2010, Roger Light 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. */ #include #include #include namespace mosquittopp { static void on_connect_wrapper(void *obj, int rc) { class mosquittopp *m = (class mosquittopp *)obj; m->on_connect(rc); } static void on_disconnect_wrapper(void *obj) { class mosquittopp *m = (class mosquittopp *)obj; m->on_disconnect(); } static void on_publish_wrapper(void *obj, uint16_t mid) { class mosquittopp *m = (class mosquittopp *)obj; m->on_publish(mid); } static void on_message_wrapper(void *obj, const struct mosquitto_message *message) { class mosquittopp *m = (class mosquittopp *)obj; m->on_message(message); } static void on_subscribe_wrapper(void *obj, uint16_t mid, int qos_count, const uint8_t *granted_qos) { class mosquittopp *m = (class mosquittopp *)obj; m->on_subscribe(mid, qos_count, granted_qos); } static void on_unsubscribe_wrapper(void *obj, uint16_t mid) { class mosquittopp *m = (class mosquittopp *)obj; m->on_unsubscribe(mid); } void mosquittopp::lib_version(int *major, int *minor, int *revision) { if(major) *major = LIBMOSQUITTO_MAJOR; if(minor) *minor = LIBMOSQUITTO_MINOR; if(revision) *revision = LIBMOSQUITTO_REVISION; } int mosquittopp::lib_init() { return mosquitto_lib_init(); } int mosquittopp::lib_cleanup() { return mosquitto_lib_cleanup(); } mosquittopp::mosquittopp(const char *id) { mosq = mosquitto_new(id, this); mosquitto_connect_callback_set(mosq, on_connect_wrapper); mosquitto_disconnect_callback_set(mosq, on_disconnect_wrapper); mosquitto_publish_callback_set(mosq, on_publish_wrapper); mosquitto_message_callback_set(mosq, on_message_wrapper); mosquitto_subscribe_callback_set(mosq, on_subscribe_wrapper); mosquitto_unsubscribe_callback_set(mosq, on_unsubscribe_wrapper); } mosquittopp::~mosquittopp() { mosquitto_destroy(mosq); } int mosquittopp::connect(const char *host, int port, int keepalive, bool clean_session) { return mosquitto_connect(mosq, host, port, keepalive, clean_session); } int mosquittopp::reconnect() { return mosquitto_reconnect(mosq); } int mosquittopp::disconnect() { return mosquitto_disconnect(mosq); } int mosquittopp::socket() { return mosquitto_socket(mosq); } int mosquittopp::log_init(int priorities, int destinations) { return mosquitto_log_init(mosq, priorities, destinations); } int mosquittopp::will_set(bool will, const char *topic, uint32_t payloadlen, const uint8_t *payload, int qos, bool retain) { return mosquitto_will_set(mosq, will, topic, payloadlen, payload, qos, retain); } int mosquittopp::username_pw_set(const char *username, const char *password) { return mosquitto_username_pw_set(mosq, username, password); } int mosquittopp::publish(uint16_t *mid, const char *topic, uint32_t payloadlen, const uint8_t *payload, int qos, bool retain) { return mosquitto_publish(mosq, mid, topic, payloadlen, payload, qos, retain); } void mosquittopp::message_retry_set(unsigned int message_retry) { mosquitto_message_retry_set(mosq, message_retry); } int mosquittopp::subscribe(uint16_t *mid, const char *sub, int qos) { return mosquitto_subscribe(mosq, mid, sub, qos); } int mosquittopp::unsubscribe(uint16_t *mid, const char *sub) { return mosquitto_unsubscribe(mosq, mid, sub); } int mosquittopp::loop(int timeout) { return mosquitto_loop(mosq, timeout); } int mosquittopp::loop_misc() { return mosquitto_loop_misc(mosq); } int mosquittopp::loop_read() { return mosquitto_loop_read(mosq); } int mosquittopp::loop_write() { return mosquitto_loop_write(mosq); } } mosquitto-0.15/lib/cpp/mosquittopp.h0000664000175000017500000000657511713444064016651 0ustar rogerroger/* Copyright (c) 2010, Roger Light 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. */ #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 #include #include namespace mosquittopp { /* * 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 *mosq; public: mosquittopp(const char *id); ~mosquittopp(); static void lib_version(int *major, int *minor, int *revision); static int lib_init(); static int lib_cleanup(); int socket(); int log_init(int priorities, int destinations); int will_set(bool will, const char *topic, uint32_t payloadlen=0, const uint8_t *payload=NULL, int qos=0, bool retain=false); int username_pw_set(const char *username, const char *password=NULL); int connect(const char *host, int port=1883, int keepalive=60, bool clean_session=true); int reconnect(); int disconnect(); int publish(uint16_t *mid, const char *topic, uint32_t payloadlen=0, const uint8_t *payload=NULL, int qos=0, bool retain=false); int subscribe(uint16_t *mid, const char *sub, int qos=0); int unsubscribe(uint16_t *mid, const char *sub); void message_retry_set(unsigned int message_retry); int loop(int timeout=-1); int loop_misc(); int loop_read(); int loop_write(); virtual void on_connect(int rc) {return;}; virtual void on_disconnect() {return;}; virtual void on_publish(uint16_t mid) {return;}; virtual void on_message(const struct mosquitto_message *message) {return;}; virtual void on_subscribe(uint16_t mid, int qos_count, const uint8_t *granted_qos) {return;}; virtual void on_unsubscribe(uint16_t mid) {return;}; virtual void on_error() {return;}; }; } #endif mosquitto-0.15/lib/cpp/Makefile0000664000175000017500000000155611713444064015526 0ustar rogerrogerinclude ../../config.mk .PHONY : clean install all : libmosquittopp.so.0 install : all $(INSTALL) -d ${DESTDIR}$(prefix)/lib${LIB_SUFFIX}/ $(INSTALL) -s libmosquittopp.so.0 ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquittopp.so.0 ln -sf libmosquittopp.so.0 ${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.0 -rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquittopp.so -rm -f ${DESTDIR}${prefix}/include/mosquittopp.h clean : -rm -f *.o libmosquittopp.so.0 libmosquittopp.so.0 : mosquittopp.o $(CXX) -shared -Wl,--as-needed -Wl,-soname,libmosquittopp.so.0 $< -o $@ ../libmosquitto.so.0 mosquittopp.o : mosquittopp.cpp mosquittopp.h $(CXX) $(CFLAGS) -fPIC -c $< -o $@ mosquitto-0.15/lib/util_mosq.c0000664000175000017500000001173111713444064015460 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #include #include #include #include #include #include #include #ifdef WITH_BROKER #include #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; iremaining_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) { 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 && time(NULL) - 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 if(mosq->sock != INVALID_SOCKET && time(NULL) - mosq->last_msg_out >= mosq->keepalive){ if(mosq->state == mosq_cs_connected){ _mosquitto_send_pingreq(mosq); }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); } } } /* Convert ////some////over/slashed///topic/etc/etc// * into some/over/slashed/topic/etc/etc */ int _mosquitto_fix_sub_topic(char **subtopic) { char *fixed = NULL; char *token; char *saveptr = NULL; assert(subtopic); assert(*subtopic); /* size of fixed here is +1 for the terminating 0 and +1 for the spurious / * that gets appended. */ fixed = _mosquitto_calloc(strlen(*subtopic)+2, 1); if(!fixed) return MOSQ_ERR_NOMEM; if((*subtopic)[0] == '/'){ fixed[0] = '/'; } token = strtok_r(*subtopic, "/", &saveptr); while(token){ strcat(fixed, token); strcat(fixed, "/"); token = strtok_r(NULL, "/", &saveptr); } fixed[strlen(fixed)-1] = '\0'; _mosquitto_free(*subtopic); *subtopic = fixed; return MOSQ_ERR_SUCCESS; } 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; } mosquitto-0.15/lib/mosquitto_internal.h0000664000175000017500000000752111713444064017413 0ustar rogerroger/* Copyright (c) 2010,2011 Roger Light 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. */ #ifndef _MOSQUITTO_INTERNAL_H_ #define _MOSQUITTO_INTERNAL_H_ #include #ifdef WITH_SSL #include #endif #include #include #ifdef WIN32 #include #endif #include #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_wait_puback = 1, mosq_ms_wait_pubrec = 2, mosq_ms_wait_pubrel = 3, mosq_ms_wait_pubcomp = 4 }; enum mosquitto_client_state { mosq_cs_new = 0, mosq_cs_connected = 1, mosq_cs_disconnecting = 2 }; 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; }; #ifdef WITH_SSL struct _mosquitto_ssl{ SSL_CTX *ssl_ctx; SSL *ssl; BIO *bio; bool want_read; bool want_write; }; #endif struct mosquitto { #ifndef WIN32 int sock; #else SOCKET sock; #endif 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; uint16_t last_mid; struct _mosquitto_packet in_packet; struct _mosquitto_packet *out_packet; struct mosquitto_message *will; #ifdef WITH_SSL struct _mosquitto_ssl *ssl; #endif #ifdef WITH_BROKER struct _mqtt3_bridge *bridge; struct _mosquitto_client_msg *msgs; struct _mosquitto_acl_user *acl_list; struct _mqtt3_listener *listener; #else void *obj; bool in_callback; unsigned int message_retry; time_t last_retry_check; struct mosquitto_message_all *messages; int log_priorities; int log_destinations; void (*on_connect)(void *obj, int rc); void (*on_disconnect)(void *obj); void (*on_publish)(void *obj, uint16_t mid); void (*on_message)(void *obj, const struct mosquitto_message *message); void (*on_subscribe)(void *obj, uint16_t mid, int qos_count, const uint8_t *granted_qos); void (*on_unsubscribe)(void *obj, uint16_t mid); //void (*on_error)(); char *host; int port; #endif }; #endif mosquitto-0.15/lib/will_mosq.h0000664000175000017500000000335011713444064015455 0ustar rogerroger/* Copyright (c) 2010,2011 Roger Light 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. */ #ifndef _WILL_MOSQ_H_ #define _WILL_MOSQ_H_ #include #include int _mosquitto_will_set(struct mosquitto *mosq, bool will, const char *topic, uint32_t payloadlen, const uint8_t *payload, int qos, bool retain); #endif mosquitto-0.15/lib/read_handle_shared.c0000664000175000017500000001562311713444064017224 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WITH_BROKER #include #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, "Received PINGREQ"); #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 #ifdef WITH_BROKER _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Received PINGRESP from %s", mosq->id); #else _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Received PINGRESP"); #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, "Received %s (Mid: %d)", type, mid); if(!_mosquitto_message_delete(mosq, mid, mosq_md_out)){ /* Only inform the client the message has been sent once. */ if(mosq->on_publish){ mosq->in_callback = true; mosq->on_publish(mosq->obj, mid); mosq->in_callback = false; } } #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, ms_wait_pubcomp); #else _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Received PUBREC (Mid: %d)", mid); rc = _mosquitto_message_update(mosq, mid, mosq_md_out, mosq_ms_wait_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 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); mqtt3_db_message_release(db, mosq, mid, mosq_md_in); #else _mosquitto_log_printf(mosq, MOSQ_LOG_DEBUG, "Received PUBREL (Mid: %d)", 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. */ if(mosq->on_message){ mosq->in_callback = true; mosq->on_message(mosq->obj, &message->msg); mosq->in_callback = false; }else{ _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 *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, "Received SUBACK"); #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(uint8_t)); if(!granted_qos) return MOSQ_ERR_NOMEM; while(mosq->in_packet.pos < mosq->in_packet.remaining_length){ rc = _mosquitto_read_byte(&mosq->in_packet, &(granted_qos[i])); if(rc){ _mosquitto_free(granted_qos); return rc; } i++; } #ifndef WITH_BROKER if(mosq->on_subscribe){ mosq->in_callback = true; mosq->on_subscribe(mosq->obj, mid, qos_count, granted_qos); mosq->in_callback = false; } #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, "Received UNSUBACK"); #endif rc = _mosquitto_read_uint16(&mosq->in_packet, &mid); if(rc) return rc; #ifndef WITH_BROKER if(mosq->on_unsubscribe){ mosq->in_callback = true; mosq->on_unsubscribe(mosq->obj, mid); mosq->in_callback = false; } #endif return MOSQ_ERR_SUCCESS; } mosquitto-0.15/lib/memory_mosq.h0000664000175000017500000000404111713444064016014 0ustar rogerroger/* Copyright (c) 2010, Roger Light 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. */ #ifndef _MEMORY_MOSQ_H_ #define _MEMORY_MOSQ_H_ #include #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 mosquitto-0.15/lib/read_handle.c0000664000175000017500000001173411713444064015675 0ustar rogerroger/* Copyright (c) 2009,2010, Roger Light 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. */ #include #include #include #include #include #include #include #include #include #include #include #include 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; assert(mosq); message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all)); if(!message) return MOSQ_ERR_NOMEM; header = mosq->in_packet.command; message->direction = mosq_md_in; 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; } rc = _mosquitto_fix_sub_topic(&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, &message->msg.mid); if(rc){ _mosquitto_message_cleanup(&message); return rc; } } 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)); _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, "Received PUBLISH (d%d, q%d, r%d, m%d, '%s', ... (%ld bytes))", message->dup, message->msg.qos, message->msg.retain, message->msg.mid, message->msg.topic, (long)message->msg.payloadlen); message->timestamp = time(NULL); switch(message->msg.qos){ case 0: if(mosq->on_message){ mosq->in_callback = true; mosq->on_message(mosq->obj, &message->msg); mosq->in_callback = false; } _mosquitto_message_cleanup(&message); return MOSQ_ERR_SUCCESS; case 1: rc = _mosquitto_send_puback(mosq, message->msg.mid); if(mosq->on_message){ mosq->in_callback = true; mosq->on_message(mosq->obj, &message->msg); mosq->in_callback = false; } _mosquitto_message_cleanup(&message); return rc; case 2: rc = _mosquitto_send_pubrec(mosq, message->msg.mid); message->state = mosq_ms_wait_pubrel; _mosquitto_message_queue(mosq, message); return rc; default: return MOSQ_ERR_PROTOCOL; } } mosquitto-0.15/lib/linker.version0000664000175000017500000000160011713444064016165 0ustar rogerroger/* Linker version script - currently used here primarily to control which * symbols are exported. */ VERS_0.9 { global: mosquitto_lib_version; mosquitto_lib_init; mosquitto_lib_cleanup; mosquitto_new; mosquitto_destroy; mosquitto_log_init; mosquitto_will_set; mosquitto_username_pw_set; mosquitto_connect; mosquitto_disconnect; mosquitto_publish; mosquitto_subscribe; mosquitto_unsubscribe; mosquitto_message_copy; mosquitto_message_free; mosquitto_loop; mosquitto_socket; 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_message_retry_set; local: *; }; VERS_0.12 { global: mosquitto_reconnect; } VERS_0.9; mosquitto-0.15/lib/messages_mosq.c0000664000175000017500000001332111713444064016307 0ustar rogerroger/* Copyright (c) 2010, Roger Light 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. */ #include #include #include #include #include #include #include #include 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->messages){ tmp = mosq->messages->next; _mosquitto_message_cleanup(&mosq->messages); mosq->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) { struct mosquitto_message_all *tail; assert(mosq); assert(message); message->next = NULL; if(mosq->messages){ tail = mosq->messages; while(tail->next){ tail = tail->next; } tail->next = message; }else{ mosq->messages = message; } } 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; assert(mosq); assert(message); cur = mosq->messages; while(cur){ if(cur->msg.mid == mid && cur->direction == dir){ if(prev){ prev->next = cur->next; }else{ mosq->messages = cur->next; } *message = cur; return MOSQ_ERR_SUCCESS; } prev = cur; cur = cur->next; } return MOSQ_ERR_NOT_FOUND; } void _mosquitto_message_retry_check(struct mosquitto *mosq) { struct mosquitto_message_all *message; time_t now = time(NULL); assert(mosq); message = mosq->messages; while(message){ if(message->timestamp + mosq->message_retry < now){ switch(message->state){ case mosq_ms_wait_puback: case mosq_ms_wait_pubrec: message->timestamp = now; message->dup = true; _mosquitto_send_publish(mosq, message->msg.mid, message->msg.topic, message->msg.payloadlen, message->msg.payload, message->msg.qos, message->msg.retain, message->dup); break; case mosq_ms_wait_pubrel: message->timestamp = now; _mosquitto_send_pubrec(mosq, message->msg.mid); break; case mosq_ms_wait_pubcomp: message->timestamp = now; _mosquitto_send_pubrel(mosq, message->msg.mid, true); break; default: break; } } message = message->next; } } void mosquitto_message_retry_set(struct mosquitto *mosq, unsigned int message_retry) { assert(mosq); if(mosq) mosq->message_retry = message_retry; } int _mosquitto_message_update(struct mosquitto *mosq, uint16_t mid, enum mosquitto_msg_direction dir, enum mosquitto_msg_state state) { struct mosquitto_message_all *message; assert(mosq); message = mosq->messages; while(message){ if(message->msg.mid == mid && message->direction == dir){ message->state = state; message->timestamp = time(NULL); return MOSQ_ERR_SUCCESS; } message = message->next; } return MOSQ_ERR_NOT_FOUND; } mosquitto-0.15/lib/mosquitto.c0000664000175000017500000003022411713444064015506 0ustar rogerroger/* Copyright (c) 2010-2012 Roger Light 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. */ #include #include #include #include #ifndef WIN32 #include #include #else #include typedef int ssize_t; #endif #include #include #include #include #include #include #include #include #include #include #include #ifndef ECONNRESET #define ECONNRESET 104 #endif #if !defined(WIN32) && defined(__SYMBIAN32__) #define HAVE_PSELECT #endif void mosquitto_lib_version(int *major, int *minor, int *revision) { if(major) *major = LIBMOSQUITTO_MAJOR; if(minor) *minor = LIBMOSQUITTO_MINOR; if(revision) *revision = LIBMOSQUITTO_REVISION; } int mosquitto_lib_init(void) { _mosquitto_net_init(); return MOSQ_ERR_SUCCESS; } int mosquitto_lib_cleanup(void) { _mosquitto_net_cleanup(); return MOSQ_ERR_SUCCESS; } struct mosquitto *mosquitto_new(const char *id, void *obj) { struct mosquitto *mosq = NULL; if(!id) return NULL; mosq = (struct mosquitto *)_mosquitto_calloc(1, sizeof(struct mosquitto)); if(mosq){ if(obj){ mosq->obj = obj; }else{ mosq->obj = mosq; } mosq->sock = INVALID_SOCKET; mosq->keepalive = 60; mosq->message_retry = 20; mosq->last_retry_check = 0; mosq->id = _mosquitto_strdup(id); mosq->username = NULL; mosq->password = NULL; mosq->in_packet.payload = NULL; _mosquitto_packet_cleanup(&mosq->in_packet); mosq->out_packet = NULL; mosq->last_msg_in = time(NULL); mosq->last_msg_out = time(NULL); mosq->last_mid = 0; mosq->state = mosq_cs_new; mosq->messages = NULL; mosq->will = NULL; mosq->on_connect = NULL; mosq->on_publish = NULL; mosq->on_message = NULL; mosq->on_subscribe = NULL; mosq->on_unsubscribe = NULL; mosq->log_destinations = MOSQ_LOG_NONE; mosq->log_priorities = MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE | MOSQ_LOG_INFO; mosq->host = NULL; mosq->port = 1883; mosq->in_callback = false; #ifdef WITH_SSL mosq->ssl = NULL; #endif } return mosq; } int mosquitto_will_set(struct mosquitto *mosq, bool will, const char *topic, uint32_t payloadlen, const uint8_t *payload, int qos, bool retain) { if(!mosq) return MOSQ_ERR_INVAL; return _mosquitto_will_set(mosq, will, topic, payloadlen, payload, qos, retain); } int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password) { if(!mosq) return MOSQ_ERR_INVAL; if(username){ mosq->username = _mosquitto_strdup(username); if(!mosq->username) return MOSQ_ERR_NOMEM; if(mosq->password){ _mosquitto_free(mosq->password); mosq->password = NULL; } if(password){ mosq->password = _mosquitto_strdup(password); if(!mosq->password){ _mosquitto_free(mosq->username); mosq->username = NULL; return MOSQ_ERR_NOMEM; } } }else{ if(mosq->username){ _mosquitto_free(mosq->username); mosq->username = NULL; } if(mosq->password){ _mosquitto_free(mosq->password); mosq->password = NULL; } } return MOSQ_ERR_SUCCESS; } void mosquitto_destroy(struct mosquitto *mosq) { if(mosq->id) _mosquitto_free(mosq->id); _mosquitto_message_cleanup_all(mosq); 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); } if(mosq->host){ _mosquitto_free(mosq->host); } #ifdef WITH_SSL if(mosq->ssl){ if(mosq->ssl->ssl){ SSL_free(mosq->ssl->ssl); } if(mosq->ssl->ssl_ctx){ SSL_CTX_free(mosq->ssl->ssl_ctx); } _mosquitto_free(mosq->ssl); } #endif _mosquitto_free(mosq); } int mosquitto_socket(struct mosquitto *mosq) { if(!mosq) return MOSQ_ERR_INVAL; return mosq->sock; } int mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive, bool clean_session) { if(!mosq) return MOSQ_ERR_INVAL; if(!host || port <= 0) return MOSQ_ERR_INVAL; if(mosq->host) _mosquitto_free(mosq->host); mosq->host = _mosquitto_strdup(host); if(!mosq->host) return MOSQ_ERR_NOMEM; mosq->port = port; mosq->keepalive = keepalive; mosq->clean_session = clean_session; return mosquitto_reconnect(mosq); } int mosquitto_reconnect(struct mosquitto *mosq) { int rc; if(!mosq) return MOSQ_ERR_INVAL; if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL; rc = _mosquitto_socket_connect(mosq, mosq->host, mosq->port); if(rc){ return rc; } return _mosquitto_send_connect(mosq, mosq->keepalive, mosq->clean_session); } int mosquitto_disconnect(struct mosquitto *mosq) { if(!mosq) return MOSQ_ERR_INVAL; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; mosq->state = mosq_cs_disconnecting; return _mosquitto_send_disconnect(mosq); } int mosquitto_publish(struct mosquitto *mosq, uint16_t *mid, const char *topic, uint32_t payloadlen, const uint8_t *payload, int qos, bool retain) { struct mosquitto_message_all *message; uint16_t local_mid; if(!mosq || !topic || qos<0 || qos>2) return MOSQ_ERR_INVAL; if(payloadlen > 268435455) return MOSQ_ERR_PAYLOAD_SIZE; if(_mosquitto_topic_wildcard_len_check(topic) != MOSQ_ERR_SUCCESS){ return MOSQ_ERR_INVAL; } local_mid = _mosquitto_mid_generate(mosq); if(mid){ *mid = local_mid; } if(qos == 0){ return _mosquitto_send_publish(mosq, local_mid, topic, payloadlen, payload, qos, retain, false); }else{ message = _mosquitto_calloc(1, sizeof(struct mosquitto_message_all)); if(!message) return MOSQ_ERR_NOMEM; message->next = NULL; message->timestamp = time(NULL); message->direction = mosq_md_out; if(qos == 1){ message->state = mosq_ms_wait_puback; }else if(qos == 2){ message->state = mosq_ms_wait_pubrec; } message->msg.mid = local_mid; message->msg.topic = _mosquitto_strdup(topic); if(!message->msg.topic){ _mosquitto_message_cleanup(&message); return MOSQ_ERR_NOMEM; } if(payloadlen){ message->msg.payloadlen = payloadlen; message->msg.payload = _mosquitto_malloc(payloadlen*sizeof(uint8_t)); if(!message->msg.payload){ _mosquitto_message_cleanup(&message); return MOSQ_ERR_NOMEM; } memcpy(message->msg.payload, payload, payloadlen*sizeof(uint8_t)); }else{ message->msg.payloadlen = 0; message->msg.payload = NULL; } message->msg.qos = qos; message->msg.retain = retain; message->dup = false; _mosquitto_message_queue(mosq, message); return _mosquitto_send_publish(mosq, message->msg.mid, message->msg.topic, message->msg.payloadlen, message->msg.payload, message->msg.qos, message->msg.retain, message->dup); } } int mosquitto_subscribe(struct mosquitto *mosq, uint16_t *mid, const char *sub, int qos) { if(!mosq) return MOSQ_ERR_INVAL; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; return _mosquitto_send_subscribe(mosq, mid, false, sub, qos); } int mosquitto_unsubscribe(struct mosquitto *mosq, uint16_t *mid, const char *sub) { if(!mosq) return MOSQ_ERR_INVAL; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; return _mosquitto_send_unsubscribe(mosq, mid, false, sub); } #if 0 int mosquitto_ssl_set(struct mosquitto *mosq, const char *pemfile, const char *password) { #ifdef WITH_SSL if(!mosq || mosq->ssl) return MOSQ_ERR_INVAL; //FIXME mosq->ssl = _mosquitto_malloc(sizeof(struct _mosquitto_ssl)); if(!mosq->ssl) return MOSQ_ERR_NOMEM; mosq->ssl->ssl_ctx = SSL_CTX_new(TLSv1_method()); if(!mosq->ssl->ssl_ctx) return MOSQ_ERR_SSL; mosq->ssl->ssl = SSL_new(mosq->ssl->ssl_ctx); return MOSQ_ERR_SUCCESS; #else return MOSQ_ERR_NOT_SUPPORTED; #endif } #endif int mosquitto_loop(struct mosquitto *mosq, int timeout) { #ifdef HAVE_PSELECT struct timespec local_timeout; #else struct timeval local_timeout; #endif fd_set readfds, writefds; int fdcount; int rc; if(!mosq) return MOSQ_ERR_INVAL; if(mosq->sock == INVALID_SOCKET) return MOSQ_ERR_NO_CONN; FD_ZERO(&readfds); FD_SET(mosq->sock, &readfds); FD_ZERO(&writefds); if(mosq->out_packet){ FD_SET(mosq->sock, &writefds); #ifdef WITH_SSL }else if(mosq->ssl && mosq->ssl->want_write){ FD_SET(mosq->sock, &writefds); #endif } if(timeout >= 0){ local_timeout.tv_sec = timeout/1000; #ifdef HAVE_PSELECT local_timeout.tv_nsec = (timeout-local_timeout.tv_sec*1000)*1e6; #else local_timeout.tv_usec = (timeout-local_timeout.tv_sec*1000)*1000; #endif }else{ local_timeout.tv_sec = 1; #ifdef HAVE_PSELECT local_timeout.tv_nsec = 0; #else local_timeout.tv_usec = 0; #endif } #ifdef HAVE_PSELECT fdcount = pselect(mosq->sock+1, &readfds, &writefds, NULL, &local_timeout, NULL); #else fdcount = select(mosq->sock+1, &readfds, &writefds, NULL, &local_timeout); #endif if(fdcount == -1){ #ifdef WIN32 errno = WSAGetLastError(); #endif return MOSQ_ERR_ERRNO; }else{ if(FD_ISSET(mosq->sock, &readfds)){ rc = mosquitto_loop_read(mosq); if(rc){ _mosquitto_socket_close(mosq); if(mosq->state == mosq_cs_disconnecting){ rc = MOSQ_ERR_SUCCESS; } if(mosq->on_disconnect){ mosq->in_callback = true; mosq->on_disconnect(mosq->obj); mosq->in_callback = false; } return rc; } } if(FD_ISSET(mosq->sock, &writefds)){ rc = mosquitto_loop_write(mosq); if(rc){ _mosquitto_socket_close(mosq); if(mosq->state == mosq_cs_disconnecting){ rc = MOSQ_ERR_SUCCESS; } if(mosq->on_disconnect){ mosq->in_callback = true; mosq->on_disconnect(mosq->obj); mosq->in_callback = false; } return rc; } } } mosquitto_loop_misc(mosq); return MOSQ_ERR_SUCCESS; } int mosquitto_loop_misc(struct mosquitto *mosq) { if(!mosq) return MOSQ_ERR_INVAL; _mosquitto_check_keepalive(mosq); if(mosq->last_retry_check+1 < time(NULL)){ _mosquitto_message_retry_check(mosq); mosq->last_retry_check = time(NULL); } return MOSQ_ERR_SUCCESS; } int mosquitto_loop_read(struct mosquitto *mosq) { return _mosquitto_packet_read(mosq); } int mosquitto_loop_write(struct mosquitto *mosq) { return _mosquitto_packet_write(mosq); } void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(void *, int)) { mosq->on_connect = on_connect; } void mosquitto_disconnect_callback_set(struct mosquitto *mosq, void (*on_disconnect)(void *)) { mosq->on_disconnect = on_disconnect; } void mosquitto_publish_callback_set(struct mosquitto *mosq, void (*on_publish)(void *, uint16_t)) { mosq->on_publish = on_publish; } void mosquitto_message_callback_set(struct mosquitto *mosq, void (*on_message)(void *, const struct mosquitto_message *)) { mosq->on_message = on_message; } void mosquitto_subscribe_callback_set(struct mosquitto *mosq, void (*on_subscribe)(void *, uint16_t, int, const uint8_t *)) { mosq->on_subscribe = on_subscribe; } void mosquitto_unsubscribe_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(void *, uint16_t)) { mosq->on_unsubscribe = on_unsubscribe; } mosquitto-0.15/lib/logging_mosq.h0000664000175000017500000000322311713444064016133 0ustar rogerroger/* Copyright (c) 2009,2010, Roger Light 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. */ #ifndef _LOGGING_MOSQ_H_ #define _LOGGING_MOSQ_H_ #include int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...); #endif mosquitto-0.15/lib/send_client_mosq.c0000664000175000017500000001246311713444064016775 0ustar rogerroger/* Copyright (c) 2009-2011 Roger Light 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. */ #include #include #include #include #include #include #include #include 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; 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, strlen(PROTOCOL_NAME)); _mosquitto_write_byte(packet, PROTOCOL_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; return _mosquitto_packet_queue(mosq, packet); } int _mosquitto_send_disconnect(struct mosquitto *mosq) { assert(mosq); return _mosquitto_send_simple_command(mosq, DISCONNECT); } int _mosquitto_send_subscribe(struct mosquitto *mosq, uint16_t *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 = local_mid; _mosquitto_write_uint16(packet, local_mid); /* Payload */ _mosquitto_write_string(packet, topic, strlen(topic)); _mosquitto_write_byte(packet, topic_qos); return _mosquitto_packet_queue(mosq, packet); } int _mosquitto_send_unsubscribe(struct mosquitto *mosq, uint16_t *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 = local_mid; _mosquitto_write_uint16(packet, local_mid); /* Payload */ _mosquitto_write_string(packet, topic, strlen(topic)); return _mosquitto_packet_queue(mosq, packet); } mosquitto-0.15/lib/memory_mosq.c0000664000175000017500000000623511713444064016016 0ustar rogerroger/* Copyright (c) 2009,2010, Roger Light 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. */ #include #include #include #include #ifdef REAL_WITH_MEMORY_TRACKING # if defined(__APPLE__) # define malloc_usable_size malloc_good_size # else # include # endif #endif #include #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; } mosquitto-0.15/lib/send_mosq.h0000664000175000017500000000543711713444064015447 0ustar rogerroger/* Copyright (c) 2010, Roger Light 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. */ #ifndef _SEND_MOSQ_H_ #define _SEND_MOSQ_H_ #include 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 uint8_t *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 uint8_t *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, uint16_t *mid, bool dup, const char *topic, uint8_t topic_qos); int _mosquitto_send_unsubscribe(struct mosquitto *mosq, uint16_t *mid, bool dup, const char *topic); #endif mosquitto-0.15/lib/logging_mosq.c0000664000175000017500000000505111713444064016127 0ustar rogerroger/* Copyright (c) 2009,2010, Roger Light 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. */ #include #include #include #include #include #include #include int mosquitto_log_init(struct mosquitto *mosq, int priorities, int destinations) { assert(mosq); mosq->log_priorities = priorities; mosq->log_destinations = destinations; return MOSQ_ERR_SUCCESS; } int _mosquitto_log_printf(struct mosquitto *mosq, int priority, const char *fmt, ...) { va_list va; char *s; int len; assert(mosq); assert(fmt); if((mosq->log_priorities & priority) && mosq->log_destinations != MOSQ_LOG_NONE){ len = strlen(fmt) + 500; s = _mosquitto_malloc(len*sizeof(char)); if(!s) 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. */ if(mosq->log_destinations & MOSQ_LOG_STDOUT){ fprintf(stdout, "%s\n", s); fflush(stdout); } if(mosq->log_destinations & MOSQ_LOG_STDERR){ fprintf(stderr, "%s\n", s); fflush(stderr); } _mosquitto_free(s); } return MOSQ_ERR_SUCCESS; } mosquitto-0.15/lib/Makefile0000664000175000017500000000400711713444064014736 0ustar rogerrogerinclude ../config.mk .PHONY : clean install all : libmosquitto.so.0 make -C cpp make -C python install : all $(INSTALL) -d ${DESTDIR}$(prefix)/lib${LIB_SUFFIX}/ $(INSTALL) -s libmosquitto.so.0 ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so.0 ln -sf libmosquitto.so.0 ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so $(INSTALL) -d ${DESTDIR}${prefix}/include/ $(INSTALL) mosquitto.h ${DESTDIR}${prefix}/include/mosquitto.h make -C cpp install make -C python install uninstall : -rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so.0 -rm -f ${DESTDIR}${prefix}/lib${LIB_SUFFIX}/libmosquitto.so -rm -f ${DESTDIR}${prefix}/include/mosquitto.h clean : -rm -f *.o libmosquitto.so.0 libmosquitto.so make -C cpp clean make -C python clean libmosquitto.so.0 : 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 util_mosq.o will_mosq.o $(CC) -shared -Wl,--as-needed -Wl,--version-script=linker.version -Wl,-soname,libmosquitto.so.0 $^ -o $@ ${LIBS} mosquitto.o : mosquitto.c mosquitto.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ logging_mosq.o : logging_mosq.c logging_mosq.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ messages_mosq.o : messages_mosq.c messages_mosq.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ memory_mosq.o : memory_mosq.c memory_mosq.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ net_mosq.o : net_mosq.c net_mosq.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ read_handle.o : read_handle.c read_handle.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ read_handle_client.o : read_handle_client.c read_handle.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ read_handle_shared.o : read_handle_shared.c read_handle.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ send_mosq.o : send_mosq.c send_mosq.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ send_client_mosq.o : send_client_mosq.c send_mosq.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ util_mosq.o : util_mosq.c util_mosq.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ will_mosq.o : will_mosq.c will_mosq.h $(CC) $(CFLAGS) -fPIC -c $< -o $@ mosquitto-0.15/lib/mqtt3_protocol.h0000664000175000017500000000371711713444064016447 0ustar rogerroger/* Copyright (c) 2009,2010, Roger Light 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. */ #ifndef _MQTT3_PROTOCOL_H_ #define _MQTT3_PROTOCOL_H_ /* For version 3 of the MQTT protocol */ #define PROTOCOL_NAME "MQIsdp" #define PROTOCOL_VERSION 3 /* 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 #endif mosquitto-0.15/lib/read_handle.h0000664000175000017500000000423711713444064015702 0ustar rogerroger/* Copyright (c) 2010, Roger Light 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. */ #ifndef _READ_HANDLE_H_ #define _READ_HANDLE_H_ #include 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 mosquitto-0.15/man/0000775000175000017500000000000011713444064013302 5ustar rogerrogermosquitto-0.15/man/po/0000775000175000017500000000000011713444064013720 5ustar rogerrogermosquitto-0.15/man/po/mqtt/0000775000175000017500000000000011713444064014705 5ustar rogerrogermosquitto-0.15/man/po/mqtt/mqtt.7.pot0000664000175000017500000001731311713444064016570 0ustar rogerrogermsgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2011-04-29 17:23+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: mqtt.7.xml:7(refentrytitle) mqtt.7.xml:12(refname) mqtt.7.xml:18(command) msgid "mqtt" msgstr "" #: mqtt.7.xml:8(manvolnum) msgid "7" msgstr "" #: mqtt.7.xml:13(refpurpose) msgid "MQ Telemetry Transport" msgstr "" #: mqtt.7.xml:23(title) msgid "Description" msgstr "" #: mqtt.7.xml:24(para) msgid "mqtt is a publish/subscribe messaging protocol intended that is designed to be lightweight. It is useful for use with low power sensors, but is applicable to many scenarios." msgstr "" #: mqtt.7.xml:27(para) msgid "This manual describes some of the features of mqtt version 3.1, to assist end users in getting the most out of it. For more complete information on mqtt, see http://mqtt.org/." msgstr "" #: mqtt.7.xml:34(title) msgid "Publish/Subscribe" msgstr "" #: mqtt.7.xml:35(para) msgid "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, pachube 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." msgstr "" #: mqtt.7.xml:48(title) msgid "Topics/Subscriptions" msgstr "" #: mqtt.7.xml:49(para) msgid "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:" msgstr "" #: mqtt.7.xml:57(listitem) msgid "sensors/COMPUTER_NAME/temperature/HARDDRIVE_NAME" msgstr "" #: mqtt.7.xml:59(para) msgid "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, or ." msgstr "" #: mqtt.7.xml:63(para) msgid " 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:" msgstr "" #: mqtt.7.xml:67(listitem) msgid "sensors/+/temperature/+" msgstr "" #: mqtt.7.xml:69(para) msgid "As another example, for a topic of \"a/b/c/d\", the following example subscriptions will match:" msgstr "" #: mqtt.7.xml:72(para) mqtt.7.xml:89(para) msgid "a/b/c/d" msgstr "" #: mqtt.7.xml:73(para) msgid "+/b/c/d" msgstr "" #: mqtt.7.xml:74(para) msgid "a/+/c/d" msgstr "" #: mqtt.7.xml:75(para) msgid "a/+/+/d" msgstr "" #: mqtt.7.xml:76(para) msgid "+/+/+/+" msgstr "" #: mqtt.7.xml:78(para) msgid "The following subscriptions will not match:" msgstr "" #: mqtt.7.xml:80(para) msgid "a/b/c" msgstr "" #: mqtt.7.xml:81(para) msgid "b/+/c/d" msgstr "" #: mqtt.7.xml:82(para) msgid "+/+/+" msgstr "" #: mqtt.7.xml:84(para) msgid " 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:" msgstr "" #: mqtt.7.xml:90(para) msgid "#" msgstr "" #: mqtt.7.xml:91(para) msgid "a/#" msgstr "" #: mqtt.7.xml:92(para) msgid "a/b/#" msgstr "" #: mqtt.7.xml:93(para) msgid "a/b/c/#" msgstr "" #: mqtt.7.xml:94(para) msgid "+/b/c/#" msgstr "" #: mqtt.7.xml:99(title) msgid "Quality of Service" msgstr "" #: mqtt.7.xml:100(para) msgid "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." msgstr "" #: mqtt.7.xml:111(para) msgid "Higher levels of QoS are more reliable, but involve higher latency and have higher bandwidth requirements." msgstr "" #: mqtt.7.xml:114(listitem) msgid "0: The broker/client will deliver the message once, with no confirmation." msgstr "" #: mqtt.7.xml:115(listitem) msgid "1: The broker/client will deliver the message at least once, with confirmation required." msgstr "" #: mqtt.7.xml:116(listitem) msgid "2: The broker/client will deliver the message exactly once by using a four step handshake." msgstr "" #: mqtt.7.xml:121(title) msgid "Retained Messages" msgstr "" #: mqtt.7.xml:122(para) msgid "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." msgstr "" #: mqtt.7.xml:133(title) msgid "Clean session / Durable connections" msgstr "" #: mqtt.7.xml:134(para) msgid "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." msgstr "" #: mqtt.7.xml:144(title) msgid "Wills" msgstr "" #: mqtt.7.xml:145(para) msgid "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." msgstr "" #: mqtt.7.xml:152(title) msgid "See Also" msgstr "" #: mqtt.7.xml:155(refentrytitle) msgid "mosquitto" msgstr "" #: mqtt.7.xml:156(manvolnum) msgid "8" msgstr "" #: mqtt.7.xml:159(refentrytitle) msgid "mosquitto_pub" msgstr "" #: mqtt.7.xml:160(manvolnum) mqtt.7.xml:164(manvolnum) msgid "1" msgstr "" #: mqtt.7.xml:163(refentrytitle) msgid "mosquitto_sub" msgstr "" #: mqtt.7.xml:170(title) msgid "Author" msgstr "" #: mqtt.7.xml:171(para) msgid "Roger Light roger@atchoo.org" msgstr "" #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: mqtt.7.xml:0(None) msgid "translator-credits" msgstr "" mosquitto-0.15/man/po/mosquitto_sub/0000775000175000017500000000000011713444064016635 5ustar rogerrogermosquitto-0.15/man/po/mosquitto_sub/mosquitto_sub.1.pot0000664000175000017500000002314411713444064022441 0ustar rogerrogermsgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2011-04-29 17:23+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: mosquitto_sub.1.xml:7(refentrytitle) mosquitto_sub.1.xml:12(refname) mosquitto_sub.1.xml:18(command) msgid "mosquitto_sub" msgstr "" #: mosquitto_sub.1.xml:8(manvolnum) mosquitto_sub.1.xml:270(manvolnum) msgid "1" msgstr "" #: mosquitto_sub.1.xml:13(refpurpose) msgid "an mqtt version 3.1 client for subscribing to topics" msgstr "" #: mosquitto_sub.1.xml:20(option) mosquitto_sub.1.xml:86(option) msgid "-c" msgstr "" #: mosquitto_sub.1.xml:23(option) mosquitto_sub.1.xml:99(option) msgid "-d" msgstr "" #: mosquitto_sub.1.xml:26(option) mosquitto_sub.1.xml:106(option) msgid "-h" msgstr "" #: mosquitto_sub.1.xml:26(replaceable) msgid "hostname" msgstr "" #: mosquitto_sub.1.xml:29(option) mosquitto_sub.1.xml:113(option) msgid "-i" msgstr "" #: mosquitto_sub.1.xml:29(replaceable) msgid "client_id" msgstr "" #: mosquitto_sub.1.xml:32(option) mosquitto_sub.1.xml:122(option) msgid "-k" msgstr "" #: mosquitto_sub.1.xml:32(replaceable) msgid "keepalive time" msgstr "" #: mosquitto_sub.1.xml:35(option) mosquitto_sub.1.xml:131(option) msgid "-p" msgstr "" #: mosquitto_sub.1.xml:35(replaceable) msgid "port number" msgstr "" #: mosquitto_sub.1.xml:38(option) mosquitto_sub.1.xml:147(option) msgid "-q" msgstr "" #: mosquitto_sub.1.xml:38(replaceable) msgid "message QoS" msgstr "" #: mosquitto_sub.1.xml:41(option) mosquitto_sub.1.xml:178(option) msgid "-v" msgstr "" #: mosquitto_sub.1.xml:46(option) mosquitto_sub.1.xml:169(option) msgid "-u" msgstr "" #: mosquitto_sub.1.xml:46(replaceable) msgid "username" msgstr "" #: mosquitto_sub.1.xml:49(option) mosquitto_sub.1.xml:138(option) msgid "--pw" msgstr "" #: mosquitto_sub.1.xml:49(replaceable) msgid "password" msgstr "" #: mosquitto_sub.1.xml:56(option) mosquitto_sub.1.xml:211(option) msgid "--will-topic" msgstr "" #: mosquitto_sub.1.xml:56(replaceable) msgid "topic" msgstr "" #: mosquitto_sub.1.xml:59(option) mosquitto_sub.1.xml:188(option) msgid "--will-payload" msgstr "" #: mosquitto_sub.1.xml:59(replaceable) msgid "payload" msgstr "" #: mosquitto_sub.1.xml:62(option) mosquitto_sub.1.xml:196(option) msgid "--will-qos" msgstr "" #: mosquitto_sub.1.xml:62(replaceable) msgid "qos" msgstr "" #: mosquitto_sub.1.xml:65(option) mosquitto_sub.1.xml:203(option) msgid "--will-retain" msgstr "" #: mosquitto_sub.1.xml:70(option) mosquitto_sub.1.xml:159(option) msgid "-t" msgstr "" #: mosquitto_sub.1.xml:70(replaceable) msgid "message topic" msgstr "" #: mosquitto_sub.1.xml:76(title) msgid "Description" msgstr "" #: mosquitto_sub.1.xml:77(para) msgid "mosquitto_sub is a simple mqtt version 3.1 client that will subscribe to a topic and print the messages that it receives." msgstr "" #: mosquitto_sub.1.xml:83(title) msgid "Options" msgstr "" #: mosquitto_sub.1.xml:87(option) msgid "--disable-clean-session" msgstr "" #: mosquitto_sub.1.xml:89(para) msgid "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." msgstr "" #: mosquitto_sub.1.xml:94(para) msgid "If using this option, it is recommended that the client id is set manually with " msgstr "" #: mosquitto_sub.1.xml:100(option) msgid "--debug" msgstr "" #: mosquitto_sub.1.xml:102(para) msgid "Enable debug messages." msgstr "" #: mosquitto_sub.1.xml:107(option) msgid "--host" msgstr "" #: mosquitto_sub.1.xml:109(para) msgid "Specify the host to connect to. Defaults to localhost." msgstr "" #: mosquitto_sub.1.xml:114(option) msgid "--id" msgstr "" #: mosquitto_sub.1.xml:116(para) msgid "The id to use for this client. If not given, defaults to mosquitto_sub_ appended with the process id of the client." msgstr "" #: mosquitto_sub.1.xml:123(option) msgid "--keepalive" msgstr "" #: mosquitto_sub.1.xml:125(para) msgid "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." msgstr "" #: mosquitto_sub.1.xml:132(option) msgid "--port" msgstr "" #: mosquitto_sub.1.xml:134(para) msgid "Connect to the port specified instead of the default 1883." msgstr "" #: mosquitto_sub.1.xml:140(para) msgid "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 --username option." msgstr "" #: mosquitto_sub.1.xml:148(option) msgid "--qos" msgstr "" #: mosquitto_sub.1.xml:150(para) msgid "Specify the quality of service desired for the incoming messages, from 0, 1 and 2. Defaults to 0. See mqtt7 for more information on QoS." msgstr "" #: mosquitto_sub.1.xml:154(para) msgid "The QoS is identical for all topics subscribed to in a single instance of mosquitto_sub." msgstr "" #: mosquitto_sub.1.xml:160(option) msgid "--topic" msgstr "" #: mosquitto_sub.1.xml:162(para) msgid "The mqtt topic to subscribe to. See mqtt7 for more information on mqtt topics." msgstr "" #: mosquitto_sub.1.xml:165(para) msgid "This option may be repeated to subscribe to multiple topics." msgstr "" #: mosquitto_sub.1.xml:170(option) msgid "--username" msgstr "" #: mosquitto_sub.1.xml:172(para) msgid "Provide a username to be used for authenticating with the broker. This requires a broker that supports MQTT v3.1. See also the --pw argument." msgstr "" #: mosquitto_sub.1.xml:179(option) msgid "--verbose" msgstr "" #: mosquitto_sub.1.xml:181(para) msgid "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\"." msgstr "" #: mosquitto_sub.1.xml:190(para) msgid "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 --will-topic." msgstr "" #: mosquitto_sub.1.xml:198(para) msgid "The QoS to use for the Will. Defaults to 0. This must be used in conjunction with --will-topic." msgstr "" #: mosquitto_sub.1.xml:205(para) msgid "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 --will-topic." msgstr "" #: mosquitto_sub.1.xml:213(para) msgid "The topic on which to send a Will, in the event that the client disconnects unexpectedly." msgstr "" #: mosquitto_sub.1.xml:221(title) msgid "Wills" msgstr "" #: mosquitto_sub.1.xml:222(para) msgid "mosquitto_sub can register a message with the broker that will be sent out if it disconnects unexpectedly. See mqtt7 for more information." msgstr "" #: mosquitto_sub.1.xml:226(para) msgid "The minimum requirement for this is to use --will-topic to specify which topic the will should be sent out on. This will result in a non-retained, zero length message with QoS 0." msgstr "" #: mosquitto_sub.1.xml:229(para) msgid "Use the --will-retain, --will-payload and --will-qos arguments to modify the other will parameters." msgstr "" #: mosquitto_sub.1.xml:234(title) msgid "Examples" msgstr "" #: mosquitto_sub.1.xml:235(para) msgid "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." msgstr "" #: mosquitto_sub.1.xml:238(para) msgid "Subscribe to temperature information on localhost with QoS 1:" msgstr "" #: mosquitto_sub.1.xml:240(para) msgid "mosquitto_sub -t sensors/temperature -q 1" msgstr "" #: mosquitto_sub.1.xml:242(para) msgid "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." msgstr "" #: mosquitto_sub.1.xml:247(para) msgid "mosquitto_sub -t sensors/machines/+/temperature/+" msgstr "" #: mosquitto_sub.1.xml:249(para) msgid "Subscribe to all broker status messages:" msgstr "" #: mosquitto_sub.1.xml:251(para) msgid "mosquitto_sub -v -t \\$SYS/#" msgstr "" #: mosquitto_sub.1.xml:256(title) msgid "Bugs" msgstr "" #: mosquitto_sub.1.xml:257(para) msgid "mosquitto_sub bug information can be found at http://launchpad.net/mosquitto." msgstr "" #: mosquitto_sub.1.xml:262(title) msgid "See Also" msgstr "" #: mosquitto_sub.1.xml:265(refentrytitle) msgid "mqtt" msgstr "" #: mosquitto_sub.1.xml:266(manvolnum) msgid "7" msgstr "" #: mosquitto_sub.1.xml:269(refentrytitle) msgid "mosquitto_pub" msgstr "" #: mosquitto_sub.1.xml:273(refentrytitle) msgid "mosquitto" msgstr "" #: mosquitto_sub.1.xml:274(manvolnum) msgid "8" msgstr "" #: mosquitto_sub.1.xml:277(refentrytitle) msgid "libmosquitto" msgstr "" #: mosquitto_sub.1.xml:278(manvolnum) msgid "3" msgstr "" #: mosquitto_sub.1.xml:284(title) msgid "Author" msgstr "" #: mosquitto_sub.1.xml:285(para) msgid "Roger Light roger@atchoo.org" msgstr "" #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: mosquitto_sub.1.xml:0(None) msgid "translator-credits" msgstr "" mosquitto-0.15/man/po/mosquitto.conf/0000775000175000017500000000000011713444064016710 5ustar rogerrogermosquitto-0.15/man/po/mosquitto.conf/mosquitto.conf.5.pot0000664000175000017500000004027311713444064022575 0ustar rogerrogermsgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2011-04-29 17:22+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: mosquitto.conf.5.xml:7(refentrytitle) mosquitto.conf.5.xml:12(refname) mosquitto.conf.5.xml:18(command) mosquitto.conf.5.xml:393(para) msgid "mosquitto.conf" msgstr "" #: mosquitto.conf.5.xml:8(manvolnum) mosquitto.conf.5.xml:411(manvolnum) msgid "5" msgstr "" #: mosquitto.conf.5.xml:13(refpurpose) msgid "the configuration file for mosquitto" msgstr "" #: mosquitto.conf.5.xml:23(title) msgid "Description" msgstr "" #: mosquitto.conf.5.xml:24(para) msgid "mosquitto.conf is the configuration file for mosquitto. This file can reside anywhere as long as mosquitto can read it. By default, mosquitto does not need a configuration file and will use the default values listed below. See mosquitto8 for information on how to load a configuration file." msgstr "" #: mosquitto.conf.5.xml:33(title) msgid "File Format" msgstr "" #: mosquitto.conf.5.xml:34(para) msgid "All lines with a # as the very first character are treated as a comment." msgstr "" #: mosquitto.conf.5.xml:36(para) msgid "Configuration lines start with a variable name. The variable value is separated from the name by a single space." msgstr "" #: mosquitto.conf.5.xml:41(title) msgid "Variables" msgstr "" #: mosquitto.conf.5.xml:44(option) msgid "acl_file" msgstr "" #: mosquitto.conf.5.xml:46(para) msgid "Set the path to an access control list file. If defined, the contents of the file are used to control client access to topics on the broker." msgstr "" #: mosquitto.conf.5.xml:49(para) msgid "If this parameter is defined then only the topics listed will have access. Topic access is added with lines of the format:" msgstr "" #: mosquitto.conf.5.xml:53(code) msgid "topic [read|write] <topic>" msgstr "" #: mosquitto.conf.5.xml:55(para) msgid "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." msgstr "" #: mosquitto.conf.5.xml:60(para) msgid "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:" msgstr "" #: mosquitto.conf.5.xml:64(code) msgid "user <username>" msgstr "" #: mosquitto.conf.5.xml:66(para) msgid "The username referred to here is the same as in password_file. It is not the clientid." msgstr "" #: mosquitto.conf.5.xml:71(option) msgid "allow_anonymous" msgstr "" #: mosquitto.conf.5.xml:73(para) msgid "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." msgstr "" #: mosquitto.conf.5.xml:81(option) msgid "autosave_interval" msgstr "" #: mosquitto.conf.5.xml:83(para) msgid "The number of seconds that mosquitto will wait between each time it saves the in-memory database to disk. If set to 0, the in-memory database will only be saved when mosquitto exits or when receiving the SIGUSR1 signal. Note that this setting only has an effect if persistence is enabled. Defaults to 1800 seconds (30 minutes)." msgstr "" #: mosquitto.conf.5.xml:93(option) msgid "bind_address" msgstr "" #: mosquitto.conf.5.xml:95(para) msgid "Listen for incoming network connections on the specified IP address/hostname only. This is useful to restrict access to certain network interfaces. To restrict access to mosquitto to the local host only, use \"bind_address localhost\". This only applies to the default listener. Use the listener variable to control other listeners." msgstr "" #: mosquitto.conf.5.xml:104(option) msgid "clientid_prefixes" msgstr "" #: mosquitto.conf.5.xml:106(para) msgid "If defined, only clients that have a clientid with a prefix that matches clientid_prefixes will be allowed to connect to the broker. For example, setting \"secure-\" here would mean a client \"secure-client\" could connect but another with clientid \"mqtt\" couldn't. By default, all client ids are valid." msgstr "" #: mosquitto.conf.5.xml:115(option) msgid "listener" msgstr "" #: mosquitto.conf.5.xml:117(para) msgid "Listen for incoming network connection on the specified port. A second optional argument allows the listener to be bound to a specific ip address/hostname. If this variable is used and neither bind_address nor port are used then the default listener will not be started. This option may be specified multiple times." msgstr "" #: mosquitto.conf.5.xml:126(option) msgid "log_dest" msgstr "" #: mosquitto.conf.5.xml:128(para) msgid "Send log messages to a particular destination. Possible destinations are: stdout stderr syslog topic. 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 and topic logs to the broker topic '$SYS/broker/log/<severity>', where severity is one of D, E, W, N, I which are debug, error, warning, notice and information. Use \"log_dest none\" if you wish to disable logging. Defaults to stderr. This option may be specified multiple times." msgstr "" #: mosquitto.conf.5.xml:141(option) msgid "log_type" msgstr "" #: mosquitto.conf.5.xml:143(para) msgid "Choose types of messages to log. Possible types are: debug, error, warning, notice, information, none. Defaults to error, warning, notice and information. This option may be specified multiple times. Note that the debug type (used for decoding incoming network packets) is never logged in syslog or topics." msgstr "" #: mosquitto.conf.5.xml:152(option) msgid "max_connections" msgstr "" #: mosquitto.conf.5.xml:154(para) msgid "Limit the total number of clients connected. Set to -1 to have \"unlimited\" connections. Note that other limits may be imposed that are outside the control of mosquitto. See e.g. limits.conf5." msgstr "" #: mosquitto.conf.5.xml:161(option) msgid "max_inflight_messages" msgstr "" #: mosquitto.conf.5.xml:163(para) msgid "The maximum number of QoS 1 or 2 messages that can be in the process of being transmitted simultaneously. This includes messages currently going through handshakes and messages that are being retried. Defaults to 20. Set to 0 for no maximum. If set to 1, this will guarantee in-order delivery of messages." msgstr "" #: mosquitto.conf.5.xml:172(option) msgid "max_queued_messages" msgstr "" #: mosquitto.conf.5.xml:174(para) msgid "The maximum number of QoS 1 or 2 messages to hold in the queue above those messages that are currently in flight. Defaults to 100. Set to 0 for no maximum (not recommended)." msgstr "" #: mosquitto.conf.5.xml:181(option) msgid "password_file" msgstr "" #: mosquitto.conf.5.xml:183(para) msgid "Set the path to a password file. If defined, the contents of the file are used to control client access to the broker. Each line should be in the format \"username:password\", where the colon and password are optional but recommended. If allow_anonymous is set to false, only users defined in this file will be able to connect. Setting allow_anonymous to true when password_file is defined is valid and could be used with acl_file to have e.g. read only guest/anonymous accounts and defined users that can publish." msgstr "" #: mosquitto.conf.5.xml:196(option) msgid "persistence" msgstr "" #: mosquitto.conf.5.xml:198(para) msgid "Can be true or false. If true, connection, subscription and message data will be written to the disk in mosquitto.db at the location dictated by persistence_location. When mosquitto is restarted, it will reload the information stored in mosquitto.db. The data will be written to disk when mosquitto closes and also at periodic intervals as defined by autosave_interval. Writing of the persistence database may also be forced by sending mosquitto the SIGUSR1 signal. If false, the data will be stored in memory only. Defaults to false." msgstr "" #: mosquitto.conf.5.xml:211(option) msgid "persistence_file" msgstr "" #: mosquitto.conf.5.xml:213(para) msgid "The filename to use for the persistent database. Defaults to mosquitto.db." msgstr "" #: mosquitto.conf.5.xml:217(option) msgid "persistence_location" msgstr "" #: mosquitto.conf.5.xml:219(para) msgid "The path where the persistence database should be stored. Must end in a trailing slash. If not given, then the current directory is used." msgstr "" #: mosquitto.conf.5.xml:225(option) msgid "pid_file" msgstr "" #: mosquitto.conf.5.xml:227(para) msgid "Write a pid file to the file specified. If not given (the default), no pid file will be written. If the pid file cannot be written, mosquitto will exit. This option only has an effect is mosquitto is run in daemon mode." msgstr "" #: mosquitto.conf.5.xml:231(para) msgid "If mosquitto is being automatically started by an init script it will usually be required to write a pid file. This should then be configured as /var/run/mosquitto.pid" msgstr "" #: mosquitto.conf.5.xml:238(option) msgid "port" msgstr "" #: mosquitto.conf.5.xml:240(para) msgid "Set the network port for the default listener to listen on. Defaults to 1883." msgstr "" #: mosquitto.conf.5.xml:245(option) msgid "retry_interval" msgstr "" #: mosquitto.conf.5.xml:247(para) msgid "The integer number of seconds after a QoS=1 or QoS=2 message has been sent that mosquitto will wait before retrying when no response is received. If unset, defaults to 20 seconds." msgstr "" #: mosquitto.conf.5.xml:254(option) msgid "store_clean_interval" msgstr "" #: mosquitto.conf.5.xml:256(para) msgid "The integer number of seconds between the internal message store being cleaned of messages that are no longer referenced. 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. Defaults to 10 seconds." msgstr "" #: mosquitto.conf.5.xml:266(option) msgid "sys_interval" msgstr "" #: mosquitto.conf.5.xml:268(para) msgid "The integer number of seconds between updates of the $SYS subscription hierarchy, which provides status information about the broker. If unset, defaults to 10 seconds." msgstr "" #: mosquitto.conf.5.xml:275(option) msgid "user" msgstr "" #: mosquitto.conf.5.xml:277(para) msgid "When run as root, change to this user and its primary group on startup. If mosquitto is unable to change to this user and group, it will exit with an error. The user specified must have read/write access to the persistence database if it is to be written. If run as a non-root user, this setting has no effect. Defaults to mosquitto." msgstr "" #: mosquitto.conf.5.xml:283(para) msgid "This setting has no effect on Windows and so you should run mosquitto as the user you wish it to run as." msgstr "" #: mosquitto.conf.5.xml:292(title) msgid "Configuring Bridges" msgstr "" #: mosquitto.conf.5.xml:293(para) msgid "Multiple bridges (connections to other brokers) can be configured using the following variables." msgstr "" #: mosquitto.conf.5.xml:297(option) msgid "address" msgstr "" #: mosquitto.conf.5.xml:297(replaceable) mosquitto.conf.5.xml:298(replaceable) msgid "address[:port]" msgstr "" #: mosquitto.conf.5.xml:298(option) msgid "addresses" msgstr "" #: mosquitto.conf.5.xml:300(para) msgid "Specify the address and optionally the port of the bridge to connect to. This must be given for each bridge connection. If the port is not specified, the default of 1883 is used." msgstr "" #: mosquitto.conf.5.xml:304(para) msgid "Unlike rsmb, it is not currently possible to specify multiple addresses for a single bridge connection here. This is true even if the name \"addresses\" is used." msgstr "" #: mosquitto.conf.5.xml:310(term) msgid " [ true | false ]" msgstr "" #: mosquitto.conf.5.xml:312(para) msgid "Set the clean session option for this bridge. Setting to false (the default), means that all subscriptions on the remote broker are kept in case of the network connection dropping. If set to true, all subscriptions and messages on the remote broker will be cleaned up if the connection drops. Note that setting to true may cause a large amount of retained messages to be sent each time the bridge reconnects." msgstr "" #: mosquitto.conf.5.xml:323(option) msgid "clientid" msgstr "" #: mosquitto.conf.5.xml:323(replaceable) msgid "id" msgstr "" #: mosquitto.conf.5.xml:325(para) msgid "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." msgstr "" #: mosquitto.conf.5.xml:332(option) msgid "connection" msgstr "" #: mosquitto.conf.5.xml:332(replaceable) mosquitto.conf.5.xml:380(replaceable) msgid "name" msgstr "" #: mosquitto.conf.5.xml:334(para) msgid "This variable marks the start of a new bridge connection. It is also used to give the bridge a name which is used as the client id on the remote broker." msgstr "" #: mosquitto.conf.5.xml:341(option) msgid "keepalive_interval" msgstr "" #: mosquitto.conf.5.xml:341(replaceable) msgid "seconds" msgstr "" #: mosquitto.conf.5.xml:343(para) msgid "Set the number of seconds after which the bridge should send a ping if no other traffic has occurred. Defaults to 60. A minimum value of 5 seconds isallowed." msgstr "" #: mosquitto.conf.5.xml:350(option) msgid "password" msgstr "" #: mosquitto.conf.5.xml:350(replaceable) msgid "value" msgstr "" #: mosquitto.conf.5.xml:352(para) msgid "Configure a password for the bridge. This is used for authentication purposes when connecting to a broker that support MQTT v3.1 and requires a username and/or password to connect. This option is only valid if a username is also supplied." msgstr "" #: mosquitto.conf.5.xml:360(term) msgid "pattern [ out | in | both ]" msgstr "" #: mosquitto.conf.5.xml:362(para) msgid "Define a topic pattern to be shared between the two brokers. Any topics matching the pattern (which may include wildcards) are shared. The second parameter defines the direction that the messages will be shared in, so it is possible to import messages from a remote broker using \"in\", export messages to a remote broker using \"out\" or share messages in both directions. If this parameter is not defined, the default of \"out\" is used." msgstr "" #: mosquitto.conf.5.xml:370(para) msgid "This option can be specified multiple times per bridge." msgstr "" #: mosquitto.conf.5.xml:372(para) msgid "Care must be taken to ensure that loops are not created with this option. If you are experiencing high CPU load from a broker, it is possible that you have a loop where each broker is forever forwarding each other the same messages." msgstr "" #: mosquitto.conf.5.xml:380(option) msgid "username" msgstr "" #: mosquitto.conf.5.xml:382(para) msgid "Configure a username for the bridge. This is used for authentication purposes when connecting to a broker that support MQTT v3.1 and requires a username and/or password to connect. See also the password option." msgstr "" #: mosquitto.conf.5.xml:392(title) msgid "Files" msgstr "" #: mosquitto.conf.5.xml:397(title) msgid "Bugs" msgstr "" #: mosquitto.conf.5.xml:398(para) msgid "mosquitto bug information can be found at http://launchpad.net/mosquitto." msgstr "" #: mosquitto.conf.5.xml:403(title) msgid "See Also" msgstr "" #: mosquitto.conf.5.xml:406(refentrytitle) msgid "mosquitto" msgstr "" #: mosquitto.conf.5.xml:407(manvolnum) msgid "8" msgstr "" #: mosquitto.conf.5.xml:410(refentrytitle) msgid "limits.conf" msgstr "" #: mosquitto.conf.5.xml:417(title) msgid "Author" msgstr "" #: mosquitto.conf.5.xml:418(para) msgid "Roger Light roger@atchoo.org" msgstr "" #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: mosquitto.conf.5.xml:0(None) msgid "translator-credits" msgstr "" mosquitto-0.15/man/po/mosquitto/0000775000175000017500000000000011713444064015764 5ustar rogerrogermosquitto-0.15/man/po/mosquitto/mosquitto.8.pot0000664000175000017500000002555411713444064020735 0ustar rogerrogermsgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2011-04-29 17:22+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: mosquitto.8.xml:7(refentrytitle) mosquitto.8.xml:12(refname) mosquitto.8.xml:18(command) msgid "mosquitto" msgstr "" #: mosquitto.8.xml:8(manvolnum) msgid "8" msgstr "" #: mosquitto.8.xml:13(refpurpose) msgid "an mqtt broker" msgstr "" #: mosquitto.8.xml:20(option) mosquitto.8.xml:42(option) msgid "-c" msgstr "" #: mosquitto.8.xml:20(replaceable) msgid "config file" msgstr "" #: mosquitto.8.xml:23(option) mosquitto.8.xml:49(option) msgid "-d" msgstr "" #: mosquitto.8.xml:24(option) mosquitto.8.xml:50(option) msgid "--daemon" msgstr "" #: mosquitto.8.xml:27(option) mosquitto.8.xml:56(option) msgid "-p" msgstr "" #: mosquitto.8.xml:27(replaceable) msgid "port number" msgstr "" #: mosquitto.8.xml:33(title) msgid "Description" msgstr "" #: mosquitto.8.xml:34(para) msgid "mosquitto is a broker for the mqtt protocol version 3.1." msgstr "" #: mosquitto.8.xml:35(para) msgid "It is intended to be a drop in replacement for rsmb, but it's a little way off yet." msgstr "" #: mosquitto.8.xml:39(title) msgid "Options" msgstr "" #: mosquitto.8.xml:43(option) msgid "--config-file" msgstr "" #: mosquitto.8.xml:45(para) msgid "Load configuration from a file. If not given, the default values as described in mosquitto.conf5 are used." msgstr "" #: mosquitto.8.xml:52(para) msgid "Run mosquitto in the background as a daemon. All other behaviour remains the same." msgstr "" #: mosquitto.8.xml:57(option) msgid "--port" msgstr "" #: mosquitto.8.xml:59(para) msgid "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." msgstr "" #: mosquitto.8.xml:66(title) msgid "Limitations" msgstr "" #: mosquitto.8.xml:67(para) msgid "mosquitto implements all of the mqtt protocol version 3.1, but there are some significant limitations compared to rsmb." msgstr "" #: mosquitto.8.xml:69(para) msgid "There is only basic bridge support." msgstr "" #: mosquitto.8.xml:70(para) msgid "There are fewer configuration options." msgstr "" #: mosquitto.8.xml:71(para) msgid "There is less logging information." msgstr "" #: mosquitto.8.xml:72(para) msgid "The $SYS hierarchy is smaller." msgstr "" #: mosquitto.8.xml:73(para) msgid "It isn't as well tested or documented..." msgstr "" #: mosquitto.8.xml:75(para) msgid "It should be noted that all of the above limitations should have \"currently\" included in them. They will all be fixed at some point." msgstr "" #: mosquitto.8.xml:79(title) msgid "Broker Status" msgstr "" #: mosquitto.8.xml:80(para) msgid "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 seconds. If is 0, then updates are not sent." msgstr "" #: mosquitto.8.xml:83(option) msgid "$SYS/broker/bytes/received" msgstr "" #: mosquitto.8.xml:85(para) msgid "The total number of bytes received since the broker started." msgstr "" #: mosquitto.8.xml:89(option) msgid "$SYS/broker/bytes/sent" msgstr "" #: mosquitto.8.xml:91(para) msgid "The total number of bytes sent since the broker started." msgstr "" #: mosquitto.8.xml:95(option) msgid "$SYS/broker/changeset" msgstr "" #: mosquitto.8.xml:97(para) msgid "The repository changeset (revision) associated with this build." msgstr "" #: mosquitto.8.xml:101(option) msgid "$SYS/broker/clients/total" msgstr "" #: mosquitto.8.xml:103(para) msgid "The total number of clients currently either connected to the broker or disconnected but with clean session not set." msgstr "" #: mosquitto.8.xml:107(option) msgid "$SYS/broker/heap/current size" msgstr "" #: mosquitto.8.xml:109(para) msgid "The current size of the heap memory in use by mosquitto. Note that this topic may be unavailable depending on compile time options." msgstr "" #: mosquitto.8.xml:115(option) msgid "$SYS/broker/messages/stored" msgstr "" #: mosquitto.8.xml:117(para) msgid "The number of messages currently held in the message store." msgstr "" #: mosquitto.8.xml:121(option) msgid "$SYS/broker/messages/received" msgstr "" #: mosquitto.8.xml:123(para) msgid "The total number of messages received since the broker started." msgstr "" #: mosquitto.8.xml:127(option) msgid "$SYS/broker/messages/sent" msgstr "" #: mosquitto.8.xml:129(para) msgid "The total number of messages sent since the broker started." msgstr "" #: mosquitto.8.xml:133(option) msgid "$SYS/broker/timestamp" msgstr "" #: mosquitto.8.xml:135(para) msgid "The timestamp at which this particular build of the broker was made. Static." msgstr "" #: mosquitto.8.xml:139(option) msgid "$SYS/broker/uptime" msgstr "" #: mosquitto.8.xml:141(para) msgid "The amount of time in seconds the broker has been online." msgstr "" #: mosquitto.8.xml:145(option) msgid "$SYS/broker/version" msgstr "" #: mosquitto.8.xml:147(para) msgid "The version of the broker. Static." msgstr "" #: mosquitto.8.xml:154(title) msgid "Wildcard Topic Subscriptions" msgstr "" #: mosquitto.8.xml:155(para) msgid "In addition to allowing clients to subscribe to specific topics, mosquitto also allows the use of two wildcards in subscriptions. 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:" msgstr "" #: mosquitto.8.xml:161(para) mosquitto.8.xml:177(para) msgid "a/b/c/d" msgstr "" #: mosquitto.8.xml:162(para) msgid "+/b/c/d" msgstr "" #: mosquitto.8.xml:163(para) msgid "a/+/c/d" msgstr "" #: mosquitto.8.xml:164(para) msgid "a/+/+/d" msgstr "" #: mosquitto.8.xml:165(para) msgid "+/+/+/+" msgstr "" #: mosquitto.8.xml:167(para) msgid "The following subscriptions will not match:" msgstr "" #: mosquitto.8.xml:169(para) msgid "a/b/c" msgstr "" #: mosquitto.8.xml:170(para) msgid "b/+/c/d" msgstr "" #: mosquitto.8.xml:171(para) msgid "+/+/+" msgstr "" #: mosquitto.8.xml:173(para) msgid "The second wildcard is and is used to match all subsequent levels of hierarchy. With a topic of \"a/b/c/d\", the following example subscriptions will match:" msgstr "" #: mosquitto.8.xml:178(para) msgid "#" msgstr "" #: mosquitto.8.xml:179(para) msgid "a/#" msgstr "" #: mosquitto.8.xml:180(para) msgid "a/b/#" msgstr "" #: mosquitto.8.xml:181(para) msgid "a/b/c/#" msgstr "" #: mosquitto.8.xml:182(para) msgid "+/b/c/#" msgstr "" #: mosquitto.8.xml:184(para) msgid "The $SYS hierarchy does not match a subscription of \"#\". If you want to observe the entire $SYS hierarchy, subscribe to $SYS/#." msgstr "" #: mosquitto.8.xml:187(para) msgid "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 wildcard must only ever be used as the final character of a subscription." msgstr "" #: mosquitto.8.xml:194(title) msgid "Bridges" msgstr "" #: mosquitto.8.xml:195(para) msgid "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." msgstr "" #: mosquitto.8.xml:205(para) msgid "For information on configuring bridges, see mosquitto.conf5." msgstr "" #: mosquitto.8.xml:210(title) msgid "Signals" msgstr "" #: mosquitto.8.xml:213(term) msgid "SIGUSR1" msgstr "" #: mosquitto.8.xml:215(para) msgid "Upon receiving the SIGUSR1 signal, mosquitto will write the persistence database to disk. This signal is only acted upon if persistence is enabled." msgstr "" #: mosquitto.8.xml:230(title) msgid "Files" msgstr "" #: mosquitto.8.xml:233(filename) msgid "/etc/mosquitto.conf" msgstr "" #: mosquitto.8.xml:235(para) msgid "Configuration file. See mosquitto.conf5." msgstr "" #: mosquitto.8.xml:239(filename) msgid "/var/lib/mosquitto/mosquitto.db" msgstr "" #: mosquitto.8.xml:241(para) msgid "Persistent message data storage location if persist enabled." msgstr "" #: mosquitto.8.xml:245(filename) msgid "/etc/hosts.allow" msgstr "" #: mosquitto.8.xml:246(filename) msgid "/etc/hosts.deny" msgstr "" #: mosquitto.8.xml:248(para) msgid "Host access control via tcp-wrappers as described in hosts_access5." msgstr "" #: mosquitto.8.xml:255(title) msgid "Bugs" msgstr "" #: mosquitto.8.xml:256(para) msgid "mosquitto bug information can be found at http://launchpad.net/mosquitto." msgstr "" #: mosquitto.8.xml:260(title) msgid "See Also" msgstr "" #: mosquitto.8.xml:263(refentrytitle) msgid "mosquitto.conf" msgstr "" #: mosquitto.8.xml:264(manvolnum) mosquitto.8.xml:268(manvolnum) msgid "5" msgstr "" #: mosquitto.8.xml:267(refentrytitle) msgid "hosts_access" msgstr "" #: mosquitto.8.xml:271(refentrytitle) msgid "mosquitto_pub" msgstr "" #: mosquitto.8.xml:272(manvolnum) mosquitto.8.xml:276(manvolnum) msgid "1" msgstr "" #: mosquitto.8.xml:275(refentrytitle) msgid "mosquitto_sub" msgstr "" #: mosquitto.8.xml:279(refentrytitle) msgid "libmosquitto" msgstr "" #: mosquitto.8.xml:280(manvolnum) msgid "3" msgstr "" #: mosquitto.8.xml:286(title) msgid "Thanks" msgstr "" #: mosquitto.8.xml:287(para) msgid "Thanks to Andy Stanford-Clark for being one of the people who came up with MQTT in the first place and providing clarifications of the protocol." msgstr "" #: mosquitto.8.xml:288(para) msgid "Thanks also to everybody at the Ubuntu UK Podcast and Linux Outlaws for organising OggCamp, where Andy gave a talk that inspired mosquitto." msgstr "" #: mosquitto.8.xml:292(title) msgid "Author" msgstr "" #: mosquitto.8.xml:293(para) msgid "Roger Light roger@atchoo.org" msgstr "" #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: mosquitto.8.xml:0(None) msgid "translator-credits" msgstr "" mosquitto-0.15/man/po/mosquitto_pub/0000775000175000017500000000000011713444064016632 5ustar rogerrogermosquitto-0.15/man/po/mosquitto_pub/mosquitto_pub.1.pot0000664000175000017500000002377511713444064022445 0ustar rogerrogermsgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2011-04-29 17:23+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: mosquitto_pub.1.xml:7(refentrytitle) mosquitto_pub.1.xml:12(refname) mosquitto_pub.1.xml:18(command) msgid "mosquitto_pub" msgstr "" #: mosquitto_pub.1.xml:8(manvolnum) mosquitto_pub.1.xml:275(manvolnum) msgid "1" msgstr "" #: mosquitto_pub.1.xml:13(refpurpose) msgid "an mqtt version 3.1 client for publishing simple messages" msgstr "" #: mosquitto_pub.1.xml:20(option) mosquitto_pub.1.xml:89(option) msgid "-d" msgstr "" #: mosquitto_pub.1.xml:23(option) mosquitto_pub.1.xml:103(option) msgid "-h" msgstr "" #: mosquitto_pub.1.xml:23(replaceable) msgid "hostname" msgstr "" #: mosquitto_pub.1.xml:26(option) mosquitto_pub.1.xml:110(option) msgid "-i" msgstr "" #: mosquitto_pub.1.xml:26(replaceable) msgid "client_id" msgstr "" #: mosquitto_pub.1.xml:29(option) mosquitto_pub.1.xml:138(option) msgid "-p" msgstr "" #: mosquitto_pub.1.xml:29(replaceable) msgid "port number" msgstr "" #: mosquitto_pub.1.xml:32(option) mosquitto_pub.1.xml:154(option) msgid "-q" msgstr "" #: mosquitto_pub.1.xml:32(replaceable) msgid "message QoS" msgstr "" #: mosquitto_pub.1.xml:35(option) mosquitto_pub.1.xml:161(option) msgid "-r" msgstr "" #: mosquitto_pub.1.xml:39(option) mosquitto_pub.1.xml:96(option) msgid "-f" msgstr "" #: mosquitto_pub.1.xml:39(replaceable) msgid "file" msgstr "" #: mosquitto_pub.1.xml:41(option) mosquitto_pub.1.xml:117(option) msgid "-l" msgstr "" #: mosquitto_pub.1.xml:43(option) mosquitto_pub.1.xml:124(option) msgid "-m" msgstr "" #: mosquitto_pub.1.xml:43(replaceable) msgid "message" msgstr "" #: mosquitto_pub.1.xml:45(option) mosquitto_pub.1.xml:131(option) msgid "-n" msgstr "" #: mosquitto_pub.1.xml:46(option) mosquitto_pub.1.xml:168(option) msgid "-s" msgstr "" #: mosquitto_pub.1.xml:51(option) mosquitto_pub.1.xml:182(option) msgid "-u" msgstr "" #: mosquitto_pub.1.xml:51(replaceable) msgid "username" msgstr "" #: mosquitto_pub.1.xml:54(option) mosquitto_pub.1.xml:145(option) msgid "--pw" msgstr "" #: mosquitto_pub.1.xml:54(replaceable) msgid "password" msgstr "" #: mosquitto_pub.1.xml:61(option) mosquitto_pub.1.xml:214(option) msgid "--will-topic" msgstr "" #: mosquitto_pub.1.xml:61(replaceable) msgid "topic" msgstr "" #: mosquitto_pub.1.xml:64(option) mosquitto_pub.1.xml:191(option) msgid "--will-payload" msgstr "" #: mosquitto_pub.1.xml:64(replaceable) msgid "payload" msgstr "" #: mosquitto_pub.1.xml:67(option) mosquitto_pub.1.xml:199(option) msgid "--will-qos" msgstr "" #: mosquitto_pub.1.xml:67(replaceable) msgid "qos" msgstr "" #: mosquitto_pub.1.xml:70(option) mosquitto_pub.1.xml:206(option) msgid "--will-retain" msgstr "" #: mosquitto_pub.1.xml:75(option) mosquitto_pub.1.xml:175(option) msgid "-t" msgstr "" #: mosquitto_pub.1.xml:75(replaceable) msgid "message-topic" msgstr "" #: mosquitto_pub.1.xml:81(title) msgid "Description" msgstr "" #: mosquitto_pub.1.xml:82(para) msgid "mosquitto_pub is a simple mqtt version 3.1 client that will publish a single message on a topic and exit." msgstr "" #: mosquitto_pub.1.xml:86(title) msgid "Options" msgstr "" #: mosquitto_pub.1.xml:90(option) msgid "--debug" msgstr "" #: mosquitto_pub.1.xml:92(para) msgid "Enable debug messages." msgstr "" #: mosquitto_pub.1.xml:97(option) msgid "--file" msgstr "" #: mosquitto_pub.1.xml:99(para) msgid "Send the contents of a file as the message." msgstr "" #: mosquitto_pub.1.xml:104(option) msgid "--host" msgstr "" #: mosquitto_pub.1.xml:106(para) msgid "Specify the host to connect to. Defaults to localhost." msgstr "" #: mosquitto_pub.1.xml:111(option) msgid "--id" msgstr "" #: mosquitto_pub.1.xml:113(para) msgid "The id to use for this client. If not given, defaults to mosquitto_pub_ appended with the process id of the client." msgstr "" #: mosquitto_pub.1.xml:118(option) msgid "--stdin-line" msgstr "" #: mosquitto_pub.1.xml:120(para) msgid "Send messages read from stdin, splitting separate lines into separate messages. Note that blank lines won't be sent." msgstr "" #: mosquitto_pub.1.xml:125(option) msgid "--message" msgstr "" #: mosquitto_pub.1.xml:127(para) msgid "Send a single message from the command line." msgstr "" #: mosquitto_pub.1.xml:132(option) msgid "--null-message" msgstr "" #: mosquitto_pub.1.xml:134(para) msgid "Send a null (zero length) message." msgstr "" #: mosquitto_pub.1.xml:139(option) msgid "--port" msgstr "" #: mosquitto_pub.1.xml:141(para) msgid "Connect to the port specified instead of the default 1883." msgstr "" #: mosquitto_pub.1.xml:147(para) msgid "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 --username option." msgstr "" #: mosquitto_pub.1.xml:155(option) msgid "--qos" msgstr "" #: mosquitto_pub.1.xml:157(para) msgid "Specify the quality of service to use for the message, from 0, 1 and 2. Defaults to 0." msgstr "" #: mosquitto_pub.1.xml:162(option) msgid "--retain" msgstr "" #: mosquitto_pub.1.xml:164(para) msgid "If retain is given, the message will be retained as a \"last know good\" value on the broker. See mqtt7 for more information." msgstr "" #: mosquitto_pub.1.xml:169(option) msgid "--stdin-file" msgstr "" #: mosquitto_pub.1.xml:171(para) msgid "Send a message read from stdin, sending the entire content as a single message." msgstr "" #: mosquitto_pub.1.xml:176(option) msgid "--topic" msgstr "" #: mosquitto_pub.1.xml:178(para) msgid "The mqtt topic on which to publish the message. See mqtt7 for more information on mqtt topics." msgstr "" #: mosquitto_pub.1.xml:183(option) msgid "--username" msgstr "" #: mosquitto_pub.1.xml:185(para) msgid "Provide a username to be used for authenticating with the broker. This requires a broker that supports MQTT v3.1. See also the --pw argument." msgstr "" #: mosquitto_pub.1.xml:193(para) msgid "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 --will-topic." msgstr "" #: mosquitto_pub.1.xml:201(para) msgid "The QoS to use for the Will. Defaults to 0. This must be used in conjunction with --will-topic." msgstr "" #: mosquitto_pub.1.xml:208(para) msgid "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 --will-topic." msgstr "" #: mosquitto_pub.1.xml:216(para) msgid "The topic on which to send a Will, in the event that the client disconnects unexpectedly." msgstr "" #: mosquitto_pub.1.xml:224(title) msgid "Wills" msgstr "" #: mosquitto_pub.1.xml:225(para) msgid "mosquitto_sub can register a message with the broker that will be sent out if it disconnects unexpectedly. See mqtt7 for more information." msgstr "" #: mosquitto_pub.1.xml:229(para) msgid "The minimum requirement for this is to use --will-topic to specify which topic the will should be sent out on. This will result in a non-retained, zero length message with QoS 0." msgstr "" #: mosquitto_pub.1.xml:232(para) msgid "Use the --will-retain, -will-payload and --will-qos arguments to modify the other will parameters." msgstr "" #: mosquitto_pub.1.xml:237(title) msgid "Examples" msgstr "" #: mosquitto_pub.1.xml:238(para) msgid "Publish temperature information to localhost with QoS 1:" msgstr "" #: mosquitto_pub.1.xml:240(para) msgid "mosquitto_pub -t sensors/temperature -m 32 -q 1" msgstr "" #: mosquitto_pub.1.xml:242(para) msgid "Publish timestamp and temperature information to a remote host on a non-standard port and QoS 0:" msgstr "" #: mosquitto_pub.1.xml:244(para) msgid "mosquitto_pub -h 192.168.1.1 -p 1885 -t sensors/temperature -m \"1266193804 32\"" msgstr "" #: mosquitto_pub.1.xml:246(para) msgid "Publish light switch status. Message is set to retained because there may be a long period of time between light switch events:" msgstr "" #: mosquitto_pub.1.xml:248(para) msgid "mosquitto_pub -r -t switches/kitchen_lights/status -m \"on\"" msgstr "" #: mosquitto_pub.1.xml:250(para) msgid "Send the contents of a file in two ways:" msgstr "" #: mosquitto_pub.1.xml:252(para) msgid "mosquitto_pub -t my/topic -f ./data" msgstr "" #: mosquitto_pub.1.xml:253(para) msgid "mosquitto_pub -t my/topic -s < ./data" msgstr "" #: mosquitto_pub.1.xml:255(para) msgid "Send parsed electricity usage data from a Current Cost meter, reading from stdin with one line/reading as one message:" msgstr "" #: mosquitto_pub.1.xml:257(para) msgid "read_cc128.pl | mosquitto_pub -t sensors/cc128 -l" msgstr "" #: mosquitto_pub.1.xml:262(title) msgid "Bugs" msgstr "" #: mosquitto_pub.1.xml:263(para) msgid "mosquitto_pub bug information can be found at http://launchpad.net/mosquitto." msgstr "" #: mosquitto_pub.1.xml:267(title) msgid "See Also" msgstr "" #: mosquitto_pub.1.xml:270(refentrytitle) msgid "mqtt" msgstr "" #: mosquitto_pub.1.xml:271(manvolnum) msgid "7" msgstr "" #: mosquitto_pub.1.xml:274(refentrytitle) msgid "mosquitto_sub" msgstr "" #: mosquitto_pub.1.xml:278(refentrytitle) msgid "mosquitto" msgstr "" #: mosquitto_pub.1.xml:279(manvolnum) msgid "8" msgstr "" #: mosquitto_pub.1.xml:282(refentrytitle) msgid "libmosquitto" msgstr "" #: mosquitto_pub.1.xml:283(manvolnum) msgid "3" msgstr "" #: mosquitto_pub.1.xml:289(title) msgid "Author" msgstr "" #: mosquitto_pub.1.xml:290(para) msgid "Roger Light roger@atchoo.org" msgstr "" #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: mosquitto_pub.1.xml:0(None) msgid "translator-credits" msgstr "" mosquitto-0.15/man/po/libmosquitto/0000775000175000017500000000000011713444064016453 5ustar rogerrogermosquitto-0.15/man/po/libmosquitto/libmosquitto.3.pot0000664000175000017500000002426211713444064022101 0ustar rogerrogermsgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2011-04-29 17:23+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: libmosquitto.3.xml:7(refentrytitle) libmosquitto.3.xml:12(refname) msgid "libmosquitto" msgstr "" #: libmosquitto.3.xml:8(manvolnum) msgid "3" msgstr "" #: libmosquitto.3.xml:13(refpurpose) msgid "MQTT version 3.1 client library" msgstr "" #: libmosquitto.3.xml:17(title) msgid "Description" msgstr "" #: libmosquitto.3.xml:18(para) msgid "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 are also bindings for libmosquitto for C++ and Python. They are not documented here." msgstr "" #: libmosquitto.3.xml:22(para) msgid "This is fairly incomplete, please see mosquitto.h for a better description of the functions." msgstr "" #: libmosquitto.3.xml:27(title) msgid "Status" msgstr "" #: libmosquitto.3.xml:28(para) msgid "The libmosquitto api is currently regarded as experimental and unstable and may change in future releases." msgstr "" #: libmosquitto.3.xml:33(title) msgid "libmosquitto symbol names" msgstr "" #: libmosquitto.3.xml:34(para) msgid "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!" msgstr "" #: libmosquitto.3.xml:41(title) msgid "Functions" msgstr "" #: libmosquitto.3.xml:44(title) msgid "Library version" msgstr "" #: libmosquitto.3.xml:47(function) msgid "mosquitto_lib_version" msgstr "" #: libmosquitto.3.xml:47(funcdef) msgid "unsigned long " msgstr "" #: libmosquitto.3.xml:48(parameter) msgid "int *major" msgstr "" #: libmosquitto.3.xml:49(parameter) msgid "int *minor" msgstr "" #: libmosquitto.3.xml:50(parameter) msgid "int *revision" msgstr "" #: libmosquitto.3.xml:53(para) msgid "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. 9000 for 0.9) that can be used for comparisons." msgstr "" #: libmosquitto.3.xml:61(title) msgid "Library initialisation and cleanup" msgstr "" #: libmosquitto.3.xml:64(function) msgid "mosquitto_lib_init" msgstr "" #: libmosquitto.3.xml:64(funcdef) libmosquitto.3.xml:67(funcdef) libmosquitto.3.xml:91(funcdef) libmosquitto.3.xml:121(funcdef) libmosquitto.3.xml:145(funcdef) libmosquitto.3.xml:155(funcdef) libmosquitto.3.xml:171(funcdef) libmosquitto.3.xml:178(funcdef) libmosquitto.3.xml:190(funcdef) libmosquitto.3.xml:195(funcdef) libmosquitto.3.xml:199(funcdef) libmosquitto.3.xml:203(funcdef) libmosquitto.3.xml:207(funcdef) msgid "int " msgstr "" #: libmosquitto.3.xml:67(function) msgid "mosquitto_lib_cleanup" msgstr "" #: libmosquitto.3.xml:73(title) msgid "Client constructor/destructor" msgstr "" #: libmosquitto.3.xml:76(function) msgid "mosquitto_new" msgstr "" #: libmosquitto.3.xml:76(funcdef) msgid "struct mosquitto *" msgstr "" #: libmosquitto.3.xml:77(parameter) msgid "const char *id" msgstr "" #: libmosquitto.3.xml:78(parameter) msgid "void *obj" msgstr "" #: libmosquitto.3.xml:81(function) msgid "mosquitto_destroy" msgstr "" #: libmosquitto.3.xml:81(funcdef) libmosquitto.3.xml:137(funcdef) msgid "void " msgstr "" #: libmosquitto.3.xml:82(parameter) libmosquitto.3.xml:92(parameter) libmosquitto.3.xml:122(parameter) libmosquitto.3.xml:138(parameter) libmosquitto.3.xml:146(parameter) libmosquitto.3.xml:156(parameter) libmosquitto.3.xml:172(parameter) libmosquitto.3.xml:179(parameter) libmosquitto.3.xml:191(parameter) libmosquitto.3.xml:196(parameter) libmosquitto.3.xml:200(parameter) libmosquitto.3.xml:204(parameter) libmosquitto.3.xml:208(parameter) msgid "struct mosquitto *mosq" msgstr "" #: libmosquitto.3.xml:88(title) msgid "Logging" msgstr "" #: libmosquitto.3.xml:91(function) msgid "mosquitto_log_init" msgstr "" #: libmosquitto.3.xml:93(parameter) msgid "int priorities" msgstr "" #: libmosquitto.3.xml:94(parameter) msgid "int destinations" msgstr "" #: libmosquitto.3.xml:98(para) msgid "Configure the logging settings for this client. Returns 0 on success, 1 on error." msgstr "" #: libmosquitto.3.xml:101(listitem) msgid "MOSQ_LOG_INFO" msgstr "" #: libmosquitto.3.xml:102(listitem) msgid "MOSQ_LOG_NOTICE" msgstr "" #: libmosquitto.3.xml:103(listitem) msgid "MOSQ_LOG_WARNING" msgstr "" #: libmosquitto.3.xml:104(listitem) msgid "MOSQ_LOG_ERROR" msgstr "" #: libmosquitto.3.xml:105(listitem) msgid "MOSQ_LOG_DEBUG" msgstr "" #: libmosquitto.3.xml:99(para) msgid "Set priorities by ORing any of the items in the following list: " msgstr "" #: libmosquitto.3.xml:110(listitem) msgid "MOSQ_LOG_NONE" msgstr "" #: libmosquitto.3.xml:111(listitem) msgid "MOSQ_LOG_STDOUT" msgstr "" #: libmosquitto.3.xml:112(listitem) msgid "MOSQ_LOG_STDERR" msgstr "" #: libmosquitto.3.xml:108(para) msgid "Set destinations by ORing any of the items in the following list: " msgstr "" #: libmosquitto.3.xml:118(title) msgid "Wills" msgstr "" #: libmosquitto.3.xml:121(function) msgid "mosquitto_will_set" msgstr "" #: libmosquitto.3.xml:123(parameter) msgid "bool will" msgstr "" #: libmosquitto.3.xml:124(parameter) libmosquitto.3.xml:158(parameter) msgid "const char *topic" msgstr "" #: libmosquitto.3.xml:125(parameter) libmosquitto.3.xml:159(parameter) msgid "uint32_t payloadlen" msgstr "" #: libmosquitto.3.xml:126(parameter) libmosquitto.3.xml:160(parameter) msgid "const uint8_t *payload" msgstr "" #: libmosquitto.3.xml:127(parameter) libmosquitto.3.xml:161(parameter) libmosquitto.3.xml:175(parameter) msgid "int qos" msgstr "" #: libmosquitto.3.xml:128(parameter) libmosquitto.3.xml:162(parameter) msgid "bool retain" msgstr "" #: libmosquitto.3.xml:134(title) msgid "Connect/disconnect" msgstr "" #: libmosquitto.3.xml:137(function) msgid "mosquitto_connect" msgstr "" #: libmosquitto.3.xml:139(parameter) msgid "const char *host" msgstr "" #: libmosquitto.3.xml:140(parameter) msgid "int port" msgstr "" #: libmosquitto.3.xml:141(parameter) msgid "int keepalive" msgstr "" #: libmosquitto.3.xml:142(parameter) msgid "bool clean_session" msgstr "" #: libmosquitto.3.xml:145(function) msgid "mosquitto_disconnect" msgstr "" #: libmosquitto.3.xml:152(title) msgid "Publish" msgstr "" #: libmosquitto.3.xml:155(function) msgid "mosquitto_publish" msgstr "" #: libmosquitto.3.xml:157(parameter) libmosquitto.3.xml:173(parameter) libmosquitto.3.xml:180(parameter) msgid "uint16_t *mid" msgstr "" #: libmosquitto.3.xml:168(title) msgid "Subscribe/unsubscribe" msgstr "" #: libmosquitto.3.xml:171(function) msgid "mosquitto_subscribe" msgstr "" #: libmosquitto.3.xml:174(parameter) libmosquitto.3.xml:181(parameter) msgid "const char *sub" msgstr "" #: libmosquitto.3.xml:178(function) msgid "mosquitto_unsubscribe" msgstr "" #: libmosquitto.3.xml:187(title) msgid "Network loop" msgstr "" #: libmosquitto.3.xml:190(function) msgid "mosquitto_loop" msgstr "" #: libmosquitto.3.xml:192(parameter) msgid "int timeout" msgstr "" #: libmosquitto.3.xml:195(function) msgid "mosquitto_loop_read" msgstr "" #: libmosquitto.3.xml:199(function) msgid "mosquitto_loop_write" msgstr "" #: libmosquitto.3.xml:203(function) msgid "mosquitto_loop_misc" msgstr "" #: libmosquitto.3.xml:207(function) msgid "mosquitto_socket" msgstr "" #: libmosquitto.3.xml:214(title) msgid "Callbacks" msgstr "" #: libmosquitto.3.xml:215(para) msgid "See mosquitto.h" msgstr "" #: libmosquitto.3.xml:250(title) msgid "Examples" msgstr "" #: libmosquitto.3.xml:251(programlisting) #, no-wrap msgid "\n#include <mosquitto.h>\n\nvoid my_message_callback(void *obj, struct mosquitto_message *message)\n{\n\tif(message->payloadlen){\n\t\tprintf(\"%s %s\\n\", message->topic, message->payload);\n\t}else{\n\t\tprintf(\"%s (null)\\n\", message->topic);\n\t}\n\tfflush(stdout);\n}\n\nvoid my_connect_callback(void *obj, int result)\n{\n\tstruct mosquitto *mosq = obj;\n\n\tint i;\n\tif(!result){\n\t\tmosquitto_subscribe(mosq, topics[i], topic_qos);\n\t}else{\n\t\tfprintf(stderr, \"Connect failed\\n\");\n\t}\n}\n\nvoid my_subscribe_callback(void *obj, uint16_t mid, int qos_count, const uint8_t *granted_qos)\n{\n\tint i;\n\n\tprintf(\"Subscribed (mid: %d): %d\", mid, granted_qos[0]);\n\tfor(i=1; i<qos_count; i++){\n\t\tprintf(\", %d\", granted_qos[i]);\n\t}\n\tprintf(\"\\n\");\n}\n\nint main(int argc, char *argv[])\n{\n\tchar id[30];\n\tint i;\n\tchar *host = \"localhost\";\n\tint port = 1883;\n\tint keepalive = 60;\n\tbool clean_session = true;\n\tstruct mosquitto *mosq = NULL;\n\n\tmosq = mosquitto_new(id, NULL);\n\tif(!mosq){\n\t\tfprintf(stderr, \"Error: Out of memory.\\n\");\n\t\treturn 1;\n\t}\n\tmosquitto_log_init(mosq, MOSQ_LOG_DEBUG | MOSQ_LOG_ERR | MOSQ_LOG_WARNING\n\t\t\t| MOSQ_LOG_NOTICE | MOSQ_LOG_INFO, MOSQ_LOG_STDERR);\n\n\tmosquitto_connect_callback_set(mosq, my_connect_callback);\n\tmosquitto_message_callback_set(mosq, my_message_callback);\n\tmosquitto_subscribe_callback_set(mosq, my_subscribe_callback);\n\n\tif(mosquitto_connect(mosq, host, port, keepalive, clean_session)){\n\t\tfprintf(stderr, \"Unable to connect.\\n\");\n\t\treturn 1;\n\t}\n\n\twhile(!mosquitto_loop(mosq, -1)){\n\t}\n\tmosquitto_destroy(mosq);\n\treturn 0;\n}\n\t\t" msgstr "" #: libmosquitto.3.xml:322(title) msgid "See Also" msgstr "" #: libmosquitto.3.xml:325(refentrytitle) msgid "mosquitto" msgstr "" #: libmosquitto.3.xml:326(manvolnum) msgid "8" msgstr "" #: libmosquitto.3.xml:329(refentrytitle) msgid "mqtt" msgstr "" #: libmosquitto.3.xml:330(manvolnum) msgid "7" msgstr "" #: libmosquitto.3.xml:336(title) msgid "Author" msgstr "" #: libmosquitto.3.xml:337(para) msgid "Roger Light roger@atchoo.org" msgstr "" #. Put one translator per line, in the form of NAME , YEAR1, YEAR2 #: libmosquitto.3.xml:0(None) msgid "translator-credits" msgstr "" mosquitto-0.15/man/CMakeLists.txt0000664000175000017500000000044511713444064016045 0ustar rogerrogerinstall(FILES 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 mqtt.7 DESTINATION ${MANDIR}/man7) install(FILES mosquitto.8 DESTINATION ${MANDIR}/man8) mosquitto-0.15/man/mosquitto.conf.50000664000175000017500000004077411713444064016374 0ustar rogerroger'\" -*- coding: us-ascii -*- .if \n(.g .ds T< \\FC .if \n(.g .ds T> \\F[\n[.fam]] .de URL \\$2 \(la\\$1\(ra\\$3 .. .if \n(.g .mso www.tmac .TH mosquitto.conf 5 "5 February 2012" "" "" .SH NAME mosquitto.conf \- the configuration file for mosquitto .SH SYNOPSIS 'nh .fi .ad l \fBmosquitto.conf\fR \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu 'in \n(.iu-\nxu .ad b 'hy .SH DESCRIPTION \fBmosquitto.conf\fR is the configuration file for mosquitto. This file can reside anywhere as long as mosquitto can read it. By default, mosquitto does not need a configuration file and will use the default values listed below. See \fBmosquitto\fR(8) for information on how to load a configuration file. .SH "FILE FORMAT" All lines with a # as the very first character are treated as a comment. .PP Configuration lines start with a variable name. The variable value is separated from the name by a single space. .SH VARIABLES .TP \*(T<\fBacl_file\fR\*(T> \fIfile path\fR Set the path to an access control list file. If defined, the contents of the file are used to control client access to topics on the broker. If this parameter is defined then only the topics listed will have access. Topic access is added with lines of the format: \*(T\*(T> The access type is controlled using "read" or "write". This parameter is optional - if not given then the access is read/write. 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: \*(T\*(T> The username referred to here is the same as in password_file. It is not the clientid. It is also possible to define ACLs based on pattern substitution within the topic. The form is the same as for the topic keyword, but using pattern as the keyword. \*(T\*(T> The patterns available for substition are: .RS .TP 0.2i \(bu %c to match the client id of the client .TP 0.2i \(bu %u to match the username of the client .PP The substitution pattern must be the only text for that level of hierarchy. Pattern ACLs apply to all users even if the "user" keyword has previously been given. Example: \*(T Reloaded on reload signal. The currently loaded ACLs will be freed and reloaded. Existing subscriptions will be affected after the reload. .RE .TP \*(T<\fBallow_anonymous\fR\*(T> [ true | false ] 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. Reloaded on reload signal. .TP \*(T<\fBautosave_interval\fR\*(T> \fIseconds\fR The number of seconds that mosquitto will wait between each time it saves the in-memory database to disk. If set to 0, the in-memory database will only be saved when mosquitto exits or when receiving the SIGUSR1 signal. Note that this setting only has an effect if persistence is enabled. Defaults to 1800 seconds (30 minutes). Reloaded on reload signal. .TP \*(T<\fBbind_address\fR\*(T> \fIaddress\fR Listen for incoming network connections on the specified IP address/hostname only. This is useful to restrict access to certain network interfaces. To restrict access to mosquitto to the local host only, use "bind_address localhost". This only applies to the default listener. Use the listener variable to control other listeners. Not reloaded on reload signal. .TP \*(T<\fBclientid_prefixes\fR\*(T> \fIprefix\fR If defined, only clients that have a clientid with a prefix that matches clientid_prefixes will be allowed to connect to the broker. For example, setting "secure-" here would mean a client "secure-client" could connect but another with clientid "mqtt" couldn't. By default, all client ids are valid. Reloaded on reload signal. Note that currently connected clients will be unaffected by any changes. .TP \*(T<\fBconnection_messages\fR\*(T> < true | false > If set to true, the log will include entries when clients connect and disconnect. If set to false, these entries will not appear. Reloaded on reload signal. .TP \*(T<\fBlistener\fR\*(T> \fIport\fR Listen for incoming network connection on the specified port. A second optional argument allows the listener to be bound to a specific ip address/hostname. If this variable is used and neither bind_address nor port are used then the default listener will not be started. This option may be specified multiple times. See also the mount_point option. Not reloaded on reload signal. .TP \*(T<\fBlog_dest\fR\*(T> \fIdestinations\fR Send log messages to a particular destination. Possible destinations are: stdout stderr syslog topic. 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 and topic logs to the broker topic '$SYS/broker/log/', where severity is one of D, E, W, N, I which are debug, error, warning, notice and information. Use "log_dest none" if you wish to disable logging. Defaults to stderr. This option may be specified multiple times. Reloaded on reload signal. .TP \*(T<\fBlog_timestamp\fR\*(T> [ true | false ] Boolean value, if set to true a timestamp value will be added to each log entry. The default is true. Reloaded on reload signal. .TP \*(T<\fBlog_type\fR\*(T> \fItypes\fR Choose types of messages to log. Possible types are: debug, error, warning, notice, information, none. Defaults to error, warning, notice and information. This option may be specified multiple times. Note that the debug type (used for decoding incoming network packets) is never logged in syslog or topics. Reloaded on reload signal. .TP \*(T<\fBmax_connections\fR\*(T> \fIcount\fR Limit the total number of clients connected for the current listener. Set to \*(T<\-1\*(T> to have "unlimited" connections. Note that other limits may be imposed that are outside the control of mosquitto. See e.g. \fBlimits.conf\fR(5). Not reloaded on reload signal. .TP \*(T<\fBmax_inflight_messages\fR\*(T> \fIcount\fR The maximum number of QoS 1 or 2 messages that can be in the process of being transmitted simultaneously. This includes messages currently going through handshakes and messages that are being retried. Defaults to 20. Set to 0 for no maximum. If set to 1, this will guarantee in-order delivery of messages. Reloaded on reload signal. .TP \*(T<\fBmax_queued_messages\fR\*(T> \fIcount\fR The maximum number of QoS 1 or 2 messages to hold in the queue above those messages that are currently in flight. Defaults to 100. Set to 0 for no maximum (not recommended). Reloaded on reload signal. .TP \*(T<\fBmount_point\fR\*(T> \fItopic prefix\fR This option is used with the listener option to isolate groups of clients. When a client connects to a listener which uses this option, the string argument is attached to the start of all topics for this client. This prefix is removed when any messages are sent to the client. This means a client connected to a listener with mount point \*(T<\fBexample\fR\*(T> can only see messages that are published in the topic hierarchy \*(T<\fBexample\fR\*(T> and above. Not reloaded on reload signal. .TP \*(T<\fBpassword_file\fR\*(T> \fIfile path\fR Set the path to a password file. If defined, the contents of the file are used to control client access to the broker. Each line should be in the format "username:password", where the colon and password are optional but recommended. If allow_anonymous is set to false, only users defined in this file will be able to connect. Setting allow_anonymous to true when password_file is defined is valid and could be used with acl_file to have e.g. read only guest/anonymous accounts and defined users that can publish. Reloaded on reload signal. The currently loaded username and password data will be freed and reloaded. Clients that are already connected will not be affected. .TP \*(T<\fBpersistence\fR\*(T> [ true | false ] Can be true or false. If true, connection, subscription and message data will be written to the disk in mosquitto.db at the location dictated by persistence_location. When mosquitto is restarted, it will reload the information stored in mosquitto.db. The data will be written to disk when mosquitto closes and also at periodic intervals as defined by autosave_interval. Writing of the persistence database may also be forced by sending mosquitto the SIGUSR1 signal. If false, the data will be stored in memory only. Defaults to false. Reloaded on reload signal. .TP \*(T<\fBpersistence_file\fR\*(T> \fIfile name\fR The filename to use for the persistent database. Defaults to mosquitto.db. Reloaded on reload signal. .TP \*(T<\fBpersistence_location\fR\*(T> \fIpath\fR The path where the persistence database should be stored. Must end in a trailing slash. If not given, then the current directory is used. Reloaded on reload signal. .TP \*(T<\fBpid_file\fR\*(T> \fIfile path\fR Write a pid file to the file specified. If not given (the default), no pid file will be written. If the pid file cannot be written, mosquitto will exit. This option only has an effect is mosquitto is run in daemon mode. If mosquitto is being automatically started by an init script it will usually be required to write a pid file. This should then be configured as /var/run/mosquitto.pid Not reloaded on reload signal. .TP \*(T<\fBport\fR\*(T> \fIport number\fR Set the network port for the default listener to listen on. Defaults to 1883. Not reloaded on reload signal. .TP \*(T<\fBretained_persistence\fR\*(T> [ true | false ] This is a synonym of the \*(T<\fBpersistence\fR\*(T> option. Reloaded on reload signal. .TP \*(T<\fBretry_interval\fR\*(T> \fIseconds\fR The integer number of seconds after a QoS=1 or QoS=2 message has been sent that mosquitto will wait before retrying when no response is received. If unset, defaults to 20 seconds. Reloaded on reload signal. .TP \*(T<\fBstore_clean_interval\fR\*(T> \fIseconds\fR The integer number of seconds between the internal message store being cleaned of messages that are no longer referenced. 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. Defaults to 10 seconds. Reloaded on reload signal. .TP \*(T<\fBsys_interval\fR\*(T> \fIseconds\fR The integer number of seconds between updates of the $SYS subscription hierarchy, which provides status information about the broker. If unset, defaults to 10 seconds. Reloaded on reload signal. .TP \*(T<\fBuser\fR\*(T> \fIusername\fR When run as root, change to this user and its primary group on startup. If mosquitto is unable to change to this user and group, it will exit with an error. The user specified must have read/write access to the persistence database if it is to be written. If run as a non-root user, this setting has no effect. Defaults to mosquitto. This setting has no effect on Windows and so you should run mosquitto as the user you wish it to run as. Not reloaded on reload signal. .SH "CONFIGURING BRIDGES" Multiple bridges (connections to other brokers) can be configured using the following variables. .PP Bridges cannot currently be reloaded on reload signal. .TP \*(T<\fBaddress\fR\*(T> \fIaddress[:port]\fR, \*(T<\fBaddresses\fR\*(T> \fIaddress[:port]\fR Specify the address and optionally the port of the bridge to connect to. This must be given for each bridge connection. If the port is not specified, the default of 1883 is used. Unlike rsmb, it is not currently possible to specify multiple addresses for a single bridge connection here. This is true even if the name "addresses" is used. .TP \*(T<\fBcleansession\fR\*(T> [ true | false ] Set the clean session option for this bridge. Setting to false (the default), means that all subscriptions on the remote broker are kept in case of the network connection dropping. If set to true, all subscriptions and messages on the remote broker will be cleaned up if the connection drops. Note that setting to true may cause a large amount of retained messages to be sent each time the bridge reconnects. .TP \*(T<\fBclientid\fR\*(T> \fIid\fR 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. .TP \*(T<\fBconnection\fR\*(T> \fIname\fR This variable marks the start of a new bridge connection. It is also used to give the bridge a name which is used as the client id on the remote broker. .TP \*(T<\fBkeepalive_interval\fR\*(T> \fIseconds\fR Set the number of seconds after which the bridge should send a ping if no other traffic has occurred. Defaults to 60. A minimum value of 5 seconds isallowed. .TP \*(T<\fBidle_timeout\fR\*(T> \fIseconds\fR Set the amount of time a bridge using the lazy start type must be idle before it will be stopped. Defaults to 60 seconds. .TP \*(T<\fBnotifications\fR\*(T> [ true | 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/bridge/connection//state. If the message is 1 then the connection is active, or 0 if the connection has failed. Defaults to true. .TP \*(T<\fBpassword\fR\*(T> \fIvalue\fR Configure a password for the bridge. This is used for authentication purposes when connecting to a broker that support MQTT v3.1 and requires a username and/or password to connect. This option is only valid if a username is also supplied. .TP \*(T<\fBstart_type\fR\*(T> [ automatic | lazy | once ] 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. .TP \*(T<\fBthreshold\fR\*(T> \fIcount\fR Set the number of messages that need to be queued for a bridge with lazy start type to be restarted. Defaults to 10 messages. .TP \*(T<\fBtopic\fR\*(T> \fIpattern\fR [ out | in | both ] Define a topic pattern to be shared between the two brokers. Any topics matching the pattern (which may include wildcards) are shared. The second parameter defines the direction that the messages will be shared in, so it is possible to import messages from a remote broker using "in", export messages to a remote broker using "out" or share messages in both directions. If this parameter is not defined, the default of "out" is used. This option can be specified multiple times per bridge. Care must be taken to ensure that loops are not created with this option. If you are experiencing high CPU load from a broker, it is possible that you have a loop where each broker is forever forwarding each other the same messages. .TP \*(T<\fBusername\fR\*(T> \fIname\fR Configure a username for the bridge. This is used for authentication purposes when connecting to a broker that support MQTT v3.1 and requires a username and/or password to connect. See also the password option. .SH "EXTERNAL SECURITY CHECKS" The following options are available when external security checks have been compiled in. Unless you have done this yourself it is unlikely to exist. .TP \*(T<\fBdb_host\fR\*(T> \fIhostname\fR Database host name. Reloaded on reload signal. .TP \*(T<\fBdb_port\fR\*(T> \fIport\fR Database port. Reloaded on reload signal. .TP \*(T<\fBdb_name\fR\*(T> \fIname\fR Database name. Reloaded on reload signal. .TP \*(T<\fBdb_username\fR\*(T> \fIusername\fR Database username. Reloaded on reload signal. .TP \*(T<\fBdb_password\fR\*(T> \fIpassword\fR Database password. Reloaded on reload signal. .SH FILES mosquitto.conf .SH BUGS \fBmosquitto\fR bug information can be found at http://launchpad.net/mosquitto .SH "SEE ALSO" \fBmosquitto\fR(8) \fBmqtt\fR(7) \fBlimits.conf\fR(5) .SH AUTHOR Roger Light <\*(T> mosquitto-0.15/man/mosquitto_sub.1.xml0000664000175000017500000002574611713444064017116 0ustar rogerroger mosquitto_sub 1 mosquitto_sub an mqtt version 3.1 client for subscribing to topics mosquitto_sub hostname client_id client id prefix keepalive time port number message QoS username password topic payload qos message topic Description mosquitto_sub is a simple mqtt version 3.1 client that will subscribe to a topic and print the messages that it receives. Options 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. If using this option, it is recommended that the client id is set manually with Enable debug messages. Specify the host to connect to. Defaults to localhost. 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 argument. 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 argument. 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. Connect to the port specified instead of the default 1883. 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. Specify the quality of service desired for the incoming messages, from 0, 1 and 2. Defaults to 0. See mqtt7 for more information on QoS. The QoS is identical for all topics subscribed to in a single instance of mosquitto_sub. 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 without a port). The mqtt topic to subscribe to. See mqtt7 for more information on mqtt topics. This option may be repeated to subscribe to multiple topics. Provide a username to be used for authenticating with the broker. This requires a broker that supports MQTT v3.1. See also the argument. 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". 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 . The QoS to use for the Will. Defaults to 0. This must be used in conjunction with . 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 . The topic on which to send a Will, in the event that the client disconnects unexpectedly. Wills mosquitto_sub can register a message with the broker that will be sent out if it disconnects unexpectedly. See mqtt7 for more information. The minimum requirement for this is to use to specify which topic the will should be sent out on. This will result in a non-retained, zero length message with QoS 0. Use the , and arguments to modify the other will parameters. Examples 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. Subscribe to temperature information on localhost with QoS 1: mosquitto_sub -t sensors/temperature -q 1 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. mosquitto_sub -t sensors/machines/+/temperature/+ Subscribe to all broker status messages: mosquitto_sub -v -t \$SYS/# Bugs mosquitto_sub bug information can be found at http://launchpad.net/mosquitto See Also mqtt 7 mosquitto_pub 1 mosquitto 8 libmosquitto 3 Author Roger Light roger@atchoo.org mosquitto-0.15/man/libmosquitto.3.xml0000664000175000017500000002661411713444064016731 0ustar rogerroger libmosquitto 3 libmosquitto MQTT version 3.1 client library Description 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 are also bindings for libmosquitto for C++ and Python. They are not documented here. This is fairly incomplete, please see mosquitto.h for a better description of the functions. Status The libmosquitto api is currently regarded as experimental and unstable and may change in future releases. libmosquitto symbol names 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! Functions Library version unsigned long mosquitto_lib_version int *major int *minor int *revision 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. 9000 for 0.9) that can be used for comparisons. Library initialisation and cleanup int mosquitto_lib_init int mosquitto_lib_cleanup Client constructor/destructor struct mosquitto *mosquitto_new const char *id void *obj void mosquitto_destroy struct mosquitto *mosq Logging int mosquitto_log_init struct mosquitto *mosq int priorities int destinations Configure the logging settings for this client. Returns 0 on success, 1 on error. Set priorities by ORing any of the items in the following list: MOSQ_LOG_INFO MOSQ_LOG_NOTICE MOSQ_LOG_WARNING MOSQ_LOG_ERROR MOSQ_LOG_DEBUG Set destinations by ORing any of the items in the following list: MOSQ_LOG_NONE MOSQ_LOG_STDOUT MOSQ_LOG_STDERR Wills int mosquitto_will_set struct mosquitto *mosq bool will const char *topic uint32_t payloadlen const uint8_t *payload int qos bool retain Connect/disconnect void mosquitto_connect struct mosquitto *mosq const char *host int port int keepalive bool clean_session void mosquitto_reconnect struct mosquitto *mosq int mosquitto_disconnect struct mosquitto *mosq Publish int mosquitto_publish struct mosquitto *mosq uint16_t *mid const char *topic uint32_t payloadlen const uint8_t *payload int qos bool retain Subscribe/unsubscribe int mosquitto_subscribe struct mosquitto *mosq uint16_t *mid const char *sub int qos int mosquitto_unsubscribe struct mosquitto *mosq uint16_t *mid const char *sub Network loop int mosquitto_loop struct mosquitto *mosq int timeout int mosquitto_loop_read struct mosquitto *mosq int mosquitto_loop_write struct mosquitto *mosq int mosquitto_loop_misc struct mosquitto *mosq int mosquitto_socket struct mosquitto *mosq Callbacks See mosquitto.h Examples #include <mosquitto.h> void my_message_callback(void *obj, 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(void *obj, int result) { struct mosquitto *mosq = obj; int i; if(!result){ mosquitto_subscribe(mosq, topics[i], topic_qos); }else{ fprintf(stderr, "Connect failed\n"); } } void my_subscribe_callback(void *obj, uint16_t mid, int qos_count, const uint8_t *granted_qos) { int i; printf("Subscribed (mid: %d): %d", mid, granted_qos[0]); for(i=1; i<qos_count; i++){ printf(", %d", granted_qos[i]); } printf("\n"); } 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; mosq = mosquitto_new(id, NULL); if(!mosq){ fprintf(stderr, "Error: Out of memory.\n"); return 1; } mosquitto_log_init(mosq, MOSQ_LOG_DEBUG | MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE | MOSQ_LOG_INFO, MOSQ_LOG_STDERR); 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, clean_session)){ fprintf(stderr, "Unable to connect.\n"); return 1; } while(!mosquitto_loop(mosq, -1)){ } mosquitto_destroy(mosq); return 0; } See Also mosquitto 8 mqtt 7 Author Roger Light roger@atchoo.org mosquitto-0.15/man/mosquitto_pub.1.xml0000664000175000017500000002715611713444064017110 0ustar rogerroger mosquitto_pub 1 mosquitto_pub an mqtt version 3.1 client for publishing simple messages mosquitto_pub hostname client_id client id prefix port number message QoS file message username password topic payload qos message-topic Description mosquitto_pub is a simple mqtt version 3.1 client that will publish a single message on a topic and exit. Options Enable debug messages. Send the contents of a file as the message. Specify the host to connect to. Defaults to localhost. 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 argument. 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 argument. Send messages read from stdin, splitting separate lines into separate messages. Note that blank lines won't be sent. Send a single message from the command line. Send a null (zero length) message. Connect to the port specified instead of the default 1883. 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. Specify the quality of service to use for the message, from 0, 1 and 2. Defaults to 0. 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 without a port). If retain is given, the message will be retained as a "last know good" value on the broker. See mqtt7 for more information. Send a message read from stdin, sending the entire content as a single message. The mqtt topic on which to publish the message. See mqtt7 for more information on mqtt topics. Provide a username to be used for authenticating with the broker. This requires a broker that supports MQTT v3.1. See also the argument. 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 . The QoS to use for the Will. Defaults to 0. This must be used in conjunction with . 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 . The topic on which to send a Will, in the event that the client disconnects unexpectedly. Wills mosquitto_sub can register a message with the broker that will be sent out if it disconnects unexpectedly. See mqtt7 for more information. The minimum requirement for this is to use to specify which topic the will should be sent out on. This will result in a non-retained, zero length message with QoS 0. Use the , and arguments to modify the other will parameters. Examples Publish temperature information to localhost with QoS 1: mosquitto_pub -t sensors/temperature -m 32 -q 1 Publish timestamp and temperature information to a remote host on a non-standard port and QoS 0: mosquitto_pub -h 192.168.1.1 -p 1885 -t sensors/temperature -m "1266193804 32" Publish light switch status. Message is set to retained because there may be a long period of time between light switch events: mosquitto_pub -r -t switches/kitchen_lights/status -m "on" Send the contents of a file in two ways: mosquitto_pub -t my/topic -f ./data mosquitto_pub -t my/topic -s < ./data Send parsed electricity usage data from a Current Cost meter, reading from stdin with one line/reading as one message: read_cc128.pl | mosquitto_pub -t sensors/cc128 -l Bugs mosquitto_pub bug information can be found at http://launchpad.net/mosquitto See Also mqtt 7 mosquitto_sub 1 mosquitto 8 libmosquitto 3 Author Roger Light roger@atchoo.org mosquitto-0.15/man/mosquitto.80000664000175000017500000002001111713444064015431 0ustar rogerroger'\" -*- coding: us-ascii -*- .if \n(.g .ds T< \\FC .if \n(.g .ds T> \\F[\n[.fam]] .de URL \\$2 \(la\\$1\(ra\\$3 .. .if \n(.g .mso www.tmac .TH mosquitto 8 "5 February 2012" "" "" .SH NAME mosquitto \- an mqtt broker .SH SYNOPSIS 'nh .fi .ad l \fBmosquitto\fR \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu [\fB-c\fR \fIconfig file\fR] [\fB-d\fR | \fB--daemon\fR] [\fB-p\fR \fIport number\fR] 'in \n(.iu-\nxu .ad b 'hy .SH DESCRIPTION \fBmosquitto\fR is a broker for the mqtt protocol version 3.1. .SH OPTIONS .TP \*(T<\fB\-c\fR\*(T>, \*(T<\fB\-\-config\-file\fR\*(T> Load configuration from a file. If not given, the default values as described in \fBmosquitto.conf\fR(5) are used. .TP \*(T<\fB\-d\fR\*(T>, \*(T<\fB\-\-daemon\fR\*(T> Run \fBmosquitto\fR in the background as a daemon. All other behaviour remains the same. .TP \*(T<\fB\-p\fR\*(T>, \*(T<\fB\-\-port\fR\*(T> 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. .SH LIMITATIONS \fBmosquitto\fR implements all of the mqtt protocol version 3.1, but there are some limitations compared to rsmb. .TP 0.2i \(bu There are fewer configuration options. .TP 0.2i \(bu There is less logging information. .TP 0.2i \(bu It isn't as well tested or documented... .PP It should be noted that all of the above limitations should have "currently" included in them. They will all be fixed at some point. .SH "BROKER STATUS" 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 \*(T<\fBsys_interval\fR\*(T> seconds. If \*(T<\fBsys_interval\fR\*(T> is 0, then updates are not sent. .TP \*(T<\fB$SYS/broker/bytes/per second/received\fR\*(T> The average number of bytes received per second since the broker started. .TP \*(T<\fB$SYS/broker/bytes/per second/sent\fR\*(T> The average number of bytes sent per second since the broker started. .TP \*(T<\fB$SYS/broker/bytes/received\fR\*(T> The total number of bytes received since the broker started. .TP \*(T<\fB$SYS/broker/bytes/sent\fR\*(T> The total number of bytes sent since the broker started. .TP \*(T<\fB$SYS/broker/changeset\fR\*(T> The repository changeset (revision) associated with this build. Static. .TP \*(T<\fB$SYS/broker/clients/active\fR\*(T> The number of currently connected clients .TP \*(T<\fB$SYS/broker/clients/inactive\fR\*(T> The total number of persistent clients (with clean session disabled) that are registered at the broker but are currently disconnected. .TP \*(T<\fB$SYS/broker/clients/maximum\fR\*(T> 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. .TP \*(T<\fB$SYS/broker/clients/total\fR\*(T> The total number of active clients currently connected to the broker. .TP \*(T<\fB$SYS/broker/heap/current size\fR\*(T> The current size of the heap memory in use by mosquitto. Note that this topic may be unavailable depending on compile time options. .TP \*(T<\fB$SYS/broker/heap/maximum size\fR\*(T> The largest amount of heap memory used by mosquitto. Note that this topic may be unavailable depending on compile time options. .TP \*(T<\fB$SYS/broker/messages/inflight\fR\*(T> The number of messages with QoS>0 that are awaiting acknowledgments. .TP \*(T<\fB$SYS/broker/messages/per second/received\fR\*(T> The average number of messages received per second since the broker started. .TP \*(T<\fB$SYS/broker/messages/per second/sent\fR\*(T> The average number of messages sent per second since the broker started. .TP \*(T<\fB$SYS/broker/messages/received\fR\*(T> The total number of messages received since the broker started. .TP \*(T<\fB$SYS/broker/messages/sent\fR\*(T> The total number of messages sent since the broker started. .TP \*(T<\fB$SYS/broker/messages/stored\fR\*(T> The number of messages currently held in the message store. .TP \*(T<\fB$SYS/broker/timestamp\fR\*(T> The timestamp at which this particular build of the broker was made. Static. .TP \*(T<\fB$SYS/broker/uptime\fR\*(T> The amount of time in seconds the broker has been online. .TP \*(T<\fB$SYS/broker/version\fR\*(T> The version of the broker. Static. .SH "WILDCARD TOPIC SUBSCRIPTIONS" In addition to allowing clients to subscribe to specific topics, mosquitto also allows the use of two wildcards in subscriptions. \*(T<\fB+\fR\*(T> 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: .TP 0.2i \(bu a/b/c/d .TP 0.2i \(bu +/b/c/d .TP 0.2i \(bu a/+/c/d .TP 0.2i \(bu a/+/+/d .TP 0.2i \(bu +/+/+/+ .PP The following subscriptions will not match: .TP 0.2i \(bu a/b/c .TP 0.2i \(bu b/+/c/d .TP 0.2i \(bu +/+/+ .PP The second wildcard is \*(T<\fB#\fR\*(T> and is used to match all subsequent levels of hierarchy. With a topic of "a/b/c/d", the following example subscriptions will match: .TP 0.2i \(bu a/b/c/d .TP 0.2i \(bu # .TP 0.2i \(bu a/# .TP 0.2i \(bu a/b/# .TP 0.2i \(bu a/b/c/# .TP 0.2i \(bu +/b/c/# .PP The $SYS hierarchy does not match a subscription of "#". If you want to observe the entire $SYS hierarchy, subscribe to $SYS/#. .PP 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 \*(T<\fB#\fR\*(T> wildcard must only ever be used as the final character of a subscription. .SH BRIDGES 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. .PP For information on configuring bridges, see \fBmosquitto.conf\fR(5). .SH SIGNALS .TP SIGHUP Upon receiving the SIGHUP signal, mosquitto will attempt to reload configuration file data, assuming that the \*(T<\fB\-c\fR\*(T> argument was provided when mosquitto was started. Not all configuration parameters can be reloaded without restarting. See \fBmosquitto.conf\fR(5) for details. .TP SIGUSR1 Upon receiving the SIGUSR1 signal, mosquitto will write the persistence database to disk. This signal is only acted upon if persistence is enabled. .TP SIGHUP Upon receiving the SIGHUP signal, mosquitto will attempt to reload its configuration. Not all configuration parameters can be reloaded without a restart. See \fBmosquitto.conf\fR(5) for details. .TP SIGUSR2 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. .SH FILES .TP \*(T<\fI/etc/mosquitto/mosquitto.conf\fR\*(T> Configuration file. See \fBmosquitto.conf\fR(5). .TP \*(T<\fI/var/lib/mosquitto/mosquitto.db\fR\*(T> Persistent message data storage location if persist enabled. .TP \*(T<\fI/etc/hosts.allow\fR\*(T>, \*(T<\fI/etc/hosts.deny\fR\*(T> Host access control via tcp-wrappers as described in \fBhosts_access\fR(5). .SH BUGS \fBmosquitto\fR bug information can be found at http://launchpad.net/mosquitto .SH "SEE ALSO" \fBmqtt\fR(7) \fBmosquitto.conf\fR(5) \fBhosts_access\fR(5) \fBmosquitto_pub\fR(1) \fBmosquitto_sub\fR(1) \fBlibmosquitto\fR(3) .SH THANKS Thanks to Andy Stanford-Clark for being one of the people who came up with MQTT in the first place and providing clarifications of the protocol. .PP Thanks also to everybody at the Ubuntu UK Podcast and Linux Outlaws for organising OggCamp, where Andy gave a talk that inspired mosquitto. .SH AUTHOR Roger Light <\*(T> mosquitto-0.15/man/mqtt.7.xml0000664000175000017500000001670511713444064015167 0ustar rogerroger mqtt 7 mqtt MQ Telemetry Transport mqtt Description mqtt is a publish/subscribe messaging protocol intended that is designed to be lightweight. It is useful for use with low power sensors, but is applicable to many scenarios. This manual describes some of the features of mqtt version 3.1, to assist end users in getting the most out of it. For more complete information on mqtt, see http://mqtt.org/. Publish/Subscribe 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, pachube 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. Topics/Subscriptions 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: sensors/COMPUTER_NAME/temperature/HARDDRIVE_NAME 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, or . 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: sensors/+/temperature/+ As another example, for a topic of "a/b/c/d", the following example subscriptions will match: a/b/c/d +/b/c/d a/+/c/d a/+/+/d +/+/+/+ The following subscriptions will not match: a/b/c b/+/c/d +/+/+ 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: a/b/c/d # a/# a/b/# a/b/c/# +/b/c/# Quality of Service 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. Higher levels of QoS are more reliable, but involve higher latency and have higher bandwidth requirements. 0: The broker/client will deliver the message once, with no confirmation. 1: The broker/client will deliver the message at least once, with confirmation required. 2: The broker/client will deliver the message exactly once by using a four step handshake. Retained Messages 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. Clean session / Durable connections 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. Wills 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. See Also mosquitto 8 mosquitto_pub 1 mosquitto_sub 1 Author Roger Light roger@atchoo.org mosquitto-0.15/man/mosquitto_pub.10000664000175000017500000001377611713444064016314 0ustar rogerroger'\" -*- coding: us-ascii -*- .if \n(.g .ds T< \\FC .if \n(.g .ds T> \\F[\n[.fam]] .de URL \\$2 \(la\\$1\(ra\\$3 .. .if \n(.g .mso www.tmac .TH mosquitto_pub 1 "5 February 2012" "" "" .SH NAME mosquitto_pub \- an mqtt version 3.1 client for publishing simple messages .SH SYNOPSIS 'nh .fi .ad l \fBmosquitto_pub\fR \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu [\fB-d\fR] [\fB-h\fR \fIhostname\fR] [\fB-i\fR \fIclient_id\fR] [\fB-I\fR \fIclient id prefix\fR] [\fB-p\fR \fIport number\fR] [\fB-q\fR \fImessage QoS\fR] [\fB--quiet\fR] [\fB-r\fR] { \fB-f\fR \fIfile\fR | \fB-l\fR | \fB-m\fR \fImessage\fR | \fB-n\fR | \fB-s\fR} [ \fB-u\fR \fIusername\fR [\fB-P\fR \fIpassword\fR] ] [ \fB--will-topic\fR \fItopic\fR [\fB--will-payload\fR \fIpayload\fR] [\fB--will-qos\fR \fIqos\fR] [\fB--will-retain\fR] ] \fB-t\fR \fImessage-topic\fR 'in \n(.iu-\nxu .ad b 'hy .SH DESCRIPTION \fBmosquitto_pub\fR is a simple mqtt version 3.1 client that will publish a single message on a topic and exit. .SH OPTIONS .TP \*(T<\fB\-d\fR\*(T>, \*(T<\fB\-\-debug\fR\*(T> Enable debug messages. .TP \*(T<\fB\-f\fR\*(T>, \*(T<\fB\-\-file\fR\*(T> Send the contents of a file as the message. .TP \*(T<\fB\-h\fR\*(T>, \*(T<\fB\-\-host\fR\*(T> Specify the host to connect to. Defaults to localhost. .TP \*(T<\fB\-i\fR\*(T>, \*(T<\fB\-\-id\fR\*(T> 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 \*(T<\fB\-\-id\-prefix\fR\*(T> argument. .TP \*(T<\fB\-I\fR\*(T>, \*(T<\fB\-\-id\-prefix\fR\*(T> 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 \*(T<\fB\-\-id\fR\*(T> argument. .TP \*(T<\fB\-l\fR\*(T>, \*(T<\fB\-\-stdin\-line\fR\*(T> Send messages read from stdin, splitting separate lines into separate messages. Note that blank lines won't be sent. .TP \*(T<\fB\-m\fR\*(T>, \*(T<\fB\-\-message\fR\*(T> Send a single message from the command line. .TP \*(T<\fB\-n\fR\*(T>, \*(T<\fB\-\-null\-message\fR\*(T> Send a null (zero length) message. .TP \*(T<\fB\-p\fR\*(T>, \*(T<\fB\-\-port\fR\*(T> Connect to the port specified instead of the default 1883. .TP \*(T<\fB\-P\fR\*(T>, \*(T<\fB\-\-pw\fR\*(T> 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 \*(T<\fB\-\-username\fR\*(T> option. .TP \*(T<\fB\-q\fR\*(T>, \*(T<\fB\-\-qos\fR\*(T> Specify the quality of service to use for the message, from 0, 1 and 2. Defaults to 0. .TP \*(T<\fB\-\-quiet\fR\*(T> 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 \*(T<\fB\-\-port\fR\*(T> without a port). .TP \*(T<\fB\-r\fR\*(T>, \*(T<\fB\-\-retain\fR\*(T> If retain is given, the message will be retained as a "last know good" value on the broker. See \fBmqtt\fR(7) for more information. .TP \*(T<\fB\-s\fR\*(T>, \*(T<\fB\-\-stdin\-file\fR\*(T> Send a message read from stdin, sending the entire content as a single message. .TP \*(T<\fB\-t\fR\*(T>, \*(T<\fB\-\-topic\fR\*(T> The mqtt topic on which to publish the message. See \fBmqtt\fR(7) for more information on mqtt topics. .TP \*(T<\fB\-u\fR\*(T>, \*(T<\fB\-\-username\fR\*(T> Provide a username to be used for authenticating with the broker. This requires a broker that supports MQTT v3.1. See also the \*(T<\fB\-\-pw\fR\*(T> argument. .TP \*(T<\fB\-\-will\-payload\fR\*(T> 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 \*(T<\fB\-\-will\-topic\fR\*(T>. .TP \*(T<\fB\-\-will\-qos\fR\*(T> The QoS to use for the Will. Defaults to 0. This must be used in conjunction with \*(T<\fB\-\-will\-topic\fR\*(T>. .TP \*(T<\fB\-\-will\-retain\fR\*(T> 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 \*(T<\fB\-\-will\-topic\fR\*(T>. .TP \*(T<\fB\-\-will\-topic\fR\*(T> The topic on which to send a Will, in the event that the client disconnects unexpectedly. .SH WILLS mosquitto_sub can register a message with the broker that will be sent out if it disconnects unexpectedly. See \fBmqtt\fR(7) for more information. .PP The minimum requirement for this is to use \*(T<\fB\-\-will\-topic\fR\*(T> to specify which topic the will should be sent out on. This will result in a non-retained, zero length message with QoS 0. .PP Use the \*(T<\fB\-\-will\-retain\fR\*(T>, \*(T<\fB\-\-will\-payload\fR\*(T> and \*(T<\fB\-\-will\-qos\fR\*(T> arguments to modify the other will parameters. .SH EXAMPLES Publish temperature information to localhost with QoS 1: .TP 0.2i \(bu mosquitto_pub \*(T<\-t\*(T> sensors/temperature \*(T<\-m\*(T> 32 \*(T<\-q\*(T> 1 .PP Publish timestamp and temperature information to a remote host on a non-standard port and QoS 0: .TP 0.2i \(bu mosquitto_pub \*(T<\-h\*(T> 192.168.1.1 \*(T<\-p\*(T> 1885 \*(T<\-t\*(T> sensors/temperature \*(T<\-m\*(T> "1266193804 32" .PP Publish light switch status. Message is set to retained because there may be a long period of time between light switch events: .TP 0.2i \(bu mosquitto_pub \*(T<\-r\*(T> \*(T<\-t\*(T> switches/kitchen_lights/status \*(T<\-m\*(T> "on" .PP Send the contents of a file in two ways: .TP 0.2i \(bu mosquitto_pub \*(T<\-t\*(T> my/topic \*(T<\-f\*(T> ./data .TP 0.2i \(bu mosquitto_pub \*(T<\-t\*(T> my/topic \*(T<\-s\*(T> < ./data .PP Send parsed electricity usage data from a Current Cost meter, reading from stdin with one line/reading as one message: .TP 0.2i \(bu read_cc128.pl | mosquitto_pub \*(T<\-t\*(T> sensors/cc128 \*(T<\-l\*(T> .SH BUGS \fBmosquitto_pub\fR bug information can be found at http://launchpad.net/mosquitto .SH "SEE ALSO" \fBmqtt\fR(7) \fBmosquitto_sub\fR(1) \fBmosquitto\fR(8) \fBlibmosquitto\fR(3) .SH AUTHOR Roger Light <\*(T> mosquitto-0.15/man/mosquitto_sub.10000664000175000017500000001372111713444064016305 0ustar rogerroger'\" -*- coding: us-ascii -*- .if \n(.g .ds T< \\FC .if \n(.g .ds T> \\F[\n[.fam]] .de URL \\$2 \(la\\$1\(ra\\$3 .. .if \n(.g .mso www.tmac .TH mosquitto_sub 1 "5 February 2012" "" "" .SH NAME mosquitto_sub \- an mqtt version 3.1 client for subscribing to topics .SH SYNOPSIS 'nh .fi .ad l \fBmosquitto_sub\fR \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu [\fB-c\fR] [\fB-d\fR] [\fB-h\fR \fIhostname\fR] [\fB-i\fR \fIclient_id\fR] [\fB-I\fR \fIclient id prefix\fR] [\fB-k\fR \fIkeepalive time\fR] [\fB-p\fR \fIport number\fR] [\fB-q\fR \fImessage QoS\fR] [\fB--quiet\fR] [\fB-v\fR] [ \fB-u\fR \fIusername\fR [\fB-P\fR \fIpassword\fR] ] [ \fB--will-topic\fR \fItopic\fR [\fB--will-payload\fR \fIpayload\fR] [\fB--will-qos\fR \fIqos\fR] [\fB--will-retain\fR] ] \fB-t\fR \fImessage topic\fR \&... 'in \n(.iu-\nxu .ad b 'hy .SH DESCRIPTION \fBmosquitto_sub\fR is a simple mqtt version 3.1 client that will subscribe to a topic and print the messages that it receives. .SH OPTIONS .TP \*(T<\fB\-c\fR\*(T>, \*(T<\fB\-\-disable\-clean\-session\fR\*(T> 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. If using this option, it is recommended that the client id is set manually with \*(T<\fB\-\-id\fR\*(T> .TP \*(T<\fB\-d\fR\*(T>, \*(T<\fB\-\-debug\fR\*(T> Enable debug messages. .TP \*(T<\fB\-h\fR\*(T>, \*(T<\fB\-\-host\fR\*(T> Specify the host to connect to. Defaults to localhost. .TP \*(T<\fB\-i\fR\*(T>, \*(T<\fB\-\-id\fR\*(T> 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 \*(T<\fB\-\-id\-prefix\fR\*(T> argument. .TP \*(T<\fB\-I\fR\*(T>, \*(T<\fB\-\-id\-prefix\fR\*(T> 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 \*(T<\fB\-\-id\fR\*(T> argument. .TP \*(T<\fB\-k\fR\*(T>, \*(T<\fB\-\-keepalive\fR\*(T> 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. .TP \*(T<\fB\-p\fR\*(T>, \*(T<\fB\-\-port\fR\*(T> Connect to the port specified instead of the default 1883. .TP \*(T<\fB\-P\fR\*(T>, \*(T<\fB\-\-pw\fR\*(T> 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 \*(T<\fB\-\-username\fR\*(T> option. .TP \*(T<\fB\-q\fR\*(T>, \*(T<\fB\-\-qos\fR\*(T> Specify the quality of service desired for the incoming messages, from 0, 1 and 2. Defaults to 0. See \fBmqtt\fR(7) for more information on QoS. The QoS is identical for all topics subscribed to in a single instance of mosquitto_sub. .TP \*(T<\fB\-\-quiet\fR\*(T> 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 \*(T<\fB\-\-port\fR\*(T> without a port). .TP \*(T<\fB\-t\fR\*(T>, \*(T<\fB\-\-topic\fR\*(T> The mqtt topic to subscribe to. See \fBmqtt\fR(7) for more information on mqtt topics. This option may be repeated to subscribe to multiple topics. .TP \*(T<\fB\-u\fR\*(T>, \*(T<\fB\-\-username\fR\*(T> Provide a username to be used for authenticating with the broker. This requires a broker that supports MQTT v3.1. See also the \*(T<\fB\-\-pw\fR\*(T> argument. .TP \*(T<\fB\-v\fR\*(T>, \*(T<\fB\-\-verbose\fR\*(T> 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". .TP \*(T<\fB\-\-will\-payload\fR\*(T> 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 \*(T<\fB\-\-will\-topic\fR\*(T>. .TP \*(T<\fB\-\-will\-qos\fR\*(T> The QoS to use for the Will. Defaults to 0. This must be used in conjunction with \*(T<\fB\-\-will\-topic\fR\*(T>. .TP \*(T<\fB\-\-will\-retain\fR\*(T> 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 \*(T<\fB\-\-will\-topic\fR\*(T>. .TP \*(T<\fB\-\-will\-topic\fR\*(T> The topic on which to send a Will, in the event that the client disconnects unexpectedly. .SH WILLS mosquitto_sub can register a message with the broker that will be sent out if it disconnects unexpectedly. See \fBmqtt\fR(7) for more information. .PP The minimum requirement for this is to use \*(T<\fB\-\-will\-topic\fR\*(T> to specify which topic the will should be sent out on. This will result in a non-retained, zero length message with QoS 0. .PP Use the \*(T<\fB\-\-will\-retain\fR\*(T>, \*(T<\fB\-\-will\-payload\fR\*(T> and \*(T<\fB\-\-will\-qos\fR\*(T> arguments to modify the other will parameters. .SH EXAMPLES 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. .PP Subscribe to temperature information on localhost with QoS 1: .TP 0.2i \(bu mosquitto_sub \*(T<\-t\*(T> sensors/temperature \*(T<\-q\*(T> 1 .PP 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. .TP 0.2i \(bu mosquitto_sub \*(T<\-t\*(T> sensors/machines/+/temperature/+ .PP Subscribe to all broker status messages: .TP 0.2i \(bu mosquitto_sub \*(T<\-v\*(T> \*(T<\-t\*(T> \e$SYS/# .SH BUGS \fBmosquitto_sub\fR bug information can be found at http://launchpad.net/mosquitto .SH "SEE ALSO" \fBmqtt\fR(7) \fBmosquitto_pub\fR(1) \fBmosquitto\fR(8) \fBlibmosquitto\fR(3) .SH AUTHOR Roger Light <\*(T> mosquitto-0.15/man/mqtt.70000664000175000017500000001314111713444064014357 0ustar rogerroger'\" -*- coding: us-ascii -*- .if \n(.g .ds T< \\FC .if \n(.g .ds T> \\F[\n[.fam]] .de URL \\$2 \(la\\$1\(ra\\$3 .. .if \n(.g .mso www.tmac .TH mqtt 7 "5 February 2012" "" "" .SH NAME mqtt \- MQ Telemetry Transport .SH SYNOPSIS 'nh .fi .ad l \fBmqtt\fR \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu 'in \n(.iu-\nxu .ad b 'hy .SH DESCRIPTION \fBmqtt\fR is a publish/subscribe messaging protocol intended that is designed to be lightweight. It is useful for use with low power sensors, but is applicable to many scenarios. .PP This manual describes some of the features of mqtt version 3.1, to assist end users in getting the most out of it. For more complete information on mqtt, see http://mqtt.org/. .SH PUBLISH/SUBSCRIBE 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, pachube 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. .SH TOPICS/SUBSCRIPTIONS 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: .TP 0.2i \(bu sensors/COMPUTER_NAME/temperature/HARDDRIVE_NAME .PP 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, \*(T<\fB+\fR\*(T> or \*(T<\fB#\fR\*(T>. .PP \*(T<\fB+\fR\*(T> 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: .TP 0.2i \(bu sensors/+/temperature/+ .PP As another example, for a topic of "a/b/c/d", the following example subscriptions will match: .TP 0.2i \(bu a/b/c/d .TP 0.2i \(bu +/b/c/d .TP 0.2i \(bu a/+/c/d .TP 0.2i \(bu a/+/+/d .TP 0.2i \(bu +/+/+/+ .PP The following subscriptions will not match: .TP 0.2i \(bu a/b/c .TP 0.2i \(bu b/+/c/d .TP 0.2i \(bu +/+/+ .PP \*(T<\fB#\fR\*(T> 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: .TP 0.2i \(bu a/b/c/d .TP 0.2i \(bu # .TP 0.2i \(bu a/# .TP 0.2i \(bu a/b/# .TP 0.2i \(bu a/b/c/# .TP 0.2i \(bu +/b/c/# .SH "QUALITY OF SERVICE" 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. .PP Higher levels of QoS are more reliable, but involve higher latency and have higher bandwidth requirements. .TP 0.2i \(bu 0: The broker/client will deliver the message once, with no confirmation. .TP 0.2i \(bu 1: The broker/client will deliver the message at least once, with confirmation required. .TP 0.2i \(bu 2: The broker/client will deliver the message exactly once by using a four step handshake. .SH "RETAINED MESSAGES" 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. .SH "CLEAN SESSION / DURABLE CONNECTIONS" 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. .SH WILLS 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. .SH "SEE ALSO" \fBmosquitto\fR(8) \fBmosquitto_pub\fR(1) \fBmosquitto_sub\fR(1) .SH AUTHOR Roger Light <\*(T> mosquitto-0.15/man/mosquitto.8.xml0000664000175000017500000003417311713444064016246 0ustar rogerroger mosquitto 8 mosquitto an mqtt broker mosquitto config file port number Description mosquitto is a broker for the mqtt protocol version 3.1. Options Load configuration from a file. If not given, the default values as described in mosquitto.conf5 are used. Run mosquitto in the background as a daemon. All other behaviour remains the same. 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. Limitations mosquitto implements all of the mqtt protocol version 3.1, but there are some limitations compared to rsmb. There are fewer configuration options. There is less logging information. It isn't as well tested or documented... It should be noted that all of the above limitations should have "currently" included in them. They will all be fixed at some point. Broker Status 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 seconds. If is 0, then updates are not sent. The average number of bytes received per second since the broker started. The average number of bytes sent per second since the broker started. The total number of bytes received since the broker started. The total number of bytes sent since the broker started. The repository changeset (revision) associated with this build. Static. The number of currently connected clients The total number of persistent clients (with clean session disabled) that are registered at the broker but are currently disconnected. 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. The total number of active clients currently connected to the broker. The current size of the heap memory in use by mosquitto. Note that this topic may be unavailable depending on compile time options. The largest amount of heap memory used by mosquitto. Note that this topic may be unavailable depending on compile time options. The number of messages with QoS>0 that are awaiting acknowledgments. The average number of messages received per second since the broker started. The average number of messages sent per second since the broker started. The total number of messages received since the broker started. The total number of messages sent since the broker started. The number of messages currently held in the message store. The timestamp at which this particular build of the broker was made. Static. The amount of time in seconds the broker has been online. The version of the broker. Static. Wildcard Topic Subscriptions In addition to allowing clients to subscribe to specific topics, mosquitto also allows the use of two wildcards in subscriptions. 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: a/b/c/d +/b/c/d a/+/c/d a/+/+/d +/+/+/+ The following subscriptions will not match: a/b/c b/+/c/d +/+/+ The second wildcard is and is used to match all subsequent levels of hierarchy. With a topic of "a/b/c/d", the following example subscriptions will match: a/b/c/d # a/# a/b/# a/b/c/# +/b/c/# The $SYS hierarchy does not match a subscription of "#". If you want to observe the entire $SYS hierarchy, subscribe to $SYS/#. 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 wildcard must only ever be used as the final character of a subscription. Bridges 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. For information on configuring bridges, see mosquitto.conf5. Signals SIGHUP Upon receiving the SIGHUP signal, mosquitto will attempt to reload configuration file data, assuming that the argument was provided when mosquitto was started. Not all configuration parameters can be reloaded without restarting. See mosquitto.conf5 for details. SIGUSR1 Upon receiving the SIGUSR1 signal, mosquitto will write the persistence database to disk. This signal is only acted upon if persistence is enabled. SIGHUP Upon receiving the SIGHUP signal, mosquitto will attempt to reload its configuration. Not all configuration parameters can be reloaded without a restart. See mosquitto.conf5 for details. SIGUSR2 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. Files /etc/mosquitto/mosquitto.conf Configuration file. See mosquitto.conf5. /var/lib/mosquitto/mosquitto.db Persistent message data storage location if persist enabled. /etc/hosts.allow /etc/hosts.deny Host access control via tcp-wrappers as described in hosts_access5. Bugs mosquitto bug information can be found at http://launchpad.net/mosquitto See Also mqtt 7 mosquitto.conf 5 hosts_access 5 mosquitto_pub 1 mosquitto_sub 1 libmosquitto 3 Thanks Thanks to Andy Stanford-Clark for being one of the people who came up with MQTT in the first place and providing clarifications of the protocol. Thanks also to everybody at the Ubuntu UK Podcast and Linux Outlaws for organising OggCamp, where Andy gave a talk that inspired mosquitto. Author Roger Light roger@atchoo.org mosquitto-0.15/man/libmosquitto.30000664000175000017500000001632311713444064016126 0ustar rogerroger'\" -*- coding: us-ascii -*- .if \n(.g .ds T< \\FC .if \n(.g .ds T> \\F[\n[.fam]] .de URL \\$2 \(la\\$1\(ra\\$3 .. .if \n(.g .mso www.tmac .TH libmosquitto 3 "5 February 2012" "" "" .SH NAME libmosquitto \- MQTT version 3.1 client library .SH DESCRIPTION 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 are also bindings for libmosquitto for C++ and Python. They are not documented here. .PP This is fairly incomplete, please see mosquitto.h for a better description of the functions. .SH STATUS The libmosquitto api is currently regarded as experimental and unstable and may change in future releases. .SH "LIBMOSQUITTO SYMBOL NAMES" 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! .SH FUNCTIONS .SS "LIBRARY VERSION" 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIint *major\fR, \fIint *minor\fR, \fIint *revision\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy .PP 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. 9000 for 0.9) that can be used for comparisons. .SS "LIBRARY INITIALISATION AND CLEANUP" 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(void);\*(T> 'in \n(.iu-\nxu .ad b 'hy 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(void);\*(T> 'in \n(.iu-\nxu .ad b 'hy .SS "CLIENT CONSTRUCTOR/DESTRUCTOR" 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIconst char *id\fR, \fIvoid *obj\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy .SS LOGGING 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR, \fIint priorities\fR, \fIint destinations\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy .PP Configure the logging settings for this client. Returns 0 on success, 1 on error. .PP Set \*(T by ORing any of the items in the following list: .TP 0.2i \(bu MOSQ_LOG_INFO .TP 0.2i \(bu MOSQ_LOG_NOTICE .TP 0.2i \(bu MOSQ_LOG_WARNING .TP 0.2i \(bu MOSQ_LOG_ERROR .TP 0.2i \(bu MOSQ_LOG_DEBUG .PP Set \*(T by ORing any of the items in the following list: .TP 0.2i \(bu MOSQ_LOG_NONE .TP 0.2i \(bu MOSQ_LOG_STDOUT .TP 0.2i \(bu MOSQ_LOG_STDERR .SS WILLS 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR, \fIbool will\fR, \fIconst char *topic\fR, \fIuint32_t payloadlen\fR, \fIconst uint8_t *payload\fR, \fIint qos\fR, \fIbool retain\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy .SS CONNECT/DISCONNECT 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR, \fIconst char *host\fR, \fIint port\fR, \fIint keepalive\fR, \fIbool clean_session\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy .SS PUBLISH 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR, \fIuint16_t *mid\fR, \fIconst char *topic\fR, \fIuint32_t payloadlen\fR, \fIconst uint8_t *payload\fR, \fIint qos\fR, \fIbool retain\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy .SS SUBSCRIBE/UNSUBSCRIBE 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR, \fIuint16_t *mid\fR, \fIconst char *sub\fR, \fIint qos\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR, \fIuint16_t *mid\fR, \fIconst char *sub\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy .SS "NETWORK LOOP" 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR, \fIint timeout\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(\fIstruct mosquitto *mosq\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy .SS CALLBACKS See mosquitto.h .SH EXAMPLES .nf \*(T< #include void my_message_callback(void *obj, struct mosquitto_message *message) { if(message\->payloadlen){ printf("%s %s\en", message\->topic, message\->payload); }else{ printf("%s (null)\en", message\->topic); } fflush(stdout); } void my_connect_callback(void *obj, int result) { struct mosquitto *mosq = obj; int i; if(!result){ mosquitto_subscribe(mosq, topics[i], topic_qos); }else{ fprintf(stderr, "Connect failed\en"); } } void my_subscribe_callback(void *obj, uint16_t mid, int qos_count, const uint8_t *granted_qos) { int i; printf("Subscribed (mid: %d): %d", mid, granted_qos[0]); for(i=1; i .fi .SH "SEE ALSO" \fBmosquitto\fR(8) \fBmqtt\fR(7) .SH AUTHOR Roger Light <\*(T> mosquitto-0.15/man/Makefile0000664000175000017500000000442311713444064014745 0ustar rogerrogerinclude ../config.mk .PHONY : all clean install uninstall dist DB2M:=$(shell which docbook2man.pl 2> /dev/null) ifeq ($(strip $(DB2M)),) DB2XM:=$(shell which docbook2x-man 2> /dev/null) ifeq ($(strip $(DB2XM)),) DOCBOOK2MAN=docbook2man else DOCBOOK2MAN=docbook2x-man endif else DOCBOOK2MAN=docbook2man.pl endif all : mosquitto.8 mosquitto.conf.5 mosquitto_pub.1 mosquitto_sub.1 mqtt.7 libmosquitto.3 clean : reallyclean : clean -rm -f *.orig dist : mosquitto.8 mosquitto.conf.5 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_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) -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_pub.1 -rm -f ${DESTDIR}${mandir}/man1/mosquitto_sub.1 -rm -f ${DESTDIR}${mandir}/man7/mqtt.7 -rm -f ${DESTDIR}${mandir}/man3/libmosquitto.3 mosquitto.8 : mosquitto.8.xml $(DOCBOOK2MAN) mosquitto.8.xml mosquitto.conf.5 : mosquitto.conf.5.xml $(DOCBOOK2MAN) mosquitto.conf.5.xml mosquitto_pub.1 : mosquitto_pub.1.xml $(DOCBOOK2MAN) $^ mosquitto_sub.1 : mosquitto_sub.1.xml $(DOCBOOK2MAN) $^ mqtt.7 : mqtt.7.xml $(DOCBOOK2MAN) $^ libmosquitto.3 : libmosquitto.3.xml $(DOCBOOK2MAN) $^ 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_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/libmosquitto/libmosquitto.3.pot libmosquitto.3.xml # To merge new translations do: # /usr/bin/xml2po -p de.po chapter1.xml > chapter1.de.xml mosquitto-0.15/man/mosquitto.conf.5.xml0000664000175000017500000006135711713444064017173 0ustar rogerroger mosquitto.conf 5 mosquitto.conf the configuration file for mosquitto mosquitto.conf Description mosquitto.conf is the configuration file for mosquitto. This file can reside anywhere as long as mosquitto can read it. By default, mosquitto does not need a configuration file and will use the default values listed below. See mosquitto8 for information on how to load a configuration file. File Format All lines with a # as the very first character are treated as a comment. Configuration lines start with a variable name. The variable value is separated from the name by a single space. Variables file path Set the path to an access control list file. If defined, the contents of the file are used to control client access to topics on the broker. If this parameter is defined then only the topics listed will have access. 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. It is also possible to define ACLs based on pattern substitution within the topic. The form is the same as for the topic keyword, but using pattern as the keyword. pattern [read|write] <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. Pattern ACLs apply to all users even if the "user" keyword has previously been given. Example: pattern write sensor/%u/data Reloaded on reload signal. The currently loaded ACLs will be freed and reloaded. Existing subscriptions will be affected after the reload. [ true | false ] 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. Reloaded on reload signal. seconds The number of seconds that mosquitto will wait between each time it saves the in-memory database to disk. If set to 0, the in-memory database will only be saved when mosquitto exits or when receiving the SIGUSR1 signal. Note that this setting only has an effect if persistence is enabled. Defaults to 1800 seconds (30 minutes). Reloaded on reload signal. address Listen for incoming network connections on the specified IP address/hostname only. This is useful to restrict access to certain network interfaces. To restrict access to mosquitto to the local host only, use "bind_address localhost". This only applies to the default listener. Use the listener variable to control other listeners. Not reloaded on reload signal. prefix If defined, only clients that have a clientid with a prefix that matches clientid_prefixes will be allowed to connect to the broker. For example, setting "secure-" here would mean a client "secure-client" could connect but another with clientid "mqtt" couldn't. By default, all client ids are valid. Reloaded on reload signal. Note that currently connected clients will be unaffected by any changes. < true | false > If set to true, the log will include entries when clients connect and disconnect. If set to false, these entries will not appear. Reloaded on reload signal. port Listen for incoming network connection on the specified port. A second optional argument allows the listener to be bound to a specific ip address/hostname. If this variable is used and neither bind_address nor port are used then the default listener will not be started. This option may be specified multiple times. See also the mount_point option. Not reloaded on reload signal. destinations Send log messages to a particular destination. Possible destinations are: stdout stderr syslog topic. 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 and topic logs to the broker topic '$SYS/broker/log/<severity>', where severity is one of D, E, W, N, I which are debug, error, warning, notice and information. Use "log_dest none" if you wish to disable logging. Defaults to stderr. This option may be specified multiple times. Reloaded on reload signal. [ true | false ] Boolean value, if set to true a timestamp value will be added to each log entry. The default is true. Reloaded on reload signal. types Choose types of messages to log. Possible types are: debug, error, warning, notice, information, none. Defaults to error, warning, notice and information. This option may be specified multiple times. Note that the debug type (used for decoding incoming network packets) is never logged in syslog or topics. Reloaded on reload signal. count Limit the total number of clients connected for the current listener. Set to -1 to have "unlimited" connections. Note that other limits may be imposed that are outside the control of mosquitto. See e.g. limits.conf5. Not reloaded on reload signal. count The maximum number of QoS 1 or 2 messages that can be in the process of being transmitted simultaneously. This includes messages currently going through handshakes and messages that are being retried. Defaults to 20. Set to 0 for no maximum. If set to 1, this will guarantee in-order delivery of messages. Reloaded on reload signal. count The maximum number of QoS 1 or 2 messages to hold in the queue above those messages that are currently in flight. Defaults to 100. Set to 0 for no maximum (not recommended). Reloaded on reload signal. topic prefix This option is used with the listener option to isolate groups of clients. When a client connects to a listener which uses this option, the string argument is attached to the start of all topics for this client. This prefix is removed when any messages are sent to the client. This means a client connected to a listener with mount point can only see messages that are published in the topic hierarchy and above. Not reloaded on reload signal. file path Set the path to a password file. If defined, the contents of the file are used to control client access to the broker. Each line should be in the format "username:password", where the colon and password are optional but recommended. If allow_anonymous is set to false, only users defined in this file will be able to connect. Setting allow_anonymous to true when password_file is defined is valid and could be used with acl_file to have e.g. read only guest/anonymous accounts and defined users that can publish. Reloaded on reload signal. The currently loaded username and password data will be freed and reloaded. Clients that are already connected will not be affected. [ true | false ] Can be true or false. If true, connection, subscription and message data will be written to the disk in mosquitto.db at the location dictated by persistence_location. When mosquitto is restarted, it will reload the information stored in mosquitto.db. The data will be written to disk when mosquitto closes and also at periodic intervals as defined by autosave_interval. Writing of the persistence database may also be forced by sending mosquitto the SIGUSR1 signal. If false, the data will be stored in memory only. Defaults to false. Reloaded on reload signal. file name The filename to use for the persistent database. Defaults to mosquitto.db. Reloaded on reload signal. path The path where the persistence database should be stored. Must end in a trailing slash. If not given, then the current directory is used. Reloaded on reload signal. file path Write a pid file to the file specified. If not given (the default), no pid file will be written. If the pid file cannot be written, mosquitto will exit. This option only has an effect is mosquitto is run in daemon mode. If mosquitto is being automatically started by an init script it will usually be required to write a pid file. This should then be configured as /var/run/mosquitto.pid Not reloaded on reload signal. port number Set the network port for the default listener to listen on. Defaults to 1883. Not reloaded on reload signal. [ true | false ] This is a synonym of the option. Reloaded on reload signal. seconds The integer number of seconds after a QoS=1 or QoS=2 message has been sent that mosquitto will wait before retrying when no response is received. If unset, defaults to 20 seconds. Reloaded on reload signal. seconds The integer number of seconds between the internal message store being cleaned of messages that are no longer referenced. 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. Defaults to 10 seconds. Reloaded on reload signal. seconds The integer number of seconds between updates of the $SYS subscription hierarchy, which provides status information about the broker. If unset, defaults to 10 seconds. Reloaded on reload signal. username When run as root, change to this user and its primary group on startup. If mosquitto is unable to change to this user and group, it will exit with an error. The user specified must have read/write access to the persistence database if it is to be written. If run as a non-root user, this setting has no effect. Defaults to mosquitto. This setting has no effect on Windows and so you should run mosquitto as the user you wish it to run as. Not reloaded on reload signal. Configuring Bridges Multiple bridges (connections to other brokers) can be configured using the following variables. Bridges cannot currently be reloaded on reload signal. address[:port] address[:port] Specify the address and optionally the port of the bridge to connect to. This must be given for each bridge connection. If the port is not specified, the default of 1883 is used. Unlike rsmb, it is not currently possible to specify multiple addresses for a single bridge connection here. This is true even if the name "addresses" is used. [ true | false ] Set the clean session option for this bridge. Setting to false (the default), means that all subscriptions on the remote broker are kept in case of the network connection dropping. If set to true, all subscriptions and messages on the remote broker will be cleaned up if the connection drops. Note that setting to true may cause a large amount of retained messages to be sent each time the bridge reconnects. id 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. name This variable marks the start of a new bridge connection. It is also used to give the bridge a name which is used as the client id on the remote broker. seconds Set the number of seconds after which the bridge should send a ping if no other traffic has occurred. Defaults to 60. A minimum value of 5 seconds isallowed. seconds Set the amount of time a bridge using the lazy start type must be idle before it will be stopped. Defaults to 60 seconds. [ true | 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/bridge/connection/<clientid>/state. If the message is 1 then the connection is active, or 0 if the connection has failed. Defaults to true. value Configure a password for the bridge. This is used for authentication purposes when connecting to a broker that support MQTT v3.1 and requires a username and/or password to connect. This option is only valid if a username is also supplied. [ automatic | lazy | once ] 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. count Set the number of messages that need to be queued for a bridge with lazy start type to be restarted. Defaults to 10 messages. pattern [ out | in | both ] Define a topic pattern to be shared between the two brokers. Any topics matching the pattern (which may include wildcards) are shared. The second parameter defines the direction that the messages will be shared in, so it is possible to import messages from a remote broker using "in", export messages to a remote broker using "out" or share messages in both directions. If this parameter is not defined, the default of "out" is used. This option can be specified multiple times per bridge. Care must be taken to ensure that loops are not created with this option. If you are experiencing high CPU load from a broker, it is possible that you have a loop where each broker is forever forwarding each other the same messages. name Configure a username for the bridge. This is used for authentication purposes when connecting to a broker that support MQTT v3.1 and requires a username and/or password to connect. See also the password option. External Security Checks The following options are available when external security checks have been compiled in. Unless you have done this yourself it is unlikely to exist. hostname Database host name. Reloaded on reload signal. port Database port. Reloaded on reload signal. name Database name. Reloaded on reload signal. username Database username. Reloaded on reload signal. password Database password. Reloaded on reload signal. Files mosquitto.conf Bugs mosquitto bug information can be found at http://launchpad.net/mosquitto See Also mosquitto 8 mqtt 7 limits.conf 5 Author Roger Light roger@atchoo.org mosquitto-0.15/installer/0000775000175000017500000000000011713444064014524 5ustar rogerrogermosquitto-0.15/installer/mosquitto.nsi0000664000175000017500000001016211713444064017303 0ustar rogerroger; 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 0.15 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\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" 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" 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_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\devel\mosquitto.h" Delete "$INSTDIR\devel\mosquitto.lib" Delete "$INSTDIR\devel\mosquittopp.h" Delete "$INSTDIR\devel\mosquittopp.lib" 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 mosquitto-0.15/installer/mosquitto-cygwin.nsi0000664000175000017500000001024611713444064020604 0ustar rogerroger; 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 0.15 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 "..\src\mosquitto.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" 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" 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\mosquitto.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\devel\mosquitto.h" Delete "$INSTDIR\devel\mosquitto.lib" Delete "$INSTDIR\devel\mosquittopp.h" Delete "$INSTDIR\devel\mosquittopp.lib" 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 mosquitto-0.15/readme-windows.txt0000664000175000017500000000042011713444064016211 0ustar rogerrogerMosquitto 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. mosquitto-0.15/client/0000775000175000017500000000000011713444064014005 5ustar rogerrogermosquitto-0.15/client/CMakeLists.txt0000664000175000017500000000077011713444064016551 0ustar rogerrogerinclude_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 libmosquitto) target_link_libraries(mosquitto_sub libmosquitto) install(TARGETS mosquitto_pub RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR}) install(TARGETS mosquitto_sub RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR}) mosquitto-0.15/client/pub_client.c0000664000175000017500000004112311713444064016276 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #include #include #include #include #ifndef WIN32 #include #else #include #include #define snprintf sprintf_s #endif #include #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 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 uint16_t mid_sent = 0; 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(void *obj, int result) { struct mosquitto *mosq = obj; 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, (uint8_t *)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{ switch(result){ case 1: if(!quiet) fprintf(stderr, "Connection Refused: unacceptable protocol version\n"); break; case 2: if(!quiet) fprintf(stderr, "Connection Refused: identifier rejected\n"); break; case 3: if(!quiet) fprintf(stderr, "Connection Refused: broker unavailable\n"); break; case 4: if(!quiet) fprintf(stderr, "Connection Refused: bad user name or password\n"); break; case 5: if(!quiet) fprintf(stderr, "Connection Refused: not authorised\n"); break; default: if(!quiet) fprintf(stderr, "Connection Refused: unknown reason\n"); break; } } } void my_disconnect_callback(void *obj) { connected = false; } void my_publish_callback(void *obj, uint16_t mid) { struct mosquitto *mosq = obj; if(mode != MSGMODE_STDIN_LINE && disconnect_sent == false){ mosquitto_disconnect(mosq); disconnect_sent = true; } } 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; } if(msglen == 0){ fclose(fptr); if(!quiet) fprintf(stderr, "Error: File \"%s\" is empty.\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) { printf("mosquitto_pub is a simple mqtt client that will publish a message on a single topic and exit.\n\n"); printf("Usage: mosquitto_pub [-h host] [-p port] [-q qos] [-r] {-f file | -l | -n | -m message} -t topic\n"); printf(" [-i id] [-I id_prefix]\n"); printf(" [-d] [--quiet]\n"); printf(" [-u username [-P password]]\n"); printf(" [--will-topic [--will-payload payload] [--will-qos qos] [--will-retain]]\n\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(" -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(" -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(" --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"); 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; int keepalive = 60; int opt; char buf[1024]; bool debug = false; struct mosquitto *mosq = NULL; int rc; int rc2; char hostname[21]; char err[1024]; uint8_t *will_payload = NULL; long will_payloadlen = 0; int will_qos = 0; bool will_retain = false; char *will_topic = NULL; for(i=1; i65535){ fprintf(stderr, "Error: Invalid port given: %d\n", port); print_usage(); return 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], "-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], "-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], "-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; #ifndef WIN32 opt = fcntl(fileno(stdin), F_GETFL, 0); if(opt == -1 || fcntl(fileno(stdin), F_SETFL, opt | O_NONBLOCK) == -1){ fprintf(stderr, "Error: Unable to set stdin to non-blocking.\n"); return 1; } #endif } }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], "-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], "-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], "-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], "-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 = (uint8_t *)argv[i+1]; will_payloadlen = strlen((char *)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(id_prefix){ id = malloc(strlen(id_prefix)+10); if(!id){ if(!quiet) fprintf(stderr, "Error: Out of memory.\n"); return 1; } snprintf(id, strlen(id_prefix)+10, "%s%d", id_prefix, getpid()); }else if(!id){ id = malloc(30); if(!id){ if(!quiet) fprintf(stderr, "Error: Out of memory.\n"); return 1; } memset(hostname, 0, 21); gethostname(hostname, 20); snprintf(id, 23, "mosq_pub_%d_%s", getpid(), hostname); } 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"); } mosquitto_lib_init(); mosq = mosquitto_new(id, NULL); if(!mosq){ if(!quiet) fprintf(stderr, "Error: Out of memory.\n"); return 1; } if(debug){ mosquitto_log_init(mosq, MOSQ_LOG_DEBUG | MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE | MOSQ_LOG_INFO, MOSQ_LOG_STDERR); } if(will_topic && mosquitto_will_set(mosq, true, will_topic, will_payloadlen, will_payload, will_qos, will_retain)){ if(!quiet) fprintf(stderr, "Error: Problem setting will.\n"); return 1; } if(username && mosquitto_username_pw_set(mosq, username, password)){ if(!quiet) fprintf(stderr, "Error: Problem setting username and password.\n"); return 1; } mosquitto_connect_callback_set(mosq, my_connect_callback); mosquitto_disconnect_callback_set(mosq, my_disconnect_callback); mosquitto_publish_callback_set(mosq, my_publish_callback); rc = mosquitto_connect(mosq, host, port, keepalive, true); 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); } } return rc; } do{ if(mode == MSGMODE_STDIN_LINE && status == STATUS_CONNACK_RECVD){ if(fgets(buf, 1024, stdin)){ buf[strlen(buf)-1] = '\0'; rc2 = mosquitto_publish(mosq, &mid_sent, topic, strlen(buf), (uint8_t *)buf, qos, retain); if(rc2){ if(!quiet) fprintf(stderr, "Error: Publish returned %d, disconnecting.\n", rc2); mosquitto_disconnect(mosq); } }else if(feof(stdin) && disconnect_sent == false){ mosquitto_disconnect(mosq); disconnect_sent = true; } } rc = mosquitto_loop(mosq, -1); }while(rc == MOSQ_ERR_SUCCESS && connected); if(message && mode == MSGMODE_FILE){ free(message); } mosquitto_destroy(mosq); mosquitto_lib_cleanup(); return rc; } mosquitto-0.15/client/sub_client.c0000664000175000017500000003111411713444064016300 0ustar rogerroger/* Copyright (c) 2009-2012 Roger Light 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. */ #include #include #include #include #ifndef WIN32 #include #else #include #include #define snprintf sprintf_s #endif #include static char **topics = NULL; static int topic_count = 0; static int topic_qos = 0; static char *username = NULL; static char *password = NULL; int verbose = 0; bool quiet = false; void my_message_callback(void *obj, const struct mosquitto_message *message) { if(verbose){ if(message->payloadlen){ printf("%s %s\n", message->topic, message->payload); }else{ printf("%s (null)\n", message->topic); } fflush(stdout); }else{ if(message->payloadlen){ printf("%s\n", message->payload); fflush(stdout); } } } void my_connect_callback(void *obj, int result) { struct mosquitto *mosq = obj; int i; if(!result){ for(i=0; i65535){ fprintf(stderr, "Error: Invalid port given: %d\n", port); print_usage(); return 1; } } i++; }else if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--disable-clean-session")){ clean_session = false; }else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")){ debug = true; }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], "-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], "-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{ topic_qos = atoi(argv[i+1]); if(topic_qos<0 || topic_qos>2){ fprintf(stderr, "Error: Invalid QoS given: %d\n", topic_qos); print_usage(); return 1; } } i++; }else if(!strcmp(argv[i], "--quiet")){ quiet = 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_count++; topics = realloc(topics, topic_count*sizeof(char *)); topics[topic_count-1] = 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], "-v") || !strcmp(argv[i], "--verbose")){ 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{ 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 = (uint8_t *)argv[i+1]; will_payloadlen = strlen((char *)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(!quiet) fprintf(stderr, "Error: You must provide a client id if you are using the -c option.\n"); return 1; } if(id_prefix){ id = malloc(strlen(id_prefix)+10); if(!id){ if(!quiet) fprintf(stderr, "Error: Out of memory.\n"); return 1; } snprintf(id, strlen(id_prefix)+10, "%s%d", id_prefix, getpid()); }else if(!id){ id = malloc(30); if(!id){ if(!quiet) fprintf(stderr, "Error: Out of memory.\n"); return 1; } memset(hostname, 0, 21); gethostname(hostname, 20); snprintf(id, 23, "mosq_sub_%d_%s", getpid(), hostname); } if(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(password && !username){ if(!quiet) fprintf(stderr, "Warning: Not using password since username not set.\n"); } mosquitto_lib_init(); mosq = mosquitto_new(id, NULL); if(!mosq){ if(!quiet) fprintf(stderr, "Error: Out of memory.\n"); return 1; } if(debug){ mosquitto_log_init(mosq, MOSQ_LOG_DEBUG | MOSQ_LOG_ERR | MOSQ_LOG_WARNING | MOSQ_LOG_NOTICE | MOSQ_LOG_INFO, MOSQ_LOG_STDERR); } if(will_topic && mosquitto_will_set(mosq, true, will_topic, will_payloadlen, will_payload, will_qos, will_retain)){ if(!quiet) fprintf(stderr, "Error: Problem setting will.\n"); return 1; } if(username && mosquitto_username_pw_set(mosq, username, password)){ if(!quiet) fprintf(stderr, "Error: Problem setting username and password.\n"); 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); } rc = mosquitto_connect(mosq, host, port, keepalive, clean_session); 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); } } return rc; } do{ rc = mosquitto_loop(mosq, -1); }while(rc == MOSQ_ERR_SUCCESS); mosquitto_destroy(mosq); mosquitto_lib_cleanup(); return rc; } mosquitto-0.15/client/Makefile0000664000175000017500000000134011713444064015443 0ustar rogerrogerCC=cc CFLAGS=-I../lib -Wall -ggdb LDFLAGS=-L../lib ../lib/libmosquitto.so.0 INSTALL=install prefix=/usr/local .PHONY: all install uninstall clean all : mosquitto_pub mosquitto_sub mosquitto_pub : pub_client.o ../lib/libmosquitto.so.0 ${CC} $< -o $@ ${LDFLAGS} mosquitto_sub : sub_client.o ../lib/libmosquitto.so.0 ${CC} $< -o $@ ${LDFLAGS} ../lib/libmosquitto.so.0 : $(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 clean : -rm -f *.o mosquitto_pub mosquitto_sub mosquitto-0.15/Makefile0000664000175000017500000000511511713444064014171 0ustar rogerrogerinclude config.mk DIRS=lib client src man DISTDIRS=man .PHONY : all mosquitto clean reallyclean install uninstall dist sign copy all : mosquitto mosquitto : for d in ${DIRS}; do $(MAKE) -C $${d}; done clean : for d in ${DIRS}; do $(MAKE) -C $${d} clean; done reallyclean : for d in ${DIRS}; do $(MAKE) -C $${d} reallyclean; done -rm -f *.orig install : mosquitto @for d in ${DIRS}; do $(MAKE) -C $${d} install; done $(INSTALL) -d ${DESTDIR}/etc/mosquitto $(INSTALL) -m 644 mosquitto.conf ${DESTDIR}/etc/mosquitto/mosquitto.conf $(INSTALL) -m 644 aclfile.example ${DESTDIR}/etc/mosquitto/aclfile.example $(INSTALL) -m 644 pwfile.example ${DESTDIR}/etc/mosquitto/pwfile.example uninstall : @for d in ${DIRS}; do $(MAKE) -C $${d} uninstall; done dist : reallyclean @for d in ${DISTDIRS}; do $(MAKE) -C $${d} dist; done mkdir -p dist/mosquitto-${VERSION} cp -r client installer lib logo man misc security service src ChangeLog.txt CMakeLists.txt COPYING Makefile compiling.txt config.h config.mk external_security_checks.txt readme.txt readme-windows.txt mosquitto.conf aclfile.example pwfile.example dist/mosquitto-${VERSION}/ cd dist; tar -zcf mosquitto-${VERSION}.tar.gz mosquitto-${VERSION}/ for m in libmosquitto.3 mosquitto.8 mosquitto.conf.5 mosquitto_pub.1 mosquitto_sub.1 mqtt.7; \ do \ hfile=$$(echo $${m} | sed -e 's/\./-/g'); \ man2html man/$${m} > dist/$${hfile}.html; \ sed -i 's#http://localhost/cgi-bin/man/man2html?8+mosquitto#mosquitto-8.html#' dist/$${hfile}.html; \ sed -i 's#http://localhost/cgi-bin/man/man2html?3+libmosquitto#libmosquitto-3.html#' dist/$${hfile}.html; \ sed -i 's#http://localhost/cgi-bin/man/man2html?5+mosquitto.conf#mosquitto-conf-5.html#' dist/$${hfile}.html; \ sed -i 's#http://localhost/cgi-bin/man/man2html?1+mosquitto_pub#mosquitto_pub-1.html#' dist/$${hfile}.html; \ sed -i 's#http://localhost/cgi-bin/man/man2html?1+mosquitto_sub#mosquitto_sub-1.html#' dist/$${hfile}.html; \ sed -i 's#http://localhost/cgi-bin/man/man2html?7+mqtt#mqtt-7.html#' dist/$${hfile}.html; \ sed -i 's#http://localhost/cgi-bin/man/man2html?5+hosts_access#http://www.linuxmanpages.com/man5/hosts_access.5.php#' dist/$${hfile}.html; \ sed -i 's#http://localhost/cgi-bin/man/man2html#http://mosquitto.org/#' dist/$${hfile}.html; \ sed -i '1,2d' 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:mosquitto.org/files/source/ cd dist; scp *.html mosquitto:mosquitto.org/man/ scp ChangeLog.txt mosquitto:mosquitto.org/ mosquitto-0.15/aclfile.example0000664000175000017500000000005311713444064015501 0ustar rogerrogertopic read $SYS/# user roger topic foo/bar