Annotation of libaitmqtt/src/conn.c, revision 1.3.12.3
1.1 misho 1: /*************************************************************************
2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
1.3.12.3! misho 6: * $Id: conn.c,v 1.3.12.2 2022/09/13 22:20:59 misho Exp $
1.1 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.3.12.2 misho 15: Copyright 2004 - 2022
1.1 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
46: #include "global.h"
47:
48:
49: /*
50: * mqtt_msgCONNECT() Create CONNECT message
51: *
52: * @csConnID = ConnectID
1.3.12.3! misho 53: * @Version = MQTT version, if =0 default version is 3.1.1
1.3.12.2 misho 54: * @KASec = Keep alive timeout, if =0 default timeout for MQTT
1.1 misho 55: * @csUser = Username if !=NULL
56: * @csPass = Password for Username, only if csUser is set
57: * @csWillTopic = Will Topic if !=NULL Will Flags set into message
58: * @csWillMessage = Will Message, may be NULL
59: * @ClrSess = Clear Session subscriptions after disconnect
60: * @WillQOS = Will QOS if csWillTopic is set
61: * @WillRetain = Will Retain Will Message if csWillTopic is set
1.3.12.3! misho 62: * return: NULL error or allocated CONNECT message
1.1 misho 63: */
1.3.12.2 misho 64: mqtt_msg_t *
65: mqtt_msgCONNECT(const char *csConnID, u_char Version, u_short KASec,
66: const char *csUser, const char *csPass,
1.1 misho 67: const char *csWillTopic, const char *csWillMessage,
68: u_char ClrSess, u_char WillQOS, u_char WillRetain)
69: {
1.2 misho 70: int len, siz = 0;
1.3 misho 71: u_int n, *l;
1.3.12.2 misho 72: mqtt_msg_t *msg = NULL;
1.1 misho 73: struct mqtthdr *hdr;
74: mqtthdr_var_t *var, *cid, *topic, *wmsg, *user, *pass;
75: mqtthdr_connflgs_t *flags;
76: mqtt_len_t *ka;
1.2 misho 77: void *data;
1.1 misho 78:
1.3.12.2 misho 79: if (!csConnID)
80: return NULL;
1.3.12.1 misho 81: if (strlen(csConnID) >= MQTT_CONNID_MAX) {
82: mqtt_SetErr(EINVAL, "Invalid argument ConnID is too long (max %d bytes)",
83: MQTT_CONNID_MAX - 1);
1.3.12.2 misho 84: return NULL;
85: }
1.3.12.3! misho 86: if (Version && (Version < MQTT_PROTO_VER_3 || Version > MQTT_PROTO_VER_5)) {
1.3.12.2 misho 87: mqtt_SetErr(EINVAL, "Unsupported version");
88: return NULL;
1.1 misho 89: }
1.3.12.1 misho 90: if (csUser && strlen(csUser) >= MQTT_CRED_MAX) {
91: mqtt_SetErr(EINVAL, "Invalid argument Username is too long (max %d bytes)",
92: MQTT_CRED_MAX - 1);
1.3.12.2 misho 93: return NULL;
1.1 misho 94: }
1.3.12.1 misho 95: if (csPass && strlen(csPass) >= MQTT_CRED_MAX) {
96: mqtt_SetErr(EINVAL, "Invalid argument Password is too long (max %d bytes)",
97: MQTT_CRED_MAX - 1);
1.3.12.2 misho 98: return NULL;
1.1 misho 99: }
100: if (WillQOS > MQTT_QOS_EXACTLY) {
1.2 misho 101: mqtt_SetErr(EINVAL, "Invalid argument WillQOS - unknown QOS value");
1.3.12.2 misho 102: return NULL;
1.1 misho 103: }
104:
1.2 misho 105: /* calculate message size */
1.3.12.2 misho 106: len = 10; /* connect arguments: MQTT(6)+Version(1)+ConnFlags(1)+KeepAlive(2) */
1.2 misho 107: len += sizeof(mqtt_len_t) + strlen(csConnID); /* connect id */
108: if (csUser && *csUser) { /* user/pass */
109: len += sizeof(mqtt_len_t) + strlen(csUser);
110: if (csPass)
111: len += sizeof(mqtt_len_t) + strlen(csPass);
112: }
113: if (csWillTopic && *csWillTopic) { /* will messages */
114: len += sizeof(mqtt_len_t) + strlen(csWillTopic);
115: len += sizeof(mqtt_len_t) + (csWillMessage ? strlen(csWillMessage) : 0);
116: }
117:
118: /* calculate header size */
119: siz = sizeof(struct mqtthdr); /* mqtt fixed header */
120: n = mqtt_encodeLen(len); /* message size */
121: siz += mqtt_sizeLen(n) - 1; /* length size */
122:
1.3.12.2 misho 123: if (!(msg = mqtt_msgAlloc(siz + len)))
124: return NULL;
1.1 misho 125: else {
1.3.12.2 misho 126: data = msg->msg_base;
1.2 misho 127: hdr = (struct mqtthdr *) data;
1.1 misho 128: }
129:
130: /* fixed header */
131: hdr->mqtt_msg.type = MQTT_TYPE_CONNECT;
1.3 misho 132: l = (u_int*) hdr->mqtt_len;
133: *l = n;
1.2 misho 134: data += siz;
1.1 misho 135:
136: /* variable header */
1.2 misho 137: var = (mqtthdr_var_t*) data;
1.3.12.2 misho 138: var->var_sb.val = htons(strlen(MQTT_PROTO_STR));
139: memcpy(var->var_data, MQTT_PROTO_STR, ntohs(var->var_sb.val));
1.2 misho 140: data += MQTTHDR_VAR_SIZEOF(var);
1.1 misho 141:
1.2 misho 142: /* protocol version */
1.3.12.3! misho 143: *(u_char*) data++ = Version ? Version : MQTT_PROTO_VER_311;
1.1 misho 144:
145: /* CONNECT header */
1.2 misho 146: flags = (mqtthdr_connflgs_t*) data++;
1.1 misho 147: flags->clean_sess = ClrSess ? 1 : 0;
148: if (csUser && *csUser) {
149: flags->username = 1;
150: flags->password = csPass ? 1 : 0;
151: } else {
152: flags->username = 0;
153: flags->password = 0;
154: }
155: if (csWillTopic && *csWillTopic) {
156: flags->will_flg = 1;
157: flags->will_qos = WillQOS;
158: flags->will_retain = WillRetain ? 1 : 0;
159: } else {
160: flags->will_flg = 0;
161: flags->will_qos = 0;
162: flags->will_retain = 0;
163: }
164:
1.2 misho 165: /* keep alive */
166: ka = (mqtt_len_t*) data;
1.3.12.2 misho 167: ka->val = KASec ? htons(KASec) : htons(MQTT_KEEPALIVE);
1.2 misho 168: data += sizeof(mqtt_len_t);
1.1 misho 169:
170: /* ConnID */
1.2 misho 171: cid = (mqtthdr_var_t*) data;
1.1 misho 172: cid->var_sb.val = htons(strlen(csConnID));
173: memcpy(cid->var_data, csConnID, ntohs(cid->var_sb.val));
1.2 misho 174: data += MQTTHDR_VAR_SIZEOF(cid);
1.1 misho 175:
176: /* If Will Flags setup */
177: if (csWillTopic && *csWillTopic) {
1.2 misho 178: topic = (mqtthdr_var_t*) data;
1.1 misho 179: topic->var_sb.val = htons(strlen(csWillTopic));
180: memcpy(topic->var_data, csWillTopic, ntohs(topic->var_sb.val));
1.2 misho 181: data += MQTTHDR_VAR_SIZEOF(topic);
1.1 misho 182:
1.2 misho 183: wmsg = (mqtthdr_var_t*) data;
1.1 misho 184: if (csWillMessage && *csWillMessage) {
185: wmsg->var_sb.val = htons(strlen(csWillMessage));
186: memcpy(wmsg->var_data, csWillMessage, ntohs(wmsg->var_sb.val));
187: } else
188: wmsg->var_sb.val = 0;
1.2 misho 189: data += MQTTHDR_VAR_SIZEOF(wmsg);
1.1 misho 190: }
191:
192: /* If defined Username & Password */
193: if (csUser && *csUser) {
1.2 misho 194: user = (mqtthdr_var_t*) data;
1.1 misho 195: user->var_sb.val = htons(strlen(csUser));
196: memcpy(user->var_data, csUser, ntohs(user->var_sb.val));
1.2 misho 197: data += MQTTHDR_VAR_SIZEOF(user);
1.1 misho 198:
199: if (csPass && *csPass) {
1.2 misho 200: pass = (mqtthdr_var_t*) data;
1.1 misho 201: pass->var_sb.val = htons(strlen(csPass));
202: memcpy(pass->var_data, csPass, ntohs(pass->var_sb.val));
1.2 misho 203: data += MQTTHDR_VAR_SIZEOF(pass);
1.1 misho 204: }
205: }
206:
1.3.12.2 misho 207: return msg;
1.1 misho 208: }
1.3.12.3! misho 209:
1.1 misho 210: /*
211: * mqtt_msgCONNACK() Create CONNACK message
212: *
213: * @retcode = Return code
1.3.12.3! misho 214: * return: NULL error or allocated CONNACK message
1.1 misho 215: */
1.3.12.2 misho 216: mqtt_msg_t *
217: mqtt_msgCONNACK(u_char retcode)
1.1 misho 218: {
219: struct mqtthdr *hdr;
220: mqtthdr_connack_t *ack;
1.3.12.2 misho 221: mqtt_msg_t *msg = NULL;
1.1 misho 222:
223: if (retcode > MQTT_RETCODE_DENIED) {
1.2 misho 224: mqtt_SetErr(EINVAL, "Invalid retcode");
1.3.12.2 misho 225: return NULL;
1.1 misho 226: }
227:
1.3.12.2 misho 228: if (!(msg = mqtt_msgAlloc(sizeof(struct mqtthdr) + sizeof(mqtthdr_connack_t))))
229: return NULL;
1.1 misho 230: else {
1.3.12.3! misho 231: hdr = (struct mqtthdr *) msg->msg_base;
! 232: ack = (mqtthdr_connack_t*) msg->msg_base + sizeof(struct mqtthdr);
1.1 misho 233: }
234:
235: /* fixed header */
236: hdr->mqtt_msg.type = MQTT_TYPE_CONNACK;
237: *hdr->mqtt_len = sizeof(mqtthdr_connack_t);
238:
239: /* CONNACK header */
240: ack->reserved = 0;
241: ack->retcode = retcode;
242:
1.3.12.3! misho 243: return msg;
1.1 misho 244: }
245:
1.3.12.3! misho 246: static mqtt_msg_t *
! 247: _mqtt_msgSIMPLE_(u_char cmd)
1.1 misho 248: {
249: struct mqtthdr *hdr;
1.3.12.3! misho 250: mqtt_msg_t *msg = NULL;
1.1 misho 251:
1.3.12.3! misho 252: if (!(msg = mqtt_msgAlloc(sizeof(struct mqtthdr))))
! 253: return NULL;
! 254: else
! 255: hdr = (struct mqtthdr *) msg->msg_base;
1.1 misho 256:
257: /* fixed header */
258: hdr->mqtt_msg.type = cmd;
259: *hdr->mqtt_len = 0;
260:
1.3.12.3! misho 261: return msg;
1.1 misho 262: }
263:
264: /*
265: * mqtt_msgPINGREQ() Create PINGREQ message
266: *
1.3.12.3! misho 267: * return: NULL error or allocated message
1.1 misho 268: */
1.3.12.3! misho 269: mqtt_msg_t *
! 270: mqtt_msgPINGREQ()
1.1 misho 271: {
1.3.12.3! misho 272: return _mqtt_msgSIMPLE_(MQTT_TYPE_PINGREQ);
1.1 misho 273: }
274:
275: /*
276: * mqtt_msgPINGRESP() Create PINGRESP message
277: *
1.3.12.3! misho 278: * return: NULL error or allocated message
1.1 misho 279: */
1.3.12.3! misho 280: mqtt_msg_t *
! 281: mqtt_msgPINGRESP()
1.1 misho 282: {
1.3.12.3! misho 283: return _mqtt_msgSIMPLE_(MQTT_TYPE_PINGRESP);
1.1 misho 284: }
285:
286: /*
287: * mqtt_msgDISCONNECT() Create DISCONNECT message
288: *
1.3.12.3! misho 289: * return: NULL error or allocated message
1.1 misho 290: */
1.3.12.3! misho 291: mqtt_msg_t *
! 292: mqtt_msgDISCONNECT()
1.1 misho 293: {
1.3.12.3! misho 294: return _mqtt_msgSIMPLE_(MQTT_TYPE_DISCONNECT);
1.1 misho 295: }
296:
297: /* ============= decode ============ */
298:
1.3.12.3! misho 299: //#pragma GCC visibility push(hidden)
! 300: /* _mqtt_readHEADER() read fixed header from MQTT message */
! 301: static struct mqtthdr *
! 302: _mqtt_readHEADER(mqtt_msg_t * __restrict buf, u_char cmd, int *len, caddr_t *next)
! 303: {
! 304: struct mqtthdr *hdr;
! 305: int bytes;
! 306:
! 307: if (!buf || !buf->msg_base || !buf->msg_len)
! 308: return NULL;
! 309:
! 310: hdr = (struct mqtthdr*) buf->msg_base;
! 311: if (hdr->mqtt_msg.type != cmd) {
! 312: mqtt_SetErr(EINVAL, "Error:: wrong command #%d should be %d",
! 313: hdr->mqtt_msg.type, cmd);
! 314: return NULL;
! 315: }
! 316:
! 317: if (len)
! 318: *len = mqtt_decodeLen(hdr->mqtt_len, &bytes);
! 319:
! 320: if (next)
! 321: *next = buf->msg_base + bytes + 1;
! 322:
! 323: return hdr;
! 324: }
! 325: //#pragma GCC visibility pop
! 326:
1.1 misho 327: /*
328: * mqtt_readCONNECT() Read elements from CONNECT message
329: *
330: * @buf = Message buffer
1.3.12.3! misho 331: * @KASec = Keep Alive in seconds for current connection
1.1 misho 332: * @psConnID = ConnectID
333: * @connLen = ConnectID length
334: * @psUser = Username if !=NULL
335: * @userLen = Username length
336: * @psPass = Password for Username, only if csUser is set
337: * @passLen = Password length
1.3.12.3! misho 338: * @psWillTopic = Will Topic if !=NULL Will Flags set into message and must be e_free()
! 339: * @psWillMessage = Will Message, may be NULL if !NULL must be e_free() after use!
1.1 misho 340: * return: .reserved == 1 is error or == 0 connection flags & msg ok
341: */
342: mqtthdr_connack_t
1.3.12.3! misho 343: mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short *KASec, char * __restrict psConnID, int connLen,
1.1 misho 344: char * __restrict psUser, int userLen, char * __restrict psPass, int passLen,
345: char ** __restrict psWillTopic, char ** __restrict psWillMessage)
346: {
347: mqtthdr_connflgs_t flg = { MQTT_CONNFLGS_INIT };
348: mqtthdr_connack_t cack = { 1, MQTT_RETCODE_DENIED };
349: struct mqtthdr *hdr;
350: mqtthdr_var_t *var;
351: mqtt_len_t *ka;
1.3.12.3! misho 352: int len;
1.1 misho 353: caddr_t pos;
354:
355: if (!buf || !buf->msg_base || !buf->msg_len || !psConnID || !connLen)
356: return cack;
357:
1.3.12.3! misho 358: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_CONNECT, &len, &pos);
1.1 misho 359: if (!hdr)
360: return cack;
361: if (len < 12) {
1.2 misho 362: mqtt_SetErr(EINVAL, "Short message length %d", len);
1.1 misho 363: return cack;
1.3.12.3! misho 364: } else
1.1 misho 365: var = (mqtthdr_var_t*) pos;
1.3.12.3! misho 366:
1.1 misho 367: /* check init string & protocol */
1.3.12.3! misho 368: if (var->var_sb.sb.l == 4 && !strcmp((char*) var->var_data, MQTT_PROTO_STR))
! 369: pos += var->var_sb.sb.l + sizeof(mqtt_len_t);
! 370: else if (var->var_sb.sb.l == 6 || strcmp((char*) var->var_data, MQTT_CONN_STR))
! 371: pos += var->var_sb.sb.l + sizeof(mqtt_len_t);
! 372: else {
1.2 misho 373: mqtt_SetErr(EINVAL, "Invalid init string %.6s(%d)",
1.1 misho 374: var->var_data, var->var_sb.sb.l);
375: cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
376: return cack;
377: }
1.3.12.3! misho 378: switch (*pos) {
! 379: case MQTT_PROTO_VER_3:
! 380: case MQTT_PROTO_VER_311:
! 381: case MQTT_PROTO_VER_5:
! 382: pos++;
! 383: break;
! 384: default:
! 385: mqtt_SetErr(EINVAL, "Invalid protocol version %d", *pos);
! 386: cack.retcode = MQTT_RETCODE_REFUSE_VER;
! 387: return cack;
! 388: }
1.1 misho 389: flg = *(mqtthdr_connflgs_t*) pos;
390: pos++;
391: ka = (mqtt_len_t*) pos;
1.3.12.3! misho 392: *KASec = ntohs(ka->val);
1.1 misho 393: pos += sizeof(mqtt_len_t);
394:
395: len -= pos - (caddr_t) var;
396:
397: /* get ConnID */
398: var = (mqtthdr_var_t*) pos;
399: len -= MQTTHDR_VAR_SIZEOF(var);
1.3.12.3! misho 400: if (len < 0 || var->var_sb.sb.l >= MQTT_CONNID_MAX) {
1.2 misho 401: mqtt_SetErr(EINVAL, "Unexpected EOM at Connection ID %d", len);
1.1 misho 402: cack.retcode = MQTT_RETCODE_REFUSE_ID;
403: return cack;
404: } else {
405: memset(psConnID, 0, connLen--);
1.3.12.3! misho 406: memcpy(psConnID, var->var_data,
! 407: ntohs(var->var_sb.val) > connLen ? connLen : ntohs(var->var_sb.val));
1.1 misho 408: pos += MQTTHDR_VAR_SIZEOF(var);
409: }
410:
411: /* get Willz */
412: if (flg.will_flg) {
413: var = (mqtthdr_var_t*) pos;
414: len -= MQTTHDR_VAR_SIZEOF(var);
415: if (len < 0) {
1.2 misho 416: mqtt_SetErr(EINVAL, "Unexpected EOM at Will Topic %d", len);
1.1 misho 417: cack.retcode = MQTT_RETCODE_REFUSE_ID;
418: return cack;
419: } else {
420: if (psWillTopic) {
1.3.12.3! misho 421: *psWillTopic = e_malloc(ntohs(var->var_sb.val) + 1);
1.1 misho 422: if (!*psWillTopic) {
423: LOGERR;
424: cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
425: return cack;
426: } else
427: memset(*psWillTopic, 0, ntohs(var->var_sb.val) + 1);
428: memcpy(*psWillTopic, var->var_data, ntohs(var->var_sb.val));
429: }
430: pos += MQTTHDR_VAR_SIZEOF(var);
431: }
432:
433: var = (mqtthdr_var_t*) pos;
434: len -= MQTTHDR_VAR_SIZEOF(var);
435: if (len < 0) {
1.2 misho 436: mqtt_SetErr(EINVAL, "Unexpected EOM at Will Message %d", len);
1.3.12.3! misho 437: e_free(psWillTopic);
1.1 misho 438: cack.retcode = MQTT_RETCODE_REFUSE_ID;
439: return cack;
440: } else {
441: if (psWillMessage) {
1.3.12.3! misho 442: *psWillMessage = e_malloc(ntohs(var->var_sb.val) + 1);
1.1 misho 443: if (!*psWillMessage) {
444: LOGERR;
1.3.12.3! misho 445: e_free(psWillTopic);
1.1 misho 446: cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
447: return cack;
448: } else
449: memset(*psWillMessage, 0, ntohs(var->var_sb.val) + 1);
450: memcpy(*psWillMessage, var->var_data, ntohs(var->var_sb.val));
451: }
452: pos += MQTTHDR_VAR_SIZEOF(var);
453: }
454: }
455:
456: /* get User/Pass */
457: if (flg.username) {
458: var = (mqtthdr_var_t*) pos;
459: len -= MQTTHDR_VAR_SIZEOF(var);
460: if (len < 0 || var->var_sb.sb.l > 12) {
1.2 misho 461: mqtt_SetErr(EINVAL, "Unexpected EOM at Username %d", len);
1.3.12.3! misho 462: if (flg.will_flg) {
! 463: if (psWillTopic)
! 464: e_free(psWillTopic);
! 465: if (psWillMessage)
! 466: e_free(psWillMessage);
! 467: }
1.1 misho 468: cack.retcode = MQTT_RETCODE_REFUSE_USERPASS;
469: return cack;
470: } else {
471: if (psUser && userLen) {
472: memset(psUser, 0, userLen--);
473: memcpy(psUser, var->var_data,
474: ntohs(var->var_sb.val) > userLen ? userLen : ntohs(var->var_sb.val));
475: }
476: pos += MQTTHDR_VAR_SIZEOF(var);
477: }
478: }
479: if (flg.password) {
480: var = (mqtthdr_var_t*) pos;
481: len -= MQTTHDR_VAR_SIZEOF(var);
482: if (len < 0 || var->var_sb.sb.l > 12) {
1.2 misho 483: mqtt_SetErr(EINVAL, "Unexpected EOM at Password %d", len);
1.3.12.3! misho 484: if (flg.will_flg) {
! 485: if (psWillTopic)
! 486: e_free(psWillTopic);
! 487: if (psWillMessage)
! 488: e_free(psWillMessage);
! 489: }
1.1 misho 490: cack.retcode = MQTT_RETCODE_REFUSE_USERPASS;
491: return cack;
492: } else {
493: if (psPass && passLen) {
494: memset(psPass, 0, passLen--);
495: memcpy(psPass, var->var_data,
496: ntohs(var->var_sb.val) > passLen ? passLen : ntohs(var->var_sb.val));
497: }
498: pos += MQTTHDR_VAR_SIZEOF(var);
499: }
500: }
501:
502: flg.reserved = 0;
503: cack.reserved = flg.flags;
504: cack.retcode = MQTT_RETCODE_ACCEPTED;
505: return cack;
506: }
507:
508: /*
509: * mqtt_readCONNACK() Read CONNACK message
510: *
511: * @buf = Message buffer
512: * return: -1 error or >-1 CONNECT message return code
513: */
514: u_char
515: mqtt_readCONNACK(mqtt_msg_t * __restrict buf)
516: {
1.3.12.3! misho 517: int len;
1.1 misho 518: struct mqtthdr *hdr;
519: mqtthdr_connack_t *ack;
520: caddr_t pos;
521:
522: if (!buf || !buf->msg_base || !buf->msg_len)
523: return (u_char) -1;
524:
1.3.12.3! misho 525: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_CONNACK, &len, &pos);
1.1 misho 526: if (!hdr)
527: return (u_char) -1;
528: if (len < sizeof(mqtthdr_connack_t)) {
1.2 misho 529: mqtt_SetErr(EINVAL, "Short message length %d", len);
1.1 misho 530: return (u_char) -1;
1.3.12.3! misho 531: } else
1.1 misho 532: ack = (mqtthdr_connack_t*) pos;
533:
534: if (ack->retcode > MQTT_RETCODE_DENIED) {
1.2 misho 535: mqtt_SetErr(EINVAL, "Invalid retcode %u", ack->retcode);
1.1 misho 536: return (u_char) -1;
537: }
538:
539: return ack->retcode;
540: }
541:
542: /*
543: * mqtt_readDISCONNECT() Read DISCONNECT message
544: *
545: * @buf = Message buffer
546: * return: -1 error, 0 ok, >0 undefined result
547: */
548: int
549: mqtt_readDISCONNECT(mqtt_msg_t * __restrict buf)
550: {
1.3.12.3! misho 551: int len;
1.1 misho 552:
1.3.12.3! misho 553: if (!_mqtt_readHEADER(buf, MQTT_TYPE_DISCONNECT, &len, NULL))
1.1 misho 554: return -1;
555:
556: return len;
557: }
558:
559: /*
560: * mqtt_readPINGREQ() Read PINGREQ message
561: *
562: * @buf = Message buffer
563: * return: -1 error, 0 ok, >0 undefined result
564: */
565: int
566: mqtt_readPINGREQ(mqtt_msg_t * __restrict buf)
567: {
1.3.12.3! misho 568: int len;
1.1 misho 569:
1.3.12.3! misho 570: if (!_mqtt_readHEADER(buf, MQTT_TYPE_PINGREQ, &len, NULL))
1.1 misho 571: return -1;
572:
573: return len;
574: }
575:
576: /*
577: * mqtt_readPINGRESP() Read PINGRESP message
578: *
579: * @buf = Message buffer
580: * return: -1 error, 0 ok, >0 undefined result
581: */
582: int
583: mqtt_readPINGRESP(mqtt_msg_t * __restrict buf)
584: {
1.3.12.3! misho 585: int len;
1.1 misho 586:
1.3.12.3! misho 587: if (!_mqtt_readHEADER(buf, MQTT_TYPE_PINGRESP, &len, NULL))
1.1 misho 588: return -1;
589:
590: return len;
591: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>