connection_layer/
host_codec.rs1use crate::client_to_host::ClientToHostCommands;
2use crate::host_to_client::{ConnectResponse, HostToClientCommands};
3use crate::{verify_hash, write_to_stream, ConnectionId, ConnectionSecretSeed, RequestId};
4use flood_rs::in_stream::InOctetStream;
5use flood_rs::out_stream::OutOctetStream;
6use flood_rs::{Deserialize, ReadOctetStream, Serialize};
7use freelist_rs::FreeList;
8use log::{debug, trace};
9use secure_random::SecureRandom;
10use std::collections::HashMap;
11use std::io;
12use std::io::ErrorKind;
13
14pub trait DatagramHostEncoder {
15 fn encode(&mut self, connection_id: u8, buf: &[u8]) -> io::Result<Vec<u8>>;
16}
17
18pub struct HostConnection {
19 pub created_from_request: RequestId,
20 pub connection_id: ConnectionId,
21 pub seed: ConnectionSecretSeed,
22 pub has_received_connect: bool,
23}
24
25pub struct ConnectionLayerHostCodec {
26 pub connection_ids: FreeList<u8>,
27 pub connections: HashMap<u8, HostConnection>,
28 pub random: Box<dyn SecureRandom>,
29}
30
31impl ConnectionLayerHostCodec {
32 pub fn new(random: Box<dyn SecureRandom>) -> Self {
33 let mut s = Self {
34 connections: HashMap::new(),
35 connection_ids: FreeList::new(0xff),
36 random,
37 };
38 s.connection_ids.allocate(); s
41 }
42}
43
44
45impl DatagramHostEncoder for ConnectionLayerHostCodec {
46 fn encode(&mut self, connection_id: u8, buf: &[u8]) -> io::Result<Vec<u8>> {
47 let connection = self.connections.get_mut(&connection_id);
48 if connection.is_none() {
49 Err(io::Error::new(
50 ErrorKind::InvalidData,
51 format!("Unknown connection {}", connection_id),
52 ))?;
53 }
54 let actual_connection = connection.unwrap();
55 let mut stream = OutOctetStream::new();
56 if actual_connection.has_received_connect {
57 trace!(
58 "host sending on connection {} size: {}",
59 actual_connection.connection_id.value,
60 buf.len()
61 );
62 write_to_stream(
63 &mut stream,
64 actual_connection.connection_id,
65 actual_connection.seed,
66 buf,
67 )?;
68 } else {
69 debug!(
70 "host sending connect response connection_id: {} for request: {}",
71 actual_connection.connection_id.value, actual_connection.created_from_request
72 );
73 ConnectionId { value: 0 }.to_stream(&mut stream)?;
74 let connect_response = ConnectResponse {
75 request_id: actual_connection.created_from_request,
76 connection_id: actual_connection.connection_id,
77 seed: actual_connection.seed,
78 };
79 HostToClientCommands::Connect(connect_response).serialize(&mut stream)?
80 }
81
82 flood_rs::WriteOctetStream::write(&mut stream, buf)?;
83
84 Ok(stream.octets().to_vec())
85 }
86}
87
88
89pub trait DatagramHostDecoder {
90 fn decode(&mut self, buf: &[u8]) -> io::Result<(u8, Vec<u8>)>;
91}
92
93impl DatagramHostDecoder for ConnectionLayerHostCodec {
94 fn decode(&mut self, buf: &[u8]) -> io::Result<(u8, Vec<u8>)> {
95 let mut in_stream = InOctetStream::new(buf);
96 let connection_id = ConnectionId::from_stream(&mut in_stream)?;
97 if connection_id.value != 0 {
98 if let Some(connection) = self.connections.get_mut(&connection_id.value) {
99 let murmur = in_stream.read_u32()?;
100 verify_hash(murmur, connection.seed, &buf[5..])?;
101 trace!(
102 "host received payload of size: {} from connection {}",
103 buf.len() - 5,
104 connection.connection_id.value
105 );
106
107 connection.has_received_connect = true;
108 Ok((
110 connection_id.value,
111 buf[in_stream.cursor.position() as usize..].to_vec(),
112 ))
113 } else {
114 Err(io::Error::new(
115 io::ErrorKind::InvalidData,
116 "unknown connection_id",
117 ))?
118 }
119 } else {
120 let command = ClientToHostCommands::deserialize(&mut in_stream)?;
122 match command {
123 ClientToHostCommands::Connect(connect_request) => {
124 debug!("host received connect request {connect_request:?}");
125 let assigned_connection_id = self.connection_ids.allocate().ok_or(
126 io::Error::new(io::ErrorKind::InvalidData, "free list problem"),
127 )?;
128 let new_connection = HostConnection {
129 created_from_request: connect_request.request_id,
130 connection_id: ConnectionId {
131 value: assigned_connection_id,
132 },
133 seed: ConnectionSecretSeed(self.random.get_random_u64() as u32),
134 has_received_connect: false,
135 };
136 self.connections
137 .insert(assigned_connection_id, new_connection);
138 Ok((
139 assigned_connection_id,
140 buf[in_stream.cursor.position() as usize..].to_vec(),
141 ))
142 }
143 }
144 }
145 }
146}