Tizen 2.1 base
[platform/core/connectivity/net-config.git] / src / network-statistics.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012-2013 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 <vconf.h>
21 #include <vconf-keys.h>
22
23 #include "wifi.h"
24 #include "log.h"
25 #include "util.h"
26 #include "netsupplicant.h"
27 #include "wifi-indicator.h"
28 #include "network-statistics.h"
29
30 #include "netconfig-iface-network-statistics-glue.h"
31
32 #define NETCONFIG_NETWORK_STATISTICS_PATH       "/net/netconfig/network_statistics"
33
34 #define NETCONFIG_PROCDEVFILE           "/proc/net/dev"
35
36 #define PROP_DEFAULT            FALSE
37 #define PROP_DEFAULT_STR        NULL
38
39 enum {
40         PROP_O,
41         PROP_NETWORK_STATISTICS_CONN,
42         PROP_NETWORK_STATISTICS_PATH,
43 };
44
45 struct NetconfigNetworkStatisticsClass {
46         GObjectClass parent;
47 };
48
49 struct NetconfigNetworkStatistics {
50         GObject parent;
51
52         DBusGConnection *conn;
53         gchar *path;
54 };
55
56 G_DEFINE_TYPE(NetconfigNetworkStatistics, netconfig_network_statistics, G_TYPE_OBJECT);
57
58 static void __netconfig_network_statistics_gobject_get_property(GObject *object,
59                 guint prop_id, GValue *value, GParamSpec *pspec)
60 {
61         return;
62 }
63
64 static void __netconfig_network_statistics_gobject_set_property(GObject *object,
65                 guint prop_id, const GValue *value, GParamSpec *pspec)
66 {
67         NetconfigNetworkStatistics *network_statistics = NETCONFIG_NETWORK_STATISTICS(object);
68
69         switch (prop_id) {
70         case PROP_NETWORK_STATISTICS_CONN:
71         {
72                 network_statistics->conn = g_value_get_boxed(value);
73                 INFO("network_statistics(%p) set conn(%p)", network_statistics, network_statistics->conn);
74                 break;
75         }
76
77         case PROP_NETWORK_STATISTICS_PATH:
78         {
79                 if (network_statistics->path)
80                         g_free(network_statistics->path);
81
82                 network_statistics->path = g_value_dup_string(value);
83                 INFO("network_statistics(%p) path(%s)", network_statistics, network_statistics->path);
84
85                 break;
86         }
87
88         default:
89                 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
90         }
91 }
92
93 static void netconfig_network_statistics_init(NetconfigNetworkStatistics *network_statistics)
94 {
95         DBG("network_statistics initialize");
96
97         network_statistics->conn = NULL;
98         network_statistics->path = g_strdup(PROP_DEFAULT_STR);
99 }
100
101 static void netconfig_network_statistics_class_init(NetconfigNetworkStatisticsClass *klass)
102 {
103         GObjectClass *object_class = G_OBJECT_CLASS(klass);
104
105         DBG("class initialize");
106
107         object_class->get_property = __netconfig_network_statistics_gobject_get_property;
108         object_class->set_property = __netconfig_network_statistics_gobject_set_property;
109
110         /* DBus register */
111         dbus_g_object_type_install_info(NETCONFIG_TYPE_NETWORK_STATISTICS,
112                         &dbus_glib_netconfig_iface_network_statistics_object_info);
113
114         /* property */
115         g_object_class_install_property(object_class, PROP_NETWORK_STATISTICS_CONN,
116                         g_param_spec_boxed("conn", "CONNECTION", "DBus connection",
117                                         DBUS_TYPE_G_CONNECTION,
118                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
119
120         g_object_class_install_property(object_class, PROP_NETWORK_STATISTICS_PATH,
121                         g_param_spec_string("path", "Path", "Object path",
122                                         PROP_DEFAULT_STR,
123                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
124 }
125
126
127 static gboolean __netconfig_wifi_get_bytes_statistics(guint64 *tx, guint64 *rx)
128 {
129         gboolean ret = FALSE;
130         FILE *fp;
131         gchar buf[1024];
132         gchar ifname[16] = { 0, };
133         gchar *p_ifname = NULL, *p_entry = NULL;
134         gchar *ifname_ptr = &ifname[0];
135
136         *tx = 0;
137         *rx = 0;
138
139         if (netconfig_wifi_get_ifname(&ifname_ptr) != TRUE) {
140                 DBG("Fail to get Wi-Fi ifname from wpa_supplicant: %s", ifname_ptr);
141                 return FALSE;
142         }
143
144         fp = fopen(NETCONFIG_PROCDEVFILE, "r");
145         if (fp == NULL) {
146                 ERR("Failed to open file %s", NETCONFIG_PROCDEVFILE);
147                 return FALSE;
148         }
149
150         /* skip the first and second line */
151         if (fgets(buf, sizeof(buf), fp) == NULL ||
152                         fgets(buf, sizeof(buf), fp) == NULL)
153                 goto endline;
154
155         while (fgets(buf, sizeof(buf), fp)) {
156                 guint64 llval;
157                 gulong lval;
158
159                 p_ifname = buf;
160                 while (*p_ifname == ' ') p_ifname++;
161                 p_entry = strchr(p_ifname, ':');
162                 *p_entry++ = '\0';
163
164                 if (g_str_equal(p_ifname, ifname) != TRUE)
165                         continue;
166
167                 /* read interface statistics */
168                 sscanf(p_entry,
169                                 "%llu %llu %lu %lu %lu %lu %lu %lu "
170                                 "%llu %llu %lu %lu %lu %lu %lu %lu",
171                                 rx,                     /* rx bytes */
172                                 &llval,         /* rx packet */
173                                 &lval,          /* rx errors */
174                                 &lval,          /* rx dropped */
175                                 &lval,          /* rx fifo errors */
176                                 &lval,          /* rx frame errors */
177                                 &lval,          /* rx compressed */
178                                 &lval,          /* rx multicast */
179
180                                 tx,                     /* tx bytes */
181                                 &llval,         /* tx packet */
182                                 &lval,          /* tx errors */
183                                 &lval,          /* tx dropped */
184                                 &lval,          /* tx fifo errors */
185                                 &lval,          /* collisions */
186                                 &lval,          /* tx carrier errors */
187                                 &lval           /* tx compressed */
188                                 );
189
190                 ret = TRUE;
191                 break;
192         }
193
194 endline:
195         fclose(fp);
196         return ret;
197 }
198
199 gboolean netconfig_iface_network_statistics_get_wifi_total_tx_bytes(NetconfigNetworkStatistics *network_statistics, guint64 *total_bytes, GError **error)
200 {
201         guint64 tx = 0, rx = 0;
202         guint64 tx_bytes = 0;
203         int val = 0;
204
205         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, &val);
206         tx_bytes = (guint64)val;
207
208         if (__netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
209                 *total_bytes = (guint64)tx + (guint64)tx_bytes;
210         else
211                 *total_bytes = (guint64)tx_bytes;
212
213         return TRUE;
214 }
215
216 gboolean netconfig_iface_network_statistics_get_wifi_total_rx_bytes(NetconfigNetworkStatistics *network_statistics, guint64 *total_bytes, GError **error)
217 {
218         guint64 tx = 0, rx = 0;
219         guint64 rx_bytes = 0;
220         int val = 0;
221
222         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, &val);
223         rx_bytes = (guint64)val;
224
225         if (__netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
226                 *total_bytes = (guint64)rx + (guint64)rx_bytes;
227         else
228                 *total_bytes = (guint64)rx_bytes;
229
230         return TRUE;
231 }
232
233 gboolean netconfig_iface_network_statistics_get_wifi_last_tx_bytes(NetconfigNetworkStatistics *network_statistics, guint64 *last_bytes, GError **error)
234 {
235         guint64 tx = 0, rx = 0;
236         guint64 tx_bytes = 0;
237         int val = 0;
238
239         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, &val);
240         tx_bytes = (guint64)val;
241
242         if (netconfig_wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
243                 *last_bytes = (guint64)tx_bytes;
244                 return TRUE;
245         }
246
247         if (__netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
248                 *last_bytes = (((guint64)tx - (guint64)tx_bytes) > (guint64)0) ?
249                                 ((guint64)tx - (guint64)tx_bytes) : (guint64)0;
250         else
251                 *last_bytes = (guint64)tx_bytes;
252
253         return TRUE;
254 }
255
256 gboolean netconfig_iface_network_statistics_get_wifi_last_rx_bytes(NetconfigNetworkStatistics *network_statistics, guint64 *last_bytes, GError **error)
257 {
258         guint64 tx = 0, rx = 0;
259         guint64 rx_bytes = 0;
260         int val = 0;
261
262         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, &val);
263         rx_bytes = (guint64)val;
264
265         if (netconfig_wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
266                 *last_bytes = (guint64)rx_bytes;
267                 return TRUE;
268         }
269
270         if (__netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
271                 *last_bytes = (((guint64)rx - (guint64)rx_bytes) > (guint64)0) ?
272                                 ((guint64)rx - (guint64)rx_bytes) : (guint64)0;
273         else
274                 *last_bytes = (guint64)rx_bytes;
275
276         return TRUE;
277 }
278
279 gboolean netconfig_iface_network_statistics_reset_cellular_total_tx_bytes(NetconfigNetworkStatistics *network_statistics, GError **error)
280 {
281         vconf_set_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_SNT, 0);
282         return TRUE;
283 }
284
285 gboolean netconfig_iface_network_statistics_reset_cellular_total_rx_bytes(NetconfigNetworkStatistics *network_statistics, GError **error)
286 {
287         vconf_set_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_RCV, 0);
288         return TRUE;
289 }
290
291 gboolean netconfig_iface_network_statistics_reset_cellular_last_tx_bytes(NetconfigNetworkStatistics *network_statistics, GError **error)
292 {
293         vconf_set_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_SNT, 0);
294         return TRUE;
295 }
296
297 gboolean netconfig_iface_network_statistics_reset_cellular_last_rx_bytes(NetconfigNetworkStatistics *network_statistics, GError **error)
298 {
299         vconf_set_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_RCV, 0);
300         return TRUE;
301 }
302
303 gboolean netconfig_iface_network_statistics_reset_wifi_total_tx_bytes(NetconfigNetworkStatistics *network_statistics, GError **error)
304 {
305         guint64 tx = 0, rx = 0;
306
307         if (__netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
308                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, -(int)tx);
309         else
310                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, 0);
311
312         return TRUE;
313 }
314
315 gboolean netconfig_iface_network_statistics_reset_wifi_total_rx_bytes(NetconfigNetworkStatistics *network_statistics, GError **error)
316 {
317         guint64 tx = 0, rx = 0;
318
319         if (__netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
320                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, -(int)rx);
321         else
322                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, 0);
323
324         return TRUE;
325 }
326
327 gboolean netconfig_iface_network_statistics_reset_wifi_last_tx_bytes(NetconfigNetworkStatistics *network_statistics, GError **error)
328 {
329         guint64 tx = 0, rx = 0;
330
331         if (netconfig_wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
332                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, 0);
333                 return TRUE;
334         }
335
336         if (__netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
337                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, (int)tx);
338         else
339                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, 0);
340
341         return TRUE;
342 }
343
344 gboolean netconfig_iface_network_statistics_reset_wifi_last_rx_bytes(NetconfigNetworkStatistics *network_statistics, GError **error)
345 {
346         guint64 tx = 0, rx = 0;
347
348         if (netconfig_wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
349                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, 0);
350                 return TRUE;
351         }
352
353         if (__netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
354                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, (int)rx);
355         else
356                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, 0);
357
358         return TRUE;
359 }
360
361 void netconfig_wifi_statistics_update_powered_off(void)
362 {
363         guint64 cur_tx = 0, cur_rx = 0;
364         guint64 prev_tx = 0, prev_rx = 0;
365         guint64 total_tx = 0, total_rx = 0;
366         int val = 0;
367
368         if (__netconfig_wifi_get_bytes_statistics(&cur_tx, &cur_rx) != TRUE)
369                 return;
370
371         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, &val);
372         prev_tx = (guint64)val;
373
374         vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, &val);
375         prev_rx = (guint64)val;
376
377         total_tx = prev_tx + cur_tx;
378         total_rx = prev_rx + cur_rx;
379
380         vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, (int)total_tx);
381         vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, (int)total_rx);
382 }
383
384 static void netconfig_wifi_statistics_update_state(
385                 enum netconfig_wifi_service_state state, void *user_data)
386 {
387         guint64 tx = 0, rx = 0;
388         guint64 last_tx = 0, last_rx = 0;
389         int val = 0;
390         static enum netconfig_wifi_service_state prev_state = NETCONFIG_WIFI_UNKNOWN;
391
392         if (prev_state == NETCONFIG_WIFI_UNKNOWN) {
393                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, 0);
394                 vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, 0);
395
396                 prev_state = NETCONFIG_WIFI_IDLE;
397                 return;
398         }
399
400         if (__netconfig_wifi_get_bytes_statistics(&tx, &rx) != TRUE)
401                 return;
402
403         if (state == NETCONFIG_WIFI_CONNECTED) {
404                 last_tx = tx;
405                 last_rx = rx;
406         } else {
407                 if (prev_state != NETCONFIG_WIFI_CONNECTED)
408                         return;
409
410                 vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, &val);
411                 last_tx = (guint64)val;
412
413                 vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, &val);
414                 last_rx = (guint64)val;
415
416                 last_tx = (((guint64)tx - (guint64)last_tx) > (guint64)0) ?
417                                 ((guint64)tx - (guint64)last_tx) : (guint64)0;
418                 last_rx = (((guint64)rx - (guint64)last_rx) > (guint64)0) ?
419                                 ((guint64)rx - (guint64)last_rx) : (guint64)0;
420         }
421
422         vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, (int)last_tx);
423         vconf_set_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, (int)last_rx);
424
425         prev_state = state;
426 }
427
428 static struct netconfig_wifi_state_notifier state_notifier = {
429                 .netconfig_wifi_state_changed = netconfig_wifi_statistics_update_state,
430                 .user_data = NULL,
431 };
432
433 gpointer netconfig_network_statistics_create_and_init(DBusGConnection *conn)
434 {
435         GObject *object;
436
437         g_return_val_if_fail(conn != NULL, NULL);
438
439         object = g_object_new(NETCONFIG_TYPE_NETWORK_STATISTICS, "conn", conn, "path",
440                         NETCONFIG_NETWORK_STATISTICS_PATH, NULL);
441
442         INFO("create network_statistics(%p)", object);
443
444         dbus_g_connection_register_g_object(conn, NETCONFIG_NETWORK_STATISTICS_PATH, object);
445
446         INFO("network_statistics(%p) register DBus path(%s)", object, NETCONFIG_NETWORK_STATISTICS_PATH);
447
448         netconfig_wifi_statistics_update_state(NETCONFIG_WIFI_IDLE, NULL);
449         netconfig_wifi_state_notifier_register(&state_notifier);
450
451         return object;
452 }