File:  [ELWIX - Embedded LightWeight unIX -] / mqtt / inc / Attic / aitmqtt.h
Revision 1.1.1.1.2.27: download - view: text, annotated - select for diffs - revision graph
Mon Dec 5 22:17:39 2011 UTC (12 years, 6 months ago) by misho
Branches: mqtt1_0
Diff to: branchpoint 1.1.1.1: preferred, colored
finish acks for publish & unsubscribe

#ifndef __AITMQTT_H
#define __AITMQTT_H


/* FIXED HEADER */

struct mqtthdr {
	union {
		struct {
			unsigned char	retain:1, 
					qos:2,
					dup:1,
					type:4;
		};
		unsigned char		val;
	} mqtt_msg;
	unsigned char			mqtt_len[1];	/* may be grow to 4 bytes */
} __packed;
#define MQTTHDR_MSGINIT(x)	(assert((x)), (x)->mqtt_msg.val ^= (x)->mqtt_msg.val)

#define MQTT_TYPE_UNKNOWN	0	/* reserved */
#define MQTT_TYPE_CONNECT	1	/* client request to connect to server */
#define MQTT_TYPE_CONNACK	2	/* connect acknowledgment */
#define MQTT_TYPE_PUBLISH	3	/* publish message */
#define MQTT_TYPE_PUBACK	4	/* publish acknowledgment */
#define MQTT_TYPE_PUBREC	5	/* publish received (assured delivery part 1) */
#define MQTT_TYPE_PUBREL	6	/* publish release (assured delivery part 2) */
#define MQTT_TYPE_PUBCOMP	7	/* publish complete (assured delivery part 3) */
#define MQTT_TYPE_SUBSCRIBE	8	/* client subscribe request */
#define MQTT_TYPE_SUBACK	9	/* subscribe acknowledgment */
#define MQTT_TYPE_UNSUBSCRIBE	10	/* client unsubscribe request */
#define MQTT_TYPE_UNSUBACK	11	/* unsubscribe acknowledgment */
#define MQTT_TYPE_PINGREQ	12	/* PING request */
#define MQTT_TYPE_PINGRESP	13	/* PING response */
#define MQTT_TYPE_DISCONNECT	14	/* client is disconnecting */
#define MQTT_TYPE_MAX		15	/* reserved */

#define MQTT_FLAG_DUP		1	/* This flag is set when the client or server attempts to re-deliver 
					   a PUBLISH, PUBREL, SUBSCRIBE or UNSUBSCRIBE message. 
					   This applies to messages where the value of QoS is greater than 
					   zero (0), and an acknowledgment is required. 
					   When the DUP bit is set, the variable header includes a Message ID.

					   The recipient should treat this flag as a hint as to whether 
					   the message may have been previously received. 
					   It should not be relied on to detect duplicates. */

#define MQTT_QOS_ONCE		0	/* At most once, Fire and Forget, <=1 */
#define MQTT_QOS_ACK		1	/* At least once, Acknowledged delivery, >=1 */
#define MQTT_QOS_EXACTLY	2	/* Exactly once, Assured delivery, =1 */
#define MQTT_QOS_RESERVED	3	/* reserved */

#define MQTT_FLAG_RETAIN	1	/* This flag is only used on PUBLISH messages.

					   When a client sends a PUBLISH to a server, 
					   if the Retain flag is set (1), 
					   the server should hold on to the message after it has been 
					   delivered to the current subscribers.
					   When a new subscription is established on a topic, 
					   the last retained message on that topic should be sent to 
					   the subscriber with the Retain flag set.
					   If there is no retained message, nothing is sent
					   This is useful where publishers send messages on a 
					   "report by exception" basis, where it might be some time between messages. 
					   This allows new subscribers to instantly receive data with the retained, 
					   or Last Known Good, value.

					   When a server sends a PUBLISH to a client as a result of 
					   a subscription that already existed when the original PUBLISH arrived, 
					   the Retain flag should not be set, regardless of the Retain flag 
					   of the original PUBLISH. This allows a client to distinguish messages 
					   that are being received because they were retained and those 
					   that are being received "live".

					   Retained messages should be kept over restarts of the server.
					   A server may delete a retained message if it receives a message 
					   with a zero-length payload and the Retain flag set on the same topic. */

/* VARIABLE HEADERS */

#define MQTT_RETCODE_ACCEPTED		0
#define MQTT_RETCODE_REFUSE_VER		1
#define MQTT_RETCODE_REFUSE_ID		2
#define MQTT_RETCODE_REFUSE_UNAVAIL	3
#define MQTT_RETCODE_REFUSE_USERPASS	4
#define MQTT_RETCODE_DENIED		5


