diff --git a/Cargo.lock b/Cargo.lock
index 3f16950..aa4e467 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -62,6 +62,7 @@ dependencies = [
"aquatic_common",
"mio",
"native-tls",
+ "serde",
]
[[package]]
diff --git a/aquatic_common_tcp/Cargo.toml b/aquatic_common_tcp/Cargo.toml
index f9d3d0d..f24dae0 100644
--- a/aquatic_common_tcp/Cargo.toml
+++ b/aquatic_common_tcp/Cargo.toml
@@ -12,4 +12,5 @@ name = "aquatic_common_tcp"
anyhow = "1"
aquatic_common = { path = "../aquatic_common" }
mio = { version = "0.7", features = ["tcp", "os-poll", "os-util"] }
-native-tls = "0.2"
\ No newline at end of file
+native-tls = "0.2"
+serde = { version = "1", features = ["derive"] }
\ No newline at end of file
diff --git a/aquatic_common_tcp/src/config.rs b/aquatic_common_tcp/src/config.rs
index e69de29..8cd23e3 100644
--- a/aquatic_common_tcp/src/config.rs
+++ b/aquatic_common_tcp/src/config.rs
@@ -0,0 +1,106 @@
+use serde::{Serialize, Deserialize};
+
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+pub enum LogLevel {
+ Off,
+ Error,
+ Warn,
+ Info,
+ Debug,
+ Trace
+}
+
+
+impl Default for LogLevel {
+ fn default() -> Self {
+ Self::Error
+ }
+}
+
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(default)]
+pub struct HandlerConfig {
+ /// Maximum number of requests to receive from channel before locking
+ /// mutex and starting work
+ pub max_requests_per_iter: usize,
+ pub channel_recv_timeout_microseconds: u64,
+}
+
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(default)]
+pub struct TlsConfig {
+ pub use_tls: bool,
+ pub tls_pkcs12_path: String,
+ pub tls_pkcs12_password: String,
+}
+
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(default)]
+pub struct CleaningConfig {
+ /// Clean peers this often (seconds)
+ pub interval: u64,
+ /// Remove peers that haven't announced for this long (seconds)
+ pub max_peer_age: u64,
+ /// Remove connections that are older than this (seconds)
+ pub max_connection_age: u64,
+}
+
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(default)]
+pub struct PrivilegeConfig {
+ /// Chroot and switch user after binding to sockets
+ pub drop_privileges: bool,
+ /// Chroot to this path
+ pub chroot_path: String,
+ /// User to switch to after chrooting
+ pub user: String,
+}
+
+
+impl Default for HandlerConfig {
+ fn default() -> Self {
+ Self {
+ max_requests_per_iter: 10000,
+ channel_recv_timeout_microseconds: 200,
+ }
+ }
+}
+
+
+impl Default for TlsConfig {
+ fn default() -> Self {
+ Self {
+ use_tls: false,
+ tls_pkcs12_path: "".into(),
+ tls_pkcs12_password: "".into(),
+ }
+ }
+}
+
+
+impl Default for CleaningConfig {
+ fn default() -> Self {
+ Self {
+ interval: 30,
+ max_peer_age: 180,
+ max_connection_age: 180,
+ }
+ }
+}
+
+
+impl Default for PrivilegeConfig {
+ fn default() -> Self {
+ Self {
+ drop_privileges: false,
+ chroot_path: ".".to_string(),
+ user: "nobody".to_string(),
+ }
+ }
+}
\ No newline at end of file
diff --git a/aquatic_common_tcp/src/network/mod.rs b/aquatic_common_tcp/src/network/mod.rs
index bb01fe9..0915833 100644
--- a/aquatic_common_tcp/src/network/mod.rs
+++ b/aquatic_common_tcp/src/network/mod.rs
@@ -1 +1,35 @@
-pub mod stream;
\ No newline at end of file
+pub mod stream;
+
+use std::fs::File;
+use std::io::Read;
+
+use anyhow::Context;
+use native_tls::{Identity, TlsAcceptor};
+
+use crate::config::TlsConfig;
+
+
+pub fn create_tls_acceptor(
+ config: &TlsConfig,
+) -> anyhow::Result