Skip to content

Commit 2c07e8c

Browse files
committed
Merge branch 'main' of https://github.com/RustDoIt/common
2 parents 1ffc8f3 + 266d7b5 commit 2c07e8c

4 files changed

Lines changed: 159 additions & 69 deletions

File tree

README.md

Lines changed: 42 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,55 @@
1-
# Common
2-
This library contains all the code that is common between each component (clients and servers).
1+
# Overview of the `common` library
32

4-
## How to Instantiate a generic Node (client or server)
5-
It follows an example implementation of a generic Node (in this case a Server):
3+
The `common` library provides foundational components for a drone-based network simulation in Rust, supporting packet routing, fragmentation, reassembly, and node management in an unreliable network environment. It integrates with `wg_internal` for core packet and node primitives. Key design principles include idempotent operations, flood-based discovery, source routing, and resilience to packet drops or node crashes via acknowledgments and retries.
64

7-
```rust
8-
pub struct Server {
9-
routing_handler: RoutingHandler,
10-
received_messages: Vec<(String, String)>,
11-
communication_server: Vec<NodeId>,
12-
controller_recv: Receiver<Box<dyn Any>>,
13-
packet_recv: Receiver<Packet>,
14-
assembler: FragmentAssembler,
15-
...
16-
}
5+
## Modules and Key Components
176

18-
impl Server {
19-
#[must_use]
20-
pub fn new(
21-
id: NodeId,
22-
neighbors: HashMap<NodeId, Sender<Packet>>,
23-
packet_recv: Receiver<Packet>,
24-
controller_recv: Receiver<Box<dyn Any>>,
25-
controller_send: Sender<Box<dyn Any>>,
26-
...
27-
) -> Self {
28-
let routing_handler = RoutingHandler::new(id, NodeType::Client, neighbors, controller_send);
7+
### `types`
8+
Defines core data structures and enums for network entities, files, requests/responses, commands, and events.
299

30-
Self {
31-
routing_handler,
32-
received_messages: vec![],
33-
communication_server: vec![],
34-
controller_recv,
35-
packet_recv,
36-
assembler: FragmentAssembler::default()
37-
...
38-
}
39-
}
40-
}
10+
- **MediaReference**: Represents a reference to media stored at a specific node (NodeId) with a UUID.
11+
- **TextFile**: Encapsulates a text file with title, content, and embedded media references.
12+
- **MediaFile**: Handles binary media files, chunked into 1024-byte segments for transmission.
13+
- **File**: Composite of a TextFile and associated MediaFiles.
14+
- **WebRequest/WebResponse**: Enums for web-like queries (e.g., server type, file lists, media retrieval) and responses (e.g., data delivery, errors like not found or UUID parsing failures).
15+
- **ChatRequest/ChatResponse**: Enums for chat operations (e.g., registration, client lists, messaging) and responses (e.g., message delivery, client lists).
16+
- **Event/Command**: Traits and enums for node-specific events (e.g., NodeEvent for packet sent/flood started) and commands (e.g., NodeCommand for adding/removing senders, shutdown).
17+
- **ChatEvent/WebEvent/NodeEvent**: Specific event variants for chat (e.g., message received, registration), web (e.g., file added/removed, queries), and general node operations.
18+
- **ClientType/ServerType/NodeType**: Enums classifying nodes (e.g., ChatClient, TextServer, Drone).
4119

20+
### `assembler`
21+
Manages packet fragmentation and reassembly.
4222

43-
impl Processor for Server {
44-
fn controller_recv(&self) -> &Receiver<Box<dyn Any>> {
45-
&self.controller_recv
46-
}
23+
- **FragmentAssembler**: Tracks fragments by session ID and sender NodeId. Adds fragments, checks completeness via expected/received counts, and reassembles data into a complete message when all fragments arrive.
4724

48-
fn packet_recv(&self) -> &Receiver<Packet> {
49-
&self.packet_recv
50-
}
25+
### `file_conversion`
26+
Utilities for converting local files to library types.
5127

52-
fn handle_command(&mut self, cmd: Box<dyn Any>) {
53-
if let Ok(cmd) = cmd.downcast::<ServerCommand>() {
54-
match *cmd {
55-
// match on server command
56-
}
57-
}
28+
- **file_to_media_file**: Reads binary file content, chunks it, and creates a MediaFile.
29+
- **file_to_text_file**: Reads text file content and creates a TextFile (without media refs by default).
5830

59-
}
31+
### `network`
32+
Models the network topology and operations.
6033

61-
fn assembler(&mut self) -> &mut FragmentAssembler {
62-
&mut self.assembler
63-
}
34+
- **NetworkError**: Enum for errors like path not found, node removal, or send failures.
35+
- **Node**: Represents a network node with ID, type (NodeType), and adjacent nodes.
36+
- **Network**: Maintains a list of nodes; supports adding/removing/updating nodes, changing types, finding shortest paths via BFS, and filtering by type (e.g., get_servers, get_clients).
6437

65-
fn routing_header(&mut self) -> &mut RoutingHandler {
66-
&mut self.routing_handler
67-
}
38+
### `routing_handler`
39+
Handles routing logic, including discovery and packet transmission.
6840

69-
fn handle_msg(&mut self, msg: Vec<u8>) {
41+
- **RoutingHandler**: Core struct managing node ID, network view (Network), neighbors (senders by NodeId), flood tracking, and buffers for packets/fragments.
42+
- Initiates floods for discovery (start_flood).
43+
- Handles flood requests/responses to update topology.
44+
- Sends messages with fragmentation if >128 bytes (send_message).
45+
- Processes acks (mark fragments received), nacks (retry or remove faulty nodes), and retries (retry_send).
46+
- Manages neighbor addition/removal and buffering for pending packets.
7047

71-
if let Ok(msg) = serde_json::from_slice::<ClientRequest>(&msg) {
72-
match msg {
73-
// match on ClientRequest
74-
}
75-
}
76-
}
77-
}
78-
```
48+
### `packet_processor`
49+
Defines processing loop for packets and commands.
50+
51+
- **Processor**: Trait for entities that handle incoming packets and commands.
52+
- Integrates FragmentAssembler and RoutingHandler.
53+
- Processes packets (e.g., fragments to reassemble messages, acks/nacks/floods via routing handler).
54+
- Runs an event loop selecting between controller commands (handle_command) and packets (handle_packet), with flood initiation on start.
55+
- Subtypes must implement message handling (handle_msg) and command processing.

