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