Skip to main content

rns_ctl/
bridge.rs

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