1use shadow_core::{PeerId, PeerInfo};
4use shadow_core::error::{Result, ShadowError};
5use crypto::Keypair;
6use dht::{DHTNode, NodeConfig as DHTConfig};
7use nat_traversal::{StunClient, types::NatInfo};
8use std::sync::Arc;
9use tokio::sync::RwLock;
10
11pub struct ShadowNode {
13 keypair: Keypair,
15 peer_id: PeerId,
17 dht: Arc<DHTNode>,
19 nat_info: Arc<RwLock<Option<NatInfo>>>,
21}
22
23impl ShadowNode {
24 pub fn new(keypair: Keypair) -> Self {
26 let public_identity = keypair.public_identity();
29 let serialized = bincode::serialize(&public_identity.verify_key).unwrap();
31 let mut peer_id_bytes = [0u8; 32];
32 peer_id_bytes.copy_from_slice(&serialized[..32.min(serialized.len())]);
33 let peer_id = PeerId::from_bytes(peer_id_bytes);
34 let dht = Arc::new(DHTNode::new(peer_id, DHTConfig::default()));
35
36 Self {
37 keypair,
38 peer_id,
39 dht,
40 nat_info: Arc::new(RwLock::new(None)),
41 }
42 }
43
44 pub fn peer_id(&self) -> PeerId {
46 self.peer_id
47 }
48
49 pub fn keypair(&self) -> &Keypair {
51 &self.keypair
52 }
53
54 pub fn dht(&self) -> &Arc<DHTNode> {
56 &self.dht
57 }
58
59 pub async fn start(&self) -> Result<()> {
61 let stun_client = StunClient::default();
63 match stun_client.discover_nat() {
64 Ok(info) => {
65 tracing::info!("NAT discovery: {:?}", info.nat_type);
66 *self.nat_info.write().await = Some(info);
67 }
68 Err(e) => {
69 tracing::warn!("NAT discovery failed: {}", e);
70 }
71 }
72
73 let dht_clone = self.dht.clone();
75 tokio::spawn(async move {
76 dht_clone.start_maintenance().await;
77 });
78
79 Ok(())
80 }
81
82 pub async fn stop(&self) -> Result<()> {
84 Ok(())
85 }
86
87 pub async fn add_peer(&self, peer: PeerInfo) -> Result<()> {
89 self.dht.add_peer(peer)?;
90 Ok(())
91 }
92
93 pub fn get_peers(&self) -> Vec<PeerInfo> {
95 self.dht.all_peers()
96 }
97
98 pub async fn nat_info(&self) -> Option<NatInfo> {
100 self.nat_info.read().await.clone()
101 }
102
103 pub async fn store_data(&self, key: [u8; 32], data: bytes::Bytes) -> Result<()> {
105 let peer_id_bytes = *self.peer_id.as_bytes();
106 self.dht.store_value(key, data, peer_id_bytes)?;
107 Ok(())
108 }
109
110 pub async fn get_data(&self, key: &[u8; 32]) -> Option<bytes::Bytes> {
112 self.dht.get_value(key).map(|v| v.data)
113 }
114
115 pub fn stats(&self) -> NodeStats {
117 let dht_stats = self.dht.stats();
118
119 NodeStats {
120 peer_id: self.peer_id,
121 connected_peers: dht_stats.peer_count,
122 stored_values: dht_stats.value_count,
123 storage_bytes: dht_stats.storage_size,
124 }
125 }
126}
127
128pub struct NodeHandle {
130 node: Arc<ShadowNode>,
131}
132
133impl NodeHandle {
134 pub fn new(node: ShadowNode) -> Self {
136 Self {
137 node: Arc::new(node),
138 }
139 }
140
141 pub fn node(&self) -> &Arc<ShadowNode> {
143 &self.node
144 }
145
146 pub async fn start(&self) -> Result<()> {
148 self.node.start().await
149 }
150
151 pub async fn stop(&self) -> Result<()> {
153 self.node.stop().await
154 }
155}
156
157impl Clone for NodeHandle {
158 fn clone(&self) -> Self {
159 Self {
160 node: self.node.clone(),
161 }
162 }
163}
164
165#[derive(Debug, Clone)]
167pub struct NodeStats {
168 pub peer_id: PeerId,
169 pub connected_peers: usize,
170 pub stored_values: usize,
171 pub storage_bytes: usize,
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
179 fn test_node_creation() {
180 let keypair = Keypair::generate();
181 let node = ShadowNode::new(keypair);
182
183 assert_eq!(node.get_peers().len(), 0);
184 }
185
186 #[tokio::test]
187 async fn test_node_lifecycle() {
188 let keypair = Keypair::generate();
189 let node = NodeHandle::new(ShadowNode::new(keypair));
190
191 node.start().await.ok();
193 node.stop().await.ok();
194 }
195}