#include "global.h"
/* ------------------------------------------------------------------- */
/*
* 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,
u_char ClrSess, u_char WillQOS, u_char WillRetain)
{
int siz = 0;
struct mqtthdr *hdr;
mqtthdr_var_t *var, *cid, *topic, *wmsg, *user, *pass;
mqtthdr_protover_t *proto;
mqtthdr_connflgs_t *flags;
mqtt_v_t *ka;
if (!buf || !csConnID)
return -1;
if (strlen(csConnID) > 23) {
mqtt_SetErr(EINVAL, "Error:: invalid argument ConnID is too long (max 23 bytes)");
return -1;
}
if (csUser && strlen(csUser) > 12) {
mqtt_SetErr(EINVAL, "Error:: invalid argument Username is too long (max 12 bytes)");
return -1;
}
if (csPass && strlen(csPass) > 12) {
mqtt_SetErr(EINVAL, "Error:: invalid argument Password is too long (max 12 bytes)");
return -1;
}
if (WillQOS > MQTT_QOS_EXACTLY) {
mqtt_SetErr(EINVAL, "Error:: invalid argument WillQOS - unknown QOS value");
return -1;
}
if (mqtt_msgRealloc(buf, BUFSIZ) == -1)
return -1;
else {
hdr = (struct mqtthdr *) (buf->msg_base + siz);
siz += sizeof(struct mqtthdr);
var = (mqtthdr_var_t*) (buf->msg_base + siz);
siz += 8;
proto = buf->msg_base + siz;
siz++;
flags = (mqtthdr_connflgs_t*) (buf->msg_base + siz);
siz++;
ka = (mqtt_v_t*) (buf->msg_base + siz);
siz += sizeof(mqtt_v_t);
}
/* fixed header */
hdr->mqtt_msg.type = MQTT_TYPE_CONNECT;
*hdr->mqtt_len = 0;
/* variable header */
var->var_sb.sb.l = 6;
memcpy(var->var_data, MQTT_CONN_STR, 6);
*proto = MQTT_PROTO_VER;
/* CONNECT header */
flags->clean_sess = ClrSess ? 1 : 0;
if (csUser) {
flags->username = 1;
flags->password = csPass ? 1 : 0;
} else {
flags->username = 0;
flags->password = 0;
}
if (csWillTopic) {
flags->will_flg = 1;
flags->will_qos = WillQOS;
flags->will_retain = WillRetain ? 1 : 0;
} else {
flags->will_flg = 0;
flags->will_qos = 0;
flags->will_retain = 0;
}
ka->sb.l = MQTT_KEEPALIVE;
/* ConnID */
cid = (mqtthdr_var_t*) (buf->msg_base + siz);
cid->var_sb.val = htons(strlen(csConnID));
siz += MQTTHDR_VAR_SIZEOF(cid);
memcpy(cid->var_data, csConnID, ntohs(cid->var_sb.val));
/* If Will Flags setup */
if (csWillTopic) {
topic = (mqtthdr_var_t*) (buf->msg_base + siz);
topic->var_sb.val = htons(strlen(csWillTopic));
memcpy(topic->var_data, csWillTopic, ntohs(topic->var_sb.val));
siz += MQTTHDR_VAR_SIZEOF(topic);
wmsg = (mqtthdr_var_t*) (buf->msg_base + siz);
if (csWillMessage) {
wmsg->var_sb.val = htons(strlen(csWillMessage));
memcpy(wmsg->var_data, csWillMessage, ntohs(wmsg->var_sb.val));
} else
wmsg->var_sb.val = 0;
siz += MQTTHDR_VAR_SIZEOF(wmsg);
}
/* If defined Username & Password */
if (csUser) {
user = (mqtthdr_var_t*) (buf->msg_base + siz);
user->var_sb.val = htons(strlen(csUser));
memcpy(user->var_data, csUser, ntohs(user->var_sb.val));
siz += MQTTHDR_VAR_SIZEOF(user);
if (csPass) {
pass = (mqtthdr_var_t*) (buf->msg_base + siz);
pass->var_sb.val = htons(strlen(csPass));
memcpy(pass->var_data, csPass, ntohs(pass->var_sb.val));
siz += MQTTHDR_VAR_SIZEOF(pass);
}
}
*hdr->mqtt_len = mqtt_encodeLen(siz - sizeof(struct mqtthdr));
mqtt_msgRealloc(buf, siz);
return siz;
}
/*
* 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, u_char retcode)
{
int siz = 0;
struct mqtthdr *hdr;
mqtthdr_connack_t *ack;
if (!buf)
return -1;
if (retcode > MQTT_RETCODE_DENIED) {
mqtt_SetErr(EINVAL, "Error:: invalid retcode");
return -1;
}
if (mqtt_msgRealloc(buf, sizeof(struct mqtthdr) + sizeof(mqtthdr_connack_t)) == -1)
return -1;
else {
hdr = (struct mqtthdr *) (buf->msg_base + siz);
siz += sizeof(struct mqtthdr);
ack = (mqtthdr_connack_t*) (buf->msg_base + siz);
siz += sizeof(mqtthdr_connack_t);
}
/* fixed header */
hdr->mqtt_msg.type = MQTT_TYPE_CONNACK;
*hdr->mqtt_len = sizeof(mqtthdr_connack_t);
/* CONNACK header */
ack->reserved = 0;
ack->retcode = retcode;
return siz;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>