Annotation of libaitmqtt/src/read.c, revision 1.1.2.1
1.1.2.1 ! misho 1: /*************************************************************************
! 2: * (C) 2022 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
! 3: * by Michael Pounov <misho@elwix.org>
! 4: *
! 5: * $Author: misho $
! 6: * $Id: conn.c,v 1.3.12.3 2022/09/14 14:32:48 misho Exp $
! 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:
! 15: Copyright 2004 - 2022
! 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: /* _mqtt_readHEADER() read fixed header from MQTT message */
! 50: static struct mqtthdr *
! 51: _mqtt_readHEADER(mqtt_msg_t * __restrict buf, u_char cmd, int *len, caddr_t *next)
! 52: {
! 53: struct mqtthdr *hdr;
! 54: int bytes;
! 55:
! 56: if (!buf || !buf->msg_base || !buf->msg_len)
! 57: return NULL;
! 58:
! 59: hdr = (struct mqtthdr*) buf->msg_base;
! 60: if (hdr->mqtt_msg.type != cmd) {
! 61: mqtt_SetErr(EINVAL, "Error:: wrong command #%d should be %d",
! 62: hdr->mqtt_msg.type, cmd);
! 63: return NULL;
! 64: }
! 65:
! 66: if (len)
! 67: *len = mqtt_decodeLen(hdr->mqtt_len, &bytes);
! 68:
! 69: if (next)
! 70: *next = buf->msg_base + bytes + 1;
! 71:
! 72: return hdr;
! 73: }
! 74:
! 75:
! 76: /*
! 77: * mqtt_readCONNECT() Read elements from CONNECT message
! 78: *
! 79: * @buf = Message buffer
! 80: * @KASec = Keep Alive in seconds for current connection
! 81: * @psConnID = ConnectID
! 82: * @connLen = ConnectID length
! 83: * @psUser = Username if !=NULL
! 84: * @userLen = Username length
! 85: * @psPass = Password for Username, only if csUser is set
! 86: * @passLen = Password length
! 87: * @psWillTopic = Will Topic if !=NULL Will Flags set into message and must be e_free()
! 88: * @psWillMessage = Will Message, may be NULL if !NULL must be e_free() after use!
! 89: * return: .reserved == 1 is error or == 0 connection flags & msg ok
! 90: */
! 91: mqtthdr_connack_t
! 92: mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short *KASec, char * __restrict psConnID, int connLen,
! 93: char * __restrict psUser, int userLen, char * __restrict psPass, int passLen,
! 94: char ** __restrict psWillTopic, char ** __restrict psWillMessage)
! 95: {
! 96: mqtthdr_connflgs_t flg = { MQTT_CONNFLGS_INIT };
! 97: mqtthdr_connack_t cack = { 1, MQTT_RETCODE_DENIED };
! 98: struct mqtthdr *hdr;
! 99: mqtthdr_var_t *var;
! 100: mqtt_len_t *ka;
! 101: int len;
! 102: caddr_t pos;
! 103:
! 104: if (!buf || !buf->msg_base || !buf->msg_len || !psConnID || !connLen)
! 105: return cack;
! 106:
! 107: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_CONNECT, &len, &pos);
! 108: if (!hdr)
! 109: return cack;
! 110: if (len < 12) {
! 111: mqtt_SetErr(EINVAL, "Short message length %d", len);
! 112: return cack;
! 113: } else
! 114: var = (mqtthdr_var_t*) pos;
! 115:
! 116: /* check init string & protocol */
! 117: if (var->var_sb.sb.l == 4 && !strcmp((char*) var->var_data, MQTT_PROTO_STR))
! 118: pos += var->var_sb.sb.l + sizeof(mqtt_len_t);
! 119: else if (var->var_sb.sb.l == 6 || strcmp((char*) var->var_data, MQTT_CONN_STR))
! 120: pos += var->var_sb.sb.l + sizeof(mqtt_len_t);
! 121: else {
! 122: mqtt_SetErr(EINVAL, "Invalid init string %.6s(%d)",
! 123: var->var_data, var->var_sb.sb.l);
! 124: cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
! 125: return cack;
! 126: }
! 127: switch (*pos) {
! 128: case MQTT_PROTO_VER_3:
! 129: case MQTT_PROTO_VER_311:
! 130: case MQTT_PROTO_VER_5:
! 131: pos++;
! 132: break;
! 133: default:
! 134: mqtt_SetErr(EINVAL, "Invalid protocol version %d", *pos);
! 135: cack.retcode = MQTT_RETCODE_REFUSE_VER;
! 136: return cack;
! 137: }
! 138: flg = *(mqtthdr_connflgs_t*) pos;
! 139: pos++;
! 140: ka = (mqtt_len_t*) pos;
! 141: *KASec = ntohs(ka->val);
! 142: pos += sizeof(mqtt_len_t);
! 143:
! 144: len -= pos - (caddr_t) var;
! 145:
! 146: /* get ConnID */
! 147: var = (mqtthdr_var_t*) pos;
! 148: len -= MQTTHDR_VAR_SIZEOF(var);
! 149: if (len < 0 || var->var_sb.sb.l >= MQTT_CONNID_MAX) {
! 150: mqtt_SetErr(EINVAL, "Unexpected EOM at Connection ID %d", len);
! 151: cack.retcode = MQTT_RETCODE_REFUSE_ID;
! 152: return cack;
! 153: } else {
! 154: memset(psConnID, 0, connLen--);
! 155: memcpy(psConnID, var->var_data,
! 156: ntohs(var->var_sb.val) > connLen ? connLen : ntohs(var->var_sb.val));
! 157: pos += MQTTHDR_VAR_SIZEOF(var);
! 158: }
! 159:
! 160: /* get Willz */
! 161: if (flg.will_flg) {
! 162: var = (mqtthdr_var_t*) pos;
! 163: len -= MQTTHDR_VAR_SIZEOF(var);
! 164: if (len < 0) {
! 165: mqtt_SetErr(EINVAL, "Unexpected EOM at Will Topic %d", len);
! 166: cack.retcode = MQTT_RETCODE_REFUSE_ID;
! 167: return cack;
! 168: } else {
! 169: if (psWillTopic) {
! 170: *psWillTopic = e_malloc(ntohs(var->var_sb.val) + 1);
! 171: if (!*psWillTopic) {
! 172: LOGERR;
! 173: cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
! 174: return cack;
! 175: } else
! 176: memset(*psWillTopic, 0, ntohs(var->var_sb.val) + 1);
! 177: memcpy(*psWillTopic, var->var_data, ntohs(var->var_sb.val));
! 178: }
! 179: pos += MQTTHDR_VAR_SIZEOF(var);
! 180: }
! 181:
! 182: var = (mqtthdr_var_t*) pos;
! 183: len -= MQTTHDR_VAR_SIZEOF(var);
! 184: if (len < 0) {
! 185: mqtt_SetErr(EINVAL, "Unexpected EOM at Will Message %d", len);
! 186: e_free(psWillTopic);
! 187: cack.retcode = MQTT_RETCODE_REFUSE_ID;
! 188: return cack;
! 189: } else {
! 190: if (psWillMessage) {
! 191: *psWillMessage = e_malloc(ntohs(var->var_sb.val) + 1);
! 192: if (!*psWillMessage) {
! 193: LOGERR;
! 194: e_free(psWillTopic);
! 195: cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
! 196: return cack;
! 197: } else
! 198: memset(*psWillMessage, 0, ntohs(var->var_sb.val) + 1);
! 199: memcpy(*psWillMessage, var->var_data, ntohs(var->var_sb.val));
! 200: }
! 201: pos += MQTTHDR_VAR_SIZEOF(var);
! 202: }
! 203: }
! 204:
! 205: /* get User/Pass */
! 206: if (flg.username) {
! 207: var = (mqtthdr_var_t*) pos;
! 208: len -= MQTTHDR_VAR_SIZEOF(var);
! 209: if (len < 0 || var->var_sb.sb.l > 12) {
! 210: mqtt_SetErr(EINVAL, "Unexpected EOM at Username %d", len);
! 211: if (flg.will_flg) {
! 212: if (psWillTopic)
! 213: e_free(psWillTopic);
! 214: if (psWillMessage)
! 215: e_free(psWillMessage);
! 216: }
! 217: cack.retcode = MQTT_RETCODE_REFUSE_USERPASS;
! 218: return cack;
! 219: } else {
! 220: if (psUser && userLen) {
! 221: memset(psUser, 0, userLen--);
! 222: memcpy(psUser, var->var_data,
! 223: ntohs(var->var_sb.val) > userLen ? userLen : ntohs(var->var_sb.val));
! 224: }
! 225: pos += MQTTHDR_VAR_SIZEOF(var);
! 226: }
! 227: }
! 228: if (flg.password) {
! 229: var = (mqtthdr_var_t*) pos;
! 230: len -= MQTTHDR_VAR_SIZEOF(var);
! 231: if (len < 0 || var->var_sb.sb.l > 12) {
! 232: mqtt_SetErr(EINVAL, "Unexpected EOM at Password %d", len);
! 233: if (flg.will_flg) {
! 234: if (psWillTopic)
! 235: e_free(psWillTopic);
! 236: if (psWillMessage)
! 237: e_free(psWillMessage);
! 238: }
! 239: cack.retcode = MQTT_RETCODE_REFUSE_USERPASS;
! 240: return cack;
! 241: } else {
! 242: if (psPass && passLen) {
! 243: memset(psPass, 0, passLen--);
! 244: memcpy(psPass, var->var_data,
! 245: ntohs(var->var_sb.val) > passLen ? passLen : ntohs(var->var_sb.val));
! 246: }
! 247: pos += MQTTHDR_VAR_SIZEOF(var);
! 248: }
! 249: }
! 250:
! 251: flg.reserved = 0;
! 252: cack.reserved = flg.flags;
! 253: cack.retcode = MQTT_RETCODE_ACCEPTED;
! 254: return cack;
! 255: }
! 256:
! 257: /*
! 258: * mqtt_readCONNACK() Read CONNACK message
! 259: *
! 260: * @buf = Message buffer
! 261: * return: -1 error or >-1 CONNECT message return code
! 262: */
! 263: u_char
! 264: mqtt_readCONNACK(mqtt_msg_t * __restrict buf)
! 265: {
! 266: int len;
! 267: struct mqtthdr *hdr;
! 268: mqtthdr_connack_t *ack;
! 269: caddr_t pos;
! 270:
! 271: if (!buf || !buf->msg_base || !buf->msg_len)
! 272: return (u_char) -1;
! 273:
! 274: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_CONNACK, &len, &pos);
! 275: if (!hdr)
! 276: return (u_char) -1;
! 277: if (len < sizeof(mqtthdr_connack_t)) {
! 278: mqtt_SetErr(EINVAL, "Short message length %d", len);
! 279: return (u_char) -1;
! 280: } else
! 281: ack = (mqtthdr_connack_t*) pos;
! 282:
! 283: if (ack->retcode > MQTT_RETCODE_DENIED) {
! 284: mqtt_SetErr(EINVAL, "Invalid retcode %u", ack->retcode);
! 285: return (u_char) -1;
! 286: }
! 287:
! 288: return ack->retcode;
! 289: }
! 290:
! 291: /*
! 292: * mqtt_readDISCONNECT() Read DISCONNECT message
! 293: *
! 294: * @buf = Message buffer
! 295: * return: -1 error, 0 ok, >0 undefined result
! 296: */
! 297: int
! 298: mqtt_readDISCONNECT(mqtt_msg_t * __restrict buf)
! 299: {
! 300: int len;
! 301:
! 302: if (!_mqtt_readHEADER(buf, MQTT_TYPE_DISCONNECT, &len, NULL))
! 303: return -1;
! 304:
! 305: return len;
! 306: }
! 307:
! 308: /*
! 309: * mqtt_readPINGREQ() Read PINGREQ message
! 310: *
! 311: * @buf = Message buffer
! 312: * return: -1 error, 0 ok, >0 undefined result
! 313: */
! 314: int
! 315: mqtt_readPINGREQ(mqtt_msg_t * __restrict buf)
! 316: {
! 317: int len;
! 318:
! 319: if (!_mqtt_readHEADER(buf, MQTT_TYPE_PINGREQ, &len, NULL))
! 320: return -1;
! 321:
! 322: return len;
! 323: }
! 324:
! 325: /*
! 326: * mqtt_readPINGRESP() Read PINGRESP message
! 327: *
! 328: * @buf = Message buffer
! 329: * return: -1 error, 0 ok, >0 undefined result
! 330: */
! 331: int
! 332: mqtt_readPINGRESP(mqtt_msg_t * __restrict buf)
! 333: {
! 334: int len;
! 335:
! 336: if (!_mqtt_readHEADER(buf, MQTT_TYPE_PINGRESP, &len, NULL))
! 337: return -1;
! 338:
! 339: return len;
! 340: }
! 341:
! 342: /*
! 343: * mqtt_readPUBLISH() Read PUBLISH message
! 344: *
! 345: * @buf = Message buffer
! 346: * @psTopic = Topic
! 347: * @topicLen = Topic length
! 348: * @msgID = MessageID
! 349: * @pData = Data buffer, may be NULL
! 350: * return: -1 error or !=-1 allocated data buffer length
! 351: */
! 352: int
! 353: mqtt_readPUBLISH(mqtt_msg_t * __restrict buf, char * __restrict psTopic, int topicLen,
! 354: u_short *msgID, void ** __restrict pData)
! 355: {
! 356: int len;
! 357: struct mqtthdr *hdr;
! 358: mqtthdr_var_t *var;
! 359: mqtt_len_t *v;
! 360: caddr_t pos;
! 361:
! 362: if (!buf || !psTopic || !msgID)
! 363: return -1;
! 364:
! 365: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PUBLISH, &len, &pos);
! 366: if (!hdr)
! 367: return -1;
! 368: else
! 369: var = (mqtthdr_var_t*) pos;
! 370:
! 371: /* topic */
! 372: len -= MQTTHDR_VAR_SIZEOF(var);
! 373: if (len < 0) {
! 374: mqtt_SetErr(EINVAL, "Short message length %d", len);
! 375: return -1;
! 376: } else {
! 377: memset(psTopic, 0, topicLen--);
! 378: memcpy(psTopic, var->var_data, ntohs(var->var_sb.val) > topicLen ?
! 379: topicLen : ntohs(var->var_sb.val));
! 380: pos += MQTTHDR_VAR_SIZEOF(var);
! 381: v = (mqtt_len_t*) pos;
! 382: }
! 383:
! 384: len -= sizeof(mqtt_len_t);
! 385: if (len < 0) {
! 386: mqtt_SetErr(EINVAL, "Short message length %d", len);
! 387: return -1;
! 388: } else {
! 389: *msgID = ntohs(v->val);
! 390: pos += sizeof(mqtt_len_t);
! 391: }
! 392:
! 393: /* data */
! 394: if (len < 0) {
! 395: mqtt_SetErr(EINVAL, "Short message length %d", len);
! 396: return -1;
! 397: } else if (pData) {
! 398: if (!(*pData = e_malloc(len + 1))) {
! 399: LOGERR;
! 400: return -1;
! 401: } else
! 402: ((char*) (*pData))[len] = 0;
! 403:
! 404: memcpy(*pData, pos, len);
! 405: }
! 406:
! 407: return len;
! 408: }
! 409:
! 410: /*
! 411: * mqtt_readPUBACK() Read PUBACK message
! 412: *
! 413: * @buf = Message buffer
! 414: * return: -1 error or MessageID
! 415: */
! 416: u_short
! 417: mqtt_readPUBACK(mqtt_msg_t * __restrict buf)
! 418: {
! 419: int len;
! 420: struct mqtthdr *hdr;
! 421: mqtt_len_t *v;
! 422: caddr_t pos;
! 423:
! 424: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PUBACK, &len, &pos);
! 425: if (!hdr)
! 426: return (u_short) -1;
! 427: if (len < sizeof(mqtt_len_t)) {
! 428: mqtt_SetErr(EINVAL, "Short message length %d", len);
! 429: return (u_short) -1;
! 430: } else
! 431: v = (mqtt_len_t*) pos;
! 432:
! 433: return ntohs(v->val);
! 434: }
! 435:
! 436: /*
! 437: * mqtt_readPUBREC() Read PUBREC message
! 438: *
! 439: * @buf = Message buffer
! 440: * return: -1 error or MessageID
! 441: */
! 442: u_short
! 443: mqtt_readPUBREC(mqtt_msg_t * __restrict buf)
! 444: {
! 445: int len;
! 446: struct mqtthdr *hdr;
! 447: mqtt_len_t *v;
! 448: caddr_t pos;
! 449:
! 450: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PUBREC, &len, &pos);
! 451: if (!hdr)
! 452: return (u_short) -1;
! 453: if (len < sizeof(mqtt_len_t)) {
! 454: mqtt_SetErr(EINVAL, "Short message length %d", len);
! 455: return (u_short) -1;
! 456: } else
! 457: v = (mqtt_len_t*) pos;
! 458:
! 459: return ntohs(v->val);
! 460: }
! 461:
! 462: /*
! 463: * mqtt_readPUBREL() Read PUBREL message
! 464: *
! 465: * @buf = Message buffer
! 466: * return: -1 error or MessageID
! 467: */
! 468: u_short
! 469: mqtt_readPUBREL(mqtt_msg_t * __restrict buf)
! 470: {
! 471: int len;
! 472: struct mqtthdr *hdr;
! 473: mqtt_len_t *v;
! 474: caddr_t pos;
! 475:
! 476: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PUBREL, &len, &pos);
! 477: if (!hdr)
! 478: return (u_short) -1;
! 479: if (len < sizeof(mqtt_len_t)) {
! 480: mqtt_SetErr(EINVAL, "Short message length %d", len);
! 481: return (u_short) -1;
! 482: } else
! 483: v = (mqtt_len_t*) pos;
! 484:
! 485: return ntohs(v->val);
! 486: }
! 487:
! 488: /*
! 489: * mqtt_readPUBCOMP() Read PUBCOMP message
! 490: *
! 491: * @buf = Message buffer
! 492: * return: -1 error or MessageID
! 493: */
! 494: u_short
! 495: mqtt_readPUBCOMP(mqtt_msg_t * __restrict buf)
! 496: {
! 497: int len;
! 498: struct mqtthdr *hdr;
! 499: mqtt_len_t *v;
! 500: caddr_t pos;
! 501:
! 502: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PUBCOMP, &len, &pos);
! 503: if (!hdr)
! 504: return (u_short) -1;
! 505: if (len < sizeof(mqtt_len_t)) {
! 506: mqtt_SetErr(EINVAL, "Short message length %d", len);
! 507: return (u_short) -1;
! 508: } else
! 509: v = (mqtt_len_t*) pos;
! 510:
! 511: return ntohs(v->val);
! 512: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>