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_value_s app_value;
40 if (pkg_id == NULL || app_id == NULL || mac == NULL) {
41 STC_LOGE("invalid station station info");
42 return STC_ERROR_INVALID_PARAMETER;
45 memset(&app_value, 0, sizeof(stc_app_value_s));
46 app_value.pkg_id = g_strdup(pkg_id);
47 app_value.app_id = g_strconcat(app_id, STC_TETHERING_APP_SUFFIX, NULL);
48 app_value.type = STC_APP_TYPE_TETHERING;
49 app_value.processes = NULL;
50 g_strlcpy(app_value.mac, mac, STATION_MAC_STR_LEN);
52 ret = stc_monitor_app_add(STC_UNKNOWN_CLASSID, app_id, pkg_id, app_value);
53 FREE(app_value.pkg_id);
54 FREE(app_value.app_id);
58 static stc_error_e remove_station_monitor(gchar *pkg_id, gchar *app_id)
63 if (pkg_id == NULL || app_id == NULL) {
64 STC_LOGE("invalid station station info");
65 return STC_ERROR_INVALID_PARAMETER;
68 sta_app_id = g_strconcat(app_id, STC_TETHERING_APP_SUFFIX, NULL);
70 ret = stc_monitor_app_remove(STC_UNKNOWN_CLASSID, sta_app_id);
76 static int _compare_sta_by_mac_func(gconstpointer a,
79 tether_sta_info_s *si = (tether_sta_info_s *)a;
80 return g_ascii_strcasecmp(si->mac, (const char *)b);
83 static int _compare_sta_by_classid_func(gconstpointer a,
86 tether_sta_info_s *si = (tether_sta_info_s *)a;
87 int *classid = (int *)b;
88 return si->classid - *classid;
91 static int _get_station_info(gconstpointer data, GCompareFunc func,
92 tether_sta_info_s **si)
94 GSList *list = station_list;
95 tether_sta_info_s *info = NULL;
97 if (func == NULL || si == NULL)
103 list = g_slist_find_custom(list, data, func);
112 static void _remove_station_info(gconstpointer data, GCompareFunc func)
114 GSList *list = station_list;
115 tether_sta_info_s *info = NULL;
122 list = g_slist_find_custom(list, data, func);
126 info = (tether_sta_info_s *)list->data;
127 STC_LOGI("STA-REMOVED: (%s) (%s) (%s)", info->ip, info->mac, info->name);
129 /* remove tethering client from monitoring */
130 remove_station_monitor(info->mac, info->station_id);
132 g_free(info->station_id);
135 station_list = g_slist_delete_link(station_list, list);
138 static void _add_station_info(tether_sta_info_s *info)
140 tether_sta_info_s *tmp = NULL;
142 STC_LOGE("info is NULL");
146 if (_get_station_info(info->mac, _compare_sta_by_mac_func, &tmp) == 0) {
147 if (!g_strcmp0(tmp->name, info->name) && !g_strcmp0(tmp->ip, info->ip))
150 /* Remove the station if dhcp info changed. */
151 _remove_station_info(info->mac, _compare_sta_by_mac_func);
154 station_list = g_slist_prepend(station_list, info);
155 STC_LOGI("STA-ADDED: (%s) (%s) (%s)", info->ip, info->mac, info->name);
157 /* add tethering client for monitoring data usage */
158 info->station_id = g_strdup_printf("%s_%s", info->mac, info->name);
159 add_station_monitor(info->mac, info->station_id, info->mac);
162 static void _mobileap_signal_cb(GDBusConnection *conn,
163 const gchar *name, const gchar *path,
164 const gchar *interface, const gchar *sig,
165 GVariant *param, gpointer user_data)
171 char *hostname = NULL;
173 tether_sta_info_s *sta = NULL;
175 ret_msg_if(sig == NULL, "signal name NULL");
176 ret_msg_if(param == NULL, "param NULL");
178 STC_LOGI("%s interface(%s)", sig, interface);
180 g_variant_get(param, "(susssu)", &state, &type, &ip, &mac, &hostname, &tm);
181 STC_LOGI("%s: ip(%s) mac(%s) name(%s) tm(%d)", state, ip, mac, hostname, tm);
183 if (!g_strcmp0(state, "DhcpConnected")) {
184 sta = (tether_sta_info_s *)g_malloc0(sizeof(tether_sta_info_s));
186 STC_LOGE("g_malloc0 failed");
190 g_strlcpy(sta->ip, ip, INET_ADDRSTRLEN);
191 g_strlcpy(sta->mac, mac, STATION_MAC_STR_LEN);
192 g_strlcpy(sta->name, hostname, STATION_STR_HOSTNAME_LEN);
193 _add_station_info(sta);
194 } else if (!g_strcmp0(state, "DhcpLeaseDeleted")) {
195 _remove_station_info(mac, _compare_sta_by_mac_func);
204 stc_error_e tether_plugin_get_station_ip(const char *mac, char *ip)
206 tether_sta_info_s *tmp = NULL;
208 if (mac == NULL || ip == NULL)
209 return STC_ERROR_FAIL;
211 if (_get_station_info((gconstpointer)mac,
212 _compare_sta_by_mac_func, &tmp) != 0) {
213 STC_LOGE("mac(%s) not found", mac);
214 return STC_ERROR_FAIL;
217 g_strlcpy(ip, tmp->ip, INET_ADDRSTRLEN);
218 return STC_ERROR_NONE;
221 stc_error_e tether_plugin_get_station_by_classid(const int classid, char *mac)
223 tether_sta_info_s *tmp = NULL;
224 int classid_value = classid;
227 return STC_ERROR_FAIL;
229 if (_get_station_info((gconstpointer)&classid_value,
230 _compare_sta_by_classid_func, &tmp) != 0) {
231 STC_LOGE("classid(%d) not found", classid);
232 return STC_ERROR_FAIL;
235 g_strlcpy(mac, tmp->mac, STATION_MAC_STR_LEN);
236 return STC_ERROR_NONE;
239 stc_error_e tether_plugin_set_station_classid(const char *mac, int classid)
241 tether_sta_info_s *tmp = NULL;
244 STC_LOGE("invalid param");
245 return STC_ERROR_FAIL;
248 if (_get_station_info((gconstpointer)mac,
249 _compare_sta_by_mac_func, &tmp) != 0) {
250 STC_LOGE("mac(%s) not found", mac);
251 return STC_ERROR_FAIL;
255 tmp->classid = classid;
257 return STC_ERROR_NONE;
260 int tether_plugin_init(void)
262 GError *error = NULL;
267 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
273 cancellable = g_cancellable_new();
275 g_mobileap_signal_sub_id = g_dbus_connection_signal_subscribe(connection,
277 TETHERING_SERVICE_INTERFACE,
278 SIGNAL_NAME_DHCP_STATUS,
280 G_DBUS_SIGNAL_FLAGS_NONE,
284 STC_LOGI("tether plugin initialised");
288 void tether_plugin_deinit(void)
293 g_object_unref(connection);
294 g_object_unref(cancellable);
297 STC_LOGI("tether plugin deinitialised");
300 API stc_plugin_tether_s tether_plugin = {
301 .init = tether_plugin_init,
302 .deinit = tether_plugin_deinit,
303 .get_station_ip = tether_plugin_get_station_ip,
304 .get_station_by_classid = tether_plugin_get_station_by_classid,
305 .set_station_classid = tether_plugin_set_station_classid