Update to rustls = 0.22.0-alpha.5
This commit is contained in:
parent
7d7b1b3f99
commit
5ead01a5c7
6 changed files with 67 additions and 63 deletions
|
|
@ -19,4 +19,4 @@ resolver = "2"
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
boring = { version = "4.0", default-features = false }
|
boring = { version = "4.0", default-features = false }
|
||||||
boring-sys = { version = "4.0", default-features = false }
|
boring-sys = { version = "4.0", default-features = false }
|
||||||
rustls = { version = "=0.22.0-alpha.4", default-features = false }
|
rustls = { version = "=0.22.0-alpha.5", default-features = false }
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ This is just a dump of me figuring out how to interface with boring and rustls.
|
||||||
It works to establish a connection and exchange data but I haven't written real tests yet, nor did I cleanup the code or made the effort to make it look nice.
|
It works to establish a connection and exchange data but I haven't written real tests yet, nor did I cleanup the code or made the effort to make it look nice.
|
||||||
There is probably some code in here that should rather live in the `boring` crate.
|
There is probably some code in here that should rather live in the `boring` crate.
|
||||||
|
|
||||||
Further, the rustls crypto provider API is still not stable it seems. This works currently with `rustls = 0.22.0-alpha.4`.
|
Further, the rustls crypto provider API is still not stable it seems. This works currently with `rustls = 0.22.0-alpha.5`.
|
||||||
|
|
||||||
### Supported ciphers
|
### Supported ciphers
|
||||||
Currently, supports only TLS 1.3:
|
Currently, supports only TLS 1.3:
|
||||||
|
|
@ -17,6 +17,8 @@ AES_256_GCM_SHA384
|
||||||
CHACHA20_POLY1305_SHA256
|
CHACHA20_POLY1305_SHA256
|
||||||
```
|
```
|
||||||
|
|
||||||
|
QUIC: not yet supported
|
||||||
|
|
||||||
TLS 1.2:
|
TLS 1.2:
|
||||||
```
|
```
|
||||||
ECDHE_ECDSA_AES128_GCM_SHA256
|
ECDHE_ECDSA_AES128_GCM_SHA256
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ where
|
||||||
T: BoringAead,
|
T: BoringAead,
|
||||||
{
|
{
|
||||||
fn encrypt(
|
fn encrypt(
|
||||||
&self,
|
&mut self,
|
||||||
msg: cipher::BorrowedPlainMessage,
|
msg: cipher::BorrowedPlainMessage,
|
||||||
seq: u64,
|
seq: u64,
|
||||||
) -> Result<cipher::OpaqueMessage, rustls::Error> {
|
) -> Result<cipher::OpaqueMessage, rustls::Error> {
|
||||||
|
|
@ -121,8 +121,7 @@ where
|
||||||
let fixed_iv_len = <T as BoringCipher>::FIXED_IV_LEN;
|
let fixed_iv_len = <T as BoringCipher>::FIXED_IV_LEN;
|
||||||
let explicit_nonce_len = <T as BoringCipher>::EXPLICIT_NONCE_LEN;
|
let explicit_nonce_len = <T as BoringCipher>::EXPLICIT_NONCE_LEN;
|
||||||
|
|
||||||
let total_len =
|
let total_len = self.encrypted_payload_len(msg.payload.len());
|
||||||
msg.payload.len() + self.crypter.max_overhead() + explicit_nonce_len;
|
|
||||||
|
|
||||||
let mut full_payload = Vec::with_capacity(total_len);
|
let mut full_payload = Vec::with_capacity(total_len);
|
||||||
full_payload.extend_from_slice(&nonce.0.as_ref()[fixed_iv_len..]);
|
full_payload.extend_from_slice(&nonce.0.as_ref()[fixed_iv_len..]);
|
||||||
|
|
@ -139,7 +138,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtocolVersion::TLSv1_3 => {
|
ProtocolVersion::TLSv1_3 => {
|
||||||
let total_len = msg.payload.len() + 1 + self.crypter.max_overhead();
|
let total_len = self.encrypted_payload_len(msg.payload.len());
|
||||||
|
|
||||||
let mut payload = Vec::with_capacity(total_len);
|
let mut payload = Vec::with_capacity(total_len);
|
||||||
payload.extend_from_slice(msg.payload);
|
payload.extend_from_slice(msg.payload);
|
||||||
|
|
@ -160,10 +159,15 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next version seems to add this
|
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
|
||||||
// fn encrypted_payload_len(&self, payload_len: usize) -> usize {
|
match self.tls_version {
|
||||||
// payload_len + 1 + self.crypter.max_overhead()
|
ProtocolVersion::TLSv1_2 => {
|
||||||
// }
|
payload_len + self.crypter.max_overhead() + <T as BoringCipher>::EXPLICIT_NONCE_LEN
|
||||||
|
}
|
||||||
|
ProtocolVersion::TLSv1_3 => payload_len + 1 + self.crypter.max_overhead(),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> cipher::MessageDecrypter for BoringAeadCrypter<T>
|
impl<T> cipher::MessageDecrypter for BoringAeadCrypter<T>
|
||||||
|
|
@ -171,7 +175,7 @@ where
|
||||||
T: BoringAead,
|
T: BoringAead,
|
||||||
{
|
{
|
||||||
fn decrypt(
|
fn decrypt(
|
||||||
&self,
|
&mut self,
|
||||||
mut m: cipher::OpaqueMessage,
|
mut m: cipher::OpaqueMessage,
|
||||||
seq: u64,
|
seq: u64,
|
||||||
) -> Result<cipher::PlainMessage, rustls::Error> {
|
) -> Result<cipher::PlainMessage, rustls::Error> {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ pub static ECDHE_ECDSA_AES128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite {
|
||||||
common: rustls::CipherSuiteCommon {
|
common: rustls::CipherSuiteCommon {
|
||||||
suite: rustls::CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
suite: rustls::CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
hash_provider: hash::SHA256,
|
hash_provider: hash::SHA256,
|
||||||
|
confidentiality_limit: 1 << 23,
|
||||||
|
integrity_limit: 1 << 52,
|
||||||
},
|
},
|
||||||
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
|
||||||
prf_provider: &PRF_SHA256,
|
prf_provider: &PRF_SHA256,
|
||||||
|
|
@ -37,6 +39,8 @@ pub static ECDHE_RSA_AES128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite {
|
||||||
common: rustls::CipherSuiteCommon {
|
common: rustls::CipherSuiteCommon {
|
||||||
suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
hash_provider: hash::SHA256,
|
hash_provider: hash::SHA256,
|
||||||
|
confidentiality_limit: 1 << 23,
|
||||||
|
integrity_limit: 1 << 52,
|
||||||
},
|
},
|
||||||
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
|
||||||
prf_provider: &PRF_SHA256,
|
prf_provider: &PRF_SHA256,
|
||||||
|
|
@ -48,6 +52,8 @@ pub static ECDHE_ECDSA_AES256_GCM_SHA384: Tls12CipherSuite = Tls12CipherSuite {
|
||||||
common: rustls::CipherSuiteCommon {
|
common: rustls::CipherSuiteCommon {
|
||||||
suite: rustls::CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
suite: rustls::CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
hash_provider: hash::SHA384,
|
hash_provider: hash::SHA384,
|
||||||
|
confidentiality_limit: 1 << 23,
|
||||||
|
integrity_limit: 1 << 52,
|
||||||
},
|
},
|
||||||
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
|
||||||
prf_provider: &PRF_SHA384,
|
prf_provider: &PRF_SHA384,
|
||||||
|
|
@ -59,6 +65,8 @@ pub static ECDHE_RSA_AES256_GCM_SHA384: Tls12CipherSuite = Tls12CipherSuite {
|
||||||
common: rustls::CipherSuiteCommon {
|
common: rustls::CipherSuiteCommon {
|
||||||
suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
hash_provider: hash::SHA384,
|
hash_provider: hash::SHA384,
|
||||||
|
confidentiality_limit: 1 << 23,
|
||||||
|
integrity_limit: 1 << 52,
|
||||||
},
|
},
|
||||||
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
|
||||||
prf_provider: &PRF_SHA384,
|
prf_provider: &PRF_SHA384,
|
||||||
|
|
@ -70,6 +78,8 @@ pub static ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12Ci
|
||||||
common: rustls::CipherSuiteCommon {
|
common: rustls::CipherSuiteCommon {
|
||||||
suite: rustls::CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
suite: rustls::CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
hash_provider: hash::SHA256,
|
hash_provider: hash::SHA256,
|
||||||
|
confidentiality_limit: u64::MAX,
|
||||||
|
integrity_limit: 1 << 36,
|
||||||
},
|
},
|
||||||
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
|
||||||
prf_provider: &PRF_SHA256,
|
prf_provider: &PRF_SHA256,
|
||||||
|
|
@ -81,6 +91,8 @@ pub static ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12Ciph
|
||||||
common: rustls::CipherSuiteCommon {
|
common: rustls::CipherSuiteCommon {
|
||||||
suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
hash_provider: hash::SHA256,
|
hash_provider: hash::SHA256,
|
||||||
|
confidentiality_limit: u64::MAX,
|
||||||
|
integrity_limit: 1 << 36,
|
||||||
},
|
},
|
||||||
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
|
||||||
prf_provider: &PRF_SHA256,
|
prf_provider: &PRF_SHA256,
|
||||||
|
|
|
||||||
|
|
@ -6,26 +6,35 @@ pub static AES_128_GCM_SHA256: Tls13CipherSuite = Tls13CipherSuite {
|
||||||
common: rustls::CipherSuiteCommon {
|
common: rustls::CipherSuiteCommon {
|
||||||
suite: rustls::CipherSuite::TLS13_AES_128_GCM_SHA256,
|
suite: rustls::CipherSuite::TLS13_AES_128_GCM_SHA256,
|
||||||
hash_provider: hash::SHA256,
|
hash_provider: hash::SHA256,
|
||||||
|
confidentiality_limit: 1 << 23,
|
||||||
|
integrity_limit: 1 << 52,
|
||||||
},
|
},
|
||||||
hkdf_provider: &hkdf::Hkdf::<hkdf::Sha256>::DEFAULT,
|
hkdf_provider: &hkdf::Hkdf::<hkdf::Sha256>::DEFAULT,
|
||||||
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
|
||||||
|
quic: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static AES_256_GCM_SHA384: Tls13CipherSuite = Tls13CipherSuite {
|
pub static AES_256_GCM_SHA384: Tls13CipherSuite = Tls13CipherSuite {
|
||||||
common: rustls::CipherSuiteCommon {
|
common: rustls::CipherSuiteCommon {
|
||||||
suite: rustls::CipherSuite::TLS13_AES_256_GCM_SHA384,
|
suite: rustls::CipherSuite::TLS13_AES_256_GCM_SHA384,
|
||||||
hash_provider: hash::SHA384,
|
hash_provider: hash::SHA384,
|
||||||
|
confidentiality_limit: 1 << 23,
|
||||||
|
integrity_limit: 1 << 52,
|
||||||
},
|
},
|
||||||
hkdf_provider: &hkdf::Hkdf::<hkdf::Sha384>::DEFAULT,
|
hkdf_provider: &hkdf::Hkdf::<hkdf::Sha384>::DEFAULT,
|
||||||
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
|
||||||
|
quic: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static CHACHA20_POLY1305_SHA256: Tls13CipherSuite = Tls13CipherSuite {
|
pub static CHACHA20_POLY1305_SHA256: Tls13CipherSuite = Tls13CipherSuite {
|
||||||
common: rustls::CipherSuiteCommon {
|
common: rustls::CipherSuiteCommon {
|
||||||
suite: rustls::CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
|
suite: rustls::CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
|
||||||
hash_provider: hash::SHA256,
|
hash_provider: hash::SHA256,
|
||||||
|
confidentiality_limit: u64::MAX,
|
||||||
|
integrity_limit: 1 << 36,
|
||||||
},
|
},
|
||||||
|
|
||||||
hkdf_provider: &hkdf::Hkdf::<hkdf::Sha256>::DEFAULT,
|
hkdf_provider: &hkdf::Hkdf::<hkdf::Sha256>::DEFAULT,
|
||||||
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
|
||||||
|
quic: None,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use tokio::{
|
||||||
use boring_rustls_provider::{tls12, tls13, PROVIDER};
|
use boring_rustls_provider::{tls12, tls13, PROVIDER};
|
||||||
use rustls::{
|
use rustls::{
|
||||||
version::{TLS12, TLS13},
|
version::{TLS12, TLS13},
|
||||||
ServerConfig, SupportedCipherSuite,
|
ClientConfig, ServerConfig, SupportedCipherSuite,
|
||||||
};
|
};
|
||||||
use rustls_pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
|
use rustls_pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
|
|
@ -28,7 +28,7 @@ async fn test_tls13_crypto() {
|
||||||
];
|
];
|
||||||
|
|
||||||
for cipher in ciphers {
|
for cipher in ciphers {
|
||||||
let config = rustls::ClientConfig::builder_with_provider(PROVIDER)
|
let config = ClientConfig::builder_with_provider(PROVIDER)
|
||||||
.with_cipher_suites(&[cipher])
|
.with_cipher_suites(&[cipher])
|
||||||
.with_safe_default_kx_groups()
|
.with_safe_default_kx_groups()
|
||||||
.with_protocol_versions(&[&TLS13])
|
.with_protocol_versions(&[&TLS13])
|
||||||
|
|
@ -36,22 +36,7 @@ async fn test_tls13_crypto() {
|
||||||
.with_root_certificates(root_store.clone())
|
.with_root_certificates(root_store.clone())
|
||||||
.with_no_client_auth();
|
.with_no_client_auth();
|
||||||
|
|
||||||
let listener = new_listener().await;
|
do_exchange(config, server_config.clone()).await;
|
||||||
let addr = listener.local_addr().unwrap();
|
|
||||||
tokio::spawn(spawn_echo_server(listener, server_config.clone()));
|
|
||||||
|
|
||||||
let connector = TlsConnector::from(Arc::new(config));
|
|
||||||
let stream = TcpStream::connect(&addr).await.unwrap();
|
|
||||||
|
|
||||||
let mut stream = connector
|
|
||||||
.connect(rustls::ServerName::try_from("localhost").unwrap(), stream)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
stream.write_all(b"HELLO").await.unwrap();
|
|
||||||
let mut buf = Vec::new();
|
|
||||||
let bytes = stream.read_to_end(&mut buf).await.unwrap();
|
|
||||||
assert_eq!(&buf[..bytes], b"HELLO");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,7 +54,7 @@ async fn test_tls12_ec_crypto() {
|
||||||
];
|
];
|
||||||
|
|
||||||
for cipher in ciphers {
|
for cipher in ciphers {
|
||||||
let config = rustls::ClientConfig::builder_with_provider(PROVIDER)
|
let config = ClientConfig::builder_with_provider(PROVIDER)
|
||||||
.with_cipher_suites(&[cipher])
|
.with_cipher_suites(&[cipher])
|
||||||
.with_safe_default_kx_groups()
|
.with_safe_default_kx_groups()
|
||||||
.with_protocol_versions(&[&TLS12])
|
.with_protocol_versions(&[&TLS12])
|
||||||
|
|
@ -77,22 +62,7 @@ async fn test_tls12_ec_crypto() {
|
||||||
.with_root_certificates(root_store.clone())
|
.with_root_certificates(root_store.clone())
|
||||||
.with_no_client_auth();
|
.with_no_client_auth();
|
||||||
|
|
||||||
let listener = new_listener().await;
|
do_exchange(config, server_config.clone()).await;
|
||||||
let addr = listener.local_addr().unwrap();
|
|
||||||
tokio::spawn(spawn_echo_server(listener, server_config.clone()));
|
|
||||||
|
|
||||||
let connector = TlsConnector::from(Arc::new(config));
|
|
||||||
let stream = TcpStream::connect(&addr).await.unwrap();
|
|
||||||
|
|
||||||
let mut stream = connector
|
|
||||||
.connect(rustls::ServerName::try_from("localhost").unwrap(), stream)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
stream.write_all(b"HELLO").await.unwrap();
|
|
||||||
let mut buf = Vec::new();
|
|
||||||
let bytes = stream.read_to_end(&mut buf).await.unwrap();
|
|
||||||
assert_eq!(&buf[..bytes], b"HELLO");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,7 +80,7 @@ async fn test_tls12_rsa_crypto() {
|
||||||
];
|
];
|
||||||
|
|
||||||
for cipher in ciphers {
|
for cipher in ciphers {
|
||||||
let config = rustls::ClientConfig::builder_with_provider(PROVIDER)
|
let config = ClientConfig::builder_with_provider(PROVIDER)
|
||||||
.with_cipher_suites(&[cipher])
|
.with_cipher_suites(&[cipher])
|
||||||
.with_safe_default_kx_groups()
|
.with_safe_default_kx_groups()
|
||||||
.with_protocol_versions(&[&TLS12])
|
.with_protocol_versions(&[&TLS12])
|
||||||
|
|
@ -118,22 +88,7 @@ async fn test_tls12_rsa_crypto() {
|
||||||
.with_root_certificates(root_store.clone())
|
.with_root_certificates(root_store.clone())
|
||||||
.with_no_client_auth();
|
.with_no_client_auth();
|
||||||
|
|
||||||
let listener = new_listener().await;
|
do_exchange(config, server_config.clone()).await;
|
||||||
let addr = listener.local_addr().unwrap();
|
|
||||||
tokio::spawn(spawn_echo_server(listener, server_config.clone()));
|
|
||||||
|
|
||||||
let connector = TlsConnector::from(Arc::new(config));
|
|
||||||
let stream = TcpStream::connect(&addr).await.unwrap();
|
|
||||||
|
|
||||||
let mut stream = connector
|
|
||||||
.connect(rustls::ServerName::try_from("localhost").unwrap(), stream)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
stream.write_all(b"HELLO").await.unwrap();
|
|
||||||
let mut buf = Vec::new();
|
|
||||||
let bytes = stream.read_to_end(&mut buf).await.unwrap();
|
|
||||||
assert_eq!(&buf[..bytes], b"HELLO");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,6 +96,28 @@ async fn new_listener() -> TcpListener {
|
||||||
TcpListener::bind("localhost:0").await.unwrap()
|
TcpListener::bind("localhost:0").await.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn do_exchange(config: ClientConfig, server_config: Arc<ServerConfig>) {
|
||||||
|
let listener = new_listener().await;
|
||||||
|
let addr = listener.local_addr().unwrap();
|
||||||
|
tokio::spawn(spawn_echo_server(listener, server_config.clone()));
|
||||||
|
|
||||||
|
let connector = TlsConnector::from(Arc::new(config));
|
||||||
|
let stream = TcpStream::connect(&addr).await.unwrap();
|
||||||
|
|
||||||
|
let mut stream = connector
|
||||||
|
.connect(
|
||||||
|
rustls_pki_types::ServerName::try_from("localhost").unwrap(),
|
||||||
|
stream,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
stream.write_all(b"HELLO").await.unwrap();
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
let bytes = stream.read_to_end(&mut buf).await.unwrap();
|
||||||
|
assert_eq!(&buf[..bytes], b"HELLO");
|
||||||
|
}
|
||||||
|
|
||||||
async fn spawn_echo_server(listener: TcpListener, config: Arc<ServerConfig>) {
|
async fn spawn_echo_server(listener: TcpListener, config: Arc<ServerConfig>) {
|
||||||
let acceptor = TlsAcceptor::from(config);
|
let acceptor = TlsAcceptor::from(config);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue