1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
pub mod common {
pub use crate::protocol::args::Arg;
pub use crate::protocol::versions::Version;
pub mod utils {
//!
//! The utils module contains the utility functions used by the SHDP protocol.
//! It is used to handle utility functions that may be used by the protocol.
//!
///
/// Represents a TLS certificate.
///
#[cfg(any(
feature = "tls-server",
feature = "wss-server",
feature = "tls-client",
feature = "wss-client"
))]
pub struct Certificate {
/// The path to the certificate file.
pub cert_path: String,
/// The path to the private key file.
pub key_path: String,
}
#[derive(Debug)]
pub(crate) enum Listener<'a> {
#[cfg(feature = "tcp-server")]
TokioServer(&'a tokio::net::TcpListener),
#[cfg(feature = "ws-server")]
StdServer(smol::net::TcpListener),
#[cfg(feature = "tcp-client")]
#[allow(dead_code)]
TokioClient(Arc<std::sync::Mutex<tokio::net::TcpStream>>),
#[cfg(feature = "ws-client")]
StdClient(std::net::TcpStream),
#[cfg(feature = "ws-server")]
_Phantom(PhantomData<&'a ()>),
}
impl<'a> Listener<'a> {
#[cfg(feature = "tcp-server")]
pub(crate) fn get_tokio_server(&self) -> &tokio::net::TcpListener {
match self {
Listener::TokioServer(listener) => listener,
_ => panic!("Listener is not a tokio listener"),
}
}
#[cfg(feature = "wss-server")]
pub(crate) fn get_std_server(&self) -> &smol::net::TcpListener {
match self {
Listener::StdServer(listener) => listener,
_ => panic!("Listener is not an smol listener"),
}
}
#[cfg(feature = "tcp-client")]
#[allow(dead_code)]
pub(crate) fn get_tokio_client(
&mut self,
) -> Arc<std::sync::Mutex<tokio::net::TcpStream>> {
match self {
Listener::TokioClient(listener) => listener.clone(),
_ => panic!("Listener is not a tokio stream"),
}
}
#[cfg(feature = "ws-client")]
pub(crate) fn get_std_client(&mut self) -> &mut std::net::TcpStream {
match self {
Listener::StdClient(listener) => listener,
_ => panic!("Listener is not a std stream"),
}
}
}
///
/// Manually stops a connection.
///
/// # Arguments
/// * `ip` - The ip address to stop listening on.
/// * `port` - The port to stop listening on.
///
/// # Example
/// ```rust,no_run
/// #[cfg(feature = "tcp-server")]
///
///
/// use shdp::prelude::common::utils::stop;
///
/// use shdp::prelude::server::tcp::listen;
///
/// // Creating a server for demonstration purposes.
///
/// listen(String::from("8080"));
///
/// stop(String::from("127.0.0.1"), String::from("8080"));
/// ```
pub async fn stop(ip: String, port: String) {
let mut devices = match DEVICES.lock() {
Ok(devices) => devices,
Err(poisoned) => {
println!("[SHDP] Mutex poisoned, recovering: {:?}", poisoned);
poisoned.into_inner()
}
};
if let Some(listener) = devices.remove(&(ip, port)) {
match listener {
#[cfg(feature = "tcp-server")]
Listener::TokioServer(listener) => drop(listener.to_owned()),
#[cfg(feature = "ws-server")]
Listener::StdServer(listener) => drop(listener),
#[cfg(feature = "tcp-client")]
Listener::TokioClient(listener) => {
let _ = listener.lock().unwrap().shutdown().await;
}
#[cfg(feature = "ws-client")]
Listener::StdClient(listener) => {
let _ = listener.shutdown(std::net::Shutdown::Both);
}
#[cfg(feature = "ws-server")]
Listener::_Phantom(_) => {
panic!("Phantom should not be used!")
}
};
}
}
lazy_static! {
pub(crate) static ref DEVICES: Arc<Mutex<HashMap<RemoteId, Listener<'static>>>> =
Arc::new(Mutex::new(HashMap::new()));
}
#[cfg(feature = "ws-server")]
use std::marker::PhantomData;
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
use lazy_static::lazy_static;
#[cfg(feature = "tcp-client")]
use tokio::io::AsyncWriteExt;
use crate::protocol::prelude::RemoteId;
}
pub mod bits {
//!
//! The bits module contains the bit manipulation functions and structures used by the SHDP protocol.
//! It is used to handle the bits that are sent and received by the protocol.
//!
pub use crate::protocol::managers::bits::decoder::*;
pub use crate::protocol::managers::bits::encoder::*;
pub mod util {
//!
//! The util module contains the utility functions used by the SHDP protocol.
//! It is used to handle utility functions that may be used by the protocol.
//!
pub use crate::protocol::managers::bits::prelude::*;
}
}
pub mod event {
//!
//! The event module contains the event structures and functions used by the SHDP protocol.
//! It is used to handle events that may occur during the protocol execution.
//!
pub use crate::protocol::managers::event::*;
}
pub mod error {
//!
//! The error module contains the error structures and functions used by the SHDP protocol.
//! It is used to handle errors that may occur during the protocol execution.
//!
pub use crate::protocol::errors::*;
}
pub mod registry {
//!
//! The registry module contains the registry structures and functions used by the SHDP protocol.
//! It is used to store events and listeners that will be by each the server and the client.
//!
pub use crate::protocol::managers::registry::*;
}
}
///
/// A RemoteId is a tuple of two strings, the first being the remote's host address and the second being the remote's port.
///
pub type RemoteId = (String, String);