| version 1.1.2.5, 2011/11/22 14:13:04 | version 1.1.2.13, 2011/12/13 10:12:36 | 
| Line 32  mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha | Line 32  mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha | 
 |  |  | 
 | if (!buf || !csConnID) | if (!buf || !csConnID) | 
 | return -1; | return -1; | 
| if (strlen(csConnID) > 23) { | if (strlen(csConnID) > 24) { | 
 | mqtt_SetErr(EINVAL, "Error:: invalid argument ConnID is too long (max 23 bytes)"); | mqtt_SetErr(EINVAL, "Error:: invalid argument ConnID is too long (max 23 bytes)"); | 
 | return -1; | 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)"); | mqtt_SetErr(EINVAL, "Error:: invalid argument Username is too long (max 12 bytes)"); | 
 | return -1; | 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)"); | mqtt_SetErr(EINVAL, "Error:: invalid argument Password is too long (max 12 bytes)"); | 
 | return -1; | return -1; | 
 | } | } | 
| Line 238  int | Line 238  int | 
 | mqtt_msgDISCONNECT(mqtt_msg_t * __restrict buf) | mqtt_msgDISCONNECT(mqtt_msg_t * __restrict buf) | 
 | { | { | 
 | return _mqtt_msgSIMPLE_(buf, MQTT_TYPE_DISCONNECT); | 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; | 
 | } | } |