зеркало из https://github.com/Azure/azure-umqtt-c.git
Add extra error checking on incoming PUBLISH
This commit is contained in:
Родитель
f8936af0cd
Коммит
0ccca7964c
|
@ -9,7 +9,6 @@ set -e
|
|||
cat /etc/*release | grep VERSION*
|
||||
gcc --version
|
||||
openssl version
|
||||
curl --version
|
||||
|
||||
script_dir=$(cd "$(dirname "$0")" && pwd)
|
||||
build_root=$(cd "${script_dir}/.." && pwd)
|
||||
|
|
|
@ -120,10 +120,10 @@ static STRING_HANDLE construct_trace_log_handle(MQTT_CLIENT* mqtt_client)
|
|||
return trace_log;
|
||||
}
|
||||
|
||||
static uint16_t byteutil_read_uint16(uint8_t** buffer, size_t len)
|
||||
static uint16_t byteutil_read_uint16(uint8_t** buffer, size_t byteLen)
|
||||
{
|
||||
uint16_t result = 0;
|
||||
if (buffer != NULL && *buffer != NULL && len >= 2)
|
||||
if (buffer != NULL && *buffer != NULL && byteLen >= 2)
|
||||
{
|
||||
result = 256 * (**buffer) + (*(*buffer + 1));
|
||||
*buffer += 2; // Move the ptr
|
||||
|
@ -138,29 +138,28 @@ static uint16_t byteutil_read_uint16(uint8_t** buffer, size_t len)
|
|||
static char* byteutil_readUTF(uint8_t** buffer, size_t* byteLen)
|
||||
{
|
||||
char* result = NULL;
|
||||
if (buffer != NULL)
|
||||
|
||||
const uint8_t* bufferInitial = *buffer;
|
||||
// Get the length of the string
|
||||
uint16_t stringLen = byteutil_read_uint16(buffer, *byteLen);
|
||||
// Verify that byteutil_read_uint16 succeeded (by stringLen>0) and that we're
|
||||
// not being asked to read a string longer than buffer passed in.
|
||||
if ((stringLen > 0) && ((size_t)(stringLen + (*buffer - bufferInitial)) <= *byteLen))
|
||||
{
|
||||
// Get the length of the string
|
||||
uint16_t len = byteutil_read_uint16(buffer, *byteLen);
|
||||
if (len > 0)
|
||||
result = (char*)malloc(stringLen + 1);
|
||||
if (result != NULL)
|
||||
{
|
||||
result = (char*)malloc(len + 1);
|
||||
if (result != NULL)
|
||||
{
|
||||
(void)memcpy(result, *buffer, len);
|
||||
result[len] = '\0';
|
||||
*buffer += len;
|
||||
if (byteLen != NULL)
|
||||
{
|
||||
*byteLen = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
(void)memcpy(result, *buffer, stringLen);
|
||||
result[stringLen] = '\0';
|
||||
*buffer += stringLen;
|
||||
*byteLen = stringLen;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("readByte buffer == NULL.");
|
||||
LogError("String passed not a valid UTF.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -304,7 +303,7 @@ static void logIncomingRawTrace(MQTT_CLIENT* mqtt_client, CONTROL_PACKET_TYPE pa
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // ENABLE_RAW_TRACE
|
||||
|
||||
static void log_outgoing_trace(MQTT_CLIENT* mqtt_client, STRING_HANDLE trace_log)
|
||||
{
|
||||
|
@ -325,8 +324,7 @@ static void log_incoming_trace(MQTT_CLIENT* mqtt_client, STRING_HANDLE trace_log
|
|||
LOG(AZ_LOG_TRACE, LOG_LINE, "<- %s %s", tmBuffer, STRING_c_str(trace_log) );
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifdef ENABLE_RAW_TRACE
|
||||
#else // NO_LOGGING
|
||||
static void logOutgoingRawTrace(MQTT_CLIENT* mqtt_client, const uint8_t* data, size_t length)
|
||||
{
|
||||
AZURE_UNREFERENCED_PARAMETER(mqtt_client);
|
||||
|
@ -339,7 +337,6 @@ static void log_outgoing_trace(MQTT_CLIENT* mqtt_client, STRING_HANDLE trace_log
|
|||
AZURE_UNREFERENCED_PARAMETER(mqtt_client);
|
||||
AZURE_UNREFERENCED_PARAMETER(trace_log);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void log_incoming_trace(MQTT_CLIENT* mqtt_client, STRING_HANDLE trace_log)
|
||||
{
|
||||
|
@ -603,23 +600,131 @@ static int cloneMqttOptions(MQTT_CLIENT* mqtt_client, const MQTT_CLIENT_OPTIONS*
|
|||
return result;
|
||||
}
|
||||
|
||||
static void ProcessPublishMessage(MQTT_CLIENT* mqtt_client, uint8_t* initialPos, size_t packetLength, int flags)
|
||||
{
|
||||
bool isDuplicateMsg = (flags & DUPLICATE_FLAG_MASK) ? true : false;
|
||||
bool isRetainMsg = (flags & RETAIN_FLAG_MASK) ? true : false;
|
||||
QOS_VALUE qosValue = (flags == 0) ? DELIVER_AT_MOST_ONCE : (flags & QOS_LEAST_ONCE_FLAG_MASK) ? DELIVER_AT_LEAST_ONCE : DELIVER_EXACTLY_ONCE;
|
||||
|
||||
uint8_t* iterator = initialPos;
|
||||
size_t numberOfBytesToBeRead = packetLength;
|
||||
size_t lengthOfTopicName = numberOfBytesToBeRead;
|
||||
char* topicName = byteutil_readUTF(&iterator, &lengthOfTopicName);
|
||||
if (topicName == NULL)
|
||||
{
|
||||
LogError("Publish MSG: failure reading topic name");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_PARSE_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
STRING_HANDLE trace_log = NULL;
|
||||
|
||||
#ifndef NO_LOGGING
|
||||
if (mqtt_client->logTrace)
|
||||
{
|
||||
trace_log = STRING_construct_sprintf("PUBLISH | IS_DUP: %s | RETAIN: %d | QOS: %s | TOPIC_NAME: %s", isDuplicateMsg ? TRUE_CONST : FALSE_CONST,
|
||||
isRetainMsg ? 1 : 0, ENUM_TO_STRING(QOS_VALUE, qosValue), topicName);
|
||||
}
|
||||
#endif
|
||||
uint16_t packetId = 0;
|
||||
numberOfBytesToBeRead = packetLength - (iterator - initialPos);
|
||||
if (qosValue != DELIVER_AT_MOST_ONCE)
|
||||
{
|
||||
packetId = byteutil_read_uint16(&iterator, numberOfBytesToBeRead);
|
||||
#ifndef NO_LOGGING
|
||||
if (mqtt_client->logTrace)
|
||||
{
|
||||
STRING_sprintf(trace_log, " | PACKET_ID: %"PRIu16, packetId);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if ((qosValue != DELIVER_AT_MOST_ONCE) && (packetId == 0))
|
||||
{
|
||||
LogError("Publish MSG: packetId=0, invalid");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_PARSE_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
numberOfBytesToBeRead = packetLength - (iterator - initialPos);
|
||||
|
||||
MQTT_MESSAGE_HANDLE msgHandle = mqttmessage_create_in_place(packetId, topicName, qosValue, iterator, numberOfBytesToBeRead);
|
||||
if (msgHandle == NULL)
|
||||
{
|
||||
LogError("failure in mqttmessage_create");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
|
||||
}
|
||||
else if (mqttmessage_setIsDuplicateMsg(msgHandle, isDuplicateMsg) != 0 ||
|
||||
mqttmessage_setIsRetained(msgHandle, isRetainMsg) != 0)
|
||||
{
|
||||
LogError("failure setting mqtt message property");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NO_LOGGING
|
||||
if (mqtt_client->logTrace)
|
||||
{
|
||||
STRING_sprintf(trace_log, " | PAYLOAD_LEN: %zu", numberOfBytesToBeRead);
|
||||
log_incoming_trace(mqtt_client, trace_log);
|
||||
}
|
||||
#endif
|
||||
mqtt_client->fnMessageRecv(msgHandle, mqtt_client->ctx);
|
||||
|
||||
BUFFER_HANDLE pubRel = NULL;
|
||||
if (qosValue == DELIVER_EXACTLY_ONCE)
|
||||
{
|
||||
pubRel = mqtt_codec_publishReceived(packetId);
|
||||
if (pubRel == NULL)
|
||||
{
|
||||
LogError("Failed to allocate publish receive message.");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
|
||||
}
|
||||
}
|
||||
else if (qosValue == DELIVER_AT_LEAST_ONCE)
|
||||
{
|
||||
pubRel = mqtt_codec_publishAck(packetId);
|
||||
if (pubRel == NULL)
|
||||
{
|
||||
LogError("Failed to allocate publish ack message.");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
|
||||
}
|
||||
}
|
||||
if (pubRel != NULL)
|
||||
{
|
||||
size_t size = BUFFER_length(pubRel);
|
||||
(void)sendPacketItem(mqtt_client, BUFFER_u_char(pubRel), size);
|
||||
BUFFER_delete(pubRel);
|
||||
}
|
||||
}
|
||||
mqttmessage_destroy(msgHandle);
|
||||
}
|
||||
|
||||
if (trace_log != NULL)
|
||||
{
|
||||
STRING_delete(trace_log);
|
||||
}
|
||||
|
||||
free(topicName);
|
||||
}
|
||||
}
|
||||
|
||||
static void recvCompleteCallback(void* context, CONTROL_PACKET_TYPE packet, int flags, BUFFER_HANDLE headerData)
|
||||
{
|
||||
MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
|
||||
if (mqtt_client != NULL)
|
||||
{
|
||||
size_t len = 0;
|
||||
size_t packetLength = 0;
|
||||
uint8_t* iterator = NULL;
|
||||
if (headerData != NULL)
|
||||
{
|
||||
len = BUFFER_length(headerData);
|
||||
packetLength = BUFFER_length(headerData);
|
||||
iterator = BUFFER_u_char(headerData);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_RAW_TRACE
|
||||
logIncomingRawTrace(mqtt_client, packet, (uint8_t)flags, iterator, len);
|
||||
logIncomingRawTrace(mqtt_client, packet, (uint8_t)flags, iterator, packetLength);
|
||||
#endif
|
||||
if ((iterator != NULL && len > 0) || packet == PINGRESP_TYPE)
|
||||
if ((iterator != NULL && packetLength > 0) || packet == PINGRESP_TYPE)
|
||||
{
|
||||
switch (packet)
|
||||
{
|
||||
|
@ -651,107 +756,7 @@ static void recvCompleteCallback(void* context, CONTROL_PACKET_TYPE packet, int
|
|||
}
|
||||
case PUBLISH_TYPE:
|
||||
{
|
||||
bool isDuplicateMsg = (flags & DUPLICATE_FLAG_MASK) ? true : false;
|
||||
bool isRetainMsg = (flags & RETAIN_FLAG_MASK) ? true : false;
|
||||
QOS_VALUE qosValue = (flags == 0) ? DELIVER_AT_MOST_ONCE : (flags & QOS_LEAST_ONCE_FLAG_MASK) ? DELIVER_AT_LEAST_ONCE : DELIVER_EXACTLY_ONCE;
|
||||
|
||||
uint8_t* initialPos = iterator;
|
||||
size_t length = len - (iterator - initialPos);
|
||||
char* topicName = byteutil_readUTF(&iterator, &length);
|
||||
if (topicName == NULL)
|
||||
{
|
||||
LogError("Publish MSG: failure reading topic name");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_PARSE_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
STRING_HANDLE trace_log = NULL;
|
||||
|
||||
#ifndef NO_LOGGING
|
||||
if (mqtt_client->logTrace)
|
||||
{
|
||||
trace_log = STRING_construct_sprintf("PUBLISH | IS_DUP: %s | RETAIN: %d | QOS: %s | TOPIC_NAME: %s", isDuplicateMsg ? TRUE_CONST : FALSE_CONST,
|
||||
isRetainMsg ? 1 : 0, ENUM_TO_STRING(QOS_VALUE, qosValue), topicName);
|
||||
}
|
||||
#endif
|
||||
uint16_t packetId = 0;
|
||||
length = len - (iterator - initialPos);
|
||||
if (qosValue != DELIVER_AT_MOST_ONCE)
|
||||
{
|
||||
packetId = byteutil_read_uint16(&iterator, length);
|
||||
#ifndef NO_LOGGING
|
||||
if (mqtt_client->logTrace)
|
||||
{
|
||||
STRING_sprintf(trace_log, " | PACKET_ID: %"PRIu16, packetId);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
length = len - (iterator - initialPos);
|
||||
|
||||
MQTT_MESSAGE_HANDLE msgHandle = mqttmessage_create_in_place(packetId, topicName, qosValue, iterator, length);
|
||||
if (msgHandle == NULL)
|
||||
{
|
||||
LogError("failure in mqttmessage_create");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
|
||||
if (trace_log != NULL)
|
||||
{
|
||||
STRING_delete(trace_log);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mqttmessage_setIsDuplicateMsg(msgHandle, isDuplicateMsg) != 0 ||
|
||||
mqttmessage_setIsRetained(msgHandle, isRetainMsg) != 0)
|
||||
{
|
||||
LogError("failure setting mqtt message property");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
|
||||
if (trace_log != NULL)
|
||||
{
|
||||
STRING_delete(trace_log);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NO_LOGGING
|
||||
if (mqtt_client->logTrace)
|
||||
{
|
||||
STRING_sprintf(trace_log, " | PAYLOAD_LEN: %zu", length);
|
||||
log_incoming_trace(mqtt_client, trace_log);
|
||||
STRING_delete(trace_log);
|
||||
}
|
||||
#endif
|
||||
mqtt_client->fnMessageRecv(msgHandle, mqtt_client->ctx);
|
||||
|
||||
BUFFER_HANDLE pubRel = NULL;
|
||||
if (qosValue == DELIVER_EXACTLY_ONCE)
|
||||
{
|
||||
pubRel = mqtt_codec_publishReceived(packetId);
|
||||
if (pubRel == NULL)
|
||||
{
|
||||
LogError("Failed to allocate publish receive message.");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
|
||||
}
|
||||
}
|
||||
else if (qosValue == DELIVER_AT_LEAST_ONCE)
|
||||
{
|
||||
pubRel = mqtt_codec_publishAck(packetId);
|
||||
if (pubRel == NULL)
|
||||
{
|
||||
LogError("Failed to allocate publish ack message.");
|
||||
set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
|
||||
}
|
||||
}
|
||||
if (pubRel != NULL)
|
||||
{
|
||||
size_t size = BUFFER_length(pubRel);
|
||||
(void)sendPacketItem(mqtt_client, BUFFER_u_char(pubRel), size);
|
||||
BUFFER_delete(pubRel);
|
||||
}
|
||||
}
|
||||
mqttmessage_destroy(msgHandle);
|
||||
}
|
||||
free(topicName);
|
||||
}
|
||||
ProcessPublishMessage(mqtt_client, iterator, packetLength, flags);
|
||||
break;
|
||||
}
|
||||
case PUBACK_TYPE:
|
||||
|
@ -765,7 +770,7 @@ static void recvCompleteCallback(void* context, CONTROL_PACKET_TYPE packet, int
|
|||
(packet == PUBREL_TYPE) ? MQTT_CLIENT_ON_PUBLISH_REL : MQTT_CLIENT_ON_PUBLISH_COMP;
|
||||
|
||||
PUBLISH_ACK publish_ack = { 0 };
|
||||
publish_ack.packetId = byteutil_read_uint16(&iterator, len);
|
||||
publish_ack.packetId = byteutil_read_uint16(&iterator, packetLength);
|
||||
|
||||
#ifndef NO_LOGGING
|
||||
if (mqtt_client->logTrace)
|
||||
|
@ -811,8 +816,8 @@ static void recvCompleteCallback(void* context, CONTROL_PACKET_TYPE packet, int
|
|||
/*Codes_SRS_MQTT_CLIENT_07_030: [If the actionResult parameter is of type SUBACK_TYPE then the msgInfo value shall be a SUBSCRIBE_ACK structure.]*/
|
||||
SUBSCRIBE_ACK suback = { 0 };
|
||||
|
||||
size_t remainLen = len;
|
||||
suback.packetId = byteutil_read_uint16(&iterator, len);
|
||||
size_t remainLen = packetLength;
|
||||
suback.packetId = byteutil_read_uint16(&iterator, packetLength);
|
||||
remainLen -= 2;
|
||||
|
||||
#ifndef NO_LOGGING
|
||||
|
@ -862,7 +867,7 @@ static void recvCompleteCallback(void* context, CONTROL_PACKET_TYPE packet, int
|
|||
{
|
||||
/*Codes_SRS_MQTT_CLIENT_07_031: [If the actionResult parameter is of type UNSUBACK_TYPE then the msgInfo value shall be a UNSUBSCRIBE_ACK structure.]*/
|
||||
UNSUBSCRIBE_ACK unsuback = { 0 };
|
||||
unsuback.packetId = byteutil_read_uint16(&iterator, len);
|
||||
unsuback.packetId = byteutil_read_uint16(&iterator, packetLength);
|
||||
|
||||
#ifndef NO_LOGGING
|
||||
if (mqtt_client->logTrace)
|
||||
|
|
|
@ -2285,6 +2285,47 @@ TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_AT_LEAST_ONCE_succeeds)
|
|||
mqtt_client_deinit(mqttHandle);
|
||||
}
|
||||
|
||||
/*Test_SRS_MQTT_CLIENT_07_029: [If the actionResult parameter are of types PUBACK_TYPE, PUBREC_TYPE, PUBREL_TYPE or PUBCOMP_TYPE then the msgInfo value shall be a PUBLISH_ACK structure.]*/
|
||||
TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_AT_LEAST_ONCE_no_body_succeeds)
|
||||
{
|
||||
// arrange
|
||||
// Packet contains a topic name, PacketID, but no body. This is legal mqtt for AT_LEAST_ONCE PUBLISH.
|
||||
unsigned char PUBLISH_RESP[] = { 0x00, 0x0a, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x34 };
|
||||
size_t length = sizeof(PUBLISH_RESP) / sizeof(PUBLISH_RESP[0]);
|
||||
|
||||
uint8_t flag = 0x0a;
|
||||
|
||||
MQTT_CLIENT_HANDLE mqttHandle = mqtt_client_init(TestRecvCallback, TestOpCallback, (void*)&PUBLISH_RESP, TestErrorCallback, NULL);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
BUFFER_HANDLE publish_handle = TEST_BUFFER_HANDLE;
|
||||
STRICT_EXPECTED_CALL(BUFFER_length(TEST_BUFFER_HANDLE)).SetReturn(length);
|
||||
STRICT_EXPECTED_CALL(BUFFER_u_char(TEST_BUFFER_HANDLE)).SetReturn(PUBLISH_RESP);
|
||||
EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_create_in_place(TEST_PACKET_ID, IGNORED_PTR_ARG, DELIVER_AT_LEAST_ONCE, IGNORED_PTR_ARG, 0));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_setIsDuplicateMsg(IGNORED_PTR_ARG, true));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_setIsRetained(IGNORED_PTR_ARG, false));
|
||||
STRICT_EXPECTED_CALL(mqtt_codec_publishAck(TEST_PACKET_ID));
|
||||
EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG));
|
||||
EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(tickcounter_get_current_ms(TEST_COUNTER_HANDLE, IGNORED_PTR_ARG)).IgnoreArgument(2);
|
||||
EXPECTED_CALL(xio_send(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG));
|
||||
EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_destroy(IGNORED_PTR_ARG));
|
||||
EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
|
||||
// act
|
||||
g_packetComplete(mqttHandle, PUBLISH_TYPE, flag, publish_handle);
|
||||
|
||||
// assert
|
||||
ASSERT_IS_TRUE(g_msgRecvCallbackInvoked);
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
|
||||
// cleanup
|
||||
mqtt_client_deinit(mqttHandle);
|
||||
}
|
||||
|
||||
|
||||
/*Test_SRS_MQTT_CLIENT_07_029: [If the actionResult parameter are of types PUBACK_TYPE, PUBREC_TYPE, PUBREL_TYPE or PUBCOMP_TYPE then the msgInfo value shall be a PUBLISH_ACK structure.]*/
|
||||
TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_AT_MOST_ONCE_succeeds)
|
||||
{
|
||||
|
@ -2318,6 +2359,74 @@ TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_AT_MOST_ONCE_succeeds)
|
|||
mqtt_client_deinit(mqttHandle);
|
||||
}
|
||||
|
||||
/*Test_SRS_MQTT_CLIENT_07_029: [If the actionResult parameter are of types PUBACK_TYPE, PUBREC_TYPE, PUBREL_TYPE or PUBCOMP_TYPE then the msgInfo value shall be a PUBLISH_ACK structure.]*/
|
||||
TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_AT_MOST_ONCE_with_two_zeros_body_data_succeeds)
|
||||
{
|
||||
// arrange
|
||||
// This is legal publish. The 0x00 0x00 would be illegal PacketID if we were using PacketID's, which AT_MOST_ONCE does not.
|
||||
unsigned char PUBLISH_VALUE[] = { 0x00, 0x04, 0x6d, 0x73, 0x67, 0x41, 0x00, 0x00 };
|
||||
size_t length = sizeof(PUBLISH_VALUE) / sizeof(PUBLISH_VALUE[0]);
|
||||
|
||||
uint8_t flag = 0x00;
|
||||
|
||||
MQTT_CLIENT_HANDLE mqttHandle = mqtt_client_init(TestRecvCallback, TestOpCallback, (void*)&PUBLISH_VALUE, TestErrorCallback, NULL);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
BUFFER_HANDLE publish_handle = TEST_BUFFER_HANDLE;
|
||||
STRICT_EXPECTED_CALL(BUFFER_length(TEST_BUFFER_HANDLE)).SetReturn(length);
|
||||
STRICT_EXPECTED_CALL(BUFFER_u_char(TEST_BUFFER_HANDLE)).SetReturn(PUBLISH_VALUE);
|
||||
EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_create_in_place(0, IGNORED_PTR_ARG, DELIVER_AT_MOST_ONCE, IGNORED_PTR_ARG, 2));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_setIsDuplicateMsg(IGNORED_PTR_ARG, false));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_setIsRetained(IGNORED_PTR_ARG, false));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_destroy(IGNORED_PTR_ARG));
|
||||
EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
|
||||
// act
|
||||
g_packetComplete(mqttHandle, PUBLISH_TYPE, flag, publish_handle);
|
||||
|
||||
// assert
|
||||
ASSERT_IS_TRUE(g_msgRecvCallbackInvoked);
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
|
||||
// cleanup
|
||||
mqtt_client_deinit(mqttHandle);
|
||||
}
|
||||
|
||||
TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_AT_MOST_ONCE_no_body_succeeds)
|
||||
{
|
||||
// arrange
|
||||
// The topic name is the only data sent; no follow on packet ID or body. This is legaly.
|
||||
unsigned char PUBLISH_VALUE[] = { 0x00, 0x04, 0x6d, 0x73, 0x67, 0x41 };
|
||||
size_t length = sizeof(PUBLISH_VALUE) / sizeof(PUBLISH_VALUE[0]);
|
||||
|
||||
uint8_t flag = 0x00;
|
||||
|
||||
MQTT_CLIENT_HANDLE mqttHandle = mqtt_client_init(TestRecvCallback, TestOpCallback, (void*)&PUBLISH_VALUE, TestErrorCallback, NULL);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
BUFFER_HANDLE publish_handle = TEST_BUFFER_HANDLE;
|
||||
STRICT_EXPECTED_CALL(BUFFER_length(TEST_BUFFER_HANDLE)).SetReturn(length);
|
||||
STRICT_EXPECTED_CALL(BUFFER_u_char(TEST_BUFFER_HANDLE)).SetReturn(PUBLISH_VALUE);
|
||||
EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_create_in_place(0, IGNORED_PTR_ARG, DELIVER_AT_MOST_ONCE, IGNORED_PTR_ARG, 0));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_setIsDuplicateMsg(IGNORED_PTR_ARG, false));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_setIsRetained(IGNORED_PTR_ARG, false));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_destroy(IGNORED_PTR_ARG));
|
||||
EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
|
||||
// act
|
||||
g_packetComplete(mqttHandle, PUBLISH_TYPE, flag, publish_handle);
|
||||
|
||||
// assert
|
||||
ASSERT_IS_TRUE(g_msgRecvCallbackInvoked);
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
|
||||
// cleanup
|
||||
mqtt_client_deinit(mqttHandle);
|
||||
}
|
||||
|
||||
|
||||
/*Test_SRS_MQTT_CLIENT_07_029: [If the actionResult parameter are of types PUBACK_TYPE, PUBREC_TYPE, PUBREL_TYPE or PUBCOMP_TYPE then the msgInfo value shall be a PUBLISH_ACK structure.]*/
|
||||
TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_ACK_succeeds)
|
||||
{
|
||||
|
@ -2530,6 +2639,121 @@ TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_COMPLETE_succeeds)
|
|||
mqtt_client_deinit(mqttHandle);
|
||||
}
|
||||
|
||||
|
||||
TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_too_long_topic_name_length_fails)
|
||||
{
|
||||
// arrange
|
||||
unsigned char PUBLISH_RESP[] = { 0x00, 0x01}; // Topic length is 1, but there is not a byte following
|
||||
size_t length = sizeof(PUBLISH_RESP) / sizeof(PUBLISH_RESP[0]);
|
||||
|
||||
uint8_t flag = 0x0d;
|
||||
|
||||
MQTT_CLIENT_HANDLE mqttHandle = mqtt_client_init(TestRecvCallback, TestOpCallback, (void*)&PUBLISH_RESP, TestErrorCallback, NULL);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
BUFFER_HANDLE publish_handle = TEST_BUFFER_HANDLE;
|
||||
STRICT_EXPECTED_CALL(BUFFER_length(TEST_BUFFER_HANDLE)).SetReturn(length);
|
||||
STRICT_EXPECTED_CALL(BUFFER_u_char(TEST_BUFFER_HANDLE)).SetReturn(PUBLISH_RESP);
|
||||
|
||||
// act
|
||||
g_packetComplete(mqttHandle, PUBLISH_TYPE, flag, publish_handle);
|
||||
|
||||
// assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_IS_TRUE(g_errorCallbackInvoked);
|
||||
ASSERT_IS_FALSE(g_msgRecvCallbackInvoked);
|
||||
|
||||
// cleanup
|
||||
mqtt_client_deinit(mqttHandle);
|
||||
}
|
||||
|
||||
TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_invalid_topic_name_length_fails)
|
||||
{
|
||||
// arrange
|
||||
unsigned char PUBLISH_RESP[] = { 0x00 }; // Topic length needs to contain at least two bytes
|
||||
size_t length = sizeof(PUBLISH_RESP) / sizeof(PUBLISH_RESP[0]);
|
||||
|
||||
uint8_t flag = 0x0d;
|
||||
|
||||
MQTT_CLIENT_HANDLE mqttHandle = mqtt_client_init(TestRecvCallback, TestOpCallback, (void*)&PUBLISH_RESP, TestErrorCallback, NULL);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
BUFFER_HANDLE publish_handle = TEST_BUFFER_HANDLE;
|
||||
STRICT_EXPECTED_CALL(BUFFER_length(TEST_BUFFER_HANDLE)).SetReturn(length);
|
||||
STRICT_EXPECTED_CALL(BUFFER_u_char(TEST_BUFFER_HANDLE)).SetReturn(PUBLISH_RESP);
|
||||
|
||||
// act
|
||||
g_packetComplete(mqttHandle, PUBLISH_TYPE, flag, publish_handle);
|
||||
|
||||
// assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_IS_TRUE(g_errorCallbackInvoked);
|
||||
ASSERT_IS_FALSE(g_msgRecvCallbackInvoked);
|
||||
|
||||
// cleanup
|
||||
mqtt_client_deinit(mqttHandle);
|
||||
}
|
||||
|
||||
TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_too_short_packetID_fails)
|
||||
{
|
||||
// arrange
|
||||
unsigned char PUBLISH_RESP[] = { 0x00, 0x01, 0x0A, 0x00 }; // PacketId needed to be 2 bytes, but only 1 (after 0x0A) is supplied.
|
||||
size_t length = sizeof(PUBLISH_RESP) / sizeof(PUBLISH_RESP[0]);
|
||||
|
||||
uint8_t flag = 0x0d;
|
||||
|
||||
MQTT_CLIENT_HANDLE mqttHandle = mqtt_client_init(TestRecvCallback, TestOpCallback, (void*)&PUBLISH_RESP, TestErrorCallback, NULL);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
BUFFER_HANDLE publish_handle = TEST_BUFFER_HANDLE;
|
||||
STRICT_EXPECTED_CALL(BUFFER_length(TEST_BUFFER_HANDLE)).SetReturn(length);
|
||||
STRICT_EXPECTED_CALL(BUFFER_u_char(TEST_BUFFER_HANDLE)).SetReturn(PUBLISH_RESP);
|
||||
STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG));
|
||||
STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
|
||||
|
||||
// act
|
||||
g_packetComplete(mqttHandle, PUBLISH_TYPE, flag, publish_handle);
|
||||
|
||||
// assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_IS_TRUE(g_errorCallbackInvoked);
|
||||
ASSERT_IS_FALSE(g_msgRecvCallbackInvoked);
|
||||
|
||||
// cleanup
|
||||
mqtt_client_deinit(mqttHandle);
|
||||
}
|
||||
|
||||
TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_packetId_is_zero_fails)
|
||||
{
|
||||
// arrange
|
||||
unsigned char PUBLISH_RESP[] = { 0x00, 0x01, 0x0A, 0x00, 0x00 }; // packetId has enough bytes, but it can't be 0
|
||||
size_t length = sizeof(PUBLISH_RESP) / sizeof(PUBLISH_RESP[0]);
|
||||
|
||||
uint8_t flag = 0x0d;
|
||||
|
||||
MQTT_CLIENT_HANDLE mqttHandle = mqtt_client_init(TestRecvCallback, TestOpCallback, (void*)&PUBLISH_RESP, TestErrorCallback, NULL);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
BUFFER_HANDLE publish_handle = TEST_BUFFER_HANDLE;
|
||||
STRICT_EXPECTED_CALL(BUFFER_length(TEST_BUFFER_HANDLE)).SetReturn(length);
|
||||
STRICT_EXPECTED_CALL(BUFFER_u_char(TEST_BUFFER_HANDLE)).SetReturn(PUBLISH_RESP);
|
||||
STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG));
|
||||
STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
|
||||
// act
|
||||
g_packetComplete(mqttHandle, PUBLISH_TYPE, flag, publish_handle);
|
||||
|
||||
// assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_IS_TRUE(g_errorCallbackInvoked);
|
||||
ASSERT_IS_FALSE(g_msgRecvCallbackInvoked);
|
||||
|
||||
// cleanup
|
||||
mqtt_client_deinit(mqttHandle);
|
||||
}
|
||||
|
||||
|
||||
/*Test_SRS_MQTT_CLIENT_07_031: [If the actionResult parameter is of type UNSUBACK_TYPE then the msgInfo value shall be a UNSUBSCRIBE_ACK structure.]*/
|
||||
TEST_FUNCTION(mqtt_client_recvCompleteCallback_SUBACK_succeeds)
|
||||
{
|
||||
|
@ -2717,7 +2941,6 @@ TEST_FUNCTION(mqtt_client_trace_PUBLISH_succeeds)
|
|||
#ifndef NO_LOGGING
|
||||
STRICT_EXPECTED_CALL(get_time(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG));
|
||||
#endif
|
||||
STRICT_EXPECTED_CALL(mqtt_codec_publishReceived(TEST_PACKET_ID)).SetReturn((BUFFER_HANDLE)0x111111);
|
||||
EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG)).SetReturn(length);
|
||||
|
@ -2729,6 +2952,9 @@ TEST_FUNCTION(mqtt_client_trace_PUBLISH_succeeds)
|
|||
#endif
|
||||
EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(mqttmessage_destroy(IGNORED_PTR_ARG));
|
||||
#ifndef NO_LOGGING
|
||||
STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG));
|
||||
#endif
|
||||
EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
|
||||
g_packetComplete(mqttHandle, PUBLISH_TYPE, flag, publish_handle);
|
||||
|
|
Загрузка…
Ссылка в новой задаче