Exemple #1
0
void test_specified_user_verifier(void **state)
{
    (void)state;

    ASSERT_EQUAL(kaa_user_manager_attach_to_user(user_manager, USER_EXTERNAL_ID, ACCESS_TOKEN, USER_VERIFIER), KAA_ERR_NONE);

    size_t expected_size = 0;
    ASSERT_EQUAL(kaa_user_request_get_size(user_manager, &expected_size), KAA_ERR_NONE);

    uint8_t buffer[expected_size];
    kaa_platform_message_writer_t *writer = NULL;
    ASSERT_EQUAL(kaa_platform_message_writer_create(&writer, buffer, expected_size), KAA_ERR_NONE);
    ASSERT_NOT_NULL(writer);

    ASSERT_EQUAL(kaa_user_request_serialize(user_manager, writer), KAA_ERR_NONE);

    uint8_t *buf_cursor = buffer;
    ASSERT_EQUAL(KAA_EXTENSION_USER, KAA_HTONS(*(uint16_t*)buf_cursor));
    buf_cursor += sizeof(uint16_t);

    char options[] = { 0x00, 0x01 };
    ASSERT_EQUAL(memcmp(buf_cursor, options, 2), 0);
    buf_cursor += 2;

    ASSERT_EQUAL(*(uint32_t * ) buf_cursor, KAA_HTONL(2 * sizeof(uint32_t)
                                                    + kaa_aligned_size_get(strlen(USER_EXTERNAL_ID))
                                                    + kaa_aligned_size_get(strlen(ACCESS_TOKEN)
                                                    + kaa_aligned_size_get(strlen(USER_VERIFIER)))));
    buf_cursor += sizeof(uint32_t);

    ASSERT_EQUAL(0, *buf_cursor);
    ++buf_cursor;

    ASSERT_EQUAL(strlen(USER_EXTERNAL_ID), *buf_cursor);
    ++buf_cursor;

    ASSERT_EQUAL(KAA_HTONS(strlen(ACCESS_TOKEN)), *(uint16_t *) buf_cursor);
    buf_cursor += sizeof(uint16_t);

    ASSERT_EQUAL(KAA_HTONS(strlen(USER_VERIFIER)), *(uint16_t *) buf_cursor);
    buf_cursor += sizeof(uint32_t); // + reserved 16B

    ASSERT_EQUAL(memcmp(buf_cursor, USER_EXTERNAL_ID, strlen(USER_EXTERNAL_ID)), 0);
    buf_cursor += kaa_aligned_size_get(strlen(USER_EXTERNAL_ID));

    ASSERT_EQUAL(memcmp(buf_cursor, ACCESS_TOKEN, strlen(ACCESS_TOKEN)), 0);
    buf_cursor += kaa_aligned_size_get(strlen(ACCESS_TOKEN));

    ASSERT_EQUAL(memcmp(buf_cursor, USER_VERIFIER, strlen(USER_VERIFIER)), 0);
    buf_cursor += kaa_aligned_size_get(strlen(USER_VERIFIER));

    kaa_platform_message_writer_destroy(writer);
}
Exemple #2
0
void test_create_request(void **state)
{
    (void)state;

    size_t expected_size = 0;
    ASSERT_EQUAL(kaa_configuration_manager_get_size(config_manager, &expected_size), KAA_ERR_NONE);
    ASSERT_EQUAL(expected_size, KAA_EXTENSION_HEADER_SIZE + SHA_1_DIGEST_LENGTH);

    uint8_t request_buffer[expected_size];
    kaa_platform_message_writer_t *writer = NULL;
    ASSERT_EQUAL(kaa_platform_message_writer_create(&writer, request_buffer, expected_size), KAA_ERR_NONE);
    ASSERT_EQUAL(kaa_configuration_manager_request_serialize(config_manager, writer), KAA_ERR_NONE);

    uint8_t *cursor = writer->begin;
    ASSERT_EQUAL(KAA_HTONS(*((uint16_t *) cursor)), KAA_EXTENSION_CONFIGURATION);
    cursor += sizeof(uint32_t);

    ASSERT_EQUAL(KAA_NTOHL(*((uint32_t *) cursor)),  SHA_1_DIGEST_LENGTH);    // checking payload size
    cursor += sizeof(uint32_t);

    kaa_digest check_hash;
    ext_calculate_sha_hash(KAA_CONFIGURATION_DATA, KAA_CONFIGURATION_DATA_LENGTH, check_hash);  // checking configuration hash
    ASSERT_EQUAL(memcmp(cursor, check_hash, SHA_1_DIGEST_LENGTH), 0);
    cursor += SHA_1_DIGEST_LENGTH;

    ASSERT_EQUAL(cursor, writer->end);

    kaa_platform_message_writer_destroy(writer);
}
Exemple #3
0
kaa_error_t ext_tcp_utils_set_sockaddr_port(kaa_sockaddr_t *addr, uint16_t port)
{
    KAA_RETURN_IF_NIL2(addr, port, KAA_ERR_BADPARAM);
    switch (addr->sa_family) {
        case AF_INET: {
            struct sockaddr_in *s_in = (struct sockaddr_in *) addr;
            s_in->sin_port = KAA_HTONS(port);
            break;
        }
        case AF_INET6: {
            struct sockaddr_in6 *s_in6 = (struct sockaddr_in6 *) addr;
            s_in6->sin6_port = KAA_HTONS(port);
            break;
        }
        default:
            return KAA_ERR_SOCKET_INVALID_FAMILY;
    }
    return KAA_ERR_NONE;
}
Exemple #4
0
KAA_TEST_CASE_EX(log_callback_with_storage, on_fail_and_success_called)
{
    (void)state;

    kaa_error_t rc;
    int dummy_ctx;

    kaa_log_delivery_listener_t listeners = {
        mock_log_event_success_fn,
        mock_log_event_failed_fn,
        NULL,
        &dummy_ctx,
    };

    /* Notify mocks about test intentions */
    check_bucket = 1;
    expected_bucked_id = 42;
    failed_call_is_expected = 1;
    success_call_is_expected = 1;
    expected_ctx = &dummy_ctx;

    rc = kaa_logging_set_listeners(log_collector, &listeners);
    ASSERT_EQUAL(KAA_ERR_NONE, rc);

    /* Response packet is passed internally via test reader */
    struct response_packet *response = (struct response_packet *) test_reader_buffer;
    *(uint16_t *) response->resps[RESP_SUCCESS_IDX].bucket_id
        = KAA_HTONS(expected_bucked_id);
    *(uint16_t *) response->resps[RESP_FAILURE_IDX].bucket_id
        = KAA_HTONS(expected_bucked_id);

    /* Test itself */
    rc = kaa_logging_handle_server_sync(log_collector, test_reader, TEST_EXT_OP, test_filled_size);

    ASSERT_EQUAL(rc, KAA_ERR_NONE);

    /* Post-conditions check */

    ASSERT_TRUE(success_call_completed);
    ASSERT_TRUE(failed_call_completed);
    ASSERT_FALSE(timeout_call_completed);
}
static kaa_error_t kaa_client_sync_serialize(kaa_platform_protocol_t *self,
        const kaa_extension_id services[], size_t services_count, uint8_t *buffer, size_t *size)
{
    kaa_platform_message_writer_t writer = KAA_MESSAGE_WRITER(buffer, *size);

    uint16_t total_services_count = services_count + 1 /* Meta extension */;

    kaa_error_t error_code = kaa_platform_message_header_write(&writer,
            KAA_PLATFORM_PROTOCOL_ID, KAA_PLATFORM_PROTOCOL_VERSION);
    if (error_code) {
        KAA_LOG_ERROR(self->logger, error_code, "Failed to write the client sync header");
        goto fail;
    }

    uint16_t *extension_count_p = (uint16_t *)writer.current;
    writer.current += KAA_PROTOCOL_EXTENSIONS_COUNT_SIZE;
    // TODO: static assert KAA_PROTOCOL_EXTENSIONS_COUNT_SIZE == sizeof(uint16_t)

    error_code = kaa_meta_data_request_serialize(self, &writer, self->request_id);
    if (error_code) {
        goto fail;
    }

    while (!error_code && services_count--) {
        size_t size_required = writer.end - writer.current;
        bool need_resync = false;
        error_code = kaa_extension_request_serialize(services[services_count],
                self->request_id, writer.current, &size_required, &need_resync);
        if (error_code) {
            KAA_LOG_ERROR(self->logger, error_code,
                    "Failed to serialize the '%d' extension", services[services_count]);
            continue;
        }

        if (!need_resync) {
            --total_services_count;
            continue;
        }

        writer.current += size_required;
    }

    *extension_count_p = KAA_HTONS(total_services_count);
    *size = writer.current - writer.begin;

fail:
    return error_code;
}
Exemple #6
0
kaa_error_t kaa_profile_request_serialize(kaa_profile_manager_t *self, kaa_platform_message_writer_t *writer)
{
    KAA_RETURN_IF_NIL2(self, writer, KAA_ERR_BADPARAM);

    KAA_LOG_TRACE(self->logger, KAA_ERR_NONE, "Going to compile profile client sync");

    kaa_error_t error_code = kaa_platform_message_write_extension_header(writer
                                                                       , KAA_EXTENSION_PROFILE
                                                                       , 0
                                                                       , self->extension_data->payload_size);
    KAA_RETURN_IF_ERR(error_code);

    uint32_t network_order_32 = KAA_HTONL(0);
#if KAA_PROFILE_SCHEMA_VERSION > 0
    if (resync_is_required(self)) {
        network_order_32 = KAA_HTONL(self->profile_body.size);
        error_code = kaa_platform_message_write(writer, &network_order_32, sizeof(uint32_t));
        KAA_RETURN_IF_ERR(error_code);
        if (self->profile_body.size) {
            KAA_LOG_TRACE(self->logger, KAA_ERR_NONE, "Writing profile body (size %u)...", self->profile_body.size);
            error_code = kaa_platform_message_write_aligned(writer, self->profile_body.buffer, self->profile_body.size);
            if (error_code) {
                KAA_LOG_ERROR(self->logger, error_code, "Failed to write profile body");
                return error_code;
            }
        }
    } else {
        error_code = kaa_platform_message_write(writer, &network_order_32, sizeof(uint32_t));
        KAA_RETURN_IF_ERR(error_code);
    }
#else
    error_code = kaa_platform_message_write(writer, &network_order_32, sizeof(uint32_t));
    KAA_RETURN_IF_ERR(error_code);
#endif

    uint16_t network_order_16 = 0;
    uint16_t field_number_with_reserved = 0;

    if (!self->status->is_registered) {
        field_number_with_reserved = KAA_HTONS(PUB_KEY_VALUE << 8);
        error_code = kaa_platform_message_write(writer
                                             , &field_number_with_reserved
                                             , sizeof(uint16_t));
        KAA_RETURN_IF_ERR(error_code);

        network_order_16 = KAA_HTONS(self->extension_data->public_key.size);
        error_code = kaa_platform_message_write(writer, &network_order_16, sizeof(uint16_t));
        KAA_RETURN_IF_ERR(error_code);

        KAA_LOG_TRACE(self->logger, KAA_ERR_NONE, "Writing public key (size %u)...", self->extension_data->public_key.size);
        error_code = kaa_platform_message_write_aligned(writer
                                                     , (char*)self->extension_data->public_key.buffer
                                                     , self->extension_data->public_key.size);
        if (error_code) {
            KAA_LOG_ERROR(self->logger, error_code, "Failed to write public key");
            return error_code;
        }
    }

    if (self->extension_data->access_token.buffer) {
        field_number_with_reserved = KAA_HTONS(ACCESS_TOKEN_VALUE << 8);
        error_code = kaa_platform_message_write(writer
                                             , &field_number_with_reserved
                                             , sizeof(uint16_t));
        KAA_RETURN_IF_ERR(error_code);

        network_order_16 = KAA_HTONS(self->extension_data->access_token.size);
        error_code = kaa_platform_message_write(writer, &network_order_16, sizeof(uint16_t));
        KAA_RETURN_IF_ERR(error_code);

        KAA_LOG_TRACE(self->logger, KAA_ERR_NONE, "Writing access token (size %u)...", self->extension_data->access_token.size);
        error_code = kaa_platform_message_write_aligned(writer
                                                     , (char*)self->extension_data->access_token.buffer
                                                     , self->extension_data->access_token.size);
        if (error_code) {
            KAA_LOG_ERROR(self->logger, error_code, "Failed to write access token");
            return error_code;
        }
    }

    return error_code;
}
Exemple #7
0
void test_create_request(void **state)
{
    (void)state;

    kaa_user_log_record_t *test_log_record = kaa_test_log_record_create();
    test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER);
    size_t test_log_record_size = test_log_record->get_size(test_log_record);

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector, status,
            channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));
    strategy.decision = NOOP;
    strategy.max_parallel_uploads = UINT32_MAX;

    kaa_log_bucket_constraints_t constraints = {
        .max_bucket_size = 2 * test_log_record_size,
        .max_bucket_log_count = UINT32_MAX,
    };

    error_code = kaa_logging_init(log_collector, create_mock_storage(), &strategy, &constraints);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    size_t expected_size = 0;
    error_code = kaa_logging_request_get_size(log_collector, &expected_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    uint8_t buffer[expected_size];
    kaa_platform_message_writer_t *writer = NULL;
    error_code = kaa_platform_message_writer_create(&writer, buffer, expected_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    ASSERT_NOT_NULL(writer);

    error_code = kaa_logging_request_serialize(log_collector, writer);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    kaa_platform_message_writer_destroy(writer);

    uint8_t *buf_cursor = buffer;
    ASSERT_EQUAL(KAA_EXTENSION_LOGGING, KAA_HTONS(*(uint16_t *)buf_cursor));
    buf_cursor += sizeof(uint16_t);

    uint8_t options[] = { 0x00, 0x01 };
    ASSERT_EQUAL(memcmp(buf_cursor, options, 2), 0);
    buf_cursor += 2;

    ASSERT_EQUAL(*(uint32_t *) buf_cursor, KAA_HTONL(20));
    buf_cursor += sizeof(uint32_t);

    uint8_t request_id_records_count[]  = { 0x00, 0x01, 0x00, 0x01 };
    ASSERT_EQUAL(memcmp(buf_cursor, request_id_records_count, 4), 0);
    buf_cursor += 4;

    uint8_t record_buf[test_log_record_size];
    avro_writer_t avro_writer = avro_writer_memory((char *)record_buf, test_log_record_size);
    test_log_record->serialize(avro_writer, test_log_record);
    avro_writer_free(avro_writer);

    ASSERT_EQUAL(*(uint32_t *) buf_cursor, KAA_HTONL(test_log_record_size));
    buf_cursor += sizeof(uint32_t);

    ASSERT_EQUAL(memcmp(buf_cursor, record_buf, test_log_record_size), 0);

    kaa_log_collector_destroy(log_collector);
    test_log_record->destroy(test_log_record);
}



void test_response(void **state)
{
    (void)state;

    srand(time(NULL));

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector, status, channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));

    mock_storage_context_t *storage = create_mock_storage();

    kaa_log_bucket_constraints_t constraints = {
        .max_bucket_size = 1024,
        .max_bucket_log_count = UINT32_MAX,
    };

    error_code = kaa_logging_init(log_collector, storage, &strategy, &constraints);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    uint32_t response_count = 2;
    size_t response_buffer_size = sizeof(uint32_t) + sizeof(uint32_t) * response_count;
    uint8_t response_buffer[response_buffer_size];

    uint8_t *response = response_buffer;
    *((uint32_t *)response) = KAA_HTONL(response_count);
    response += sizeof(uint32_t);

    /* First response */
    *((uint16_t *)response) = KAA_HTONS(rand());
    response += sizeof(uint16_t);
    *((uint8_t *)response) = 0x0; // SUCCESS
    response += sizeof(uint8_t);
    *((uint8_t *)response) = 0;
    response += sizeof(uint8_t);

    /* Second response */
    *((uint16_t *)response) = KAA_HTONS(rand());
    response += sizeof(uint16_t);
    *((uint8_t *)response) = 0x1; // FAILURE
    response += sizeof(uint8_t);
    *((uint8_t *)response) = rand() % 4;
    response += sizeof(uint8_t);

    kaa_platform_message_reader_t *reader = NULL;
    error_code = kaa_platform_message_reader_create(&reader, response_buffer, response_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    ASSERT_NOT_NULL(reader);

    error_code = kaa_logging_handle_server_sync(log_collector, reader, 0, response_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    ASSERT_TRUE(strategy.on_failure_count);
    ASSERT_TRUE(storage->on_remove_by_id_count);
    ASSERT_TRUE(storage->on_unmark_by_id_count);

    kaa_platform_message_reader_destroy(reader);
    kaa_log_collector_destroy(log_collector);
}



void test_timeout(void **state)
{
    (void)state;

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector,
            status, channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    kaa_user_log_record_t *test_log_record = kaa_test_log_record_create();
    test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER);
    size_t test_log_record_size = test_log_record->get_size(test_log_record);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));
    strategy.timeout = TEST_TIMEOUT;
    strategy.decision = NOOP;
    strategy.max_parallel_uploads = UINT32_MAX;

    kaa_log_bucket_constraints_t constraints = {
        .max_bucket_size = 2 * test_log_record_size,
        .max_bucket_log_count = UINT32_MAX,
    };

    error_code = kaa_logging_init(log_collector, create_mock_storage(), &strategy, &constraints);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    size_t request_buffer_size = 256;
    uint8_t request_buffer[request_buffer_size];
    kaa_platform_message_writer_t *writer = NULL;
    error_code = kaa_platform_message_writer_create(&writer, request_buffer, request_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_request_serialize(log_collector, writer);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    sleep(TEST_TIMEOUT + 1);

    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    ASSERT_TRUE(strategy.on_timeout_count);

    test_log_record->destroy(test_log_record);
    kaa_platform_message_writer_destroy(writer);
    kaa_log_collector_destroy(log_collector);
}

