1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

net: add a net.dial_tcp_with_bind/2 function (#15055) (#15056)

This commit is contained in:
shove 2022-07-15 17:38:17 +08:00 committed by GitHub
parent 4f997feee7
commit b4ed5d5f20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 0 deletions

View File

@ -45,6 +45,37 @@ pub fn dial_tcp(address string) ?&TcpConn {
return error('dial_tcp failed for address $address')
}
// bind local address and dail.
pub fn dial_tcp_with_bind(saddr string, laddr string) ?&TcpConn {
addrs := resolve_addrs_fuzzy(saddr, .tcp) or {
return error('$err.msg(); could not resolve address $saddr in dial_tcp_with_bind')
}
// Very simple dialer
for addr in addrs {
mut s := new_tcp_socket(addr.family()) or {
return error('$err.msg(); could not create new tcp socket in dial_tcp_with_bind')
}
s.bind(laddr) or {
s.close() or { continue }
continue
}
s.connect(addr) or {
// Connection failed
s.close() or { continue }
continue
}
return &TcpConn{
sock: s
read_timeout: net.tcp_default_read_timeout
write_timeout: net.tcp_default_write_timeout
}
}
// failed
return error('dial_tcp_with_bind failed for address $saddr')
}
pub fn (mut c TcpConn) close() ? {
$if trace_tcp ? {
eprintln(' TcpConn.close | c.sock.handle: ${c.sock.handle:6}')
@ -366,6 +397,22 @@ pub fn (mut s TcpSocket) set_option_int(opt SocketOption, value int) ? {
socket_error(C.setsockopt(s.handle, C.SOL_SOCKET, int(opt), &value, sizeof(int)))?
}
// bind a local rddress for TcpSocket
pub fn (mut s TcpSocket) bind(addr string) ? {
addrs := resolve_addrs(addr, AddrFamily.ip, .tcp) or {
return error('$err.msg(); could not resolve address $addr')
}
// TODO(logic to pick here)
a := addrs[0]
// cast to the correct type
alen := a.len()
socket_error_message(C.bind(s.handle, voidptr(&a), alen), 'binding to $addr failed') or {
return err
}
}
fn (mut s TcpSocket) close() ? {
return shutdown(s.handle)
}

View File

@ -100,3 +100,11 @@ fn test_tcp_unix() {
fn testsuite_end() {
eprintln('\ndone')
}
fn test_bind() {
$if !network ? {
return
}
conn := net.dial_tcp_with_bind('vlang.io:80', '127.0.0.1:0')
conn.close()
}