typedef union {
	struct {
		unsigned short	m:8,
				l:8;
	} sb;
	unsigned short	val;
} mqtt_v_t;

typedef struct {
	unsigned char	sub_ret;
	struct __sbuf	sub_topic;
	struct __sbuf	sub_value;
} mqtt_subscr_t;

typedef struct {
	mqtt_v_t	var_sb;
	unsigned char	var_data[0];
} __packed mqtthdr_var_t;
#define MQTTHDR_VAR_SIZEOF(x)		(assert((x)), sizeof(mqtt_v_t) + ntohs((x)->var_sb.val))

typedef unsigned char mqtthdr_protover_t;

typedef struct {
	unsigned char	reserved:1,
			clean_sess:1,
			will_flg:1,
			will_qos:2,
			will_retain:1,
			password:1,
			username:1;
} __packed mqtthdr_connflgs_t;

typedef struct {
	unsigned char	reserved;
	unsigned char	retcode;
} __packed mqtthdr_connack_t;


/* MQTT Message buffer */

typedef struct {
	void		*msg_base;
	unsigned short	msg_len;
} mqtt_msg_t;

/* MQTT dispatcher callbacks */

typedef int (*mqtt_cb_t)(void *);


// -------------------------------------------------------
// mqtt_GetErrno() Get error code of last operation
inline int mqtt_GetErrno();
// mqtt_GetError() Get error text of last operation
inline const char *mqtt_GetError();
// -------------------------------------------------------


/*
 * mqtt_msgAlloc() Allocate memory for MQTT Message
 *
 * @len = >0 Allocate buffer with length
 * return: NULL error or Message, after use must call mqtt_msgFree() with all!=0
 */
inline mqtt_msg_t *mqtt_msgAlloc(unsigned short len);
/*
 * mqtt_msgFree() Free MQTT message
 *
 * @msg = Message buffer
 * @all = !=0 Destroy entire message, if MQTT Message allocated with mqtt_msgAlloc()
 * return: none
 */
inline void mqtt_msgFree(mqtt_msg_t ** __restrict msg, int all);
/*
 * mqtt_msgRealloc() Reallocate MQTT message buffer
 *
 * @msg = MQTT message
 * @len = new length
 * return: -1 error or >-1 old buffer length
 */
inline int mqtt_msgRealloc(mqtt_msg_t * __restrict msg, unsigned short len);

/*
 * mqtt_encodeLen() Encode number to MQTT length field
 *
 * @num = number for encode
 * return: -1 error or >-1 length
 */
inline unsigned int mqtt_encodeLen(unsigned int num);
/*
 * mqtt_decodeLen() Decode length from MQTT packet
 *
 * @len = length from MQTT header
 * @n = sizeof bytes, if !=NULL
 * return: -1 error, >-1 length of message
 */
inline unsigned int mqtt_decodeLen(void * __restrict len, int * __restrict n);
/*
 * mqtt_sizeLen Return sizeof len field
 *
 * @len = length
 * return: -1 error, >-1 sizeof len in bytes
 */
inline char mqtt_sizeLen(unsigned int len);
/*
 * mqtt_str2sub Create MQTT subscribe variable from string(s)
 *
 * @csStr = strings
 * @strnum = number of strings elements
 * @qoses = QoS elements applied to subscribe variable, 
 * 		count of elements must be equal with csStr elements
 * return: NULL error or != subscribe variables array, must be free after use with mqtt_freeSub()
 */
inline mqtt_subscr_t *mqtt_str2sub(const char **csStr, unsigned short strnum, unsigned char *qoses);
/*
 * mqtt_subFree() Free array from subscribe variables
 *
 * @subs = Subscribe variables
 * return: none
 */
inline void mqtt_subFree(mqtt_subscr_t ** __restrict subs);
/*
 * mqtt_subAlloc() Create array from subscribe variables
 *
 * @num = Number of elements
 * return: NULL error or subscribe array, after use must call mqtt_subFree()
 */
inline mqtt_subscr_t *mqtt_subAlloc(unsigned short num);


/*** SENDER FUNCTIONS ***/

/*
 * mqtt_msgCONNECT() Create CONNECT message
 *
 * @buf = Message buffer
 * @csConnID = ConnectID
 * @csUser = Username if !=NULL
 * @csPass = Password for Username, only if csUser is set
 * @csWillTopic = Will Topic if !=NULL Will Flags set into message
 * @csWillMessage = Will Message, may be NULL
 * @ClrSess = Clear Session subscriptions after disconnect
 * @WillQOS = Will QOS if csWillTopic is set
 * @WillRetain = Will Retain Will Message if csWillTopic is set
 * return: -1 error or >-1 message size for send
 */
int mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const char *csConnID, 
		const char *csUser, const char *csPass, 
		const char *csWillTopic, const char *csWillMessage, 
		unsigned char ClrSess, unsigned char WillQOS, unsigned char WillRetain);
/*
 * mqtt_msgCONNACK() Create CONNACK message
 *
 * @buf = Message buffer
 * @retcode = Return code
 * return: -1 error or >-1 message size for send
 */
int mqtt_msgCONNACK(mqtt_msg_t * __restrict buf, unsigned char retcode);
/*
 * mqtt_msgDISCONNECT() Create DISCONNECT message
 *
 * @buf = Message buffer
 * return: -1 error or >-1 message size for send
 */
int mqtt_msgDISCONNECT(mqtt_msg_t * __restrict buf);
/*
 * mqtt_msgPINGREQ() Create PINGREQ message
 *
 * @buf = Message buffer
 * return: -1 error or >-1 message size for send
 */
int mqtt_msgPINGREQ(mqtt_msg_t * __restrict buf);
/*
 * mqtt_msgPINGRESP() Create PINGRESP message
 *
 * @buf = Message buffer
 * return: -1 error or >-1 message size for send
 */
int mqtt_msgPINGRESP(mqtt_msg_t * __restrict buf);

/*
 * mqtt_msgPUBLISH() Create PUBLISH message
 *
 * @buf = Message buffer
 * @csTopic = Publish topic
 * @msgID = MessageID >0, if QOS != MQTT_QOS_ONCE
 * @Dup = Duplicate message
 * @QOS = QoS
 * @Retain = Retain message
 * @pData = Publish data into topic
 * @datlen = Publish data length
 * return: -1 error or >-1 message size for send
 */
int mqtt_msgPUBLISH(mqtt_msg_t * __restrict buf, const char *csTopic, unsigned short msgID, 
		unsigned char Dup, unsigned char QOS, unsigned char Retain, 
		const void *pData, unsigned short datlen);
/*
 * mqtt_msgPUBACK() Create PUBACK message
 *
 * @buf = Message buffer
 * @msgID = MessageID
 * return: -1 error or >-1 message size for send
 */
inline int mqtt_msgPUBACK(mqtt_msg_t * __restrict buf, unsigned short msgID);
/*
 * mqtt_msgPUBREC() Create PUBREC message
 *
 * @buf = Message buffer
 * @msgID = MessageID
 * return: -1 error or >-1 message size for send
 */
inline int mqtt_msgPUBREC(mqtt_msg_t * __restrict buf, unsigned short msgID);
/*
 * mqtt_msgPUBREL() Create PUBREL message
 *
 * @buf = Message buffer
 * @msgID = MessageID
 * return: -1 error or >-1 message size for send
 */
inline int mqtt_msgPUBREL(mqtt_msg_t * __restrict buf, unsigned short msgID);
/*
 * mqtt_msgPUBCOMP() Create PUBCOMP message
 *
 * @buf = Message buffer
 * @msgID = MessageID
 * return: -1 error or >-1 message size for send
 */
inline int mqtt_msgPUBCOMP(mqtt_msg_t * __restrict buf, unsigned short msgID);

/*
 * mqtt_msgSUBSCRIBE() Create SUBSCRIBE message
 *
 * @buf = Message buffer
 * @Topics = MQTT subscription topics
 * @msgID = MessageID
 * @Dup = Duplicate message
 * @QOS = QoS
 * return: -1 error or >-1 message size for send
 */
int
mqtt_msgSUBSCRIBE(mqtt_msg_t * __restrict buf, mqtt_subscr_t * __restrict Topics, 
		unsigned short msgID, unsigned char Dup, unsigned char QOS);
/*
 * mqtt_msgSUBACK() Create SUBACK message
 *
 * @buf = Message buffer
 * @Topics = MQTT subscription topics
 * @msgID = MessageID
 * return: -1 error or >-1 message size for send
 */
int mqtt_msgSUBACK(mqtt_msg_t * __restrict buf, mqtt_subscr_t * __restrict Topics, 
		unsigned short msgID);
/*
 * mqtt_msgUNSUBSCRIBE() Create UNSUBSCRIBE message
 *
 * @buf = Message buffer
 * @Topics = MQTT subscription topics
 * @msgID = MessageID
 * @Dup = Duplicate message
 * @QOS = QoS
 * return: -1 error or >-1 message size for send
 */
int
mqtt_msgUNSUBSCRIBE(mqtt_msg_t * __restrict buf, mqtt_subscr_t * __restrict Topics, 
		unsigned short msgID, unsigned char Dup, unsigned char QOS);
/*
 * mqtt_msgUNSUBACK() Create UNSUBACK message
 *
 * @buf = Message buffer
 * @msgID = MessageID
 * return: -1 error or >-1 message size for send
 */
