Skip to main content

rns_ctl/
bridge.rs

1use rns_core::types::{DestHash, IdentityHash, LinkId, PacketHash};
2use rns_net::destination::AnnouncedIdentity;
3use rns_net::Callbacks;
4
5use crate::encode::{to_base64, to_hex};
6use crate::state::*;
7
8/// Callbacks implementation that bridges rns-net events into shared state + WebSocket broadcast.
9pub struct CtlCallbacks {
10    state: SharedState,
11    ws_broadcast: WsBroadcast,
12}
13
14impl CtlCallbacks {
15    pub fn new(state: SharedState, ws_broadcast: WsBroadcast) -> Self {
16        CtlCallbacks { state, ws_broadcast }
17    }
18}
19
20impl Callbacks for CtlCallbacks {
21    fn on_announce(&mut self, announced: AnnouncedIdentity) {
22        let record = make_announce_record(&announced);
23        let event = WsEvent::announce(&record);
24        push_announce(&self.state, record);
25        broadcast(&self.ws_broadcast, event);
26    }
27
28    fn on_path_updated(&mut self, _dest_hash: DestHash, _hops: u8) {
29        // Path updates are queryable via GET /api/paths; no event record needed.
30    }
31
32    fn on_local_delivery(&mut self, dest_hash: DestHash, raw: Vec<u8>, packet_hash: PacketHash) {
33        let record = PacketRecord {
34            dest_hash: to_hex(&dest_hash.0),
35            packet_hash: to_hex(&packet_hash.0),
36            data_base64: to_base64(&raw),
37            received_at: rns_net::time::now(),
38        };
39        let event = WsEvent::packet(&record);
40        push_packet(&self.state, record);
41        broadcast(&self.ws_broadcast, event);
42    }
43
44    fn on_proof(&mut self, dest_hash: DestHash, packet_hash: PacketHash, rtt: f64) {
45        let record = ProofRecord {
46            dest_hash: to_hex(&dest_hash.0),
47            packet_hash: to_hex(&packet_hash.0),
48            rtt,
49        };
50        let event = WsEvent::proof(&record);
51        push_proof(&self.state, record);
52        broadcast(&self.ws_broadcast, event);
53    }
54
55    fn on_proof_requested(&mut self, _dest_hash: DestHash, _packet_hash: PacketHash) -> bool {
56        true
57    }
58
59    fn on_link_established(&mut self, link_id: LinkId, rtt: f64, is_initiator: bool) {
60        let record = LinkEventRecord {
61            link_id: to_hex(&link_id.0),
62            event_type: "established".into(),
63            is_initiator: Some(is_initiator),
64            rtt: Some(rtt),
65            identity_hash: None,
66            reason: None,
67        };
68        let event = WsEvent::link(&record);
69        push_link_event(&self.state, record);
70        broadcast(&self.ws_broadcast, event);
71    }
72
73    fn on_link_closed(&mut self, link_id: LinkId, reason: Option<rns_core::link::TeardownReason>) {
74        let record = LinkEventRecord {
75            link_id: to_hex(&link_id.0),
76            event_type: "closed".into(),
77            is_initiator: None,
78            rtt: None,
79            identity_hash: None,
80            reason: reason.map(|r| format!("{:?}", r)),
81        };
82        let event = WsEvent::link(&record);
83        push_link_event(&self.state, record);
84        broadcast(&self.ws_broadcast, event);
85    }
86
87    fn on_remote_identified(&mut self, link_id: LinkId, identity_hash: IdentityHash, _public_key: [u8; 64]) {
88        let record = LinkEventRecord {
89            link_id: to_hex(&link_id.0),
90            event_type: "identified".into(),
91            is_initiator: None,
92            rtt: None,
93            identity_hash: Some(to_hex(&identity_hash.0)),
94            reason: None,
95        };
96        let event = WsEvent::link(&record);
97        push_link_event(&self.state, record);
98        broadcast(&self.ws_broadcast, event);
99    }
100
101    fn on_resource_received(&mut self, link_id: LinkId, data: Vec<u8>, metadata: Option<Vec<u8>>) {
102        let record = ResourceEventRecord {
103            link_id: to_hex(&link_id.0),
104            event_type: "received".into(),
105            data_base64: Some(to_base64(&data)),
106            metadata_base64: metadata.as_ref().map(|m| to_base64(m)),
107            error: None,
108            received: None,
109            total: None,
110        };
111        let event = WsEvent::resource(&record);
112        push_resource_event(&self.state, record);
113        broadcast(&self.ws_broadcast, event);
114    }
115
116    fn on_resource_completed(&mut self, link_id: LinkId) {
117        let record = ResourceEventRecord {
118            link_id: to_hex(&link_id.0),
119            event_type: "completed".into(),
120            data_base64: None,
121            metadata_base64: None,
122            error: None,
123            received: None,
124            total: None,
125        };
126        let event = WsEvent::resource(&record);
127        push_resource_event(&self.state, record);
128        broadcast(&self.ws_broadcast, event);
129    }
130
131    fn on_resource_failed(&mut self, link_id: LinkId, error: String) {
132        let record = ResourceEventRecord {
133            link_id: to_hex(&link_id.0),
134            event_type: "failed".into(),
135            data_base64: None,
136            metadata_base64: None,
137            error: Some(error),
138            received: None,
139            total: None,
140        };
141        let event = WsEvent::resource(&record);
142        push_resource_event(&self.state, record);
143        broadcast(&self.ws_broadcast, event);
144    }
145
146    fn on_resource_progress(&mut self, link_id: LinkId, received: usize, total: usize) {
147        let record = ResourceEventRecord {
148            link_id: to_hex(&link_id.0),
149            event_type: "progress".into(),
150            data_base64: None,
151            metadata_base64: None,
152            error: None,
153            received: Some(received),
154            total: Some(total),
155        };
156        let event = WsEvent::resource(&record);
157        push_resource_event(&self.state, record);
158        broadcast(&self.ws_broadcast, event);
159    }
160
161    fn on_resource_accept_query(
162        &mut self,
163        _link_id: LinkId,
164        _resource_hash: Vec<u8>,
165        _transfer_size: u64,
166        _has_metadata: bool,
167    ) -> bool {
168        true
169    }
170
171    fn on_channel_message(&mut self, link_id: LinkId, msgtype: u16, payload: Vec<u8>) {
172        let record = PacketRecord {
173            dest_hash: format!("channel:{}:{}", to_hex(&link_id.0), msgtype),
174            packet_hash: String::new(),
175            data_base64: to_base64(&payload),
176            received_at: rns_net::time::now(),
177        };
178        let event = WsEvent::packet(&record);
179        push_packet(&self.state, record);
180        broadcast(&self.ws_broadcast, event);
181    }
182
183    fn on_response(&mut self, link_id: LinkId, request_id: [u8; 16], data: Vec<u8>) {
184        let record = PacketRecord {
185            dest_hash: format!("response:{}:{}", to_hex(&link_id.0), to_hex(&request_id)),
186            packet_hash: String::new(),
187            data_base64: to_base64(&data),
188            received_at: rns_net::time::now(),
189        };
190        let event = WsEvent::packet(&record);
191        push_packet(&self.state, record);
192        broadcast(&self.ws_broadcast, event);
193    }
194}