From bd31dfe666c9495c9491ae2e7ae72dfaaed720ac Mon Sep 17 00:00:00 2001 From: Vecna Date: Sat, 14 Jan 2023 13:57:38 -0500 Subject: [PATCH] lox_auth now listens for connections, performs a function --- Cargo.toml | 2 ++ src/bin/lox_auth.rs | 18 +++++++++++++++- src/server_net.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/server_net.rs diff --git a/Cargo.toml b/Cargo.toml index 7d25edd..0fff586 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,5 @@ lox = { git = "https://git-crysp.uwaterloo.ca/iang/lox.git", branch = "vvecna/lo ed25519-dalek = { version = "1", features = ["serde"] } serde = "1" serde_json = "1.0" +# TODO: reduce feature set to just the ones needed +tokio = { version = "1.20", features = ["full"] } diff --git a/src/bin/lox_auth.rs b/src/bin/lox_auth.rs index 9bf0467..943cd22 100644 --- a/src/bin/lox_auth.rs +++ b/src/bin/lox_auth.rs @@ -1,13 +1,23 @@ +// This seems like probably not the best way to do this, but it works. +#[path = "../server_net.rs"] +mod server_net; +use crate::server_net::listen; + use lox::BridgeAuth; +use std::env::args; use std::fs::File; use std::io::Write; use std::path::Path; -fn main() { +#[tokio::main] +async fn main() { let bridgedb_pubkey_filename = "bridgedb_pubkey.json"; let lox_auth_filename = "lox_auth.json"; let lox_auth_pubkeys_filename = "lox_auth_pubkeys.json"; + // network address to listen on, e.g., localhost:8080 + let addr = args().nth(1).unwrap(); + // import bridgedb pubkey // note: currently no checks for valid data let bridgedb_pubkey_infile = File::open(bridgedb_pubkey_filename).unwrap(); @@ -54,4 +64,10 @@ fn main() { ) .expect("Failed to write to lox_auth pubkeys file"); } + + listen(addr, reverse_string).await; +} + +fn reverse_string(str: String) -> String { + str.trim().chars().rev().collect::() + "\n" } diff --git a/src/server_net.rs b/src/server_net.rs new file mode 100644 index 0000000..1edb4ac --- /dev/null +++ b/src/server_net.rs @@ -0,0 +1,52 @@ +/*! The networking methods for our server components to call. In +particular, this file provides a listen() methods to handle creating +a server process so the other code doesn't need to care about how +these work. */ + +// This file is based on tokio's echo.rs example: +// https://github.com/tokio-rs/tokio/blob/master/examples/echo.rs + +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpListener; + +use std::str; + +pub async fn listen(addr: String, fun: fn(String) -> String) { + let listener = TcpListener::bind(&addr) + .await + .expect("Failed to create TcpListener"); + println!("Listening on: {}", addr); + + loop { + // asynchronously wait for an inbound socket + let (mut socket, _) = listener.accept().await.expect("Failed to create socket"); + + tokio::spawn(async move { + let mut buf = vec![0; 1024]; + + // read data, perform function on it, write result + loop { + let n = socket + .read(&mut buf) + .await + .expect("Failed to read data from socket"); + + if n == 0 { + return; + } + + // I think this is a problem if there's more data than fits in the buffer... + // But that's a problem for future me. + let s = str::from_utf8(&buf[0..n]) + .expect("Invalid UTF-8 sequence") + .to_string(); + let response = fun(s); + + socket + .write_all(response.as_bytes()) + .await + .expect("Failed to write data to socket"); + } + }); + } +}