2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <vconf/vconf.h>
26 #include "stc-monitor.h"
27 #include "stc-plugin-tether.h"
29 static GSList *station_list = NULL;
30 static GDBusConnection *connection = NULL;
31 static GCancellable *cancellable = NULL;
32 static int g_mobileap_signal_sub_id = 0;
34 static stc_error_e add_station_monitor(gchar *pkg_id, gchar *app_id,
38 stc_app_key_s app_key;
39 stc_app_value_s app_value;
41 if (pkg_id == NULL || app_id == NULL || mac == NULL) {
42 STC_LOGE("invalid station station info");
43 return STC_ERROR_INVALID_PARAMETER;
46 memset(&app_key, 0, sizeof(stc_app_key_s));
47 memset(&app_value, 0, sizeof(stc_app_value_s));
48 app_key.pkg_id = g_strdup(pkg_id);
49 app_key.app_id = g_strconcat(app_id, STC_TETHERING_APP_SUFFIX, NULL);
50 app_value.type = STC_APP_TYPE_TETHERING;
51 app_value.processes = NULL;
52 g_strlcpy(app_value.mac, mac, STATION_MAC_STR_LEN);
54 ret = stc_monitor_application_add(app_key, app_value);
60 static stc_error_e remove_station_monitor(gchar *pkg_id, gchar *app_id)
63 stc_app_key_s app_key;
65 if (pkg_id == NULL || app_id == NULL) {
66 STC_LOGE("invalid station station info");
67 return STC_ERROR_INVALID_PARAMETER;
70 memset(&app_key, 0, sizeof(stc_app_key_s));
71 app_key.pkg_id = g_strdup(pkg_id);
72 app_key.app_id = g_strconcat(app_id, STC_TETHERING_APP_SUFFIX, NULL);
74 ret = stc_monitor_application_remove(app_key);
80 static int _compare_sta_by_mac_func(gconstpointer a,
83 tether_sta_info_s *si = (tether_sta_info_s *)a;
84 return g_ascii_strcasecmp(si->mac, (const char *)b);
87 static int _compare_sta_by_classid_func(gconstpointer a,
90 tether_sta_info_s *si = (tether_sta_info_s *)a;
91 int *classid = (int *)b;
92 return si->classid - *classid;
95 static int _get_station_info(gconstpointer data, GCompareFunc func,
96 tether_sta_info_s **si)
98 GSList *list = station_list;
99 tether_sta_info_s *info = NULL;
101 if (func == NULL || si == NULL)
107 list = g_slist_find_custom(list, data, func);
116 static void _remove_station_info(gconstpointer data, GCompareFunc func)
118 GSList *list = station_list;
119 tether_sta_info_s *info = NULL;
126 list = g_slist_find_custom(list, data, func);
130 info = (tether_sta_info_s *)list->data;
131 STC_LOGI("STA-REMOVED: (%s) (%s) (%s)", info->ip, info->mac, info->name);
133 /* remove tethering client from monitoring */
134 remove_station_monitor(info->mac, info->station_id);
136 g_free(info->station_id);
139 station_list = g_slist_delete_link(station_list, list);
142 static void _add_station_info(tether_sta_info_s *info)
144 tether_sta_info_s *tmp = NULL;
146 STC_LOGE("info is NULL");
150 if (_get_station_info(info->mac, _compare_sta_by_mac_func, &tmp) == 0) {
151 if (!g_strcmp0(tmp->name, info->name) && !g_strcmp0(tmp->ip, info->ip))
154 /* Remove the station if dhcp info changed. */
155 _remove_station_info(info->mac, _compare_sta_by_mac_func);
158 station_list = g_slist_prepend(station_list, info);
159 STC_LOGI("STA-ADDED: (%s) (%s) (%s)", info->ip, info->mac, info->name);
161 /* add tethering client for monitoring data usage */
162 info->station_id = g_strdup_printf("%s_%s", info->mac, info->name);
163 add_station_monitor(info->mac, info->station_id, info->mac);
166 static void _mobileap_signal_cb(GDBusConnection *conn,
167 const gchar *name, const gchar *path,
168 const gchar *interface, const gchar *sig,
169 GVariant *param, gpointer user_data)
175 char *hostname = NULL;
177 tether_sta_info_s *sta = NULL;
179 ret_msg_if(sig == NULL, "signal name NULL");
180 ret_msg_if(param == NULL, "param NULL");
182 STC_LOGI("%s interface(%s)", sig, interface);
184 g_variant_get(param, "(susssu)", &state, &type, &ip, &mac, &hostname, &tm);
185 STC_LOGI("%s: ip(%s) mac(%s) name(%s) tm(%d)", state, ip, mac, hostname, tm);
187 if (!g_strcmp0(state, "DhcpConnected")) {
188 sta = (tether_sta_info_s *)g_malloc0(sizeof(tether_sta_info_s));
190 STC_LOGE("g_malloc0 failed");
194 g_strlcpy(sta->ip, ip, INET_ADDRSTRLEN);
195 g_strlcpy(sta->mac, mac, STATION_MAC_STR_LEN);
196 g_strlcpy(sta->name, hostname, STATION_STR_HOSTNAME_LEN);
197 _add_station_info(sta);
198 } else if (!g_strcmp0(state, "DhcpLeaseDeleted")) {
199 _remove_station_info(mac, _compare_sta_by_mac_func);
208 stc_error_e tether_plugin_get_station_ip(const char *mac, char *ip)
210 tether_sta_info_s *tmp = NULL;
212 if (mac == NULL || ip == NULL)
213 return STC_ERROR_FAIL;
215 if (_get_station_info((gconstpointer)mac,
216 _compare_sta_by_mac_func, &tmp) != 0) {
217 STC_LOGE("mac(%s) not found", mac);
218 return STC_ERROR_FAIL;
221 g_strlcpy(ip, tmp->ip, INET_ADDRSTRLEN);
222 return STC_ERROR_NONE;
225 stc_error_e tether_plugin_get_station_by_classid(const int classid, char *mac)
227 tether_sta_info_s *tmp = NULL;
228 int classid_value = classid;
231 return STC_ERROR_FAIL;
233 if (_get_station_info((gconstpointer)&classid_value,
234 _compare_sta_by_classid_func, &tmp) != 0) {
235 STC_LOGE("classid(%s) not found", classid);
236 return STC_ERROR_FAIL;
239 g_strlcpy(mac, tmp->mac, STATION_MAC_STR_LEN);
240 return STC_ERROR_NONE;
243 stc_error_e tether_plugin_set_station_classid(const char *mac, int classid)
245 tether_sta_info_s *tmp = NULL;
248 STC_LOGE("invalid param");
249 return STC_ERROR_FAIL;
252 if (_get_station_info((gconstpointer)mac,
253 _compare_sta_by_mac_func, &tmp) != 0) {
254 STC_LOGE("mac(%s) not found", mac);
255 return STC_ERROR_FAIL;
259 tmp->classid = classid;
261 return STC_ERROR_NONE;
264 int tether_plugin_init(void)
266 GError *error = NULL;
271 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
277 cancellable = g_cancellable_new();
279 g_mobileap_signal_sub_id = g_dbus_connection_signal_subscribe(connection,
281 TETHERING_SERVICE_INTERFACE,
282 SIGNAL_NAME_DHCP_STATUS,
284 G_DBUS_SIGNAL_FLAGS_NONE,
288 STC_LOGI("tether plugin initialised");
292 void tether_plugin_deinit(void)
297 g_object_unref(connection);
298 g_object_unref(cancellable);
301 STC_LOGI("tether plugin deinitialised");
304 API stc_plugin_tether_s tether_plugin = {
305 .init = tether_plugin_init,
306 .deinit = tether_plugin_deinit,
307 .get_station_ip = tether_plugin_get_station_ip,
308 .get_station_by_classid = tether_plugin_get_station_by_classid,
309 .set_station_classid = tether_plugin_set_station_classid