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; |
} |
} |