81 lines
2.0 KiB
Go
81 lines
2.0 KiB
Go
//go:build darwin || linux
|
|
|
|
package gateway
|
|
|
|
import (
|
|
"io"
|
|
"net"
|
|
"os"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
"syscall"
|
|
)
|
|
|
|
func qualificationProcessCPUSeconds() float64 {
|
|
var usage syscall.Rusage
|
|
if syscall.Getrusage(syscall.RUSAGE_SELF, &usage) != nil {
|
|
return -1
|
|
}
|
|
return float64(usage.Utime.Sec+usage.Stime.Sec) +
|
|
float64(usage.Utime.Usec+usage.Stime.Usec)/1_000_000
|
|
}
|
|
|
|
func qualificationProviderVideoSocketDiagnostics(connection *net.UDPConn) (receiveBuffer int, receiveBufferAvailable bool, kernelDrops uint64, kernelDropsAvailable bool) {
|
|
if connection == nil {
|
|
return 0, false, 0, false
|
|
}
|
|
raw, err := connection.SyscallConn()
|
|
if err != nil {
|
|
return 0, false, 0, false
|
|
}
|
|
var inode uint64
|
|
var socketErr error
|
|
if err := raw.Control(func(descriptor uintptr) {
|
|
receiveBuffer, socketErr = syscall.GetsockoptInt(int(descriptor), syscall.SOL_SOCKET, syscall.SO_RCVBUF)
|
|
if runtime.GOOS == "linux" {
|
|
var stat syscall.Stat_t
|
|
if statErr := syscall.Fstat(int(descriptor), &stat); statErr == nil {
|
|
inode = stat.Ino
|
|
}
|
|
}
|
|
}); err != nil || socketErr != nil {
|
|
return 0, false, 0, false
|
|
}
|
|
receiveBufferAvailable = true
|
|
if runtime.GOOS == "linux" {
|
|
kernelDrops, kernelDropsAvailable = qualificationLinuxUDPDrops(inode)
|
|
}
|
|
return receiveBuffer, receiveBufferAvailable, kernelDrops, kernelDropsAvailable
|
|
}
|
|
|
|
func qualificationLinuxUDPDrops(inode uint64) (uint64, bool) {
|
|
if inode == 0 {
|
|
return 0, false
|
|
}
|
|
inodeText := strconv.FormatUint(inode, 10)
|
|
for _, path := range []string{"/proc/net/udp", "/proc/net/udp6"} {
|
|
file, err := os.Open(path)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
raw, readErr := io.ReadAll(io.LimitReader(file, 1<<20))
|
|
closeErr := file.Close()
|
|
if readErr != nil || closeErr != nil {
|
|
continue
|
|
}
|
|
for _, line := range strings.Split(string(raw), "\n") {
|
|
fields := strings.Fields(line)
|
|
if len(fields) < 11 || fields[9] != inodeText {
|
|
continue
|
|
}
|
|
drops, err := strconv.ParseUint(fields[len(fields)-1], 10, 64)
|
|
if err != nil {
|
|
return 0, false
|
|
}
|
|
return drops, true
|
|
}
|
|
}
|
|
return 0, false
|
|
}
|