void test_decline_timeout(void **state)
{
    (void)state;

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector, status, channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    kaa_user_log_record_t *test_log_record = kaa_test_log_record_create();
    test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER);
    size_t test_log_record_size = test_log_record->get_size(test_log_record);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));
    strategy.timeout = TEST_TIMEOUT;
    strategy.decision = NOOP;
    strategy.max_parallel_uploads = UINT32_MAX;

    mock_storage_context_t *storage = create_mock_storage();
    ASSERT_NOT_NULL(storage);

    kaa_log_bucket_constraints_t constraints = {
        .max_bucket_size = 2 * test_log_record_size,
        .max_bucket_log_count = UINT32_MAX,
    };

    error_code = kaa_logging_init(log_collector, storage, &strategy, &constraints);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    size_t request_buffer_size = 256;
    uint8_t request_buffer[request_buffer_size];
    kaa_platform_message_writer_t *writer = NULL;
    error_code = kaa_platform_message_writer_create(&writer, request_buffer, request_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_request_serialize(log_collector, writer);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    sleep(TEST_TIMEOUT + 1);

    uint16_t bucket_id = *((uint16_t *)(request_buffer + KAA_EXTENSION_HEADER_SIZE));
    bucket_id = KAA_NTOHS(bucket_id);

    uint32_t response_count = 1;
    size_t response_buffer_size = sizeof(uint32_t) + sizeof(uint32_t) * response_count;
    uint8_t response_buffer[response_buffer_size];

    uint8_t *response = response_buffer;
    *((uint32_t *)response) = KAA_HTONL(response_count);
    response += sizeof(uint32_t);

    /* First response */
    *((uint16_t *)response) = KAA_HTONS(bucket_id);
    response += sizeof(uint16_t);
    *((uint8_t *)response) = 0x0; // SUCCESS
    response += sizeof(uint8_t);
    *((uint8_t *)response) = 0;
    response += sizeof(uint8_t);

    kaa_platform_message_reader_t *reader = NULL;
    error_code = kaa_platform_message_reader_create(&reader, response_buffer, response_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    ASSERT_NOT_NULL(reader);

    error_code = kaa_logging_handle_server_sync(log_collector, reader, 0, response_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    ASSERT_TRUE(storage->on_remove_by_id_count);

    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    ASSERT_FALSE(strategy.on_timeout_count);

    test_log_record->destroy(test_log_record);
    kaa_platform_message_writer_destroy(writer);
    kaa_platform_message_reader_destroy(reader);
    kaa_log_collector_destroy(log_collector);
}

void test_max_parallel_uploads_with_log_sync(void **state)
{
    (void)state;

    uint32_t channel_id = 0;
    kaa_transport_channel_interface_t transport_context;
    test_kaa_channel_create(&transport_context);

    kaa_channel_manager_add_transport_channel(channel_manager, &transport_context, &channel_id);

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector, status, channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    kaa_user_log_record_t *test_log_record = kaa_test_log_record_create();
    test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER);
    size_t test_log_size = test_log_record->get_size(test_log_record);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));
    strategy.timeout = INT16_MAX;
    strategy.decision = UPLOAD;

    mock_storage_context_t *storage = create_mock_storage();
    ASSERT_NOT_NULL(storage);

    kaa_log_bucket_constraints_t constraints = {
        .max_bucket_size = 2 * test_log_size,
        .max_bucket_log_count = UINT32_MAX,
    };

    error_code = kaa_logging_init(log_collector, storage, &strategy, &constraints);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    /*
     * Ensure the log delivery is forbidden at all.
     */
    strategy.max_parallel_uploads = 0;
    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    ASSERT_EQUAL(((mock_transport_channel_context_t *)transport_context.context)->on_sync_count, 0);

    /*
     * Ensure the first request is allowed.
     */
    strategy.max_parallel_uploads = 1;
    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    ASSERT_EQUAL(((mock_transport_channel_context_t *)transport_context.context)->on_sync_count, 1);

    /*
     * Do the first request to remember the delivery timeout of the log batch.
     */
    size_t request_buffer_size = 256;
    uint8_t request_buffer[request_buffer_size];
    kaa_platform_message_writer_t *writer = NULL;
    error_code = kaa_platform_message_writer_create(&writer, request_buffer, request_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_request_serialize(log_collector, writer);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    /*
     * Ensure the second request is forbidden.
     */
    ASSERT_EQUAL(((mock_transport_channel_context_t *)transport_context.context)->on_sync_count, 1);

    /*
     * Clean up.
     */
    error_code = kaa_channel_manager_remove_transport_channel(channel_manager, channel_id);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    test_log_record->destroy(test_log_record);
    kaa_log_collector_destroy(log_collector);
}

