--- mqtt/src/Attic/conn.c 2011/11/22 14:13:04 1.1.2.5 +++ mqtt/src/Attic/conn.c 2011/12/13 10:12:36 1.1.2.13 @@ -32,15 +32,15 @@ mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha if (!buf || !csConnID) return -1; - if (strlen(csConnID) > 23) { + if (strlen(csConnID) > 24) { mqtt_SetErr(EINVAL, "Error:: invalid argument ConnID is too long (max 23 bytes)"); return -1; } - if (csUser && strlen(csUser) > 12) { + if (csUser && strlen(csUser) > 13) { mqtt_SetErr(EINVAL, "Error:: invalid argument Username is too long (max 12 bytes)"); return -1; } - if (csPass && strlen(csPass) > 12) { + if (csPass && strlen(csPass) > 13) { mqtt_SetErr(EINVAL, "Error:: invalid argument Password is too long (max 12 bytes)"); return -1; } @@ -238,4 +238,261 @@ int mqtt_msgDISCONNECT(mqtt_msg_t * __restrict buf) { return _mqtt_msgSIMPLE_(buf, MQTT_TYPE_DISCONNECT); +} + +/* ============= decode ============ */ + +/* + * mqtt_readCONNECT() Read elements from CONNECT message + * + * @buf = Message buffer + * @kasec = Keep Alive in seconds for current connection + * @psConnID = ConnectID + * @connLen = ConnectID length + * @psUser = Username if !=NULL + * @userLen = Username length + * @psPass = Password for Username, only if csUser is set + * @passLen = Password length + * @psWillTopic = Will Topic if !=NULL Will Flags set into message and must be free() + * @psWillMessage = Will Message, may be NULL if !NULL must be free() after use! + * return: .reserved == 1 is error or == 0 connection flags & msg ok + */ +mqtthdr_connack_t +mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short *kasec, char * __restrict psConnID, int connLen, + char * __restrict psUser, int userLen, char * __restrict psPass, int passLen, + char ** __restrict psWillTopic, char ** __restrict psWillMessage) +{ + mqtthdr_connflgs_t flg = { MQTT_CONNFLGS_INIT }; + mqtthdr_connack_t cack = { 1, MQTT_RETCODE_DENIED }; + struct mqtthdr *hdr; + mqtthdr_var_t *var; + mqtt_v_t *ka; + mqtthdr_protover_t *proto; + int len, ret; + caddr_t pos; + + if (!buf || !buf->msg_base || !buf->msg_len || !psConnID || !connLen) + return cack; + + hdr = _mqtt_readHEADER(buf, MQTT_TYPE_CONNECT, &ret, &len); + if (!hdr) + return cack; + if (len < 12) { + mqtt_SetErr(EINVAL, "Error:: short message length %d", len); + return cack; + } else { + pos = buf->msg_base + ret + 1; + var = (mqtthdr_var_t*) pos; + } + /* check init string & protocol */ + if (var->var_sb.sb.l != 6 || strncmp((char*) var->var_data, MQTT_CONN_STR, 6)) { + mqtt_SetErr(EINVAL, "Error:: invalid init string %.6s(%d)", + var->var_data, var->var_sb.sb.l); + cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL; + return cack; + } else { + pos += var->var_sb.sb.l + sizeof(mqtt_v_t); + proto = (mqtthdr_protover_t*) pos; + } + if (*proto != MQTT_PROTO_VER) { + mqtt_SetErr(EINVAL, "Error:: invalid protocol version %d", *pos); + cack.retcode = MQTT_RETCODE_REFUSE_VER; + return cack; + } else + pos++; + flg = *(mqtthdr_connflgs_t*) pos; + pos++; + ka = (mqtt_v_t*) pos; + *kasec = ntohs(ka->val); + pos += sizeof(mqtt_v_t); + + len -= pos - (caddr_t) var; + + /* get ConnID */ + var = (mqtthdr_var_t*) pos; + len -= MQTTHDR_VAR_SIZEOF(var); + if (len < 0) { + mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Connection ID %d", len); + cack.retcode = MQTT_RETCODE_REFUSE_ID; + return cack; + } else { + memset(psConnID, 0, connLen--); + memcpy(psConnID, var->var_data, ntohs(var->var_sb.val) > connLen ? connLen : ntohs(var->var_sb.val)); + pos += MQTTHDR_VAR_SIZEOF(var); + } + + /* get Willz */ + if (flg.will_flg) { + var = (mqtthdr_var_t*) pos; + len -= MQTTHDR_VAR_SIZEOF(var); + if (len < 0) { + mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Will Topic %d", len); + cack.retcode = MQTT_RETCODE_REFUSE_ID; + return cack; + } else { + if (psWillTopic) { + *psWillTopic = malloc(ntohs(var->var_sb.val) + 1); + if (!*psWillTopic) { + LOGERR; + cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL; + return cack; + } else + memset(*psWillTopic, 0, ntohs(var->var_sb.val) + 1); + memcpy(*psWillTopic, var->var_data, ntohs(var->var_sb.val)); + } + pos += MQTTHDR_VAR_SIZEOF(var); + } + + var = (mqtthdr_var_t*) pos; + len -= MQTTHDR_VAR_SIZEOF(var); + if (len < 0) { + mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Will Message %d", len); + cack.retcode = MQTT_RETCODE_REFUSE_ID; + return cack; + } else { + if (psWillMessage) { + *psWillMessage = malloc(ntohs(var->var_sb.val) + 1); + if (!*psWillMessage) { + LOGERR; + cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL; + return cack; + } else + memset(*psWillMessage, 0, ntohs(var->var_sb.val) + 1); + memcpy(*psWillMessage, var->var_data, ntohs(var->var_sb.val)); + } + pos += MQTTHDR_VAR_SIZEOF(var); + } + } + + /* get User/Pass */ + if (flg.username) { + var = (mqtthdr_var_t*) pos; + len -= MQTTHDR_VAR_SIZEOF(var); + if (len < 0) { + mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Username %d", len); + cack.retcode = MQTT_RETCODE_REFUSE_USERPASS; + return cack; + } else { + if (psUser && userLen) { + memset(psUser, 0, userLen--); + memcpy(psUser, var->var_data, + ntohs(var->var_sb.val) > userLen ? userLen : ntohs(var->var_sb.val)); + } + pos += MQTTHDR_VAR_SIZEOF(var); + } + } + if (flg.password) { + var = (mqtthdr_var_t*) pos; + len -= MQTTHDR_VAR_SIZEOF(var); + if (len < 0) { + mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Password %d", len); + cack.retcode = MQTT_RETCODE_REFUSE_USERPASS; + return cack; + } else { + if (psPass && passLen) { + memset(psPass, 0, passLen--); + memcpy(psPass, var->var_data, + ntohs(var->var_sb.val) > passLen ? passLen : ntohs(var->var_sb.val)); + } + pos += MQTTHDR_VAR_SIZEOF(var); + } + } + + flg.reserved = 0; + cack.reserved = flg.flags; + cack.retcode = MQTT_RETCODE_ACCEPTED; + return cack; +} + +/* + * mqtt_readCONNACK() Read CONNACK message + * + * @buf = Message buffer + * return: -1 error or >-1 CONNECT message return code + */ +u_char +mqtt_readCONNACK(mqtt_msg_t * __restrict buf) +{ + int len, ret; + struct mqtthdr *hdr; + mqtthdr_connack_t *ack; + caddr_t pos; + + if (!buf || !buf->msg_base || !buf->msg_len) + return (u_char) -1; + + hdr = _mqtt_readHEADER(buf, MQTT_TYPE_CONNACK, &ret, &len); + if (!hdr) + return (u_char) -1; + if (len < sizeof(mqtthdr_connack_t)) { + mqtt_SetErr(EINVAL, "Error:: short message length %d", len); + return (u_char) -1; + } else { + pos = buf->msg_base + ret + 1; + ack = (mqtthdr_connack_t*) pos; + } + + if (ack->retcode > MQTT_RETCODE_DENIED) { + mqtt_SetErr(EINVAL, "Error:: invalid retcode %u", ack->retcode); + return (u_char) -1; + } + + return ack->retcode; +} + +/* + * mqtt_readDISCONNECT() Read DISCONNECT message + * + * @buf = Message buffer + * return: -1 error, 0 ok, >0 undefined result + */ +int +mqtt_readDISCONNECT(mqtt_msg_t * __restrict buf) +{ + int len, ret; + struct mqtthdr *hdr; + + hdr = _mqtt_readHEADER(buf, MQTT_TYPE_DISCONNECT, &ret, &len); + if (!hdr || ret != 1) + return -1; + + return len; +} + +/* + * mqtt_readPINGREQ() Read PINGREQ message + * + * @buf = Message buffer + * return: -1 error, 0 ok, >0 undefined result + */ +int +mqtt_readPINGREQ(mqtt_msg_t * __restrict buf) +{ + int len, ret; + struct mqtthdr *hdr; + + hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PINGREQ, &ret, &len); + if (!hdr || ret != 1) + return -1; + + return len; +} + +/* + * mqtt_readPINGRESP() Read PINGRESP message + * + * @buf = Message buffer + * return: -1 error, 0 ok, >0 undefined result + */ +int +mqtt_readPINGRESP(mqtt_msg_t * __restrict buf) +{ + int len, ret; + struct mqtthdr *hdr; + + hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PINGRESP, &ret, &len); + if (!hdr || ret != 1) + return -1; + + return len; }