Base Code merged to SPIN 2.4
[platform/core/connectivity/net-config.git] / src / network-statistics.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <vconf.h>
22 #include <vconf-keys.h>
23
24 #include "log.h"
25 #include "util.h"
26 #include "netsupplicant.h"
27 #include "network-statistics.h"
28
29 #include "generated-code.h"
30
31 #define NETCONFIG_PROCDEV                                       "/proc/net/dev"
32
33 static Network_statistics *netconfigstatistics = NULL;
34
35 gboolean netconfig_wifi_get_bytes_statistics(guint64 *tx, guint64 *rx)
36 {
37         gboolean ret = FALSE;
38         FILE *fp;
39         gchar buf[1024];
40         gchar *p_ifname = NULL, *p_entry = NULL;
41
42         *tx = 0;
43         *rx = 0;
44
45         fp = fopen(NETCONFIG_PROCDEV, "r");
46         if (fp == NULL) {
47                 ERR("Failed to open %s", NETCONFIG_PROCDEV);
48                 return FALSE;
49         }
50
51         /* skip the first and second line */
52         if (fgets(buf, sizeof(buf), fp) == NULL ||
53                         fgets(buf, sizeof(buf), fp) == NULL)
54                 goto endline;
55
56         while (fgets(buf, sizeof(buf), fp)) {
57                 guint64 llval;
58                 gulong lval;
59
60                 p_ifname = buf;
61                 while (*p_ifname == ' ') p_ifname++;
62                 p_entry = strchr(p_ifname, ':');
63                 *p_entry++ = '\0';
64
65                 if (g_strcmp0(p_ifname, WIFI_IFNAME) != 0)
66                         continue;
67
68                 /* read interface statistics */
69                 sscanf(p_entry,
70                                 "%llu %llu %lu %lu %lu %lu %lu %lu "
71                                 "%llu %llu %lu %lu %lu %lu %lu %lu",
72                                 rx,                     /* rx bytes */
73                                 &llval,         /* rx packet */
74                                 &lval,          /* rx errors */
75                                 &lval,          /* rx dropped */
76                                 &lval,          /* rx fifo errors */
77                                 &lval,          /* rx frame errors */
78                                 &lval,          /* rx compressed */
79                                 &lval,          /* rx multicast */
80
81                                 tx,                     /* tx bytes */
82                                 &llval,         /* tx packet */
83                                 &lval,          /* tx errors */
84                                 &lval,          /* tx dropped */
85                                 &lval,          /* tx fifo errors */
86                                 &lval,          /* collisions */
87                                 &lval,          /* tx carrier errors */
88                                 &lval           /* tx compressed */
89                                 );
90
91                 ret = TRUE;
92                 break;
93         }
94
95 endline:
96         fclose(fp);
97         return ret;
98 }
99
100 static gboolean handle_get_wifi_total_tx_bytes(
101                 Network_statistics *object,
102                 GDBusMethodInvocation *context)
103 {
104         guint64 tx = 0, rx = 0;
105         guint64 tx_bytes = 0;
106         guint64 total_bytes = 0;
107         int val = 0;
108
109         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, &val);
110         tx_bytes = (guint64)val;
111
112         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
113                 total_bytes = tx + tx_bytes;
114         else
115                 total_bytes = tx_bytes;
116
117         network_statistics_complete_get_wifi_total_tx_bytes(object, context, total_bytes);
118         return TRUE;
119 }
120
121 static gboolean handle_get_wifi_total_rx_bytes(
122                 Network_statistics *object,
123                 GDBusMethodInvocation *context)
124 {
125         guint64 tx = 0, rx = 0;
126         guint64 rx_bytes = 0;
127         guint64 total_bytes = 0;
128         int val = 0;
129
130         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, &val);
131         rx_bytes = (guint64)val;
132
133         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
134                 total_bytes = rx + rx_bytes;
135         else
136                 total_bytes = rx_bytes;
137
138         network_statistics_complete_get_wifi_total_rx_bytes(object, context, total_bytes);
139         return TRUE;
140 }
141
142 static gboolean handle_get_wifi_last_tx_bytes(
143                 Network_statistics *object,
144                 GDBusMethodInvocation *context)
145 {
146         guint64 tx = 0, rx = 0;
147         guint64 tx_bytes = 0;
148         guint64 last_bytes = 0;
149         int val = 0;
150
151         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, &val);
152         tx_bytes = (guint64)val;
153
154         if (netconfig_wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
155                 last_bytes = tx_bytes;
156                 network_statistics_complete_get_wifi_last_tx_bytes(object, context, last_bytes);
157                 return TRUE;
158         }
159
160         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
161                 last_bytes = tx < tx_bytes ? 0 : tx - tx_bytes;
162         else
163                 last_bytes = tx_bytes;
164
165         network_statistics_complete_get_wifi_last_tx_bytes(object, context, last_bytes);
166         return TRUE;
167 }
168
169 static gboolean handle_get_wifi_last_rx_bytes(
170                 Network_statistics *object,
171                 GDBusMethodInvocation *context)
172 {
173         guint64 tx = 0, rx = 0;
174         guint64 rx_bytes = 0;
175         guint64 last_bytes = 0;
176         int val = 0;
177
178         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, &val);
179         rx_bytes = (guint64)val;
180
181         if (netconfig_wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
182                 last_bytes = rx_bytes;
183                 network_statistics_complete_get_wifi_last_rx_bytes(object, context, last_bytes);
184                 return TRUE;
185         }
186
187         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
188                 last_bytes = rx < rx_bytes ? 0 : rx - rx_bytes;
189         else
190                 last_bytes = rx_bytes;
191
192         network_statistics_complete_get_wifi_last_rx_bytes(object, context, last_bytes);
193         return TRUE;
194 }
195
196 static gboolean handle_reset_cellular_total_tx_bytes(
197                 Network_statistics *object,
198                 GDBusMethodInvocation *context)
199 {
200         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_SNT, 0);
201         network_statistics_complete_reset_cellular_total_tx_bytes(object, context);
202         return TRUE;
203 }
204
205 static gboolean handle_reset_cellular_total_rx_bytes(
206                 Network_statistics *object,
207                 GDBusMethodInvocation *context)
208 {
209         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_RCV, 0);
210         network_statistics_complete_reset_cellular_total_rx_bytes(object, context);
211         return TRUE;
212 }
213
214 static gboolean handle_reset_cellular_last_tx_bytes(
215                 Network_statistics *object,
216                 GDBusMethodInvocation *context)
217 {
218         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_SNT, 0);
219         network_statistics_complete_reset_cellular_last_tx_bytes(object, context);
220         return TRUE;
221 }
222
223 static gboolean handle_reset_cellular_last_rx_bytes(
224                 Network_statistics *object,
225                 GDBusMethodInvocation *context)
226 {
227         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_RCV, 0);
228         network_statistics_complete_reset_cellular_last_rx_bytes(object, context);
229         return TRUE;
230 }
231
232 static gboolean handle_reset_wifi_total_tx_bytes(
233                 Network_statistics *object,
234                 GDBusMethodInvocation *context)
235 {
236         guint64 tx = 0, rx = 0;
237
238         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
239                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, -(int)tx);
240         else
241                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, 0);
242
243         network_statistics_complete_reset_wifi_total_tx_bytes(object, context);
244
245         return TRUE;
246 }
247
248 static gboolean handle_reset_wifi_total_rx_bytes(
249                 Network_statistics *object,
250                 GDBusMethodInvocation *context)
251 {
252         guint64 tx = 0, rx = 0;
253
254         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
255                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, -(int)rx);
256         else
257                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, 0);
258
259         network_statistics_complete_reset_wifi_total_rx_bytes(object, context);
260         return TRUE;
261 }
262
263 static gboolean handle_reset_wifi_last_tx_bytes(
264                 Network_statistics *object,
265                 GDBusMethodInvocation *context)
266 {
267         guint64 tx = 0, rx = 0;
268
269         if (netconfig_wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
270                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, 0);
271                 network_statistics_complete_reset_wifi_last_tx_bytes(object, context);
272                 return TRUE;
273         }
274
275         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
276                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, (int)tx);
277         else
278                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, 0);
279
280         network_statistics_complete_reset_wifi_last_tx_bytes(object, context);
281
282         return TRUE;
283 }
284
285 static gboolean handle_reset_wifi_last_rx_bytes(
286                 Network_statistics *object,
287                 GDBusMethodInvocation *context)
288 {
289         guint64 tx = 0, rx = 0;
290
291         if (netconfig_wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
292                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, 0);
293                 network_statistics_complete_reset_wifi_last_rx_bytes(object, context);
294                 return TRUE;
295         }
296
297         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
298                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, (int)rx);
299         else
300                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, 0);
301
302         network_statistics_complete_reset_wifi_last_rx_bytes(object, context);
303
304         return TRUE;
305 }
306
307 void netconfig_wifi_statistics_update_powered_off(void)
308 {
309         guint64 cur_tx = 0, cur_rx = 0;
310         guint64 prev_tx = 0, prev_rx = 0;
311         guint64 total_tx = 0, total_rx = 0;
312         int val = 0;
313
314         if (netconfig_wifi_get_bytes_statistics(&cur_tx, &cur_rx) != TRUE)
315                 return;
316
317         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, &val);
318         prev_tx = (guint64)val;
319
320         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, &val);
321         prev_rx = (guint64)val;
322
323         total_tx = prev_tx + cur_tx;
324         total_rx = prev_rx + cur_rx;
325
326         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, (int)total_tx);
327         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, (int)total_rx);
328 }
329
330 static void netconfig_wifi_statistics_update_state(
331                 enum netconfig_wifi_service_state state, void *user_data)
332 {
333         guint64 tx = 0, rx = 0;
334         guint64 last_tx = 0, last_rx = 0;
335         int val = 0;
336         static enum netconfig_wifi_service_state prev_state = NETCONFIG_WIFI_UNKNOWN;
337
338         if (prev_state == NETCONFIG_WIFI_UNKNOWN) {
339                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, 0);
340                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, 0);
341
342                 prev_state = NETCONFIG_WIFI_IDLE;
343                 return;
344         }
345
346         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) != TRUE)
347                 return;
348
349         if (state == NETCONFIG_WIFI_CONNECTED) {
350                 last_tx = tx;
351                 last_rx = rx;
352         } else {
353                 if (prev_state != NETCONFIG_WIFI_CONNECTED)
354                         return;
355
356                 vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, &val);
357                 last_tx = (guint64)val;
358
359                 vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, &val);
360                 last_rx = (guint64)val;
361
362                 last_tx = tx < last_tx ? 0 : tx - last_tx;
363                 last_rx = rx < last_rx ? 0 : rx - last_rx;
364         }
365
366         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, (int)last_tx);
367         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, (int)last_rx);
368
369         prev_state = state;
370 }
371
372 static struct netconfig_wifi_state_notifier state_notifier = {
373                 .netconfig_wifi_state_changed = netconfig_wifi_statistics_update_state,
374                 .user_data = NULL,
375 };
376
377 void netconfig_network_statistics_create_and_init(void)
378 {
379         DBG("Creating statistics object");
380         GDBusInterfaceSkeleton *interface = NULL;
381         GDBusConnection *connection = NULL;
382         GDBusObjectManagerServer *server = netconfig_get_statistics_manager();
383         if (server == NULL)
384                 return;
385
386         connection = netconfig_gdbus_get_connection();
387         g_dbus_object_manager_server_set_connection(server, connection);
388
389         /*Interface 1*/
390         netconfigstatistics = network_statistics_skeleton_new();
391
392         interface = G_DBUS_INTERFACE_SKELETON(netconfigstatistics);
393         g_signal_connect(netconfigstatistics, "handle-get-wifi-last-rx-bytes",
394                                 G_CALLBACK(handle_get_wifi_last_rx_bytes), NULL);
395         g_signal_connect(netconfigstatistics, "handle-get-wifi-last-tx-bytes",
396                                 G_CALLBACK(handle_get_wifi_last_tx_bytes), NULL);
397         g_signal_connect(netconfigstatistics, "handle-get-wifi-total-rx-bytes",
398                                 G_CALLBACK(handle_get_wifi_total_rx_bytes), NULL);
399         g_signal_connect(netconfigstatistics, "handle-get-wifi-total-tx-bytes",
400                                 G_CALLBACK(handle_get_wifi_total_tx_bytes), NULL);
401         g_signal_connect(netconfigstatistics, "handle-reset-cellular-last-rx-bytes",
402                                 G_CALLBACK(handle_reset_cellular_last_rx_bytes), NULL);
403         g_signal_connect(netconfigstatistics, "handle-reset-cellular-last-tx-bytes",
404                                 G_CALLBACK(handle_reset_cellular_last_tx_bytes), NULL);
405         g_signal_connect(netconfigstatistics, "handle-reset-cellular-total-rx-bytes",
406                                 G_CALLBACK(handle_reset_cellular_total_rx_bytes), NULL);
407         g_signal_connect(netconfigstatistics, "handle-reset-cellular-total-tx-bytes",
408                                 G_CALLBACK(handle_reset_cellular_total_tx_bytes), NULL);
409         g_signal_connect(netconfigstatistics, "handle-reset-wifi-last-rx-bytes",
410                                 G_CALLBACK(handle_reset_wifi_last_rx_bytes), NULL);
411         g_signal_connect(netconfigstatistics, "handle-reset-wifi-last-tx-bytes",
412                                 G_CALLBACK(handle_reset_wifi_last_tx_bytes), NULL);
413         g_signal_connect(netconfigstatistics, "handle-reset-wifi-total-rx-bytes",
414                                 G_CALLBACK(handle_reset_wifi_total_rx_bytes), NULL);
415         g_signal_connect(netconfigstatistics, "handle-reset-wifi-total-tx-bytes",
416                                 G_CALLBACK(handle_reset_wifi_total_tx_bytes), NULL);
417
418         if (!g_dbus_interface_skeleton_export(interface, connection,
419                         NETCONFIG_NETWORK_STATISTICS_PATH, NULL)) {
420                 ERR("Export with path failed");
421         }
422
423         netconfig_wifi_statistics_update_state(NETCONFIG_WIFI_IDLE, NULL);
424         netconfig_wifi_state_notifier_register(&state_notifier);
425
426         return;
427 }