Browse Source

lox_auth now listens for connections, performs a function

Vecna 3 years ago
parent
commit
bd31dfe666
3 changed files with 71 additions and 1 deletions
  1. 2 0
      Cargo.toml
  2. 17 1
      src/bin/lox_auth.rs
  3. 52 0
      src/server_net.rs

+ 2 - 0
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"] }

+ 17 - 1
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::<String>() + "\n"
 }

+ 52 - 0
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");
+            }
+        });
+    }
+}