105 lines
2.3 KiB
V
105 lines
2.3 KiB
V
@[has_globals]
|
|
module netio
|
|
|
|
import os
|
|
import sync
|
|
|
|
// Mutex for accessing to protocol entries via getprotoent(3).
|
|
__global netio_protoent_mutex &sync.Mutex
|
|
|
|
struct C.protoent {
|
|
p_name &char
|
|
p_aliases &&char
|
|
p_proto i32
|
|
}
|
|
|
|
fn C.getprotoent() &C.protoent
|
|
fn C.getprotobyname(&char) &C.protoent
|
|
fn C.getprotobynumber(i32) &C.protoent
|
|
fn C.setprotoent(i32)
|
|
fn C.endprotoent()
|
|
|
|
// The protocol number type.
|
|
// See [protocols(5)](https://man7.org/linux/man-pages/man5/protocols.5.html),
|
|
// and [getprotoent(3)](https://man7.org/linux/man-pages/man3/getprotoent.3.html) for details.
|
|
pub type Protocol = int
|
|
|
|
// entry returns the protocol entry from database.
|
|
pub fn (p Protocol) entry() !ProtocolEntry {
|
|
return protocol_by_number(p)!
|
|
}
|
|
|
|
pub struct ProtocolEntry {
|
|
pub:
|
|
name string // The official name of protocol.
|
|
aliases []string // List of alternative names for the protocol.
|
|
number int // The protocol number.
|
|
}
|
|
|
|
fn make_proto(ent C.protoent) ProtocolEntry {
|
|
mut aliases := []string{}
|
|
if unsafe { ent.p_aliases[0] != nil } {
|
|
mut ptr := *ent.p_aliases
|
|
mut nullterm := 1
|
|
for {
|
|
if *ptr == 0 {
|
|
break
|
|
}
|
|
str := unsafe { cstring_to_vstring(ptr) }
|
|
ptr = unsafe { ptr + str.len + nullterm }
|
|
nullterm++
|
|
aliases << str
|
|
}
|
|
}
|
|
return ProtocolEntry{
|
|
name: unsafe { cstring_to_vstring(ent.p_name) }
|
|
aliases: aliases
|
|
number: int(ent.p_proto)
|
|
}
|
|
}
|
|
|
|
// protocols returns all protocol entries from database in arbitrary order.
|
|
pub fn protocols() []ProtocolEntry {
|
|
netio_protoent_mutex.@lock()
|
|
C.setprotoent(1)
|
|
defer {
|
|
C.endprotoent()
|
|
netio_protoent_mutex.unlock()
|
|
}
|
|
mut protos := []ProtocolEntry{}
|
|
for {
|
|
proto := C.getprotoent()
|
|
if isnil(proto) {
|
|
break
|
|
}
|
|
protos << make_proto(proto)
|
|
}
|
|
return protos
|
|
}
|
|
|
|
// protocol_by_name returns the protocol entry by name e.g. 'tcp', 'icmp'.
|
|
pub fn protocol_by_name(name string) !ProtocolEntry {
|
|
netio_protoent_mutex.@lock()
|
|
defer {
|
|
netio_protoent_mutex.unlock()
|
|
}
|
|
proto := C.getprotobyname(&char(name.str))
|
|
if isnil(proto) {
|
|
return os.last_error()
|
|
}
|
|
return make_proto(proto)
|
|
}
|
|
|
|
// protocol_by_number returns the protocol entry by protocol number.
|
|
pub fn protocol_by_number(num int) !ProtocolEntry {
|
|
netio_protoent_mutex.@lock()
|
|
defer {
|
|
netio_protoent_mutex.unlock()
|
|
}
|
|
proto := C.getprotobynumber(num)
|
|
if isnil(proto) {
|
|
return os.last_error()
|
|
}
|
|
return make_proto(proto)
|
|
}
|