connection_layer/
client_codec.rs1use crate::client_to_host::{ClientToHostCommands, ConnectRequest};
2use crate::host_to_client::HostToClientCommands;
3use crate::{verify_hash, write_to_stream, ConnectionId, ConnectionSecretSeed, RequestId, Version};
4use datagram::{DatagramDecoder, DatagramEncoder};
5use flood_rs::in_stream::InOctetStream;
6use flood_rs::out_stream::OutOctetStream;
7use flood_rs::{Deserialize, ReadOctetStream, Serialize};
8use log::{debug, trace};
9use std::io;
10
11pub struct ConnectionInfo {
12 pub connection_id: ConnectionId,
13 pub seed: ConnectionSecretSeed,
14}
15
16
17pub struct ConnectionLayerClientCodec {
18 pub connection_info: Option<ConnectionInfo>,
19 pub request_id: RequestId,
20}
21
22impl ConnectionLayerClientCodec {
23 pub fn new(request_id: RequestId) -> Self {
24 Self {
25 connection_info: None,
26 request_id,
27 }
28 }
29}
30
31
32impl DatagramEncoder for ConnectionLayerClientCodec {
33 fn encode(&mut self, buf: &[u8]) -> io::Result<Vec<u8>> {
34 let mut stream = OutOctetStream::new();
35 match &self.connection_info {
36 None => {
37 ConnectionId { value: 0 }.to_stream(&mut stream)?;
38 let connect_request = ConnectRequest {
39 request_id: self.request_id,
40 version: Version { major: 0, minor: 2 },
41 };
42 debug!("client sending connect request {connect_request:?}");
43 ClientToHostCommands::Connect(connect_request).serialize(&mut stream)?;
44 trace!("send request {}", hexify::format_hex(stream.octets_ref()));
45 }
46 Some(connection_info) => {
47 trace!(
48 "client sending payload connection_id: {} size: {}",
49 connection_info.connection_id.value,
50 buf.len()
51 );
52
53 write_to_stream(
54 &mut stream,
55 connection_info.connection_id,
56 connection_info.seed,
57 buf,
58 )?
59 }
60 }
61 flood_rs::WriteOctetStream::write(&mut stream, buf)?;
62
63 Ok(stream.octets().to_vec())
64 }
65}
66
67impl DatagramDecoder for ConnectionLayerClientCodec {
68 fn decode(&mut self, buf: &[u8]) -> io::Result<Vec<u8>> {
69 let mut in_stream = InOctetStream::new(buf);
70 let connection_id = ConnectionId::from_stream(&mut in_stream)?;
71
72 match &self.connection_info {
73 None => {
74 let command = HostToClientCommands::deserialize(&mut in_stream)?;
75 match command {
76 HostToClientCommands::Connect(connect_response) => {
77 debug!("client received connect response {connect_response:?}");
78 self.connection_info = Some(ConnectionInfo {
79 connection_id: connect_response.connection_id,
80 seed: connect_response.seed,
81 })
82 }
83 }
84 Ok(buf[in_stream.cursor.position() as usize..].to_vec())
85 }
86 Some(connection_info) => {
87 if connection_id != connection_info.connection_id {
88 Err(io::Error::new(io::ErrorKind::InvalidData, "problem"))
89 } else {
90 let murmur = in_stream.read_u32()?;
91 verify_hash(murmur, connection_info.seed, &buf[5..])?;
92 debug!(
93 "client received payload size:{} connection:{}",
94 buf.len() - 5,
95 connection_id.value
96 );
97 Ok(buf[5..].to_vec())
98 }
99 }
100 }
101 }
102}