/*
Hurry Curry! - a game about cooking
Copyright 2024 metamuffin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3 of the License only.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
use anyhow::Result;
use futures_util::{
stream::{SplitSink, SplitStream, StreamExt},
SinkExt, TryStreamExt,
};
use hurrycurry_protocol::{PacketC, PacketS, BINCODE_CONFIG, VERSION};
use log::{debug, info, warn};
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::{net::TcpStream, sync::RwLock};
use tokio_tungstenite::{client_async_tls_with_config, MaybeTlsStream, WebSocketStream};
use tungstenite::{
client::{uri_mode, IntoClientRequest},
http::Request,
stream::Mode,
Message,
};
pub struct Network {
sock_recv: RwLock>>>,
sock_send: RwLock>, Message>>,
use_bincode: AtomicBool,
}
impl Network {
pub async fn connect(addr: &str) -> Result {
let (parts, _) = addr.into_client_request().unwrap().into_parts();
let mut builder = Request::builder()
.uri(parts.uri.clone().clone())
.method(parts.method.clone())
.version(parts.version);
*builder.headers_mut().unwrap() = parts.headers.clone();
let request = builder.body(()).unwrap();
let host = request.uri().host().unwrap();
let host = if host.starts_with('[') {
&host[1..host.len() - 1]
} else {
host
};
let port = request
.uri()
.port_u16()
.unwrap_or(match uri_mode(request.uri())? {
Mode::Plain => 27032,
Mode::Tls => 443,
});
info!("Connecting: host={host:?} port={port}");
let stream = TcpStream::connect((host, port)).await?;
stream.set_nodelay(true).unwrap();
let (sock, _) = client_async_tls_with_config(request, stream, None, None).await?;
info!("Handshake complete.");
let (sock_send, sock_recv) = sock.split();
Ok(Self {
sock_recv: RwLock::new(sock_recv),
sock_send: RwLock::new(sock_send),
use_bincode: false.into(),
})
}
pub async fn receive(&self) -> anyhow::Result