static void s_reporting_task_fn()

in source/device_defender.c [807:919]


static void s_reporting_task_fn(struct aws_task *task, void *userdata, enum aws_task_status status) {
    struct aws_iotdevice_defender_task *defender_task = (struct aws_iotdevice_defender_task *)userdata;
    struct aws_allocator *allocator = defender_task->allocator;
    struct aws_iotdevice_network_ifconfig ifconfig;
    AWS_ZERO_STRUCT(ifconfig);
    const size_t custom_metrics_len = aws_array_list_length(&defender_task->config.custom_metrics);
    struct defender_custom_metric_data *custom_metric_data =
        custom_metrics_len == 0
            ? NULL
            : aws_mem_calloc(allocator, custom_metrics_len, sizeof(struct defender_custom_metric_data));
    int return_code = 0;

    if (status == AWS_TASK_STATUS_RUN_READY) {
        AWS_LOGF_DEBUG(
            AWS_LS_IOTDEVICE_DEFENDER_TASK, "id=%p: Running DeviceDefender reporting task", (void *)defender_task);

        if (AWS_OP_SUCCESS != (return_code = get_network_config_and_transfer(&ifconfig, allocator))) {
            AWS_LOGF_ERROR(
                AWS_LS_IOTDEVICE_DEFENDER_TASK,
                "id=%p: Failed to retrieve network configuration: %s",
                (void *)defender_task,
                aws_error_name(return_code));
            goto cleanup;
        }
        struct aws_iotdevice_metric_network_transfer totals = {
            .bytes_in = 0, .bytes_out = 0, .packets_in = 0, .packets_out = 0};
        get_system_network_total(&totals, &ifconfig);

        struct aws_array_list net_conns;
        AWS_ZERO_STRUCT(net_conns);
        aws_array_list_init_dynamic(&net_conns, allocator, 5, sizeof(struct aws_iotdevice_metric_net_connection));
        if (AWS_OP_SUCCESS != (return_code = get_network_connections(&net_conns, &ifconfig, allocator))) {
            AWS_LOGF_ERROR(
                AWS_LS_IOTDEVICE_DEFENDER_TASK,
                "id=%p: Failed to get network connection data: %s",
                (void *)defender_task,
                aws_error_name(return_code));
            goto cleanup;
        }

        if (AWS_OP_SUCCESS != s_init_custom_metric_data(custom_metric_data, defender_task)) {
            goto cleanup;
        }

        /* per metric retrieval errors do not result in failure */
        s_get_custom_metrics_data(defender_task, custom_metric_data, custom_metrics_len);
        struct aws_iotdevice_metric_network_transfer *ptr_delta_xfer = NULL;
        struct aws_iotdevice_metric_network_transfer delta_xfer;
        AWS_ZERO_STRUCT(delta_xfer);

        if (defender_task->has_previous_net_xfer) {
            delta_xfer.bytes_in = 0;
            delta_xfer.bytes_out = 0;
            delta_xfer.packets_in = 0;
            delta_xfer.packets_out = 0;

            get_network_total_delta(&delta_xfer, &defender_task->previous_net_xfer, &totals);
            ptr_delta_xfer = &delta_xfer;

        } else {
            defender_task->has_previous_net_xfer = true;
        }

        /* serialize and publish MAY not publish successfully, but in the event
           of failure, it will handle cleaning up the memory it allocated and
           and invoke the task failure callback. If it succeeeds, task completion
           deferred until puback packet for the report is recieved. */
        s_serialize_and_publish_defender_report(
            defender_task, &totals, ptr_delta_xfer, &net_conns, custom_metrics_len, custom_metric_data);

        for (size_t interface_index = 0; interface_index < net_conns.length; ++interface_index) {
            struct aws_iotdevice_metric_net_connection *con = NULL;
            if (aws_array_list_get_at_ptr(&net_conns, (void **)&con, interface_index)) {
                continue;
            }
            if (con->local_interface) {
                aws_string_destroy(con->local_interface);
            }
            if (con->remote_address) {
                aws_string_destroy(con->remote_address);
            }
        }

        aws_array_list_clean_up(&net_conns);
        aws_hash_table_clean_up(&ifconfig.iface_name_to_info);

        uint64_t now;
        aws_event_loop_current_clock_time(defender_task->event_loop, &now);
        aws_event_loop_schedule_task_future(
            defender_task->event_loop, task, now + defender_task->config.task_period_ns);
    } else if (status == AWS_TASK_STATUS_CANCELED) {
        AWS_LOGF_DEBUG(
            AWS_LS_IOTDEVICE_DEFENDER_TASK, "id=%p: Reporting task cancelled, cleaning up", (void *)defender_task);

        if (defender_task->config.task_canceled_fn != NULL) {
            defender_task->config.task_canceled_fn(defender_task->config.callback_userdata);
        }
        /* cleanup of task memory happens in task cleanup or stop function */
    } else {
        s_invoke_failure_callback(&defender_task->config, false, AWS_ERROR_IOTDEVICE_DEFENDER_UNKNOWN_TASK_STATUS);
        uint64_t now;
        aws_event_loop_current_clock_time(defender_task->event_loop, &now);
        aws_event_loop_schedule_task_future(
            defender_task->event_loop, task, now + defender_task->config.task_period_ns);
    }

cleanup:
    s_clean_up_custom_metric_data(allocator, custom_metric_data, custom_metrics_len);

    if (aws_hash_table_is_valid(&ifconfig.iface_name_to_info)) {
        aws_hash_table_clean_up(&ifconfig.iface_name_to_info);
    }
}