mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
NetUsage: finish first working version
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -82,6 +82,7 @@ static FFModuleBaseInfo* M[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* N[] = {
|
||||
(void*) &instance.config.netUsage,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
bool ffNetifGetDefaultRoute(FFstrbuf* iface);
|
||||
#else
|
||||
bool ffNetifGetDefaultRoute(uint32_t* ifIndex);
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -13,4 +13,4 @@ typedef struct FFNetUsageIoCounters
|
||||
uint64_t txDrops;
|
||||
} FFNetUsageIoCounters;
|
||||
|
||||
const char* ffGetNetIoCounter(FFlist* result /* list of FFNetUsageIoCounters */);
|
||||
const char* ffDetectNetUsage(FFlist* result);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ typedef struct FFconfig
|
||||
FFMediaOptions media;
|
||||
FFMemoryOptions memory;
|
||||
FFMonitorOptions monitor;
|
||||
FFNetUsageOptions netUsage;
|
||||
FFOSOptions os;
|
||||
FFOpenCLOptions openCL;
|
||||
FFOpenGLOptions openGL;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user