From d92f5c55ba74f054f795e64e6047af611948b3b0 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 20 Jan 2021 12:11:01 +0200 Subject: [PATCH] net: use mut and refs as receivers consistently (#8205) --- vlib/net/ftp/ftp.v | 2 +- vlib/net/net_nix.c.v | 4 +- vlib/net/smtp/smtp.v | 89 +++++++++++++----------- vlib/net/smtp/smtp_test.v | 61 +++++++++++++--- vlib/net/tcp.v | 79 ++++++++++----------- vlib/net/tcp_read_line.v | 2 +- vlib/net/tcp_simple_client_server_test.v | 56 ++++++--------- vlib/net/tcp_test.v | 31 +++------ vlib/net/udp.v | 53 +++++++------- vlib/net/udp_test.v | 29 ++++---- vlib/vweb/tests/vweb_test.v | 2 +- vlib/vweb/vweb.v | 24 ++++--- vlib/x/websocket/io.v | 2 +- vlib/x/websocket/websocket_client.v | 3 +- vlib/x/websocket/websocket_server.v | 5 +- 15 files changed, 236 insertions(+), 206 deletions(-) diff --git a/vlib/net/ftp/ftp.v b/vlib/net/ftp/ftp.v index 17346ce7a3..03f2f68fbe 100644 --- a/vlib/net/ftp/ftp.v +++ b/vlib/net/ftp/ftp.v @@ -55,7 +55,7 @@ fn (mut dtp DTP) read() ?[]byte { return data } -fn (dtp DTP) close() { +fn (mut dtp DTP) close() { dtp.conn.close() } diff --git a/vlib/net/net_nix.c.v b/vlib/net/net_nix.c.v index 8cc83c6fba..4230442b19 100644 --- a/vlib/net/net_nix.c.v +++ b/vlib/net/net_nix.c.v @@ -9,7 +9,7 @@ module net #include #include #include - +#flag solaris -lsocket fn error_code() int { return C.errno } @@ -24,5 +24,3 @@ pub const ( const ( error_ewouldblock = C.EWOULDBLOCK ) - -#flag solaris -lsocket diff --git a/vlib/net/smtp/smtp.v b/vlib/net/smtp/smtp.v index c918d12b17..5e65085594 100644 --- a/vlib/net/smtp/smtp.v +++ b/vlib/net/smtp/smtp.v @@ -12,14 +12,14 @@ import time import io const ( - recv_size = 128 + recv_size = 128 ) enum ReplyCode { - ready = 220 - close = 221 - auth_ok = 235 - action_ok = 250 + ready = 220 + close = 221 + auth_ok = 235 + action_ok = 250 mail_start = 354 } @@ -39,7 +39,7 @@ pub: password string from string pub mut: - is_open bool + is_open bool } pub struct Mail { @@ -54,15 +54,19 @@ pub struct Mail { } // new_client returns a new SMTP client and connects to it -pub fn new_client(config Client) ?Client { - mut c := config - c.reconnect()? +pub fn new_client(config Client) ?&Client { + mut c := &Client{ + ...config + } + c.reconnect() ? return c } // reconnect reconnects to the SMTP server if the connection was closed pub fn (mut c Client) reconnect() ? { - if c.is_open { return error('Already connected to server') } + if c.is_open { + return error('Already connected to server') + } conn := net.dial_tcp('$c.server:$c.port') or { return error('Connecting to server failed') } c.conn = conn @@ -76,29 +80,34 @@ pub fn (mut c Client) reconnect() ? { } // send sends an email -pub fn (c Client) send(config Mail) ? { - if !c.is_open { return error('Disconnected from server') } +pub fn (mut c Client) send(config Mail) ? { + if !c.is_open { + return error('Disconnected from server') + } from := if config.from != '' { config.from } else { c.from } c.send_mailfrom(from) or { return error('Sending mailfrom failed') } c.send_mailto(config.to) or { return error('Sending mailto failed') } c.send_data() or { return error('Sending mail data failed') } - c.send_body({ config | from: from }) or { return error('Sending mail body failed') } + c.send_body({ + config | + from: from + }) or { return error('Sending mail body failed') } } // quit closes the connection to the server pub fn (mut c Client) quit() ? { c.send_str('QUIT\r\n') c.expect_reply(.close) - c.conn.close()? + c.conn.close() ? c.is_open = false } // expect_reply checks if the SMTP server replied with the expected reply code -fn (c Client) expect_reply(expected ReplyCode) ? { - bytes := io.read_all(reader: c.conn)? +fn (mut c Client) expect_reply(expected ReplyCode) ? { + bytes := io.read_all(reader: c.conn) ? str := bytes.bytestr().trim_space() - $if smtp_debug? { + $if smtp_debug ? { eprintln('\n\n[RECV]') eprint(str) } @@ -108,30 +117,32 @@ fn (c Client) expect_reply(expected ReplyCode) ? { if ReplyCode(status) != expected { return error('Received unexpected status code $status, expecting $expected') } - } else { return error('Recieved unexpected SMTP data: $str') } + } else { + return error('Recieved unexpected SMTP data: $str') + } } [inline] -fn (c Client) send_str(s string) ? { - $if smtp_debug? { +fn (mut c Client) send_str(s string) ? { + $if smtp_debug ? { eprintln('\n\n[SEND START]') eprint(s.trim_space()) eprintln('\n[SEND END]') } - c.conn.write(s.bytes())? + c.conn.write(s.bytes()) ? } [inline] -fn (c Client) send_ehlo() ? { - c.send_str('EHLO $c.server\r\n')? - c.expect_reply(.action_ok)? +fn (mut c Client) send_ehlo() ? { + c.send_str('EHLO $c.server\r\n') ? + c.expect_reply(.action_ok) ? } [inline] -fn (c Client) send_auth() ? { +fn (mut c Client) send_auth() ? { if c.username.len == 0 { return - } + } mut sb := strings.new_builder(100) sb.write_b(0) sb.write(c.username) @@ -139,26 +150,26 @@ fn (c Client) send_auth() ? { sb.write(c.password) a := sb.str() auth := 'AUTH PLAIN ${base64.encode(a)}\r\n' - c.send_str(auth)? - c.expect_reply(.auth_ok)? + c.send_str(auth) ? + c.expect_reply(.auth_ok) ? } -fn (c Client) send_mailfrom(from string) ? { - c.send_str('MAIL FROM: <$from>\r\n')? - c.expect_reply(.action_ok)? +fn (mut c Client) send_mailfrom(from string) ? { + c.send_str('MAIL FROM: <$from>\r\n') ? + c.expect_reply(.action_ok) ? } -fn (c Client) send_mailto(to string) ? { - c.send_str('RCPT TO: <$to>\r\n')? - c.expect_reply(.action_ok)? +fn (mut c Client) send_mailto(to string) ? { + c.send_str('RCPT TO: <$to>\r\n') ? + c.expect_reply(.action_ok) ? } -fn (c Client) send_data() ? { - c.send_str('DATA\r\n')? +fn (mut c Client) send_data() ? { + c.send_str('DATA\r\n') ? c.expect_reply(.mail_start) } -fn (c Client) send_body(cfg Mail) ? { +fn (mut c Client) send_body(cfg Mail) ? { is_html := cfg.body_type == .html date := cfg.date.utc_string().trim_right(' UTC') // TODO mut sb := strings.new_builder(200) @@ -174,6 +185,6 @@ fn (c Client) send_body(cfg Mail) ? { sb.write('\r\n\r\n') sb.write(cfg.body) sb.write('\r\n.\r\n') - c.send_str(sb.str())? - c.expect_reply(.action_ok)? + c.send_str(sb.str()) ? + c.expect_reply(.action_ok) ? } diff --git a/vlib/net/smtp/smtp_test.v b/vlib/net/smtp/smtp_test.v index 0cb8f8a01f..769dd9441c 100644 --- a/vlib/net/smtp/smtp_test.v +++ b/vlib/net/smtp/smtp_test.v @@ -3,7 +3,7 @@ import smtp import time // Used to test that a function call returns an error -fn fn_errors(c smtp.Client, m smtp.Mail) bool { +fn fn_errors(mut c smtp.Client, m smtp.Mail) bool { c.send(m) or { return true } return false } @@ -14,7 +14,9 @@ fn fn_errors(c smtp.Client, m smtp.Mail) bool { * Created by: nedimf (07/2020) */ fn test_smtp() { - $if !network ? { return } + $if !network ? { + return + } client_cfg := smtp.Client{ server: 'smtp.mailtrap.io' @@ -32,20 +34,57 @@ fn test_smtp() { body: 'Plain text' } - mut client := smtp.new_client(client_cfg) or { assert false return } + mut client := smtp.new_client(client_cfg) or { + assert false + return + } assert true - client.send(send_cfg) or { assert false return } + client.send(send_cfg) or { + assert false + return + } assert true // client.send({ send_cfg | body_type: .html, body: '

HTML V email!

' }) or { assert false return } - client.send({ send_cfg | from: 'alexander@vlang.io' }) or { assert false return } - client.send({ send_cfg | cc: 'alexander@vlang.io,joe@vlang.io', bcc: 'spytheman@vlang.io' }) or { assert false return } - client.send({ send_cfg | date: time.now().add_days(1000) }) or { assert false return } + client.send({ + send_cfg | + from: 'alexander@vlang.io' + }) or { + assert false + return + } + client.send({ + send_cfg | + cc: 'alexander@vlang.io,joe@vlang.io' + bcc: 'spytheman@vlang.io' + }) or { + assert false + return + } + client.send({ + send_cfg | + date: time.now().add_days(1000) + }) or { + assert false + return + } assert true - client.quit() or { assert false return } + client.quit() or { + assert false + return + } assert true // This call should return an error, since the connection is closed - if !fn_errors(client, send_cfg) { assert false return } - client.reconnect() or { assert false return } - client.send(send_cfg) or { assert false return } + if !fn_errors(mut client, send_cfg) { + assert false + return + } + client.reconnect() or { + assert false + return + } + client.send(send_cfg) or { + assert false + return + } assert true } diff --git a/vlib/net/tcp.v b/vlib/net/tcp.v index 9bb111def2..bf515fc387 100644 --- a/vlib/net/tcp.v +++ b/vlib/net/tcp.v @@ -8,8 +8,8 @@ const ( ) pub struct TcpConn { -pub: - sock TcpSocket +pub mut: + sock TcpSocket mut: write_deadline time.Time read_deadline time.Time @@ -17,23 +17,23 @@ mut: write_timeout time.Duration } -pub fn dial_tcp(address string) ?TcpConn { - s := new_tcp_socket() ? +pub fn dial_tcp(address string) ?&TcpConn { + mut s := new_tcp_socket() ? s.connect(address) ? - return TcpConn{ + return &TcpConn{ sock: s read_timeout: tcp_default_read_timeout write_timeout: tcp_default_write_timeout } } -pub fn (c TcpConn) close() ? { +pub fn (mut c TcpConn) close() ? { c.sock.close() ? return none } // write_ptr blocks and attempts to write all data -pub fn (c TcpConn) write_ptr(b byteptr, len int) ? { +pub fn (mut c TcpConn) write_ptr(b byteptr, len int) ? { $if trace_tcp ? { eprintln('>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' + unsafe { b.vstring_with_len(len) }) @@ -61,16 +61,16 @@ pub fn (c TcpConn) write_ptr(b byteptr, len int) ? { } // write blocks and attempts to write all data -pub fn (c TcpConn) write(bytes []byte) ? { +pub fn (mut c TcpConn) write(bytes []byte) ? { return c.write_ptr(bytes.data, bytes.len) } // write_str blocks and attempts to write all data -pub fn (c TcpConn) write_str(s string) ? { +pub fn (mut c TcpConn) write_str(s string) ? { return c.write_ptr(s.str, s.len) } -pub fn (c TcpConn) read_ptr(buf_ptr byteptr, len int) ?int { +pub fn (mut c TcpConn) read_ptr(buf_ptr byteptr, len int) ?int { mut res := wrap_read_result(C.recv(c.sock.handle, buf_ptr, len, 0)) ? $if trace_tcp ? { eprintln('<<< TcpConn.read_ptr | c.sock.handle: $c.sock.handle | buf_ptr: ${ptr_str(buf_ptr)} len: $len | res: $res') @@ -92,11 +92,11 @@ pub fn (c TcpConn) read_ptr(buf_ptr byteptr, len int) ?int { return none } -pub fn (c TcpConn) read(mut buf []byte) ?int { +pub fn (mut c TcpConn) read(mut buf []byte) ?int { return c.read_ptr(buf.data, buf.len) } -pub fn (c TcpConn) read_deadline() ?time.Time { +pub fn (mut c TcpConn) read_deadline() ?time.Time { if c.read_deadline.unix == 0 { return c.read_deadline } @@ -107,7 +107,7 @@ pub fn (mut c TcpConn) set_read_deadline(deadline time.Time) { c.read_deadline = deadline } -pub fn (c TcpConn) write_deadline() ?time.Time { +pub fn (mut c TcpConn) write_deadline() ?time.Time { if c.write_deadline.unix == 0 { return c.write_deadline } @@ -118,7 +118,7 @@ pub fn (mut c TcpConn) set_write_deadline(deadline time.Time) { c.write_deadline = deadline } -pub fn (c TcpConn) read_timeout() time.Duration { +pub fn (c &TcpConn) read_timeout() time.Duration { return c.read_timeout } @@ -126,7 +126,7 @@ pub fn (mut c TcpConn) set_read_timeout(t time.Duration) { c.read_timeout = t } -pub fn (c TcpConn) write_timeout() time.Duration { +pub fn (c &TcpConn) write_timeout() time.Duration { return c.write_timeout } @@ -135,23 +135,23 @@ pub fn (mut c TcpConn) set_write_timeout(t time.Duration) { } [inline] -pub fn (c TcpConn) wait_for_read() ? { +pub fn (mut c TcpConn) wait_for_read() ? { return wait_for_read(c.sock.handle, c.read_deadline, c.read_timeout) } [inline] -pub fn (c TcpConn) wait_for_write() ? { +pub fn (mut c TcpConn) wait_for_write() ? { return wait_for_write(c.sock.handle, c.write_deadline, c.write_timeout) } -pub fn (c TcpConn) peer_addr() ?Addr { +pub fn (c &TcpConn) peer_addr() ?Addr { mut addr := C.sockaddr{} len := sizeof(C.sockaddr) socket_error(C.getpeername(c.sock.handle, &addr, &len)) ? return new_addr(addr) } -pub fn (c TcpConn) peer_ip() ?string { +pub fn (c &TcpConn) peer_ip() ?string { buf := [44]byte{} peeraddr := C.sockaddr_in{} speeraddr := sizeof(peeraddr) @@ -164,19 +164,20 @@ pub fn (c TcpConn) peer_ip() ?string { return res } -pub fn (c TcpConn) str() string { +pub fn (c &TcpConn) str() string { // TODO - return 'TcpConn' + return 'TcpConn {write_deadline: $c.write_deadline, read_deadline: $c.read_deadline, read_timeout: $c.read_timeout, write_timeout: $c.write_timeout, sock: $c.sock}' } pub struct TcpListener { - sock TcpSocket +pub mut: + sock TcpSocket mut: accept_timeout time.Duration accept_deadline time.Time } -pub fn listen_tcp(port int) ?TcpListener { +pub fn listen_tcp(port int) ?&TcpListener { s := new_tcp_socket() ? validate_port(port) ? mut addr := C.sockaddr_in{} @@ -188,14 +189,14 @@ pub fn listen_tcp(port int) ?TcpListener { sockaddr := unsafe { &C.sockaddr(&addr) } socket_error(C.bind(s.handle, sockaddr, size)) ? socket_error(C.listen(s.handle, 128)) ? - return TcpListener{ + return &TcpListener{ sock: s accept_deadline: no_deadline accept_timeout: infinite_timeout } } -pub fn (l TcpListener) accept() ?TcpConn { +pub fn (mut l TcpListener) accept() ?&TcpConn { addr := C.sockaddr_storage{} unsafe { C.memset(&addr, 0, sizeof(C.sockaddr_storage)) } size := sizeof(C.sockaddr_storage) @@ -210,14 +211,14 @@ pub fn (l TcpListener) accept() ?TcpConn { } } new_sock := tcp_socket_from_handle(new_handle) ? - return TcpConn{ + return &TcpConn{ sock: new_sock read_timeout: tcp_default_read_timeout write_timeout: tcp_default_write_timeout } } -pub fn (c TcpListener) accept_deadline() ?time.Time { +pub fn (c &TcpListener) accept_deadline() ?time.Time { if c.accept_deadline.unix != 0 { return c.accept_deadline } @@ -228,7 +229,7 @@ pub fn (mut c TcpListener) set_accept_deadline(deadline time.Time) { c.accept_deadline = deadline } -pub fn (c TcpListener) accept_timeout() time.Duration { +pub fn (c &TcpListener) accept_timeout() time.Duration { return c.accept_timeout } @@ -236,16 +237,16 @@ pub fn (mut c TcpListener) set_accept_timeout(t time.Duration) { c.accept_timeout = t } -pub fn (c TcpListener) wait_for_accept() ? { +pub fn (mut c TcpListener) wait_for_accept() ? { return wait_for_read(c.sock.handle, c.accept_deadline, c.accept_timeout) } -pub fn (c TcpListener) close() ? { +pub fn (mut c TcpListener) close() ? { c.sock.close() ? return none } -pub fn (c TcpListener) address() ?Addr { +pub fn (c &TcpListener) address() ?Addr { return c.sock.address() } @@ -256,7 +257,7 @@ pub: fn new_tcp_socket() ?TcpSocket { sockfd := socket_error(C.socket(SocketFamily.inet, SocketType.tcp, 0)) ? - s := TcpSocket{ + mut s := TcpSocket{ handle: sockfd } // s.set_option_bool(.reuse_addr, true)? @@ -271,7 +272,7 @@ fn new_tcp_socket() ?TcpSocket { } fn tcp_socket_from_handle(sockfd int) ?TcpSocket { - s := TcpSocket{ + mut s := TcpSocket{ handle: sockfd } // s.set_option_bool(.reuse_addr, true)? @@ -285,7 +286,7 @@ fn tcp_socket_from_handle(sockfd int) ?TcpSocket { return s } -pub fn (s TcpSocket) set_option_bool(opt SocketOption, value bool) ? { +pub fn (mut s TcpSocket) set_option_bool(opt SocketOption, value bool) ? { // TODO reenable when this `in` operation works again // if opt !in opts_can_set { // return err_option_not_settable @@ -297,16 +298,16 @@ pub fn (s TcpSocket) set_option_bool(opt SocketOption, value bool) ? { return none } -pub fn (s TcpSocket) set_option_int(opt SocketOption, value int) ? { +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))) ? return none } -fn (s TcpSocket) close() ? { +fn (mut s TcpSocket) close() ? { return shutdown(s.handle) } -fn (s TcpSocket) @select(test Select, timeout time.Duration) ?bool { +fn (mut s TcpSocket) @select(test Select, timeout time.Duration) ?bool { return @select(s.handle, test, timeout) } @@ -314,7 +315,7 @@ const ( connect_timeout = 5 * time.second ) -fn (s TcpSocket) connect(a string) ? { +fn (mut s TcpSocket) connect(a string) ? { addr := resolve_addr(a, .inet, .tcp) ? res := C.connect(s.handle, &addr.addr, addr.len) if res == 0 { @@ -335,7 +336,7 @@ fn (s TcpSocket) connect(a string) ? { } // address gets the address of a socket -pub fn (s TcpSocket) address() ?Addr { +pub fn (s &TcpSocket) address() ?Addr { mut addr := C.sockaddr_in{} size := sizeof(C.sockaddr_in) // cast to the correct type diff --git a/vlib/net/tcp_read_line.v b/vlib/net/tcp_read_line.v index 07024c58b0..cd78953e50 100644 --- a/vlib/net/tcp_read_line.v +++ b/vlib/net/tcp_read_line.v @@ -10,7 +10,7 @@ const ( // It will *always* return a line, ending with CRLF, or just '', on EOF. // NB: if you want more control over the buffer, please use a buffered IO // reader instead: `io.new_buffered_reader({reader: io.make_reader(con)})` -pub fn (con TcpConn) read_line() string { +pub fn (mut con TcpConn) read_line() string { mut buf := [max_read]byte{} // where C.recv will store the network data mut res := '' // The final result, including the ending \n. for { diff --git a/vlib/net/tcp_simple_client_server_test.v b/vlib/net/tcp_simple_client_server_test.v index 56394be9c6..51e572c1db 100644 --- a/vlib/net/tcp_simple_client_server_test.v +++ b/vlib/net/tcp_simple_client_server_test.v @@ -6,36 +6,28 @@ const ( server_port = 22334 ) -fn setup() (net.TcpListener, net.TcpConn, net.TcpConn) { - server := net.listen_tcp(server_port) or { - panic(err) - } - mut client := net.dial_tcp('127.0.0.1:$server_port') or { - panic(err) - } - mut socket := server.accept() or { - panic(err) - } +fn setup() (&net.TcpListener, &net.TcpConn, &net.TcpConn) { + mut server := net.listen_tcp(server_port) or { panic(err) } + mut client := net.dial_tcp('127.0.0.1:$server_port') or { panic(err) } + mut socket := server.accept() or { panic(err) } $if debug_peer_ip ? { - ip := con.peer_ip() or { - '$err' - } + ip := con.peer_ip() or { '$err' } eprintln('connection peer_ip: $ip') } assert true return server, client, socket } -fn cleanup(server &net.TcpListener, client &net.TcpConn, socket &net.TcpConn) { +fn cleanup(mut server net.TcpListener, mut client net.TcpConn, mut socket net.TcpConn) { server.close() or { } client.close() or { } socket.close() or { } } fn test_socket() { - server, client, socket := setup() + mut server, mut client, mut socket := setup() defer { - cleanup(server, client, socket) + cleanup(mut server, mut client, mut socket) } message := 'Hello World' socket.write_str(message) or { @@ -65,14 +57,12 @@ fn test_socket() { } fn test_socket_write_and_read() { - server, client, socket := setup() + mut server, mut client, mut socket := setup() defer { - cleanup(server, client, socket) + cleanup(mut server, mut client, mut socket) } message1 := 'a message 1' - socket.write_str(message1) or { - assert false - } + socket.write_str(message1) or { assert false } mut rbuf := []byte{len: message1.len} client.read(mut rbuf) line := rbuf.bytestr() @@ -80,18 +70,16 @@ fn test_socket_write_and_read() { } fn test_socket_read_line() { - server, client, socket := setup() - mut reader := io.new_buffered_reader({ + mut server, mut client, mut socket := setup() + mut reader := io.new_buffered_reader( reader: io.make_reader(client) - }) + ) defer { - cleanup(server, client, socket) + cleanup(mut server, mut client, mut socket) } message1, message2 := 'message1', 'message2' message := '$message1\n$message2\n' - socket.write_str(message) or { - assert false - } + socket.write_str(message) or { assert false } assert true // line1 := reader.read_line() or { @@ -109,9 +97,9 @@ fn test_socket_read_line() { } fn test_socket_write_fail_without_panic() { - server, client, socket := setup() + mut server, mut client, mut socket := setup() defer { - cleanup(server, client, socket) + cleanup(mut server, mut client, mut socket) } message2 := 'a message 2' // ensure that socket.write (i.e. done on the server side) @@ -131,12 +119,12 @@ fn test_socket_write_fail_without_panic() { } fn test_socket_read_line_long_line_without_eol() { - server, client, socket := setup() - mut reader := io.new_buffered_reader({ + mut server, mut client, mut socket := setup() + mut reader := io.new_buffered_reader( reader: io.make_reader(client) - }) + ) defer { - cleanup(server, client, socket) + cleanup(mut server, mut client, mut socket) } message := strings.repeat_string('123', 400) socket.write_str(message) diff --git a/vlib/net/tcp_test.v b/vlib/net/tcp_test.v index 3c5f5163f2..557300c73d 100644 --- a/vlib/net/tcp_test.v +++ b/vlib/net/tcp_test.v @@ -4,8 +4,7 @@ const ( test_port = 45123 ) -fn handle_conn(_c net.TcpConn) { - mut c := _c +fn handle_conn(mut c net.TcpConn) { for { mut buf := []byte{len: 100, init: 0} read := c.read(mut buf) or { @@ -19,25 +18,23 @@ fn handle_conn(_c net.TcpConn) { } } -fn echo_server(l net.TcpListener) ? { +fn echo_server(mut l net.TcpListener) ? { for { - new_conn := l.accept() or { - continue - } - go handle_conn(new_conn) + mut new_conn := l.accept() or { continue } + go handle_conn(mut new_conn) } return none } fn echo() ? { - mut c := net.dial_tcp('127.0.0.1:$test_port')? + mut c := net.dial_tcp('127.0.0.1:$test_port') ? defer { c.close() or { } } data := 'Hello from vlib/net!' - c.write_str(data)? + c.write_str(data) ? mut buf := []byte{len: 4096} - read := c.read(mut buf)? + read := c.read(mut buf) ? assert read == data.len for i := 0; i < read; i++ { assert buf[i] == data[i] @@ -47,16 +44,8 @@ fn echo() ? { } fn test_tcp() { - l := net.listen_tcp(test_port) or { - panic(err) - } - go echo_server(l) - echo() or { - panic(err) - } + mut l := net.listen_tcp(test_port) or { panic(err) } + go echo_server(mut l) + echo() or { panic(err) } l.close() or { } } - -fn main() { - test_tcp() -} diff --git a/vlib/net/udp.v b/vlib/net/udp.v index 2d65c73e5d..a823c3670f 100644 --- a/vlib/net/udp.v +++ b/vlib/net/udp.v @@ -8,7 +8,8 @@ const ( ) pub struct UdpConn { - sock UdpSocket +pub mut: + sock UdpSocket mut: write_deadline time.Time read_deadline time.Time @@ -16,7 +17,7 @@ mut: write_timeout time.Duration } -pub fn dial_udp(laddr string, raddr string) ?UdpConn { +pub fn dial_udp(laddr string, raddr string) ?&UdpConn { // Dont have to do this when its fixed // this just allows us to store this `none` optional in a struct resolve_wrapper := fn (raddr string) ?Addr { @@ -30,27 +31,27 @@ pub fn dial_udp(laddr string, raddr string) ?UdpConn { l: local r: resolve_wrapper(raddr) } - return UdpConn{ + return &UdpConn{ sock: sock read_timeout: udp_default_read_timeout write_timeout: udp_default_write_timeout } } -pub fn (c UdpConn) write_ptr(b byteptr, len int) ? { +pub fn (mut c UdpConn) write_ptr(b byteptr, len int) ? { remote := c.sock.remote() or { return err_no_udp_remote } return c.write_to_ptr(remote, b, len) } -pub fn (c UdpConn) write(buf []byte) ? { +pub fn (mut c UdpConn) write(buf []byte) ? { return c.write_ptr(buf.data, buf.len) } -pub fn (c UdpConn) write_str(s string) ? { +pub fn (mut c UdpConn) write_str(s string) ? { return c.write_ptr(s.str, s.len) } -pub fn (c UdpConn) write_to_ptr(addr Addr, b byteptr, len int) ? { +pub fn (mut c UdpConn) write_to_ptr(addr Addr, b byteptr, len int) ? { res := C.sendto(c.sock.handle, b, len, 0, &addr.addr, addr.len) if res >= 0 { return none @@ -66,17 +67,17 @@ pub fn (c UdpConn) write_to_ptr(addr Addr, b byteptr, len int) ? { } // write_to blocks and writes the buf to the remote addr specified -pub fn (c UdpConn) write_to(addr Addr, buf []byte) ? { +pub fn (mut c UdpConn) write_to(addr Addr, buf []byte) ? { return c.write_to_ptr(addr, buf.data, buf.len) } // write_to_string blocks and writes the buf to the remote addr specified -pub fn (c UdpConn) write_to_string(addr Addr, s string) ? { +pub fn (mut c UdpConn) write_to_string(addr Addr, s string) ? { return c.write_to_ptr(addr, s.str, s.len) } // read reads from the socket into buf up to buf.len returning the number of bytes read -pub fn (c UdpConn) read(mut buf []byte) ?(int, Addr) { +pub fn (mut c UdpConn) read(mut buf []byte) ?(int, Addr) { mut addr_from := C.sockaddr{} len := sizeof(C.sockaddr) mut res := wrap_read_result(C.recvfrom(c.sock.handle, buf.data, buf.len, 0, &addr_from, @@ -100,7 +101,7 @@ pub fn (c UdpConn) read(mut buf []byte) ?(int, Addr) { return none } -pub fn (c UdpConn) read_deadline() ?time.Time { +pub fn (c &UdpConn) read_deadline() ?time.Time { if c.read_deadline.unix == 0 { return c.read_deadline } @@ -111,7 +112,7 @@ pub fn (mut c UdpConn) set_read_deadline(deadline time.Time) { c.read_deadline = deadline } -pub fn (c UdpConn) write_deadline() ?time.Time { +pub fn (c &UdpConn) write_deadline() ?time.Time { if c.write_deadline.unix == 0 { return c.write_deadline } @@ -122,7 +123,7 @@ pub fn (mut c UdpConn) set_write_deadline(deadline time.Time) { c.write_deadline = deadline } -pub fn (c UdpConn) read_timeout() time.Duration { +pub fn (c &UdpConn) read_timeout() time.Duration { return c.read_timeout } @@ -130,7 +131,7 @@ pub fn (mut c UdpConn) set_read_timeout(t time.Duration) { c.read_timeout = t } -pub fn (c UdpConn) write_timeout() time.Duration { +pub fn (c &UdpConn) write_timeout() time.Duration { return c.write_timeout } @@ -139,27 +140,27 @@ pub fn (mut c UdpConn) set_write_timeout(t time.Duration) { } [inline] -pub fn (c UdpConn) wait_for_read() ? { +pub fn (mut c UdpConn) wait_for_read() ? { return wait_for_read(c.sock.handle, c.read_deadline, c.read_timeout) } [inline] -pub fn (c UdpConn) wait_for_write() ? { +pub fn (mut c UdpConn) wait_for_write() ? { return wait_for_write(c.sock.handle, c.write_deadline, c.write_timeout) } -pub fn (c UdpConn) str() string { +pub fn (c &UdpConn) str() string { // TODO return 'UdpConn' } -pub fn (c UdpConn) close() ? { +pub fn (mut c UdpConn) close() ? { return c.sock.close() } -pub fn listen_udp(port int) ?UdpConn { +pub fn listen_udp(port int) ?&UdpConn { s := new_udp_socket(port) ? - return UdpConn{ + return &UdpConn{ sock: s read_timeout: udp_default_read_timeout write_timeout: udp_default_write_timeout @@ -172,9 +173,9 @@ struct UdpSocket { r ?Addr } -fn new_udp_socket(local_port int) ?UdpSocket { +fn new_udp_socket(local_port int) ?&UdpSocket { sockfd := socket_error(C.socket(SocketFamily.inet, SocketType.udp, 0)) ? - s := UdpSocket{ + mut s := &UdpSocket{ handle: sockfd } s.set_option_bool(.reuse_addr, true) ? @@ -197,11 +198,11 @@ fn new_udp_socket(local_port int) ?UdpSocket { return s } -pub fn (s UdpSocket) remote() ?Addr { +pub fn (s &UdpSocket) remote() ?Addr { return s.r } -pub fn (s UdpSocket) set_option_bool(opt SocketOption, value bool) ? { +pub fn (mut s UdpSocket) set_option_bool(opt SocketOption, value bool) ? { // TODO reenable when this `in` operation works again // if opt !in opts_can_set { // return err_option_not_settable @@ -213,10 +214,10 @@ pub fn (s UdpSocket) set_option_bool(opt SocketOption, value bool) ? { return none } -fn (s UdpSocket) close() ? { +fn (mut s UdpSocket) close() ? { return shutdown(s.handle) } -fn (s UdpSocket) @select(test Select, timeout time.Duration) ?bool { +fn (mut s UdpSocket) @select(test Select, timeout time.Duration) ?bool { return @select(s.handle, test, timeout) } diff --git a/vlib/net/udp_test.v b/vlib/net/udp_test.v index adc8be9ef6..100cf3d6c7 100644 --- a/vlib/net/udp_test.v +++ b/vlib/net/udp_test.v @@ -1,12 +1,9 @@ import net -fn echo_server(_c net.UdpConn) { - mut c := _c +fn echo_server(mut c net.UdpConn) { for { - mut buf := []byte{ len: 100, init: 0 } - read, addr := c.read(mut buf) or { - continue - } + mut buf := []byte{len: 100, init: 0} + read, addr := c.read(mut buf) or { continue } c.write_to(addr, buf[..read]) or { println('Server: connection dropped') @@ -16,14 +13,16 @@ fn echo_server(_c net.UdpConn) { } fn echo() ? { - mut c := net.dial_udp('127.0.0.1:40003', '127.0.0.1:40001')? - defer { c.close() or { } } + mut c := net.dial_udp('127.0.0.1:40003', '127.0.0.1:40001') ? + defer { + c.close() or { } + } data := 'Hello from vlib/net!' - c.write_str(data)? + c.write_str(data) ? - mut buf := []byte{ len: 100, init: 0 } - read, addr := c.read(mut buf)? + mut buf := []byte{len: 100, init: 0} + read, addr := c.read(mut buf) ? assert read == data.len println('Got address $addr') @@ -35,21 +34,21 @@ fn echo() ? { assert buf[i] == data[i] } - println('Got "${buf.bytestr()}"') + println('Got "$buf.bytestr()"') - c.close()? + c.close() ? return none } fn test_udp() { - l := net.listen_udp(40001) or { + mut l := net.listen_udp(40001) or { println(err) assert false panic('') } - go echo_server(l) + go echo_server(mut l) echo() or { println(err) assert false diff --git a/vlib/vweb/tests/vweb_test.v b/vlib/vweb/tests/vweb_test.v index 595b3595da..13617f1e88 100644 --- a/vlib/vweb/tests/vweb_test.v +++ b/vlib/vweb/tests/vweb_test.v @@ -230,7 +230,7 @@ struct SimpleTcpClientConfig { } fn simple_tcp_client(config SimpleTcpClientConfig) ?string { - mut client := net.TcpConn{} + mut client := &net.TcpConn(0) mut tries := 0 for tries < config.retries { tries++ diff --git a/vlib/vweb/vweb.v b/vlib/vweb/vweb.v index 84f38eafc1..4877e5be48 100644 --- a/vlib/vweb/vweb.v +++ b/vlib/vweb/vweb.v @@ -44,10 +44,10 @@ mut: content_type string = 'text/plain' status string = '200 OK' pub: - req http.Request - conn net.TcpConn + req http.Request // TODO Response pub mut: + conn &net.TcpConn static_files map[string]string static_mime_types map[string]string form map[string]string @@ -123,7 +123,7 @@ pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bo defer { s.free() } - send_string(ctx.conn, s) or { return false } + send_string(mut ctx.conn, s) or { return false } return true } @@ -152,7 +152,7 @@ pub fn (mut ctx Context) redirect(url string) Result { return Result{} } ctx.done = true - send_string(ctx.conn, 'HTTP/1.1 302 Found\r\nLocation: $url$ctx.headers\r\n$headers_close') or { + send_string(mut ctx.conn, 'HTTP/1.1 302 Found\r\nLocation: $url$ctx.headers\r\n$headers_close') or { return Result{} } return Result{} @@ -163,7 +163,7 @@ pub fn (mut ctx Context) not_found() Result { return Result{} } ctx.done = true - send_string(ctx.conn, http_404) or { } + send_string(mut ctx.conn, http_404) or { } return Result{} } @@ -242,8 +242,10 @@ pub fn run(port int) { pub fn run_app(mut app T, port int) { println('Running a Vweb app on http://localhost:$port') - l := net.listen_tcp(port) or { panic('failed to listen') } - app.Context = Context{} + mut l := net.listen_tcp(port) or { panic('failed to listen') } + app.Context = Context{ + conn: 0 + } app.init_once() $for method in T.methods { $if method.return_type is Result { @@ -301,7 +303,7 @@ fn handle_conn(mut conn net.TcpConn, mut app T) { vals := first_line.split(' ') if vals.len < 2 { println('no vals for http') - send_string(conn, http_500) or { } + send_string(mut conn, http_500) or { } return } mut headers := []string{} @@ -383,7 +385,7 @@ fn handle_conn(mut conn net.TcpConn, mut app T) { mime_type := app.static_mime_types[static_file_name] if static_file != '' && mime_type != '' { data := os.read_file(static_file) or { - send_string(conn, http_404) or { } + send_string(mut conn, http_404) or { } return } app.send_response_to_client(mime_type, data) @@ -544,7 +546,7 @@ fn handle_conn(mut conn net.TcpConn, mut app T) { } if action == '' { // site not found - send_string(conn, http_404) or { } + send_string(mut conn, http_404) or { } return } $for method in T.methods { @@ -685,6 +687,6 @@ fn filter(s string) string { pub type RawHtml = string -fn send_string(conn net.TcpConn, s string) ? { +fn send_string(mut conn net.TcpConn, s string) ? { conn.write(s.bytes()) ? } diff --git a/vlib/x/websocket/io.v b/vlib/x/websocket/io.v index be40ef5fdb..eba4f66b2d 100644 --- a/vlib/x/websocket/io.v +++ b/vlib/x/websocket/io.v @@ -86,7 +86,7 @@ fn (mut ws Client) shutdown_socket() ? { } // dial_socket connects tcp socket and initializes default configurations -fn (mut ws Client) dial_socket() ?net.TcpConn { +fn (mut ws Client) dial_socket() ?&net.TcpConn { tcp_address := '$ws.uri.hostname:$ws.uri.port' mut t := net.dial_tcp(tcp_address) ? optval := int(1) diff --git a/vlib/x/websocket/websocket_client.v b/vlib/x/websocket/websocket_client.v index 07046d31c1..23d4d1ebd0 100644 --- a/vlib/x/websocket/websocket_client.v +++ b/vlib/x/websocket/websocket_client.v @@ -30,7 +30,7 @@ pub: uri Uri // uri of current connection id string // unique id of client pub mut: - conn net.TcpConn // underlying TCP socket connection + conn &net.TcpConn // underlying TCP socket connection nonce_size int = 16 // size of nounce used for masking panic_on_callback bool // set to true of callbacks can panic state State // current state of connection @@ -75,6 +75,7 @@ pub enum OPCode { pub fn new_client(address string) ?&Client { uri := parse_uri(address) ? return &Client{ + conn: 0 is_server: false ssl_conn: openssl.new_ssl_conn() is_ssl: address.starts_with('wss') diff --git a/vlib/x/websocket/websocket_server.v b/vlib/x/websocket/websocket_server.v index 295c47d4fe..e7a95a99d4 100644 --- a/vlib/x/websocket/websocket_server.v +++ b/vlib/x/websocket/websocket_server.v @@ -9,8 +9,8 @@ import rand // Server represents a websocket server connection pub struct Server { mut: - logger &log.Log // logger used to log - ls net.TcpListener // listener used to get incoming connection to socket + logger &log.Log // logger used to log + ls &net.TcpListener // listener used to get incoming connection to socket accept_client_callbacks []AcceptClientFn // accept client callback functions message_callbacks []MessageEventHandler // new message callback functions close_callbacks []CloseEventHandler // close message callback functions @@ -36,6 +36,7 @@ pub mut: // new_server instance a new websocket server on provided port and route pub fn new_server(port int, route string) &Server { return &Server{ + ls: 0 port: port logger: &log.Log{ level: .info