void test_max_parallel_uploads_with_sync_all(void **state)
{
    (void)state;

    uint32_t channel_id = 0;
    kaa_transport_channel_interface_t transport_context;
    test_kaa_channel_create(&transport_context);

    kaa_channel_manager_add_transport_channel(channel_manager, &transport_context, &channel_id);

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector,
            status, channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    kaa_user_log_record_t *test_log_record = kaa_test_log_record_create();
    test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER);
    size_t test_log_size = test_log_record->get_size(test_log_record);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));
    strategy.timeout = INT16_MAX;
    strategy.decision = UPLOAD;

    mock_storage_context_t *storage = create_mock_storage();
    ASSERT_NOT_NULL(storage);

    kaa_log_bucket_constraints_t constraints = {
        .max_bucket_size = 2 * test_log_size,
        .max_bucket_log_count = UINT32_MAX,
    };

    error_code = kaa_logging_init(log_collector, storage, &strategy, &constraints);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    /*
     * Ensure the log delivery is forbidden at all.
     */
    strategy.max_parallel_uploads = 0;
    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    size_t expected_size = 0;
    error_code = kaa_logging_request_get_size(log_collector, &expected_size);
    assert_int_equal(KAA_ERR_NONE, error_code);
    ASSERT_FALSE(expected_size);

    /*
     * Ensure the first request is allowed.
     */
    strategy.max_parallel_uploads = 1;
    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    /*
     * Do the first request to remember the delivery timeout of the log batch.
     */
    error_code = kaa_logging_request_get_size(log_collector, &expected_size);
    assert_int_equal(KAA_ERR_NONE, error_code);
    ASSERT_TRUE(expected_size);
    size_t request_buffer_size = 256;
    uint8_t request_buffer[request_buffer_size];
    kaa_platform_message_writer_t *writer = NULL;
    error_code = kaa_platform_message_writer_create(&writer, request_buffer, request_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_request_serialize(log_collector, writer);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    /*
     * Ensure the second request is forbidden.
     */
    error_code = kaa_logging_request_get_size(log_collector, &expected_size);
    assert_int_equal(KAA_ERR_NONE, error_code);
    ASSERT_FALSE(expected_size);

    /*
     * Clean up.
     */
    error_code = kaa_channel_manager_remove_transport_channel(channel_manager, channel_id);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    test_log_record->destroy(test_log_record);
    kaa_log_collector_destroy(log_collector);
}

