Skip to content

Commit 08189d6

Browse files
authored
vweb2 (#19997)
1 parent 2768de1 commit 08189d6

27 files changed

+4001
-24
lines changed

cmd/tools/modules/testing/common.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ pub fn new_test_session(_vargs string, will_compile bool) TestSession {
250250
skip_files << 'examples/call_v_from_python/test.v' // the example only makes sense to be compiled, when python is installed
251251
skip_files << 'examples/call_v_from_ruby/test.v' // the example only makes sense to be compiled, when ruby is installed
252252
skip_files << 'vlib/vweb/vweb_app_test.v' // imports the `sqlite` module, which in turn includes sqlite3.h
253+
skip_files << 'vlib/x/vweb/tests/vweb_app_test.v' // imports the `sqlite` module, which in turn includes sqlite3.h
253254
}
254255
$if !macos {
255256
skip_files << 'examples/macos_tray/tray.v'

cmd/tools/vtest-self.v

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ const skip_on_ubuntu_musl = [
259259
'vlib/net/smtp/smtp_test.v',
260260
'vlib/v/tests/websocket_logger_interface_should_compile_test.v',
261261
'vlib/v/tests/fn_literal_type_test.v',
262+
'vlib/vweb/x/tests/vweb_test.v',
263+
'vlib/vweb/x/tests/vweb_app_test.v',
262264
]
263265
const skip_on_linux = [
264266
'do_not_remove',

examples/pico/pico.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ fn callback(data voidptr, req picohttpparser.Request, mut res picohttpparser.Res
4949
}
5050

5151
fn main() {
52-
println('Starting webserver on http://127.0.0.1:${port}/ ...')
52+
println('Starting webserver on http://localhost:${port}/ ...')
5353
mut server := picoev.new(port: port, cb: callback)
5454
server.serve()
5555
}

examples/pico/raw_callback.v

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import net
44
import picoev
55

66
const port = 8080
7+
78
const http_response = 'HTTP/1.1 200 OK\r\nContent-type: text/html\r\nContent-length: 18\r\n\r\nHello from Picoev!'
89

910
fn main() {
@@ -15,7 +16,7 @@ fn main() {
1516
pico.serve()
1617
}
1718

18-
fn handle_conn(mut pv picoev.Picoev, fd int) {
19+
fn handle_conn(mut pv picoev.Picoev, fd int, events int) {
1920
// setup a nonblocking tcp connection
2021
mut conn := &net.TcpConn{
2122
sock: net.tcp_socket_from_handle_raw(fd)

vlib/io/buffered_reader.v

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mut:
1111
mfails int // maximum fails, after which we can assume that the stream has ended
1212
pub mut:
1313
end_of_stream bool // whether we reached the end of the upstream reader
14+
total_read int // total number of bytes read
1415
}
1516

1617
// BufferedReaderConfig are options that can be given to a buffered reader.
@@ -55,6 +56,7 @@ pub fn (mut r BufferedReader) read(mut buf []u8) !int {
5556
}
5657
}
5758
r.offset += read
59+
r.total_read += read
5860
return read
5961
}
6062

@@ -128,6 +130,7 @@ pub fn (mut r BufferedReader) read_line() !string {
128130
// try and find a newline character
129131
mut i := r.offset
130132
for ; i < r.len; i++ {
133+
r.total_read++
131134
c := r.buf[i]
132135
if c == `\n` {
133136
// great, we hit something

vlib/io/reader_test.v

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,38 @@ fn test_leftover() {
126126
}
127127
assert r.end_of_stream()
128128
}
129+
130+
fn test_totalread_read() {
131+
text := 'Some testing text'
132+
mut s := StringReader{
133+
text: text
134+
}
135+
mut r := new_buffered_reader(reader: s)
136+
137+
mut buf := []u8{len: text.len}
138+
total := r.read(mut buf) or {
139+
assert false
140+
panic('bad')
141+
}
142+
143+
assert r.total_read == total
144+
}
145+
146+
fn test_totalread_readline() {
147+
text := 'Some testing text\nmore_enters'
148+
mut s := StringReader{
149+
text: text
150+
}
151+
mut r := new_buffered_reader(reader: s)
152+
153+
_ := r.read_line() or {
154+
assert false
155+
panic('bad')
156+
}
157+
_ := r.read_line() or {
158+
assert false
159+
panic('bad')
160+
}
161+
162+
assert r.total_read == text.len
163+
}

vlib/picoev/picoev.v

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
module picoev
22

3+
import net
34
import picohttpparser
45
import time
56

67
pub const max_fds = 1024
8+
79
pub const max_queue = 4096
810

911
// events
1012
pub const picoev_read = 1
13+
1114
pub const picoev_write = 2
15+
1216
pub const picoev_timeout = 4
17+
1318
pub const picoev_add = 0x40000000
19+
1420
pub const picoev_del = 0x20000000
21+
1522
pub const picoev_readwrite = 3
1623

1724
// Target is a data representation of everything that needs to be associated with a single
@@ -31,19 +38,21 @@ pub:
3138
port int = 8080
3239
cb fn (voidptr, picohttpparser.Request, mut picohttpparser.Response) = unsafe { nil }
3340
err_cb fn (voidptr, picohttpparser.Request, mut picohttpparser.Response, IError) = default_err_cb
34-
raw_cb fn (mut Picoev, int) = unsafe { nil }
35-
user_data voidptr = unsafe { nil }
36-
timeout_secs int = 8
37-
max_headers int = 100
38-
max_read int = 4096
39-
max_write int = 8192
41+
raw_cb fn (mut Picoev, int, int) = unsafe { nil }
42+
user_data voidptr = unsafe { nil }
43+
timeout_secs int = 8
44+
max_headers int = 100
45+
max_read int = 4096
46+
max_write int = 8192
47+
family net.AddrFamily = .ip
48+
host string = 'localhost'
4049
}
4150

4251
@[heap]
4352
pub struct Picoev {
4453
cb fn (voidptr, picohttpparser.Request, mut picohttpparser.Response) = unsafe { nil }
4554
err_cb fn (voidptr, picohttpparser.Request, mut picohttpparser.Response, IError) = default_err_cb
46-
raw_cb fn (mut Picoev, int) = unsafe { nil }
55+
raw_cb fn (mut Picoev, int, int) = unsafe { nil }
4756

4857
timeout_secs int
4958
max_headers int = 100
@@ -98,7 +107,7 @@ pub fn (mut pv Picoev) add(fd int, events int, timeout int, cb voidptr) int {
98107

99108
// del removes a file descriptor from the loop
100109
@[direct_array_access]
101-
fn (mut pv Picoev) del(fd int) int {
110+
pub fn (mut pv Picoev) del(fd int) int {
102111
assert fd < picoev.max_fds
103112
mut target := pv.file_descriptors[fd]
104113

@@ -212,7 +221,7 @@ fn raw_callback(fd int, events int, context voidptr) {
212221
} else if events & picoev.picoev_read != 0 {
213222
pv.set_timeout(fd, pv.timeout_secs)
214223
if !isnil(pv.raw_cb) {
215-
pv.raw_cb(mut pv, fd)
224+
pv.raw_cb(mut pv, fd, events)
216225
return
217226
}
218227

@@ -272,6 +281,12 @@ fn raw_callback(fd int, events int, context voidptr) {
272281

273282
// Callback (should call .end() itself)
274283
pv.cb(pv.user_data, req, mut &res)
284+
} else if events & picoev.picoev_write != 0 {
285+
pv.set_timeout(fd, pv.timeout_secs)
286+
if !isnil(pv.raw_cb) {
287+
pv.raw_cb(mut pv, fd, events)
288+
return
289+
}
275290
}
276291
}
277292

vlib/picoev/socket_util.c.v

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
module picoev
22

33
import net
4-
import net.conv
54
import picohttpparser
65

76
#include <errno.h>
@@ -102,7 +101,7 @@ fn fatal_socket_error(fd int) bool {
102101
// listen creates a listening tcp socket and returns its file descriptor
103102
fn listen(config Config) int {
104103
// not using the `net` modules sockets, because not all socket options are defined
105-
fd := C.socket(net.AddrFamily.ip, net.SocketType.tcp, 0)
104+
fd := C.socket(config.family, net.SocketType.tcp, 0)
106105
assert fd != -1
107106

108107
$if trace_fd ? {
@@ -124,20 +123,18 @@ fn listen(config Config) int {
124123
}
125124

126125
// addr settings
126+
saddr := '${config.host}:${config.port}'
127+
addrs := net.resolve_addrs(saddr, config.family, .tcp) or { panic(err) }
128+
addr := addrs[0]
129+
alen := addr.len()
127130

128-
sin_port := conv.hton16(u16(config.port))
129-
sin_addr := conv.hton32(u32(C.INADDR_ANY))
130-
mut addr := C.sockaddr_in{
131-
sin_family: u8(C.AF_INET)
132-
sin_port: sin_port
133-
sin_addr: sin_addr
131+
net.socket_error_message(C.bind(fd, voidptr(&addr), alen), 'binding to ${saddr} failed') or {
132+
panic(err)
133+
}
134+
net.socket_error_message(C.listen(fd, C.SOMAXCONN), 'listening on ${saddr} with maximum backlog pending queue of ${C.SOMAXCONN}, failed') or {
135+
panic(err)
134136
}
135-
size := sizeof(C.sockaddr_in)
136-
bind_res := C.bind(fd, voidptr(unsafe { &net.Addr(&addr) }), size)
137-
assert bind_res == 0
138137

139-
listen_res := C.listen(fd, C.SOMAXCONN)
140-
assert listen_res == 0
141138
setup_sock(fd) or {
142139
config.err_cb(config.user_data, picohttpparser.Request{}, mut &picohttpparser.Response{},
143140
err)

0 commit comments

Comments
 (0)