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>