oxedyne/fe2o3/fe2o3_net/src/ws/handler.rs
4.9 KiB, 16 runs
created by r1870400018:607, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | use crate::{ |
| 2 | ws::core::WebSocketMessage, |
| 3 | }; |
| 4 | |
| 5 | use oxedyne_fe2o3_core::prelude::*; |
| 6 | use oxedyne_fe2o3_iop_crypto::enc::Encrypter; |
| 7 | use oxedyne_fe2o3_iop_db::api::Database; |
| 8 | use oxedyne_fe2o3_iop_hash::api::Hasher; |
| 9 | use oxedyne_fe2o3_jdat::{ |
| 10 | id::NumIdDat, |
| 11 | }; |
| 12 | use oxedyne_fe2o3_syntax::SyntaxRef; |
| 13 | |
| 14 | use std::{ |
| 15 | sync::{ |
| 16 | Arc, |
| 17 | RwLock, |
| 18 | }, |
| 19 | }; |
| 20 | |
| 21 | use tokio::sync::broadcast; |
| 22 | |
| 23 | |
| 24 | pub trait WebSocketHandler: |
| 25 | Clone |
| 26 | + std::fmt::Debug |
| 27 | + Send |
| 28 | + Sync |
| 29 | { |
| 30 | const DEV_REFRESH_MSG: &'static str = "dev_refresh"; |
| 31 | |
| 32 | fn handle_text< |
| 33 | const UIDL: usize, |
| 34 | UID: NumIdDat<UIDL> + 'static, |
| 35 | ENC: Encrypter, |
| 36 | KH: Hasher, |
| 37 | DB: Database<UIDL, UID, ENC, KH>, |
| 38 | >( |
| 39 | &mut self, |
| 40 | txt: String, |
| 41 | db: Option<(Arc<RwLock<DB>>, UID)>, |
| 42 | syntax: SyntaxRef, |
| 43 | id: &String, |
| 44 | ) |
| 45 | -> Outcome<Option<WebSocketMessage>>; |
| 46 | |
| 47 | fn handle_binary< |
| 48 | const UIDL: usize, |
| 49 | UID: NumIdDat<UIDL> + 'static, |
| 50 | ENC: Encrypter, |
| 51 | KH: Hasher, |
| 52 | DB: Database<UIDL, UID, ENC, KH>, |
| 53 | >( |
| 54 | &mut self, |
| 55 | byts: Vec<u8>, |
| 56 | db: Option<(Arc<RwLock<DB>>, UID)>, |
| 57 | syntax: SyntaxRef, |
| 58 | id: &String, |
| 59 | ) |
| 60 | -> Outcome<Option<WebSocketMessage>>; |
| 61 | |
| 62 | fn dev_receiver(&self, id: &String) -> Outcome<Option<broadcast::Receiver<()>>> { |
| 63 | debug!("{}: No dev receiver has been defined to accept client refresh messages.", id); |
| 64 | Ok(None) |
| 65 | } |
| 66 | |
| 67 | /// Attach a per-connection session identifier to a cloned handler just |
| 68 | /// before the WebSocket handshake runs. The default implementation is |
| 69 | /// a no-op, so handlers that do not care about session state are |
| 70 | /// unaffected. Handlers that implement session-scoped commands |
| 71 | /// override this to store the id for later use inside `handle_text`. |
| 72 | fn attach_sid(self, _sid: Option<String>) -> Self |
| 73 | where |
| 74 | Self: Sized, |
| 75 | { |
| 76 | self |
| 77 | } |
| 78 | |
| 79 | /// Record, on a cloned handler just before the handshake, whether the |
| 80 | /// connection carries an authenticated operator session. The default is a |
| 81 | /// no-op returning the handler unchanged, so handlers with no operator-only |
| 82 | /// commands are unaffected. A handler that gates privileged commands on an |
| 83 | /// operator overrides this to store the flag; it must default those |
| 84 | /// commands to refused so a handler that never has this set stays closed. |
| 85 | fn with_operator_authed(self, _authed: bool) -> Self |
| 86 | where |
| 87 | Self: Sized, |
| 88 | { |
| 89 | self |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | #[derive(Clone, Debug)] |
| 94 | pub struct WebSocketEchoHandler; |
| 95 | |
| 96 | impl WebSocketHandler for WebSocketEchoHandler { |
| 97 | fn handle_text< |
| 98 | const UIDL: usize, |
| 99 | UID: NumIdDat<UIDL> + 'static, |
| 100 | ENC: Encrypter, |
| 101 | KH: Hasher, |
| 102 | DB: Database<UIDL, UID, ENC, KH>, |
| 103 | >( |
| 104 | &mut self, |
| 105 | txt: String, |
| 106 | _db: Option<(Arc<RwLock<DB>>, UID)>, |
| 107 | _syntax: SyntaxRef, |
| 108 | id: &String, |
| 109 | ) |
| 110 | -> Outcome<Option<WebSocketMessage>> |
| 111 | { |
| 112 | trace!("{}: WebSocketEchoHandler received text message: '{}'", id, txt); |
| 113 | let response = WebSocketMessage::Text(txt); // Echo. |
| 114 | Ok(Some(response)) |
| 115 | } |
| 116 | |
| 117 | fn handle_binary< |
| 118 | const UIDL: usize, |
| 119 | UID: NumIdDat<UIDL> + 'static, |
| 120 | ENC: Encrypter, |
| 121 | KH: Hasher, |
| 122 | DB: Database<UIDL, UID, ENC, KH>, |
| 123 | >( |
| 124 | &mut self, |
| 125 | byts: Vec<u8>, |
| 126 | _db: Option<(Arc<RwLock<DB>>, UID)>, |
| 127 | _syntax: SyntaxRef, |
| 128 | id: &String, |
| 129 | ) |
| 130 | -> Outcome<Option<WebSocketMessage>> |
| 131 | { |
| 132 | trace!("{}: WebSocketEchoHandler received binary message of length {}: {:02x?}", |
| 133 | id, byts.len(), byts); |
| 134 | let response = WebSocketMessage::Binary(byts); // Echo. |
| 135 | Ok(Some(response)) |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | #[derive(Clone, Debug)] |
| 140 | pub struct WebSocketSinkHandler; |
| 141 | |
| 142 | impl WebSocketHandler for WebSocketSinkHandler { |
| 143 | fn handle_text< |
| 144 | const UIDL: usize, |
| 145 | UID: NumIdDat<UIDL> + 'static, |
| 146 | ENC: Encrypter, |
| 147 | KH: Hasher, |
| 148 | DB: Database<UIDL, UID, ENC, KH>, |
| 149 | >( |
| 150 | &mut self, |
| 151 | txt: String, |
| 152 | _db: Option<(Arc<RwLock<DB>>, UID)>, |
| 153 | _syntax: SyntaxRef, |
| 154 | id: &String, |
| 155 | ) |
| 156 | -> Outcome<Option<WebSocketMessage>> |
| 157 | { |
| 158 | trace!("{}: WebSocketSinkHandler received text message: '{}'", id, txt); |
| 159 | Ok(None) |
| 160 | } |
| 161 | |
| 162 | fn handle_binary< |
| 163 | const UIDL: usize, |
| 164 | UID: NumIdDat<UIDL> + 'static, |
| 165 | ENC: Encrypter, |
| 166 | KH: Hasher, |
| 167 | DB: Database<UIDL, UID, ENC, KH>, |
| 168 | >( |
| 169 | &mut self, |
| 170 | byts: Vec<u8>, |
| 171 | _db: Option<(Arc<RwLock<DB>>, UID)>, |
| 172 | _syntax: SyntaxRef, |
| 173 | id: &String, |
| 174 | ) |
| 175 | -> Outcome<Option<WebSocketMessage>> |
| 176 | { |
| 177 | trace!("{}: WebSocketSinkHandler received binary message of length {}: {:02x?}", |
| 178 | id, byts.len(), byts); |
| 179 | Ok(None) |
| 180 | } |
| 181 | } |