@[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) }