Skip to content

Commit cdfc0bb

Browse files
committed
vlib: revert x.json2 and net changes
1 parent 726559c commit cdfc0bb

29 files changed

Lines changed: 1014 additions & 394 deletions

‎vlib/io/readerwriter.v‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ mut:
1717
// read reads up to `buf.len` bytes into `buf`. It returns
1818
// the number of bytes read or any error encountered.
1919
pub fn (mut r ReaderWriterImpl) read(mut buf []u8) !int {
20-
mut local_buf := unsafe { buf[0..buf.len] }
21-
return r.r.read(mut local_buf)
20+
return r.r.read(mut buf)
2221
}
2322

2423
// write writes `buf.len` bytes from `buf` to the underlying

‎vlib/net/http/backend.c.v‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// that can be found in the LICENSE file.
44
module http
55

6-
import net.mbedtls
6+
import net.ssl
77
import strings
88

99
fn (req &Request) ssl_do(port int, method Method, host_name string, path string) !Response {
@@ -18,8 +18,13 @@ fn (req &Request) ssl_do(port int, method Method, host_name string, path string)
1818
}
1919

2020
fn net_ssl_do(req &Request, port int, method Method, host_name string, path string) !Response {
21-
mut ssl_conn := mbedtls.new_ssl_conn_with_values(req.verify, req.cert, req.cert_key,
22-
req.validate, req.in_memory_verification)!
21+
mut ssl_conn := ssl.new_ssl_conn(
22+
verify: req.verify
23+
cert: req.cert
24+
cert_key: req.cert_key
25+
validate: req.validate
26+
in_memory_verification: req.in_memory_verification
27+
)!
2328
mut retries := 0
2429
for {
2530
ssl_conn.dial(host_name, port) or {
@@ -43,11 +48,11 @@ fn net_ssl_do(req &Request, port int, method Method, host_name string, path stri
4348
}
4449

4550
fn read_from_ssl_connection_cb(con voidptr, buf &u8, bufsize int) !int {
46-
mut ssl_conn := unsafe { &mbedtls.SSLConn(con) }
51+
mut ssl_conn := unsafe { &ssl.SSLConn(con) }
4752
return ssl_conn.socket_read_into_ptr(buf, bufsize)
4853
}
4954

50-
fn (req &Request) do_request(req_headers string, mut ssl_conn mbedtls.SSLConn) !Response {
55+
fn (req &Request) do_request(req_headers string, mut ssl_conn ssl.SSLConn) !Response {
5156
ssl_conn.write_string(req_headers) or { return err }
5257
mut content := strings.new_builder(4096)
5358
req.receive_all_data_from_cb_in_builder(mut content, voidptr(ssl_conn), read_from_ssl_connection_cb)!

‎vlib/net/http/download.v‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub fn download_file(url string, out_file_path string) ! {
1212
println('http.download_file url=${url} out_file_path=${out_file_path}')
1313
}
1414
s := get(url) or { return err }
15-
if s.status_code != 200 {
15+
if s.status() != .ok {
1616
return error_with_code(s.body, s.status_code)
1717
}
1818
$if debug_http ? {
@@ -26,7 +26,7 @@ pub fn download_file_with_cookies(url string, out_file_path string, cookies map[
2626
println('http.download_file url=${url} out_file_path=${out_file_path}')
2727
}
2828
s := fetch(method: .get, url: url, cookies: cookies) or { return err }
29-
if s.status_code != 200 {
29+
if s.status() != .ok {
3030
return error('received http code ${s.status_code}')
3131
}
3232
$if debug_http ? {

‎vlib/net/http/download_progress.v‎

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
module http
22

3-
import os
4-
53
// Downloader is the interface that you have to implement, if you need to customise
64
// how download_file_with_progress works, and what output it produces while a file
75
// is downloaded.
@@ -47,20 +45,38 @@ pub mut:
4745
// fail, despite saving all the data in the file before that. The default is 65536 bytes.
4846
pub fn download_file_with_progress(url string, path string, params DownloaderParams) !Response {
4947
mut d := unsafe { params.downloader }
50-
mut req := Request{
51-
method: .get
52-
url: url
53-
user_ptr: voidptr(d)
48+
mut config := params.FetchConfig
49+
config.url = url
50+
config.user_ptr = voidptr(d)
51+
config.on_progress_body = download_progres_cb
52+
if config.stop_copying_limit == -1 {
53+
// leave more than enough space for potential redirect headers
54+
config.stop_copying_limit = 65536
5455
}
56+
mut req := prepare(config)!
5557
d.on_start(mut req, path)!
5658
response := req.do()!
57-
if response.status_code != 200 {
58-
return error_with_code(response.body, response.status_code)
59-
}
60-
if response.body.len > 0 {
61-
d.on_chunk(&req, response.body.bytes(), 0, u64(response.body.len))!
59+
$if windows && !no_vschannel ? {
60+
// TODO: remove this, when windows supports streaming properly through vschannel
61+
// For now though, just ensure that the complete body is "received" in one big chunk:
62+
d.on_chunk(req, response.body.bytes(), 0, u64(response.body.len))!
6263
}
63-
os.write_file(path, response.body)!
64-
d.on_finish(&req, &response)!
64+
d.on_finish(req, response)!
6565
return response
6666
}
67+
68+
const zz = &Downloader(unsafe { nil })
69+
70+
fn download_progres_cb(request &Request, chunk []u8, body_so_far u64, expected_size u64, status_code int) ! {
71+
// TODO: remove this hack, when `unsafe { &Downloader( request.user_ptr ) }` works reliably,
72+
// by just casting, without trying to promote the argument to the heap at all.
73+
mut d := unsafe { zz }
74+
pd := unsafe { &voidptr(&d) }
75+
unsafe {
76+
*pd = request.user_ptr
77+
}
78+
if status_code == 200 {
79+
// ignore redirects, we are interested in the chunks of the final file:
80+
d.on_chunk(request, chunk, body_so_far, expected_size)!
81+
}
82+
}

‎vlib/net/http/download_terminal_downloader.v‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ import time
44

55
// TerminalStreamingDownloader is the same as http.SilentStreamingDownloader, but produces a progress line on stdout.
66
pub struct TerminalStreamingDownloader {
7+
SilentStreamingDownloader
78
mut:
8-
silent SilentStreamingDownloader
99
start_time time.Time
1010
past_time time.Time
1111
past_received u64
1212
}
1313

1414
// on_start is called once at the start of the download.
1515
pub fn (mut d TerminalStreamingDownloader) on_start(mut request Request, path string) ! {
16-
d.silent.on_start(mut request, path)!
16+
d.SilentStreamingDownloader.on_start(mut request, path)!
1717
d.start_time = time.now()
1818
d.past_time = time.now()
1919
}
@@ -38,14 +38,14 @@ pub fn (mut d TerminalStreamingDownloader) on_chunk(request &Request, chunk []u8
3838
estimated_s := estimated.seconds()
3939
eta_s := f64_max(estimated_s - elapsed_s, 0.0)
4040

41-
d.silent.on_chunk(request, chunk, already_received, expected)!
42-
print('\rDownloading to `${d.silent.path}` ${100.0 * ratio:6.2f}%, ${f64(already_received) / (1024 * 1024):7.3f}/${f64(expected) / (1024 * 1024):-7.3f}MB, ${speed:6.0f}KB/s, elapsed: ${elapsed_s:6.0f}s, eta: ${eta_s:6.0f}s')
41+
d.SilentStreamingDownloader.on_chunk(request, chunk, already_received, expected)!
42+
print('\rDownloading to `${d.path}` ${100.0 * ratio:6.2f}%, ${f64(already_received) / (1024 * 1024):7.3f}/${f64(expected) / (1024 * 1024):-7.3f}MB, ${speed:6.0f}KB/s, elapsed: ${elapsed_s:6.0f}s, eta: ${eta_s:6.0f}s')
4343
flush_stdout()
4444
}
4545

4646
// on_finish is called once at the end of the download.
4747
pub fn (mut d TerminalStreamingDownloader) on_finish(request &Request, response &Response) ! {
48-
d.silent.on_finish(request, response)!
48+
d.SilentStreamingDownloader.on_finish(request, response)!
4949
println('')
5050
flush_stdout()
5151
}

‎vlib/net/http/header.v‎

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
module http
55

66
import strings
7+
import arrays
78

89
struct HeaderKV {
910
key string
@@ -608,19 +609,14 @@ pub fn (h Header) custom_values(key string, flags HeaderQueryConfig) []string {
608609
// keys gets all header keys as strings
609610
pub fn (h Header) keys() []string {
610611
mut res := []string{cap: h.cur_pos}
611-
mut seen := map[string]bool{}
612612
for i := 0; i < h.cur_pos; i++ {
613613
if h.data[i].value == '' {
614614
continue
615615
}
616-
key := h.data[i].key
617-
if seen[key] {
618-
continue
619-
}
620-
seen[key] = true
621-
res << key
616+
res << h.data[i].key
622617
}
623-
return res
618+
// Make sure keys are lower case and unique
619+
return arrays.uniq(res)
624620
}
625621

626622
@[params]
@@ -698,7 +694,7 @@ pub fn (h Header) join(other Header) Header {
698694
for v in other.custom_values(k, exact: true) {
699695
combined.add_custom(k, v) or {
700696
// panic because this should never fail
701-
panic('unexpected header merge error')
697+
panic('unexpected error: ' + err.str())
702698
}
703699
}
704700
}

‎vlib/net/http/http_proxy.v‎

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ module http
22

33
import encoding.base64
44
import net
5-
import net.mbedtls
65
import net.urllib
6+
import net.ssl
77
import net.socks
88

99
@[heap]
@@ -52,9 +52,9 @@ pub fn new_http_proxy(raw_url string) !&HttpProxy {
5252
return error('Unknown port')
5353
}
5454

55-
if url.user.username != '' || url.user.password != '' {
56-
username = url.user.username
57-
password = url.user.password
55+
if u := url.user {
56+
username = u.username
57+
password = u.password
5858
}
5959

6060
return &HttpProxy{
@@ -149,7 +149,7 @@ fn (pr &HttpProxy) dial(host string) !&net.TcpConn {
149149
}
150150
}
151151

152-
fn (pr &HttpProxy) ssl_dial(host string) !&mbedtls.SSLConn {
152+
fn (pr &HttpProxy) ssl_dial(host string) !&ssl.SSLConn {
153153
if pr.scheme in ['http', 'https'] {
154154
mut tcp := net.dial_tcp(pr.host)!
155155
tcp.write(pr.build_proxy_headers(host).bytes())!
@@ -159,14 +159,17 @@ fn (pr &HttpProxy) ssl_dial(host string) !&mbedtls.SSLConn {
159159
return error('ssl dial error: ${bf.bytestr()}')
160160
}
161161

162-
mut ssl_conn := mbedtls.new_ssl_conn_with_values('', '', '', false, false)!
162+
mut ssl_conn := ssl.new_ssl_conn(
163+
verify: ''
164+
cert: ''
165+
cert_key: ''
166+
validate: false
167+
in_memory_verification: false
168+
)!
163169
ssl_conn.connect(mut tcp, host.all_before_last(':'))!
164170
return ssl_conn
165171
} else if pr.scheme == 'socks5' {
166-
mut tcp := socks.socks5_dial(pr.host, host, pr.username, pr.password)!
167-
mut ssl_conn := mbedtls.new_ssl_conn_with_values('', '', '', false, false)!
168-
ssl_conn.connect(mut tcp, host.all_before_last(':'))!
169-
return ssl_conn
172+
return socks.socks5_ssl_dial(pr.host, host, pr.username, pr.password)!
170173
} else {
171174
return error('http_proxy ssl_dial: invalid proxy scheme')
172175
}

‎vlib/net/http/request.v‎

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ pub fn (req &Request) do() !Response {
174174
if !req.allow_redirect {
175175
break
176176
}
177-
if resp.status_code !in [301, 302, 303, 307, 308] {
177+
if resp.status() !in [.moved_permanently, .found, .see_other, .temporary_redirect,
178+
.permanent_redirect] {
178179
break
179180
}
180181
// follow any redirects
@@ -399,7 +400,7 @@ fn (req &Request) receive_all_data_from_cb_in_builder(mut content strings.Builde
399400
if headers_end < 0 {
400401
unsafe { header_buf.write_ptr(bp, len) }
401402
if header_buf.len >= headers_body_boundary.len {
402-
header_str := header_buf.spart(0, header_buf.len)
403+
header_str := header_buf.bytestr()
403404
hidx := header_str.index_(headers_body_boundary)
404405
if hidx >= 0 {
405406
headers_end = hidx + headers_body_boundary.len
@@ -505,10 +506,7 @@ pub fn parse_request(mut reader io.BufferedReader) !Request {
505506
pub fn parse_request_head(mut reader io.BufferedReader) !Request {
506507
// request line
507508
mut line := reader.read_line()!
508-
request_line := parse_request_line(line)!
509-
method := request_line.method
510-
target := request_line.target
511-
version := request_line.version
509+
method, target, version := parse_request_line(line)!
512510

513511
// headers
514512
mut header := new_header()
@@ -523,6 +521,7 @@ pub fn parse_request_head(mut reader io.BufferedReader) !Request {
523521
}
524522
if pos + 1 < line.len {
525523
value := line[pos + 1..]
524+
_, _ = key, value
526525
// println('key,value=${key},${value}')
527526
header.add_custom(key, value)!
528527
}
@@ -552,10 +551,7 @@ pub fn parse_request_head_str(s string) !Request {
552551
return error('malformed request: no request line found')
553552
}
554553
line0 := s[..pos0].trim_space()
555-
request_line := parse_request_line(line0)!
556-
method := request_line.method
557-
target := request_line.target
558-
version := request_line.version
554+
method, target, version := parse_request_line(line0)!
559555

560556
// headers
561557
mut header := new_header()
@@ -617,13 +613,7 @@ pub fn parse_request_str(s string) !Request {
617613
return request
618614
}
619615

620-
struct ParsedRequestLine {
621-
method Method
622-
target urllib.URL
623-
version Version
624-
}
625-
626-
fn parse_request_line(line string) !ParsedRequestLine {
616+
fn parse_request_line(line string) !(Method, urllib.URL, Version) {
627617
// println('S=${s}')
628618
words := line.split(' ')
629619
// println('words=')
@@ -655,11 +645,7 @@ fn parse_request_line(line string) !ParsedRequestLine {
655645
if version == .unknown {
656646
return error('unsupported version')
657647
}
658-
return ParsedRequestLine{
659-
method: method
660-
target: target
661-
version: version
662-
}
648+
return method, target, version
663649
}
664650

665651
// Parse URL encoded key=value&key=value forms

‎vlib/net/http/server.v‎

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ pub fn (mut s Server) listen_and_serve() {
7373
s.addr = l.str()
7474
s.listener.set_accept_timeout(s.accept_timeout)
7575

76-
// Keep the request loop synchronous for now. It avoids the worker-channel path,
77-
// while preserving the handler behavior for local server use.
78-
mut worker := HandlerWorker{
79-
id: 0
80-
handler: s.handler
81-
max_keep_alive_requests: s.max_keep_alive_requests
76+
// Create tcp connection channel
77+
ch := chan &net.TcpConn{cap: s.pool_channel_slots}
78+
// Create workers
79+
mut ws := []thread{cap: s.worker_num}
80+
for wid in 0 .. s.worker_num {
81+
ws << new_handler_worker(wid, ch, s.handler, s.max_keep_alive_requests)
8282
}
8383

8484
if s.show_startup_message {
@@ -102,7 +102,7 @@ pub fn (mut s Server) listen_and_serve() {
102102
}
103103
conn.set_read_timeout(s.read_timeout)
104104
conn.set_write_timeout(s.write_timeout)
105-
worker.handle_conn(mut conn)
105+
ch <- conn
106106
}
107107
if s.state == .stopped {
108108
s.close()
@@ -161,11 +161,29 @@ pub fn (mut s Server) wait_till_running(params WaitTillRunningParams) !int {
161161

162162
struct HandlerWorker {
163163
id int
164+
ch chan &net.TcpConn
164165
max_keep_alive_requests int
165166
pub mut:
166167
handler Handler
167168
}
168169

170+
fn new_handler_worker(wid int, ch chan &net.TcpConn, handler Handler, max_keep_alive_requests int) thread {
171+
mut w := &HandlerWorker{
172+
id: wid
173+
ch: ch
174+
handler: handler
175+
max_keep_alive_requests: max_keep_alive_requests
176+
}
177+
return spawn w.process_requests()
178+
}
179+
180+
fn (mut w HandlerWorker) process_requests() {
181+
for {
182+
mut conn := <-w.ch or { break }
183+
w.handle_conn(mut conn)
184+
}
185+
}
186+
169187
fn (mut w HandlerWorker) handle_conn(mut conn net.TcpConn) {
170188
defer {
171189
conn.close() or { eprintln('close() failed: ${err}') }

0 commit comments

Comments
 (0)