Commit 00bdf989 authored by Ian Craggs's avatar Ian Craggs

Merge branch 'issue_2' into develop

Automatic reconnect and offline buffering
parents ad943e4c b62244d5
......@@ -5,12 +5,12 @@
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.2116872643" moduleId="org.eclipse.cdt.core.settings" name="debug-native">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
......@@ -38,6 +38,17 @@
</tool>
</toolChain>
</folderInfo>
<fileInfo id="cdt.managedbuild.toolchain.gnu.base.2116872643.660980254" name="mqttclient_module.c" rcbsApplicability="disable" resourcePath="test/python/mqttclient_module.c" toolsToInvoke="cdt.managedbuild.tool.gnu.c.compiler.base.919295913.892752676">
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.919295913.892752676" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base.919295913">
<option id="gnu.c.compiler.option.include.paths.1043418401" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="/usr/include/python2.6"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1471037566" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
</fileInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
......@@ -46,12 +57,12 @@
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.2116872643.128299804" moduleId="org.eclipse.cdt.core.settings" name="debug-x86-linux">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
......@@ -79,6 +90,14 @@
</tool>
</toolChain>
</folderInfo>
<fileInfo id="cdt.managedbuild.toolchain.gnu.base.2116872643.128299804.44392871" name="mqttclient_module.c" rcbsApplicability="disable" resourcePath="test/python/mqttclient_module.c" toolsToInvoke="cdt.managedbuild.tool.gnu.c.compiler.base.1542253543.1236301446">
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1542253543.1236301446" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base.1542253543">
<option id="gnu.c.compiler.option.include.paths.387085861" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="/usr/include/python2.6/"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.912266645" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
</fileInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
......@@ -87,12 +106,12 @@
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.2116872643.1588218084" moduleId="org.eclipse.cdt.core.settings" name="debug-arm-linux-gnueabihf">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
......@@ -120,6 +139,14 @@
</tool>
</toolChain>
</folderInfo>
<fileInfo id="cdt.managedbuild.toolchain.gnu.base.2116872643.1588218084.1410045178" name="mqttclient_module.c" rcbsApplicability="disable" resourcePath="test/python/mqttclient_module.c" toolsToInvoke="cdt.managedbuild.tool.gnu.c.compiler.base.1805700752.404015131">
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1805700752.404015131" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base.1805700752">
<option id="gnu.c.compiler.option.include.paths.253579949" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="/usr/include/python2.6/"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.987997893" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
</fileInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
......@@ -128,9 +155,6 @@
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="org.eclipse.paho.mqtt.c.null.1335713239" name="org.eclipse.paho.mqtt.c"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
......@@ -144,4 +168,25 @@
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.2116872643.128299804;cdt.managedbuild.toolchain.gnu.base.2116872643.128299804.;cdt.managedbuild.tool.gnu.cpp.compiler.base.1478312340;cdt.managedbuild.tool.gnu.cpp.compiler.input.1918693642">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.2116872643.128299804;cdt.managedbuild.toolchain.gnu.base.2116872643.128299804.;cdt.managedbuild.tool.gnu.c.compiler.base.1542253543;cdt.managedbuild.tool.gnu.c.compiler.input.273102950">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.2116872643.1588218084;cdt.managedbuild.toolchain.gnu.base.2116872643.1588218084.;cdt.managedbuild.tool.gnu.c.compiler.base.1805700752;cdt.managedbuild.tool.gnu.c.compiler.input.892553453">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.2116872643;cdt.managedbuild.toolchain.gnu.base.2116872643.2105697674;cdt.managedbuild.tool.gnu.cpp.compiler.base.2093522624;cdt.managedbuild.tool.gnu.cpp.compiler.input.58852055">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.2116872643.1588218084;cdt.managedbuild.toolchain.gnu.base.2116872643.1588218084.;cdt.managedbuild.tool.gnu.cpp.compiler.base.1005171182;cdt.managedbuild.tool.gnu.cpp.compiler.input.1367844459">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.2116872643;cdt.managedbuild.toolchain.gnu.base.2116872643.2105697674;cdt.managedbuild.tool.gnu.c.compiler.base.919295913;cdt.managedbuild.tool.gnu.c.compiler.input.873628110">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
</cproject>
......@@ -5,6 +5,11 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
......@@ -23,5 +28,6 @@
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
</pydev_project>
......@@ -84,10 +84,10 @@ HEADERS = $(srcdir)/*.h
HEADERS_C = $(filter-out $(srcdir)/MQTTAsync.h, $(HEADERS))
HEADERS_A = $(HEADERS)
SAMPLE_FILES_C = stdinpub stdoutsub pubsync pubasync subasync
SAMPLE_FILES_C = paho_cs_pub paho_cs_sub MQTTClient_publish MQTTClient_publish_async MQTTClient_subscribe
SYNC_SAMPLES = ${addprefix ${blddir}/samples/,${SAMPLE_FILES_C}}
SAMPLE_FILES_A = stdinpuba stdoutsuba MQTTAsync_subscribe MQTTAsync_publish
SAMPLE_FILES_A = paho_c_pub paho_c_sub MQTTAsync_subscribe MQTTAsync_publish
ASYNC_SAMPLES = ${addprefix ${blddir}/samples/,${SAMPLE_FILES_A}}
TEST_FILES_C = test1 test2 sync_client_test test_mqtt4sync
......
Issue 2 - offline buffering and automatic reconnect
if we don't have automatic reconnect and we don't successfully connect, then ...
offline buffering implies automatic reconnect?
is it worth having automatic reconnect without offline buffering?
should automatic reconnect even be offered separately?
\ No newline at end of file
This diff is collapsed.
/*******************************************************************************
* Copyright (c) 2009, 2015 IBM Corp.
* Copyright (c) 2009, 2016 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
......@@ -16,6 +16,7 @@
* Ian Craggs - multiple server connection support
* Ian Craggs - MQTT 3.1.1 support
* Ian Craggs - fix for bug 444103 - success/failure callbacks not invoked
* Ian Craggs - automatic reconnect and offline buffering (send while disconnected)
*******************************************************************************/
/********************************************************************/
......@@ -24,7 +25,7 @@
* @cond MQTTAsync_main
* @mainpage Asynchronous MQTT client library for C
*
* &copy; Copyright IBM Corp. 2009, 2015
* &copy; Copyright IBM Corp. 2009, 2016
*
* @brief An Asynchronous MQTT client library for C.
*
......@@ -317,6 +318,23 @@ typedef void MQTTAsync_deliveryComplete(void* context, MQTTAsync_token token);
*/
typedef void MQTTAsync_connectionLost(void* context, char* cause);
/**
* This is a callback function, which will be called when the client
* library successfully connects. This is superfluous when the connection
* is made in response to a MQTTAsync_connect call, because the onSuccess
* callback can be used. It is intended for use when automatic reconnect
* is enabled, so that when a reconnection attempt succeeds in the background,
* the application is notified and can take any required actions.
* @param context A pointer to the <i>context</i> value originally passed to
* MQTTAsync_setCallbacks(), which contains any application-specific context.
* @param cause The reason for the disconnection.
* Currently, <i>cause</i> is always set to NULL.
*/
typedef void MQTTAsync_connected(void* context, char* cause);
/** The data returned on completion of an unsuccessful API call in the response callback onFailure. */
typedef struct
{
......@@ -440,6 +458,14 @@ typedef struct
*/
DLLExport int MQTTAsync_setCallbacks(MQTTAsync handle, void* context, MQTTAsync_connectionLost* cl,
MQTTAsync_messageArrived* ma, MQTTAsync_deliveryComplete* dc);
DLLExport int MQTTAsync_setConnected(MQTTAsync handle, void* context, MQTTAsync_connected* co);
/**
......@@ -488,6 +514,24 @@ DLLExport int MQTTAsync_setCallbacks(MQTTAsync handle, void* context, MQTTAsync_
DLLExport int MQTTAsync_create(MQTTAsync* handle, const char* serverURI, const char* clientId,
int persistence_type, void* persistence_context);
typedef struct
{
/** The eyecatcher for this structure. must be MQCO. */
const char struct_id[4];
/** The version number of this structure. Must be 0 */
int struct_version;
/** Whether to allow messages to be sent when the client library is not connected. */
int sendWhileDisconnected;
/** the maximum number of messages allowed to be buffered while not connected. */
int maxBufferedMessages;
} MQTTAsync_createOptions;
#define MQTTAsync_createOptions_initializer { {'M', 'Q', 'C', 'O'}, 0, 0, 100 }
DLLExport int MQTTAsync_createWithOptions(MQTTAsync* handle, const char* serverURI, const char* clientId,
int persistence_type, void* persistence_context, MQTTAsync_createOptions* options);
/**
* MQTTAsync_willOptions defines the MQTT "Last Will and Testament" (LWT) settings for
* the client. In the event that a client unexpectedly loses its connection to
......@@ -583,10 +627,11 @@ typedef struct
{
/** The eyecatcher for this structure. must be MQTC. */
const char struct_id[4];
/** The version number of this structure. Must be 0, 1 or 2.
/** The version number of this structure. Must be 0, 1, 2, 3 or 4.
* 0 signifies no SSL options and no serverURIs
* 1 signifies no serverURIs
* 2 signifies no MQTTVersion
* 3 signifies no automatic reconnect options
*/
int struct_version;
/** The "keep alive" interval, measured in seconds, defines the maximum time
......@@ -695,10 +740,23 @@ typedef struct
* MQTTVERSION_3_1_1 (4) = only try version 3.1.1
*/
int MQTTVersion;
/**
* Reconnect automatically in the case of a connection being lost?
*/
int automaticReconnect;
/**
* Minimum retry interval in seconds. Doubled on each failed retry.
*/
int minRetryInterval;
/**
* Maximum retry interval in seconds. The doubling stops here on failed retries.
*/
int maxRetryInterval;
} MQTTAsync_connectOptions;
#define MQTTAsync_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 3, 60, 1, 10, NULL, NULL, NULL, 30, 0, NULL, NULL, NULL, NULL, 0, NULL, 0}
#define MQTTAsync_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 4, 60, 1, 10, NULL, NULL, NULL, 30, 0, NULL, NULL, NULL, NULL, 0, NULL, 0, \
0, 1, 60}
/**
* This function attempts to connect a previously-created client (see
......
#*******************************************************************************
# Copyright (c) 2015 logi.cals GmbH
# Copyright (c) 2015, 2016 logi.cals GmbH
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
......@@ -12,6 +12,7 @@
#
# Contributors:
# Rainer Poisel - initial version
# Ian Craggs - update sample names
#*******************************************************************************/
# Note: on OS X you should install XCode and the associated command-line tools
......@@ -24,37 +25,37 @@ INCLUDE_DIRECTORIES(
)
# sample files c
ADD_EXECUTABLE(stdinpub stdinpub.c)
ADD_EXECUTABLE(stdoutsub stdoutsub.c)
ADD_EXECUTABLE(pubsync pubsync.c)
ADD_EXECUTABLE(pubasync pubasync.c)
ADD_EXECUTABLE(subasync subasync.c)
TARGET_LINK_LIBRARIES(stdinpub paho-mqtt3c)
TARGET_LINK_LIBRARIES(stdoutsub paho-mqtt3c)
TARGET_LINK_LIBRARIES(pubsync paho-mqtt3c)
TARGET_LINK_LIBRARIES(pubasync paho-mqtt3c)
TARGET_LINK_LIBRARIES(subasync paho-mqtt3c)
ADD_EXECUTABLE(stdinpuba stdinpuba.c)
ADD_EXECUTABLE(stdoutsuba stdoutsuba.c)
ADD_EXECUTABLE(paho_c_pub paho_c_pub.c)
ADD_EXECUTABLE(paho_c_sub paho_c_sub.c)
ADD_EXECUTABLE(paho_cs_pub paho_cs_pub.c)
ADD_EXECUTABLE(paho_cs_sub paho_cs_sub.c)
TARGET_LINK_LIBRARIES(paho_c_pub paho-mqtt3a)
TARGET_LINK_LIBRARIES(paho_c_sub paho-mqtt3a)
TARGET_LINK_LIBRARIES(paho_cs_pub paho-mqtt3c)
TARGET_LINK_LIBRARIES(paho_cs_sub paho-mqtt3c)
ADD_EXECUTABLE(MQTTAsync_subscribe MQTTAsync_subscribe.c)
ADD_EXECUTABLE(MQTTAsync_publish MQTTAsync_publish.c)
ADD_EXECUTABLE(MQTTClient_subscribe MQTTClient_subscribe.c)
ADD_EXECUTABLE(MQTTClient_publish MQTTClient_publish.c)
ADD_EXECUTABLE(MQTTClient_publish_async MQTTClient_publish_async.c)
TARGET_LINK_LIBRARIES(stdinpuba paho-mqtt3a)
TARGET_LINK_LIBRARIES(stdoutsuba paho-mqtt3a)
TARGET_LINK_LIBRARIES(MQTTAsync_subscribe paho-mqtt3a)
TARGET_LINK_LIBRARIES(MQTTAsync_publish paho-mqtt3a)
INSTALL(TARGETS stdinpub
stdoutsub
pubsync
pubasync
subasync
stdinpuba
stdoutsuba
TARGET_LINK_LIBRARIES(MQTTClient_subscribe paho-mqtt3c)
TARGET_LINK_LIBRARIES(MQTTClient_publish paho-mqtt3c)
TARGET_LINK_LIBRARIES(MQTTClient_publish_async paho-mqtt3c)
INSTALL(TARGETS paho_c_sub
paho_c_pub
paho_cs_sub
paho_cs_pub
MQTTAsync_subscribe
MQTTAsync_publish
MQTTClient_subscribe
MQTTClient_publish
MQTTClient_publish_async
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib)
/*******************************************************************************
* Copyright (c) 2012, 2013 IBM Corp.
* Copyright (c) 2012, 2016 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
......@@ -118,11 +118,15 @@ void onDisconnect(void* context, MQTTAsync_successData* response)
static int connected = 0;
void myconnect(MQTTAsync* client);
void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
printf("Connect failed, rc %d\n", response ? -1 : response->code);
printf("Connect failed, rc %d\n", response ? response->code : -1);
connected = -1;
MQTTAsync client = (MQTTAsync)context;
myconnect(client);
}
......@@ -135,7 +139,6 @@ void onConnect(void* context, MQTTAsync_successData* response)
connected = 1;
}
void myconnect(MQTTAsync* client)
{
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
......@@ -152,18 +155,13 @@ void myconnect(MQTTAsync* client)
conn_opts.context = client;
ssl_opts.enableServerCertAuth = 0;
conn_opts.ssl = &ssl_opts;
conn_opts.automaticReconnect = 1;
connected = 0;
if ((rc = MQTTAsync_connect(*client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
while (connected == 0)
#if defined(WIN32)
Sleep(100);
#else
usleep(10000L);
#endif
}
......@@ -209,120 +207,12 @@ void connectionLost(void* context, char* cause)
}
}
#if !defined(_WINDOWS)
#include <sys/time.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#define MAXHOSTNAMELEN 256
#define EAGAIN WSAEWOULDBLOCK
#define EINTR WSAEINTR
#define EINPROGRESS WSAEINPROGRESS
#define EWOULDBLOCK WSAEWOULDBLOCK
#define ENOTCONN WSAENOTCONN
#define ECONNRESET WSAECONNRESET
#define setenv(a, b, c) _putenv_s(a, b)
#endif
#if !defined(SOCKET_ERROR)
#define SOCKET_ERROR -1
#endif
typedef struct
{
int socket;
time_t lastContact;
#if defined(OPENSSL)
SSL* ssl;
SSL_CTX* ctx;
#endif
} networkHandles;
typedef struct
{
char* clientID; /**< the string id of the client */
char* username; /**< MQTT v3.1 user name */
char* password; /**< MQTT v3.1 password */
unsigned int cleansession : 1; /**< MQTT clean session flag */
unsigned int connected : 1; /**< whether it is currently connected */
unsigned int good : 1; /**< if we have an error on the socket we turn this off */
unsigned int ping_outstanding : 1;
int connect_state : 4;
networkHandles net;
/* ... */
} Clients;
typedef struct MQTTAsync_struct
{
char* serverURI;
int ssl;
Clients* c;
/* "Global", to the client, callback definitions */
MQTTAsync_connectionLost* cl;
MQTTAsync_messageArrived* ma;
MQTTAsync_deliveryComplete* dc;
void* context; /* the context to be associated with the main callbacks*/
#if 0
MQTTAsync_command connect; /* Connect operation properties */
MQTTAsync_command disconnect; /* Disconnect operation properties */
MQTTAsync_command* pending_write; /* Is there a socket write pending? */
List* responses;
unsigned int command_seqno;
MQTTPacket* pack;
#endif
} MQTTAsyncs;
int test6_socket_error(char* aString, int sock)
{
#if defined(WIN32)
int errno;
#endif
#if defined(WIN32)
errno = WSAGetLastError();
#endif
if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK)
{
if (strcmp(aString, "shutdown") != 0 || (errno != ENOTCONN && errno != ECONNRESET))
printf("Socket error %d in %s for socket %d", errno, aString, sock);
}
return errno;
}
int test6_socket_close(int socket)
{
int rc;
#if defined(WIN32)
if (shutdown(socket, SD_BOTH) == SOCKET_ERROR)
test6_socket_error("shutdown", socket);
if ((rc = closesocket(socket)) == SOCKET_ERROR)
test6_socket_error("close", socket);
#else
if (shutdown(socket, SHUT_RDWR) == SOCKET_ERROR)
test6_socket_error("shutdown", socket);
if ((rc = close(socket)) == SOCKET_ERROR)
test6_socket_error("close", socket);
#endif
return rc;
}
int main(int argc, char** argv)
{
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
MQTTAsync_responseOptions pub_opts = MQTTAsync_responseOptions_initializer;
MQTTAsync_createOptions create_opts = MQTTAsync_createOptions_initializer;
MQTTAsync client;
char* topic = NULL;
char* buffer = NULL;
......@@ -341,7 +231,8 @@ int main(int argc, char** argv)
topic = argv[1];
printf("Using topic %s\n", topic);
rc = MQTTAsync_create(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE, NULL);
create_opts.sendWhileDisconnected = 1;
rc = MQTTAsync_createWithOptions(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE, NULL, &create_opts);
signal(SIGINT, cfinish);
signal(SIGTERM, cfinish);
......@@ -375,19 +266,9 @@ int main(int argc, char** argv)
pub_opts.onFailure = onPublishFailure;
do
{
published = 0;
rc = MQTTAsync_send(client, topic, data_len, buffer, opts.qos, opts.retained, &pub_opts);
while (published == 0)
#if defined(WIN32)
Sleep(100);
#else
usleep(1000L);
#endif
if (published == -1)
myconnect(&client);
test6_socket_close(((MQTTAsyncs*)client)->c->net.socket);
}
while (published != 1);
while (rc != MQTTASYNC_SUCCESS);
}
printf("Stopping\n");
......
/*******************************************************************************
* Copyright (c) 2012, 2013 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
* Guilherme Maciel Ferreira - add keep alive option
*******************************************************************************/
/*
stdin publisher
compulsory parameters:
--topic topic to publish on
defaulted parameters:
--host localhost
--port 1883
--qos 0
--delimiters \n
--clientid stdin-publisher
--maxdatalen 100
--keepalive 10
--userid none
--password none
*/
#include "MQTTClient.h"
#include "MQTTClientPersistence.h"
#include <stdio.h>
#include <signal.h>
#include <memory.h>
#if defined(WIN32)
#include <windows.h>
#define sleep Sleep
#else
#include <sys/time.h>
#include <stdlib.h>
#endif
volatile int toStop = 0;
struct
{
char* clientid;
char* delimiter;
int maxdatalen;
int qos;
int retained;
char* username;
char* password;
char* host;
char* port;
int verbose;
int keepalive;
} opts =
{
"stdin-publisher", "\n", 100, 0, 0, NULL, NULL, "localhost", "1883", 0, 10
};
void usage(void)
{
printf("MQTT stdin publisher\n");
printf("Usage: stdinpub topicname <options>, where options are:\n");
printf(" --host <hostname> (default is %s)\n", opts.host);
printf(" --port <port> (default is %s)\n", opts.port);
printf(" --qos <qos> (default is %d)\n", opts.qos);
printf(" --retained (default is %s)\n", opts.retained ? "on" : "off");
printf(" --delimiter <delim> (default is \\n)\n");
printf(" --clientid <clientid> (default is %s)\n", opts.clientid);
printf(" --maxdatalen <bytes> (default is %d)\n", opts.maxdatalen);
printf(" --username none\n");
printf(" --password none\n");
printf(" --keepalive <seconds> (default is %d seconds)\n", opts.keepalive);
exit(EXIT_FAILURE);
}
void myconnect(MQTTClient* client, MQTTClient_connectOptions* opts)
{
printf("Connecting\n");
if (MQTTClient_connect(*client, opts) != 0)
{
printf("Failed to connect\n");
exit(EXIT_FAILURE);
}
}
void cfinish(int sig)
{
signal(SIGINT, NULL);
toStop = 1;
}
void getopts(int argc, char** argv);
int messageArrived(void* context, char* topicName, int topicLen, MQTTClient_message* m)
{
/* not expecting any messages */
return 1;
}
int main(int argc, char** argv)
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
char* topic = NULL;
char* buffer = NULL;
int rc = 0;
char url[100];
if (argc < 2)
usage();
getopts(argc, argv);
sprintf(url, "%s:%s", opts.host, opts.port);
if (opts.verbose)
printf("URL is %s\n", url);
topic = argv[1];
printf("Using topic %s\n", topic);
rc = MQTTClient_create(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE, NULL);
signal(SIGINT, cfinish);
signal(SIGTERM, cfinish);
rc = MQTTClient_setCallbacks(client, NULL, NULL, messageArrived, NULL);
conn_opts.keepAliveInterval = opts.keepalive;
conn_opts.reliable = 0;
conn_opts.cleansession = 1;
conn_opts.username = opts.username;
conn_opts.password = opts.password;
myconnect(&client, &conn_opts);
buffer = malloc(opts.maxdatalen);
while (!toStop)
{
int data_len = 0;
int delim_len = 0;
delim_len = strlen(opts.delimiter);
do
{
buffer[data_len++] = getchar();
if (data_len > delim_len)
{
//printf("comparing %s %s\n", opts.delimiter, &buffer[data_len - delim_len]);
if (strncmp(opts.delimiter, &buffer[data_len - delim_len], delim_len) == 0)
break;
}
} while (data_len < opts.maxdatalen);
if (opts.verbose)
printf("Publishing data of length %d\n", data_len);
rc = MQTTClient_publish(client, topic, data_len, buffer, opts.qos, opts.retained, NULL);
if (rc != 0)
{
myconnect(&client, &conn_opts);
rc = MQTTClient_publish(client, topic, data_len, buffer, opts.qos, opts.retained, NULL);
}
if (opts.qos > 0)
MQTTClient_yield();
}
printf("Stopping\n");
free(buffer);
MQTTClient_disconnect(client, 0);
MQTTClient_destroy(&client);
return EXIT_SUCCESS;
}
void getopts(int argc, char** argv)
{
int count = 2;
while (count < argc)
{
if (strcmp(argv[count], "--retained") == 0)
opts.retained = 1;
if (strcmp(argv[count], "--verbose") == 0)
opts.verbose = 1;
else if (strcmp(argv[count], "--qos") == 0)
{
if (++count < argc)
{
if (strcmp(argv[count], "0") == 0)
opts.qos = 0;
else if (strcmp(argv[count], "1") == 0)
opts.qos = 1;
else if (strcmp(argv[count], "2") == 0)
opts.qos = 2;
else
usage();
}
else
usage();
}
else if (strcmp(argv[count], "--host") == 0)
{
if (++count < argc)
opts.host = argv[count];
else
usage();
}
else if (strcmp(argv[count], "--port") == 0)
{
if (++count < argc)
opts.port = argv[count];
else
usage();
}
else if (strcmp(argv[count], "--clientid") == 0)
{
if (++count < argc)
opts.clientid = argv[count];
else
usage();
}
else if (strcmp(argv[count], "--username") == 0)
{
if (++count < argc)
opts.username = argv[count];
else
usage();
}
else if (strcmp(argv[count], "--password") == 0)
{
if (++count < argc)
opts.password = argv[count];
else
usage();
}
else if (strcmp(argv[count], "--maxdatalen") == 0)
{
if (++count < argc)
opts.maxdatalen = atoi(argv[count]);
else
usage();
}
else if (strcmp(argv[count], "--delimiter") == 0)
{
if (++count < argc)
opts.delimiter = argv[count];
else
usage();
}
else if (strcmp(argv[count], "--keepalive") == 0)
{
if (++count < argc)
opts.keepalive = atoi(argv[count]);
else
usage();
}
count++;
}
}
This diff is collapsed.
This diff is collapsed.
from distutils.core import setup, Extension
paho_mqtt3c = Extension('paho_mqtt3c',
define_macros = [('NO_HEAP_TRACKING', '1')],
sources = ['mqttclient_module.c', '../../src/LinkedList.c'],
libraries = ['paho-mqtt3c'],
library_dirs = ['../../build/output'],
include_dirs = ['../../src'])
paho_mqtt3a = Extension('paho_mqtt3a',
define_macros = [('NO_HEAP_TRACKING', '1')],
sources = ['mqttasync_module.c', '../../src/LinkedList.c'],
libraries = ['paho-mqtt3a'],
library_dirs = ['../../build/output'],
include_dirs = ['../../src'])
setup (name = 'EclipsePahoMQTTClient',
version = '1.0',
description = 'Binding to the Eclipse Paho C clients',
ext_modules = [paho_mqtt3c, paho_mqtt3a])
import paho_mqtt3c as mqttv3, time, random
print dir(mqttv3)
host = "localhost"
clientid = "myclientid"
noclients = 4
def deliveryComplete(context, msgid):
print "deliveryComplete", msgid
def connectionLost(context, cause):
print "connectionLost"
print "rc from reconnect is", mqttv3.connect(self.client)
def messageArrived(context, topicName, message):
print "clientid", context
print "topicName", topicName
print "message", message
return 1
print messageArrived
myclientid = None
clients = []
for i in range(noclients):
myclientid = clientid+str(i)
rc, client = mqttv3.create("tcp://"+host+":1883", myclientid)
print "client is", hex(client)
print "rc from create is", rc
print "rc from setcallbacks is", mqttv3.setcallbacks(client, client, connectionLost, messageArrived, deliveryComplete)
print "client is", hex(client)
print "rc from connect is", mqttv3.connect(client, {})
clients.append(client)
for client in clients:
print "rc from subscribe is", mqttv3.subscribe(client, "$SYS/#")
for client in clients:
print "rc from publish is", mqttv3.publish(client, "a topic", "a message")
print "rc from publish is", mqttv3.publish(client, "a topic", "a message", 1)
print "rc from publish is", mqttv3.publish(client, "a topic", "a message", 2)
print "about to sleep"
time.sleep(10)
print "finished sleeping"
for client in clients:
print "rc from isConnected is", mqttv3.isConnected(client)
print "rc from disconnect is", mqttv3.disconnect(client)
mqttv3.destroy(client)
import paho_mqtt3a as mqttv3, time, random
import contextlib
print dir(mqttv3)
hostname = "localhost"
clientid = "myclientid"
topic = "test2_topic"
def deliveryComplete(context, msgid):
print "deliveryComplete", msgid
def connectionLost(context, cause):
print "connectionLost"
print "rc from reconnect is", mqttv3.connect(self.client)
def messageArrived(context, topicName, message):
print "messageArrived", message
#print "clientid", context
#print "topicName", topicName
return 1
def onSuccess(context, successData):
print "onSuccess for", context["clientid"], context["state"], successData
responseOptions = {"context": context, "onSuccess": onSuccess, "onFailure" : onFailure}
#responseOptions = {"context": context}
if context["state"] == "connecting":
context["state"] = "subscribing"
print "rc from subscribe is", mqttv3.subscribe(client, topic, 2, responseOptions)
elif context["state"] == "subscribing":
context["state"] = "publishing qos 0"
print "rc from publish is", mqttv3.send(client, topic, "a QoS 0 message", 0, 0, responseOptions)
elif context["state"] == "publishing qos 0":
context["state"] = "publishing qos 1"
print "rc from publish is", mqttv3.send(client, topic, "a QoS 1 message", 1, 0, responseOptions)
elif context["state"] == "publishing qos 1":
context["state"] = "publishing qos 2"
print "rc from publish is", mqttv3.send(client, topic, "a QoS 2 message", 2, 0, responseOptions)
elif context["state"] == "publishing qos 2":
context["state"] = "finished"
print "leaving onSuccess"
def onFailure(context, failureData):
print "onFailure for", context["clientid"]
context["state"] = "finished"
noclients = 1
myclientid = None
clients = []
for i in range(noclients):
myclientid = clientid+str(i)
rc, client = mqttv3.create("tcp://"+hostname+":1883", myclientid)
#print "client is", hex(client)
print "rc from create is", rc
print "rc from setcallbacks is", mqttv3.setcallbacks(client, client, connectionLost, messageArrived, deliveryComplete)
context = {"client" : client, "clientid" : clientid, "state" : "connecting"}
print "rc from connect is", mqttv3.connect(client, {"context": context, "onSuccess": onSuccess, "onFailure": onFailure})
clients.append(context)
while [x for x in clients if x["state"] != "finished"]:
print [x for x in clients if x["state"] != "finished"]
time.sleep(1)
for client in clients:
if mqttv3.isConnected(client["client"]):
print "rc from disconnect is", mqttv3.disconnect(client["client"], 1000)
time.sleep(1)
mqttv3.destroy(client["client"])
print "after destroy"
import paho_mqtt3a as mqttv3, time, random
import contextlib
print dir(mqttv3)
hostname = "localhost"
clientid = "myclientid"
topic = "test2_topic"
def deliveryComplete(context, msgid):
print "deliveryComplete", msgid
def connectionLost(context, cause):
print "connectionLost", cause
client = context
responseOptions = {"context": context, "onSuccess": onSuccess, "onFailure" : onFailure}
print "rc from publish while disconnected is", mqttv3.send(client, topic, "message while disconnected", 2, 0, responseOptions)
def messageArrived(context, topicName, message):
print "messageArrived", message
#print "clientid", context
#print "topicName", topicName
return 1
def connected(context, cause):
print "connected", cause
def onSuccess(context, successData):
print "onSuccess for", context["clientid"], context["state"], successData
responseOptions = {"context": context, "onSuccess": onSuccess, "onFailure" : onFailure}
if context["state"] == "connecting":
context["state"] = "subscribing"
print "rc from subscribe is", mqttv3.subscribe(client, topic, 2, responseOptions)
elif context["state"] == "subscribing":
context["state"] = "publishing qos 0"
print "rc from publish is", mqttv3.send(client, topic, "a QoS 0 message", 0, 0, responseOptions)
elif context["state"] == "publishing qos 0":
context["state"] = "publishing qos 1"
print "rc from publish is", mqttv3.send(client, topic, "a QoS 1 message", 1, 0, responseOptions)
elif context["state"] == "publishing qos 1":
context["state"] = "publishing qos 2"
print "rc from publish is", mqttv3.send(client, topic, "a QoS 2 message", 2, 0, responseOptions)
elif context["state"] == "publishing qos 2":
context["state"] = "finished"
print "leaving onSuccess"
def onFailure(context, failureData):
print "onFailure for", context["clientid"]
context["state"] = "finished"
noclients = 1
myclientid = None
clients = []
for i in range(noclients):
myclientid = clientid+str(i)
rc, client = mqttv3.create("tcp://"+hostname+":1883", myclientid, mqttv3.PERSISTENCE_DEFAULT, {"sendWhileDisconnected" : 1})
#print "client is", hex(client)
print "rc from create is", rc
print "rc from setcallbacks is", mqttv3.setcallbacks(client, client, connectionLost, messageArrived, deliveryComplete)
print "rc from setconnected is", mqttv3.setconnected(client, client, connected)
context = {"client" : client, "clientid" : clientid, "state" : "connecting"}
print "rc from connect is", mqttv3.connect(client, {"cleansession" : 0, "automaticReconnect": 1, "context": context, "onSuccess": onSuccess, "onFailure": onFailure})
clients.append(context)
while [x for x in clients if x["state"] != "finished"]:
print [x for x in clients if x["state"] != "finished"]
time.sleep(1)
print "waiting for 60 seconds"
time.sleep(60)
for client in clients:
if mqttv3.isConnected(client["client"]):
print "rc from disconnect is", mqttv3.disconnect(client["client"], 1000)
time.sleep(1)
mqttv3.destroy(client["client"])
print "after destroy"
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment