Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 8 additions & 10 deletions kissmp-bridge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,19 @@ kissmp-server = { path = "../kissmp-server" }
bincode = "1.3"
serde = { version = "1.0", features = ["derive"] }
serde_json="1.0"
futures = "0.3.5"
quinn = "0.7.1"
# Held back due to rustls using webpki 0.21
webpki = "0.21"
anyhow = "1.0.32"
futures = "0.3"
quinn = "0.8"
anyhow = "1.0"
reqwest = { version = "0.11", default-features = false, features=["rustls-tls"] }
tiny_http="0.8"
tiny_http="0.11"
tokio-stream="0.1.5"
rustls = { version = "0.19", features = ["dangerous_configuration"] }
rustls = { version = "0.20", features = ["dangerous_configuration"] }
tokio = { version = "1.4", features = ["time", "macros", "sync", "io-util", "net"] }
discord-rpc-client = {version = "0.3", optional = true}
percent-encoding = "2.1"
audiopus = "0.2"
rodio = "0.14"
rodio = "0.15"
cpal = "0.13"
fon = "0.5.0"
fon = "0.6"
log = "0.4"
indoc = "1.0"
indoc = "1.0"
67 changes: 35 additions & 32 deletions kissmp-bridge/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod voice_chat;

use futures::stream::FuturesUnordered;
use futures::{StreamExt};
use std::convert::TryInto;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, WriteHalf};
use tokio::net::{TcpListener, TcpStream};
Expand Down Expand Up @@ -86,39 +87,39 @@ async fn main() {
}
}

fn build_quinn_client_config() -> quinn::ClientConfig {
use std::sync::Arc;

let client_crypto_config = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_custom_certificate_verifier(Arc::new(AcceptAnyCertificate))
.with_no_client_auth();

let mut c = quinn::ClientConfig::new(Arc::new(client_crypto_config));
Arc::get_mut(&mut c.transport)
.unwrap()
.max_idle_timeout(Some(SERVER_IDLE_TIMEOUT.try_into().unwrap()));

c
}

async fn connect_to_server(
addr: SocketAddr,
client_stream: TcpStream,
discord_tx: std::sync::mpsc::Sender<DiscordState>
) -> () {
let endpoint = {
let mut client_cfg = quinn::ClientConfig::default();

let mut transport = quinn::TransportConfig::default();
transport
.max_idle_timeout(Some(SERVER_IDLE_TIMEOUT))
.unwrap();
client_cfg.transport = std::sync::Arc::new(transport);

let tls_cfg = std::sync::Arc::get_mut(&mut client_cfg.crypto).unwrap();
tls_cfg
.dangerous()
.set_certificate_verifier(std::sync::Arc::new(AcceptAnyCertificate));

let mut endpoint = quinn::Endpoint::builder();
endpoint.default_client_config(client_cfg);

let bind_from = match addr {
SocketAddr::V4(_) => IpAddr::from(Ipv4Addr::UNSPECIFIED),
SocketAddr::V6(_) => IpAddr::from(Ipv6Addr::UNSPECIFIED),
};
let mut endpoint = quinn::Endpoint::client(match addr {
SocketAddr::V4(_) => SocketAddr::new(IpAddr::from(Ipv4Addr::UNSPECIFIED), 0),
SocketAddr::V6(_) => SocketAddr::new(IpAddr::from(Ipv6Addr::UNSPECIFIED), 0),
}).unwrap();

endpoint.set_default_client_config(build_quinn_client_config());

endpoint
.bind(&SocketAddr::new(bind_from, 0))
.unwrap().0
};

let server_connection = match endpoint.connect(&addr, "kissmp").unwrap().await {
let server_connection = match endpoint.connect(addr, "kissmp").unwrap().await {
Ok(c) => c,
Err(e) => {
error!("Failed to connect to the server: {}", e);
Expand Down Expand Up @@ -240,7 +241,7 @@ async fn client_outgoing(
async fn server_incoming(
server_commands_sender: tokio::sync::mpsc::Sender<shared::ServerCommand>,
vc_playback_sender: std::sync::mpsc::Sender<voice_chat::VoiceChatPlaybackEvent>,
server_connection: quinn::generic::NewConnection<quinn::crypto::rustls::TlsSession>
server_connection: quinn::NewConnection
) -> AHResult {
let mut reliable_commands = server_connection
.uni_streams
Expand Down Expand Up @@ -281,7 +282,7 @@ async fn server_incoming(
}

async fn client_incoming(
server_stream: quinn::generic::Connection<quinn::crypto::rustls::TlsSession>,
server_stream: quinn::Connection,
vc_playback_sender: std::sync::mpsc::Sender<voice_chat::VoiceChatPlaybackEvent>,
mut client_stream_reader: tokio::io::ReadHalf<TcpStream>,
vc_recording_sender: std::sync::mpsc::Sender<voice_chat::VoiceChatRecordingEvent>,
Expand Down Expand Up @@ -325,7 +326,7 @@ async fn client_incoming(
}

async fn server_outgoing(
server_stream: quinn::generic::Connection<quinn::crypto::rustls::TlsSession>,
server_stream: quinn::Connection,
mut client_event_receiver: tokio::sync::mpsc::UnboundedReceiver<(bool, shared::ClientCommand)>
) -> AHResult {
while let Some((reliable, client_command)) = client_event_receiver.recv().await {
Expand All @@ -342,14 +343,16 @@ async fn server_outgoing(

struct AcceptAnyCertificate;

impl rustls::ServerCertVerifier for AcceptAnyCertificate {
impl rustls::client::ServerCertVerifier for AcceptAnyCertificate {
fn verify_server_cert(
&self,
_roots: &rustls::RootCertStore,
_presented_certs: &[rustls::Certificate],
_dns_name: webpki::DNSNameRef,
_end_entity: &rustls::Certificate,
_intermediates: &[rustls::Certificate],
_server_name: &rustls::ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
) -> Result<rustls::ServerCertVerified, rustls::TLSError> {
Ok(rustls::ServerCertVerified::assertion())
_now: std::time::SystemTime,
) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
Ok(rustls::client::ServerCertVerified::assertion())
}
}
4 changes: 2 additions & 2 deletions kissmp-bridge/src/voice_chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ pub fn encode_and_send_samples(
.map(|x| x[0])
.collect();
if sample_rate.0 != SAMPLE_RATE.0 {
let audio = fon::Audio::<fon::mono::Mono16>::with_i16_buffer(sample_rate.0, data);
let mut audio = fon::Audio::<fon::mono::Mono16>::with_stream(SAMPLE_RATE.0, &audio);
let audio = fon::Audio::<fon::chan::Ch16, 1>::with_i16_buffer(sample_rate.0, data);
let mut audio = fon::Audio::<fon::chan::Ch16, 1>::with_audio(SAMPLE_RATE.0, &audio);
audio.as_i16_slice().to_vec()
} else {
data
Expand Down
6 changes: 3 additions & 3 deletions kissmp-master/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ edition = "2018"
[dependencies]
shared = { path = "../shared" }
#tide = "0.15.0"
warp = "0.2"
warp = "0.3"
serde_json="1.0"
censor = "0.1.1"
tokio={version = "0.2", features = ["rt-threaded", "macros", "net"]}
censor = "0.2"
tokio={version = "1.20", features = ["rt", "rt-multi-thread", "macros", "net"]}
#async-std = { version = "1.8.0", features = ["attributes"] }
serde = { version = "1.0", features = ["derive"] }
34 changes: 17 additions & 17 deletions kissmp-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,28 @@ edition = "2018"

[dependencies]
shared = { path = "../shared" }
rand = "0.7.3"
rand = "0.8"
serde_json="1.0"
bincode="1.3.1"
rmp="0.8.9"
rmp-serde="0.14.4"
futures = "0.3.13"
quinn = "0.7.1"
anyhow = "1.0.32"
rlua = "0.17.0"
notify = "4.0.15"
tokio-util = {version = "0.6.5", features = ["codec"]}
bincode="1.3"
rmp="0.8"
rmp-serde="1.1"
futures = "0.3"
quinn = "0.8"
rustls = "0.20"
anyhow = "1.0"
rlua = "0.19"
notify = "4.0"
tokio-util = {version = "0.7", features = ["codec"]}
serde = { version = "1.0", features = ["derive"] }
reqwest = { version = "0.11.2", default-features = false, features=["rustls-tls"] }
rcgen = { version = "0.8.2", default-features = false }
reqwest = { version = "0.11", default-features = false, features=["rustls-tls"] }
rcgen = { version = "0.9", default-features = false }
tokio = { version = "1.4", features = ["rt-multi-thread", "time", "macros", "sync", "io-util", "io-std", "fs"] }
tokio-stream = "0.1.5"
dirs = "3.0"
tokio-stream = "0.1"
dirs = "4.0"
igd = { git = "https://github.com/stevefan1999-personal/rust-igd.git", rev = "c2d1f83" }
ifcfg = "0.1.2"
ifcfg = "0.1"
async-ctrlc = "1.2"
ipnetwork = "0.18"
log = "0.4"

[target.'cfg(unix)'.dependencies]
steamlocate = "1.0"
steamlocate = "1.0"
2 changes: 1 addition & 1 deletion kissmp-server/src/file_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub async fn transfer_file(
.unwrap(),
)
.await?;
stream.finish();
stream.finish().await;
chunk_n += 1;
}
Ok(())
Expand Down
58 changes: 37 additions & 21 deletions kissmp-server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#[recursion_limit = "1024"]

use ipnetwork::Ipv4Network;
use shared::vehicle;

pub mod config;
Expand All @@ -19,13 +18,14 @@ use vehicle::*;
use anyhow::{Error, Context};
use futures::FutureExt;
use futures::{select, StreamExt, TryStreamExt};
use quinn::{Certificate, CertificateChain, PrivateKey};
use std::collections::HashMap;
use std::convert::TryInto;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::time::Duration;
use tokio::sync::mpsc;
use tokio_stream::wrappers::{IntervalStream, ReceiverStream};
use log::{info, warn, error};
const CLIENT_IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(60);

#[derive(Clone)]
pub struct Connection {
Expand Down Expand Up @@ -88,6 +88,26 @@ pub struct Server {
tick: u64,
}

fn build_quinn_server_config(
certificate_chain: Vec<rustls::Certificate>,
private_key: rustls::PrivateKey
) -> quinn::ServerConfig {
use std::sync::Arc;

let server_crypto_config = rustls::ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(certificate_chain, private_key)
.expect("bad certificate/key for server");

let mut c = quinn::ServerConfig::with_crypto(Arc::new(server_crypto_config));
Arc::get_mut(&mut c.transport)
.unwrap()
.max_idle_timeout(Some(CLIENT_IDLE_TIMEOUT.try_into().unwrap()));

c
}

impl Server {
pub fn from_config(config: config::Config) -> Self {
let (lua, receiver) = lua::setup_lua();
Expand Down Expand Up @@ -152,29 +172,24 @@ impl Server {
warn!("uPnP mapping failed.");
}
}
let socket = UdpSocket::bind(&addr).unwrap();
let mut ticks = IntervalStream::new(tokio::time::interval(
std::time::Duration::from_secs(1) / self.tickrate as u32,
))
.fuse();

let mut send_info_ticks =
IntervalStream::new(tokio::time::interval(std::time::Duration::from_secs(5))).fuse();

let (certificate_chain, key) = generate_certificate();

let mut server_config = quinn::ServerConfigBuilder::default();
server_config.certificate(certificate_chain, key).unwrap();
let mut server_config = server_config.build();
let server_config = build_quinn_server_config(certificate_chain, key);

let mut transport = quinn::TransportConfig::default();
transport
.max_idle_timeout(Some(std::time::Duration::from_secs(60)))
.unwrap();
server_config.transport = std::sync::Arc::new(transport);
// TODO: multiple binds (for IPv4/6 configurations, or servers with multiple interfaces)

let mut endpoint = quinn::Endpoint::builder();
endpoint.listen(server_config);
let (_, incoming) = endpoint.with_socket(socket).unwrap();
let (_, incoming) = quinn::Endpoint::server(
server_config,
addr
).unwrap();

let (client_events_tx, client_events_rx) = mpsc::channel(128);
let mut client_events_rx = ReceiverStream::new(client_events_rx).fuse();
Expand Down Expand Up @@ -431,7 +446,7 @@ impl Server {
async fn drive_receive(
id: u32,
streams: quinn::IncomingUniStreams,
datagrams: quinn::generic::Datagrams<quinn::crypto::rustls::TlsSession>,
datagrams: quinn::Datagrams,
mut client_events_tx: mpsc::Sender<(u32, IncomingEvent)>,
) -> anyhow::Result<()> {
let mut cmds = streams
Expand Down Expand Up @@ -527,14 +542,15 @@ impl Drop for Server {
}
}

fn generate_certificate() -> (CertificateChain, PrivateKey) {
fn generate_certificate() -> (Vec<rustls::Certificate>, rustls::PrivateKey) {
info!("Generating certificate...");
let cert = rcgen::generate_simple_self_signed(vec!["kissmp".into()]).unwrap();
let key = cert.serialize_private_key_der();
let cert = cert.serialize_der().unwrap();
let self_signed_certificate = rcgen::generate_simple_self_signed(vec!["kissmp".into()]).unwrap();
let certificate = rustls::Certificate(self_signed_certificate.serialize_der().unwrap());
let private_key = rustls::PrivateKey(self_signed_certificate.serialize_private_key_der());
let cert_chain = vec![certificate];
(
CertificateChain::from_certs(Certificate::from_der(&cert)),
PrivateKey::from_der(&key).unwrap(),
cert_chain,
private_key,
)
}

Expand Down
6 changes: 3 additions & 3 deletions shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ edition = "2018"
[dependencies]
anyhow="1.0"
serde_json="1.0"
bincode="1.3.1"
rmp="0.8.9"
rmp-serde="0.14.4"
bincode="1.3"
rmp="0.8"
rmp-serde="1.1"
serde = { version = "1.0", features = ["derive"] }
pretty_env_logger = "0.4"
chrono = "0.4"
Expand Down