Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
04e10f5
feat: add openssl-based https server support in net.openssl and veb
guweigang Jun 17, 2026
975c332
fix: address review feedback for OpenSSL HTTPS listener and veb
guweigang Jun 19, 2026
41d4b13
fix(net): honor OpenSSL listener family and timeouts
guweigang Jun 20, 2026
861e65d
test(net): cover OpenSSL listener family and timeout
guweigang Jun 20, 2026
1b6a63a
fix(veb): preserve handler responses through middleware
guweigang Jun 20, 2026
57a85b8
fix(net): honor OpenSSL listener memory and ALPN config
guweigang Jun 21, 2026
a83b139
fix(net): preserve OpenSSL listener certificate chains
guweigang Jun 23, 2026
5a64b92
Merge remote-tracking branch 'upstream/master' into openssl-https
guweigang Jun 23, 2026
009abcc
test(veb): make SSL tests discoverable
guweigang Jun 24, 2026
f34fa2e
Merge remote-tracking branch 'upstream/master' into openssl-https
guweigang Jun 24, 2026
7098911
net.openssl: always release SSLConn socket on shutdown
medvednikov Jun 26, 2026
89f9db3
test(veb): exclude mbedtls HTTPS test from -d use_openssl runs
medvednikov Jun 26, 2026
02dc1a4
Merge remote-tracking branch 'upstream/master' into openssl-https
medvednikov Jun 26, 2026
61636f2
net.openssl: clamp expired finite TLS deadlines to an immediate timeout
medvednikov Jun 26, 2026
df3a1b2
net.ssl: honor listener options for mbedtls
medvednikov Jun 26, 2026
d05ee16
net: address SSL listener review feedback
guweigang Jun 28, 2026
dcc2d8d
Merge remote-tracking branch 'upstream/master' into openssl-https
guweigang Jun 28, 2026
bc07637
Merge remote-tracking branch 'upstream/master' into openssl-https
guweigang Jun 30, 2026
acf577e
net: address OpenSSL listener review feedback
guweigang Jun 30, 2026
c860885
net: address SSL listener review feedback
guweigang Jul 1, 2026
ccf15c8
net: bound OpenSSL HTTPS handshakes
guweigang Jul 1, 2026
1e942fd
net: harden OpenSSL listener cleanup
guweigang Jul 9, 2026
7fd5b39
net: polish SSL listener review fixes
guweigang Jul 10, 2026
762ddef
net: tighten SSL listener edge cases
guweigang Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions vlib/net/mbedtls/mbedtls_ssl_listener_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module main

import net.mbedtls
import os

fn test_mbedtls_ssl_listener_preserves_ipv6_literal_by_default() ! {
$if macos || linux {
cert_path := os.join_path(@VMODROOT, 'examples', 'ssl_server', 'cert', 'server.crt')
key_path := os.join_path(@VMODROOT, 'examples', 'ssl_server', 'cert', 'server.key')
mut listener := mbedtls.new_ssl_listener('[::1]:0', mbedtls.SSLConnectConfig{
cert: cert_path
cert_key: key_path
})!
listener.shutdown()!
}
}

fn test_mbedtls_ssl_listener_preserves_unspecified_ipv6_by_default() ! {
$if macos || linux {
cert_path := os.join_path(@VMODROOT, 'examples', 'ssl_server', 'cert', 'server.crt')
key_path := os.join_path(@VMODROOT, 'examples', 'ssl_server', 'cert', 'server.key')
mut listener := mbedtls.new_ssl_listener(':0', mbedtls.SSLConnectConfig{
cert: cert_path
cert_key: key_path
})!
listener.shutdown()!
}
}
57 changes: 39 additions & 18 deletions vlib/net/mbedtls/ssl_connection.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,9 @@ pub mut:

