1use crate::constants::SOE_PROTOCOL_VERSION;
13use crate::error::Result;
14use crate::io::{BinaryReader, BinaryWriter};
15use crate::protocol::{DisconnectReason, OpCode};
16
17const OP_CODE_SIZE: usize = 2;
18
19#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct SessionRequest {
22 pub soe_protocol_version: u32,
24 pub session_id: u32,
26 pub udp_length: u32,
28 pub application_protocol: String,
30}
31
32impl SessionRequest {
33 pub const MIN_SIZE: usize = OP_CODE_SIZE + 4 + 4 + 4 + 1;
35
36 pub fn size(&self) -> usize {
38 OP_CODE_SIZE + 4 + 4 + 4 + self.application_protocol.len() + 1
39 }
40
41 pub fn deserialize(buffer: &[u8], has_op_code: bool) -> Result<Self> {
43 let mut r = BinaryReader::new(buffer);
44 if has_op_code {
45 r.read_u16()?;
46 }
47 Ok(Self {
48 soe_protocol_version: r.read_u32()?,
49 session_id: r.read_u32()?,
50 udp_length: r.read_u32()?,
51 application_protocol: r.read_null_terminated_string()?,
52 })
53 }
54
55 pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize> {
58 let mut w = BinaryWriter::new(buffer);
59 w.write_u16(OpCode::SessionRequest.as_u16())?;
60 w.write_u32(self.soe_protocol_version)?;
61 w.write_u32(self.session_id)?;
62 w.write_u32(self.udp_length)?;
63 w.write_null_terminated_string(&self.application_protocol)?;
64 Ok(w.offset())
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct SessionResponse {
71 pub session_id: u32,
73 pub crc_seed: u32,
75 pub crc_length: u8,
77 pub is_compression_enabled: bool,
79 pub unknown_value_1: u8,
81 pub udp_length: u32,
83 pub soe_protocol_version: u32,
85}
86
87impl SessionResponse {
88 pub const SIZE: usize = OP_CODE_SIZE + 4 + 4 + 1 + 1 + 1 + 4 + 4;
90
91 pub fn deserialize(buffer: &[u8], has_op_code: bool) -> Result<Self> {
93 let mut r = BinaryReader::new(buffer);
94 if has_op_code {
95 r.read_u16()?;
96 }
97 Ok(Self {
98 session_id: r.read_u32()?,
99 crc_seed: r.read_u32()?,
100 crc_length: r.read_u8()?,
101 is_compression_enabled: r.read_bool()?,
102 unknown_value_1: r.read_u8()?,
103 udp_length: r.read_u32()?,
104 soe_protocol_version: r.read_u32()?,
105 })
106 }
107
108 pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize> {
111 let mut w = BinaryWriter::new(buffer);
112 w.write_u16(OpCode::SessionResponse.as_u16())?;
113 w.write_u32(self.session_id)?;
114 w.write_u32(self.crc_seed)?;
115 w.write_u8(self.crc_length)?;
116 w.write_bool(self.is_compression_enabled)?;
117 w.write_u8(self.unknown_value_1)?;
118 w.write_u32(self.udp_length)?;
119 w.write_u32(self.soe_protocol_version)?;
120 Ok(w.offset())
121 }
122}
123
124#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub struct Disconnect {
127 pub session_id: u32,
129 pub reason: DisconnectReason,
131}
132
133impl Disconnect {
134 pub const SIZE: usize = 4 + 2;
136
137 pub fn new(session_id: u32, reason: DisconnectReason) -> Self {
139 Self { session_id, reason }
140 }
141
142 pub fn deserialize(buffer: &[u8]) -> Result<Self> {
144 let mut r = BinaryReader::new(buffer);
145 let session_id = r.read_u32()?;
146 let reason = DisconnectReason::from_u16(r.read_u16()?);
147 Ok(Self { session_id, reason })
148 }
149
150 pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize> {
152 let mut w = BinaryWriter::new(buffer);
153 w.write_u32(self.session_id)?;
154 w.write_u16(self.reason.as_u16())?;
155 Ok(w.offset())
156 }
157}
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub struct RemapConnection {
162 pub session_id: u32,
164 pub crc_seed: u32,
166}
167
168impl RemapConnection {
169 pub const SIZE: usize = OP_CODE_SIZE + 4 + 4;
171
172 pub fn deserialize(buffer: &[u8], has_op_code: bool) -> Result<Self> {
174 let mut r = BinaryReader::new(buffer);
175 if has_op_code {
176 r.read_u16()?;
177 }
178 Ok(Self {
179 session_id: r.read_u32()?,
180 crc_seed: r.read_u32()?,
181 })
182 }
183
184 pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize> {
187 let mut w = BinaryWriter::new(buffer);
188 w.write_u16(OpCode::RemapConnection.as_u16())?;
189 w.write_u32(self.session_id)?;
190 w.write_u32(self.crc_seed)?;
191 Ok(w.offset())
192 }
193}
194
195#[derive(Debug, Clone, Copy, PartialEq, Eq)]
197pub struct Acknowledge {
198 pub sequence: u16,
200}
201
202impl Acknowledge {
203 pub const SIZE: usize = 2;
205
206 pub fn new(sequence: u16) -> Self {
208 Self { sequence }
209 }
210
211 pub fn deserialize(buffer: &[u8]) -> Result<Self> {
213 let mut r = BinaryReader::new(buffer);
214 Ok(Self {
215 sequence: r.read_u16()?,
216 })
217 }
218
219 pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize> {
221 let mut w = BinaryWriter::new(buffer);
222 w.write_u16(self.sequence)?;
223 Ok(w.offset())
224 }
225}
226
227#[derive(Debug, Clone, Copy, PartialEq, Eq)]
230pub struct AcknowledgeAll {
231 pub sequence: u16,
233}
234
235impl AcknowledgeAll {
236 pub const SIZE: usize = 2;
238
239 pub fn new(sequence: u16) -> Self {
241 Self { sequence }
242 }
243
244 pub fn deserialize(buffer: &[u8]) -> Result<Self> {
246 let mut r = BinaryReader::new(buffer);
247 Ok(Self {
248 sequence: r.read_u16()?,
249 })
250 }
251
252 pub fn serialize(&self, buffer: &mut [u8]) -> Result<usize> {
254 let mut w = BinaryWriter::new(buffer);
255 w.write_u16(self.sequence)?;
256 Ok(w.offset())
257 }
258}
259
260#[derive(Debug, Clone, Copy, PartialEq, Eq)]
263pub struct UnknownSender;
264
265impl UnknownSender {
266 pub const SIZE: usize = OP_CODE_SIZE;
268
269 pub fn serialize(buffer: &mut [u8]) -> Result<usize> {
272 let mut w = BinaryWriter::new(buffer);
273 w.write_u16(OpCode::UnknownSender.as_u16())?;
274 Ok(w.offset())
275 }
276}
277
278pub fn session_request(
280 session_id: u32,
281 udp_length: u32,
282 application_protocol: &str,
283) -> SessionRequest {
284 SessionRequest {
285 soe_protocol_version: SOE_PROTOCOL_VERSION,
286 session_id,
287 udp_length,
288 application_protocol: application_protocol.to_owned(),
289 }
290}
291
292#[cfg(test)]
293mod tests {
294 use super::*;
295
296 #[test]
298 fn session_request_round_trip() {
299 let pkt = SessionRequest {
300 soe_protocol_version: 3,
301 session_id: 5_467_392,
302 udp_length: 512,
303 application_protocol: "TestProtocol".to_owned(),
304 };
305 let mut buf = vec![0u8; pkt.size()];
306 let n = pkt.serialize(&mut buf).unwrap();
307 assert_eq!(n, pkt.size());
308 assert_eq!(SessionRequest::deserialize(&buf, true).unwrap(), pkt);
309 }
310
311 #[test]
313 fn session_response_round_trip() {
314 let pkt = SessionResponse {
315 session_id: 531_633,
316 crc_seed: 34_322,
317 crc_length: 2,
318 is_compression_enabled: true,
319 unknown_value_1: 0,
320 udp_length: 512,
321 soe_protocol_version: 3,
322 };
323 let mut buf = [0u8; SessionResponse::SIZE];
324 let n = pkt.serialize(&mut buf).unwrap();
325 assert_eq!(n, SessionResponse::SIZE);
326 assert_eq!(SessionResponse::deserialize(&buf, true).unwrap(), pkt);
327 }
328
329 #[test]
331 fn disconnect_round_trip() {
332 let pkt = Disconnect::new(5, DisconnectReason::Application);
333 let mut buf = [0u8; Disconnect::SIZE];
334 pkt.serialize(&mut buf).unwrap();
335 assert_eq!(Disconnect::deserialize(&buf).unwrap(), pkt);
336 }
337
338 #[test]
340 fn remap_connection_round_trip() {
341 let pkt = RemapConnection {
342 session_id: 16,
343 crc_seed: 32,
344 };
345 let mut buf = [0u8; RemapConnection::SIZE];
346 pkt.serialize(&mut buf).unwrap();
347 assert_eq!(RemapConnection::deserialize(&buf, true).unwrap(), pkt);
348 }
349
350 #[test]
352 fn acknowledge_round_trip() {
353 let pkt = Acknowledge::new(2);
354 let mut buf = [0u8; Acknowledge::SIZE];
355 pkt.serialize(&mut buf).unwrap();
356 assert_eq!(Acknowledge::deserialize(&buf).unwrap(), pkt);
357
358 let all = AcknowledgeAll::new(2);
359 let mut buf = [0u8; AcknowledgeAll::SIZE];
360 all.serialize(&mut buf).unwrap();
361 assert_eq!(AcknowledgeAll::deserialize(&buf).unwrap(), all);
362 }
363
364 #[test]
365 fn unknown_sender_serializes_opcode() {
366 let mut buf = [0u8; UnknownSender::SIZE];
367 UnknownSender::serialize(&mut buf).unwrap();
368 assert_eq!(buf, [0x00, 0x1D]);
369 }
370}