...
This commit is contained in:
143
lib/osal/core/net.v
Normal file
143
lib/osal/core/net.v
Normal file
@@ -0,0 +1,143 @@
|
||||
module osal
|
||||
|
||||
import net
|
||||
import time
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core
|
||||
import os
|
||||
|
||||
pub enum PingResult {
|
||||
ok
|
||||
timeout // timeout from ping
|
||||
unknownhost // means we don't know the hostname its a dns issue
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct PingArgs {
|
||||
pub mut:
|
||||
address string @[required]
|
||||
count u8 = 1 // the ping is successful if it got count amount of replies from the other side
|
||||
timeout u16 = 1 // the time in which the other side should respond in seconds
|
||||
retry u8
|
||||
}
|
||||
|
||||
// if reached in timout result will be True
|
||||
// address is e.g. 8.8.8.8
|
||||
// ping means we check if the destination responds
|
||||
pub fn ping(args PingArgs) !PingResult {
|
||||
platform_ := core.platform()!
|
||||
mut cmd := 'ping'
|
||||
if args.address.contains(':') {
|
||||
cmd = 'ping6'
|
||||
}
|
||||
if platform_ == .osx {
|
||||
cmd += ' -c ${args.count} -i ${args.timeout} ${args.address}'
|
||||
} else if platform_ == .ubuntu {
|
||||
cmd += ' -c ${args.count} -w ${args.timeout} ${args.address}'
|
||||
} else {
|
||||
return error('Unsupported platform for ping')
|
||||
}
|
||||
console.print_debug(cmd)
|
||||
_ := exec(cmd: cmd, retry: args.retry, timeout: 0, stdout: false) or {
|
||||
// println("ping failed.error.\n${err}")
|
||||
if err.code() == 9999 {
|
||||
return .timeout
|
||||
}
|
||||
if platform_ == .osx {
|
||||
return match err.code() {
|
||||
2 {
|
||||
.timeout
|
||||
}
|
||||
68 {
|
||||
.unknownhost
|
||||
}
|
||||
else {
|
||||
// println("${err} ${err.code()}")
|
||||
error("can't ping on osx (${err.code()})\n${err}")
|
||||
}
|
||||
}
|
||||
} else if platform_ == .ubuntu {
|
||||
return match err.code() {
|
||||
1 { .timeout }
|
||||
2 { .unknownhost }
|
||||
else { error("can't ping on ubuntu (${err.code()})\n${err}") }
|
||||
}
|
||||
} else {
|
||||
panic('bug, should never get here')
|
||||
}
|
||||
}
|
||||
return .ok
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct TcpPortTestArgs {
|
||||
pub mut:
|
||||
address string @[required] // 192.168.8.8
|
||||
port int = 22
|
||||
timeout u16 = 2000 // total time in milliseconds to keep on trying
|
||||
}
|
||||
|
||||
// test if a tcp port answers
|
||||
//```
|
||||
// address string //192.168.8.8
|
||||
// port int = 22
|
||||
// timeout u16 = 2000 // total time in milliseconds to keep on trying
|
||||
//```
|
||||
pub fn tcp_port_test(args TcpPortTestArgs) bool {
|
||||
start_time := time.now().unix_milli()
|
||||
mut run_time := 0.0
|
||||
for true {
|
||||
run_time = time.now().unix_milli()
|
||||
if run_time > start_time + args.timeout {
|
||||
return false
|
||||
}
|
||||
_ = net.dial_tcp('${args.address}:${args.port}') or {
|
||||
time.sleep(100 * time.millisecond)
|
||||
continue
|
||||
}
|
||||
// console.print_debug(socket)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Returns the public IP address as known on the public side
|
||||
// Uses resolver4.opendns.com to fetch the IP address
|
||||
pub fn ipaddr_pub_get() !string {
|
||||
cmd := 'dig @resolver4.opendns.com myip.opendns.com +short'
|
||||
ipaddr := exec(cmd: cmd)!
|
||||
public_ip := ipaddr.output.trim('\n').trim(' \n')
|
||||
return public_ip
|
||||
}
|
||||
|
||||
// also check the address is on local interface
|
||||
pub fn ipaddr_pub_get_check() !string {
|
||||
// Check if the public IP matches any local interface
|
||||
public_ip := ipaddr_pub_get()!
|
||||
if !is_ip_on_local_interface(public_ip)! {
|
||||
return error('Public IP ${public_ip} is NOT bound to any local interface (possibly behind a NAT firewall).')
|
||||
}
|
||||
return public_ip
|
||||
}
|
||||
|
||||
// Check if the public IP matches any of the local network interfaces
|
||||
pub fn is_ip_on_local_interface(public_ip string) !bool {
|
||||
interfaces := exec(cmd: 'ip addr show', stdout: false) or {
|
||||
return error('Failed to enumerate network interfaces: ${err}')
|
||||
}
|
||||
lines := interfaces.output.split('\n')
|
||||
|
||||
// Parse through the `ip addr show` output to find local IPs
|
||||
for line in lines {
|
||||
if line.contains('inet ') {
|
||||
parts := line.trim_space().split(' ')
|
||||
if parts.len > 1 {
|
||||
local_ip := parts[1].split('/')[0] // Extract the IP address
|
||||
if public_ip == local_ip {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user