Annotation of mqtt/src/conn.c, revision 1.2

1.2     ! misho       1: #include "global.h"
        !             2: 
        !             3: 
        !             4: /* ------------------------------------------------------------------- */
        !             5: 
        !             6: /*
        !             7:  * mqtt_msgCONNECT() Create CONNECT message
        !             8:  *
        !             9:  * @buf = Message buffer
        !            10:  * @csConnID = ConnectID
        !            11:  * @kasec = Keep alive timeout
        !            12:  * @csUser = Username if !=NULL
        !            13:  * @csPass = Password for Username, only if csUser is set
        !            14:  * @csWillTopic = Will Topic if !=NULL Will Flags set into message
        !            15:  * @csWillMessage = Will Message, may be NULL
        !            16:  * @ClrSess = Clear Session subscriptions after disconnect
        !            17:  * @WillQOS = Will QOS if csWillTopic is set
        !            18:  * @WillRetain = Will Retain Will Message if csWillTopic is set
        !            19:  * return: -1 error or >-1 message size for send
        !            20:  */
        !            21: int
        !            22: mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const char *csConnID, 
        !            23:                u_short kasec, const char *csUser, const char *csPass, 
        !            24:                const char *csWillTopic, const char *csWillMessage, 
        !            25:                u_char ClrSess, u_char WillQOS, u_char WillRetain)
        !            26: {
        !            27:        int siz = 0;
        !            28:        struct mqtthdr *hdr;
        !            29:        mqtthdr_var_t *var, *cid, *topic, *wmsg, *user, *pass;
        !            30:        mqtthdr_protover_t *proto;
        !            31:        mqtthdr_connflgs_t *flags;
        !            32:        mqtt_v_t *ka;
        !            33: 
        !            34:        if (!buf || !csConnID)
        !            35:                return -1;
        !            36:        if (strlen(csConnID) > 23) {
        !            37:                mqtt_SetErr(EINVAL, "Error:: invalid argument ConnID is too long (max 23 bytes)");
        !            38:                return -1;
        !            39:        }
        !            40:        if (csUser && strlen(csUser) > 12) {
        !            41:                mqtt_SetErr(EINVAL, "Error:: invalid argument Username is too long (max 12 bytes)");
        !            42:                return -1;
        !            43:        }
        !            44:        if (csPass && strlen(csPass) > 12) {
        !            45:                mqtt_SetErr(EINVAL, "Error:: invalid argument Password is too long (max 12 bytes)");
        !            46:                return -1;
        !            47:        }
        !            48:        if (WillQOS > MQTT_QOS_EXACTLY) {
        !            49:                mqtt_SetErr(EINVAL, "Error:: invalid argument WillQOS - unknown QOS value");
        !            50:                return -1;
        !            51:        }
        !            52: 
        !            53:        if (mqtt_msgRealloc(buf, BUFSIZ) == -1)
        !            54:                return -1;
        !            55:        else {
        !            56:                hdr = (struct mqtthdr *) (buf->msg_base + siz);
        !            57:                siz += sizeof(struct mqtthdr);
        !            58:                var = (mqtthdr_var_t*) (buf->msg_base + siz);
        !            59:                siz += 8;
        !            60:                proto = buf->msg_base + siz;
        !            61:                siz++;
        !            62:                flags = (mqtthdr_connflgs_t*) (buf->msg_base + siz);
        !            63:                siz++;
        !            64:                ka = (mqtt_v_t*) (buf->msg_base + siz);
        !            65:                siz += sizeof(mqtt_v_t);
        !            66:        }
        !            67: 
        !            68:        /* fixed header */
        !            69:        MQTTHDR_MSGINIT(hdr);
        !            70:        hdr->mqtt_msg.type = MQTT_TYPE_CONNECT;
        !            71:        *hdr->mqtt_len = 0;
        !            72: 
        !            73:        /* variable header */
        !            74:        var->var_sb.sb.l = 6;
        !            75:        memcpy(var->var_data, MQTT_CONN_STR, 6);
        !            76: 
        !            77:        *proto = MQTT_PROTO_VER;
        !            78: 
        !            79:        /* CONNECT header */
        !            80:        flags->clean_sess = ClrSess ? 1 : 0;
        !            81:        if (csUser && *csUser) {
        !            82:                flags->username = 1;
        !            83:                flags->password = csPass ? 1 : 0;
        !            84:        } else {
        !            85:                flags->username = 0;
        !            86:                flags->password = 0;
        !            87:        }
        !            88:        if (csWillTopic && *csWillTopic) {
        !            89:                flags->will_flg = 1;
        !            90:                flags->will_qos = WillQOS;
        !            91:                flags->will_retain = WillRetain ? 1 : 0;
        !            92:        } else {
        !            93:                flags->will_flg = 0;
        !            94:                flags->will_qos = 0;
        !            95:                flags->will_retain = 0;
        !            96:        }
        !            97: 
        !            98:        ka->val = kasec ? htons(kasec) : htons(MQTT_KEEPALIVE);
        !            99: 
        !           100:        /* ConnID */
        !           101:        cid = (mqtthdr_var_t*) (buf->msg_base + siz);
        !           102:        cid->var_sb.val = htons(strlen(csConnID));
        !           103:        siz += MQTTHDR_VAR_SIZEOF(cid);
        !           104:        memcpy(cid->var_data, csConnID, ntohs(cid->var_sb.val));
        !           105: 
        !           106:        /* If Will Flags setup */
        !           107:        if (csWillTopic && *csWillTopic) {
        !           108:                topic = (mqtthdr_var_t*) (buf->msg_base + siz);
        !           109:                topic->var_sb.val = htons(strlen(csWillTopic));
        !           110:                memcpy(topic->var_data, csWillTopic, ntohs(topic->var_sb.val));
        !           111:                siz += MQTTHDR_VAR_SIZEOF(topic);
        !           112: 
        !           113:                wmsg = (mqtthdr_var_t*) (buf->msg_base + siz);
        !           114:                if (csWillMessage && *csWillMessage) {
        !           115:                        wmsg->var_sb.val = htons(strlen(csWillMessage));
        !           116:                        memcpy(wmsg->var_data, csWillMessage, ntohs(wmsg->var_sb.val));
        !           117:                } else
        !           118:                        wmsg->var_sb.val = 0;
        !           119:                siz += MQTTHDR_VAR_SIZEOF(wmsg);
        !           120:        }
        !           121: 
        !           122:        /* If defined Username & Password */
        !           123:        if (csUser && *csUser) {
        !           124:                user = (mqtthdr_var_t*) (buf->msg_base + siz);
        !           125:                user->var_sb.val = htons(strlen(csUser));
        !           126:                memcpy(user->var_data, csUser, ntohs(user->var_sb.val));
        !           127:                siz += MQTTHDR_VAR_SIZEOF(user);
        !           128: 
        !           129:                if (csPass && *csPass) {
        !           130:                        pass = (mqtthdr_var_t*) (buf->msg_base + siz);
        !           131:                        pass->var_sb.val = htons(strlen(csPass));
        !           132:                        memcpy(pass->var_data, csPass, ntohs(pass->var_sb.val));
        !           133:                        siz += MQTTHDR_VAR_SIZEOF(pass);
        !           134:                }
        !           135:        }
        !           136: 
        !           137:        *hdr->mqtt_len = mqtt_encodeLen(siz - sizeof(struct mqtthdr));
        !           138:        mqtt_msgRealloc(buf, siz);
        !           139:        return siz;
        !           140: }
        !           141: 
        !           142: /*
        !           143:  * mqtt_msgCONNACK() Create CONNACK message
        !           144:  *
        !           145:  * @buf = Message buffer
        !           146:  * @retcode = Return code
        !           147:  * return: -1 error or >-1 message size for send
        !           148:  */
        !           149: int
        !           150: mqtt_msgCONNACK(mqtt_msg_t * __restrict buf, u_char retcode)
        !           151: {
        !           152:        int siz = 0;
        !           153:        struct mqtthdr *hdr;
        !           154:        mqtthdr_connack_t *ack;
        !           155: 
        !           156:        if (!buf)
        !           157:                return -1;
        !           158:        if (retcode > MQTT_RETCODE_DENIED) {
        !           159:                mqtt_SetErr(EINVAL, "Error:: invalid retcode");
        !           160:                return -1;
        !           161:        }
        !           162: 
        !           163:        if (mqtt_msgRealloc(buf, sizeof(struct mqtthdr) + sizeof(mqtthdr_connack_t)) == -1)
        !           164:                return -1;
        !           165:        else {
        !           166:                hdr = (struct mqtthdr *) (buf->msg_base + siz);
        !           167:                siz += sizeof(struct mqtthdr);
        !           168:                ack = (mqtthdr_connack_t*) (buf->msg_base + siz);
        !           169:                siz += sizeof(mqtthdr_connack_t);
        !           170:        }
        !           171: 
        !           172:        /* fixed header */
        !           173:        MQTTHDR_MSGINIT(hdr);
        !           174:        hdr->mqtt_msg.type = MQTT_TYPE_CONNACK;
        !           175:        *hdr->mqtt_len = sizeof(mqtthdr_connack_t);
        !           176: 
        !           177:        /* CONNACK header */
        !           178:        ack->reserved = 0;
        !           179:        ack->retcode = retcode;
        !           180: 
        !           181:        return siz;
        !           182: }
        !           183: 
        !           184: static int
        !           185: _mqtt_msgSIMPLE_(mqtt_msg_t * __restrict buf, u_char cmd)
        !           186: {
        !           187:        int siz = 0;
        !           188:        struct mqtthdr *hdr;
        !           189: 
        !           190:        if (!buf)
        !           191:                return -1;
        !           192: 
        !           193:        if (mqtt_msgRealloc(buf, sizeof(struct mqtthdr)) == -1)
        !           194:                return -1;
        !           195:        else {
        !           196:                hdr = (struct mqtthdr *) (buf->msg_base + siz);
        !           197:                siz += sizeof(struct mqtthdr);
        !           198:        }
        !           199: 
        !           200:        /* fixed header */
        !           201:        MQTTHDR_MSGINIT(hdr);
        !           202:        hdr->mqtt_msg.type = cmd;
        !           203:        *hdr->mqtt_len = 0;
        !           204: 
        !           205:        return siz;
        !           206: }
        !           207: 
        !           208: /*
        !           209:  * mqtt_msgPINGREQ() Create PINGREQ message
        !           210:  *
        !           211:  * @buf = Message buffer
        !           212:  * return: -1 error or >-1 message size for send
        !           213:  */
        !           214: int
        !           215: mqtt_msgPINGREQ(mqtt_msg_t * __restrict buf)
        !           216: {
        !           217:        return _mqtt_msgSIMPLE_(buf, MQTT_TYPE_PINGREQ);
        !           218: }
        !           219: 
        !           220: /*
        !           221:  * mqtt_msgPINGRESP() Create PINGRESP message
        !           222:  *
        !           223:  * @buf = Message buffer
        !           224:  * return: -1 error or >-1 message size for send
        !           225:  */
        !           226: int
        !           227: mqtt_msgPINGRESP(mqtt_msg_t * __restrict buf)
        !           228: {
        !           229:        return _mqtt_msgSIMPLE_(buf, MQTT_TYPE_PINGRESP);
        !           230: }
        !           231: 
        !           232: /*
        !           233:  * mqtt_msgDISCONNECT() Create DISCONNECT message
        !           234:  *
        !           235:  * @buf = Message buffer
        !           236:  * return: -1 error or >-1 message size for send
        !           237:  */
        !           238: int
        !           239: mqtt_msgDISCONNECT(mqtt_msg_t * __restrict buf)
        !           240: {
        !           241:        return _mqtt_msgSIMPLE_(buf, MQTT_TYPE_DISCONNECT);
        !           242: }
        !           243: 
        !           244: /* ============= decode ============ */
        !           245: 
        !           246: /*
        !           247:  * mqtt_readCONNECT() Read elements from CONNECT message
        !           248:  *
        !           249:  * @buf = Message buffer
        !           250:  * @kasec = Keep Alive in seconds for current connection
        !           251:  * @psConnID = ConnectID
        !           252:  * @connLen = ConnectID length
        !           253:  * @psUser = Username if !=NULL
        !           254:  * @userLen = Username length
        !           255:  * @psPass = Password for Username, only if csUser is set
        !           256:  * @passLen = Password length
        !           257:  * @psWillTopic = Will Topic if !=NULL Will Flags set into message and must be free()
        !           258:  * @psWillMessage = Will Message, may be NULL if !NULL must be free() after use!
        !           259:  * return: .reserved == 1 is error or == 0 connection flags & msg ok
        !           260:  */
        !           261: mqtthdr_connack_t
        !           262: mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short *kasec, char * __restrict psConnID, int connLen, 
        !           263:                char * __restrict psUser, int userLen, char * __restrict psPass, int passLen,  
        !           264:                char ** __restrict psWillTopic, char ** __restrict psWillMessage)
        !           265: {
        !           266:        mqtthdr_connflgs_t flg = { MQTT_CONNFLGS_INIT };
        !           267:        mqtthdr_connack_t cack = { 1, MQTT_RETCODE_DENIED };
        !           268:        struct mqtthdr *hdr;
        !           269:        mqtthdr_var_t *var;
        !           270:        mqtt_v_t *ka;
        !           271:        mqtthdr_protover_t *proto;
        !           272:        int len, ret;
        !           273:        caddr_t pos;
        !           274: 
        !           275:        if (!buf || !buf->msg_base || !buf->msg_len || !psConnID || !connLen)
        !           276:                return cack;
        !           277: 
        !           278:        hdr = _mqtt_readHEADER(buf, MQTT_TYPE_CONNECT, &ret, &len);
        !           279:        if (!hdr)
        !           280:                return cack;
        !           281:        if (len < 12) {
        !           282:                mqtt_SetErr(EINVAL, "Error:: short message length %d", len);
        !           283:                return cack;
        !           284:        } else {
        !           285:                pos = buf->msg_base + ret + 1;
        !           286:                var = (mqtthdr_var_t*) pos;
        !           287:        }
        !           288:        /* check init string & protocol */
        !           289:        if (var->var_sb.sb.l != 6 || strncmp((char*) var->var_data, MQTT_CONN_STR, 6)) {
        !           290:                mqtt_SetErr(EINVAL, "Error:: invalid init string %.6s(%d)", 
        !           291:                                var->var_data, var->var_sb.sb.l);
        !           292:                cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
        !           293:                return cack;
        !           294:        } else {
        !           295:                pos += var->var_sb.sb.l + sizeof(mqtt_v_t);
        !           296:                proto = (mqtthdr_protover_t*) pos;
        !           297:        }
        !           298:        if (*proto != MQTT_PROTO_VER) {
        !           299:                mqtt_SetErr(EINVAL, "Error:: invalid protocol version %d", *pos);
        !           300:                cack.retcode = MQTT_RETCODE_REFUSE_VER;
        !           301:                return cack;
        !           302:        } else
        !           303:                pos++;
        !           304:        flg = *(mqtthdr_connflgs_t*) pos;
        !           305:        pos++;
        !           306:        ka = (mqtt_v_t*) pos;
        !           307:        *kasec = ntohs(ka->val);
        !           308:        pos += sizeof(mqtt_v_t);
        !           309: 
        !           310:        len -= pos - (caddr_t) var;
        !           311: 
        !           312:        /* get ConnID */
        !           313:        var = (mqtthdr_var_t*) pos;
        !           314:        len -= MQTTHDR_VAR_SIZEOF(var);
        !           315:        if (len < 0 || var->var_sb.sb.l > 23) {
        !           316:                mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Connection ID %d", len);
        !           317:                cack.retcode = MQTT_RETCODE_REFUSE_ID;
        !           318:                return cack;
        !           319:        } else {
        !           320:                memset(psConnID, 0, connLen--);
        !           321:                memcpy(psConnID, var->var_data, ntohs(var->var_sb.val) > connLen ? connLen : ntohs(var->var_sb.val));
        !           322:                pos += MQTTHDR_VAR_SIZEOF(var);
        !           323:        }
        !           324: 
        !           325:        /* get Willz */
        !           326:        if (flg.will_flg) {
        !           327:                var = (mqtthdr_var_t*) pos;
        !           328:                len -= MQTTHDR_VAR_SIZEOF(var);
        !           329:                if (len < 0) {
        !           330:                        mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Will Topic %d", len);
        !           331:                        cack.retcode = MQTT_RETCODE_REFUSE_ID;
        !           332:                        return cack;
        !           333:                } else {
        !           334:                        if (psWillTopic) {
        !           335:                                *psWillTopic = malloc(ntohs(var->var_sb.val) + 1);
        !           336:                                if (!*psWillTopic) {
        !           337:                                        LOGERR;
        !           338:                                        cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
        !           339:                                        return cack;
        !           340:                                } else
        !           341:                                        memset(*psWillTopic, 0, ntohs(var->var_sb.val) + 1);
        !           342:                                memcpy(*psWillTopic, var->var_data, ntohs(var->var_sb.val));
        !           343:                        }
        !           344:                        pos += MQTTHDR_VAR_SIZEOF(var);
        !           345:                }
        !           346: 
        !           347:                var = (mqtthdr_var_t*) pos;
        !           348:                len -= MQTTHDR_VAR_SIZEOF(var);
        !           349:                if (len < 0) {
        !           350:                        mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Will Message %d", len);
        !           351:                        cack.retcode = MQTT_RETCODE_REFUSE_ID;
        !           352:                        return cack;
        !           353:                } else {
        !           354:                        if (psWillMessage) {
        !           355:                                *psWillMessage = malloc(ntohs(var->var_sb.val) + 1);
        !           356:                                if (!*psWillMessage) {
        !           357:                                        LOGERR;
        !           358:                                        cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
        !           359:                                        return cack;
        !           360:                                } else
        !           361:                                        memset(*psWillMessage, 0, ntohs(var->var_sb.val) + 1);
        !           362:                                memcpy(*psWillMessage, var->var_data, ntohs(var->var_sb.val));
        !           363:                        }
        !           364:                        pos += MQTTHDR_VAR_SIZEOF(var);
        !           365:                }
        !           366:        }
        !           367: 
        !           368:        /* get User/Pass */
        !           369:        if (flg.username) {
        !           370:                var = (mqtthdr_var_t*) pos;
        !           371:                len -= MQTTHDR_VAR_SIZEOF(var);
        !           372:                if (len < 0 || var->var_sb.sb.l > 12) {
        !           373:                        mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Username %d", len);
        !           374:                        cack.retcode = MQTT_RETCODE_REFUSE_USERPASS;
        !           375:                        return cack;
        !           376:                } else {
        !           377:                        if (psUser && userLen) {
        !           378:                                memset(psUser, 0, userLen--);
        !           379:                                memcpy(psUser, var->var_data, 
        !           380:                                                ntohs(var->var_sb.val) > userLen ? userLen : ntohs(var->var_sb.val));
        !           381:                        }
        !           382:                        pos += MQTTHDR_VAR_SIZEOF(var);
        !           383:                }
        !           384:        }
        !           385:        if (flg.password) {
        !           386:                var = (mqtthdr_var_t*) pos;
        !           387:                len -= MQTTHDR_VAR_SIZEOF(var);
        !           388:                if (len < 0 || var->var_sb.sb.l > 12) {
        !           389:                        mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Password %d", len);
        !           390:                        cack.retcode = MQTT_RETCODE_REFUSE_USERPASS;
        !           391:                        return cack;
        !           392:                } else {
        !           393:                        if (psPass && passLen) {
        !           394:                                memset(psPass, 0, passLen--);
        !           395:                                memcpy(psPass, var->var_data, 
        !           396:                                                ntohs(var->var_sb.val) > passLen ? passLen : ntohs(var->var_sb.val));
        !           397:                        }
        !           398:                        pos += MQTTHDR_VAR_SIZEOF(var);
        !           399:                }
        !           400:        }
        !           401: 
        !           402:        flg.reserved = 0;
        !           403:        cack.reserved = flg.flags;
        !           404:        cack.retcode = MQTT_RETCODE_ACCEPTED;
        !           405:        return cack;
        !           406: }
        !           407: 
        !           408: /*
        !           409:  * mqtt_readCONNACK() Read CONNACK message
        !           410:  *
        !           411:  * @buf = Message buffer
        !           412:  * return: -1 error or >-1 CONNECT message return code
        !           413:  */
        !           414: u_char
        !           415: mqtt_readCONNACK(mqtt_msg_t * __restrict buf)
        !           416: {
        !           417:        int len, ret;
        !           418:        struct mqtthdr *hdr;
        !           419:        mqtthdr_connack_t *ack;
        !           420:        caddr_t pos;
        !           421: 
        !           422:        if (!buf || !buf->msg_base || !buf->msg_len)
        !           423:                return (u_char) -1;
        !           424: 
        !           425:        hdr = _mqtt_readHEADER(buf, MQTT_TYPE_CONNACK, &ret, &len);
        !           426:        if (!hdr)
        !           427:                return (u_char) -1;
        !           428:        if (len < sizeof(mqtthdr_connack_t)) {
        !           429:                mqtt_SetErr(EINVAL, "Error:: short message length %d", len);
        !           430:                return (u_char) -1;
        !           431:        } else {
        !           432:                pos = buf->msg_base + ret + 1;
        !           433:                ack = (mqtthdr_connack_t*) pos;
        !           434:        }
        !           435: 
        !           436:        if (ack->retcode > MQTT_RETCODE_DENIED) {
        !           437:                mqtt_SetErr(EINVAL, "Error:: invalid retcode %u", ack->retcode);
        !           438:                return (u_char) -1;
        !           439:        }
        !           440: 
        !           441:        return ack->retcode;
        !           442: }
        !           443: 
        !           444: /*
        !           445:  * mqtt_readDISCONNECT() Read DISCONNECT message
        !           446:  *
        !           447:  * @buf = Message buffer
        !           448:  * return: -1 error, 0 ok, >0 undefined result
        !           449:  */
        !           450: int
        !           451: mqtt_readDISCONNECT(mqtt_msg_t * __restrict buf)
        !           452: {
        !           453:        int len, ret;
        !           454:        struct mqtthdr *hdr;
        !           455: 
        !           456:        hdr = _mqtt_readHEADER(buf, MQTT_TYPE_DISCONNECT, &ret, &len);
        !           457:        if (!hdr || ret != 1)
        !           458:                return -1;
        !           459: 
        !           460:        return len;
        !           461: }
        !           462: 
        !           463: /*
        !           464:  * mqtt_readPINGREQ() Read PINGREQ message
        !           465:  *
        !           466:  * @buf = Message buffer
        !           467:  * return: -1 error, 0 ok, >0 undefined result
        !           468:  */
        !           469: int
        !           470: mqtt_readPINGREQ(mqtt_msg_t * __restrict buf)
        !           471: {
        !           472:        int len, ret;
        !           473:        struct mqtthdr *hdr;
        !           474: 
        !           475:        hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PINGREQ, &ret, &len);
        !           476:        if (!hdr || ret != 1)
        !           477:                return -1;
        !           478: 
        !           479:        return len;
        !           480: }
        !           481: 
        !           482: /*
        !           483:  * mqtt_readPINGRESP() Read PINGRESP message
        !           484:  *
        !           485:  * @buf = Message buffer
        !           486:  * return: -1 error, 0 ok, >0 undefined result
        !           487:  */
        !           488: int
        !           489: mqtt_readPINGRESP(mqtt_msg_t * __restrict buf)
        !           490: {
        !           491:        int len, ret;
        !           492:        struct mqtthdr *hdr;
        !           493: 
        !           494:        hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PINGRESP, &ret, &len);
        !           495:        if (!hdr || ret != 1)
        !           496:                return -1;
        !           497: 
        !           498:        return len;
        !           499: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>