Skip to content

Commit 81fd496

Browse files
committed
net: restore back the blocking TcpConn.read_line() method for simplicity
1 parent 02965e7 commit 81fd496

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

vlib/net/tcp.v

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ pub fn (c TcpConn) close() ? {
3535
// write_ptr blocks and attempts to write all data
3636
pub fn (c TcpConn) write_ptr(b byteptr, len int) ? {
3737
$if trace_tcp ? {
38-
eprintln('>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len')
38+
eprintln('>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
39+
unsafe { b.vstring_with_len(len) })
3940
}
4041
unsafe {
4142
mut ptr_base := byteptr(b)
@@ -85,6 +86,9 @@ pub fn (c TcpConn) read_ptr(buf_ptr byteptr, len int) ?int {
8586
error_ewouldblock {
8687
c.wait_for_read() ?
8788
res = wrap_read_result(C.recv(c.sock.handle, buf_ptr, len, 0)) ?
89+
$if trace_tcp ? {
90+
eprintln('<<< TcpConn.read_ptr | c.sock.handle: $c.sock.handle | buf_ptr: ${ptr_str(buf_ptr)} len: $len | res: $res')
91+
}
8892
return socket_error(res)
8993
}
9094
else {

vlib/net/tcp_read_line.v

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
module net
2+
3+
const (
4+
crlf = '\r\n'
5+
msg_peek = 0x02
6+
max_read = 400
7+
)
8+
9+
// read_line is a *simple*, *non customizable*, blocking line reader.
10+
// It will *always* return a line, ending with CRLF, or just '', on EOF.
11+
// NB: if you want more control over the buffer, please use a buffered IO
12+
// reader instead: `io.new_buffered_reader({reader: io.make_reader(con)})`
13+
pub fn (con TcpConn) read_line() string {
14+
mut buf := [max_read]byte{} // where C.recv will store the network data
15+
mut res := '' // The final result, including the ending \n.
16+
for {
17+
mut line := '' // The current line. Can be a partial without \n in it.
18+
n := C.recv(con.sock.handle, buf, max_read - 1, msg_peek | msg_nosignal)
19+
if n == -1 {
20+
return res
21+
}
22+
if n == 0 {
23+
return res
24+
}
25+
buf[n] = `\0`
26+
mut eol_idx := -1
27+
for i in 0 .. n {
28+
if int(buf[i]) == `\n` {
29+
eol_idx = i
30+
// Ensure that tos_clone(buf) later,
31+
// will return *only* the first line (including \n),
32+
// and ignore the rest
33+
buf[i + 1] = `\0`
34+
break
35+
}
36+
}
37+
bufbp := byteptr(buf)
38+
line = tos_clone(bufbp)
39+
if eol_idx > 0 {
40+
// At this point, we are sure that recv returned valid data,
41+
// that contains *at least* one line.
42+
// Ensure that the block till the first \n (including it)
43+
// is removed from the socket's receive queue, so that it does
44+
// not get read again.
45+
C.recv(con.sock.handle, buf, eol_idx + 1, msg_nosignal)
46+
res += line
47+
break
48+
}
49+
// recv returned a buffer without \n in it .
50+
C.recv(con.sock.handle, buf, n, msg_nosignal)
51+
res += line
52+
res += crlf
53+
break
54+
}
55+
return res
56+
}

0 commit comments

Comments
 (0)