src/file_conversion.rs

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,117 @@
1-
use std::fs;
1+
use std::fs::{self, File as StdFile};
22
use std::path::Path;
3-
use crate::types::{MediaFile, TextFile};
3+
use crate::types::{MediaFile, TextFile, File};
4+
use std::io::Write;
5+
6+
/// Saves a [`File`] into a directory named `cached_files_{notification_from}`.
7+
///
8+
/// The function writes the [`TextFile`] content and appends a line
9+
/// for each attached [`MediaFile`].
10+
///
11+
/// # Errors
12+
///
13+
/// Returns an error if the directory cannot be created or if the file cannot
14+
/// be created or written to.
15+
pub fn save_file(notification_from: &u8, file: &File) -> std::io::Result<()> {
16+
let dir_name = format!("cached_files_{notification_from}");
17+
let dir_path = Path::new(&dir_name);
18+
fs::create_dir_all(dir_path)?;
19+
20+
let file_name = format!("{}_{}", file.text_file.id, file.text_file.title);
21+
let file_path = dir_path.join(file_name);
22+
23+
let mut f = StdFile::create(file_path)?;
24+
writeln!(f, "{}", file.text_file.content)?;
25+
for media_file in &file.media_files {
26+
writeln!(f, "MediaFile attached: {}_{}", media_file.id, media_file.title)?;
27+
}
28+
Ok(())
29+
}
30+
31+
/// Saves a list of [`File`]s into `cached_files_{notification_from}` by
32+
/// delegating to [`save_file`] for each element.
33+
///
34+
/// # Errors
35+
///
36+
/// Returns an error if saving any single file fails.
37+
pub fn save_files(notification_from: &u8, files: &Vec<File>) -> std::io::Result<()> {
38+
for file in files {
39+
save_file(notification_from, file)?;
40+
}
41+
Ok(())
42+
}
43+
44+
/// Saves a [`TextFile`] into `cached_files_{notification_from}`.
45+
///
46+
/// The function writes the text content and appends a line for each
47+
/// attached [`MediaReference`].
48+
///
49+
/// # Errors
50+
///
51+
/// Returns an error if the directory cannot be created or if the file cannot
52+
/// be created or written to.
53+
pub fn save_text_file(notification_from: &u8, file: &TextFile) -> std::io::Result<()> {
54+
let dir_name = format!("cached_files_{notification_from}");
55+
let dir_path = Path::new(&dir_name);
56+
fs::create_dir_all(dir_path)?;
57+
58+
let file_name = format!("{}_{}", file.id, file.title);
59+
let file_path = dir_path.join(file_name);
60+
61+
let mut f = StdFile::create(file_path)?;
62+
writeln!(f, "{}", file.content)?;
63+
for media_ref in &file.media_refs {
64+
writeln!(f, "MediaFile attached: {}_{}", media_ref.location, media_ref.id)?;
65+
}
66+
Ok(())
67+
}
68+
69+
/// Saves a list of [`TextFile`]s by delegating to [`save_text_file`].
70+
///
71+
/// # Errors
72+
///
73+
/// Returns an error if saving any single file fails.
74+
pub fn save_text_files(notification_from: &u8, files: &Vec<TextFile>) -> std::io::Result<()> {
75+
for file in files {
76+
save_text_file(notification_from, file)?;
77+
}
78+
Ok(())
79+
}
80+
81+
/// Saves a single [`MediaFile`] into `cached_files_{notification_from}`.
82+
///
83+
/// The file is written as `{id}_{title}` and its binary content flushed.
84+
///
85+
/// # Errors
86+
///
87+
/// Returns an error if the directory cannot be created or if the file cannot
88+
/// be created or written to.
89+
pub fn save_media_file(notification_from: &u8, file: &MediaFile) -> std::io::Result<()> {
90+
let dir_name = format!("cached_files_{notification_from}");
91+
let dir_path = Path::new(&dir_name);
92+
fs::create_dir_all(dir_path)?;
93+
94+
let file_name = format!("{}_{}", file.id, file.title);
95+
let file_path = dir_path.join(file_name);
96+
97+
let mut f = StdFile::create(file_path)?;
98+
for chunk in &file.content {
99+
f.write_all(chunk)?;
100+
}
101+
Ok(())
102+
}
103+
104+
/// Saves a list of [`MediaFile`]s by delegating to [`save_media_file`].
105+
///
106+
/// # Errors
107+
///
108+
/// Returns an error if saving any single file fails.
109+
pub fn save_media_files(notification_from: &u8, files: &[MediaFile]) -> std::io::Result<()> {
110+
for file in files {
111+
save_media_file(notification_from, file)?;
112+
}
113+
Ok(())
114+
}
4115

5116
/// Converts a file path into a `MediaFile`.
6117
///

src/network.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,12 @@ impl Node {
5454
Self { id, kind, adjacents }
5555
}
5656

57+
#[must_use]
5758
pub fn get_id(&self) -> NodeId {
5859
self.id
5960
}
6061

62+
#[must_use]
6163
pub fn get_node_type(&self) -> NodeType {
6264
self.kind
6365
}

src/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub struct SerializedRequest {
1616

1717
#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
1818
pub struct MediaReference {
19-
location: NodeId,
19+
pub location: NodeId,
2020
pub id: Uuid,
2121
}
2222

@@ -135,7 +135,7 @@ impl MediaFile {
135135
pub struct File {
136136
pub id: Uuid,
137137
pub text_file: TextFile,
138-
media_files: Vec<MediaFile>,
138+
pub media_files: Vec<MediaFile>,
139139
}
140140

141141
impl File {

0 commit comments

Comments
 (0)