diff --git a/ptth_handlebars/file_server_dir_entry.html b/ptth_handlebars/file_server_dir_entry.html deleted file mode 100644 index 200b99e..0000000 --- a/ptth_handlebars/file_server_dir_entry.html +++ /dev/null @@ -1,5 +0,0 @@ -
  • - -{{file_name}}{{trailing_slash}} - -
  • diff --git a/ptth_handlebars/relay_server_list.html b/ptth_handlebars/relay_server_list.html new file mode 100644 index 0000000..6dd6c4b --- /dev/null +++ b/ptth_handlebars/relay_server_list.html @@ -0,0 +1,39 @@ + + + + + +Server list + + + +

    Server list

    + +
    + +{{#if servers}} + {{#each servers}} +
    + {{this.name}} +
    + {{/each}} +{{else}} + (No servers are running) +{{/if}} + +
    + + + diff --git a/ptth_handlebars/test_relay_server_list.html b/ptth_handlebars/test_relay_server_list.html new file mode 100644 index 0000000..e1dcbe2 --- /dev/null +++ b/ptth_handlebars/test_relay_server_list.html @@ -0,0 +1,37 @@ + + + + + +Server list + + + +

    Server list

    + +
    + +
    +alice +
    + +
    +beth +
    + +
    + + + diff --git a/src/relay/mod.rs b/src/relay/mod.rs index 7841d25..c8a5da1 100644 --- a/src/relay/mod.rs +++ b/src/relay/mod.rs @@ -11,6 +11,7 @@ use std::{ }; use futures::channel::oneshot; +use handlebars::Handlebars; use hyper::{ Body, Method, @@ -20,7 +21,7 @@ use hyper::{ StatusCode, }; use hyper::service::{make_service_fn, service_fn}; - +use serde::Serialize; use tokio::{ sync::Mutex, time::delay_for, @@ -38,6 +39,7 @@ enum Message { #[derive (Default)] struct ServerState { + handlebars: Arc >, watchers: Arc >>, } @@ -186,33 +188,85 @@ async fn handle_all (req: Request , state: Arc ) }); } - if let Some (listen_code) = prefix_match (path, "/7ZSFUKGV_http_listen/") { - Ok (handle_http_listen (state, listen_code.into ()).await) + Ok (if let Some (listen_code) = prefix_match (path, "/7ZSFUKGV_http_listen/") { + handle_http_listen (state, listen_code.into ()).await } else if let Some (rest) = prefix_match (path, "/servers/") { - if let Some (idx) = rest.find ('/') { + if rest == "" { + #[derive (Serialize)] + struct ServerEntry <'a> { + path: &'a str, + name: &'a str, + } + + #[derive (Serialize)] + struct ServerListPage <'a> { + servers: Vec >, + } + + let names: Vec <_> = { + state.watchers.lock ().await.senders.iter () + .map (|(k, _)| (*k).clone ()) + .collect () + }; + + //println! ("Found {} servers", names.len ()); + + let page = ServerListPage { + servers: names.iter () + .map (|name| ServerEntry { + name: &name, + path: &name, + }) + .collect (), + }; + + let s = state.handlebars.render ("relay_server_list", &page).unwrap (); + status_reply (StatusCode::OK, s) + } + else if let Some (idx) = rest.find ('/') { let listen_code = String::from (&rest [0..idx]); let path = String::from (&rest [idx..]); let (parts, _) = req.into_parts (); - Ok (handle_http_request (parts, path, state, listen_code).await) + handle_http_request (parts, path, state, listen_code).await } else { - Ok (status_reply (StatusCode::BAD_REQUEST, "Bad URI format")) + status_reply (StatusCode::BAD_REQUEST, "Bad URI format") } } else if path == "/relay_up_check" { - Ok (status_reply (StatusCode::OK, "Relay is up\n")) + status_reply (StatusCode::OK, "Relay is up\n") } else { - Ok (status_reply (StatusCode::OK, "Hi\n")) + status_reply (StatusCode::OK, "Hi\n") + }) +} + +pub fn load_templates () +-> Result , Box > +{ + let mut handlebars = Handlebars::new (); + handlebars.set_strict_mode (true); + + for (k, v) in vec! [ + ("relay_server_list", "relay_server_list.html"), + ].into_iter () { + handlebars.register_template_file (k, format! ("ptth_handlebars/{}", v))?; } + + Ok (handlebars) } pub async fn main () -> Result <(), Box > { let addr = SocketAddr::from(([0, 0, 0, 0], 4000)); - let state = Arc::new (ServerState::default ()); + let state = ServerState { + handlebars: Arc::new (load_templates ()?), + watchers: Default::default (), + }; + + let state = Arc::new (state); let make_svc = make_service_fn (|_conn| { let state = state.clone (); diff --git a/src/relay/watcher.rs b/src/relay/watcher.rs index f8f636f..69820ed 100644 --- a/src/relay/watcher.rs +++ b/src/relay/watcher.rs @@ -58,13 +58,15 @@ impl Watchers { let id_2 = id.clone (); { let mut that = that.lock ().await; - that.add_watcher_with_id (s, id_2) + that.add_watcher_with_id (s, id_2); + //println! ("Added server {}", id); } tokio::spawn (async move { delay_for (timeout).await; let mut that = that.lock ().await; that.remove_watcher (&id); + //println! ("Removed server {}", id); }); if let Ok (message) = r.await { diff --git a/src/server/file_server.rs b/src/server/file_server.rs index 614b55b..59db7f6 100644 --- a/src/server/file_server.rs +++ b/src/server/file_server.rs @@ -285,15 +285,15 @@ pub async fn serve_all ( } pub fn load_templates () --> Result , Box > +-> Result , Box > { - let mut handlebars = handlebars::Handlebars::new (); + let mut handlebars = Handlebars::new (); + handlebars.set_strict_mode (true); for (k, v) in vec! [ - ("file_server_dir_entry", "ptth_handlebars/file_server_dir_entry.html"), - ("file_server_dir", "ptth_handlebars/file_server_dir.html"), + ("file_server_dir", "file_server_dir.html"), ].into_iter () { - handlebars.register_template_file (k, v)?; + handlebars.register_template_file (k, format! ("ptth_handlebars/{}", v))?; } Ok (handlebars) diff --git a/todo.md b/todo.md index 9186089..fe88f99 100644 --- a/todo.md +++ b/todo.md @@ -1,7 +1,6 @@ -- Offer list of clients at server root - Parameter for server URL - Parameter for static file serve path -- Parameter for sererv name +- Parameter for server name - Set up tokens or privkeys or tripcodes or something so clients can't trivially impersonate servers