upd4
This commit is contained in:
+7
-100
@@ -1,24 +1,6 @@
|
||||
module netio
|
||||
|
||||
import encoding.binary
|
||||
import os
|
||||
|
||||
#include <netdb.h>
|
||||
|
||||
struct C.addrinfo {
|
||||
mut:
|
||||
ai_flags i32
|
||||
ai_family i32
|
||||
ai_socktype i32
|
||||
ai_protocol i32
|
||||
ai_addrlen i32
|
||||
ai_addr voidptr
|
||||
ai_canonname voidptr
|
||||
ai_next voidptr
|
||||
}
|
||||
|
||||
fn C.getaddrinfo(&char, &char, &C.addrinfo, &&C.addrinfo) i32
|
||||
fn C.freeaddrinfo(&C.addrinfo)
|
||||
|
||||
// max_unix_path_size value is used to pad the sockaddr_un struct.
|
||||
const max_unix_path_size = $if linux {
|
||||
@@ -29,83 +11,6 @@ const max_unix_path_size = $if linux {
|
||||
104
|
||||
}
|
||||
|
||||
// AddrInfo represents the [addrinfo](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html).
|
||||
pub struct AddrInfo {
|
||||
pub:
|
||||
flags int
|
||||
family AddrFamily
|
||||
sock_type SocketType
|
||||
protocol Protocol
|
||||
addr SocketAddr
|
||||
canonical string
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct TranslateAddrHints {
|
||||
pub:
|
||||
node ?string
|
||||
service ?string
|
||||
family AddrFamily = af_unspec
|
||||
sock_type SocketType
|
||||
protocol Protocol
|
||||
flags int
|
||||
}
|
||||
|
||||
// translate_addr translates the network address. This is a low-level wrapper around
|
||||
// the [getaddrinfo(3)](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html) C API.
|
||||
// Example:
|
||||
// ```v
|
||||
// import os
|
||||
// import netio
|
||||
//
|
||||
// // Resolve the host FQND
|
||||
// addr_info := netio.translate_addr(node: os.hostname()!, flags: ai_canonname)!
|
||||
// for addr in addr_info {
|
||||
// println(addr.canonical)
|
||||
// }
|
||||
// ```
|
||||
pub fn translate_addr(hints TranslateAddrHints) ![]AddrInfo {
|
||||
mut hints_ := C.addrinfo{}
|
||||
unsafe { vmemset(&hints_, 0, int(sizeof(hints_))) }
|
||||
hints_.ai_family = i32(hints.family)
|
||||
hints_.ai_socktype = i32(hints.sock_type)
|
||||
hints_.ai_protocol = i32(hints.protocol)
|
||||
hints_.ai_flags = i32(hints.flags)
|
||||
mut node := unsafe { nil }
|
||||
if hints.node != none {
|
||||
node = &char(hints.node.str)
|
||||
}
|
||||
mut service := unsafe { nil }
|
||||
if hints.service != none {
|
||||
service = &char(hints.service.str)
|
||||
}
|
||||
mut results := &C.addrinfo(unsafe { nil })
|
||||
if C.getaddrinfo(node, service, &hints_, &results) == -1 {
|
||||
return os.last_error()
|
||||
}
|
||||
defer {
|
||||
C.freeaddrinfo(results)
|
||||
}
|
||||
mut addrs := []AddrInfo{}
|
||||
for result := unsafe { results }; !isnil(result); result = result.ai_next {
|
||||
addrs << AddrInfo{
|
||||
flags: int(result.ai_flags)
|
||||
family: int(result.ai_family)
|
||||
sock_type: int(result.ai_socktype)
|
||||
protocol: int(result.ai_protocol)
|
||||
addr: unsafe { SocketAddr.from_ptr(result.ai_addr, result.ai_addrlen)! }
|
||||
canonical: if isnil(result.ai_canonname) {
|
||||
''
|
||||
} else {
|
||||
unsafe {
|
||||
cstring_to_vstring(result.ai_canonname)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return addrs
|
||||
}
|
||||
|
||||
// SocketAddr.ipv4 creates new AF_INET socket address.
|
||||
// addr must be set in network (big-endian) byte order.
|
||||
pub fn SocketAddr.ipv4(addr [4]u8, port u16) SocketAddr {
|
||||
@@ -149,9 +54,6 @@ pub fn SocketAddr.unix(path string) !SocketAddr {
|
||||
// the address itself, you need to do that manually. The benefit is that you can create the
|
||||
// any kind of socket address.
|
||||
//
|
||||
// Note: This function sets the address family struct field for you, it is always first
|
||||
// and 2-byte size (`u16` type).
|
||||
//
|
||||
// SocketAddr is a "constructor" for
|
||||
// [sockaddr(3type)](https://www.man7.org/linux/man-pages/man3/sockaddr.3type.html) objects.
|
||||
// Use this function only if you understand what you do. You must manually write the data
|
||||
@@ -169,7 +71,7 @@ pub fn SocketAddr.unix(path string) !SocketAddr {
|
||||
// Data must be padded to sockaddr struct size which is 16 bytes. Each field is then
|
||||
// written in turn, from top to bottom. Keep in mind that two-byte address family field
|
||||
// (sin_family in this case) is already written. According to the manual page, the
|
||||
// address and port are written using the network (big endian) byte order.
|
||||
// address and port are written using the network (big-endian) byte order.
|
||||
//
|
||||
// Example:
|
||||
// ```v
|
||||
@@ -194,6 +96,7 @@ pub fn SocketAddr.unix(path string) !SocketAddr {
|
||||
// sa.push(binary.big_endian_get_u16(u16(1080)))!
|
||||
// sa.push([u8(127), 0, 0, 1])!
|
||||
// }
|
||||
// println(sa)
|
||||
// ```
|
||||
@[unsafe]
|
||||
pub fn SocketAddr.new(af AddrFamily, size isize) SocketAddr {
|
||||
@@ -276,6 +179,10 @@ pub fn (a SocketAddr) u8_array() []u8 {
|
||||
}
|
||||
|
||||
// str returns the string representation of socket address.
|
||||
// Supported address families are AF_INET, AF_INET6, and AF_UNIX.
|
||||
// For others a string like 'SocketAddr(0x00000000)' will be returned.
|
||||
// Examples: '172.16.16.132:1080', '[fdf1:72d1:0033:0000:0000:0000:0000:0247]:25535,
|
||||
// '/run/app.sock'. See also `translate_name()`.
|
||||
pub fn (a SocketAddr) str() string {
|
||||
match a.family() {
|
||||
af_inet {
|
||||
@@ -320,7 +227,7 @@ pub fn (a SocketAddr) str() string {
|
||||
return res
|
||||
}
|
||||
else {
|
||||
return 'SocketAddr(${a.data.str()})'
|
||||
return 'SocketAddr(0x${a.data:08x})'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user