|
|
| version 1.1.2.5, 2011/11/22 14:13:04 | version 1.2, 2012/01/27 15:05:38 |
|---|---|
| Line 8 | Line 8 |
| * | * |
| * @buf = Message buffer | * @buf = Message buffer |
| * @csConnID = ConnectID | * @csConnID = ConnectID |
| * @kasec = Keep alive timeout | |
| * @csUser = Username if !=NULL | * @csUser = Username if !=NULL |
| * @csPass = Password for Username, only if csUser is set | * @csPass = Password for Username, only if csUser is set |
| * @csWillTopic = Will Topic if !=NULL Will Flags set into message | * @csWillTopic = Will Topic if !=NULL Will Flags set into message |
| Line 19 | Line 20 |
| */ | */ |
| int | int |
| mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const char *csConnID, | mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const char *csConnID, |
| const char *csUser, const char *csPass, | u_short kasec, const char *csUser, const char *csPass, |
| const char *csWillTopic, const char *csWillMessage, | const char *csWillTopic, const char *csWillMessage, |
| u_char ClrSess, u_char WillQOS, u_char WillRetain) | u_char ClrSess, u_char WillQOS, u_char WillRetain) |
| { | { |
| Line 77 mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha | Line 78 mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha |
| /* CONNECT header */ | /* CONNECT header */ |
| flags->clean_sess = ClrSess ? 1 : 0; | flags->clean_sess = ClrSess ? 1 : 0; |
| if (csUser) { | if (csUser && *csUser) { |
| flags->username = 1; | flags->username = 1; |
| flags->password = csPass ? 1 : 0; | flags->password = csPass ? 1 : 0; |
| } else { | } else { |
| flags->username = 0; | flags->username = 0; |
| flags->password = 0; | flags->password = 0; |
| } | } |
| if (csWillTopic) { | if (csWillTopic && *csWillTopic) { |
| flags->will_flg = 1; | flags->will_flg = 1; |
| flags->will_qos = WillQOS; | flags->will_qos = WillQOS; |
| flags->will_retain = WillRetain ? 1 : 0; | flags->will_retain = WillRetain ? 1 : 0; |
| Line 94 mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha | Line 95 mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha |
| flags->will_retain = 0; | flags->will_retain = 0; |
| } | } |
| ka->sb.l = MQTT_KEEPALIVE; | ka->val = kasec ? htons(kasec) : htons(MQTT_KEEPALIVE); |
| /* ConnID */ | /* ConnID */ |
| cid = (mqtthdr_var_t*) (buf->msg_base + siz); | cid = (mqtthdr_var_t*) (buf->msg_base + siz); |
| Line 103 mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha | Line 104 mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha |
| memcpy(cid->var_data, csConnID, ntohs(cid->var_sb.val)); | memcpy(cid->var_data, csConnID, ntohs(cid->var_sb.val)); |
| /* If Will Flags setup */ | /* If Will Flags setup */ |
| if (csWillTopic) { | if (csWillTopic && *csWillTopic) { |
| topic = (mqtthdr_var_t*) (buf->msg_base + siz); | topic = (mqtthdr_var_t*) (buf->msg_base + siz); |
| topic->var_sb.val = htons(strlen(csWillTopic)); | topic->var_sb.val = htons(strlen(csWillTopic)); |
| memcpy(topic->var_data, csWillTopic, ntohs(topic->var_sb.val)); | memcpy(topic->var_data, csWillTopic, ntohs(topic->var_sb.val)); |
| siz += MQTTHDR_VAR_SIZEOF(topic); | siz += MQTTHDR_VAR_SIZEOF(topic); |
| wmsg = (mqtthdr_var_t*) (buf->msg_base + siz); | wmsg = (mqtthdr_var_t*) (buf->msg_base + siz); |
| if (csWillMessage) { | if (csWillMessage && *csWillMessage) { |
| wmsg->var_sb.val = htons(strlen(csWillMessage)); | wmsg->var_sb.val = htons(strlen(csWillMessage)); |
| memcpy(wmsg->var_data, csWillMessage, ntohs(wmsg->var_sb.val)); | memcpy(wmsg->var_data, csWillMessage, ntohs(wmsg->var_sb.val)); |
| } else | } else |
| Line 119 mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha | Line 120 mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const cha |
| } | } |
| /* If defined Username & Password */ | /* If defined Username & Password */ |
| if (csUser) { | if (csUser && *csUser) { |
| user = (mqtthdr_var_t*) (buf->msg_base + siz); | user = (mqtthdr_var_t*) (buf->msg_base + siz); |
| user->var_sb.val = htons(strlen(csUser)); | user->var_sb.val = htons(strlen(csUser)); |
| memcpy(user->var_data, csUser, ntohs(user->var_sb.val)); | memcpy(user->var_data, csUser, ntohs(user->var_sb.val)); |
| siz += MQTTHDR_VAR_SIZEOF(user); | siz += MQTTHDR_VAR_SIZEOF(user); |
| if (csPass) { | if (csPass && *csPass) { |
| pass = (mqtthdr_var_t*) (buf->msg_base + siz); | pass = (mqtthdr_var_t*) (buf->msg_base + siz); |
| pass->var_sb.val = htons(strlen(csPass)); | pass->var_sb.val = htons(strlen(csPass)); |
| memcpy(pass->var_data, csPass, ntohs(pass->var_sb.val)); | memcpy(pass->var_data, csPass, ntohs(pass->var_sb.val)); |
| Line 238 int | Line 239 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 || var->var_sb.sb.l > 23) { | |
| 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 || var->var_sb.sb.l > 12) { | |
| 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 || var->var_sb.sb.l > 12) { | |
| 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; | |
| } | } |