Skip to content

Commit 0829b19

Browse files
lkainohedeshianaws
authored andcommitted
MQTT: Fixed MQTT header constructing and parsing
Bit fields must not be used in communication protocol frame parsing. See http://stackoverflow.com/questions/1490092/c-c-force-bit-field-order-and-alignment. The bit-fields used in AWS C library caused issues in PowerPC target I'm using. This might not be the most beautiful way to fix it, but it works. Tested on x86 and PowerPC architectures. fixes #59
1 parent 316107b commit 0829b19

File tree

5 files changed

+50
-53
lines changed

5 files changed

+50
-53
lines changed

include/aws_iot_mqtt_client_common_internal.h

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -69,26 +69,17 @@ typedef enum msgTypes {
6969
DISCONNECT = 14
7070
} MessageTypes;
7171

72+
/* Macros for parsing header fields from incoming MQTT frame. */
73+
#define MQTT_HEADER_FIELD_TYPE(_byte) ((_byte >> 4) & 0x0F)
74+
#define MQTT_HEADER_FIELD_DUP(_byte) ((_byte & (1 << 3)) >> 3)
75+
#define MQTT_HEADER_FIELD_QOS(_byte) ((_byte & (3 << 1)) >> 1)
76+
#define MQTT_HEADER_FIELD_RETAIN(_byte) ((_byte & (1 << 0)) >> 0)
77+
7278
/**
7379
* Bitfields for the MQTT header byte.
7480
*/
7581
typedef union {
7682
unsigned char byte; /**< the whole byte */
77-
#if defined(REVERSED)
78-
struct {
79-
unsigned int type : 4; /**< message type nibble */
80-
unsigned int dup : 1; /**< DUP flag bit */
81-
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
82-
unsigned int retain : 1; /**< retained flag bit */
83-
} bits;
84-
#else
85-
struct {
86-
unsigned int retain : 1; /**< retained flag bit */
87-
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
88-
unsigned int dup : 1; /**< DUP flag bit */
89-
unsigned int type : 4; /**< message type nibble */
90-
} bits;
91-
#endif
9283
} MQTTHeader;
9384

9485
IoT_Error_t aws_iot_mqtt_internal_init_header(MQTTHeader *pHeader, MessageTypes message_type,

src/aws_iot_mqtt_client_common_internal.c

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -194,72 +194,73 @@ IoT_Error_t aws_iot_mqtt_internal_init_header(MQTTHeader *pHeader, MessageTypes
194194

195195
/* Set all bits to zero */
196196
pHeader->byte = 0;
197+
uint8_t type = 0;
197198
switch(message_type) {
198199
case UNKNOWN:
199200
/* Should never happen */
200201
return FAILURE;
201202
case CONNECT:
202-
pHeader->bits.type = 0x01;
203+
type = 0x01;
203204
break;
204205
case CONNACK:
205-
pHeader->bits.type = 0x02;
206+
type = 0x02;
206207
break;
207208
case PUBLISH:
208-
pHeader->bits.type = 0x03;
209+
type = 0x03;
209210
break;
210211
case PUBACK:
211-
pHeader->bits.type = 0x04;
212+
type = 0x04;
212213
break;
213214
case PUBREC:
214-
pHeader->bits.type = 0x05;
215+
type = 0x05;
215216
break;
216217
case PUBREL:
217-
pHeader->bits.type = 0x06;
218+
type = 0x06;
218219
break;
219220
case PUBCOMP:
220-
pHeader->bits.type = 0x07;
221+
type = 0x07;
221222
break;
222223
case SUBSCRIBE:
223-
pHeader->bits.type = 0x08;
224+
type = 0x08;
224225
break;
225226
case SUBACK:
226-
pHeader->bits.type = 0x09;
227+
type = 0x09;
227228
break;
228229
case UNSUBSCRIBE:
229-
pHeader->bits.type = 0x0A;
230+
type = 0x0A;
230231
break;
231232
case UNSUBACK:
232-
pHeader->bits.type = 0x0B;
233+
type = 0x0B;
233234
break;
234235
case PINGREQ:
235-
pHeader->bits.type = 0x0C;
236+
type = 0x0C;
236237
break;
237238
case PINGRESP:
238-
pHeader->bits.type = 0x0D;
239+
type = 0x0D;
239240
break;
240241
case DISCONNECT:
241-
pHeader->bits.type = 0x0E;
242+
type = 0x0E;
242243
break;
243244
default:
244245
/* Should never happen */
245246
FUNC_EXIT_RC(FAILURE);
246247
}
247248

248-
pHeader->bits.dup = (1 == dup) ? 0x01 : 0x00;
249+
pHeader->byte = type << 4;
250+
pHeader->byte |= dup << 3;
251+
249252
switch(qos) {
250253
case QOS0:
251-
pHeader->bits.qos = 0x00;
252254
break;
253255
case QOS1:
254-
pHeader->bits.qos = 0x01;
256+
pHeader->byte |= 1 << 1;
255257
break;
256258
default:
257259
/* Using QOS0 as default */
258-
pHeader->bits.qos = 0x00;
259260
break;
260261
}
261262

262-
pHeader->bits.retain = (1 == retained) ? 0x01 : 0x00;
263+
pHeader->byte |= (1 == retained) ? 0x01 : 0x00;
263264

264265
FUNC_EXIT_RC(SUCCESS);
265266
}
@@ -414,7 +415,7 @@ static IoT_Error_t _aws_iot_mqtt_internal_read_packet(AWS_IoT_Client *pClient, T
414415
}
415416

416417
header.byte = pClient->clientData.readBuf[0];
417-
*pPacketType = header.bits.type;
418+
*pPacketType = MQTT_HEADER_FIELD_TYPE(header.byte);
418419

419420
FUNC_EXIT_RC(rc);
420421
}