int mqtt_msgUNSUBACK(mqtt_msg_t * __restrict buf, unsigned short msgID);


/*** RECEIVER FUNCTIONS ***/

/*
 * mqtt_readCONNECT() Read elements from CONNECT message
 *
 * @buf = Message buffer
 * @kasec = Keep Alive in seconds for current connection
 * @psConnID = ConnectID
 * @connLen = ConnectID length
 * @psUser = Username if !=NULL
 * @userLen = Username length
 * @psPass = Password for Username, only if csUser is set
 * @passLen = Password length
 * @psWillTopic = Will Topic if !=NULL Will Flags set into message
 * @topicLen = Will Topic length
 * @psWillMessage = Will Message, may be NULL
 * @msgLen = Will Message length
 * return: .reserved == 1 is error or == 0 connection flags & msg ok
 */
mqtthdr_connflgs_t mqtt_readCONNECT(mqtt_msg_t * __restrict buf, unsigned short *kasec, 
		char * __restrict psConnID, int connLen, 
		char * __restrict psUser, int userLen, char * __restrict psPass, int passLen,  
		char * __restrict psWillTopic, int topicLen, char * __restrict psWillMessage, int msgLen);
/*
 * mqtt_readCONNACK() Read CONNACK message
 *
 * @buf = Message buffer
 * return: -1 error or >-1 CONNECT message return code
 */
unsigned char mqtt_readCONNACK(mqtt_msg_t * __restrict buf);
/*
 * mqtt_readDISCONNECT() Read DISCONNECT message
 *
 * @buf = Message buffer
 * return: -1 error, 0 ok, >0 undefined result
 */
int mqtt_readDISCONNECT(mqtt_msg_t * __restrict buf);
/*
 * mqtt_readPINGREQ() Read PINGREQ message
 *
 * @buf = Message buffer
 * return: -1 error, 0 ok, >0 undefined result
 */
int mqtt_readPINGREQ(mqtt_msg_t * __restrict buf);
/*
 * mqtt_readPINGRESP() Read PINGRESP message
 *
 * @buf = Message buffer
 * return: -1 error, 0 ok, >0 undefined result
 */
int mqtt_readPINGRESP(mqtt_msg_t * __restrict buf);

/*
 * mqtt_readPUBACK() Read PUBACK message
 *
 * @buf = Message buffer
 * return: -1 error or MessageID
 */
u_short mqtt_readPUBACK(mqtt_msg_t * __restrict buf);
/*
 * mqtt_readPUBREC() Read PUBREC message
 *
 * @buf = Message buffer
 * return: -1 error or MessageID
 */
u_short mqtt_readPUBREC(mqtt_msg_t * __restrict buf);
/*
 * mqtt_readPUBREL() Read PUBREL message
 *
 * @buf = Message buffer
 * return: -1 error or MessageID
 */
u_short mqtt_readPUBREL(mqtt_msg_t * __restrict buf);
/*
 * mqtt_readPUBCOMP() Read PUBCOMP message
 *
 * @buf = Message buffer
 * return: -1 error or MessageID
 */
u_short mqtt_readPUBCOMP(mqtt_msg_t * __restrict buf);

/*
 * mqtt_readUNSUBACK() Read UNSUBACK message
 *
 * @buf = Message buffer
 * return: -1 error or MessageID
 */
u_short mqtt_readUNSUBACK(mqtt_msg_t * __restrict buf);

/*** ENGINE FUNCTIONS ***/

/*
 * mqttInitCallbacks() Init callback array for dispatcher
 *
 * return: NULL error or !=NULL allocated callback array, after use free with mqttFiniCallbacks()
 */
mqtt_cb_t *mqttInitCallbacks(void);
/*
 * mqttFiniCallbacks() Free callback array
 *
 * @cb = Callback array
 * return: none
 */
void mqttFiniCallbacks(mqtt_cb_t ** __restrict cb);
/*
 * MQTT_CALLBACK() Assign function to callback array for MQTT dispatcher
 *
 * @_cbs = Callback array
 * @_x = MQTT Message type, like MQTT_TYPE_* ...
 * @_func = Function
 * return: none
 */
#define MQTT_CALLBACK(_cbs, _x, _func)	(assert((_cbs)), (_cbs)[(_x)] = (_func))
/*
 * mqttDispatcher() MQTT Message type dispatcher
 *
 * @cb = Callback array
 * @buf = Received MQTT message
 * return: -1 error or >-1 return value from executed callback
 */
inline int mqttDispatcher(mqtt_cb_t * __restrict cb, mqtt_msg_t * __restrict buf);


#endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>