soe_network_parser_lib/modules/
soe_packet_extraction.rs1use super::pcap_extraction::*;
2use h1emu_core::soeprotocol::Soeprotocol;
3use h1emu_core::soeprotocol_packets_structs::{AckPacket, DataPacket, SubBasePackets};
4use serde_derive::Deserialize;
5use serde_derive::Serialize;
6use serde_json::*;
7use std::collections::HashMap;
8use std::fs;
9
10#[derive(Serialize, Deserialize)]
11struct ExtractedPacketSmall {
12 name: String,
13}
14
15pub fn extract_soe_packets(
16 extracted_packets: Vec<ExtractedPacket>,
17 output_directory: &String,
18 use_crc: bool,
19 crc_seed: u32,
20 write_packets_to_files: bool,
21 max_packets: usize,
22) -> HashMap<String, Vec<Value>> {
23 let mut protocol = Soeprotocol::initialize(use_crc, crc_seed);
24 let mut index: u32 = 0;
25 let mut parsed_packets: Vec<Value> = Vec::new();
26 let mut parsed_server_packets: Vec<Value> = Vec::new();
27 let mut parsed_client_packets: Vec<Value> = Vec::new();
28 let mut parsed_packets_map: HashMap<String, Vec<Value>> = HashMap::new();
29
30 for extracted_packet in extracted_packets {
31 let parsed_data = protocol.parse(extracted_packet.data);
32 parsed_packets.push(json!(parsed_data));
33 let extracted_packet_small: ExtractedPacketSmall =
35 serde_json::from_str(&parsed_data).unwrap();
36 index += 1;
37 if extracted_packet.sender == "server" {
38 parsed_server_packets.push(json!(parsed_data));
39 } else {
40 parsed_client_packets.push(json!(parsed_data));
41 }
42 if write_packets_to_files {
43 let mut file_name: String = output_directory.to_owned();
44 file_name.push_str(&index.to_string());
45 file_name.push_str("-");
46 file_name.push_str(&extracted_packet.sender);
47 file_name.push_str("-");
48 file_name.push_str(extracted_packet_small.name.as_str());
49 file_name.push_str(".json");
50 fs::write(file_name, parsed_data).expect("Unable to write to file");
51 }
52 if max_packets > 0 && index as usize >= max_packets {
53 break;
54 }
55 }
56 if write_packets_to_files {
57 let mut file_name: String = output_directory.to_owned();
58 file_name.push_str("0-full.json");
59 fs::write(
60 file_name,
61 serde_json::to_string_pretty(&parsed_packets).unwrap(),
62 )
63 .expect("Unable to write to file");
64 }
65 parsed_packets_map.insert("client".to_owned(), parsed_client_packets);
66 parsed_packets_map.insert("server".to_owned(), parsed_server_packets);
67 return parsed_packets_map;
68}
69
70fn contain_multiple_acks(packet: &SubBasePackets) -> bool {
71 let mut ack_count: u32 = 0;
73 for packet_part in &packet.sub_packets {
74 if packet_part.name == "Ack" {
75 ack_count += 1;
76 }
77 }
78 return ack_count > 1;
79}
80
81struct Stats {
82 multiple_acks_per_buffer: u32,
83 total_multi_packets: u32,
84 total_acks: u32,
85 useless_acks: u32,
86 useless_outoforder: u32,
87 total_outoforder: u32,
88 last_ack: u16,
89 last_sequence: HashMap<u16, bool>,
90 resended_data: u32,
91 total_data_packets: u32,
92}
93fn analyse_packets(parsed_packets: &Vec<Value>, stats: &mut Stats) -> () {
94 for parsed_packet in parsed_packets {
95 let extracted_packet_small: ExtractedPacketSmall =
96 serde_json::from_str(&parsed_packet.as_str().unwrap()).unwrap();
97 match extracted_packet_small.name.as_str() {
98 "MultiPacket" => {
99 stats.total_multi_packets += 1;
100 let packet: SubBasePackets =
101 serde_json::from_str(&parsed_packet.as_str().unwrap()).unwrap();
102 if contain_multiple_acks(&packet) {
103 stats.multiple_acks_per_buffer += 1;
104 }
105 for packet_part in packet.sub_packets {
106 if packet_part.name == "Ack" {
107 stats.total_acks += 1;
108 if packet_part.sequence.unwrap() < stats.last_ack {
109 stats.useless_acks += 1;
110 } else {
111 stats.last_ack = packet_part.sequence.unwrap();
112 }
113 } else if packet_part.name == "OutOfOrder" {
114 stats.total_outoforder += 1;
115 if packet_part.sequence.unwrap() < stats.last_ack {
116 stats.useless_outoforder += 1;
117 }
118 }
119 }
120 }
121 "Ack" => {
122 stats.total_acks += 1;
123 let packet: AckPacket =
124 serde_json::from_str(&parsed_packet.as_str().unwrap()).unwrap();
125 if packet.sequence < stats.last_ack {
126 stats.useless_acks += 1;
127 }
128 stats.last_ack = packet.sequence;
129 }
130 "OutOfOrder" => {
131 stats.total_outoforder += 1;
132 let packet: AckPacket =
133 serde_json::from_str(&parsed_packet.as_str().unwrap()).unwrap();
134 if packet.sequence < stats.last_ack {
135 stats.useless_outoforder += 1;
136 }
137 }
138 "Data" => {
139 let packet: DataPacket =
140 serde_json::from_str(&parsed_packet.as_str().unwrap()).unwrap();
141 if stats.last_sequence.contains_key(&packet.sequence) {
142 stats.resended_data += 1;
143 } else {
144 stats.last_sequence.insert(packet.sequence, true);
145 }
146 stats.total_data_packets += 1;
147 }
148 "DataFragment" => {
149 let packet: DataPacket =
150 serde_json::from_str(&parsed_packet.as_str().unwrap()).unwrap();
151 if stats.last_sequence.contains_key(&packet.sequence) {
152 stats.resended_data += 1;
153 } else {
154 stats.last_sequence.insert(packet.sequence, true);
155 }
156 stats.total_data_packets += 1;
157 }
158 _ => {}
159 }
160 }
161}
162
163fn log_stats(stats: Stats) -> () {
164 if stats.total_multi_packets > 0 {
165 println!(
167 "{}% of multiple acks per buffer",
168 (stats.multiple_acks_per_buffer * 100) as f32 / stats.total_multi_packets as f32
169 );
170 }
171 if stats.total_acks > 0 {
172 println!(
174 "{}% of useless acks",
175 (stats.useless_acks * 100) as f32 / stats.total_acks as f32
176 );
177 }
178 if stats.total_outoforder > 0 {
179 println!(
181 "{}% of useless outoforder",
182 (stats.useless_outoforder * 100) as f32 / stats.total_outoforder as f32
183 );
184 }
185 if stats.total_data_packets > 0 {
186 println!(
188 "{}% of resended data",
189 ((stats.resended_data + 1) * 100) as f32 / stats.total_data_packets as f32
190 );
191 }
192}
193pub fn analyze_soe_packets(parsed_packets: HashMap<String, Vec<Value>>) {
194 let server_packets = parsed_packets.get("server").unwrap();
195
196 let mut server_stats = Stats {
197 multiple_acks_per_buffer: 0,
198 total_multi_packets: 0,
199 total_acks: 0,
200 useless_acks: 0,
201 useless_outoforder: 0,
202 total_outoforder: 0,
203 last_ack: 0,
204 last_sequence: HashMap::new(),
205 resended_data: 0,
206 total_data_packets: 0,
207 };
208 analyse_packets(server_packets, &mut server_stats);
209
210 println!("server packets stats");
211
212 log_stats(server_stats);
213
214 let client_packets = parsed_packets.get("client").unwrap();
215
216 let mut client_stats = Stats {
217 multiple_acks_per_buffer: 0,
218 total_multi_packets: 0,
219 total_acks: 0,
220 useless_acks: 0,
221 useless_outoforder: 0,
222 total_outoforder: 0,
223 last_ack: 0,
224 last_sequence: HashMap::new(),
225 resended_data: 0,
226 total_data_packets: 0,
227 };
228 analyse_packets(client_packets, &mut client_stats);
229
230 println!("client packets stats");
231
232 log_stats(client_stats);
233}