void test_KineticPDU_GetStatus_should_return_appropriate_KineticStatus_based_on_KineticProto_Status_StatusCode_in_response(void) { LOG_LOCATION; KineticStatus status; PDU.proto = &PDU.protoData.message.proto; PDU.proto->command = &PDU.protoData.message.command; PDU.proto->command->status = &PDU.protoData.message.status; PDU.proto->command->status->has_code = true; PDU.proto->command->status->code = KINETIC_PROTO_STATUS_STATUS_CODE_SUCCESS; status = KineticPDU_GetStatus(&PDU); TEST_ASSERT_EQUAL(KINETIC_STATUS_SUCCESS, status); PDU.proto->command->status->code = KINETIC_PROTO_STATUS_STATUS_CODE_REMOTE_CONNECTION_ERROR; status = KineticPDU_GetStatus(&PDU); TEST_ASSERT_EQUAL(KINETIC_STATUS_CONNECTION_ERROR, status); }
KineticStatus KineticPDU_ReceiveMain(KineticPDU* const response) { assert(response != NULL); assert(response->connection != NULL); const int fd = response->connection->socket; assert(fd >= 0); LOGF1("\nReceiving PDU via fd=%d", fd); KineticStatus status; KineticMessage* msg = &response->protoData.message; // Receive the PDU header ByteBuffer rawHeader = ByteBuffer_Create(&response->headerNBO, sizeof(KineticPDUHeader), 0); status = KineticSocket_Read(fd, &rawHeader, rawHeader.array.len); if (status != KINETIC_STATUS_SUCCESS) { LOG0("Failed to receive PDU header!"); return status; } else { LOG3("PDU header received successfully"); KineticPDUHeader* headerNBO = &response->headerNBO; response->header = (KineticPDUHeader) { .versionPrefix = headerNBO->versionPrefix, .protobufLength = KineticNBO_ToHostU32(headerNBO->protobufLength), .valueLength = KineticNBO_ToHostU32(headerNBO->valueLength), }; KineticLogger_LogHeader(1, &response->header); } // Receive the protobuf message status = KineticSocket_ReadProtobuf(fd, response); if (status != KINETIC_STATUS_SUCCESS) { LOG0("Failed to receive PDU protobuf message!"); return status; } else { LOG3("Received PDU protobuf"); KineticLogger_LogProtobuf(2, response->proto); } // Validate the HMAC for the recevied protobuf message if (response->proto->authType == KINETIC_PROTO_MESSAGE_AUTH_TYPE_HMACAUTH) { if(!KineticHMAC_Validate( response->proto, response->connection->session.hmacKey)) { LOG0("Received PDU protobuf message has invalid HMAC!"); msg->has_command = true; msg->command.status = &msg->status; msg->status.code = KINETIC_PROTO_COMMAND_STATUS_STATUS_CODE_DATA_ERROR; return KINETIC_STATUS_DATA_ERROR; } else { LOG3("Received protobuf HMAC validation succeeded"); } } else if (response->proto->authType == KINETIC_PROTO_MESSAGE_AUTH_TYPE_PINAUTH) { LOG0("PIN-based authentication not yet supported!"); return KINETIC_STATUS_DATA_ERROR; } else if (response->proto->authType == KINETIC_PROTO_MESSAGE_AUTH_TYPE_UNSOLICITEDSTATUS) { LOG3("Unsolicited status message is not authenticated"); } // Extract embedded command, if supplied KineticProto_Message* pMsg = response->proto; if (pMsg->has_commandBytes && pMsg->commandBytes.data != NULL && pMsg->commandBytes.len > 0) { response->command = KineticProto_command__unpack( NULL, pMsg->commandBytes.len, pMsg->commandBytes.data); } status = KineticPDU_GetStatus(response); if (status == KINETIC_STATUS_SUCCESS) { LOG2("PDU received successfully!"); } return status; } KineticStatus KineticPDU_ReceiveValue(int socket_desc, ByteBuffer* value, size_t value_length) { assert(socket_desc >= 0); assert(value != NULL); assert(value->array.data != NULL); // Receive value payload LOGF1("Receiving value payload (%lld bytes)...", value_length); ByteBuffer_Reset(value); KineticStatus status = KineticSocket_Read(socket_desc, value, value_length); if (status != KINETIC_STATUS_SUCCESS) { LOG0("Failed to receive PDU value payload!"); return status; } LOG1("Received value payload successfully"); KineticLogger_LogByteBuffer(3, "Value Buffer", *value); return status; }
void test_KineticPDU_Receive_should_receive_a_message_for_the_exchange_and_return_false_upon_value_field_receive_failure(void) { LOG_LOCATION; KINETIC_PDU_INIT_WITH_MESSAGE(&PDU, &Connection); PDU.protoData.message.status.code = KINETIC_PROTO_STATUS_STATUS_CODE_SUCCESS; PDU.protoData.message.status.has_code = true; ByteBuffer headerNBO = ByteBuffer_Create(&PDU.headerNBO, sizeof(KineticPDUHeader)); PDU.headerNBO = (KineticPDUHeader) { .versionPrefix = 'F', .protobufLength = KineticNBO_ToHostU32(17), .valueLength = KineticNBO_ToHostU32(124) }; // Fake value/payload length uint8_t data[124]; size_t bytesToRead = sizeof(data); ByteArray expectedValue = ByteArray_Create(data, sizeof(data)); ByteArray_FillWithDummyData(expectedValue); KineticEntry entry = {.value = ByteBuffer_CreateWithArray(expectedValue)}; KineticPDU_AttachEntry(&PDU, &entry); KineticSocket_Read_ExpectAndReturn(Connection.socket, &headerNBO, sizeof(KineticPDUHeader), KINETIC_STATUS_SUCCESS); KineticSocket_ReadProtobuf_ExpectAndReturn(Connection.socket, &PDU, KINETIC_STATUS_SUCCESS); KineticHMAC_Validate_ExpectAndReturn(PDU.proto, PDU.connection->session.hmacKey, true); KineticSocket_Read_ExpectAndReturn(Connection.socket, &entry.value, bytesToRead, KINETIC_STATUS_SOCKET_ERROR); KineticStatus status = KineticPDU_Receive(&PDU); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SOCKET_ERROR, status); TEST_ASSERT_EQUAL(17, PDU.header.protobufLength); TEST_ASSERT_EQUAL(bytesToRead, expectedValue.len); TEST_ASSERT_EQUAL(expectedValue.len, PDU.header.valueLength); } void test_KineticPDU_Receive_should_receive_a_message_and_update_the_ConnectionID_for_the_connection_when_provided(void) { LOG_LOCATION; Connection.connectionID = 98765; KINETIC_PDU_INIT_WITH_MESSAGE(&PDU, &Connection); PDU.protoData.message.status.code = KINETIC_PROTO_STATUS_STATUS_CODE_SUCCESS; PDU.protoData.message.status.has_code = true; ByteBuffer headerNBO = ByteBuffer_Create(&PDU.headerNBO, sizeof(KineticPDUHeader)); // Fake value/payload length uint8_t data[124]; size_t bytesToRead = sizeof(data); ByteArray expectedValue = {.data = data, .len = sizeof(data)}; ByteArray_FillWithDummyData(expectedValue); KineticEntry entry = {.value = ByteBuffer_CreateWithArray(expectedValue)}; KineticPDU_AttachEntry(&PDU, &entry); KineticSocket_Read_ExpectAndReturn(Connection.socket, &headerNBO, sizeof(KineticPDUHeader), KINETIC_STATUS_SUCCESS); KineticSocket_ReadProtobuf_ExpectAndReturn(Connection.socket, &PDU, KINETIC_STATUS_SUCCESS); KineticHMAC_Validate_ExpectAndReturn(PDU.proto, PDU.connection->session.hmacKey, true); KineticSocket_Read_ExpectAndReturn(Connection.socket, &entry.value, bytesToRead, KINETIC_STATUS_SUCCESS); PDU.headerNBO.valueLength = KineticNBO_FromHostU32(expectedValue.len); EnableAndSetPDUConnectionID(&PDU, 12345); EnableAndSetPDUStatus(&PDU, KINETIC_PROTO_STATUS_STATUS_CODE_SUCCESS); KineticStatus status = KineticPDU_Receive(&PDU); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL(KINETIC_PROTO_STATUS_STATUS_CODE_SUCCESS, PDU.protoData.message.status.code); TEST_ASSERT_EQUAL(12345, PDU.proto->command->header->connectionID); TEST_ASSERT_EQUAL(12345, PDU.connection->connectionID); } void test_KineticPDU_Receive_should_receive_a_message_and_NOT_update_the_ConnectionID_for_the_connection_if_not_provided(void) { LOG_LOCATION; Connection.connectionID = 98765; KINETIC_PDU_INIT_WITH_MESSAGE(&PDU, &Connection); PDU.protoData.message.status.code = KINETIC_PROTO_STATUS_STATUS_CODE_SUCCESS; PDU.protoData.message.status.has_code = true; ByteBuffer headerNBO = ByteBuffer_Create(&PDU.headerNBO, sizeof(KineticPDUHeader)); // Fake value/payload length uint8_t data[124]; size_t bytesToRead = sizeof(data); ByteArray expectedValue = {.data = data, .len = sizeof(data)}; ByteArray_FillWithDummyData(expectedValue); KineticEntry entry = {.value = ByteBuffer_CreateWithArray(expectedValue)}; KineticPDU_AttachEntry(&PDU, &entry); KineticSocket_Read_ExpectAndReturn(Connection.socket, &headerNBO, sizeof(KineticPDUHeader), KINETIC_STATUS_SUCCESS); KineticSocket_ReadProtobuf_ExpectAndReturn(Connection.socket, &PDU, KINETIC_STATUS_SUCCESS); KineticHMAC_Validate_ExpectAndReturn(PDU.proto, PDU.connection->session.hmacKey, true); KineticSocket_Read_ExpectAndReturn(Connection.socket, &entry.value, bytesToRead, KINETIC_STATUS_SUCCESS); PDU.headerNBO.valueLength = KineticNBO_FromHostU32(expectedValue.len); EnableAndSetPDUStatus(&PDU, KINETIC_PROTO_STATUS_STATUS_CODE_SUCCESS); KineticStatus status = KineticPDU_Receive(&PDU); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL(KINETIC_PROTO_STATUS_STATUS_CODE_SUCCESS, PDU.protoData.message.status.code); TEST_ASSERT_EQUAL(98765, PDU.proto->command->header->connectionID); TEST_ASSERT_EQUAL(98765, PDU.connection->connectionID); } void test_KineticPDU_GetStatus_should_return_KINETIC_STATUS_INVALID_if_no_KineticProto_Status_StatusCode_in_response(void) { LOG_LOCATION; KineticStatus status; status = KineticPDU_GetStatus(NULL); TEST_ASSERT_EQUAL(KINETIC_STATUS_INVALID, status); PDU.proto = NULL; status = KineticPDU_GetStatus(&PDU); TEST_ASSERT_EQUAL(KINETIC_STATUS_INVALID, status); PDU.proto = &PDU.protoData.message.proto; PDU.proto->command = NULL; status = KineticPDU_GetStatus(&PDU); TEST_ASSERT_EQUAL(KINETIC_STATUS_INVALID, status); PDU.proto->command = &PDU.protoData.message.command; status = KineticPDU_GetStatus(&PDU); TEST_ASSERT_EQUAL(KINETIC_STATUS_INVALID, status); PDU.proto->command->status = &PDU.protoData.message.status; PDU.proto->command->status->has_code = false; status = KineticPDU_GetStatus(&PDU); TEST_ASSERT_EQUAL(KINETIC_STATUS_INVALID, status); PDU.proto->command->status->has_code = true; PDU.proto->command->status->code = KINETIC_PROTO_STATUS_STATUS_CODE_INVALID_STATUS_CODE; status = KineticPDU_GetStatus(&PDU); TEST_ASSERT_EQUAL(KINETIC_STATUS_INVALID, status); }