diff options
| author | BigBrotherNii <nicochr1004@gmail.com> | 2024-07-16 23:47:51 +0200 | 
|---|---|---|
| committer | BigBrotherNii <nicochr1004@gmail.com> | 2024-07-16 23:47:51 +0200 | 
| commit | cd679169f8e049b3f3ce890c97d62fa72a4e4eb5 (patch) | |
| tree | 4efaf40f3c818d79be881f81b7d8fa254861731d /pixel-client/src/network.rs | |
| parent | 2f9e2758199ff5148d7f90478be45aa122d6c860 (diff) | |
| parent | df418c0d3fec83fc1cbe0dabc6d4b9dfbdbcbabb (diff) | |
| download | hurrycurry-cd679169f8e049b3f3ce890c97d62fa72a4e4eb5.tar hurrycurry-cd679169f8e049b3f3ce890c97d62fa72a4e4eb5.tar.bz2 hurrycurry-cd679169f8e049b3f3ce890c97d62fa72a4e4eb5.tar.zst  | |
trying to merch qwq
Diffstat (limited to 'pixel-client/src/network.rs')
| -rw-r--r-- | pixel-client/src/network.rs | 123 | 
1 files changed, 123 insertions, 0 deletions
diff --git a/pixel-client/src/network.rs b/pixel-client/src/network.rs new file mode 100644 index 00000000..ed160773 --- /dev/null +++ b/pixel-client/src/network.rs @@ -0,0 +1,123 @@ +/* +    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 <https://www.gnu.org/licenses/>. + +*/ +use anyhow::Result; +use hurrycurry_protocol::{PacketC, PacketS, BINCODE_CONFIG}; +use log::{debug, warn}; +use std::{collections::VecDeque, net::TcpStream}; +use tungstenite::{ +    client::{uri_mode, IntoClientRequest}, +    client_tls_with_config, +    handshake::client::Request, +    stream::{MaybeTlsStream, Mode}, +    util::NonBlockingError, +    Message, WebSocket, +}; + +pub struct Network { +    sock: WebSocket<MaybeTlsStream<TcpStream>>, +    pub queue_in: VecDeque<PacketC>, +    pub queue_out: VecDeque<PacketS>, +} + +impl Network { +    pub fn connect(addr: &str) -> Result<Self> { +        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, +            }); +        let stream = TcpStream::connect((host, port))?; +        stream.set_nodelay(true).unwrap(); + +        let (mut sock, _) = client_tls_with_config(request, stream, None, None).unwrap(); + +        match sock.get_mut() { +            MaybeTlsStream::Plain(s) => s.set_nonblocking(true).unwrap(), +            MaybeTlsStream::Rustls(s) => s.sock.set_nonblocking(true).unwrap(), +            _ => todo!(), +        }; + +        Ok(Self { +            sock, +            queue_in: VecDeque::new(), +            queue_out: VecDeque::new(), +        }) +    } +    pub fn poll(&mut self) { +        loop { +            self.queue_in.extend(match self.sock.read() { +                Ok(Message::Text(packet)) => match serde_json::from_str(&packet) { +                    Ok(packet) => { +                        debug!("<- {packet:?}"); +                        Some(packet) +                    } +                    Err(e) => { +                        warn!("invalid json packet: {e:?}"); +                        None +                    } +                }, +                Ok(Message::Binary(packet)) => { +                    match bincode::decode_from_slice(&packet, BINCODE_CONFIG) { +                        Ok((packet, _)) => { +                            debug!("<- {packet:?}"); +                            Some(packet) +                        } +                        Err(e) => { +                            warn!("invalid bincode packet: {e:?}"); +                            None +                        } +                    } +                } +                Ok(_) => None, +                Err(e) => { +                    if let Some(e) = e.into_non_blocking() { +                        warn!("{e:?}"); +                        None +                    } else { +                        break; +                    } +                } +            }); +        } + +        for packet in self.queue_out.drain(..) { +            debug!("-> {packet:?}"); +            self.sock +                .write(Message::Text(serde_json::to_string(&packet).unwrap())) +                .unwrap(); +        } + +        self.sock.flush().unwrap(); +    } +}  |