// SSLListener listens on a TCP port and accepts connection secured with TLS
pub struct SSLListener {
saddr string
config SSLConnectConfig
saddr string
config SSLConnectConfig
options SSLListenerOptions
mut:
server_fd C.mbedtls_net_context
ssl C.mbedtls_ssl_context
Expand All @@ -185,11 +186,19 @@ mut:
// duration time.Duration
}

// create a new SSLListener binding to `saddr`
pub fn new_ssl_listener(saddr string, config SSLConnectConfig) !&SSLListener {
// SSLListenerOptions configures the TCP listener used by an SSLListener.
@[params]
pub struct SSLListenerOptions {
pub:
family net.AddrFamily = .unspec
}

// new_ssl_listener creates a new SSLListener binding to `saddr`.
pub fn new_ssl_listener(saddr string, config SSLConnectConfig, options SSLListenerOptions) !&SSLListener {
mut listener := &SSLListener{
saddr: saddr
config: config
saddr: saddr
config: config
options: options
}
listener.init()!
listener.opened = true
Expand Down Expand Up @@ -218,13 +227,23 @@ pub fn (mut l SSLListener) shutdown() ! {
}
}

fn ssl_listener_family(saddr string, family net.AddrFamily) net.AddrFamily {
if family != .unspec {
return family
}
address, _ := net.split_address(saddr) or { return .ip }
if address == '' || address == '::' || address.contains(':') {
return .ip6
}
return .ip
}

// internal function to init and bind the listener
fn (mut l SSLListener) init() ! {
$if trace_ssl ? {
eprintln(@METHOD)
}

lhost, lport := net.split_address(l.saddr)!
if l.config.cert == '' || l.config.cert_key == '' {
return error('net.mbedtls SSLListener.init, no certificate or key provided')
}
Expand Down Expand Up @@ -261,22 +280,20 @@ fn (mut l SSLListener) init() ! {
C.mbedtls_ssl_conf_authmode(&l.conf, C.MBEDTLS_SSL_VERIFY_REQUIRED)
}

mut bind_ip := unsafe { nil }
if lhost != '' {
bind_ip = voidptr(lhost.str)
}
bind_port := lport.str()

ret = C.mbedtls_net_bind(&l.server_fd, bind_ip, voidptr(bind_port.str), C.MBEDTLS_NET_PROTO_TCP)

if ret != 0 {
return error_with_code("net.mbedtls SSLListener.init, mbedtls_net_bind can't bind to ${l.saddr} error ret: ${ret}",
ret)
tcp_listener := net.listen_tcp(ssl_listener_family(l.saddr, l.options.family), l.saddr, net.ListenOptions{
backlog: C.MBEDTLS_NET_LISTEN_BACKLOG
}) or { return error('net.mbedtls SSLListener.init, listen_tcp failed for ${l.saddr}: ${err}') }
l.server_fd.fd = tcp_listener.sock.handle
l.opened = true
net.set_blocking(l.server_fd.fd, true) or {
l.shutdown() or {}
return error('net.mbedtls SSLListener.init, could not make listener socket blocking: ${err}')
}

ret = C.mbedtls_ssl_config_defaults(&l.conf, C.MBEDTLS_SSL_IS_SERVER,
C.MBEDTLS_SSL_TRANSPORT_STREAM, C.MBEDTLS_SSL_PRESET_DEFAULT)
if ret != 0 {
l.shutdown() or {}
return error_with_code("net.mbedtls SSLListener.init, mbedtls_ssl_config_defaults can't set config defaults ret: ${ret}",
ret)
}
Expand All @@ -289,6 +306,7 @@ fn (mut l SSLListener) init() ! {
C.mbedtls_ssl_conf_ca_chain(&l.conf, &l.certs.cacert, unsafe { nil })
ret = C.mbedtls_ssl_conf_own_cert(&l.conf, &l.certs.client_cert, &l.certs.client_key)
if ret != 0 {
l.shutdown() or {}
return error_with_code("net.mbedtls SSLListener.init, mbedtls_ssl_conf_own_cert can't load certificate ret: ${ret}",
ret)
}
Expand All @@ -299,6 +317,7 @@ fn (mut l SSLListener) init() ! {
n := l.config.alpn_protocols.len
l.alpn_list = unsafe { &&char(C.malloc(isize((n + 1) * int(sizeof(voidptr))))) }
if l.alpn_list == unsafe { nil } {
l.shutdown() or {}
return error('net.mbedtls SSLListener.init, failed to allocate ALPN list')
}
unsafe {
Expand All @@ -309,13 +328,15 @@ fn (mut l SSLListener) init() ! {
}
ret = C.mbedtls_ssl_conf_alpn_protocols(&l.conf, voidptr(l.alpn_list))
if ret != 0 {
l.shutdown() or {}
return error_with_code('net.mbedtls SSLListener.init, mbedtls_ssl_conf_alpn_protocols failed ret: ${ret}',
ret)
}
}

ret = C.mbedtls_ssl_setup(&l.ssl, &l.conf)
if ret != 0 {
l.shutdown() or {}
return error_with_code("net.mbedtls SSLListener.init, mbedtls_ssl_setup can't setup ssl ret: ${ret}",
ret)
}
Expand Down
20 changes: 20 additions & 0 deletions vlib/net/openssl/openssl.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,26 @@ fn C.SSL_CTX_set_options(ctx &C.SSL_CTX, options i32)

fn C.SSL_CTX_set_verify_depth(s &C.SSL_CTX, depth i32)

fn C.SSL_CTX_set_verify(ctx &C.SSL_CTX, mode i32, callback voidptr)

fn C.SSL_CTX_load_verify_locations(ctx &C.SSL_CTX, const_file &char, const_ca_path &char) i32

fn C.SSL_CTX_free(ctx &C.SSL_CTX)

fn C.SSL_CTX_use_certificate_file(ctx &C.SSL_CTX, const_file &char, file_type i32) i32

fn C.SSL_CTX_use_certificate_chain_file(ctx &C.SSL_CTX, const_file &char) i32

fn C.SSL_CTX_use_PrivateKey_file(ctx &C.SSL_CTX, const_file &char, file_type i32) i32

fn C.v_net_openssl_SSL_CTX_use_certificate_chain_memory(ctx &C.SSL_CTX, data &u8, len usize) i32

fn C.v_net_openssl_SSL_CTX_extra_chain_certs_count(ctx &C.SSL_CTX) int

fn C.v_net_openssl_SSL_CTX_use_PrivateKey_memory(ctx &C.SSL_CTX, data &u8, len usize) i32

fn C.v_net_openssl_SSL_CTX_load_verify_memory(ctx &C.SSL_CTX, data &u8, len usize) i32

fn C.SSL_new(&C.SSL_CTX) &C.SSL

fn C.SSL_set_fd(ssl &C.SSL, fd i32) i32
Expand Down Expand Up @@ -147,6 +159,8 @@ fn C.v_net_openssl_set_alpn_protos(ssl &C.SSL, protos &u8, protos_len u32) i32

fn C.v_net_openssl_get0_alpn_selected(ssl &C.SSL, data voidptr, len &u32)

fn C.v_net_openssl_SSL_CTX_set_alpn_select_protos(ctx &C.SSL_CTX, protos &u8, protos_len u32) voidptr

fn C.SSL_shutdown(&C.SSL) i32

fn C.SSL_free(&C.SSL)
Expand All @@ -159,8 +173,14 @@ fn C.SSLv23_client_method() &C.SSL_METHOD

fn C.TLS_method() voidptr

fn C.v_net_openssl_TLS_server_method() &C.SSL_METHOD

fn C.TLSv1_2_method() voidptr

fn C.SSL_CTX_check_private_key(ctx &C.SSL_CTX) i32

fn C.SSL_accept(ssl &C.SSL) i32

fn C.v_net_openssl_init_ssl() i32

fn init() {
Expand Down
Loading
Loading