Merge "Add dbus method for getting wifi passphrase" into tizen
[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-state.h"
28 #include "network-statistics.h"
29
30 #include "generated-code.h"
31
32 #define NETCONFIG_PROCDEV                                       "/proc/net/dev"
33 #define WIFI_VCONF_UPDATE_INTERVAL                      3600
34
35 static struct {
36         guint64 tx_diff;
37         guint64 rx_diff;
38         guint64 last_tx_offset;
39         guint64 last_rx_offset;
40 } stat_count;
41
42 static guint wifi_vconf_update_timer = 0;
43 static Network_statistics *netconfigstatistics = NULL;
44
45 static wifi_device_data_s *__find_wifi_interface_name(const char *interface_name)
46 {
47         GSList *list = wifi_state_get_device_list();
48
49         for ( ; list; list = list->next) {
50                 wifi_device_data_s *device_data = list->data;
51                 if (g_strcmp0(device_data->interface_name, interface_name) == 0)
52                         return device_data;
53         }
54
55         return NULL;
56 }
57
58 gboolean netconfig_wifi_get_bytes_statistics(guint64 *tx, guint64 *rx, gboolean update)
59 {
60         gboolean ret = FALSE;
61         FILE *fp;
62         gchar buf[1024];
63         gchar *p_ifname = NULL, *p_entry = NULL;
64         guint64 curr_tx = 0;
65         guint64 curr_rx = 0;
66         wifi_device_data_s *device_data = NULL;
67
68         *tx = 0;
69         *rx = 0;
70
71         fp = fopen(NETCONFIG_PROCDEV, "r");
72         if (fp == NULL) {
73                 ERR("Failed to open %s", NETCONFIG_PROCDEV);
74                 return FALSE;
75         }
76
77         /* skip the first and second line */
78         if (fgets(buf, sizeof(buf), fp) == NULL ||
79                         fgets(buf, sizeof(buf), fp) == NULL)
80                 goto endline;
81
82         while (fgets(buf, sizeof(buf), fp)) {
83                 long long unsigned int llval;
84                 gulong lval;
85
86                 p_ifname = buf;
87                 while (*p_ifname == ' ') p_ifname++;
88                 p_entry = strchr(p_ifname, ':');
89                 if (p_entry == NULL)
90                         continue;
91
92                 *p_entry++ = '\0';
93
94                 device_data = __find_wifi_interface_name(p_ifname);
95                 if (device_data == NULL)
96                         continue;
97
98                 /* read interface statistics */
99                 sscanf(p_entry,
100                                 "%llu %llu %lu %lu %lu %lu %lu %lu "
101                                 "%llu %llu %lu %lu %lu %lu %lu %lu",
102                                 (long long unsigned int *)&curr_rx, /* rx bytes */
103                                 &llval,         /* rx packet */
104                                 &lval,          /* rx errors */
105                                 &lval,          /* rx dropped */
106                                 &lval,          /* rx fifo errors */
107                                 &lval,          /* rx frame errors */
108                                 &lval,          /* rx compressed */
109                                 &lval,          /* rx multicast */
110
111                                 (long long unsigned int *)&curr_tx, /* tx bytes */
112                                 &llval,         /* tx packet */
113                                 &lval,          /* tx errors */
114                                 &lval,          /* tx dropped */
115                                 &lval,          /* tx fifo errors */
116                                 &lval,          /* collisions */
117                                 &lval,          /* tx carrier errors */
118                                 &lval           /* tx compressed */
119                                 );
120
121                 if (update == TRUE) {
122                         device_data->tx_diff = curr_tx - device_data->tx;
123                         device_data->rx_diff = curr_rx - device_data->rx;
124                         device_data->tx = curr_tx;
125                         device_data->rx = curr_rx;
126                 }
127
128                 *tx += device_data->tx_diff;
129                 *rx += device_data->rx_diff;
130
131                 ret = TRUE;
132         }
133
134 endline:
135         fclose(fp);
136         return ret;
137 }
138
139 void netconfig_wifi_get_bytes_default_iface(guint64 *tx, guint64 *rx)
140 {
141         wifi_device_data_s *device_data = NULL;
142
143         *tx = 0;
144         *rx = 0;
145
146         device_data = __find_wifi_interface_name(netconfig_get_default_ifname());
147         if (device_data == NULL)
148                 return;
149
150         *tx = device_data->tx_diff;
151         *rx = device_data->rx_diff;
152 }
153
154 void netconfig_wifi_set_bytes_pkt_vconf(guint64 tx_diff, guint64 rx_diff, gboolean update)
155 {
156         int val = 0;
157         guint64 last_tx = 0, last_rx = 0;
158         guint64 total_tx = 0, total_rx = 0;
159
160         stat_count.tx_diff += tx_diff;
161         stat_count.rx_diff += rx_diff;
162
163         if (update) {
164                 /* LAST */
165                 netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, &val);
166                 last_tx = (guint64)val + stat_count.tx_diff - stat_count.last_tx_offset;
167
168                 netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, &val);
169                 last_rx = (guint64)val + stat_count.rx_diff - stat_count.last_rx_offset;
170
171                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, (int)last_tx, FALSE);
172                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, (int)last_rx, FALSE);
173
174                 stat_count.last_tx_offset = 0;
175                 stat_count.last_rx_offset = 0;
176
177                 /* TOTAL */
178                 netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, &val);
179                 total_tx = (guint64)val + stat_count.tx_diff;
180
181                 netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, &val);
182                 total_rx = (guint64)val + stat_count.rx_diff;
183
184                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, (int)total_tx, FALSE);
185                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, (int)total_rx, FALSE);
186
187                 stat_count.rx_diff = 0;
188                 stat_count.tx_diff = 0;
189         }
190 }
191
192 void netconfig_wifi_reset_last_bytes(void)
193 {
194         int val = 0;
195
196         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, &val);
197         stat_count.last_tx_offset = (guint64)val + stat_count.tx_diff;
198
199         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, &val);
200         stat_count.last_rx_offset = (guint64)val + stat_count.rx_diff;
201 }
202
203 static gboolean handle_get_wifi_total_tx_bytes(
204                 Network_statistics *object,
205                 GDBusMethodInvocation *context)
206 {
207         int wifi_state = 0;
208         guint64 tx = 0, rx = 0;
209         guint64 tx_bytes = 0;
210         guint64 total_bytes = 0;
211         int val = 0;
212
213         netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
214
215         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, &val);
216         tx_bytes = (guint64)val + stat_count.tx_diff;
217
218         if (wifi_state != VCONFKEY_WIFI_CONNECTED) {
219                 total_bytes = tx_bytes;
220                 network_statistics_complete_get_wifi_total_tx_bytes(object, context, total_bytes);
221                 return TRUE;
222         }
223
224         if (netconfig_wifi_get_bytes_statistics(&tx, &rx, FALSE) == TRUE) {
225                 total_bytes = tx + tx_bytes;
226                 stat_count.tx_diff += tx;
227                 stat_count.rx_diff += rx;
228         } else {
229                 total_bytes = tx_bytes;
230         }
231
232         network_statistics_complete_get_wifi_total_tx_bytes(object, context, total_bytes);
233         return TRUE;
234 }
235
236 static gboolean handle_get_wifi_total_rx_bytes(
237                 Network_statistics *object,
238                 GDBusMethodInvocation *context)
239 {
240         int wifi_state = 0;
241         guint64 tx = 0, rx = 0;
242         guint64 rx_bytes = 0;
243         guint64 total_bytes = 0;
244         int val = 0;
245
246         netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
247
248         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, &val);
249         rx_bytes = (guint64)val + stat_count.rx_diff;
250
251         if (wifi_state != VCONFKEY_WIFI_CONNECTED) {
252                 total_bytes = rx_bytes;
253                 network_statistics_complete_get_wifi_total_rx_bytes(object, context, total_bytes);
254                 return TRUE;
255         }
256
257         if (netconfig_wifi_get_bytes_statistics(&tx, &rx, FALSE) == TRUE) {
258                 total_bytes = rx + rx_bytes;
259                 stat_count.tx_diff += tx;
260                 stat_count.rx_diff += rx;
261         } else {
262                 total_bytes = rx_bytes;
263         }
264
265         network_statistics_complete_get_wifi_total_rx_bytes(object, context, total_bytes);
266         return TRUE;
267 }
268
269 static gboolean handle_get_wifi_last_tx_bytes(
270                 Network_statistics *object,
271                 GDBusMethodInvocation *context)
272 {
273         int wifi_state = 0;
274         guint64 tx = 0, rx = 0;
275         guint64 tx_bytes = 0;
276         guint64 last_bytes = 0;
277         int val = 0;
278
279         netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
280
281         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, &val);
282         tx_bytes = (guint64)val + stat_count.tx_diff - stat_count.last_tx_offset;
283
284         if (wifi_state != VCONFKEY_WIFI_CONNECTED) {
285                 last_bytes = tx_bytes;
286                 network_statistics_complete_get_wifi_last_tx_bytes(object, context, last_bytes);
287                 return TRUE;
288         }
289
290         if (netconfig_wifi_get_bytes_statistics(&tx, &rx, FALSE) == TRUE) {
291                 last_bytes = tx + tx_bytes;
292                 stat_count.tx_diff += tx;
293                 stat_count.rx_diff += rx;
294         } else {
295                 last_bytes = tx_bytes;
296         }
297
298         network_statistics_complete_get_wifi_last_tx_bytes(object, context, last_bytes);
299         return TRUE;
300 }
301
302 static gboolean handle_get_wifi_last_rx_bytes(
303                 Network_statistics *object,
304                 GDBusMethodInvocation *context)
305 {
306         int wifi_state = 0;
307         guint64 tx = 0, rx = 0;
308         guint64 rx_bytes = 0;
309         guint64 last_bytes = 0;
310         int val = 0;
311
312         netconfig_vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
313
314         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, &val);
315         rx_bytes = (guint64)val + stat_count.rx_diff - stat_count.last_rx_offset;
316
317         if (wifi_state != VCONFKEY_WIFI_CONNECTED) {
318                 last_bytes = rx_bytes;
319                 network_statistics_complete_get_wifi_last_rx_bytes(object, context, last_bytes);
320                 return TRUE;
321         }
322
323         if (netconfig_wifi_get_bytes_statistics(&tx, &rx, FALSE) == TRUE) {
324                 last_bytes = rx + rx_bytes;
325                 stat_count.tx_diff += tx;
326                 stat_count.rx_diff += rx;
327         } else {
328                 last_bytes = rx_bytes;
329         }
330
331         network_statistics_complete_get_wifi_last_rx_bytes(object, context, last_bytes);
332         return TRUE;
333 }
334
335 static gboolean handle_reset_cellular_total_tx_bytes(
336                 Network_statistics *object,
337                 GDBusMethodInvocation *context)
338 {
339         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_SNT, 0, TRUE);
340         network_statistics_complete_reset_cellular_total_tx_bytes(object, context);
341         return TRUE;
342 }
343
344 static gboolean handle_reset_cellular_total_rx_bytes(
345                 Network_statistics *object,
346                 GDBusMethodInvocation *context)
347 {
348         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_RCV, 0, TRUE);
349         network_statistics_complete_reset_cellular_total_rx_bytes(object, context);
350         return TRUE;
351 }
352
353 static gboolean handle_reset_cellular_last_tx_bytes(
354                 Network_statistics *object,
355                 GDBusMethodInvocation *context)
356 {
357         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_SNT, 0, TRUE);
358         network_statistics_complete_reset_cellular_last_tx_bytes(object, context);
359         return TRUE;
360 }
361
362 static gboolean handle_reset_cellular_last_rx_bytes(
363                 Network_statistics *object,
364                 GDBusMethodInvocation *context)
365 {
366         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_RCV, 0, TRUE);
367         network_statistics_complete_reset_cellular_last_rx_bytes(object, context);
368         return TRUE;
369 }
370
371 static gboolean handle_reset_wifi_total_tx_bytes(
372                 Network_statistics *object,
373                 GDBusMethodInvocation *context)
374 {
375         int val = 0;
376         guint64 last_tx = 0;
377
378         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, &val);
379         last_tx = (guint64)val + stat_count.tx_diff - stat_count.last_tx_offset;
380
381         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, (int)last_tx, FALSE);
382         stat_count.last_tx_offset = 0;
383         stat_count.tx_diff = 0;
384
385         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, 0, TRUE);
386         network_statistics_complete_reset_wifi_total_tx_bytes(object, context);
387         return TRUE;
388 }
389
390 static gboolean handle_reset_wifi_total_rx_bytes(
391                 Network_statistics *object,
392                 GDBusMethodInvocation *context)
393 {
394         int val = 0;
395         guint64 last_rx = 0;
396
397         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, &val);
398         last_rx = (guint64)val + stat_count.rx_diff - stat_count.last_rx_offset;
399
400         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, (int)last_rx, FALSE);
401         stat_count.last_rx_offset = 0;
402         stat_count.rx_diff = 0;
403
404         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, 0, TRUE);
405         network_statistics_complete_reset_wifi_total_rx_bytes(object, context);
406         return TRUE;
407 }
408
409 static gboolean handle_reset_wifi_last_tx_bytes(
410                 Network_statistics *object,
411                 GDBusMethodInvocation *context)
412 {
413         int val = 0;
414         guint64 total_tx = 0;
415
416         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, &val);
417         total_tx = (guint64)val + stat_count.tx_diff;
418
419         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, (int)total_tx, FALSE);
420         stat_count.tx_diff = 0;
421
422         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, 0, TRUE);
423         stat_count.last_tx_offset = 0;
424         network_statistics_complete_reset_wifi_last_tx_bytes(object, context);
425         return TRUE;
426 }
427
428 static gboolean handle_reset_wifi_last_rx_bytes(
429                 Network_statistics *object,
430                 GDBusMethodInvocation *context)
431 {
432         int val = 0;
433         guint64 total_rx = 0;
434
435         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, &val);
436         total_rx = (guint64)val + stat_count.rx_diff;
437
438         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, (int)total_rx, FALSE);
439         stat_count.rx_diff = 0;
440
441         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, 0, TRUE);
442         stat_count.last_rx_offset = 0;
443         network_statistics_complete_reset_wifi_last_rx_bytes(object, context);
444         return TRUE;
445 }
446
447 static void wifi_statistics_update_state(void)
448 {
449         guint64 tx, rx;
450
451         netconfig_wifi_get_bytes_statistics(&tx, &rx, TRUE);
452 }
453
454 static gboolean __statistics_update_wifi_vconf(gpointer data)
455 {
456         if (stat_count.tx_diff ||
457                         stat_count.rx_diff ||
458                         stat_count.last_tx_offset ||
459                         stat_count.last_rx_offset)
460                 netconfig_wifi_set_bytes_pkt_vconf(0, 0, TRUE);
461
462         return TRUE;
463 }
464
465 void statistics_object_create_and_init(void)
466 {
467         DBG("Creating statistics object");
468         GDBusInterfaceSkeleton *interface_statistics = NULL;
469         GDBusConnection *connection = NULL;
470         GDBusObjectManagerServer *server = netdbus_get_statistics_manager();
471         if (server == NULL)
472                 return;
473
474         connection = netdbus_get_connection();
475         g_dbus_object_manager_server_set_connection(server, connection);
476
477         /*Interface netconfig.network_statistics*/
478         netconfigstatistics = network_statistics_skeleton_new();
479
480         interface_statistics = G_DBUS_INTERFACE_SKELETON(netconfigstatistics);
481         g_signal_connect(netconfigstatistics, "handle-get-wifi-last-rx-bytes",
482                                 G_CALLBACK(handle_get_wifi_last_rx_bytes), NULL);
483         g_signal_connect(netconfigstatistics, "handle-get-wifi-last-tx-bytes",
484                                 G_CALLBACK(handle_get_wifi_last_tx_bytes), NULL);
485         g_signal_connect(netconfigstatistics, "handle-get-wifi-total-rx-bytes",
486                                 G_CALLBACK(handle_get_wifi_total_rx_bytes), NULL);
487         g_signal_connect(netconfigstatistics, "handle-get-wifi-total-tx-bytes",
488                                 G_CALLBACK(handle_get_wifi_total_tx_bytes), NULL);
489         g_signal_connect(netconfigstatistics, "handle-reset-cellular-last-rx-bytes",
490                                 G_CALLBACK(handle_reset_cellular_last_rx_bytes), NULL);
491         g_signal_connect(netconfigstatistics, "handle-reset-cellular-last-tx-bytes",
492                                 G_CALLBACK(handle_reset_cellular_last_tx_bytes), NULL);
493         g_signal_connect(netconfigstatistics, "handle-reset-cellular-total-rx-bytes",
494                                 G_CALLBACK(handle_reset_cellular_total_rx_bytes), NULL);
495         g_signal_connect(netconfigstatistics, "handle-reset-cellular-total-tx-bytes",
496                                 G_CALLBACK(handle_reset_cellular_total_tx_bytes), NULL);
497         g_signal_connect(netconfigstatistics, "handle-reset-wifi-last-rx-bytes",
498                                 G_CALLBACK(handle_reset_wifi_last_rx_bytes), NULL);
499         g_signal_connect(netconfigstatistics, "handle-reset-wifi-last-tx-bytes",
500                                 G_CALLBACK(handle_reset_wifi_last_tx_bytes), NULL);
501         g_signal_connect(netconfigstatistics, "handle-reset-wifi-total-rx-bytes",
502                                 G_CALLBACK(handle_reset_wifi_total_rx_bytes), NULL);
503         g_signal_connect(netconfigstatistics, "handle-reset-wifi-total-tx-bytes",
504                                 G_CALLBACK(handle_reset_wifi_total_tx_bytes), NULL);
505
506         if (!g_dbus_interface_skeleton_export(interface_statistics, connection,
507                         NETCONFIG_NETWORK_STATISTICS_PATH, NULL)) {
508                 ERR("Export with path failed");
509         }
510
511         wifi_statistics_update_state();
512         netconfig_start_timer_seconds(WIFI_VCONF_UPDATE_INTERVAL,
513                         __statistics_update_wifi_vconf, NULL, &wifi_vconf_update_timer);
514
515         return;
516 }
517
518 void statistics_object_deinit(void)
519 {
520         netconfig_wifi_set_bytes_pkt_vconf(0, 0, TRUE);
521         netconfig_stop_timer(&wifi_vconf_update_timer);
522         g_object_unref(netconfigstatistics);
523 }