mirror of
https://github.com/vlang/v.git
synced 2025-08-04 02:07:28 -04:00
net: add net.Dialer and net.Connection interfaces, abstracting the different types of connections, already supported by the V network stack (#21657)
This commit is contained in:
parent
49f5ebf717
commit
576a0abcc7
13
vlib/net/connection.v
Normal file
13
vlib/net/connection.v
Normal file
@ -0,0 +1,13 @@
|
||||
module net
|
||||
|
||||
// Connection provides a generic SOCK_STREAM style interface that protocols can use
|
||||
// as a base connection object to support TCP, UNIX Domain Sockets and various
|
||||
// proxying solutions.
|
||||
pub interface Connection {
|
||||
addr() !Addr
|
||||
peer_addr() !Addr
|
||||
mut:
|
||||
read(mut []u8) !int
|
||||
write([]u8) !int
|
||||
close() !
|
||||
}
|
6
vlib/net/dialer.v
Normal file
6
vlib/net/dialer.v
Normal file
@ -0,0 +1,6 @@
|
||||
module net
|
||||
|
||||
// Dialer is an abstract dialer interface for producing connections to adresses.
|
||||
pub interface Dialer {
|
||||
dial(address string) !Connection
|
||||
}
|
@ -244,6 +244,11 @@ enum Select {
|
||||
except
|
||||
}
|
||||
|
||||
// close terminates the ssl connection and does cleanup
|
||||
pub fn (mut s SSLConn) close() ! {
|
||||
s.shutdown()!
|
||||
}
|
||||
|
||||
// shutdown terminates the ssl connection and does cleanup
|
||||
pub fn (mut s SSLConn) shutdown() ! {
|
||||
$if trace_ssl ? {
|
||||
@ -407,6 +412,11 @@ pub fn (mut s SSLConn) dial(hostname string, port int) ! {
|
||||
s.opened = true
|
||||
}
|
||||
|
||||
// addr retrieves the local ip address and port number for this connection
|
||||
pub fn (s &SSLConn) addr() !net.Addr {
|
||||
return net.addr_from_socket_handle(s.handle)
|
||||
}
|
||||
|
||||
// peer_addr retrieves the ip address and port number used by the peer
|
||||
pub fn (s &SSLConn) peer_addr() !net.Addr {
|
||||
return net.peer_addr_from_socket_handle(s.handle)
|
||||
|
@ -51,6 +51,11 @@ enum Select {
|
||||
except
|
||||
}
|
||||
|
||||
// close closes the ssl connection and does cleanup
|
||||
pub fn (mut s SSLConn) close() ! {
|
||||
s.shutdown()!
|
||||
}
|
||||
|
||||
// shutdown closes the ssl connection and does cleanup
|
||||
pub fn (mut s SSLConn) shutdown() ! {
|
||||
$if trace_ssl ? {
|
||||
@ -247,6 +252,11 @@ fn (mut s SSLConn) complete_connect() ! {
|
||||
}
|
||||
}
|
||||
|
||||
// addr retrieves the local ip address and port number for this connection
|
||||
pub fn (s &SSLConn) addr() !net.Addr {
|
||||
return net.addr_from_socket_handle(s.handle)
|
||||
}
|
||||
|
||||
// peer_addr retrieves the ip address and port number used by the peer
|
||||
pub fn (s &SSLConn) peer_addr() !net.Addr {
|
||||
return net.peer_addr_from_socket_handle(s.handle)
|
||||
|
@ -18,7 +18,9 @@ const auth_user_password = u8(2)
|
||||
// socks5_dial create new instance of &net.TcpConn
|
||||
pub fn socks5_dial(proxy_url string, host string, username string, password string) !&net.TcpConn {
|
||||
mut con := net.dial_tcp(proxy_url)!
|
||||
return handshake(mut con, host, username, password)!
|
||||
socks_conn_as_interface := handshake(mut con, host, username, password)!
|
||||
socks_conn := socks_conn_as_interface as net.TcpConn
|
||||
return &socks_conn
|
||||
}
|
||||
|
||||
// socks5_ssl_dial create new instance of &ssl.SSLConn
|
||||
@ -35,7 +37,35 @@ pub fn socks5_ssl_dial(proxy_url string, host string, username string, password
|
||||
return ssl_conn
|
||||
}
|
||||
|
||||
fn handshake(mut con net.TcpConn, host string, username string, password string) !&net.TcpConn {
|
||||
// SOCKS5Dialer implements the Dialer interface initiating connections through a SOCKS5 proxy.
|
||||
pub struct SOCKS5Dialer {
|
||||
pub:
|
||||
dialer net.Dialer
|
||||
proxy_address string
|
||||
username string
|
||||
password string
|
||||
}
|
||||
|
||||
// new_socks5_dialer creates a dialer that will use a SOCKS5 proxy server to
|
||||
// initiate connections. An underlying dialer is required to initiate the
|
||||
// connection to the proxy server. Most users should use either
|
||||
// net.default_tcp_dialer or ssl.create_ssl_dialer.
|
||||
pub fn new_socks5_dialer(base net.Dialer, proxy_address string, username string, password string) net.Dialer {
|
||||
return &SOCKS5Dialer{
|
||||
dialer: base
|
||||
proxy_address: proxy_address
|
||||
username: username
|
||||
password: password
|
||||
}
|
||||
}
|
||||
|
||||
// dial initiates a new connection through the SOCKS5 proxy.
|
||||
pub fn (sd SOCKS5Dialer) dial(address string) !net.Connection {
|
||||
mut conn := sd.dialer.dial(sd.proxy_address)!
|
||||
return handshake(mut conn, address, sd.username, sd.password)!
|
||||
}
|
||||
|
||||
fn handshake(mut con net.Connection, host string, username string, password string) !net.Connection {
|
||||
mut v := [socks.socks_version5, 1]
|
||||
if username.len > 0 {
|
||||
v << socks.auth_user_password
|
||||
|
22
vlib/net/ssl/dialer.v
Normal file
22
vlib/net/ssl/dialer.v
Normal file
@ -0,0 +1,22 @@
|
||||
module ssl
|
||||
|
||||
import net
|
||||
|
||||
// SSLDialer is a concrete instance of the Dialer interface,
|
||||
// for creating SSL socket connections.
|
||||
pub struct SSLDialer {
|
||||
config SSLConnectConfig
|
||||
}
|
||||
|
||||
// create_ssl_dialer creates a dialer that will initiate SSL secured
|
||||
// connections.
|
||||
pub fn new_ssl_dialer(config SSLConnectConfig) net.Dialer {
|
||||
return &SSLDialer{
|
||||
config: config
|
||||
}
|
||||
}
|
||||
|
||||
// dial initiates a new SSL connection.
|
||||
pub fn (d SSLDialer) dial(address string) !net.Connection {
|
||||
return new_ssl_conn(d.config)!
|
||||
}
|
@ -6,6 +6,21 @@ import strings
|
||||
pub const tcp_default_read_timeout = 30 * time.second
|
||||
pub const tcp_default_write_timeout = 30 * time.second
|
||||
|
||||
// TCPDialer is a concrete instance of the Dialer interface,
|
||||
// for creating tcp connections.
|
||||
pub struct TCPDialer {}
|
||||
|
||||
// dial will try to create a new abstract connection to the given address.
|
||||
// It will return an error, if that is not possible.
|
||||
pub fn (t TCPDialer) dial(address string) !Connection {
|
||||
return dial_tcp(address)!
|
||||
}
|
||||
|
||||
// default_tcp_dialer will give you an instance of Dialer, that is suitable for making new tcp connections.
|
||||
pub fn default_tcp_dialer() Dialer {
|
||||
return &TCPDialer{}
|
||||
}
|
||||
|
||||
@[heap]
|
||||
pub struct TcpConn {
|
||||
pub mut:
|
||||
@ -18,6 +33,7 @@ pub mut:
|
||||
is_blocking bool = true
|
||||
}
|
||||
|
||||
// dial_tcp will try to create a new TcpConn to the given address.
|
||||
pub fn dial_tcp(oaddress string) !&TcpConn {
|
||||
mut address := oaddress
|
||||
$if windows {
|
||||
@ -75,7 +91,7 @@ pub fn dial_tcp(oaddress string) !&TcpConn {
|
||||
return error(err_builder.str())
|
||||
}
|
||||
|
||||
// bind local address and dial.
|
||||
// dial_tcp_with_bind will bind the given local address `laddr` and dial.
|
||||
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')
|
||||
@ -111,6 +127,7 @@ pub fn dial_tcp_with_bind(saddr string, laddr string) !&TcpConn {
|
||||
return error('dial_tcp_with_bind failed for address ${saddr}')
|
||||
}
|
||||
|
||||
// close closes the tcp connection
|
||||
pub fn (mut c TcpConn) close() ! {
|
||||
$if trace_tcp ? {
|
||||
eprintln(' TcpConn.close | c.sock.handle: ${c.sock.handle:6}')
|
||||
@ -118,6 +135,8 @@ pub fn (mut c TcpConn) close() ! {
|
||||
c.sock.close()!
|
||||
}
|
||||
|
||||
// read_ptr reads data from the tcp connection to the given buffer. It reads at most `len` bytes.
|
||||
// It returns the number of actually read bytes, which can vary between 0 to `len`.
|
||||
pub fn (c TcpConn) read_ptr(buf_ptr &u8, len int) !int {
|
||||
mut should_ewouldblock := false
|
||||
mut res := $if is_coroutine ? {
|
||||
@ -175,6 +194,9 @@ pub fn (c TcpConn) read_ptr(buf_ptr &u8, len int) !int {
|
||||
return error('none')
|
||||
}
|
||||
|
||||
// read reads data from the tcp connection into the mutable buffer `buf`.
|
||||
// The number of bytes read is limited to the length of the buffer `buf.len`.
|
||||
// The returned value is the number of read bytes (between 0 and `buf.len`).
|
||||
pub fn (c TcpConn) read(mut buf []u8) !int {
|
||||
return c.read_ptr(buf.data, buf.len)!
|
||||
}
|
||||
|
@ -9,6 +9,16 @@ const unix_default_write_timeout = 30 * time.second
|
||||
const connect_timeout = 5 * time.second
|
||||
const msg_nosignal = 0x4000
|
||||
|
||||
// UnixDialer is a concrete instance of the Dialer interface,
|
||||
// for creating unix socket connections.
|
||||
pub struct UnixDialer {}
|
||||
|
||||
// dial will try to create a new abstract connection to the given address.
|
||||
// It will return an error, if that is not possible.
|
||||
pub fn (u UnixDialer) dial(address string) !net.Connection {
|
||||
return connect_stream(address)!
|
||||
}
|
||||
|
||||
@[heap]
|
||||
pub struct StreamConn {
|
||||
pub mut:
|
||||
@ -40,6 +50,16 @@ pub fn connect_stream(socket_path string) !&StreamConn {
|
||||
}
|
||||
}
|
||||
|
||||
// addr returns the local address of the stream
|
||||
pub fn (c StreamConn) addr() !net.Addr {
|
||||
return error('not implemented for unix connections')
|
||||
}
|
||||
|
||||
// peer_addr returns the address of the remote peer of the stream
|
||||
pub fn (c StreamConn) peer_addr() !net.Addr {
|
||||
return error('not implemented for unix connections')
|
||||
}
|
||||
|
||||
// close closes the connection
|
||||
pub fn (mut c StreamConn) close() ! {
|
||||
$if trace_unix ? {
|
||||
|
Loading…
x
Reference in New Issue
Block a user