vcl_protocol/
connection.rs1use crate::packet::VCLPacket;
2use crate::crypto::{KeyPair, encrypt_payload, decrypt_payload};
3use crate::handshake::{HandshakeMessage, create_client_hello, process_client_hello, process_server_hello};
4use ed25519_dalek::SigningKey;
5use x25519_dalek::EphemeralSecret;
6use rand::rngs::OsRng;
7use tokio::net::UdpSocket;
8use std::net::SocketAddr;
9use std::collections::HashSet;
10use std::time::{Duration, Instant};
11
12pub struct VCLConnection {
13 socket: UdpSocket,
14 keypair: KeyPair,
15 sequence: u64,
16 last_hash: Vec<u8>,
17 peer_addr: Option<SocketAddr>,
18 peer_public_key: Option<Vec<u8>>,
19 shared_secret: Option<[u8; 32]>,
20 is_server: bool,
21 last_sequence: u64,
22 seen_nonces: HashSet<[u8; 24]>,
23 closed: bool,
24 last_activity: Instant,
25 timeout_secs: u64,
26}
27
28impl VCLConnection {
29 pub async fn bind(addr: &str) -> Result<Self, String> {
30 let socket = UdpSocket::bind(addr).await.map_err(|e| e.to_string())?;
31 Ok(VCLConnection {
32 socket,
33 keypair: KeyPair::generate(),
34 sequence: 0,
35 last_hash: vec![0; 32],
36 peer_addr: None,
37 peer_public_key: None,
38 shared_secret: None,
39 is_server: false,
40 last_sequence: 0,
41 seen_nonces: HashSet::new(),
42 closed: false,
43 last_activity: Instant::now(),
44 timeout_secs: 60,
45 })
46 }
47
48 pub fn set_timeout(&mut self, secs: u64) {
49 self.timeout_secs = secs;
50 }
51
52 pub fn get_timeout(&self) -> u64 {
53 self.timeout_secs
54 }
55
56 pub fn last_activity(&self) -> Instant {
57 self.last_activity
58 }
59
60 pub fn set_shared_key(&mut self, private_key: &[u8]) {
61 let key_bytes: &[u8; 32] = private_key.try_into().unwrap();
62 let signing_key = SigningKey::from_bytes(key_bytes);
63 let verifying_key = signing_key.verifying_key();
64
65 self.keypair.private_key = private_key.to_vec();
66 self.keypair.public_key = verifying_key.to_bytes().to_vec();
67 }
68
69 pub async fn connect(&mut self, addr: &str) -> Result<(), String> {
70 let parsed: SocketAddr = addr.parse().map_err(|e: std::net::AddrParseError| e.to_string())?;
71 self.peer_addr = Some(parsed);
72
73 let (hello_msg, ephemeral) = create_client_hello();
74
75 let hello_bytes = bincode::serialize(&hello_msg).map_err(|e| e.to_string())?;
76 self.socket.send_to(&hello_bytes, parsed).await.map_err(|e| e.to_string())?;
77
78 let mut buf = vec![0u8; 65535];
79 let (len, _) = self.socket.recv_from(&mut buf).await.map_err(|e| e.to_string())?;
80 let server_hello: HandshakeMessage = bincode::deserialize(&buf[..len]).map_err(|e| e.to_string())?;
81
82 if let HandshakeMessage::ServerHello { public_key } = server_hello {
83 let shared = process_server_hello(ephemeral, public_key);
84 if let Some(secret) = shared {
85 self.shared_secret = Some(secret);
86 } else {
87 return Err("Handshake failed".to_string());
88 }
89 } else {
90 return Err("Expected ServerHello".to_string());
91 }
92
93 self.last_activity = Instant::now();
94 Ok(())
95 }
96
97 pub async fn accept_handshake(&mut self) -> Result<(), String> {
98 let ephemeral = EphemeralSecret::random_from_rng(OsRng);
99
100 let mut buf = vec![0u8; 65535];
101 let (len, addr) = self.socket.recv_from(&mut buf).await.map_err(|e| e.to_string())?;
102 self.peer_addr = Some(addr);
103
104 let client_hello: HandshakeMessage = bincode::deserialize(&buf[..len]).map_err(|e| e.to_string())?;
105
106 if let HandshakeMessage::ClientHello { public_key } = client_hello {
107 let (server_hello, shared) = process_client_hello(ephemeral, public_key);
108
109 let hello_bytes = bincode::serialize(&server_hello).map_err(|e| e.to_string())?;
110 self.socket.send_to(&hello_bytes, addr).await.map_err(|e| e.to_string())?;
111
112 if let Some(secret) = shared {
113 self.shared_secret = Some(secret);
114 self.is_server = true;
115 } else {
116 return Err("Handshake failed".to_string());
117 }
118 } else {
119 return Err("Expected ClientHello".to_string());
120 }
121
122 self.last_activity = Instant::now();
123 Ok(())
124 }
125
126 pub async fn send(&mut self, data: &[u8]) -> Result<(), String> {
127 if self.closed {
128 return Err("Connection closed".to_string());
129 }
130
131 self.check_timeout()?;
132
133 let key = self.shared_secret.ok_or("No shared secret")?;
134 let (encrypted_payload, nonce) = encrypt_payload(data, &key);
135
136 let mut packet = VCLPacket::new(self.sequence, self.last_hash.clone(), encrypted_payload, nonce);
137 packet.sign(&self.keypair.private_key);
138
139 let serialized = packet.serialize();
140 let addr = self.peer_addr.ok_or("No peer address")?;
141 self.socket.send_to(&serialized, addr).await.map_err(|e| e.to_string())?;
142
143 self.last_hash = packet.compute_hash();
144 self.sequence += 1;
145 self.last_activity = Instant::now();
146 Ok(())
147 }
148
149 pub async fn recv(&mut self) -> Result<VCLPacket, String> {
150 if self.closed {
151 return Err("Connection closed".to_string());
152 }
153
154 self.check_timeout()?;
155
156 let mut buf = vec![0u8; 65535];
157 let (len, addr) = self.socket.recv_from(&mut buf).await.map_err(|e| e.to_string())?;
158 if self.peer_addr.is_none() {
159 self.peer_addr = Some(addr);
160 }
161
162 let packet = VCLPacket::deserialize(&buf[..len])?;
163
164 if self.last_sequence > 0 && packet.sequence <= self.last_sequence {
165 return Err("Replay detected: old sequence number".to_string());
166 }
167
168 if self.seen_nonces.contains(&packet.nonce) {
169 return Err("Replay detected: duplicate nonce".to_string());
170 }
171 self.seen_nonces.insert(packet.nonce);
172
173 if self.seen_nonces.len() > 1000 {
174 self.seen_nonces.clear();
175 }
176
177 if !packet.validate_chain(&self.last_hash) {
178 return Err("Chain validation failed".to_string());
179 }
180
181 let verify_key = self.peer_public_key.as_ref().unwrap_or(&self.keypair.public_key);
182 if !packet.verify(verify_key) {
183 return Err("Signature validation failed".to_string());
184 }
185
186 self.last_hash = packet.compute_hash();
187 self.last_sequence = packet.sequence;
188 self.last_activity = Instant::now();
189
190 let key = self.shared_secret.ok_or("No shared secret")?;
191 let decrypted = decrypt_payload(&packet.payload, &key, &packet.nonce)?;
192
193 Ok(VCLPacket {
194 version: packet.version,
195 sequence: packet.sequence,
196 prev_hash: packet.prev_hash,
197 nonce: packet.nonce,
198 payload: decrypted,
199 signature: packet.signature,
200 })
201 }
202
203 fn check_timeout(&self) -> Result<(), String> {
204 let elapsed = self.last_activity.elapsed();
205 if elapsed.as_secs() > self.timeout_secs {
206 return Err("Connection timeout: no activity for too long".to_string());
207 }
208 Ok(())
209 }
210
211 pub fn close(&mut self) -> Result<(), String> {
212 if self.closed {
213 return Err("Connection already closed".to_string());
214 }
215
216 self.closed = true;
217 self.sequence = 0;
218 self.last_hash = vec![0; 32];
219 self.last_sequence = 0;
220 self.seen_nonces.clear();
221 self.shared_secret = None;
222
223 Ok(())
224 }
225
226 pub fn is_closed(&self) -> bool {
227 self.closed
228 }
229
230 pub fn get_public_key(&self) -> Vec<u8> {
231 self.keypair.public_key.clone()
232 }
233
234 pub fn get_shared_secret(&self) -> Option<[u8; 32]> {
235 self.shared_secret
236 }
237}