From 5406be1836e16c0339f95f7dea038e69b9065bdf Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 6 Nov 2020 05:18:18 -0500 Subject: Rework exit path + coding style + some memleaks Signed-off-by: Loic Poulain --- mhi-qmi-connect.c | 395 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 242 insertions(+), 153 deletions(-) diff --git a/mhi-qmi-connect.c b/mhi-qmi-connect.c index 4e4c5d1..b532cc8 100644 --- a/mhi-qmi-connect.c +++ b/mhi-qmi-connect.c @@ -42,7 +42,16 @@ static gboolean rmnet_setup_done; static gchar *ip_route_dump; static gboolean ping; -static int exit_code; +static int exit_reason; + +static void op_shutdown(int reason); + +enum { + SHUTDOWN_UNKNOWN, + SHUTDOWN_ERROR, + SHUTDOWN_KILLED, + SHUTDOWN_DISCONNECTED +}; /* 16 - cleanup/exit operations */ @@ -53,6 +62,8 @@ static void release_client_ready(QmiDevice *dev, GAsyncResult *res) static void release_qmi_clients(void) { + connection_status = QMI_WDS_CONNECTION_STATUS_UNKNOWN; + if (QMI_IS_CLIENT(client_wda)) qmi_device_release_client(device, (QmiClient *)client_wda, 0, 5, cancellable, (GAsyncReadyCallback) release_client_ready, NULL); @@ -82,7 +93,7 @@ static void stop_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + return; } /* Set WWAN interface down */ @@ -90,7 +101,7 @@ static void stop_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + return; } /* del RMNET interface */ @@ -98,7 +109,7 @@ static void stop_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + return; } if (!default_route) @@ -108,7 +119,7 @@ static void stop_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + return; } /* TODO: restore routing (default route) */ @@ -123,14 +134,16 @@ static void stop_network_ready(QmiClientWds *client, GAsyncResult *res) if (!output) { g_printerr("error: operation failed: %s\n", error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } - if (!qmi_message_wds_stop_network_output_get_result (output, &error)) { + if (!qmi_message_wds_stop_network_output_get_result(output, &error)) { g_printerr("error: couldn't stop network: %s\n", error->message); g_error_free(error); qmi_message_wds_stop_network_output_unref(output); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } qmi_message_wds_stop_network_output_unref(output); @@ -144,10 +157,13 @@ static void stop_network(void) { QmiMessageWdsStopNetworkInput *input; - input = qmi_message_wds_stop_network_input_new (); + if (connection_status != QMI_WDS_CONNECTION_STATUS_CONNECTED) + return; + + input = qmi_message_wds_stop_network_input_new(); qmi_message_wds_stop_network_input_set_packet_data_handle(input, packet_data_handle, NULL); qmi_client_wds_stop_network(client_wds, input, 10, cancellable, - (GAsyncReadyCallback)stop_network_ready, NULL); + (GAsyncReadyCallback)stop_network_ready, NULL); qmi_message_wds_stop_network_input_unref(input); } @@ -161,14 +177,18 @@ static void get_packet_service_status_ready(QmiClientWds *client, GAsyncResult * if (!output) { g_printerr("error: operation failed: %s\n", error->message); g_error_free(error); - release_qmi_clients(); release_qmi_clients(); return; + connection_status = QMI_WDS_CONNECTION_STATUS_UNKNOWN; + op_shutdown(SHUTDOWN_ERROR); + return; } if (!qmi_message_wds_get_packet_service_status_output_get_result(output, &error)) { g_printerr("error: couldn't get packet service status: %s\n", error->message); g_error_free(error); qmi_message_wds_get_packet_service_status_output_unref(output); - release_qmi_clients(); release_qmi_clients(); return; + connection_status = QMI_WDS_CONNECTION_STATUS_UNKNOWN; + op_shutdown(SHUTDOWN_ERROR); + return; } qmi_message_wds_get_packet_service_status_output_get_connection_status(output, &connection_status, NULL); @@ -177,8 +197,7 @@ static void get_packet_service_status_ready(QmiClientWds *client, GAsyncResult * if (connection_status != QMI_WDS_CONNECTION_STATUS_CONNECTED) { g_print("[%s] Connection status: '%s'\n", qmi_device_get_path_display(device), qmi_wds_connection_status_get_string(connection_status)); - stop_rmnet(); - stop_network(); + op_shutdown(SHUTDOWN_DISCONNECTED); return; } @@ -215,7 +234,8 @@ static void setup_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } /* Add link */ @@ -224,7 +244,8 @@ static void setup_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } g_print("[%s] interface created\n", qmi_device_get_path_display(device), mux_id); @@ -237,7 +258,8 @@ static void setup_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } g_print("[%s] interface IP is %s\n", qmi_device_get_path_display(device), mux_id, ip4_addr); @@ -249,7 +271,8 @@ static void setup_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } /* Set WWAN interface up */ @@ -257,7 +280,8 @@ static void setup_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } /* Set RMNET interface up */ @@ -265,7 +289,8 @@ static void setup_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } rmnet_setup_done = TRUE; @@ -278,7 +303,8 @@ static void setup_rmnet(void) if (!g_spawn_command_line_sync(cmdline, &ip_route_dump, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } /* Set RMNET as default route */ @@ -286,7 +312,8 @@ static void setup_rmnet(void) if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) { g_printerr("%s: %s\n", cmdline, error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } /* TODO: DNS */ @@ -301,21 +328,23 @@ static void get_current_settings_ready(QmiClientWds *client, GAsyncResult *res) guint32 addr = 0; struct in_addr in_addr_val; - output = qmi_client_wds_get_current_settings_finish (client, res, &error); + output = qmi_client_wds_get_current_settings_finish(client, res, &error); if (!output) { g_printerr("error: operation failed: %s\n", error->message); g_error_free (error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } - if (!qmi_message_wds_get_current_settings_output_get_result (output, &error)) { + if (!qmi_message_wds_get_current_settings_output_get_result(output, &error)) { g_printerr("error: couldn't get current settings: %s\n", error->message); - g_error_free (error); - qmi_message_wds_get_current_settings_output_unref (output); - release_qmi_clients(); return; + g_error_free(error); + qmi_message_wds_get_current_settings_output_unref(output); + op_shutdown(SHUTDOWN_ERROR); + return; } - if (qmi_message_wds_get_current_settings_output_get_ip_family (output, &ip_family, NULL)) + if (qmi_message_wds_get_current_settings_output_get_ip_family(output, &ip_family, NULL)) g_print("[%s] IP Family: %s\n", qmi_device_get_path_display(device), ((ip_family == QMI_WDS_IP_FAMILY_IPV4) ? "IPv4" : ((ip_family == QMI_WDS_IP_FAMILY_IPV6) ? "IPv6" : @@ -324,21 +353,22 @@ static void get_current_settings_ready(QmiClientWds *client, GAsyncResult *res) /* TODO */ if (ip_family == QMI_WDS_IP_FAMILY_IPV6) { g_printerr("IPv6 not supported\n"); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } if (qmi_message_wds_get_current_settings_output_get_ipv4_address(output, &addr, NULL)) { - in_addr_val.s_addr = GUINT32_TO_BE (addr); - memset (ip4_addr, 0, sizeof (ip4_addr)); - inet_ntop (AF_INET, &in_addr_val, ip4_addr, sizeof (ip4_addr)); + in_addr_val.s_addr = GUINT32_TO_BE(addr); + memset (ip4_addr, 0, sizeof(ip4_addr)); + inet_ntop (AF_INET, &in_addr_val, ip4_addr, sizeof(ip4_addr)); g_print("[%s] IPv4 address: %s\n", qmi_device_get_path_display(device), ip4_addr); } if (qmi_message_wds_get_current_settings_output_get_primary_ipv4_dns_address(output, &addr, NULL)) { - in_addr_val.s_addr = GUINT32_TO_BE (addr); - memset (ip4_dns, 0, sizeof (ip4_dns)); - inet_ntop (AF_INET, &in_addr_val, ip4_dns, sizeof (ip4_dns)); - g_print ("[%s] IPv4 primary DNS: %s\n", qmi_device_get_path_display(device), ip4_dns); + in_addr_val.s_addr = GUINT32_TO_BE(addr); + memset(ip4_dns, 0, sizeof(ip4_dns)); + inet_ntop(AF_INET, &in_addr_val, ip4_dns, sizeof(ip4_dns)); + g_print("[%s] IPv4 primary DNS: %s\n", qmi_device_get_path_display(device), ip4_dns); } qmi_message_wds_get_current_settings_output_unref(output); @@ -359,7 +389,8 @@ static void start_network_ready(QmiClientWds *client, GAsyncResult *res) if (!output) { g_printerr("error: operation failed: %s\n", error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } if (!qmi_message_wds_start_network_output_get_result(output, &error)) { @@ -372,7 +403,8 @@ static void start_network_ready(QmiClientWds *client, GAsyncResult *res) g_printerr("error: couldn't start network: %s\n", error->message); g_error_free(error); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } qmi_message_wds_start_network_output_get_packet_data_handle(output, &packet_data_handle, NULL); @@ -382,12 +414,12 @@ static void start_network_ready(QmiClientWds *client, GAsyncResult *res) input = qmi_message_wds_get_current_settings_input_new(); qmi_message_wds_get_current_settings_input_set_requested_settings(input, - (QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS | - QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS | - QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS | - QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO | - QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU | - QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST | + (QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU | + QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST | QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_FAMILY), NULL); @@ -425,18 +457,20 @@ static void bind_mux_data_port_ready(QmiClientWds *client, GAsyncResult *res) QmiMessageWdsBindMuxDataPortOutput *output; GError *error = NULL; - output = qmi_client_wds_bind_mux_data_port_finish (client, res, &error); + output = qmi_client_wds_bind_mux_data_port_finish(client, res, &error); if (!output) { - g_printerr ("error: operation failed: %s\n", error->message); - g_error_free (error); - release_qmi_clients(); return; + g_printerr("error: operation failed: %s\n", error->message); + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } - if (!qmi_message_wds_bind_mux_data_port_output_get_result (output, &error)) { - g_printerr ("error: couldn't bind mux data port: %s\n", error->message); - g_error_free (error); + if (!qmi_message_wds_bind_mux_data_port_output_get_result(output, &error)) { + g_printerr("error: couldn't bind mux data port: %s\n", error->message); + g_error_free(error); qmi_message_wds_bind_mux_data_port_output_unref(output); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } qmi_message_wds_bind_mux_data_port_output_unref(output); @@ -456,7 +490,9 @@ static void allocate_wds_client_ready(QmiDevice *dev, GAsyncResult *res) if (!client_wds) { g_printerr("error: couldn't create client for the '%s' service: %s\n", "WDS", error->message); - release_qmi_clients(); return; + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } input = qmi_message_wds_bind_mux_data_port_input_new(); @@ -473,7 +509,7 @@ static void allocate_wds_client_ready(QmiDevice *dev, GAsyncResult *res) } /* 8 - Data format set, start WDS operations */ -static void set_data_format_ready (QmiClientWda *client, GAsyncResult *res) +static void set_data_format_ready(QmiClientWda *client, GAsyncResult *res) { QmiMessageWdaSetDataFormatOutput *output; GError *error = NULL; @@ -482,16 +518,20 @@ static void set_data_format_ready (QmiClientWda *client, GAsyncResult *res) if (!output) { g_printerr("error: operation failed: %s\n", error->message); g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); return; } - if (!qmi_message_wda_set_data_format_output_get_result (output, &error)) { - g_printerr ("error: couldn't set data format: %s\n", error->message); - g_error_free (error); + if (!qmi_message_wda_set_data_format_output_get_result(output, &error)) { + g_printerr("error: couldn't set data format: %s\n", error->message); + g_error_free(error); qmi_message_wda_set_data_format_output_unref(output); + op_shutdown(SHUTDOWN_ERROR); return; } + qmi_message_wda_set_data_format_output_unref(output); + qmi_device_allocate_client(device, service_wds, QMI_CID_NONE, 10, cancellable, (GAsyncReadyCallback)allocate_wds_client_ready, NULL); } @@ -504,9 +544,11 @@ static void allocate_wda_client_ready(QmiDevice *dev, GAsyncResult *res) client_wda = (QmiClientWda *)qmi_device_allocate_client_finish(dev, res, &error); if (!client_wda) { - g_printerr ("error: couldn't create client for the '%s' service: %s\n", + g_printerr("error: couldn't create client for the '%s' service: %s\n", "WDA", error->message); - release_qmi_clients(); return; + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } input = qmi_message_wda_set_data_format_input_new(); @@ -527,50 +569,51 @@ static void allocate_wda_client_ready(QmiDevice *dev, GAsyncResult *res) qmi_client_wda_set_data_format(client_wda, input, 10, cancellable, (GAsyncReadyCallback)set_data_format_ready, NULL); + + qmi_message_wda_set_data_format_input_unref(input); } /* 6.3 - SIM PIN verified, start WDA operations */ static void verify_pin_ready(QmiClientUim *client, GAsyncResult *res) { - QmiMessageUimVerifyPinOutput *output; - GError *error = NULL; - - output = qmi_client_uim_verify_pin_finish(client, res, &error); - if (!output) { - g_printerr ("error: operation failed: %s\n", error->message); - g_error_free(error); - release_qmi_clients(); return; - } - - if (!qmi_message_uim_verify_pin_output_get_result (output, &error)) { - guint8 verify_retries_left; - guint8 unblock_retries_left; - - g_printerr("error: couldn't verify PIN: %s\n", error->message); - g_error_free (error); - - if (qmi_message_uim_verify_pin_output_get_retries_remaining ( - output, - &verify_retries_left, - &unblock_retries_left, - NULL)) { - g_printerr("[%s] Retries left:\n" - "\tVerify: %u\n" - "\tUnblock: %u\n", - qmi_device_get_path_display(device), - verify_retries_left, - unblock_retries_left); - } - - qmi_message_uim_verify_pin_output_unref(output); - release_qmi_clients(); return; - } - - g_print("[%s] PIN verified successfully\n", qmi_device_get_path_display(device)); - - qmi_message_uim_verify_pin_output_unref(output); + QmiMessageUimVerifyPinOutput *output; + GError *error = NULL; + + output = qmi_client_uim_verify_pin_finish(client, res, &error); + if (!output) { + g_printerr("error: operation failed: %s\n", error->message); + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; + } + + if (!qmi_message_uim_verify_pin_output_get_result(output, &error)) { + guint8 verify_retries_left; + guint8 unblock_retries_left; + + g_printerr("error: couldn't verify PIN: %s\n", error->message); + g_error_free(error); + + if (qmi_message_uim_verify_pin_output_get_retries_remaining( + output, &verify_retries_left, &unblock_retries_left, NULL)) { + g_printerr("[%s] Retries left:\n" + "\tVerify: %u\n" + "\tUnblock: %u\n", + qmi_device_get_path_display(device), + verify_retries_left, + unblock_retries_left); + } + + qmi_message_uim_verify_pin_output_unref(output); + op_shutdown(SHUTDOWN_ERROR); + return; + } + + g_print("[%s] PIN verified successfully\n", qmi_device_get_path_display(device)); + + qmi_message_uim_verify_pin_output_unref(output); - qmi_device_allocate_client(device, service_wda, QMI_CID_NONE, 10, cancellable, + qmi_device_allocate_client(device, service_wda, QMI_CID_NONE, 10, cancellable, (GAsyncReadyCallback)allocate_wda_client_ready, NULL); } @@ -585,8 +628,9 @@ static void power_on_sim_ready(QmiClientUim *client, GAsyncResult *res) output = qmi_client_uim_power_on_sim_finish(client_uim, res, &error); if (!output) { g_printerr("error: operation failed: %s\n", error->message); - g_error_free (error); - release_qmi_clients(); return; + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } if (!qmi_message_uim_power_on_sim_output_get_result(output, &error) && @@ -594,7 +638,8 @@ static void power_on_sim_ready(QmiClientUim *client, GAsyncResult *res) g_printerr("error: could not power on SIM: %s\n", error->message); g_error_free(error); qmi_message_uim_power_on_sim_output_unref(output); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } qmi_message_uim_power_on_sim_output_unref(output); @@ -603,10 +648,10 @@ static void power_on_sim_ready(QmiClientUim *client, GAsyncResult *res) input = qmi_message_uim_verify_pin_input_new(); - dummy_aid = g_array_new (FALSE, FALSE, sizeof (guint8)); + dummy_aid = g_array_new(FALSE, FALSE, sizeof(guint8)); qmi_message_uim_verify_pin_input_set_info(input, 1, sim1_pin_str, &error); - qmi_message_uim_verify_pin_input_set_session (input, QMI_UIM_SESSION_TYPE_CARD_SLOT_1, + qmi_message_uim_verify_pin_input_set_session(input, QMI_UIM_SESSION_TYPE_CARD_SLOT_1, dummy_aid, /* ignored */ &error); qmi_client_uim_verify_pin(client, input, 10, cancellable, @@ -625,9 +670,11 @@ static void allocate_uim_client_ready(QmiDevice *dev, GAsyncResult *res) client_uim = (QmiClientUim *)qmi_device_allocate_client_finish(dev, res, &error); if (!client_uim) { - g_printerr ("error: couldn't create client for the '%s' service: %s\n", + g_printerr("error: couldn't create client for the '%s' service: %s\n", "UIM", error->message); - release_qmi_clients(); return; + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } g_print("[%s] Powering SIM1...\n", qmi_device_get_path_display(device)); @@ -637,9 +684,9 @@ static void allocate_uim_client_ready(QmiDevice *dev, GAsyncResult *res) qmi_message_uim_power_on_sim_input_set_slot(input, slot, &error); qmi_client_uim_power_on_sim(client_uim, input, 10, cancellable, - (GAsyncReadyCallback)power_on_sim_ready, NULL); + (GAsyncReadyCallback)power_on_sim_ready, NULL); - qmi_message_uim_power_on_sim_input_unref(input); + qmi_message_uim_power_on_sim_input_unref(input); } /* 6 - Operating mode retrieved, start WDA operations */ @@ -651,24 +698,28 @@ static void get_operating_mode_ready(QmiClientDms *client, GAsyncResult *res) output = qmi_client_dms_get_operating_mode_finish(client, res, &error); if (!output) { - g_printerr ("error: operation failed: %s\n", error->message); - g_error_free (error); - release_qmi_clients(); return; + g_printerr("error: operation failed: %s\n", error->message); + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } if (!qmi_message_dms_get_operating_mode_output_get_result(output, &error)) { - g_printerr ("error: couldn't get power state: %s\n", error->message); - g_error_free (error); + g_printerr("error: couldn't get power state: %s\n", error->message); + g_error_free(error); qmi_message_dms_get_operating_mode_output_unref(output); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } qmi_message_dms_get_operating_mode_output_get_mode(output, &mode, NULL); + qmi_message_dms_get_operating_mode_output_unref(output); if (mode != QMI_DMS_OPERATING_MODE_ONLINE) { /* TODO put it online */ g_print("[%s] Modem is offline\n", qmi_device_get_path_display(device)); - release_qmi_clients(); return; + op_shutdown(SHUTDOWN_ERROR); + return; } g_print("[%s] Modem is online\n", qmi_device_get_path_display(device)); @@ -689,9 +740,11 @@ static void allocate_dms_client_ready(QmiDevice *dev, GAsyncResult *res) client_dms = (QmiClientDms *)qmi_device_allocate_client_finish(dev, res, &error); if (!client_dms) { - g_printerr ("error: couldn't create client for the '%s' service: %s\n", + g_printerr("error: couldn't create client for the '%s' service: %s\n", "DMS", error->message); - exit(EXIT_FAILURE); + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } qmi_client_dms_get_operating_mode(client_dms, NULL, 10, cancellable, @@ -705,7 +758,9 @@ static void device_open_ready(QmiDevice *dev, GAsyncResult *res) if (!qmi_device_open_finish(dev, res, &error)) { g_printerr("error: couldn't open the QmiDevice: %s\n", error->message); - exit(EXIT_FAILURE); + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } qmi_device_allocate_client(dev, service_dms, QMI_CID_NONE, 10, cancellable, @@ -721,7 +776,9 @@ static void device_new_ready(GObject *unused, GAsyncResult *res) device = qmi_device_new_finish(res, &error); if (!device) { g_printerr("error: couldn't create QmiDevice: %s\n", error->message); - exit(EXIT_FAILURE); + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } qmi_device_open(device, open_flags, 15, cancellable, @@ -733,9 +790,11 @@ static void wait_for_services_ready(QrtrNode *node, GAsyncResult *res, gpointer { GError *error = NULL; - if (!qrtr_node_wait_for_services_finish (node, res, &error)) { + if (!qrtr_node_wait_for_services_finish(node, res, &error)) { g_printerr ("error: failed to wait for QRTR services: %s\n", error->message); - exit(EXIT_FAILURE); + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } qmi_device_new_from_node(node, cancellable, (GAsyncReadyCallback)device_new_ready, NULL); @@ -751,25 +810,27 @@ static void qrtr_node_ready(GObject *unused, GAsyncResult *res) node = qrtr_node_for_id_finish(res, &error); if (!node) { g_printerr("error: couldn't open QRTR node: %s\n", error->message); - exit(EXIT_FAILURE); + g_error_free(error); + op_shutdown(SHUTDOWN_ERROR); + return; } services = g_array_sized_new(FALSE, FALSE, sizeof(QmiService), 10); g_array_append_val(services, service_wda); g_array_append_val(services, service_wds); g_array_append_val(services, service_dms); - + qrtr_node_wait_for_services(node, services, 5, NULL, (GAsyncReadyCallback) wait_for_services_ready, NULL); g_array_unref(services); } -/* X - Signals */ -static gboolean signals_handler(void) + +static void op_shutdown(int reason) { - /* TODO perform some nice cleanup here */ stop_rmnet(); + stop_network(); release_qmi_clients(); if (loop && g_main_loop_is_running(loop)) { @@ -777,6 +838,14 @@ static gboolean signals_handler(void) g_idle_add((GSourceFunc)g_main_loop_quit, loop); } + exit_reason = reason; +} + +/* X - Signals */ +static gboolean signals_handler(void) +{ + op_shutdown(SHUTDOWN_KILLED); + return G_SOURCE_REMOVE; } @@ -794,63 +863,43 @@ static GOptionEntry main_entries[] = { "QMAP/RMNET mux-id of the connection (default is 1)", NULL }, { "set-ip", 0, 0, G_OPTION_ARG_NONE, &set_ip, - "Setup rmnet IP address and DNS from Bearer context info", NULL - }, + "Setup rmnet IP address and DNS from Bearer context info", NULL + }, { "default-route", 0, 0, G_OPTION_ARG_NONE, &default_route, "Set rmnet interface as the defaut network route", NULL }, { NULL } }; -int main(int argc, char **argv) +int mainloop(void) { - GOptionContext *context; - GError *error = NULL; GFile *qmi_file; - context = g_option_context_new(""); - - g_option_context_add_main_entries(context, main_entries, NULL); - if (!g_option_context_parse(context, &argc, &argv, &error)) { - g_printerr ("error: %s\n", error->message); - exit(EXIT_FAILURE); - } - g_option_context_free(context); - - if (!apn_str) { - g_printerr("error: no APN name\n"); - exit(EXIT_FAILURE); - } - - if (default_route && !set_ip) { - g_printerr("error: Cannot set --default-route without --set-ip option\n"); - exit(EXIT_FAILURE); - } - if (qmi_dev) { /* Use MHI QMI character device */ gchar *id; qmi_file = g_file_new_for_commandline_arg(qmi_dev); id = g_file_get_path(qmi_file); qmi_device_new(qmi_file, cancellable, (GAsyncReadyCallback)device_new_ready, NULL); - g_free(id); + g_free(id); } else { /* QMI services over IPCR/qrtr */ /* TODO: auto detect qrtr node via lookup */ /* For now qrtr modem services are always exposed via node 3 */ qrtr_node_for_id(3, 10, cancellable, (GAsyncReadyCallback)qrtr_node_ready, NULL); } + exit_reason = SHUTDOWN_UNKNOWN; + /* Connect signals */ g_unix_signal_add(SIGINT, (GSourceFunc) signals_handler, NULL); g_unix_signal_add(SIGHUP, (GSourceFunc) signals_handler, NULL); g_unix_signal_add(SIGTERM, (GSourceFunc) signals_handler, NULL); - exit_code = 0; loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); if (cancellable) - g_object_unref(cancellable); + g_object_unref(cancellable); if (client_wda) g_object_unref(client_wda); if (client_wds) @@ -864,5 +913,45 @@ int main(int argc, char **argv) g_main_loop_unref(loop); - return exit_code; + return exit_reason; +} + +int main(int argc, char **argv) +{ + GOptionContext *context; + GError *error = NULL; + unsigned int ret; + + context = g_option_context_new(""); + + g_option_context_add_main_entries(context, main_entries, NULL); + if (!g_option_context_parse(context, &argc, &argv, &error)) { + g_printerr("error: %s\n", error->message); + exit(EXIT_FAILURE); + } + g_option_context_free(context); + + if (!apn_str) { + g_printerr("error: no APN name\n"); + exit(EXIT_FAILURE); + } + + if (default_route && !set_ip) { + g_printerr("error: Cannot set --default-route without --set-ip option\n"); + exit(EXIT_FAILURE); + } + + while (1) { + /* TODO try to reconnect on disconnect event */ + ret = mainloop(); + switch(ret) { + case SHUTDOWN_ERROR: + exit(EXIT_SUCCESS); + case SHUTDOWN_DISCONNECTED: + case SHUTDOWN_KILLED: + exit(EXIT_FAILURE); + default: + exit(EXIT_FAILURE); + } + } } -- cgit v1.2.3