/* ---------------------------------------------------------------------------*/
/* Log delivery tests                                                         */
/* ---------------------------------------------------------------------------*/

/* Server chunk, managed by a corresponding reader object.
 * Perfectly packed. Packed attribute is intentionally avoided. */
struct response_chunk {
    uint8_t bucket_id[2];  /* 16 bits for bucket ID */
    uint8_t resp_code;     /* 8 bits for response code. 0 == SUCCESS, 1 == FAILURE */
    // cppcheck-suppress unusedStructMember
    uint8_t reserved;      /* Should be 0 */
};

struct response_packet {
    uint8_t resp_cnt[4];           /* 32 bits for amount of responces in buffer */
    struct response_chunk resps[]; /* Responses itself */
};

#define RESP_PACKETS               2 /* Amount of response packets */
#define RESP_SUCCESS_IDX           0 /* Index of successfull response */
#define RESP_FAILURE_IDX           1 /* Index of failed response */
#define TEST_BUFFER_SIZE           1024
#define TEST_EXT_OP                0 /* Simple stub */


static mock_strategy_context_t         test_strategy1;
static mock_strategy_context_t         test_strategy2;
static mock_storage_context_t          *test_storage1;
static mock_storage_context_t          *test_storage2;
static kaa_log_collector_t             *log_collector;
static size_t                          test_log_record_size = TEST_BUFFER_SIZE;
/* Will contain response_packet. Thus required to be aligned. */
static uint32_t                        test_reader_buffer[TEST_BUFFER_SIZE / 4];
static uint32_t                        test_writer_buffer[TEST_BUFFER_SIZE / 4];
/* Portion of the test buffer filled with valid data */
static size_t                          test_filled_size;
static kaa_platform_message_reader_t   *test_reader;
static kaa_platform_message_writer_t   *test_writer;
static kaa_user_log_record_t           *test_log_record;

