v/vlib/x/net/address.v

75 lines
1.5 KiB
V

module net
// Addr represents an ip address
pub struct Addr {
addr C.sockaddr
len int
pub:
saddr string
port int
}
pub fn (a Addr) str() string {
return '${a.saddr}:${a.port}'
}
const (
max_ipv4_addr_len = 16
)
fn new_addr(addr C.sockaddr, _saddr string, _port int) ?Addr {
mut saddr := _saddr
if saddr == '' {
// Convert to string representation
buf := []byte{ len: max_ipv4_addr_len, init: 0 }
$if windows {
res := C.WSAStringToAddress(&addr, SocketFamily.inet, C.NULL, &buf.data, &buf.len)
if res == 0 {
socket_error(-1)?
}
} $else {
res := C.inet_ntop(SocketFamily.inet, &addr, buf.data, buf.len)
if res == 0 {
socket_error(-1)?
}
}
saddr = buf.bytestr()
}
mut port := _port
if port == 0 {
hport := (&C.sockaddr_in(&addr)).sin_port
port = C.ntohs(hport)
}
return Addr {
addr int(sizeof(C.sockaddr)) saddr port
}
}
pub fn resolve_addr(addr string, family SocketFamily, typ SocketType) ?Addr {
address, port := split_address(addr)?
mut hints := C.addrinfo{}
hints.ai_family = family
hints.ai_socktype = typ
hints.ai_flags = C.AI_PASSIVE
hints.ai_protocol = 0
hints.ai_addrlen = 0
hints.ai_canonname = C.NULL
hints.ai_addr = C.NULL
hints.ai_next = C.NULL
info := &C.addrinfo(0)
sport := '$port'
// This might look silly but is recommended by MSDN
$if windows {
socket_error(0-C.getaddrinfo(address.str, sport.str, &hints, &info))?
} $else {
wrap_error(C.getaddrinfo(address.str, sport.str, &hints, &info))
}
return new_addr(*info.ai_addr, address, port)
}