v/examples/ssl_server/server_sni_advanced.v

121 lines
2.7 KiB
V

import net.mbedtls
import os
import io
import net.http
// first run cert/makecerts.sh to generate the certificates for this server
// start the server with:
// v run server_sni_advanced.v
// test using curl:
// connection using the 1x.dk certificate
// curl -vik --resolve 1x.dk:8443:0.0.0.0 https://1x.dk:8443/
// connection using the 2x.dk certificate
// curl -vik --resolve 2x.dk:8443:0.0.0.0 https://2x.dk:8443/
// default certificate (no sni callback)
// curl -vik https://0.0.0.0:8443/
@[heap]
struct CertManager {
mut:
// cache for the certificates
certs map[string]&mbedtls.SSLCerts
}
fn (mut cm CertManager) get_cert(mut l mbedtls.SSLListener, host string) !&mbedtls.SSLCerts {
println('${host}')
if c := cm.certs[host] {
println('read certs for ${host} already ready')
return c
} else {
cert := os.read_file('cert/${host}.crt') or {
return error('Failed to read certificate ${host}: ${err}')
}
key := os.read_file('cert/${host}.key') or {
return error('Failed to read key ${host}: ${err}')
}
println('read certs for ${host}')
if mut c := mbedtls.new_sslcerts_in_memory('', cert, key) {
cm.certs[host] = c
return c
} else {
return error('mbedtls.new_sslcerts_in_memory err: ${err}')
}
}
}
fn main() {
// Load the default certificates
cert := os.read_file('cert/0x.dk.crt') or {
eprintln('Failed to read certificate: ${err}')
return
}
key := os.read_file('cert/0x.dk.key') or {
eprintln('Failed to read key: ${err}')
return
}
cm := CertManager{}
// Create the SSL configuration
mut config := mbedtls.SSLConnectConfig{
cert: cert
cert_key: key
in_memory_verification: true // !importent
get_certificate: cm.get_cert
}
mut server := mbedtls.new_ssl_listener('0.0.0.0:8443', config) or {
println('new_ssl_listener : ${err.msg()} : ${err.code()}')
return
}
println('Listening on https://0.0.0.0:8443')
// Accept and handle connections
for {
mut client := server.accept() or {
println('accept : ${err.msg()} : ${err.code()}')
continue
}
go handle_connection(mut client)
}
server.shutdown() or {
println('server.shutdown : ${err.msg()} : ${err.code()}')
return
}
}
fn handle_connection(mut ssl_conn mbedtls.SSLConn) {
mut reader := io.new_buffered_reader(reader: ssl_conn)
request := http.parse_request(mut reader) or {
println('parse_request failed : ${err}')
return
}
println('Received request: ${request.url}')
// Respond to the request
body := 'Hello, HTTPS!'
res := http.new_response(http.ResponseConfig{
body: body
})
ssl_conn.write(res.bytes()) or {
eprintln('Failed to write response: ${err}')
return
}
ssl_conn.shutdown() or {
eprintln('Failed to shutdown connection: ${err}')
return
}
}