NetUsage: finish first working version

This commit is contained in:
李通洲
2023-09-26 16:26:15 +08:00
committed by 李通洲
parent 9004d9e05c
commit 24a6efa227
22 changed files with 453 additions and 163 deletions
+7
View File
@@ -277,6 +277,7 @@ set(LIBFASTFETCH_SRC
src/detection/gpu/gpu.c
src/detection/locale/locale.c
src/detection/media/media.c
src/detection/netusage/netusage.c
src/detection/opencl/opencl.c
src/detection/os/os.c
src/detection/packages/packages.c
@@ -319,6 +320,7 @@ set(LIBFASTFETCH_SRC
src/modules/localip/localip.c
src/modules/memory/memory.c
src/modules/monitor/monitor.c
src/modules/netusage/netusage.c
src/modules/opencl/opencl.c
src/modules/opengl/opengl.c
src/modules/os/os.c
@@ -359,6 +361,7 @@ if(LINUX)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
src/common/io/io_unix.c
src/common/netif/netif_linux.c
src/common/networking_linux.c
src/common/processing_linux.c
src/detection/battery/battery_linux.c
@@ -411,6 +414,7 @@ if(LINUX)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
src/common/io/io_unix.c
src/common/netif/netif_linux.c
src/common/networking_linux.c
src/common/processing_linux.c
src/detection/battery/battery_android.c
@@ -457,6 +461,7 @@ elseif(BSD)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
src/common/io/io_unix.c
src/common/netif/netif_bsd.c
src/common/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
@@ -510,6 +515,7 @@ elseif(BSD)
elseif(APPLE)
list(APPEND LIBFASTFETCH_SRC
src/common/io/io_unix.c
src/common/netif/netif_bsd.c
src/common/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
@@ -559,6 +565,7 @@ elseif(APPLE)
elseif(WIN32)
list(APPEND LIBFASTFETCH_SRC
src/common/io/io_windows.c
src/common/netif/netif_windows.c
src/common/networking_windows.c
src/common/processing_windows.c
src/detection/battery/battery_windows.c
+3
View File
@@ -60,6 +60,9 @@ void ffPrepareCommandOption(FFdata* data)
if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME))
ffPrepareCPUUsage();
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETUSAGE_MODULE_NAME))
ffPrepareNetUsage();
if(instance.config.multithreading)
{
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
+2
View File
@@ -106,6 +106,7 @@ static void defaultConfig(void)
ffInitMediaOptions(&instance.config.media);
ffInitMemoryOptions(&instance.config.memory);
ffInitMonitorOptions(&instance.config.monitor);
ffInitNetUsageOptions(&instance.config.netUsage);
ffInitOSOptions(&instance.config.os);
ffInitOpenCLOptions(&instance.config.openCL);
ffInitOpenGLOptions(&instance.config.openGL);
@@ -319,6 +320,7 @@ static void destroyConfig(void)
ffDestroyMediaOptions(&instance.config.media);
ffDestroyMemoryOptions(&instance.config.memory);
ffDestroyMonitorOptions(&instance.config.monitor);
ffDestroyNetUsageOptions(&instance.config.netUsage);
ffDestroyOSOptions(&instance.config.os);
ffDestroyOpenCLOptions(&instance.config.openCL);
ffDestroyOpenGLOptions(&instance.config.openGL);
+1
View File
@@ -82,6 +82,7 @@ static FFModuleBaseInfo* M[] = {
};
static FFModuleBaseInfo* N[] = {
(void*) &instance.config.netUsage,
NULL,
};
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fastfetch.h"
#ifndef _WIN32
bool ffNetifGetDefaultRoute(FFstrbuf* iface);
#else
bool ffNetifGetDefaultRoute(uint32_t* ifIndex);
#endif
+96
View File
@@ -0,0 +1,96 @@
#include "netif.h"
#include "common/io/io.h"
#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n))
#if defined(__APPLE__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#elif defined(__NetBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t))
#elif defined(__FreeBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#elif defined(__OpenBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#else
# error unknown platform
#endif
static struct sockaddr *
get_rt_address(struct rt_msghdr *rtm, int desired)
{
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
for (int i = 0; i < RTAX_MAX; i++)
{
if (rtm->rtm_addrs & (1 << i))
{
if ((1 <<i ) == desired)
return sa;
sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
}
}
return NULL;
}
bool ffNetifGetDefaultRoute(FFstrbuf* iface)
{
//https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104
FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET);
if (pfRoute < 0)
return false;
{
struct timeval timeout = {1, 0};
setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
}
int pid = getpid();
struct {
struct rt_msghdr hdr;
struct sockaddr_in dst;
uint8_t data[512];
} rtmsg = {
.hdr = {
.rtm_type = RTM_GET,
.rtm_flags = RTF_UP | RTF_GATEWAY,
.rtm_version = RTM_VERSION,
.rtm_addrs = RTA_DST | RTA_IFP,
.rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst),
.rtm_pid = pid,
.rtm_seq = 1,
},
.dst = {
.sin_family = AF_INET,
.sin_len = sizeof(rtmsg.dst),
},
};
if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen)
return false;
while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0)
{
if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid)
{
struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP);
if (sdl)
{
ffStrbufSetNS(iface, sdl->sdl_nlen, sdl->sdl_data);
return true;
}
return false;
}
}
return false;
}
+25
View File
@@ -0,0 +1,25 @@
#include "netif.h"
#include "common/io/io.h"
#include <stdio.h>
bool ffNetifGetDefaultRoute(FFstrbuf* iface)
{
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r");
if (!netRoute) return false;
// skip first line
flockfile(netRoute);
while (getc_unlocked(netRoute) != '\n');
funlockfile(netRoute);
unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu,
char buf[16 /*IF_NAMESIZE*/ + 1];
while (fscanf(netRoute, "%16s%llx%*[^\n]", buf, &destination) == 2)
{
if (destination != 0) continue;
ffStrbufSetS(iface, buf);
return true;
}
return false;
}
+27
View File
@@ -0,0 +1,27 @@
#include "netif.h"
#include "util/mallocHelper.h"
#include <iphlpapi.h>
bool ffNetifGetDefaultRoute(uint32_t* ifIndex)
{
ULONG size = 0;
if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER)
return false;
FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size);
if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS)
return false;
for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i)
{
MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i];
if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0)
{
*ifIndex = ipForwardRow->dwForwardIfIndex;
break;
}
}
return true;
}
+4 -116
View File
@@ -1,5 +1,6 @@
#include "localip.h"
#include "common/io/io.h"
#include "common/netif/netif.h"
#include <string.h>
#include <ctype.h>
@@ -11,123 +12,10 @@
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <net/if_dl.h>
#include <net/route.h>
#include <sys/socket.h>
#else
#include <netpacket/packet.h>
#endif
#if defined(__linux__)
static bool getDefaultRoute(char iface[IF_NAMESIZE + 1])
{
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r");
if (!netRoute) return false;
// skip first line
flockfile(netRoute);
while (getc_unlocked(netRoute) != '\n');
funlockfile(netRoute);
unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu,
static_assert(IF_NAMESIZE >= 16, "IF_NAMESIZE is too small");
while (fscanf(netRoute, "%16s%llx%*[^\n]", iface, &destination) == 2)
{
if (destination == 0)
return true;
}
return false;
}
#elif defined(__FreeBSD__) || defined(__APPLE__)
#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n))
#if defined(__APPLE__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#elif defined(__NetBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t))
#elif defined(__FreeBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#elif defined(__OpenBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#else
# error unknown platform
#endif
static struct sockaddr *
get_rt_address(struct rt_msghdr *rtm, int desired)
{
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
for (int i = 0; i < RTAX_MAX; i++)
{
if (rtm->rtm_addrs & (1 << i))
{
if ((1 <<i ) == desired)
return sa;
sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
}
}
return NULL;
}
static bool getDefaultRoute(char iface[IF_NAMESIZE + 1])
{
//https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104
FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET);
if (pfRoute < 0)
return false;
{
struct timeval timeout = {1, 0};
setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
}
int pid = getpid();
struct {
struct rt_msghdr hdr;
struct sockaddr_in dst;
uint8_t data[512];
} rtmsg = {
.hdr = {
.rtm_type = RTM_GET,
.rtm_flags = RTF_UP | RTF_GATEWAY,
.rtm_version = RTM_VERSION,
.rtm_addrs = RTA_DST | RTA_IFP,
.rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst),
.rtm_pid = pid,
.rtm_seq = 1,
},
.dst = {
.sin_family = AF_INET,
.sin_len = sizeof(rtmsg.dst),
},
};
if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen)
return false;
while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0)
{
if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid)
{
struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP);
if (sdl)
{
assert(sdl->sdl_nlen <= IF_NAMESIZE);
memcpy(iface, sdl->sdl_data, sdl->sdl_nlen);
iface[sdl->sdl_nlen] = 0;
return true;
}
return false;
}
}
return false;
}
#endif
static void addNewIp(FFlist* list, const char* name, const char* addr, int type)
{
FFLocalIpResult* ip = NULL;
@@ -228,11 +116,11 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
if (ifAddrStruct) freeifaddrs(ifAddrStruct);
char iface[16 /*IF_NAMESIZE*/ + 1];
if (getDefaultRoute(iface))
FF_STRBUF_AUTO_DESTROY iface = ffStrbufCreate();
if (ffNetifGetDefaultRoute(&iface))
{
FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results)
ip->defaultRoute = ffStrbufEqualS(&ip->name, iface);
ip->defaultRoute = ffStrbufEqual(&ip->name, &iface);
}
return NULL;
}
+10 -29
View File
@@ -1,38 +1,11 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include "common/netif/netif.h"
#include "util/mallocHelper.h"
#include "util/windows/unicode.h"
#include "localip.h"
static void setDefaultRoute(FFlist* ips)
{
ULONG size = 0;
if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER)
return;
FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size);
if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS)
return;
for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i)
{
MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i];
if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0)
{
FF_LIST_FOR_EACH(FFLocalIpResult, ip, *ips)
{
if (ip->ifIndex == ipForwardRow->dwForwardIfIndex)
{
ip->defaultRoute = true;
break;
}
}
}
}
}
static void addNewIp(FFlist* list, const char* name, const char* value, int type, bool newIp, uint32_t ifIndex)
{
FFLocalIpResult* ip = NULL;
@@ -143,7 +116,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
}
}
setDefaultRoute(results);
uint32_t ifIndex;
if (ffNetifGetDefaultRoute(&ifIndex))
{
FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results)
{
if (ip->ifIndex != ifIndex) continue;
ip->defaultRoute = true;
}
}
return NULL;
}
+65
View File
@@ -0,0 +1,65 @@
#include "netusage.h"
#include "common/time.h"
const char* ffNetUsageGetIoCounters(FFlist* result);
static FFlist ioCounters1;
static uint64_t time1;
void ffPrepareNetUsage(void)
{
ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters));
ffNetUsageGetIoCounters(&ioCounters1);
time1 = ffTimeGetNow();
}
const char* ffDetectNetUsage(FFlist* result)
{
const char* error = NULL;
if (time1 == 0)
{
ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters));
error = ffNetUsageGetIoCounters(&ioCounters1);
if (error)
return error;
time1 = ffTimeGetNow();
ffTimeSleep(1000);
}
uint64_t time2 = ffTimeGetNow();
while (time2 - time1 < 1000)
{
ffTimeSleep((uint32_t) (1000 - (time2 - time1)));
time2 = ffTimeGetNow();
}
error = ffNetUsageGetIoCounters(result);
if (error)
return error;
if (result->length != ioCounters1.length)
return "Different number of network interfaces. Network change?";
for (uint32_t i = 0; i < result->length; ++i)
{
FFNetUsageIoCounters* icPrev = (FFNetUsageIoCounters*)ffListGet(&ioCounters1, i);
FFNetUsageIoCounters* icCurr = (FFNetUsageIoCounters*)ffListGet(result, i);
if (!ffStrbufEqual(&icPrev->name, &icCurr->name))
return "Network interface name changed";
static_assert(sizeof(FFNetUsageIoCounters) - offsetof(FFNetUsageIoCounters, txBytes) == sizeof(uint64_t) * 8, "Unexpected struct FFNetUsageIoCounters layout");
for (size_t off = offsetof(FFNetUsageIoCounters, txBytes); off < sizeof(FFNetUsageIoCounters); off += sizeof(uint64_t))
{
uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off);
uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off);
uint64_t temp = *currValue;
*currValue -= *prevValue;
*currValue /= (time2 - time1) / 1000 /* seconds */;
*prevValue = temp;
}
}
time1 = time2;
return NULL;
}
+1 -1
View File
@@ -13,4 +13,4 @@ typedef struct FFNetUsageIoCounters
uint64_t txDrops;
} FFNetUsageIoCounters;
const char* ffGetNetIoCounter(FFlist* result /* list of FFNetUsageIoCounters */);
const char* ffDetectNetUsage(FFlist* result);
+13 -10
View File
@@ -5,27 +5,30 @@
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
const char* ffGetNetIoCounter(FFlist* result)
const char* ffNetUsageGetIoCounters(FFlist* result)
{
size_t bufSize = 0;
if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0)
return "sysctl({ CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) failed";
if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0)
return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) failed";
FF_AUTO_FREE uint8_t *buf = NULL;
if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, &buf, &bufSize, 0, 0) < 0)
return "sysctl({ CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, &buf, &bufSize, 0, 0) failed";
FF_AUTO_FREE struct if_msghdr2* buf = (struct if_msghdr2*) malloc(bufSize);
if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) < 0)
return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) failed";
for (struct if_msghdr2* ifm = (struct if_msghdr2*)buf;
ifm < (struct if_msghdr2*) (buf + bufSize);
ifm = (struct if_msghdr2*) ((uint8_t *)ifm + ifm->ifm_msglen))
for (struct if_msghdr2* ifm = buf;
ifm < (struct if_msghdr2*) ((uint8_t*) buf + bufSize);
ifm = (struct if_msghdr2*) ((uint8_t*) ifm + ifm->ifm_msglen))
{
if (ifm->ifm_type != RTM_IFINFO2) continue;
if (ifm->ifm_type != RTM_IFINFO2 || !(ifm->ifm_flags & IFF_RUNNING) || (ifm->ifm_flags & IFF_NOARP)) continue;
struct sockaddr_dl* sdl = (struct sockaddr_dl*) (ifm + 1);
assert(sdl->sdl_family == AF_LINK);
if (sdl->sdl_type != IFT_ETHER && !(ifm->ifm_flags & IFF_LOOPBACK)) continue;
FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result);
*counters = (FFNetUsageIoCounters) {
+1 -1
View File
@@ -4,7 +4,7 @@
#include <net/if.h>
const char* ffGetNetIoCounter(FFlist* result)
const char* ffNetUsageGetIoCounters(FFlist* result)
{
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net");
if (!dirp) return "opendir(\"/sys/class/net\") == NULL";
+1 -1
View File
@@ -7,7 +7,7 @@
#include <ws2tcpip.h>
#include <iphlpapi.h>
const char* ffGetNetIoCounter(FFlist* result)
const char* ffNetUsageGetIoCounters(FFlist* result)
{
IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL;
+1
View File
@@ -108,6 +108,7 @@ typedef struct FFconfig
FFMediaOptions media;
FFMemoryOptions memory;
FFMonitorOptions monitor;
FFNetUsageOptions netUsage;
FFOSOptions os;
FFOpenCLOptions openCL;
FFOpenGLOptions openGL;
+5 -5
View File
@@ -13,14 +13,14 @@ static int sortIps(const FFLocalIpResult* left, const FFLocalIpResult* right)
return ffStrbufComp(&left->name, &right->name);
}
static void formatKey(const FFLocalIpOptions* options, const FFLocalIpResult* ip, uint32_t index, FFstrbuf* key)
static void formatKey(const FFLocalIpOptions* options, FFLocalIpResult* ip, uint32_t index, FFstrbuf* key)
{
if(options->moduleArgs.key.length == 0)
{
if(ip->name.length)
ffStrbufSetF(key, FF_LOCALIP_DISPLAY_NAME " (%s)", ip->name.chars);
else
ffStrbufSetS(key, FF_LOCALIP_DISPLAY_NAME);
if(!ip->name.length)
ffStrbufSetF(&ip->name, "unknown %u", (unsigned) index);
ffStrbufSetF(key, FF_LOCALIP_DISPLAY_NAME " (%s)", ip->name.chars);
}
else
{
+1
View File
@@ -31,6 +31,7 @@
#include "modules/media/media.h"
#include "modules/memory/memory.h"
#include "modules/monitor/monitor.h"
#include "modules/netusage/netusage.h"
#include "modules/opengl/opengl.h"
#include "modules/opencl/opencl.h"
#include "modules/os/os.h"
+155
View File
@@ -0,0 +1,155 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "detection/netusage/netusage.h"
#include "modules/netusage/netusage.h"
#include "util/stringUtils.h"
#define FF_NETUSAGE_DISPLAY_NAME "Net Usage"
#define FF_NETUSAGE_NUM_FORMAT_ARGS 1
static int sortInfs(const FFNetUsageIoCounters* left, const FFNetUsageIoCounters* right)
{
return ffStrbufComp(&left->name, &right->name);
}
static void formatKey(const FFNetUsageOptions* options, FFNetUsageIoCounters* inf, uint32_t index, FFstrbuf* key)
{
if(options->moduleArgs.key.length == 0)
{
if(!inf->name.length)
ffStrbufSetF(&inf->name, "unknown %u", (unsigned) index);
ffStrbufSetF(key, FF_NETUSAGE_DISPLAY_NAME " (%s)", inf->name.chars);
}
else
{
ffStrbufClear(key);
ffParseFormatString(key, &options->moduleArgs.key, 2, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT, &index},
{FF_FORMAT_ARG_TYPE_STRBUF, &inf->name},
});
}
}
void ffPrintNetUsage(FFNetUsageOptions* options)
{
FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters));
const char* error = ffDetectNetUsage(&result);
if(error)
{
ffPrintError(FF_NETUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, "%s", error);
return;
}
ffListSort(&result, (const void*) sortInfs);
uint32_t index = 0;
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate();
FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result)
{
formatKey(options, inf, result.length == 1 ? 0 : index + 1, &key);
ffStrbufClear(&buffer);
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffParseSize(inf->rxBytes, &buffer);
ffStrbufAppendS(&buffer, "/s (in) - ");
ffParseSize(inf->txBytes, &buffer);
ffStrbufAppendS(&buffer, "/s (out)");
ffStrbufPutTo(&buffer, stdout);
}
else
{
ffStrbufClear(&buffer2);
ffParseSize(inf->rxBytes, &buffer);
ffParseSize(inf->txBytes, &buffer2);
ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_NETUSAGE_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &inf->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &buffer},
{FF_FORMAT_ARG_TYPE_STRBUF, &buffer2},
{FF_FORMAT_ARG_TYPE_UINT64, &inf->txBytes},
{FF_FORMAT_ARG_TYPE_UINT64, &inf->rxBytes},
{FF_FORMAT_ARG_TYPE_UINT64, &inf->txPackets},
{FF_FORMAT_ARG_TYPE_UINT64, &inf->rxPackets},
{FF_FORMAT_ARG_TYPE_UINT64, &inf->rxErrors},
{FF_FORMAT_ARG_TYPE_UINT64, &inf->txErrors},
{FF_FORMAT_ARG_TYPE_UINT64, &inf->rxDrops},
{FF_FORMAT_ARG_TYPE_UINT64, &inf->txDrops},
});
}
++index;
}
}
void ffInitNetUsageOptions(FFNetUsageOptions* options)
{
ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETUSAGE_MODULE_NAME, ffParseNetUsageCommandOptions, ffParseNetUsageJsonObject, ffPrintNetUsage, ffGenerateNetUsageJson);
ffOptionInitModuleArg(&options->moduleArgs);
}
bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, const char* value)
{
const char* subKey = ffOptionTestPrefix(key, FF_NETUSAGE_MODULE_NAME);
if (!subKey) return false;
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
return false;
}
void ffDestroyNetUsageOptions(FFNetUsageOptions* options)
{
ffOptionDestroyModuleArg(&options->moduleArgs);
}
void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module)
{
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(module, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if(ffStrEqualsIgnCase(key, "type"))
continue;
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
ffPrintError(FF_NETUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
void ffGenerateNetUsageJson(FF_MAYBE_UNUSED FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters));
const char* error = ffDetectNetUsage(&result);
if(error)
{
yyjson_mut_obj_add_str(doc, module, "error", error);
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFNetUsageIoCounters, counter, result)
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &counter->name);
yyjson_mut_obj_add_uint(doc, obj, "txBytes", counter->txBytes);
yyjson_mut_obj_add_uint(doc, obj, "rxBytes", counter->rxBytes);
yyjson_mut_obj_add_uint(doc, obj, "txPackets", counter->txPackets);
yyjson_mut_obj_add_uint(doc, obj, "rxPackets", counter->rxPackets);
yyjson_mut_obj_add_uint(doc, obj, "rxErrors", counter->rxErrors);
yyjson_mut_obj_add_uint(doc, obj, "txErrors", counter->txErrors);
yyjson_mut_obj_add_uint(doc, obj, "rxDrops", counter->rxDrops);
yyjson_mut_obj_add_uint(doc, obj, "txDrops", counter->txDrops);
}
}
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include "fastfetch.h"
#define FF_NETUSAGE_MODULE_NAME "NetUsage"
void ffPrepareNetUsage();
void ffPrintNetUsage(FFNetUsageOptions* options);
void ffInitNetUsageOptions(FFNetUsageOptions* options);
bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, const char* value);
void ffDestroyNetUsageOptions(FFNetUsageOptions* options);
void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module);
void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module);
+11
View File
@@ -0,0 +1,11 @@
#pragma once
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
typedef struct FFNetUsageOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
} FFNetUsageOptions;
+1
View File
@@ -31,6 +31,7 @@
#include "modules/media/option.h"
#include "modules/memory/option.h"
#include "modules/monitor/option.h"
#include "modules/netusage/option.h"
#include "modules/opengl/option.h"
#include "modules/opencl/option.h"
#include "modules/os/option.h"