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

net: restore back the blocking TcpConn.read_line() method for simplicity

This commit is contained in:
Delyan Angelov 2020-12-29 17:51:10 +02:00
parent 02965e753e
commit 81fd49642a
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
2 changed files with 61 additions and 1 deletions

View File

@ -35,7 +35,8 @@ pub fn (c TcpConn) close() ? {
// write_ptr blocks and attempts to write all data // write_ptr blocks and attempts to write all data
pub fn (c TcpConn) write_ptr(b byteptr, len int) ? { pub fn (c TcpConn) write_ptr(b byteptr, len int) ? {
$if trace_tcp ? { $if trace_tcp ? {
eprintln('>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len') eprintln('>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
unsafe { b.vstring_with_len(len) })
} }
unsafe { unsafe {
mut ptr_base := byteptr(b) mut ptr_base := byteptr(b)
@ -85,6 +86,9 @@ pub fn (c TcpConn) read_ptr(buf_ptr byteptr, len int) ?int {
error_ewouldblock { error_ewouldblock {
c.wait_for_read() ? c.wait_for_read() ?
res = wrap_read_result(C.recv(c.sock.handle, buf_ptr, len, 0)) ? 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')
}
return socket_error(res) return socket_error(res)
} }
else { else {

56
vlib/net/tcp_read_line.v Normal file
View File

@ -0,0 +1,56 @@
module net
const (
crlf = '\r\n'
msg_peek = 0x02
max_read = 400
)
// read_line is a *simple*, *non customizable*, blocking line reader.
// 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 {
mut buf := [max_read]byte{} // where C.recv will store the network data
mut res := '' // The final result, including the ending \n.
for {
mut line := '' // The current line. Can be a partial without \n in it.
n := C.recv(con.sock.handle, buf, max_read - 1, msg_peek | msg_nosignal)
if n == -1 {
return res
}
if n == 0 {
return res
}
buf[n] = `\0`
mut eol_idx := -1
for i in 0 .. n {
if int(buf[i]) == `\n` {
eol_idx = i
// Ensure that tos_clone(buf) later,
// will return *only* the first line (including \n),
// and ignore the rest
buf[i + 1] = `\0`
break
}
}
bufbp := byteptr(buf)
line = tos_clone(bufbp)
if eol_idx > 0 {
// At this point, we are sure that recv returned valid data,
// that contains *at least* one line.
// Ensure that the block till the first \n (including it)
// is removed from the socket's receive queue, so that it does
// not get read again.
C.recv(con.sock.handle, buf, eol_idx + 1, msg_nosignal)
res += line
break
}
// recv returned a buffer without \n in it .
C.recv(con.sock.handle, buf, n, msg_nosignal)
res += line
res += crlf
break
}
return res
}