1use crate::node::{ShadowNode, NodeHandle};
4use shadow_core::{PeerId, PeerInfo};
5use shadow_core::error::Result;
6use bytes::Bytes;
7use tokio::sync::mpsc;
8use steganography::{ImageSteganography, LSBConfig};
9
10#[derive(Debug, Clone)]
12pub enum MessageEvent {
13 TextMessage {
15 from: PeerId,
16 content: String,
17 },
18 BinaryData {
20 from: PeerId,
21 data: Bytes,
22 },
23 FileTransfer {
25 from: PeerId,
26 filename: String,
27 size: usize,
28 },
29 PeerConnected(PeerInfo),
31 PeerDisconnected(PeerId),
33}
34
35pub struct ShadowApi {
37 node: NodeHandle,
38 event_tx: mpsc::UnboundedSender<MessageEvent>,
39 event_rx: mpsc::UnboundedReceiver<MessageEvent>,
40}
41
42impl ShadowApi {
43 pub fn new(node: ShadowNode) -> Self {
45 let (event_tx, event_rx) = mpsc::unbounded_channel();
46
47 Self {
48 node: NodeHandle::new(node),
49 event_tx,
50 event_rx,
51 }
52 }
53
54 pub async fn start(&mut self) -> Result<()> {
56 self.node.start().await
57 }
58
59 pub async fn stop(&self) -> Result<()> {
61 self.node.stop().await
62 }
63
64 pub async fn send_text(&self, _peer_id: &PeerId, _message: &str) -> Result<()> {
66 Ok(())
68 }
69
70 pub async fn send_data(&self, _peer_id: &PeerId, _data: &[u8]) -> Result<()> {
72 Ok(())
74 }
75
76 pub async fn send_file_steganographic(
78 &self,
79 peer_id: &PeerId,
80 file_data: &[u8],
81 cover_image_path: &str,
82 ) -> Result<String> {
83 let stego = ImageSteganography::new(LSBConfig::default());
85
86 let cover = ImageSteganography::load_image(cover_image_path)?;
87 let stego_image = stego.embed(&cover, file_data)?;
88
89 let output_path = format!("/tmp/stego_{}.png", uuid::Uuid::new_v4());
91 ImageSteganography::save_image(&stego_image, &output_path, steganography::ImageFormat::PNG)?;
92
93 self.send_text(peer_id, &format!("FILE:{}", output_path)).await?;
95
96 Ok(output_path)
97 }
98
99 pub async fn receive_file_steganographic(&self, stego_image_path: &str) -> Result<Vec<u8>> {
101 let stego = ImageSteganography::new(LSBConfig::default());
102 stego.extract_file(stego_image_path)
103 }
104
105 pub async fn next_event(&mut self) -> Option<MessageEvent> {
107 self.event_rx.recv().await
108 }
109
110 pub async fn add_peer(&self, peer: PeerInfo) -> Result<()> {
112 let peer_clone = peer.clone();
114
115 self.node.node().add_peer(peer).await?;
116
117 self.event_tx.send(MessageEvent::PeerConnected(peer_clone)).ok();
119
120 Ok(())
121 }
122
123 pub fn get_peers(&self) -> Vec<PeerInfo> {
125 self.node.node().get_peers()
126 }
127
128 pub fn peer_id(&self) -> PeerId {
130 self.node.node().peer_id()
131 }
132
133 pub async fn store(&self, key: [u8; 32], data: Bytes) -> Result<()> {
135 self.node.node().store_data(key, data).await
136 }
137
138 pub async fn retrieve(&self, key: &[u8; 32]) -> Option<Bytes> {
140 self.node.node().get_data(key).await
141 }
142
143 pub fn stats(&self) -> NodeStats {
145 let node_stats = self.node.node().stats();
146
147 NodeStats {
148 peer_id: node_stats.peer_id,
149 peers: node_stats.connected_peers,
150 stored: node_stats.stored_values,
151 storage_mb: node_stats.storage_bytes / (1024 * 1024),
152 }
153 }
154}
155
156#[derive(Debug, Clone)]
158pub struct NodeStats {
159 pub peer_id: PeerId,
160 pub peers: usize,
161 pub stored: usize,
162 pub storage_mb: usize,
163}
164
165#[cfg(test)]
166mod tests {
167 use super::*;
168 use crypto::Keypair;
169
170 #[test]
171 fn test_api_creation() {
172 let keypair = Keypair::generate();
173 let node = ShadowNode::new(keypair);
174 let _api = ShadowApi::new(node);
175 }
176
177 #[tokio::test]
178 async fn test_api_lifecycle() {
179 let keypair = Keypair::generate();
180 let node = ShadowNode::new(keypair);
181 let mut api = ShadowApi::new(node);
182
183 api.start().await.ok();
184 api.stop().await.ok();
185 }
186}