This package includes the SharkSSL lite library and header files.

Dependents:   WebSocket-Client-Example SharkMQ-LED-Demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SharkMQTT.h Source File

SharkMQTT.h

00001 /*
00002  *     ____             _________                __                _
00003  *    / __ \___  ____ _/ /_  __(_)___ ___  ___  / /   ____  ____ _(_)____
00004  *   / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ /   / __ \/ __ `/ / ___/
00005  *  / _, _/  __/ /_/ / / / / / / / / / / /  __/ /___/ /_/ / /_/ / / /__
00006  * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/
00007  *                                                       /____/
00008  ****************************************************************************
00009  *            HEADER
00010  *
00011  *   This file is part of SharkMQTT:
00012  *             https://realtimelogic.com/products/sharkmqtt/
00013  *
00014  *   $Id: SharkMQTT.h 3663 2015-03-05 16:52:37Z wini $
00015  *
00016  *   COPYRIGHT:  Real Time Logic, 2015
00017  *
00018  *   This software is copyrighted by and is the sole property of Real
00019  *   Time Logic LLC.  All rights, title, ownership, or other interests in
00020  *   the software remain the property of Real Time Logic LLC.  This
00021  *   software may only be used in accordance with the terms and
00022  *   conditions stipulated in the corresponding license agreement under
00023  *   which the software has been supplied.  Any unauthorized use,
00024  *   duplication, transmission, distribution, or disclosure of this
00025  *   software is expressly forbidden.
00026  *
00027  *   This Copyright notice may not be removed or modified without prior
00028  *   written consent of Real Time Logic LLC.
00029  *
00030  *   Real Time Logic LLC. reserves the right to modify this software
00031  *   without notice.
00032  *
00033  *               http://www.realtimelogic.com
00034  */
00035 
00036 #ifndef _SharkMQTT_h
00037 #define _SharkMQTT_h
00038 
00039 #include <selib.h>
00040 #include <DoubleList.h>
00041 
00042 
00043 
00044 typedef enum
00045 {
00046    MqttState_Invalid,
00047    MqttState_Pub,
00048    MqttState_PubRel,
00049    MqttState_PubRec,
00050    MqttState_SubOrUnsub
00051 } MqttState;
00052 
00053 
00054 typedef struct
00055 {
00056    DoubleLink super;
00057    U32 timeStamp;
00058    U16 packetId; /* [MQTT-2.3.1] Packet Identifier */
00059    U8 state; /* type MqttState */
00060 } MqttInFlightMsg;
00061 
00062 
00063 
00064 /** @addtogroup MQTTLib
00065 @{
00066 */
00067 
00068 /** \defgroup SharkMQTTErrorCodes Error codes returned by function SharkMQTT_getMessage
00069 \ingroup SharkMQTT
00070 \anchor SharkMQTTErrorCodes Error codes returned by function #SharkMQTT_getMessage
00071 @{
00072 */
00073 
00074 /** Error codes received from the TCP/IP stack are sent "as is". These
00075     error codes have a value greater than #SMQTTE_ERRORBASE.
00076  */
00077 #define SMQTTE_SOCKET        -1
00078 
00079 /** This code is not used. The code is the base for error codes returned by SharkMQ.
00080  */
00081 #define SMQTTE_ERRORBASE        -10000
00082 
00083 /** Similar to #SMQTT_TIMEOUT, but returned when a timeout was not expected.
00084  */
00085 #define SMQTTE_TIMEOUT          -10001
00086 
00087 /** The client sent a PING to the broker but did not receive a PONG response.
00088  */
00089 #define SMQTTE_PONGTIMEOUT      -10002
00090 
00091 /** Something's wrong.
00092  */
00093 #define SMQTTE_PROTOCOL_ERROR   -10003
00094 
00095 /** The SharkSSL output buffer is not sufficiently large for the operation
00096     you are attempting. Increase the buffer size.
00097  */
00098 #define SMQTTE_OVERFLOW         -10005
00099 
00100 /** Calling SharkMQ_connect when a connection is already established.
00101  */
00102 #define SMQTTE_ALREADYCON       -10006
00103 
00104 /** Broker refused the connection request. See #SharkMQTT_connackCode
00105     for details.
00106  */
00107 #define SMQTTE_CONREFUSED       -10007
00108 
00109 /**  Returned by SharkMQTT_connect if a password was provided and if
00110      the broker's certificate/name is not trusted.
00111  */
00112 #define SMQTTE_SERVERNOTTRUSTED -10008
00113 
00114 
00115 /** @} */ /* end SharkMQTTErrorCodes */
00116 
00117 
00118 /** \defgroup SharkMQTTRespCodes Response codes returned by function SharkMQTT_getMessage
00119 \ingroup SharkMQTT
00120 \anchor SharkMQTTRespCodes Response codes returned by function #SharkMQTT_getMessage
00121 @{
00122 */
00123 
00124 
00125 /** #SharkMQTT_getMessage call timed out. The variable
00126     SharkMQTT::timeout controls the timout period.
00127  */
00128 #define SMQTT_TIMEOUT -20000
00129 
00130 /** Asynchronous #SharkMQTT_subscribe response message received via
00131     #SharkMQTT_getMessage.
00132  */
00133 #define SMQTT_SUBACK -20001
00134 
00135 /** Asynchronous #SharkMQTT_unsubscribe response message received via
00136     #SharkMQTT_getMessage.
00137  */
00138 #define SMQTT_UNSUBACK -20002
00139 
00140 /** @} */ /* end SharkMQTTRespCodes */
00141 
00142 
00143 /** Optional MQTT Will Message; used when calling function SharkMQTT_connect.
00144  */
00145 typedef struct
00146 {
00147    const char* topic ;  /*!< Will topic (utf-8). [MQTT-3.1.3.2] */
00148    const U8* message ;  /*!< Will message (binary). [MQTT-3.1.3.3] */
00149    U16 msgLen ;         /*!< Will message length */
00150    U8 qos ;  /*!< Will QoS: 0, 1, or 2. [MQTT-3.1.2.6] */
00151    /** Specifies if the Will Message is to be Retained when it is published.
00152        [MQTT-3.1.2.7] Will Retain.
00153     */
00154    BaBool retain;
00155 } MqttWillMsg;
00156 
00157 
00158 /** Optional credentials used when calling function SharkMQTT_connect.
00159  */
00160 typedef struct
00161 {
00162    /** Optional User Name (utf-8). Set to NULL if not used. [MQTT-3.1.3.4] */
00163    const char* username;
00164    /** Optional Password (binary). Set to NULL if not
00165        used. [MQTT-3.1.3.5]. If username is set to NULL, the password
00166        MUST be set to NULL [MQTT-3.1.2-22].
00167    */
00168    const U8* password;
00169    /** You must provide a password length if 'password' is non NULL. */
00170    U16 pwdlen;
00171 } MqttCredentials;
00172 
00173 
00174 /** SharkMQTT structure.
00175     See [SharkMQ library](@ref MQTTLib) for details.
00176  */
00177 typedef struct
00178 {
00179    SOCKET sock;
00180 
00181    DoubleList recQueue; /* type MqttInFlightMsg: for QOS > 0 */
00182    DoubleList sendQueue; /* type MqttInFlightMsg: for QOS > 0 */
00183 
00184    SharkSslCon* scon;
00185 
00186    /** Time interval in seconds for MQTT PING messages sent to the
00187     * server. The default value is 20 minutes (1200 seconds).  Note:
00188     * the variable must be set before calling SharkMQTT_connect.
00189     */
00190    S32 pingTmo;
00191 
00192    S32 pongTmoCounter;
00193    U32 pingTickTime;
00194 
00195    U8* recPackHeader;    /* from constructor: buf */
00196    U16 recPackHeaderLen; /* from constructor: bufLen */
00197    
00198    U16 packetId; /* send packet ID counter */
00199 
00200    /** MQTT packet length
00201     */
00202    U32 packetLen; 
00203 
00204    /** Read packet data using #SharkMQTT_getMessage until:
00205        packetLen-bytesRead == 0.
00206        \sa SharkMQTT_msgConsumed
00207     */
00208    U32 bytesRead;
00209 
00210    /** MQTT message length
00211     */
00212    U32 msgLen;
00213 
00214    U8* overflowPtr; /* Set if: consumed more data from stream than frame len */ 
00215    int overflowLen; /* overflowPtr len is used internally in wsRawRead */
00216    int messageHeaderIx; /* Cursor used when reading recPackHeader from socket */
00217 
00218    /** Timeout in milliseconds to wait in functions waiting for server
00219        data
00220    */
00221    U32 timeout;
00222 
00223    U16 recPacketId; /* For received packets with QOS 1 or 2 */
00224    U8  recQOS; /* For received packets with QOS 1 or 2 */
00225 } SharkMQTT;
00226 
00227 
00228 /** Create a SharkMQTT client instance.
00229     \param o Uninitialized data of size sizeof(SharkMQTT).
00230     \param buf is used for internal management and must not be less
00231     than the size of the largest control message. Function
00232     SharkMQTT_getMessage will return #SMQTTE_OVERFLOW if the buffer is
00233     not sufficiently large.
00234     \param bufLen buffer length.
00235  */
00236 void SharkMQTT_constructor(SharkMQTT* o, U8* buf, U16 bufLen);
00237 
00238 
00239 /** Terminate a SharkMQTT instance.
00240     \param o SharkMQTT instance
00241 */
00242 void SharkMQTT_destructor(SharkMQTT* o);
00243 
00244 
00245 /** Read packet data using #SharkMQTT_getMessage until
00246     SharkMQTT_msgConsumed returns TRUE.
00247     \param o SharkMQTT instance
00248 */
00249 #define SharkMQTT_msgConsumed(o) (((o)->packetLen - (o)->bytesRead) == 0)
00250 
00251 
00252 /** Connection response (CONNACK) return code.
00253     This function should be called if SharkMQTT_connect returns
00254     #SMQTTE_CONREFUSED.
00255     \returns one of the following codes:
00256     - 0x00 Connection Accepted 
00257     - 0x01 Connection Refused, unacceptable protocol version 
00258     - 0x02 Connection Refused, identifier rejected 
00259     - 0x03 Connection Refused, Server unavailable 
00260     - 0x04 Connection Refused, bad user name or password 
00261     - 0x05 Connection Refused, not authorized 
00262 
00263     See [MQTT-3.2.2.3] for details.
00264  */
00265 #define SharkMQTT_connackCode(o) (o)->recPackHeader[3]
00266 
00267 
00268 /** Returns TRUE if a session is restored. This function can only be
00269     used immediately after calling function SharkMQTT_connect.
00270 
00271     See [MQTT-3.2.2.2] for details.
00272 
00273     \param o SharkMQTT instance
00274 
00275     \sa argument cleanSession in function #SharkMQTT_connect
00276  */
00277 #define SharkMQTT_sessionPresent(o) ((o)->recPackHeader[2] & 1)
00278 
00279 /** Returns SharkSslConTrust when SharkMQTT_connect returns
00280     #SMQTTE_SERVERNOTTRUSTED
00281 
00282     \param o SharkMQTT instance
00283 */
00284 #define SharkMQTT_trustInfo(o) ((SharkSslConTrust)(o)->packetLen)
00285 
00286 
00287 /** Establish (or re-establish) an MQTT session.
00288 
00289     \param o SharkMQTT instance
00290    \param scon SharkSslCon instance created by calling #SharkSsl_createCon.
00291    
00292    \param address the MQTT broker address
00293    \param port the MQTT broker listen port number (typically 1883)
00294    \param clientId a unique ID [MQTT-3.1.3.1]
00295    \param cred optional credentials
00296    \param cleanSession
00297    \param wm optional MQTT will message
00298 
00299    \returns a return value greater than zero means that a connection is
00300     established, but the connection is not trusted unless the return
00301     value is #SharkSslConTrust_CertCn.
00302 
00303     one of the following values on error.
00304    - #SMQTTE_ALREADYCON
00305    - #SMQTTE_CONREFUSED
00306    - #SMQTTE_TIMEOUT
00307    - #SMQTTE_OVERFLOW
00308    - #SMQTTE_SERVERNOTTRUSTED
00309    - -1
00310    - -2
00311    - -3
00312 
00313    Error codes -1 to -3 are error codes from #se_connect
00314 
00315    If #SMQTTE_CONREFUSED is returned, the reason for the refused
00316    connection is found by calling #SharkMQTT_connackCode.
00317 
00318    \sa #SharkMQTT_sessionPresent
00319  */
00320 int SharkMQTT_connect(SharkMQTT* o, SharkSslCon* scon,
00321                       const char* address, U16 port,
00322                       const char* clientId, MqttCredentials* cred,
00323                       BaBool cleanSession, MqttWillMsg* wm);
00324 
00325 
00326 /** Subscribe to topic.
00327 
00328     The response to SharkMQ_subscribe is asynchronous and returned as status
00329     #SMQTT_SUBACK via #SharkMQTT_getMessage.
00330 
00331     \param o SharkMQTT instance
00332     \param topic the topic name to subscribe to.
00333     \param qos Maximum Quality Of Zero on inbound messages can be set
00334     to 0, 1, or 2. Note that SharkMQTT must dynamically allocate and
00335     keep a small control structure for each received message
00336     with QOS 2. This structure is kept until the broker QOS 2
00337     handshaking has completed.
00338     \param packetId optional packet ID. The packetId can be matched
00339     when #SharkMQ_getMessage returns #SMQTT_SUBACK.
00340     \returns zero on success and a negative value on socket error.
00341  */
00342 int SharkMQTT_subscribe(SharkMQTT* o, const char* topic, U8 qos, U16* packetId);
00343 
00344 
00345 /** Requests the broker to unsubscribe the client from a topic.
00346 
00347     The response to SharkMQ_unsubscribe is asynchronous and returned as status
00348     #SMQTT_UNSUBACK via #SharkMQTT_getMessage.
00349 
00350     \param o SharkMQTT instance
00351     \param topic the topic name to unsubscribe from.
00352     \param packetId optional packet ID. The packetId can be matched
00353     when #SharkMQ_getMessage returns #SMQTT_UNSUBACK.
00354     \returns zero on success and a negative value on socket error.
00355  */
00356 int SharkMQTT_unsubscribe(SharkMQTT* o, const char* topic, U16* packetId);
00357 
00358 
00359 /** Prepare a zero copy publish by fetching the SharkSSL send buffer
00360     pointer and offset the pointer to the MQTT message payload.
00361     \param o SharkMQTT instance
00362     \param topic must match topic passed into function #SharkMQTT_publish
00363     \param qos must also match
00364     \param maxMsgLen is an out value and indicates the maximum number
00365     of bytes that can be copied into the pointer return by this
00366     function. The length is the SharkSSL buffer's out buffer size -
00367     the MQTT header size.
00368 
00369     \returns a pointer to where you can copy the message.
00370 
00371     Example:
00372 
00373     \code
00374     int maxMsgLen;
00375     U8* buf = SharkMQTT_zeroCopyPub(mqtt, "/message/", 1, &maxMsgLen);
00376     strcpy(buf, "Hello World")
00377     SharkMQTT_publish(mqtt, "/message/", NULL, strlen(buf), FALSE, 1);
00378     \endcode
00379 
00380     Notice that the message pointer is set to NULL when calling
00381     SharkMQTT_publish.
00382 */
00383 U8* SharkMQTT_zeroCopyPub(
00384    SharkMQTT* o, const char* topic, U8 qos, int* maxMsgLen);
00385 
00386 
00387 /** Publish a QOS 0 message and set the retain flag to FALSE.
00388     \param o SharkMQTT instance
00389     \param topic the topic name
00390     \param msg message payload.
00391     \param msgLen payload length.
00392 
00393     \returns zero on success and a negative value on socket error.
00394     \sa SharkMQTT_publish
00395  */
00396 #define SharkMQTT_pub0(o, topic, msg, msgLen)        \
00397    SharkMQTT_publish(o, topic, msg, msgLen, FALSE, 0)
00398 
00399 
00400 /** Publish messages to a topic.
00401 
00402    Messages with QOS 1 or 2 cannot be larger than the SharkSSL outbuf size.
00403 
00404    \param o SharkMQTT instance
00405    \param topic the topic name
00406    \param msg message payload. This pointer is set to
00407    NULL when used together with function #SharkMQTT_zeroCopyPub.
00408    \param msgLen payload length.
00409    \param retain flag is set to TRUE or FALSE [MQTT-3.3.1.3]
00410    \param qos Quality Of Zero is 0, 1, or 2. Note that SharkMQTT must
00411    dynamically allocate and keep messages with QOS 1 and 2 until the
00412    broker QOS handshaking has completed.
00413 
00414    \returns zero on success and a negative value on socket error.
00415    \sa SharkMQTT_pub0
00416  */
00417 int SharkMQTT_publish(SharkMQTT* o, const char* topic,
00418                       const void* msg, int msgLen, U8 retain, U8 qos);
00419 
00420 
00421 /** Returns packetId when the return value from #SharkMQTT_getMessage
00422     is #SMQTT_SUBACK or #SMQTT_UNSUBACK. 
00423 
00424     \param o SharkMQTT instance
00425 */
00426 #define SharkMQTT_packetId(o) (o)->recPacketId
00427 
00428 /** Returns the subscribe response code when the return value from
00429     #SharkMQTT_getMessage is #SMQTT_SUBACK.
00430 
00431     \param o SharkMQTT instance
00432 
00433     \returns
00434     - 0x00: Success - Maximum QoS 0
00435     - 0x01: Success - Maximum QoS 1
00436     - 0x02: Success - Maximum QoS 2
00437     - 0x80: Failure
00438 */
00439 #define SharkMQTT_subAckCode(o) ((U16)(o)->recPackHeader[4])
00440 
00441 
00442 /** Returns the dup flag (TRUE/FALSE) [MQTT-3.3.1.1] for received
00443     PUBLISH messages i.e. when #SharkMQTT_getMessage returns a value
00444     greater than zero.
00445 
00446     \param o SharkMQTT instance
00447  */
00448 #define SharkMQTT_dup(o) (((o)->recPackHeader[0] & 8) ? TRUE : FALSE)
00449 
00450 /**  Returns QOS (0, 1, or 2) [MQTT-3.3.1.2] for received
00451      PUBLISH messages i.e. when #SharkMQTT_getMessage returns a value
00452      greater than zero.
00453     \param o SharkMQTT instance
00454  */
00455 #define SharkMQTT_QOS(o) (((o)->recPackHeader[0] >> 1) & 3)
00456 
00457 /**  Returns the retain flag (TRUE/FALSE) [MQTT-3.3.1.3] for received
00458      PUBLISH messages i.e. when #SharkMQTT_getMessage returns a value
00459      greater than zero.
00460     \param o SharkMQTT instance
00461  */
00462 #define SharkMQTT_retain(o) ((o)->recPackHeader[0] & 1)
00463 
00464 /** Returns the topic name for received PUBLISH messages i.e. when
00465     #SharkMQTT_getMessage returns a value greater than zero.
00466     \param o SharkMQTT instance
00467  */
00468 #define SharkMQTT_topic(o) ((const char*)((o)->recPackHeader+1))
00469 
00470 /** Wait for messages sent from the broker.
00471 
00472     \param o SharkMQTT instance
00473 
00474     \param msg a pointer to the response data (out param)
00475 
00476     \returns
00477     \li a negative value signals an
00478     [error code](\ref SharkMQTTErrorCodes) or an
00479     [asynchronous response code](\ref SharkMQTTRespCodes).
00480     \li a value greater than zero signals the reception of a full
00481     message or a message fragment. See receiving large packets for details.
00482 
00483     <b>Receiving large packets:</b><br>
00484     The MQTT protocol is frame based, but the function can return a
00485     fragment before the complete MQTT packet is received if the packet
00486     sent by the broker is larger than the SharkSSL buffer. The message
00487     payload length is returned in SharkMQTT::packetLen and the data
00488     consumed thus far is returned in SharkMQTT::bytesRead. The
00489     complete frame is consumed when SharkMQTT::packetLen ==
00490     SharkMQTT::bytesRead. Function #SharkMQTT_msgConsumed returns TRUE
00491     when the complete packet has been received.
00492 
00493     <b>Note:</b> the default timeout value is set to one minute. You
00494     can set the timeout value by setting SharkMQTT::timeout to the
00495     number of milliseconds you want to wait for incoming messages
00496     before the timeout triggers. Note: Setting a long timeout may
00497     interfere with the built in PING timer.
00498  */
00499 int SharkMQTT_getMessage(SharkMQTT* o, U8** msg);
00500 
00501 
00502 /** Send a disconnect command to the broker and gracefully close the connection.
00503     \param o SharkMQTT instance
00504  */
00505 void SharkMQTT_disconnect(SharkMQTT* o);
00506 
00507 /** @} */ /* end group MQTTLib */
00508 
00509 #endif