--- libaitmqtt/src/conn.c 2012/01/26 13:07:33 1.1 +++ libaitmqtt/src/conn.c 2022/09/13 22:20:59 1.3.12.2 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: conn.c,v 1.1 2012/01/26 13:07:33 misho Exp $ +* $Id: conn.c,v 1.3.12.2 2022/09/13 22:20:59 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -12,7 +12,7 @@ terms: All of the documentation and software included in the ELWIX and AITNET Releases is copyrighted by ELWIX - Sofia/Bulgaria -Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 +Copyright 2004 - 2022 by Michael Pounov . All rights reserved. Redistribution and use in source and binary forms, with or without @@ -46,14 +46,12 @@ SUCH DAMAGE. #include "global.h" -/* ------------------------------------------------------------------- */ - /* * mqtt_msgCONNECT() Create CONNECT message * - * @buf = Message buffer * @csConnID = ConnectID - * @kasec = Keep alive timeout + * @Version = MQTT version + * @KASec = Keep alive timeout, if =0 default timeout for MQTT * @csUser = Username if !=NULL * @csPass = Password for Username, only if csUser is set * @csWillTopic = Will Topic if !=NULL Will Flags set into message @@ -61,67 +59,91 @@ SUCH DAMAGE. * @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 + * return: NULL error or allocated connect message */ -int -mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const char *csConnID, - u_short kasec, const char *csUser, const char *csPass, +mqtt_msg_t * +mqtt_msgCONNECT(const char *csConnID, u_char Version, u_short KASec, + const char *csUser, const char *csPass, const char *csWillTopic, const char *csWillMessage, u_char ClrSess, u_char WillQOS, u_char WillRetain) { - int siz = 0; + int len, siz = 0; + u_int n, *l; + mqtt_msg_t *msg = NULL; struct mqtthdr *hdr; mqtthdr_var_t *var, *cid, *topic, *wmsg, *user, *pass; - mqtthdr_protover_t *proto; mqtthdr_connflgs_t *flags; mqtt_len_t *ka; + void *data; - 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 (!csConnID) + return NULL; + if (strlen(csConnID) >= MQTT_CONNID_MAX) { + mqtt_SetErr(EINVAL, "Invalid argument ConnID is too long (max %d bytes)", + MQTT_CONNID_MAX - 1); + return NULL; } - if (csUser && strlen(csUser) > 12) { - mqtt_SetErr(EINVAL, "Error:: invalid argument Username is too long (max 12 bytes)"); - return -1; + if (Version < MQTT_PROTO_VER_3 || Version > MQTT_PROTO_VER_5) { + mqtt_SetErr(EINVAL, "Unsupported version"); + return NULL; } - if (csPass && strlen(csPass) > 12) { - mqtt_SetErr(EINVAL, "Error:: invalid argument Password is too long (max 12 bytes)"); - return -1; + if (csUser && strlen(csUser) >= MQTT_CRED_MAX) { + mqtt_SetErr(EINVAL, "Invalid argument Username is too long (max %d bytes)", + MQTT_CRED_MAX - 1); + return NULL; } + if (csPass && strlen(csPass) >= MQTT_CRED_MAX) { + mqtt_SetErr(EINVAL, "Invalid argument Password is too long (max %d bytes)", + MQTT_CRED_MAX - 1); + return NULL; + } if (WillQOS > MQTT_QOS_EXACTLY) { - mqtt_SetErr(EINVAL, "Error:: invalid argument WillQOS - unknown QOS value"); - return -1; + mqtt_SetErr(EINVAL, "Invalid argument WillQOS - unknown QOS value"); + return NULL; } - if (mqtt_msgRealloc(buf, BUFSIZ) == -1) - return -1; + /* calculate message size */ + len = 10; /* connect arguments: MQTT(6)+Version(1)+ConnFlags(1)+KeepAlive(2) */ + len += sizeof(mqtt_len_t) + strlen(csConnID); /* connect id */ + if (csUser && *csUser) { /* user/pass */ + len += sizeof(mqtt_len_t) + strlen(csUser); + if (csPass) + len += sizeof(mqtt_len_t) + strlen(csPass); + } + if (csWillTopic && *csWillTopic) { /* will messages */ + len += sizeof(mqtt_len_t) + strlen(csWillTopic); + len += sizeof(mqtt_len_t) + (csWillMessage ? strlen(csWillMessage) : 0); + } + + /* calculate header size */ + siz = sizeof(struct mqtthdr); /* mqtt fixed header */ + n = mqtt_encodeLen(len); /* message size */ + siz += mqtt_sizeLen(n) - 1; /* length size */ + + if (!(msg = mqtt_msgAlloc(siz + len))) + return NULL; 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_len_t*) (buf->msg_base + siz); - siz += sizeof(mqtt_len_t); + data = msg->msg_base; + hdr = (struct mqtthdr *) data; } /* fixed header */ - MQTTHDR_MSGINIT(hdr); hdr->mqtt_msg.type = MQTT_TYPE_CONNECT; - *hdr->mqtt_len = 0; + l = (u_int*) hdr->mqtt_len; + *l = n; + data += siz; /* variable header */ - var->var_sb.sb.l = 6; - memcpy(var->var_data, MQTT_CONN_STR, 6); + var = (mqtthdr_var_t*) data; + var->var_sb.val = htons(strlen(MQTT_PROTO_STR)); + memcpy(var->var_data, MQTT_PROTO_STR, ntohs(var->var_sb.val)); + data += MQTTHDR_VAR_SIZEOF(var); - *proto = MQTT_PROTO_VER; + /* protocol version */ + *(u_char*) data++ = Version; /* CONNECT header */ + flags = (mqtthdr_connflgs_t*) data++; flags->clean_sess = ClrSess ? 1 : 0; if (csUser && *csUser) { flags->username = 1; @@ -140,50 +162,51 @@ mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha flags->will_retain = 0; } - ka->val = kasec ? htons(kasec) : htons(MQTT_KEEPALIVE); + /* keep alive */ + ka = (mqtt_len_t*) data; + ka->val = KASec ? htons(KASec) : htons(MQTT_KEEPALIVE); + data += sizeof(mqtt_len_t); /* ConnID */ - cid = (mqtthdr_var_t*) (buf->msg_base + siz); + cid = (mqtthdr_var_t*) data; cid->var_sb.val = htons(strlen(csConnID)); - siz += MQTTHDR_VAR_SIZEOF(cid); memcpy(cid->var_data, csConnID, ntohs(cid->var_sb.val)); + data += MQTTHDR_VAR_SIZEOF(cid); /* If Will Flags setup */ if (csWillTopic && *csWillTopic) { - topic = (mqtthdr_var_t*) (buf->msg_base + siz); + topic = (mqtthdr_var_t*) data; topic->var_sb.val = htons(strlen(csWillTopic)); memcpy(topic->var_data, csWillTopic, ntohs(topic->var_sb.val)); - siz += MQTTHDR_VAR_SIZEOF(topic); + data += MQTTHDR_VAR_SIZEOF(topic); - wmsg = (mqtthdr_var_t*) (buf->msg_base + siz); + wmsg = (mqtthdr_var_t*) data; if (csWillMessage && *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); + data += MQTTHDR_VAR_SIZEOF(wmsg); } /* If defined Username & Password */ if (csUser && *csUser) { - user = (mqtthdr_var_t*) (buf->msg_base + siz); + user = (mqtthdr_var_t*) data; user->var_sb.val = htons(strlen(csUser)); memcpy(user->var_data, csUser, ntohs(user->var_sb.val)); - siz += MQTTHDR_VAR_SIZEOF(user); + data += MQTTHDR_VAR_SIZEOF(user); if (csPass && *csPass) { - pass = (mqtthdr_var_t*) (buf->msg_base + siz); + pass = (mqtthdr_var_t*) data; pass->var_sb.val = htons(strlen(csPass)); memcpy(pass->var_data, csPass, ntohs(pass->var_sb.val)); - siz += MQTTHDR_VAR_SIZEOF(pass); + data += MQTTHDR_VAR_SIZEOF(pass); } } - *hdr->mqtt_len = mqtt_encodeLen(siz - sizeof(struct mqtthdr)); - mqtt_msgRealloc(buf, siz); - return siz; + return msg; } - +#if 0 /* * mqtt_msgCONNACK() Create CONNACK message * @@ -191,22 +214,21 @@ mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha * @retcode = Return code * return: -1 error or >-1 message size for send */ -int -mqtt_msgCONNACK(mqtt_msg_t * __restrict buf, u_char retcode) +mqtt_msg_t * +mqtt_msgCONNACK(u_char retcode) { int siz = 0; struct mqtthdr *hdr; mqtthdr_connack_t *ack; + mqtt_msg_t *msg = NULL; - if (!buf) - return -1; if (retcode > MQTT_RETCODE_DENIED) { - mqtt_SetErr(EINVAL, "Error:: invalid retcode"); - return -1; + mqtt_SetErr(EINVAL, "Invalid retcode"); + return NULL; } - if (mqtt_msgRealloc(buf, sizeof(struct mqtthdr) + sizeof(mqtthdr_connack_t)) == -1) - return -1; + if (!(msg = mqtt_msgAlloc(sizeof(struct mqtthdr) + sizeof(mqtthdr_connack_t)))) + return NULL; else { hdr = (struct mqtthdr *) (buf->msg_base + siz); siz += sizeof(struct mqtthdr); @@ -313,7 +335,6 @@ mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short struct mqtthdr *hdr; mqtthdr_var_t *var; mqtt_len_t *ka; - mqtthdr_protover_t *proto; int len, ret; caddr_t pos; @@ -324,7 +345,7 @@ mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short if (!hdr) return cack; if (len < 12) { - mqtt_SetErr(EINVAL, "Error:: short message length %d", len); + mqtt_SetErr(EINVAL, "Short message length %d", len); return cack; } else { pos = buf->msg_base + ret + 1; @@ -332,7 +353,7 @@ mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short } /* check init string & protocol */ if (var->var_sb.sb.l != 6 || strncmp((char*) var->var_data, MQTT_CONN_STR, 6)) { - mqtt_SetErr(EINVAL, "Error:: invalid init string %.6s(%d)", + mqtt_SetErr(EINVAL, "Invalid init string %.6s(%d)", var->var_data, var->var_sb.sb.l); cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL; return cack; @@ -341,7 +362,7 @@ mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short proto = (mqtthdr_protover_t*) pos; } if (*proto != MQTT_PROTO_VER) { - mqtt_SetErr(EINVAL, "Error:: invalid protocol version %d", *pos); + mqtt_SetErr(EINVAL, "Invalid protocol version %d", *pos); cack.retcode = MQTT_RETCODE_REFUSE_VER; return cack; } else @@ -358,7 +379,7 @@ mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short var = (mqtthdr_var_t*) pos; len -= MQTTHDR_VAR_SIZEOF(var); if (len < 0 || var->var_sb.sb.l > 23) { - mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Connection ID %d", len); + mqtt_SetErr(EINVAL, "Unexpected EOM at Connection ID %d", len); cack.retcode = MQTT_RETCODE_REFUSE_ID; return cack; } else { @@ -372,7 +393,7 @@ mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short var = (mqtthdr_var_t*) pos; len -= MQTTHDR_VAR_SIZEOF(var); if (len < 0) { - mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Will Topic %d", len); + mqtt_SetErr(EINVAL, "Unexpected EOM at Will Topic %d", len); cack.retcode = MQTT_RETCODE_REFUSE_ID; return cack; } else { @@ -392,7 +413,7 @@ mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short var = (mqtthdr_var_t*) pos; len -= MQTTHDR_VAR_SIZEOF(var); if (len < 0) { - mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Will Message %d", len); + mqtt_SetErr(EINVAL, "Unexpected EOM at Will Message %d", len); cack.retcode = MQTT_RETCODE_REFUSE_ID; return cack; } else { @@ -415,7 +436,7 @@ mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short var = (mqtthdr_var_t*) pos; len -= MQTTHDR_VAR_SIZEOF(var); if (len < 0 || var->var_sb.sb.l > 12) { - mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Username %d", len); + mqtt_SetErr(EINVAL, "Unexpected EOM at Username %d", len); cack.retcode = MQTT_RETCODE_REFUSE_USERPASS; return cack; } else { @@ -431,7 +452,7 @@ mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short var = (mqtthdr_var_t*) pos; len -= MQTTHDR_VAR_SIZEOF(var); if (len < 0 || var->var_sb.sb.l > 12) { - mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Password %d", len); + mqtt_SetErr(EINVAL, "Unexpected EOM at Password %d", len); cack.retcode = MQTT_RETCODE_REFUSE_USERPASS; return cack; } else { @@ -471,7 +492,7 @@ mqtt_readCONNACK(mqtt_msg_t * __restrict buf) if (!hdr) return (u_char) -1; if (len < sizeof(mqtthdr_connack_t)) { - mqtt_SetErr(EINVAL, "Error:: short message length %d", len); + mqtt_SetErr(EINVAL, "Short message length %d", len); return (u_char) -1; } else { pos = buf->msg_base + ret + 1; @@ -479,7 +500,7 @@ mqtt_readCONNACK(mqtt_msg_t * __restrict buf) } if (ack->retcode > MQTT_RETCODE_DENIED) { - mqtt_SetErr(EINVAL, "Error:: invalid retcode %u", ack->retcode); + mqtt_SetErr(EINVAL, "Invalid retcode %u", ack->retcode); return (u_char) -1; } @@ -542,3 +563,4 @@ mqtt_readPINGRESP(mqtt_msg_t * __restrict buf) return len; } +#endif