From: Jaehyun Kim Date: Mon, 5 Jun 2023 11:39:16 +0000 (+0900) Subject: Add APIs to support DHCP state changes X-Git-Tag: accepted/tizen/unified/20230706.152214^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F14%2F293814%2F4;p=platform%2Fcore%2Fapi%2Fconnection.git Add APIs to support DHCP state changes Change-Id: I8ee7c017cb8e54ebf9b686f1af4be4d4726d8bf0 Signed-off-by: Jaehyun Kim --- diff --git a/include/net_connection.h b/include/net_connection.h index bac6d31..941af40 100755 --- a/include/net_connection.h +++ b/include/net_connection.h @@ -151,6 +151,15 @@ typedef enum { CONNECTION_ETHERNET_CABLE_ATTACHED = 1, /**< Ethernet cable is attached */ } connection_ethernet_cable_state_e; +/** + * @brief Enumeration for the DHCP state. + * @since_tizen 8.0 + */ +typedef enum { + CONNECTION_DHCP_STATE_UNKNOWN = 0, /**< Unknown state */ + CONNECTION_DHCP_STATE_STARTED = 1, /**< DHCP is running */ + CONNECTION_DHCP_STATE_FINISHED = 2, /**< DHCP is finished */ +} connection_dhcp_state_e; /** * @brief Enumeration for connection errors. @@ -375,6 +384,19 @@ typedef void(*connection_set_default_cb)(connection_error_e result, void* user_d typedef bool(*connection_ipv6_address_cb)(char *ipv6_address, void *user_data); /** + * @brief Called when the DHCP state is changed. + * @since_tizen 8.0 + * @param[in] state The DHCP state + * @param[in] interface_name The interface name with DHCP state change + * @param[in] result The result of DHCP operation + * @param[in] user_data The user data passed from the callback registration function + * @see connection_set_dhcp_state_changed_cb() + * @see connection_unset_dhcp_state_changed_cb() + */ +typedef void(*connection_dhcp_state_changed_cb)(connection_dhcp_state_e state, + const char *interface_name, connection_error_e result, void *user_data); + +/** * @brief Gets the type of the current profile for data connection. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] connection The connection handle @@ -526,6 +548,7 @@ int connection_get_wifi_state(connection_h connection, connection_wifi_state_e* */ int connection_get_ethernet_state(connection_h connection, connection_ethernet_state_e* state); + /** * @brief Called when the Internet state of the current connection is changed. * @since_tizen 5.5 @@ -589,6 +612,26 @@ int connection_get_ethernet_cable_state(connection_h connection, /** + * @brief Gets the DHCP state of the interface. + * @since_tizen 8.0 + * @privlevel public + * @privilege %http://tizen.org/privilege/network.get + * @param[in] connection The connection handle + * @param[in] interface_name The interface name + * @param[out] state The DHCP state of the interface + * @return @c 0 on success, + * otherwise a negative error value + * @retval #CONNECTION_ERROR_NONE Successful + * @retval #CONNECTION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONNECTION_ERROR_OPERATION_FAILED Operation failed + * @retval #CONNECTION_ERROR_PERMISSION_DENIED Permission denied + * @retval #CONNECTION_ERROR_NOT_SUPPORTED Not supported + */ +int connection_get_dhcp_state(connection_h connection, + const char *interface_name, connection_dhcp_state_e *state); + + +/** * @deprecated Deprecated since 4.0. Use connection_ethernet_cable_state_changed_cb() instead. * @brief Called when ethernet cable is plugged [in/out]. * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif @@ -796,6 +839,39 @@ int connection_unset_proxy_address_changed_cb(connection_h connection); /** + * @brief Sets the callback that is called when the DHCP state is changed. + * @since_tizen 8.0 + * @param[in] connection The connection handle + * @param[in] callback The callback function to be called + * @param[in] user_data The user data passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #CONNECTION_ERROR_NONE Successful + * @retval #CONNECTION_ERROR_NOT_INITIALIZED Not initialized + * @retval #CONNECTION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONNECTION_ERROR_OPERATION_FAILED Operation failed + * @retval #CONNECTION_ERROR_NOT_SUPPORTED Not supported + */ +int connection_set_dhcp_state_changed_cb(connection_h connection, + connection_dhcp_state_changed_cb callback, void *user_data); + + +/** + * @brief Unsets the callback that is called when the DHCP state is changed. + * @since_tizen 8.0 + * @param[in] connection The connection handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #CONNECTION_ERROR_NONE Successful + * @retval #CONNECTION_ERROR_NOT_INITIALIZED Not initialized + * @retval #CONNECTION_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONNECTION_ERROR_OPERATION_FAILED Operation failed + * @retval #CONNECTION_ERROR_NOT_SUPPORTED Not supported + */ +int connection_unset_dhcp_state_changed_cb(connection_h connection); + + +/** * @brief Adds a new profile which is created by connection_profile_create(). * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @privlevel public diff --git a/include/net_connection_private.h b/include/net_connection_private.h index 1b2c74f..8085f31 100755 --- a/include/net_connection_private.h +++ b/include/net_connection_private.h @@ -120,6 +120,7 @@ typedef struct _connection_handle_s { connection_address_changed_cb proxy_changed_callback; connection_internet_state_changed_cb internet_state_changed_callback; connection_ethernet_cable_state_changed_cb ethernet_cable_state_changed_callback; + connection_dhcp_state_changed_cb dhcp_state_changed_callback; connection_set_default_cb set_default_callback; connection_opened_cb opened_callback; connection_closed_cb closed_callback; @@ -129,6 +130,7 @@ typedef struct _connection_handle_s { void *proxy_changed_user_data; void *internet_state_changed_user_data; void *ethernet_cable_state_changed_user_data; + void *dhcp_state_changed_user_data; void *set_default_user_data; void *opened_user_data; void *closed_user_data; @@ -152,6 +154,8 @@ int _connection_libnet_get_ethernet_state(connection_handle_s *conn_handle, connection_ethernet_state_e *state); int _connection_libnet_get_ethernet_cable_state(connection_handle_s *conn_handle, connection_ethernet_cable_state_e* state); +int _connection_libnet_get_dhcp_state(connection_handle_s *conn_handle, + const char *interface_name, connection_dhcp_state_e *state); int _connection_libnet_get_bluetooth_state(connection_handle_s *conn_handle, connection_bt_state_e* state); bool _connection_libnet_check_profile_validity(connection_profile_h profile); int _connection_libnet_get_profile_iterator(connection_handle_s *conn_handle, diff --git a/packaging/capi-network-connection.spec b/packaging/capi-network-connection.spec index a53cc23..ba2906b 100755 --- a/packaging/capi-network-connection.spec +++ b/packaging/capi-network-connection.spec @@ -1,6 +1,6 @@ Name: capi-network-connection Summary: Network Connection library in TIZEN C API -Version: 1.0.125 +Version: 1.0.126 Release: 0 Group: System/Network License: Apache-2.0 diff --git a/src/connection.c b/src/connection.c index 0d33571..898b574 100755 --- a/src/connection.c +++ b/src/connection.c @@ -153,6 +153,22 @@ static void __connection_set_proxy_changed_callback(connection_handle_s *conn_ha conn_handle->proxy_changed_callback = __connection_dummy_address_changed_cb; } +static void __connection_dummy_dhcp_state_changed_cb(connection_dhcp_state_e state, + const char *interface_name, connection_error_e result, void *user_data) +{ + CONNECTION_LOG(CONNECTION_INFO, "Dummy callback"); +} + +static void __connection_set_dhcp_state_changed_callback(connection_handle_s *conn_handle, + void *callback, void *user_data) +{ + conn_handle->dhcp_state_changed_user_data = user_data; + if (callback != NULL) + conn_handle->dhcp_state_changed_callback = callback; + else + conn_handle->dhcp_state_changed_callback = __connection_dummy_dhcp_state_changed_cb; +} + static void __connection_dummy_internet_state_changed_cb(connection_internet_state_e state, void* user_data) { @@ -305,6 +321,7 @@ EXPORT_API int connection_destroy(connection_h connection) __connection_set_proxy_changed_callback(connection, NULL, NULL); __connection_set_internet_state_changed_callback(connection, NULL, NULL); __connection_set_ethernet_cable_state_changed_cb(connection, NULL, NULL); + __connection_set_dhcp_state_changed_callback(connection, NULL, NULL); _connection_handle_unref(connection); @@ -718,6 +735,31 @@ EXPORT_API int connection_get_ethernet_cable_state(connection_h connection, conn return CONNECTION_ERROR_NONE; } +EXPORT_API int connection_get_dhcp_state(connection_h connection, + const char *interface_name, connection_dhcp_state_e *state) +{ + CONN_LOCK; + + CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE); + + if (interface_name == NULL || state == NULL || + !(__connection_check_handle_validity(connection))) { + CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter"); + CONN_UNLOCK; + return CONNECTION_ERROR_INVALID_PARAMETER; + } + + int rv = _connection_libnet_get_dhcp_state(connection, interface_name, state); + if (rv != CONNECTION_ERROR_NONE) { + CONNECTION_LOG(CONNECTION_ERROR, "Fail to get DHCP state[%d]", rv); //LCOV_EXCL_LINE + CONN_UNLOCK; //LCOV_EXCL_LINE + return rv; //LCOV_EXCL_LINE + } + + CONN_UNLOCK; + return CONNECTION_ERROR_NONE; +} + EXPORT_API int connection_set_ethernet_cable_state_chaged_cb(connection_h connection, connection_ethernet_cable_state_chaged_cb callback, void *user_data) { @@ -933,6 +975,43 @@ EXPORT_API int connection_unset_proxy_address_changed_cb(connection_h connection return CONNECTION_ERROR_NONE; } +EXPORT_API int connection_set_dhcp_state_changed_cb(connection_h connection, + connection_dhcp_state_changed_cb callback, void *user_data) +{ + CONN_LOCK; + + CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE); + + if (callback == NULL || !(__connection_check_handle_validity(connection))) { + CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter"); + CONN_UNLOCK; + return CONNECTION_ERROR_INVALID_PARAMETER; + } + + __connection_set_dhcp_state_changed_callback(connection, callback, user_data); + + CONN_UNLOCK; + return CONNECTION_ERROR_NONE; +} + +EXPORT_API int connection_unset_dhcp_state_changed_cb(connection_h connection) +{ + CONN_LOCK; + + CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE); + + if (!(__connection_check_handle_validity(connection))) { + CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter"); + CONN_UNLOCK; + return CONNECTION_ERROR_INVALID_PARAMETER; + } + + __connection_set_dhcp_state_changed_callback(connection, NULL, NULL); + + CONN_UNLOCK; + return CONNECTION_ERROR_NONE; +} + EXPORT_API int connection_set_internet_state_changed_cb(connection_h connection, connection_internet_state_changed_cb callback, void *user_data) { diff --git a/src/libnetwork.c b/src/libnetwork.c index 5ed4ddb..c357e3c 100755 --- a/src/libnetwork.c +++ b/src/libnetwork.c @@ -576,6 +576,48 @@ static void __libnet_evt_cb(net_event_info_t *event_cb, void *user_data) return; } break; + case NET_EVENT_DHCP_STATE_CHANGED: + CONNECTION_LOG(CONNECTION_INFO, "Got DHCP Changed Indication"); + net_dhcp_state_info_t *dhcp_state_info = (net_dhcp_state_info_t*)event_cb->data; + connection_dhcp_state_e dhcp_state = CONNECTION_DHCP_STATE_UNKNOWN; + connection_error_e result = CONNECTION_ERROR_NONE; + + if (!dhcp_state_info || !dhcp_state_info->ifname || !dhcp_state_info->state) { + CONN_UNLOCK; + return; + } + + if (conn_handle->dhcp_state_changed_callback) { + if (g_strcmp0(dhcp_state_info->state, "DHCP_STARTED") == 0) { + result = CONNECTION_ERROR_NONE; + dhcp_state = CONNECTION_DHCP_STATE_STARTED; + } else if (g_strcmp0(dhcp_state_info->state, "DHCP_SUCCESS") == 0) { + result = CONNECTION_ERROR_NONE; + dhcp_state = CONNECTION_DHCP_STATE_FINISHED; + } else if (g_strcmp0(dhcp_state_info->state, "DHCP_FAIL") == 0) { + result = CONNECTION_ERROR_DHCP_FAILED; + dhcp_state = CONNECTION_DHCP_STATE_FINISHED; + } else { + result = CONNECTION_ERROR_NONE; + dhcp_state = CONNECTION_DHCP_STATE_UNKNOWN; + } + + _connection_handle_ref(conn_handle); + CONN_UNLOCK; + + conn_handle->dhcp_state_changed_callback( + dhcp_state, + dhcp_state_info->ifname, + result, + conn_handle->dhcp_state_changed_user_data); + + CONN_LOCK; + _connection_handle_unref(conn_handle); + CONN_UNLOCK; + + return; + } + break; case NET_EVENT_INTERNET_ONLINE_IND: case NET_EVENT_INTERNET_OFFLINE_IND: CONNECTION_LOG(CONNECTION_INFO, "Got Internet State Changed Indication: %s", @@ -911,6 +953,35 @@ int _connection_libnet_get_ethernet_cable_state(connection_handle_s *conn_handle *state = CONNECTION_ETHERNET_CABLE_DETACHED; return CONNECTION_ERROR_NONE; } + +int _connection_libnet_get_dhcp_state(connection_handle_s *conn_handle, + const char *interface_name, connection_dhcp_state_e *state) +{ + int rv = 0; + char *status_str = NULL; + + rv = net_get_dhcp_state(conn_handle->network_info_handle, interface_name, &status_str); + if (rv == NET_ERR_ACCESS_DENIED) { + CONNECTION_LOG(CONNECTION_ERROR, "Access denied"); + return CONNECTION_ERROR_PERMISSION_DENIED; + } else if (rv != NET_ERR_NONE) { + CONNECTION_LOG(CONNECTION_ERROR, "Failed to get DHCP state[%d]", rv); + return CONNECTION_ERROR_OPERATION_FAILED; + } + + if (g_strcmp0(status_str, "DHCP_STARTED") == 0) + *state = CONNECTION_DHCP_STATE_STARTED; + else if (g_strcmp0(status_str, "DHCP_SUCCESS") == 0) + *state = CONNECTION_DHCP_STATE_FINISHED; + else if (g_strcmp0(status_str, "DHCP_FAIL") == 0) + *state = CONNECTION_DHCP_STATE_FINISHED; + else + *state = CONNECTION_DHCP_STATE_UNKNOWN; + + g_free(status_str); + + return CONNECTION_ERROR_NONE; +} //LCOV_EXCL_STOP int _connection_libnet_get_bluetooth_state(connection_handle_s *conn_handle, connection_bt_state_e *state) diff --git a/test/connection_test.c b/test/connection_test.c index 3db86eb..ecbfd3d 100755 --- a/test/connection_test.c +++ b/test/connection_test.c @@ -290,6 +290,13 @@ static void test_internet_state_changed_callback(connection_internet_state_e sta printf("Internet state changed callback, state : %d\n", state); } +static void test_dhcp_state_changed_callback(connection_dhcp_state_e state, + const char *interface_name, connection_error_e result, void *user_data) +{ + printf("DHCP state changed callback, ifname: %s, state: %d, result: %d\n", + interface_name, state, result); +} + static void test_profile_state_callback(connection_profile_state_e state, void* user_data) { char *profile_name; @@ -1098,6 +1105,7 @@ int test_register_client(void) connection_set_ethernet_cable_state_changed_cb(connection, test_get_ethernet_cable_state_callback, NULL); connection_set_internet_state_changed_cb(connection, test_internet_state_changed_callback, NULL); + connection_set_dhcp_state_changed_cb(connection, test_dhcp_state_changed_callback, NULL); } else { printf("Client registration failed [%s]\n", test_print_error(err)); return -1; @@ -2271,6 +2279,29 @@ int test_get_ethernet_cable_state(void) return 1; } +int test_get_dhcp_state(void) +{ + int rv = 0; + connection_dhcp_state_e dhcp_state; + char if_name[40] = {0}; + + if (test_get_user_string("Input Interface name: ", if_name, 40) == false) + return -1; + + g_strstrip(if_name); + + rv = connection_get_dhcp_state(connection, if_name, &dhcp_state); + + if (rv != CONNECTION_ERROR_NONE) { + printf("Fail to get DHCP state [%s]\n", test_print_error(rv)); + return -1; + } + + printf("Retval = [%s], DHCP state [%d]\n", test_print_error(rv), dhcp_state); + + return 1; +} + int test_reset_profile(void) { int type, sim_id, rv; @@ -3061,6 +3092,7 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data) printf("v - Get all cellular default profiles\n"); printf("w - Get mac address\n"); printf("x - Get ethernet cable state\n"); + printf("y - Get DHCP state\n"); printf("B - Add IPv6 new route\n"); printf("C - Remove IPv6 route\n"); printf("D - Add new route entry\n"); @@ -3188,6 +3220,9 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data) case 'x': rv = test_get_ethernet_cable_state(); break; + case 'y': + rv = test_get_dhcp_state(); + break; case 'B': rv = test_add_route_ipv6(); break;