1 /*
2 * Copyright (c) 2021 Jan Ziak <0xe2.0x9a.0x9b@xfce.org>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <stdio.h>
31 #include <string.h>
32 #include "network.h"
33
34 #ifdef HAVE_LIBGTOP
35
36 #include <glibtop/netlist.h>
37 #include <glibtop/netload.h>
38
39 static gint
read_netload_libgtop(gulong * bytes)40 read_netload_libgtop (gulong *bytes)
41 {
42 glibtop_netlist netlist;
43 char **interfaces, **i;
44
45 interfaces = glibtop_get_netlist (&netlist);
46 if (!interfaces)
47 return -1;
48
49 *bytes = 0;
50 for (i = interfaces; *i != NULL; i++)
51 {
52 glibtop_netload netload;
53 glibtop_get_netload (&netload, *i);
54 *bytes += netload.bytes_total;
55 }
56
57 return 0;
58 }
59
60 #else
61
62 static gint
read_netload_libgtop(gulong * bytes)63 read_netload_libgtop (gulong *bytes)
64 {
65 return -1;
66 }
67
68 #endif
69
70 static const char *const PROC_NET_NETSTAT = "/proc/net/netstat";
71
72 static gint
read_netload_proc(gulong * bytes)73 read_netload_proc (gulong *bytes)
74 {
75 char buf[4*1024];
76 const char *s;
77 unsigned long long dummy, in_octets, out_octets;
78
79 {
80 FILE *fd;
81 size_t size;
82
83 fd = fopen (PROC_NET_NETSTAT, "r");
84 if (!fd)
85 return -1;
86
87 if ((size = fread (buf, sizeof (*buf), G_N_ELEMENTS (buf) - 1, fd)) == 0)
88 {
89 fclose(fd);
90 return -1;
91 }
92 buf[size] = '\0';
93
94 if (fclose (fd) != 0)
95 return -1;
96 }
97
98 /* Skip first 3 lines */
99 s = buf;
100 s = strchr(s, '\n'); if (!s) return -1;
101 s++;
102 s = strchr(s, '\n'); if (!s) return -1;
103 s++;
104 s = strchr(s, '\n'); if (!s) return -1;
105 s++;
106
107 if (sscanf (s, "IpExt: %llu %llu %llu %llu %llu %llu %llu %llu",
108 &dummy, &dummy, &dummy, &dummy, &dummy, &dummy,
109 &in_octets, &out_octets) != 8)
110 return -1;
111
112 *bytes = in_octets + out_octets;
113 return 0;
114 }
115
116 gint
read_netload(gulong * net,gulong * NTotal)117 read_netload (gulong *net, gulong *NTotal)
118 {
119 static guint64 bytes[2];
120 static gint64 time[2];
121
122 *net = 0;
123 *NTotal = 0;
124
125 time[1] = g_get_monotonic_time ();
126
127 if (read_netload_proc (&bytes[1]) != 0)
128 if (read_netload_libgtop (&bytes[1]) != 0)
129 return -1;
130
131 if (time[0] != 0 && G_LIKELY (time[1] > time[0]) && G_LIKELY (bytes[1] >= bytes[0]))
132 {
133 guint64 diff_bits = 8 * (bytes[1] - bytes[0]);
134 gdouble diff_time = (time[1] - time[0]) / 1e6;
135 *net = MIN (100 * diff_bits / diff_time / MAX_BANDWIDTH_BITS, 100);
136 *NTotal = diff_bits / diff_time;
137 }
138
139 bytes[0] = bytes[1];
140 time[0] = time[1];
141
142 return 0;
143 }
144
145