1use std::io::Cursor;
10use std::time::Instant;
11
12use conclave_room;
13use conclave_room::{ConnectionIndex, Room};
14use conclave_room_serialize::{RoomInfoCommand, ServerReceiveCommand};
15
16pub struct NetworkConnection {
17 pub id: ConnectionIndex,
18 pub room: Room,
19}
20
21pub trait SendDatagram {
22 fn send(&self) -> Vec<u8>;
23}
24
25impl SendDatagram for Room {
26 fn send(&self) -> Vec<u8> {
27 let room_info_command = RoomInfoCommand {
28 term: self.term,
29 leader_index: self.leader_index,
30 client_infos: vec![],
31 };
32
33 room_info_command.to_octets()
34 }
35}
36
37pub trait ReceiveDatagram {
38 fn receive(&mut self, connection_id: ConnectionIndex, now: Instant, buffer: Cursor<&[u8]>) -> Result<(), String>;
39}
40
41impl ReceiveDatagram for Room {
42 fn receive(&mut self, connection_id: ConnectionIndex, now: Instant, reader: Cursor<&[u8]>) -> Result<(), String> {
43 if !self.connections.contains_key(&connection_id) {
44 return Err(format!("there is no connection {}", connection_id));
45 }
46 let connection = self.connections.get_mut(&connection_id).unwrap();
47 let command = ServerReceiveCommand::from_cursor(reader).unwrap();
48 match command {
49 ServerReceiveCommand::PingCommandType(ping_command) => {
50 connection.on_ping(ping_command.term, ping_command.has_connection_to_leader, ping_command.knowledge, now);
51 }
52 }
53 Ok(())
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use std::io::Cursor;
60 use std::time::Instant;
61
62 use conclave_room::Room;
63 use conclave_room_serialize::PING_COMMAND_TYPE_ID;
64
65 use crate::{ReceiveDatagram, SendDatagram};
66
67 #[test]
68 fn check_send() {
69 let room = Room::new();
70 let octets = room.send();
71
72 assert_eq!(vec![0x00, 0x00, 0x00, 0xff], octets);
73 }
74
75 #[test]
76 fn on_ping() {
77 const EXPECTED_KNOWLEDGE_VALUE: u64 = 17718865395771014920;
78 let octets = [
79 PING_COMMAND_TYPE_ID,
80 0x00, 0x20,
82 0xF5, 0xE6,
84 0x0E,
85 0x32,
86 0xE9,
87 0xE4,
88 0x7F,
89 0x08,
90 0x01, ];
92 let receive_cursor = Cursor::new(octets.as_slice());
93
94 let mut room = Room::new();
95 let now = Instant::now();
96 let first_mutable_connection = room.create_connection(now);
97 let first_connection_id = first_mutable_connection.id;
98 let receive_result = room.receive(first_connection_id, now, receive_cursor);
99 assert_eq!(receive_result, Ok(()));
100
101 let connection_after_receive = room.connections.get(&first_connection_id).unwrap();
102 assert_eq!(connection_after_receive.knowledge, EXPECTED_KNOWLEDGE_VALUE);
103 }
104}