142 lines
3.7 KiB
V
142 lines
3.7 KiB
V
import net
|
|
import time
|
|
|
|
fn echo_server(mut c net.UdpConn) {
|
|
mut count := 0
|
|
for {
|
|
eprintln('> echo_server loop count: ${count}')
|
|
mut buf := []u8{len: 100}
|
|
read, addr := c.read(mut buf) or { continue }
|
|
eprintln('Server got addr ${addr}, read: ${read} | buf: ${buf}')
|
|
c.write_to(addr, buf[..read]) or {
|
|
println('Server: connection dropped')
|
|
return
|
|
}
|
|
count++
|
|
// Normally, after responding, the test will end, but there are sometimes cases,
|
|
// when the echo_server continued looping, printing messages constantly.
|
|
// The sleep here, is a small precaution against spamming the CI with log messages,
|
|
// when there are network problems, and it allows easier root cause diagnostic, when
|
|
// they do happen:
|
|
time.sleep(1000 * time.millisecond)
|
|
}
|
|
}
|
|
|
|
const server_addr = '127.0.0.1:40003'
|
|
|
|
fn echo() ! {
|
|
mut c := net.dial_udp(server_addr) or { panic('could not net.dial_udp: ${err}') }
|
|
defer {
|
|
c.close() or {}
|
|
}
|
|
data := 'Hello from vlib/net!'
|
|
|
|
c.write_string(data) or { panic('could not write_string: ${err}') }
|
|
|
|
mut buf := []u8{len: 100, init: 0}
|
|
read, addr := c.read(mut buf) or { panic('could not read: ${err}') }
|
|
|
|
assert read == data.len
|
|
println('Got address ${addr}')
|
|
// Can't test this here because loopback addresses
|
|
// are mapped to other addresses
|
|
// assert addr.str() == '127.0.0.1:30001'
|
|
|
|
for i := 0; i < read; i++ {
|
|
assert buf[i] == data[i]
|
|
}
|
|
|
|
println('Got "${buf.bytestr()}"')
|
|
|
|
c.close()!
|
|
}
|
|
|
|
fn test_udp() {
|
|
mut l := net.listen_udp(server_addr) or { panic('could not listen_udp: ${err}') }
|
|
|
|
spawn echo_server(mut l)
|
|
echo() or { panic('could not echo: ${err}') }
|
|
|
|
l.close() or {}
|
|
}
|
|
|
|
fn udp_write_after_delay(addr string, delay time.Duration, payload string, done chan bool) {
|
|
time.sleep(delay)
|
|
mut conn := net.dial_udp(addr) or { panic(err) }
|
|
defer {
|
|
conn.close() or {}
|
|
}
|
|
conn.write_string(payload) or { panic(err) }
|
|
done <- true
|
|
}
|
|
|
|
fn test_udp_read_timeout_is_honored_for_blocking_reads() ! {
|
|
mut listener := net.listen_udp('127.0.0.1:0')!
|
|
defer {
|
|
listener.close() or {}
|
|
}
|
|
addr := listener.sock.address()!.str()
|
|
delay := 200 * time.millisecond
|
|
timeout := 20 * time.millisecond
|
|
payload := 'late udp packet'
|
|
done := chan bool{cap: 1}
|
|
|
|
spawn udp_write_after_delay(addr, delay, payload, done)
|
|
listener.set_read_timeout(timeout)
|
|
|
|
mut buf := []u8{len: payload.len}
|
|
if _, _ := listener.read(mut buf) {
|
|
assert false, 'expected udp read timeout before delayed packet arrived'
|
|
} else {
|
|
assert err.code() == net.err_timed_out_code
|
|
}
|
|
|
|
_ = <-done
|
|
listener.set_read_timeout(time.second)
|
|
read, _ := listener.read(mut buf)!
|
|
assert read == payload.len
|
|
assert buf[..read].bytestr() == payload
|
|
}
|
|
|
|
fn test_udp_multicast_ipv4_socket_options() ! {
|
|
mut listener := net.listen_udp('0.0.0.0:0')!
|
|
defer {
|
|
listener.close() or {}
|
|
}
|
|
|
|
listener.join_multicast_group('224.0.0.1', '0.0.0.0')!
|
|
listener.leave_multicast_group('224.0.0.1', '0.0.0.0')!
|
|
listener.set_multicast_ttl(2)!
|
|
listener.set_multicast_loop(true)!
|
|
listener.set_multicast_loop(false)!
|
|
listener.set_multicast_interface('0.0.0.0')!
|
|
}
|
|
|
|
fn test_udp_multicast_validates_inputs() ! {
|
|
mut listener := net.listen_udp('0.0.0.0:0')!
|
|
defer {
|
|
listener.close() or {}
|
|
}
|
|
|
|
mut ttl_failed := false
|
|
listener.set_multicast_ttl(-1) or {
|
|
ttl_failed = true
|
|
assert err.msg().contains('multicast ttl')
|
|
}
|
|
assert ttl_failed
|
|
|
|
mut non_multicast_failed := false
|
|
listener.join_multicast_group('127.0.0.1', '') or {
|
|
non_multicast_failed = true
|
|
assert err.msg().contains('not an ipv4 multicast address')
|
|
}
|
|
assert non_multicast_failed
|
|
|
|
mut iface_failed := false
|
|
listener.set_multicast_interface('not-an-ip') or {
|
|
iface_failed = true
|
|
assert err.msg().contains('ipv4 multicast interface')
|
|
}
|
|
assert iface_failed
|
|
}
|