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

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

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