src/aws_iot_mqtt_client_connect.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -194,19 +194,24 @@ static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t
194194
//}
195195

196196
flags.all = 0;
197-
flags.bits.cleansession = (pConnectParams->isCleanSession) ? 1 : 0;
198-
flags.bits.will = (pConnectParams->isWillMsgPresent) ? 1 : 0;
199-
if(flags.bits.will) {
200-
flags.bits.willQoS = pConnectParams->will.qos;
201-
flags.bits.willRetain = (pConnectParams->will.isRetained) ? 1 : 0;
197+
if (pConnectParams->isCleanSession)
198+
{
199+
flags.all |= 1 << 1;
202200
}
203201

204-
if(pConnectParams->pUsername) {
205-
flags.bits.username = 1;
202+
if (pConnectParams->isWillMsgPresent)
203+
{
204+
flags.all |= 1 << 2;
205+
flags.all |= pConnectParams->will.qos << 3;
206+
flags.all |= pConnectParams->will.isRetained << 5;
206207
}
207208

208209
if(pConnectParams->pPassword) {
209-
flags.bits.password = 1;
210+
flags.all |= 1 << 6;
211+
}
212+
213+
if(pConnectParams->pUsername) {
214+
flags.all |= 1 << 7;
210215
}
211216

212217
aws_iot_mqtt_internal_write_char(&ptr, flags.all);
@@ -225,11 +230,11 @@ static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t
225230
aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pMessage, pConnectParams->will.msgLen);
226231
}
227232

228-
if(flags.bits.username) {
233+
if(pConnectParams->pUsername) {
229234
aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pUsername, pConnectParams->usernameLen);
230235
}
231236

232-
if(flags.bits.password) {
237+
if(pConnectParams->pPassword) {
233238
aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pPassword, pConnectParams->passwordLen);
234239
}
235240

@@ -274,7 +279,7 @@ static IoT_Error_t _aws_iot_mqtt_deserialize_connack(unsigned char *pSessionPres
274279
readBytesLen = 0;
275280

276281
header.byte = aws_iot_mqtt_internal_read_char(&curdata);
277-
if(CONNACK != header.bits.type) {
282+
if(CONNACK != MQTT_HEADER_FIELD_TYPE(header.byte)) {
278283
FUNC_EXIT_RC(FAILURE);
279284
}
280285

src/aws_iot_mqtt_client_publish.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,13 +338,13 @@ IoT_Error_t aws_iot_mqtt_internal_deserialize_publish(uint8_t *dup, QoS *qos,
338338
}
339339

340340
header.byte = aws_iot_mqtt_internal_read_char(&curData);
341-
if(PUBLISH != header.bits.type) {
341+
if(PUBLISH != MQTT_HEADER_FIELD_TYPE(header.byte)) {
342342
FUNC_EXIT_RC(FAILURE);
343343
}
344344

345-
*dup = header.bits.dup;
346-
*qos = (QoS) header.bits.qos;
347-
*retained = header.bits.retain;
345+
*dup = MQTT_HEADER_FIELD_DUP(header.byte);
346+
*qos = (QoS) MQTT_HEADER_FIELD_QOS(header.byte);
347+
*retained = MQTT_HEADER_FIELD_RETAIN(header.byte);
348348

349349
/* read remaining length */
350350
rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curData, &decodedLen, &readBytesLen);
@@ -404,8 +404,8 @@ IoT_Error_t aws_iot_mqtt_internal_deserialize_ack(unsigned char *pPacketType, un
404404

405405

406406
header.byte = aws_iot_mqtt_internal_read_char(&curdata);
407-
*dup = header.bits.dup;
408-
*pPacketType = header.bits.type;
407+
*dup = MQTT_HEADER_FIELD_DUP(header.byte);
408+
*pPacketType = MQTT_HEADER_FIELD_TYPE(header.byte);
409409

410410
/* read remaining length */
411411
rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen);

src/aws_iot_mqtt_client_subscribe.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ static IoT_Error_t _aws_iot_mqtt_deserialize_suback(uint16_t *pPacketId, uint32_
140140
}
141141

142142
header.byte = aws_iot_mqtt_internal_read_char(&curData);
143-
if(SUBACK != header.bits.type) {
143+
if(SUBACK != MQTT_HEADER_FIELD_TYPE(header.byte)) {
144144
FUNC_EXIT_RC(FAILURE);
145145
}
146146

0 commit comments

Comments
 (0)