/* Values to be checked inside mock event function */
static void     *expected_ctx;
static int      check_bucket;
static uint16_t expected_bucked_id;

/* Required to trace generic mock function calls */
static int      call_is_expected;
static int      call_completed;

/* Required to trace on fail mock function calls */
static int      failed_call_is_expected;
static int      failed_call_completed;

/* Required to trace on success mock function calls */
static int      success_call_is_expected;
static int      success_call_completed;

/* Required to trace on timeout mock function calls */
static int      timeout_call_is_expected;
static int      timeout_call_completed;

/* Mock event functions */

static void mock_log_event_generic_fn(void *ctx, const kaa_log_bucket_info_t *bucket)
{
    ASSERT_TRUE(call_is_expected);
    ASSERT_NOT_NULL(bucket); /* Shouldn't be NULL no matter what */

    if (check_bucket) {
        ASSERT_EQUAL(expected_bucked_id, bucket->bucket_id);
    }

    ASSERT_EQUAL(expected_ctx, ctx);

    call_completed++;
}
Exemple #8
0
void test_profile_sync_serialize(void)
{
    KAA_TRACE_IN(logger);

    kaa_error_t error_code;
    kaa_platform_message_writer_t *manual_writer;
    kaa_platform_message_writer_t *auto_writer;

    const char *access_token = "access token";
    const size_t access_token_size = strlen(access_token);
    kaa_profile_t *profile = kaa_profile_basic_endpoint_profile_test_create();
    profile->profile_body = kaa_string_copy_create("dummy");
    size_t serialized_profile_size = profile->get_size(profile);
    char *serialized_profile = (char *) KAA_MALLOC(serialized_profile_size * sizeof(char));
    avro_writer_t avro_writer = avro_writer_memory(serialized_profile, serialized_profile_size);

    profile->serialize(avro_writer, profile);

    error_code = kaa_profile_manager_update_profile(profile_manager, profile);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    status->is_registered = false;
    error_code = kaa_profile_manager_set_endpoint_access_token(profile_manager, access_token);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    size_t profile_sync_size;
    error_code = kaa_profile_request_get_size(profile_manager, &profile_sync_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    char buffer[profile_sync_size];
    error_code = kaa_platform_message_writer_create(&manual_writer, buffer, profile_sync_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    uint32_t network_order_32;

    error_code = kaa_platform_message_write_extension_header(manual_writer
                                                           , KAA_PROFILE_EXTENSION_TYPE
                                                           , 0
                                                           , profile_sync_size - KAA_EXTENSION_HEADER_SIZE);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    bool need_resync = true;
    ASSERT_EQUAL(kaa_profile_need_profile_resync(profile_manager, &need_resync), KAA_ERR_NONE);

    network_order_32 = KAA_HTONL(0);
    if (need_resync)
        network_order_32 = KAA_HTONL(serialized_profile_size);
    error_code = kaa_platform_message_write(manual_writer, &network_order_32, sizeof(uint32_t));
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    if (need_resync) {
        error_code = kaa_platform_message_write_aligned(manual_writer, serialized_profile, serialized_profile_size);
        ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    }

    network_order_32 = KAA_HTONS(TEST_PUB_KEY_SIZE) << 16 | PUB_KEY_VALUE;
    error_code = kaa_platform_message_write(manual_writer, &network_order_32, sizeof(uint32_t));
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_platform_message_write_aligned(manual_writer, test_ep_key, TEST_PUB_KEY_SIZE);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    network_order_32 = KAA_HTONS(access_token_size) << 16 | ACCESS_TOKEN_VALUE;
    error_code = kaa_platform_message_write(manual_writer, &network_order_32, sizeof(uint32_t));
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_platform_message_write_aligned(manual_writer, access_token, access_token_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    char buffer2[profile_sync_size];
    error_code = kaa_platform_message_writer_create(&auto_writer, buffer2, profile_sync_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_profile_request_serialize(profile_manager, auto_writer);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = (memcmp(buffer, buffer2, profile_sync_size) == 0 ? KAA_ERR_NONE : KAA_ERR_BADDATA);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    KAA_FREE(serialized_profile);
    avro_writer_free(avro_writer);
    profile->destroy(profile);
    kaa_platform_message_writer_destroy(auto_writer);
    kaa_platform_message_writer_destroy(manual_writer);

    KAA_TRACE_OUT(logger);
}
Exemple #9
0
static kaa_error_t kaa_client_sync_serialize(kaa_platform_protocol_t *self
        , const kaa_service_t services[]
        , size_t services_count
        , char* buffer
        , size_t *size)
{
    kaa_platform_message_writer_t *writer = NULL;
    kaa_error_t error_code = kaa_platform_message_writer_create(&writer, buffer, *size);
    KAA_RETURN_IF_ERR(error_code);

    uint16_t total_services_count = services_count + 1 /* Meta extension */;

    error_code = kaa_platform_message_header_write(writer, KAA_PLATFORM_PROTOCOL_ID, KAA_PLATFORM_PROTOCOL_VERSION);
    if (error_code) {
        KAA_LOG_ERROR(self->logger, error_code, "Failed to write the client sync header");
        return error_code;
    }
    char *extension_count_p = writer->current;
    writer->current += KAA_PROTOCOL_EXTENSIONS_COUNT_SIZE;

    error_code = kaa_meta_data_request_serialize(self->status, writer, self->request_id);

    while (!error_code && services_count--) {
        switch (services[services_count]) {
        case KAA_SERVICE_BOOTSTRAP: {
            error_code = kaa_channel_manager_bootstrap_request_serialize(self->kaa_context->channel_manager
                         , writer);
            if (error_code)
                KAA_LOG_ERROR(self->logger, error_code, "Failed to serialize the bootstrap extension");
            break;
        }
        case KAA_SERVICE_PROFILE: {
            bool need_resync = false;
            error_code = kaa_profile_need_profile_resync(self->kaa_context->profile_manager
                         , &need_resync);
            if (!error_code) {
                if (need_resync) {
                    error_code = kaa_profile_request_serialize(self->kaa_context->profile_manager, writer);
                    if (error_code)
                        KAA_LOG_ERROR(self->logger, error_code, "Failed to serialize the profile extension");
                } else {
                    --total_services_count;
                }
            } else {
                KAA_LOG_ERROR(self->logger, error_code, "Failed to read profile's 'need_resync' flag");
            }
            break;
        }
        case KAA_SERVICE_USER: {
            error_code = kaa_user_request_serialize(self->kaa_context->user_manager, writer);
            if (error_code)
                KAA_LOG_ERROR(self->logger, error_code, "Failed to serialize the user extension");
            break;
        }
        case KAA_SERVICE_EVENT: {
#ifndef KAA_DISABLE_FEATURE_EVENTS
            error_code = kaa_event_request_serialize(self->kaa_context->event_manager, self->request_id, writer);
            if (error_code)
                KAA_LOG_ERROR(self->logger, error_code, "Failed to serialize the event extension");
#else
            --total_services_count;
#endif
            break;
        }
        case KAA_SERVICE_LOGGING: {
#ifndef KAA_DISABLE_FEATURE_LOGGING
            bool need_resync = false;
            error_code = kaa_logging_need_logging_resync(self->kaa_context->log_collector, &need_resync);
            if (!error_code) {
                if (need_resync) {
                    error_code = kaa_logging_request_serialize(self->kaa_context->log_collector, writer);
                    if (error_code)
                        KAA_LOG_ERROR(self->logger, error_code, "Failed to serialize the logging extension");
                } else {
                    --total_services_count;
                }
            } else {
                KAA_LOG_ERROR(self->logger, error_code, "Failed to read logging's 'need_resync' flag");
            }
#else
            --total_services_count;
#endif
            break;
        }
        case KAA_SERVICE_CONFIGURATION: {
#ifndef KAA_DISABLE_FEATURE_CONFIGURATION
            error_code = kaa_configuration_manager_request_serialize(self->kaa_context->configuration_manager, writer);
            if (error_code)
                KAA_LOG_ERROR(self->logger, error_code, "Failed to serialize the configuration extension");
#else
            --total_services_count;
#endif
            break;
        }
        case KAA_SERVICE_NOTIFICATION: {
#ifndef KAA_DISABLE_FEATURE_NOTIFICATION
            error_code = kaa_notification_manager_request_serialize(self->kaa_context->notification_manager, writer);
            if (error_code)
                KAA_LOG_ERROR(self->logger, error_code, "Failed to serialize the configuration extension");
#else
            --total_services_count;
#endif
            break;
        }
        default:
            break;
        }
    }
    *(uint16_t *) extension_count_p = KAA_HTONS(total_services_count);
    *size = writer->current - writer->begin;
    kaa_platform_message_writer_destroy(writer);

    return error_code;
}
void test_deserializing(void)
{
    KAA_TRACE_IN(context->logger);
    kaa_notification_t *notification = kaa_notification_notification_create();
    const char *message = "Hello World!!!\n";
    notification->message = kaa_string_copy_create(message);
    size                  =               (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) /*that was header*/+ sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) /*extension options
                                          and payload length*/  + sizeof(uint32_t) + sizeof(uint32_t) /*state sqn and delta status*/ + sizeof(uint16_t) + sizeof(uint16_t) /*field id and topic count*/ + sizeof(uint64_t) /*topic ID*/
                                          + sizeof(uint16_t) + sizeof(uint16_t) /*subscriptions type + topic name length*/ + sizeof(uint32_t) /*topic name + padding */ + sizeof(uint16_t) + sizeof(uint16_t) /*field id and notifications count*/
                                          + sizeof(uint32_t) /* Notification sqn */ + sizeof(uint16_t) + sizeof(uint16_t) /* Notification type + uid length */+ sizeof (uint32_t) /* notification body size*/ + sizeof (uint64_t) /*Topic Id*/
                                          + /*Not unicast notifications*/ + kaa_aligned_size_get(notification->get_size(notification)));

    char *unserialized_buffer = (char *)KAA_MALLOC(size);
    ASSERT_NOT_NULL(unserialized_buffer);
    buffer_pointer = unserialized_buffer;
    memset(unserialized_buffer, 0, size);
    *(uint32_t *)unserialized_buffer = KAA_HTONL((uint32_t) KAA_PLATFORM_PROTOCOL_ID); //KAA_HTONL(KAA_PLATFORM_PROTOCOL_ID);
    unserialized_buffer += sizeof(uint32_t);
    *(uint16_t *)unserialized_buffer = KAA_HTONS((uint16_t)1);
    unserialized_buffer += sizeof(uint16_t);
    *(uint16_t *)unserialized_buffer = KAA_HTONS((uint16_t)1); // extension count
    unserialized_buffer += sizeof(uint16_t);

    *(uint8_t *)unserialized_buffer = (uint8_t)KAA_NOTIFICATION_EXTENSION_TYPE;
    unserialized_buffer += sizeof(uint8_t);
    unserialized_buffer += sizeof(uint8_t) + sizeof(uint16_t); // pass by extension options

    uint32_t payload_info = sizeof(uint32_t) + sizeof(uint32_t) /*state sqn and delta status*/ + sizeof(uint16_t) + sizeof(uint16_t) /*field id and topic count*/ + sizeof(uint64_t) /*topic ID*/
                                                  + sizeof(uint16_t) + sizeof(uint16_t) /*subscriptions type + topic name length*/ + sizeof(uint32_t) /*topic name + padding */ + sizeof(uint16_t) + sizeof(uint16_t) /*field id and notifications count*/
                                                  + sizeof(uint32_t) /* Notification sqn */ + sizeof(uint16_t) + sizeof(uint16_t) /* Notification type + uid length */+ sizeof (uint32_t) /* notification body size*/ + sizeof (uint64_t) /*Topic Id*/
                                                  +   kaa_aligned_size_get(notification->get_size(notification));

    *(uint32_t *)unserialized_buffer = KAA_HTONL((uint32_t) payload_info);
    unserialized_buffer += sizeof(uint32_t);
    *(uint32_t *)unserialized_buffer = KAA_HTONL((uint32_t)455); //Notification sqn
    unserialized_buffer += sizeof(uint32_t);
    *(uint32_t *)unserialized_buffer = KAA_HTONL((uint32_t)2); // Delta status
    unserialized_buffer += sizeof(uint32_t);
    //TOPICS
    *(uint8_t *)unserialized_buffer = (uint8_t)0;
    unserialized_buffer += sizeof(uint16_t);
    *(uint16_t *)unserialized_buffer = KAA_HTONS ((uint16_t)1); // topics count
    unserialized_buffer += sizeof(uint16_t);
    *(uint64_t *)unserialized_buffer = KAA_HTONLL((uint64_t)22);    //topic id
    unserialized_buffer += sizeof(uint64_t);
    *(uint8_t *)unserialized_buffer = (uint8_t)OPTIONAL_SUBSCRIPTION;
    unserialized_buffer += sizeof(uint16_t);
    *(uint16_t *)unserialized_buffer = KAA_HTONS((uint16_t)4); //KAA
    unserialized_buffer += sizeof(uint16_t);
    *unserialized_buffer++ = 'K';*unserialized_buffer++ = 'A'; // topic name + padding
    *unserialized_buffer++ = 'A';*unserialized_buffer++ = 'A';
    unserialized_buffer += (4 - kaa_aligned_size_get(4));
    //-----------------------------------------------------------------------
    *(uint8_t *)unserialized_buffer = (uint8_t)1; //Notification field ID
    unserialized_buffer += sizeof(uint16_t);
    *(uint16_t *)unserialized_buffer = KAA_HTONS ((uint16_t)1); // notitifications count
    unserialized_buffer += sizeof(uint16_t);
    *(uint32_t *)unserialized_buffer = KAA_HTONL((uint32_t)99); //sqn
    pointer_to_sqn = unserialized_buffer; // To have the possibility to change sqn.
    unserialized_buffer += sizeof(uint32_t);
    *(uint8_t *)unserialized_buffer = (uint8_t)0x1; //notification type
    unserialized_buffer += sizeof(uint16_t);
    *(uint16_t *)unserialized_buffer = KAA_HTONS ((uint16_t) 0); //uid length
    unserialized_buffer += sizeof(uint16_t);
    *(uint32_t *)unserialized_buffer = KAA_HTONL ((uint32_t)notification->get_size(notification));
    unserialized_buffer += sizeof(uint32_t);
    *(uint64_t *)unserialized_buffer = KAA_HTONLL((uint64_t)22);
    unserialized_buffer += sizeof(uint64_t);

    avro_writer_t avro_writer = avro_writer_memory(unserialized_buffer, notification->get_size(notification));
    notification->serialize(avro_writer, notification);
    err = kaa_platform_protocol_process_server_sync(context->platform_protocol, buffer_pointer, size);
    avro_writer_free(avro_writer);

    ASSERT_EQUAL(err, KAA_ERR_NONE);

    notification->destroy(notification);

    KAA_TRACE_OUT(context->logger);
}
Exemple #11
0
kaatcp_error_t kaatcp_get_request_connect(const kaatcp_connect_t *message
                                        , char *buf
                                        , size_t *buf_size)
{
    KAA_RETURN_IF_NIL3(message, buf, buf_size, KAATCP_ERR_BAD_PARAM);

    char header[6];
    size_t payload_size = message->sync_request_size
                        + message->session_key_size
                        + message->signature_size
                        + KAA_CONNECT_HEADER_LENGTH;

    uint8_t header_size = create_basic_header(KAATCP_MESSAGE_CONNECT
                                            , payload_size
                                            , header);

    if ((*buf_size) < payload_size + header_size) {
        return KAATCP_ERR_BUFFER_NOT_ENOUGH;
    }

    char *cursor = buf;

    memcpy(cursor, header, header_size);
    cursor += header_size;

    uint16_t name_length = KAA_HTONS(message->protocol_name_length);
    memcpy(cursor, &name_length, sizeof(uint16_t));
    cursor += sizeof(uint16_t);

    memcpy(cursor, message->protocol_name, message->protocol_name_length);
    cursor += message->protocol_name_length;

    *(cursor++) = PROTOCOL_VERSION;
    *(cursor++) = message->connect_flags;

    uint32_t next_protocol_id = KAA_HTONL(message->next_ptorocol_id);
    memcpy(cursor, &next_protocol_id, sizeof(uint32_t));
    cursor += sizeof(uint32_t);

    *(cursor++) = message->session_key_flags;
    *(cursor++) = message->signature_flags;

    uint16_t keep_alive = KAA_HTONS(message->keep_alive);
    memcpy(cursor, &keep_alive, sizeof(uint16_t));
    cursor += sizeof(uint16_t);

    if (message->session_key && message->session_key_flags) {
        memcpy(cursor, message->session_key, message->session_key_size);
        cursor += message->session_key_size;
    }
    if (message->signature && message->signature_flags) {
        memcpy(cursor, message->signature, message->signature_size);
        cursor += message->signature_size;
    }

    if (message->sync_request) {
        memcpy(cursor, message->sync_request, message->sync_request_size);
        cursor += message->sync_request_size;
    }
    *buf_size = cursor - buf;
    return KAATCP_ERR_NONE;
}