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
+8
View File
@@ -0,0 +1,8 @@
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.v]
indent_style = tab
+8
View File
@@ -0,0 +1,8 @@
* text=auto eol=lf
*.bat eol=crlf
*.v linguist-language=V
*.vv linguist-language=V
*.vsh linguist-language=V
v.mod linguist-language=V
.vdocignore linguist-language=ignore
+27
View File
@@ -0,0 +1,27 @@
# Binaries for programs and plugins
main
netio
*.exe
*.exe~
*.so
*.dylib
*.dll
# Ignore binary output folders
bin/
# Ignore common editor/system specific metadata
.DS_Store
.idea/
.vscode/
*.iml
# ENV
.env
# vweb and database
*.db
*.js
# Ignore installed modules through `v install --local`:
modules/
+5
View File
@@ -0,0 +1,5 @@
# Networking Library for V
**netio** is a networking library for V programming language.
This implementation aims to be as flexible and portable.
It heavily relies on the libc.
+310
View File
@@ -0,0 +1,310 @@
module netio
import dlmalloc
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(node &char, srvc &char, hints &C.addrinfo, res &&C.addrinfo) int
fn C.freeaddrinfo(info &C.addrinfo)
const max_unix_path_size = $if linux {
108
} $else $if windows {
108
} $else {
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.
// See also [getaddrinfo(3)](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html).
// Example:
// ```v
// import os
// import netio
//
// // Resolve the host FQND
// addrs := netio.translate_addr(node: os.hostname()!, flags: C.AI_CANONNAME)!
// for addr in addrs {
// 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 in big-endian byte order.
pub fn SocketAddr.ipv4(addr [4]u8, port u16) SocketAddr {
mut sock_addr := unsafe { SocketAddr.empty(af_inet, 16) }
unsafe {
sock_addr.push(binary.little_endian_get_u16(u16(af_inet))) or {}
sock_addr.push(binary.big_endian_get_u16(port)) or {}
sock_addr.push(addr[..]) or {}
}
return sock_addr
}
// SocketAddr.ipv6 creates new AF_INET6 socket address.
// addr must be in big-endian byte order.
pub fn SocketAddr.ipv6(addr [16]u8, port u16, flow_info u32, scope_id u32) SocketAddr {
mut sock_addr := unsafe { SocketAddr.empty(af_inet6, 28) }
unsafe {
sock_addr.push(binary.big_endian_get_u16(port)) or {}
sock_addr.push(binary.big_endian_get_u32(flow_info)) or {}
sock_addr.push(addr[..]) or {}
sock_addr.push(binary.big_endian_get_u32(scope_id)) or {}
}
return sock_addr
}
// SocketAddr.unix creates new AF_UNIX socket address.
pub fn SocketAddr.unix(path string) SocketAddr {
mut sock_addr := unsafe { SocketAddr.empty(af_unix, usize(max_unix_path_size) + 2) }
unsafe {
sock_addr.push(path.bytes()) or {}
}
return sock_addr
}
// SocketAddr.empty creates new instance of SocketAddr with specified address family and size.
//
// Note: This function only allocates memory (zero filled) for the address, but **does not**
// initialize the address itself, you need to do that manually. The benefit is that you can
// create the any type of address.
//
// Note: This function sets the address family for you.
// This field is always first and have 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
// for the desired socket address, ensuring the correct sizes of all types, the order of
// the fields in the struct, the byte order, and the total size of the struct. The sizes
// and byte order may vary by platform, so you'll need to keep an eye on that as well.
// A mistake while creating an address will crash your application. So this function is
// marked as `unsafe`.
//
// The example below creates a `sockaddr_in` struct describing the loopback IPv4-address
// 127.0.0.1 with port number 1080. Note the comment in the example. This is a fragment
// of [sockaddr_in(3type)](https://www.man7.org/linux/man-pages/man3/sockaddr.3type.html)
// manual page, which shows the target C struct. Summing the field sizes yields 8
// bytes, but we need to allocate 16 bytes according to the <netinet/in.h>.
// 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 address family field (sin_family
// in this case) are already written. According to the manual page, the address and port
// are written using the network (big endian) byte order.
//
// Example:
// ```v
// import encoding.binary
// import netio
//
// // struct sockaddr_in {
// // sa_family_t sin_family; /* AF_INET */
// // in_port_t sin_port; /* Port number */
// // struct in_addr sin_addr; /* IPv4 address */
// // };
// //
// // struct in_addr {
// // in_addr_t s_addr;
// // };
// //
// // typedef uint32_t in_addr_t;
// // typedef uint16_t in_port_t;
//
// mut sa := unsafe { netio.SocketAddr.empty(u16(C.AF_INET), 16) }
// unsafe {
// sa.push(binary.big_endian_get_u16(u16(1080)))!
// sa.push([u8(127), 0, 0, 1])!
// }
// ```
@[unsafe]
pub fn SocketAddr.empty(af AddrFamily, size isize) SocketAddr {
ptr := unsafe { dlmalloc.calloc(usize(size)) }
mut sock_addr := SocketAddr{
data: ptr
len: int(size)
}
unsafe {
$if little_endian {
sock_addr.push(binary.little_endian_get_u16(u16(af))) or {}
} $else {
sock_addr.push(binary.big_endian_get_u16(u16(af))) or {}
}
}
return sock_addr
}
// SocketAddr.from_ptr creates new socket address by copying data from specified pointer.
@[unsafe]
pub fn SocketAddr.from_ptr(ptr voidptr, size isize) !SocketAddr {
data := unsafe { dlmalloc.calloc(usize(size)) }
unsafe {
vmemcpy(data, ptr, size)
}
return SocketAddr{
data: data
len: int(size)
}
}
struct SocketAddr {
mut:
data &u8 = unsafe { nil }
len int
pos int
}
// family returns the socket address family.
pub fn (a SocketAddr) family() AddrFamily {
mut f := u16(-1)
unsafe { vmemcpy(&f, a.data, isize(2)) }
return f
}
// push appends the `inp` bytes into internal data buffer.
@[unsafe]
pub fn (mut a SocketAddr) push(inp []u8) ! {
if a.pos + inp.len > a.len {
return error('push: data overflow')
}
mut i := 0
for a.pos + 1 < a.len {
unsafe {
a.data[a.pos + i] = inp[i]
}
i++
if i >= inp.len {
break
}
}
a.pos += inp.len
}
// ptr returns the pointer to sockaddr data.
pub fn (a SocketAddr) ptr() &u8 {
return a.data
}
// size reports the size of sockaddr data.
pub fn (a SocketAddr) size() u32 {
return u32(a.len)
}
pub fn (a SocketAddr) str() string {
family := a.family()
match family {
af_inet {
mut addr := [4]u8{}
mut port := [2]u8{}
unsafe {
vmemcpy(port, a.ptr() + 2, 2)
vmemcpy(addr, a.ptr() + 4, 4)
}
port_int := binary.big_endian_u16_fixed(port)
return '${addr[0]}.${addr[1]}.${addr[2]}.${addr[3]}:${port_int}'
}
af_inet6 {
mut addr := [16]u8{}
mut port := [2]u8{}
mut res := ''
unsafe {
vmemcpy(port, a.ptr() + 2, 2)
vmemcpy(addr, a.ptr() + 8, 16)
}
for i := 0; i < 16; i += 2 {
res += addr[i..i + 2].hex()
if i < 14 {
res += ':'
}
}
return res
}
af_unix {
mut path := [max_unix_path_size]u8{}
mut res := ''
unsafe {
vmemcpy(path, a.ptr() + 2, max_unix_path_size)
res = tos_clone(&u8(path[..].data))
}
return res
}
else {
return 'SocketAddr(${a.data.str()})'
}
}
}
+44
View File
@@ -0,0 +1,44 @@
module netio
/*
Address families defined on Darwin.
*/
pub const af_appletalk = AddrFamily(u16(C.AF_APPLETALK))
pub const af_ccitt = AddrFamily(u16(C.AF_CCITT))
pub const af_chaos = AddrFamily(u16(C.AF_CHAOS))
pub const af_cnt = AddrFamily(u16(C.AF_CNT))
pub const af_coip = AddrFamily(u16(C.AF_COIP))
pub const af_datakit = AddrFamily(u16(C.AF_DATAKIT))
pub const af_decnet = AddrFamily(u16(C.AF_DECnet))
pub const af_dli = AddrFamily(u16(C.AF_DLI))
pub const af_e164 = AddrFamily(u16(C.AF_E164))
pub const af_ecma = AddrFamily(u16(C.AF_ECMA))
pub const af_hylink = AddrFamily(u16(C.AF_HYLINK))
pub const af_ieee80211 = AddrFamily(u16(C.AF_IEEE80211))
pub const af_implink = AddrFamily(u16(C.AF_IMPLINK))
pub const af_inet6 = AddrFamily(u16(C.AF_INET6))
pub const af_inet = AddrFamily(u16(C.AF_INET))
pub const af_ipx = AddrFamily(u16(C.AF_IPX))
pub const af_isdn = AddrFamily(u16(C.AF_ISDN))
pub const af_iso = AddrFamily(u16(C.AF_ISO))
pub const af_lat = AddrFamily(u16(C.AF_LAT))
pub const af_link = AddrFamily(u16(C.AF_LINK))
pub const af_local = AddrFamily(u16(C.AF_LOCAL))
pub const af_max = AddrFamily(u16(C.AF_MAX))
pub const af_natm = AddrFamily(u16(C.AF_NATM))
pub const af_ndrv = AddrFamily(u16(C.AF_NDRV))
pub const af_netbios = AddrFamily(u16(C.AF_NETBIOS))
pub const af_ns = AddrFamily(u16(C.AF_NS))
pub const af_osi = AddrFamily(u16(C.AF_OSI))
pub const af_ppp = AddrFamily(u16(C.AF_PPP))
pub const af_pup = AddrFamily(u16(C.AF_PUP))
pub const af_reserved_36 = AddrFamily(u16(C.AF_RESERVED_36))
pub const af_route = AddrFamily(u16(C.AF_ROUTE))
pub const af_sip = AddrFamily(u16(C.AF_SIP))
pub const af_sna = AddrFamily(u16(C.AF_SNA))
pub const af_system = AddrFamily(u16(C.AF_SYSTEM))
pub const af_unix = AddrFamily(u16(C.AF_UNIX))
pub const af_unspec = AddrFamily(u16(C.AF_UNSPEC))
pub const af_utun = AddrFamily(u16(C.AF_UTUN))
pub const af_vsock = AddrFamily(u16(C.AF_VSOCK))
+10
View File
@@ -0,0 +1,10 @@
module netio
/*
Well defined address families. Must work on all platforms.
*/
pub const af_unspec = AddrFamily(u16(C.AF_UNSPEC))
pub const af_unix = AddrFamily(u16(C.AF_UNIX))
pub const af_inet = AddrFamily(u16(C.AF_INET))
pub const af_inet6 = AddrFamily(u16(C.AF_INET6))
+96
View File
@@ -0,0 +1,96 @@
module netio
/*
Address families defined on FreeBSD.
*/
pub const af_appletalk = AddrFamily(u16(C.AF_APPLETALK))
pub const af_arp = AddrFamily(u16(C.AF_ARP))
pub const af_atm = AddrFamily(u16(C.AF_ATM))
pub const af_bluetooth = AddrFamily(u16(C.AF_BLUETOOTH))
pub const af_ccitt = AddrFamily(u16(C.AF_CCITT))
pub const af_chaos = AddrFamily(u16(C.AF_CHAOS))
pub const af_cnt = AddrFamily(u16(C.AF_CNT))
pub const af_coip = AddrFamily(u16(C.AF_COIP))
pub const af_datakit = AddrFamily(u16(C.AF_DATAKIT))
pub const af_decnet = AddrFamily(u16(C.AF_DECnet))
pub const af_divert = AddrFamily(u16(C.AF_DIVERT))
pub const af_dli = AddrFamily(u16(C.AF_DLI))
pub const af_e164 = AddrFamily(u16(C.AF_E164))
pub const af_ecma = AddrFamily(u16(C.AF_ECMA))
pub const af_hylink = AddrFamily(u16(C.AF_HYLINK))
pub const af_hyperv = AddrFamily(u16(C.AF_HYPERV))
pub const af_ieee80211 = AddrFamily(u16(C.AF_IEEE80211))
pub const af_implink = AddrFamily(u16(C.AF_IMPLINK))
pub const af_inet6 = AddrFamily(u16(C.AF_INET6))
pub const af_inet6_sdp = AddrFamily(u16(C.AF_INET6_SDP))
pub const af_inet = AddrFamily(u16(C.AF_INET))
pub const af_inet_sdp = AddrFamily(u16(C.AF_INET_SDP))
pub const af_ipfwlog = AddrFamily(u16(C.AF_IPFWLOG))
pub const af_ipx = AddrFamily(u16(C.AF_IPX))
pub const af_isdn = AddrFamily(u16(C.AF_ISDN))
pub const af_iso = AddrFamily(u16(C.AF_ISO))
pub const af_lat = AddrFamily(u16(C.AF_LAT))
pub const af_link = AddrFamily(u16(C.AF_LINK))
pub const af_local = AddrFamily(u16(C.AF_LOCAL))
pub const af_max = AddrFamily(u16(C.AF_MAX))
pub const af_natm = AddrFamily(u16(C.AF_NATM))
pub const af_netbios = AddrFamily(u16(C.AF_NETBIOS))
pub const af_netgraph = AddrFamily(u16(C.AF_NETGRAPH))
pub const af_netlink = AddrFamily(u16(C.AF_NETLINK))
pub const af_osi = AddrFamily(u16(C.AF_OSI))
pub const af_pup = AddrFamily(u16(C.AF_PUP))
pub const af_route = AddrFamily(u16(C.AF_ROUTE))
pub const af_scluster = AddrFamily(u16(C.AF_SCLUSTER))
pub const af_sip = AddrFamily(u16(C.AF_SIP))
pub const af_slow = AddrFamily(u16(C.AF_SLOW))
pub const af_sna = AddrFamily(u16(C.AF_SNA))
pub const af_unix = AddrFamily(u16(C.AF_UNIX))
pub const af_unspec = AddrFamily(u16(C.AF_UNSPEC))
pub const af_vendor00 = AddrFamily(u16(C.AF_VENDOR00))
pub const af_vendor01 = AddrFamily(u16(C.AF_VENDOR01))
pub const af_vendor03 = AddrFamily(u16(C.AF_VENDOR03))
pub const af_vendor04 = AddrFamily(u16(C.AF_VENDOR04))
pub const af_vendor05 = AddrFamily(u16(C.AF_VENDOR05))
pub const af_vendor06 = AddrFamily(u16(C.AF_VENDOR06))
pub const af_vendor07 = AddrFamily(u16(C.AF_VENDOR07))
pub const af_vendor08 = AddrFamily(u16(C.AF_VENDOR08))
pub const af_vendor09 = AddrFamily(u16(C.AF_VENDOR09))
pub const af_vendor10 = AddrFamily(u16(C.AF_VENDOR10))
pub const af_vendor11 = AddrFamily(u16(C.AF_VENDOR11))
pub const af_vendor12 = AddrFamily(u16(C.AF_VENDOR12))
pub const af_vendor13 = AddrFamily(u16(C.AF_VENDOR13))
pub const af_vendor14 = AddrFamily(u16(C.AF_VENDOR14))
pub const af_vendor15 = AddrFamily(u16(C.AF_VENDOR15))
pub const af_vendor16 = AddrFamily(u16(C.AF_VENDOR16))
pub const af_vendor17 = AddrFamily(u16(C.AF_VENDOR17))
pub const af_vendor18 = AddrFamily(u16(C.AF_VENDOR18))
pub const af_vendor19 = AddrFamily(u16(C.AF_VENDOR19))
pub const af_vendor20 = AddrFamily(u16(C.AF_VENDOR20))
pub const af_vendor21 = AddrFamily(u16(C.AF_VENDOR21))
pub const af_vendor22 = AddrFamily(u16(C.AF_VENDOR22))
pub const af_vendor23 = AddrFamily(u16(C.AF_VENDOR23))
pub const af_vendor24 = AddrFamily(u16(C.AF_VENDOR24))
pub const af_vendor25 = AddrFamily(u16(C.AF_VENDOR25))
pub const af_vendor26 = AddrFamily(u16(C.AF_VENDOR26))
pub const af_vendor27 = AddrFamily(u16(C.AF_VENDOR27))
pub const af_vendor28 = AddrFamily(u16(C.AF_VENDOR28))
pub const af_vendor29 = AddrFamily(u16(C.AF_VENDOR29))
pub const af_vendor30 = AddrFamily(u16(C.AF_VENDOR30))
pub const af_vendor31 = AddrFamily(u16(C.AF_VENDOR31))
pub const af_vendor32 = AddrFamily(u16(C.AF_VENDOR32))
pub const af_vendor33 = AddrFamily(u16(C.AF_VENDOR33))
pub const af_vendor34 = AddrFamily(u16(C.AF_VENDOR34))
pub const af_vendor35 = AddrFamily(u16(C.AF_VENDOR35))
pub const af_vendor36 = AddrFamily(u16(C.AF_VENDOR36))
pub const af_vendor37 = AddrFamily(u16(C.AF_VENDOR37))
pub const af_vendor38 = AddrFamily(u16(C.AF_VENDOR38))
pub const af_vendor39 = AddrFamily(u16(C.AF_VENDOR39))
pub const af_vendor40 = AddrFamily(u16(C.AF_VENDOR40))
pub const af_vendor41 = AddrFamily(u16(C.AF_VENDOR41))
pub const af_vendor42 = AddrFamily(u16(C.AF_VENDOR42))
pub const af_vendor43 = AddrFamily(u16(C.AF_VENDOR43))
pub const af_vendor44 = AddrFamily(u16(C.AF_VENDOR44))
pub const af_vendor45 = AddrFamily(u16(C.AF_VENDOR45))
pub const af_vendor46 = AddrFamily(u16(C.AF_VENDOR46))
pub const af_vendor47 = AddrFamily(u16(C.AF_VENDOR47))
+56
View File
@@ -0,0 +1,56 @@
module netio
/*
Address families defined on Linux.
*/
pub const af_alg = AddrFamily(u16(C.AF_ALG))
pub const af_appletalk = AddrFamily(u16(C.AF_APPLETALK))
pub const af_ash = AddrFamily(u16(C.AF_ASH))
pub const af_atmpvc = AddrFamily(u16(C.AF_ATMPVC))
pub const af_atmsvc = AddrFamily(u16(C.AF_ATMSVC))
pub const af_ax25 = AddrFamily(u16(C.AF_AX25))
pub const af_bluetooth = AddrFamily(u16(C.AF_BLUETOOTH))
pub const af_bridge = AddrFamily(u16(C.AF_BRIDGE))
pub const af_caif = AddrFamily(u16(C.AF_CAIF))
pub const af_can = AddrFamily(u16(C.AF_CAN))
pub const af_decnet = AddrFamily(u16(C.AF_DECnet))
pub const af_econet = AddrFamily(u16(C.AF_ECONET))
pub const af_file = AddrFamily(u16(C.AF_FILE))
pub const af_ib = AddrFamily(u16(C.AF_IB))
pub const af_ieee802154 = AddrFamily(u16(C.AF_IEEE802154))
pub const af_inet6 = AddrFamily(u16(C.AF_INET6))
pub const af_inet = AddrFamily(u16(C.AF_INET))
pub const af_ipx = AddrFamily(u16(C.AF_IPX))
pub const af_irda = AddrFamily(u16(C.AF_IRDA))
pub const af_isdn = AddrFamily(u16(C.AF_ISDN))
pub const af_iucv = AddrFamily(u16(C.AF_IUCV))
pub const af_kcm = AddrFamily(u16(C.AF_KCM))
pub const af_key = AddrFamily(u16(C.AF_KEY))
pub const af_llc = AddrFamily(u16(C.AF_LLC))
pub const af_local = AddrFamily(u16(C.AF_LOCAL))
pub const af_max = AddrFamily(u16(C.AF_MAX))
pub const af_mctp = AddrFamily(u16(C.AF_MCTP))
pub const af_mpls = AddrFamily(u16(C.AF_MPLS))
pub const af_netbeui = AddrFamily(u16(C.AF_NETBEUI))
pub const af_netlink = AddrFamily(u16(C.AF_NETLINK))
pub const af_netrom = AddrFamily(u16(C.AF_NETROM))
pub const af_nfc = AddrFamily(u16(C.AF_NFC))
pub const af_packet = AddrFamily(u16(C.AF_PACKET))
pub const af_phonet = AddrFamily(u16(C.AF_PHONET))
pub const af_pppox = AddrFamily(u16(C.AF_PPPOX))
pub const af_qipcrtr = AddrFamily(u16(C.AF_QIPCRTR))
pub const af_rds = AddrFamily(u16(C.AF_RDS))
pub const af_rose = AddrFamily(u16(C.AF_ROSE))
pub const af_route = AddrFamily(u16(C.AF_ROUTE))
pub const af_rxrpc = AddrFamily(u16(C.AF_RXRPC))
pub const af_security = AddrFamily(u16(C.AF_SECURITY))
pub const af_smc = AddrFamily(u16(C.AF_SMC))
pub const af_sna = AddrFamily(u16(C.AF_SNA))
pub const af_tipc = AddrFamily(u16(C.AF_TIPC))
pub const af_unix = AddrFamily(u16(C.AF_UNIX))
pub const af_unspec = AddrFamily(u16(C.AF_UNSPEC))
pub const af_vsock = AddrFamily(u16(C.AF_VSOCK))
pub const af_wanpipe = AddrFamily(u16(C.AF_WANPIPE))
pub const af_x25 = AddrFamily(u16(C.AF_X25))
pub const af_xdp = AddrFamily(u16(C.AF_XDP))
+45
View File
@@ -0,0 +1,45 @@
// import net
import netio
// import time
import os
fn main() {
listen_addr := netio.SocketAddr.ipv4([u8(127), 0, 0, 1]!, 1081)
eprintln(listen_addr.family())
// eprintln(listen_addr)
// mut socket := netio.Socket.new(netio.af_inet, .tcp, 0)!
// socket.bind(listen_addr)!
// socket.listen(10)!
// println('Server started...')
// for {
// conn_fd := socket.accept()!.fd
// mut sock := net.tcp_socket_from_handle_raw(conn_fd)
// mut conn := net.TcpConn{
// sock: sock
// handle: conn_fd
// read_timeout: 30 * time.second
// write_timeout: 30 * time.second
// }
// read := conn.read_line()
// println('Data read: ${read}')
// net.close(conn_fd)!
// }
// socket.close()!
// hostname := dump(os.hostname()!)
ai := netio.translate_addr(
node: 'localhost'
flags: C.AI_CANONNAME
family: netio.af_inet
sock_type: netio.sock_stream
)!
dump(ai.len)
for a in ai {
println(a)
// println('Protocol: ' + netio.protocol_by_number(a.protocol)!.name)
// println('Address: ' + a.addr.str())
// println('Canonical name: ' + a.canonical)
// println('---')
}
}
+25
View File
@@ -0,0 +1,25 @@
module netio
import sync
fn init() {
netio_protoent_mutex = sync.new_mutex()
}
fn cleanup() {
netio_protoent_mutex.destroy()
unsafe { free(netio_protoent_mutex) }
}
// The socket address family type.
// See [address_families(7)](https://www.man7.org/linux/man-pages/man7/address_families.7.html).
pub type AddrFamily = u16
// The socket type.
pub type SocketType = int
// The socket level type.
pub type SocketLevel = int
// The socket option type.
pub type SocketOption = int
+1
View File
@@ -0,0 +1 @@
module netio
+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)
}
+47
View File
@@ -0,0 +1,47 @@
module netio
/*
Socket options defined on Darwin.
*/
pub const so_acceptconn = SocketOption(C.SO_ACCEPTCONN)
pub const so_bindtodevice = SocketOption(C.SO_BINDTODEVICE)
pub const so_broadcast = SocketOption(C.SO_BROADCAST)
pub const so_debug = SocketOption(C.SO_DEBUG)
pub const so_dontroute = SocketOption(C.SO_DONTROUTE)
pub const so_donttrunc = SocketOption(C.SO_DONTTRUNC)
pub const so_error = SocketOption(C.SO_ERROR)
pub const so_keepalive = SocketOption(C.SO_KEEPALIVE)
pub const so_label = SocketOption(C.SO_LABEL)
pub const so_linger = SocketOption(C.SO_LINGER)
pub const so_linger_sec = SocketOption(C.SO_LINGER_SEC)
pub const so_netsvc_marking_level = SocketOption(C.SO_NETSVC_MARKING_LEVEL)
pub const so_net_service_type = SocketOption(C.SO_NET_SERVICE_TYPE)
pub const so_nke = SocketOption(C.SO_NKE)
pub const so_noaddrerr = SocketOption(C.SO_NOADDRERR)
pub const so_nosigpipe = SocketOption(C.SO_NOSIGPIPE)
pub const so_notifyconflict = SocketOption(C.SO_NOTIFYCONFLICT)
pub const so_np_extensions = SocketOption(C.SO_NP_EXTENSIONS)
pub const so_nread = SocketOption(C.SO_NREAD)
pub const so_numrcvpkt = SocketOption(C.SO_NUMRCVPKT)
pub const so_nwrite = SocketOption(C.SO_NWRITE)
pub const so_oobinline = SocketOption(C.SO_OOBINLINE)
pub const so_peerlabel = SocketOption(C.SO_PEERLABEL)
pub const so_randomport = SocketOption(C.SO_RANDOMPORT)
pub const so_rcvbuf = SocketOption(C.SO_RCVBUF)
pub const so_rcvlowat = SocketOption(C.SO_RCVLOWAT)
pub const so_rcvtimeo = SocketOption(C.SO_RCVTIMEO)
pub const so_resolver_signature = SocketOption(C.SO_RESOLVER_SIGNATURE)
pub const so_reuseaddr = SocketOption(C.SO_REUSEADDR)
pub const so_reuseport = SocketOption(C.SO_REUSEPORT)
pub const so_reuseshareuid = SocketOption(C.SO_REUSESHAREUID)
pub const so_sndbuf = SocketOption(C.SO_SNDBUF)
pub const so_sndlowat = SocketOption(C.SO_SNDLOWAT)
pub const so_sndtimeo = SocketOption(C.SO_SNDTIMEO)
pub const so_timestamp = SocketOption(C.SO_TIMESTAMP)
pub const so_timestamp_monotonic = SocketOption(C.SO_TIMESTAMP_MONOTONIC)
pub const so_type = SocketOption(C.SO_TYPE)
pub const so_upcallclosewait = SocketOption(C.SO_UPCALLCLOSEWAIT)
pub const so_useloopback = SocketOption(C.SO_USELOOPBACK)
pub const so_wantmore = SocketOption(C.SO_WANTMORE)
pub const so_wantoobflag = SocketOption(C.SO_WANTOOBFLAG)
+53
View File
@@ -0,0 +1,53 @@
module netio
/*
Socket options defined on FreeBSD.
*/
pub const so_acceptconn = SocketOption(C.SO_ACCEPTCONN)
pub const so_acceptfilter = SocketOption(C.SO_ACCEPTFILTER)
pub const so_bintime = SocketOption(C.SO_BINTIME)
pub const so_broadcast = SocketOption(C.SO_BROADCAST)
pub const so_debug = SocketOption(C.SO_DEBUG)
pub const so_domain = SocketOption(C.SO_DOMAIN)
pub const so_dontroute = SocketOption(C.SO_DONTROUTE)
pub const so_error = SocketOption(C.SO_ERROR)
pub const so_fib = SocketOption(C.SO_FIB)
pub const so_keepalive = SocketOption(C.SO_KEEPALIVE)
pub const so_label = SocketOption(C.SO_LABEL)
pub const so_linger = SocketOption(C.SO_LINGER)
pub const so_listenincqlen = SocketOption(C.SO_LISTENINCQLEN)
pub const so_listenqlen = SocketOption(C.SO_LISTENQLEN)
pub const so_listenqlimit = SocketOption(C.SO_LISTENQLIMIT)
pub const so_max_pacing_rate = SocketOption(C.SO_MAX_PACING_RATE)
pub const so_nosigpipe = SocketOption(C.SO_NOSIGPIPE)
pub const so_no_ddp = SocketOption(C.SO_NO_DDP)
pub const so_no_offload = SocketOption(C.SO_NO_OFFLOAD)
pub const so_oobinline = SocketOption(C.SO_OOBINLINE)
pub const so_peerlabel = SocketOption(C.SO_PEERLABEL)
pub const so_protocol = SocketOption(C.SO_PROTOCOL)
pub const so_prototype = SocketOption(C.SO_PROTOTYPE)
pub const so_rcvbuf = SocketOption(C.SO_RCVBUF)
pub const so_rcvlowat = SocketOption(C.SO_RCVLOWAT)
pub const so_rcvtimeo = SocketOption(C.SO_RCVTIMEO)
pub const so_rerror = SocketOption(C.SO_RERROR)
pub const so_reuseaddr = SocketOption(C.SO_REUSEADDR)
pub const so_reuseport = SocketOption(C.SO_REUSEPORT)
pub const so_reuseport_lb = SocketOption(C.SO_REUSEPORT_LB)
pub const so_setfib = SocketOption(C.SO_SETFIB)
pub const so_sndbuf = SocketOption(C.SO_SNDBUF)
pub const so_sndlowat = SocketOption(C.SO_SNDLOWAT)
pub const so_sndtimeo = SocketOption(C.SO_SNDTIMEO)
pub const so_splice = SocketOption(C.SO_SPLICE)
pub const so_timestamp = SocketOption(C.SO_TIMESTAMP)
pub const so_ts_bintime = SocketOption(C.SO_TS_BINTIME)
pub const so_ts_clock = SocketOption(C.SO_TS_CLOCK)
pub const so_ts_clock_max = SocketOption(C.SO_TS_CLOCK_MAX)
pub const so_ts_default = SocketOption(C.SO_TS_DEFAULT)
pub const so_ts_monotonic = SocketOption(C.SO_TS_MONOTONIC)
pub const so_ts_realtime = SocketOption(C.SO_TS_REALTIME)
pub const so_ts_realtime_micro = SocketOption(C.SO_TS_REALTIME_MICRO)
pub const so_type = SocketOption(C.SO_TYPE)
pub const so_useloopback = SocketOption(C.SO_USELOOPBACK)
pub const so_user_cookie = SocketOption(C.SO_USER_COOKIE)
pub const so_vendor = SocketOption(C.SO_VENDOR)
+94
View File
@@ -0,0 +1,94 @@
module netio
/*
Socket options defined on Linux.
*/
pub const so_acceptconn = SocketOption(C.SO_ACCEPTCONN)
pub const so_attach_bpf = SocketOption(C.SO_ATTACH_BPF)
pub const so_attach_filter = SocketOption(C.SO_ATTACH_FILTER)
pub const so_attach_reuseport_cbpf = SocketOption(C.SO_ATTACH_REUSEPORT_CBPF)
pub const so_attach_reuseport_ebpf = SocketOption(C.SO_ATTACH_REUSEPORT_EBPF)
pub const so_bindtodevice = SocketOption(C.SO_BINDTODEVICE)
pub const so_bindtoifindex = SocketOption(C.SO_BINDTOIFINDEX)
pub const so_bpf_extensions = SocketOption(C.SO_BPF_EXTENSIONS)
pub const so_broadcast = SocketOption(C.SO_BROADCAST)
pub const so_bsdcompat = SocketOption(C.SO_BSDCOMPAT)
pub const so_buf_lock = SocketOption(C.SO_BUF_LOCK)
pub const so_busy_poll = SocketOption(C.SO_BUSY_POLL)
pub const so_busy_poll_budget = SocketOption(C.SO_BUSY_POLL_BUDGET)
pub const so_cnx_advice = SocketOption(C.SO_CNX_ADVICE)
pub const so_cookie = SocketOption(C.SO_COOKIE)
pub const so_debug = SocketOption(C.SO_DEBUG)
pub const so_detach_bpf = SocketOption(C.SO_DETACH_BPF)
pub const so_detach_filter = SocketOption(C.SO_DETACH_FILTER)
pub const so_detach_reuseport_bpf = SocketOption(C.SO_DETACH_REUSEPORT_BPF)
pub const so_devmem_dmabuf = SocketOption(C.SO_DEVMEM_DMABUF)
pub const so_devmem_dontneed = SocketOption(C.SO_DEVMEM_DONTNEED)
pub const so_devmem_linear = SocketOption(C.SO_DEVMEM_LINEAR)
pub const so_domain = SocketOption(C.SO_DOMAIN)
pub const so_dontroute = SocketOption(C.SO_DONTROUTE)
pub const so_error = SocketOption(C.SO_ERROR)
pub const so_get_filter = SocketOption(C.SO_GET_FILTER)
pub const so_incoming_cpu = SocketOption(C.SO_INCOMING_CPU)
pub const so_incoming_napi_id = SocketOption(C.SO_INCOMING_NAPI_ID)
pub const so_inq = SocketOption(C.SO_INQ)
pub const so_keepalive = SocketOption(C.SO_KEEPALIVE)
pub const so_linger = SocketOption(C.SO_LINGER)
pub const so_lock_filter = SocketOption(C.SO_LOCK_FILTER)
pub const so_mark = SocketOption(C.SO_MARK)
pub const so_max_pacing_rate = SocketOption(C.SO_MAX_PACING_RATE)
pub const so_meminfo = SocketOption(C.SO_MEMINFO)
pub const so_netns_cookie = SocketOption(C.SO_NETNS_COOKIE)
pub const so_nofcs = SocketOption(C.SO_NOFCS)
pub const so_no_check = SocketOption(C.SO_NO_CHECK)
pub const so_oobinline = SocketOption(C.SO_OOBINLINE)
pub const so_passcred = SocketOption(C.SO_PASSCRED)
pub const so_passpidfd = SocketOption(C.SO_PASSPIDFD)
pub const so_passrights = SocketOption(C.SO_PASSRIGHTS)
pub const so_passsec = SocketOption(C.SO_PASSSEC)
pub const so_peek_off = SocketOption(C.SO_PEEK_OFF)
pub const so_peercred = SocketOption(C.SO_PEERCRED)
pub const so_peergroups = SocketOption(C.SO_PEERGROUPS)
pub const so_peername = SocketOption(C.SO_PEERNAME)
pub const so_peerpidfd = SocketOption(C.SO_PEERPIDFD)
pub const so_peersec = SocketOption(C.SO_PEERSEC)
pub const so_prefer_busy_poll = SocketOption(C.SO_PREFER_BUSY_POLL)
pub const so_priority = SocketOption(C.SO_PRIORITY)
pub const so_protocol = SocketOption(C.SO_PROTOCOL)
pub const so_rcvbufforce = SocketOption(C.SO_RCVBUFFORCE)
pub const so_rcvbuf = SocketOption(C.SO_RCVBUF)
pub const so_rcvlowat = SocketOption(C.SO_RCVLOWAT)
pub const so_rcvmark = SocketOption(C.SO_RCVMARK)
pub const so_rcvpriority = SocketOption(C.SO_RCVPRIORITY)
pub const so_rcvtimeo = SocketOption(C.SO_RCVTIMEO)
pub const so_rcvtimeo_new = SocketOption(C.SO_RCVTIMEO_NEW)
pub const so_rcvtimeo_old = SocketOption(C.SO_RCVTIMEO_OLD)
pub const so_reserve_mem = SocketOption(C.SO_RESERVE_MEM)
pub const so_reuseaddr = SocketOption(C.SO_REUSEADDR)
pub const so_reuseport = SocketOption(C.SO_REUSEPORT)
pub const so_rxq_ovfl = SocketOption(C.SO_RXQ_OVFL)
pub const so_security_authentication = SocketOption(C.SO_SECURITY_AUTHENTICATION)
pub const so_security_encryption_network = SocketOption(C.SO_SECURITY_ENCRYPTION_NETWORK)
pub const so_security_encryption_transport = SocketOption(C.SO_SECURITY_ENCRYPTION_TRANSPORT)
pub const so_select_err_queue = SocketOption(C.SO_SELECT_ERR_QUEUE)
pub const so_sndbufforce = SocketOption(C.SO_SNDBUFFORCE)
pub const so_sndbuf = SocketOption(C.SO_SNDBUF)
pub const so_sndlowat = SocketOption(C.SO_SNDLOWAT)
pub const so_sndtimeo = SocketOption(C.SO_SNDTIMEO)
pub const so_sndtimeo_new = SocketOption(C.SO_SNDTIMEO_NEW)
pub const so_sndtimeo_old = SocketOption(C.SO_SNDTIMEO_OLD)
pub const so_timestamping = SocketOption(C.SO_TIMESTAMPING)
pub const so_timestamping_new = SocketOption(C.SO_TIMESTAMPING_NEW)
pub const so_timestamping_old = SocketOption(C.SO_TIMESTAMPING_OLD)
pub const so_timestampns = SocketOption(C.SO_TIMESTAMPNS)
pub const so_timestampns_new = SocketOption(C.SO_TIMESTAMPNS_NEW)
pub const so_timestampns_old = SocketOption(C.SO_TIMESTAMPNS_OLD)
pub const so_timestamp = SocketOption(C.SO_TIMESTAMP)
pub const so_timestamp_new = SocketOption(C.SO_TIMESTAMP_NEW)
pub const so_timestamp_old = SocketOption(C.SO_TIMESTAMP_OLD)
pub const so_txrehash = SocketOption(C.SO_TXREHASH)
pub const so_txtime = SocketOption(C.SO_TXTIME)
pub const so_type = SocketOption(C.SO_TYPE)
pub const so_wifi_status = SocketOption(C.SO_WIFI_STATUS)
pub const so_zerocopy = SocketOption(C.SO_ZEROCOPY)
+11
View File
@@ -0,0 +1,11 @@
module netio
/*
Well defined socket types.
*/
pub const sock_stream = SocketType(C.SOCK_STREAM)
pub const sock_dgram = SocketType(C.SOCK_DGRAM)
pub const sock_seqpacket = SocketType(C.SOCK_SEQPACKET)
pub const sock_raw = SocketType(C.SOCK_RAW)
pub const sock_rdm = SocketType(C.SOCK_RDM)
+13
View File
@@ -0,0 +1,13 @@
module netio
/*
Socket types defined on Linux.
*/
pub const sock_stream = SocketType(C.SOCK_STREAM)
pub const sock_dgram = SocketType(C.SOCK_DGRAM)
pub const sock_seqpacket = SocketType(C.SOCK_SEQPACKET)
pub const sock_raw = SocketType(C.SOCK_RAW)
pub const sock_rdm = SocketType(C.SOCK_RDM)
pub const sock_nonblock = SocketType(C.SOCK_NONBLOCK)
pub const sock_cloexec = SocketType(C.SOCK_CLOEXEC)
+92
View File
@@ -0,0 +1,92 @@
module netio
import os
#include <sys/socket.h>
fn C.socket(i32, i32, i32) i32
fn C.bind(i32, voidptr, i32) i32
fn C.connect(i32, voidptr, i32) i32
fn C.listen(i32, i32) i32
fn C.accept(i32, voidptr, i32) i32
fn C.shutdown(i32, i32) i32
fn C.close(i32) i32
fn C.setsockopt(i32, i32, i32, voidptr, i32) i32
fn C.getsockopt(i32, i32, i32, voidptr, i32) i32
pub struct Socket {
pub:
fd int
}
// Socket.new creates new socket.
// See [socket(7)](https://www.man7.org/linux/man-pages/man7/socket.7.html) and
// [socket(3)](https://man7.org/linux/man-pages/man3/socket.3p.html) for details.
pub fn Socket.new(domain AddrFamily, typ SocketType, protocol Protocol) !Socket {
fd := C.socket(i32(domain), i32(typ), i32(protocol))
if fd == -1 {
return os.last_error()
}
return Socket{
fd: fd
}
}
// Socket shutdown modes. See [shutdown(3p)](https://man7.org/linux/man-pages/man3/shutdown.3p.html) for details.
pub enum Shutdown {
read = C.SHUT_RD
write = C.SHUT_WR
read_and_write = C.SHUT_RDWR
}
// connect connects a socket.
pub fn (s Socket) connect(addr SocketAddr) ! {
if C.connect(s.fd, addr.ptr(), addr.size()) == -1 {
return os.last_error()
}
}
// bind binds a name to a socket.
pub fn (s Socket) bind(addr SocketAddr) ! {
if C.bind(s.fd, addr.ptr(), addr.size()) == -1 {
return os.last_error()
}
}
// listen starts listening for socket connections and limit the queue of incoming connections.
pub fn (s Socket) listen(backlog int) ! {
if C.listen(s.fd, backlog) == -1 {
return os.last_error()
}
}
// accept accepts a new connection on a socket.
pub fn (s Socket) accept() !Socket {
new_fd := C.accept(s.fd, 0, 0)
if new_fd == -1 {
return os.last_error()
}
return Socket{
fd: new_fd
}
}
// set_option sets the socket option.
pub fn (s Socket) set_option(level SocketLevel, option SocketOption, value int) ! {}
// get_option gets the socket option.
pub fn (s Socket) get_option(level SocketLevel, option SocketOption) ! {}
// shutdown shut downs socket send and receive operations.
pub fn (s Socket) shutdown(how Shutdown) ! {
if C.shutdown(s.fd, i32(how)) == -1 {
return os.last_error()
}
}
// close closes the socket.
pub fn (s Socket) close() ! {
if C.close(s.fd) == -1 {
return os.last_error()
}
}
+7
View File
@@ -0,0 +1,7 @@
module netio
/*
Well defined socket levels.
*/
pub const sol_socket = C.SOL_SOCKET
+35
View File
@@ -0,0 +1,35 @@
module netio
/*
Socket levels defined on Linux.
*/
pub const sol_aal = SocketOption(C.SOL_AAL)
pub const sol_alg = SocketOption(C.SOL_ALG)
pub const sol_atm = SocketOption(C.SOL_ATM)
pub const sol_bluetooth = SocketOption(C.SOL_BLUETOOTH)
pub const sol_caif = SocketOption(C.SOL_CAIF)
pub const sol_dccp = SocketOption(C.SOL_DCCP)
pub const sol_decnet = SocketOption(C.SOL_DECNET)
pub const sol_irda = SocketOption(C.SOL_IRDA)
pub const sol_iucv = SocketOption(C.SOL_IUCV)
pub const sol_kcm = SocketOption(C.SOL_KCM)
pub const sol_llc = SocketOption(C.SOL_LLC)
pub const sol_mctp = SocketOption(C.SOL_MCTP)
pub const sol_mptcp = SocketOption(C.SOL_MPTCP)
pub const sol_netbeui = SocketOption(C.SOL_NETBEUI)
pub const sol_netlink = SocketOption(C.SOL_NETLINK)
pub const sol_nfc = SocketOption(C.SOL_NFC)
pub const sol_packet = SocketOption(C.SOL_PACKET)
pub const sol_pnpipe = SocketOption(C.SOL_PNPIPE)
pub const sol_pppol2tp = SocketOption(C.SOL_PPPOL2TP)
pub const sol_raw = SocketOption(C.SOL_RAW)
pub const sol_rds = SocketOption(C.SOL_RDS)
pub const sol_rxrpc = SocketOption(C.SOL_RXRPC)
pub const sol_smc = SocketOption(C.SOL_SMC)
pub const sol_socket = SocketOption(C.SOL_SOCKET)
pub const sol_tipc = SocketOption(C.SOL_TIPC)
pub const sol_tls = SocketOption(C.SOL_TLS)
pub const sol_vsock = SocketOption(C.SOL_VSOCK)
pub const sol_x25 = SocketOption(C.SOL_X25)
pub const sol_xdp = SocketOption(C.SOL_XDP)
+5
View File
@@ -0,0 +1,5 @@
module netio
pub struct TCPListener {}
pub struct TCPStream {}
+3
View File
@@ -0,0 +1,3 @@
module netio
pub struct UDPSocket {}
+7
View File
@@ -0,0 +1,7 @@
Module {
name: 'netio'
description: 'Networking library'
version: '0.0.0'
license: 'MIT'
dependencies: []
}