ed3ccd4489b00d7838f5c67a4ab41290c826c543
[platform/core/connectivity/stc-manager.git] / plugin / tether / stc-plugin-tether.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <vconf/vconf.h>
18 #include <stdbool.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <errno.h>
24 #include <glib.h>
25
26 #include "stc-monitor.h"
27 #include "stc-plugin-tether.h"
28
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;
33
34 static int _compare_sta_by_mac_func(gconstpointer a,
35                 gconstpointer b)
36 {
37         tether_sta_info_s *si = (tether_sta_info_s *)a;
38         return g_ascii_strcasecmp(si->mac, (const char *)b);
39 }
40
41 static int _get_station_info(gconstpointer data, GCompareFunc func,
42                 tether_sta_info_s **si)
43 {
44         GSList *list = station_list;
45         tether_sta_info_s *info = NULL;
46
47         if (func == NULL || si == NULL)
48                 return -1;
49
50         if (!list)
51                 return -1;
52
53         list = g_slist_find_custom(list, data, func);
54         if (list == NULL)
55                 return -1;
56
57         info = list->data;
58         *si = info;
59         return 0;
60 }
61
62 static void _remove_station_info(gconstpointer data, GCompareFunc func)
63 {
64         GSList *list = station_list;
65         tether_sta_info_s *info = NULL;
66         if (func == NULL)
67                 return;
68
69         if (!list)
70                 return;
71
72         list = g_slist_find_custom(list, data, func);
73         if (list == NULL)
74                 return;
75
76         info = (tether_sta_info_s *)list->data;
77         STC_LOGI("STA-REMOVED: (%s) (%s) (%s)", info->ip, info->mac, info->name);
78         g_free(info->station_id);
79         g_free(info);
80
81         station_list = g_slist_delete_link(station_list, list);
82 }
83
84 static void _add_station_info(tether_sta_info_s *info)
85 {
86         tether_sta_info_s *tmp = NULL;
87         if (info == NULL) {
88                 STC_LOGE("info is NULL");
89                 return;
90         }
91
92         if (_get_station_info(info->mac, _compare_sta_by_mac_func, &tmp) == 0) {
93                 if (!g_strcmp0(tmp->name, info->name) && !g_strcmp0(tmp->ip, info->ip))
94                         return;
95
96                 //Remove the station if dhcp info changed.
97                 _remove_station_info(info->mac, _compare_sta_by_mac_func);
98         }
99
100         station_list = g_slist_prepend(station_list, info);
101         STC_LOGI("STA-ADDED: (%s) (%s) (%s)", info->ip, info->mac, info->name);
102         info->station_id = g_strdup_printf("%s_%s", info->mac, info->name);
103 }
104
105 static void _mobileap_signal_cb(GDBusConnection *conn,
106                                const gchar *name, const gchar *path,
107                                const gchar *interface, const gchar *sig,
108                                GVariant *param, gpointer user_data)
109 {
110         int type;
111         int tm;
112         char *ip = NULL;
113         char *mac = NULL;
114         char *hostname = NULL;
115         char *state = NULL;
116         tether_sta_info_s *sta = NULL;
117
118         ret_msg_if(sig == NULL, "signal name NULL");
119         ret_msg_if(param == NULL, "param NULL");
120
121         STC_LOGI("%s interface(%s)", sig, interface);
122
123         sta = (tether_sta_info_s *)g_malloc0(sizeof(tether_sta_info_s));
124         if (sta == NULL) {
125                 STC_LOGE("g_malloc0 failed");
126                 return;
127         }
128
129         g_variant_get(param, "(susssu)", &state, &type, &ip, &mac, &hostname, &tm);
130         STC_LOGI("%s: ip(%s) mac(%s) name(%s) tm(%d)", state, ip, mac, hostname, tm);
131
132         if (!g_strcmp0(state, "DhcpConnected")) {
133                 g_strlcpy(sta->ip, ip, STATION_STR_INFO_LEN);
134                 g_strlcpy(sta->mac, mac, STATION_STR_INFO_LEN);
135                 g_strlcpy(sta->name, hostname, STATION_STR_HOSTNAME_LEN);
136                 _add_station_info(sta);
137         } else if (!g_strcmp0(state, "DhcpLeaseDeleted")) {
138                 _remove_station_info(mac, _compare_sta_by_mac_func);
139         }
140
141         g_free(state);
142         g_free(ip);
143         g_free(mac);
144         g_free(hostname);
145 }
146
147 stc_error_e tether_plugin_status_changed(void)
148 {
149         return STC_ERROR_NONE;
150 }
151
152 int tether_plugin_init(void)
153 {
154         GError *error = NULL;
155
156         if (connection)
157                 return 0;
158
159         connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
160         if (!connection) {
161                 g_error_free(error);
162                 return -1;
163         }
164
165         cancellable = g_cancellable_new();
166
167         g_mobileap_signal_sub_id = g_dbus_connection_signal_subscribe(connection,
168                                                    NULL,
169                                                    TETHERING_SERVICE_INTERFACE,
170                                                    SIGNAL_NAME_DHCP_STATUS,
171                                                    NULL, NULL,
172                                                    G_DBUS_SIGNAL_FLAGS_NONE,
173                                                    _mobileap_signal_cb,
174                                                    NULL, NULL);
175
176         STC_LOGI("tether plugin initialised");
177         return 0;
178 }
179
180 void tether_plugin_deinit(void)
181 {
182         if (!connection)
183                 return;
184
185         g_object_unref(connection);
186         g_object_unref(cancellable);
187         connection = NULL;
188         cancellable = NULL;
189         STC_LOGI("tether plugin deinitialised");
190 }
191
192 /* Tether Plugin APIs */
193 API stc_plugin_tether_s tether_plugin = {
194         .init = tether_plugin_init,
195         .deinit = tether_plugin_deinit,
196         .status_changed = tether_plugin_status_changed
197 };