106 lines
2.1 KiB
V
106 lines
2.1 KiB
V
@[has_globals]
|
|
module protocol
|
|
|
|
import os
|
|
import sync
|
|
|
|
#include <netdb.h>
|
|
|
|
// Mutex for accessing to protocol entries via getprotoent(3).
|
|
__global netio_proto_mutex &sync.Mutex
|
|
|
|
fn init() {
|
|
netio_proto_mutex = sync.new_mutex()
|
|
}
|
|
|
|
fn cleanup() {
|
|
netio_proto_mutex.destroy()
|
|
unsafe { free(netio_proto_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()
|
|
|
|
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_proto_mutex.@lock()
|
|
C.setprotoent(1)
|
|
defer {
|
|
C.endprotoent()
|
|
netio_proto_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_proto_mutex.@lock()
|
|
defer {
|
|
netio_proto_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_proto_mutex.@lock()
|
|
defer {
|
|
netio_proto_mutex.unlock()
|
|
}
|
|
proto := C.getprotobynumber(num)
|
|
if isnil(proto) {
|
|
return os.last_error()
|
|
}
|
|
return make_proto(proto)
|
|
}
|