This commit is contained in:
ge
2026-04-01 00:53:36 +03:00
commit b27f835d33
24 changed files with 1106 additions and 0 deletions
+104
View File
@@ -0,0 +1,104 @@
@[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)
}