initial modem commit
This commit is contained in:
parent
3181706ef3
commit
9b5c37ceb3
9 changed files with 344 additions and 55 deletions
97
Cargo.lock
generated
97
Cargo.lock
generated
|
@ -10,23 +10,37 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "enum-ordinalize"
|
name = "enum-ordinalize"
|
||||||
version = "3.1.12"
|
version = "3.1.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a62bb1df8b45ecb7ffa78dca1c17a438fb193eb083db0b1b494d2a61bcb5096a"
|
checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"rustc_version",
|
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "ioctl-rs"
|
||||||
version = "0.4.3"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
|
checksum = "f7970510895cee30b3e9128319f2cefd4bde883a39f38baa279567ba3a7eb97d"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.148"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
|
@ -45,27 +59,27 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.15"
|
version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.50"
|
version = "1.0.67"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
|
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.23"
|
version = "1.0.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
@ -75,28 +89,56 @@ name = "revpfw3"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"enum-ordinalize",
|
"enum-ordinalize",
|
||||||
|
"serial",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "serial"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
checksum = "a1237a96570fc377c13baa1b88c7589ab66edced652e43ffb17088f003db3e86"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"semver",
|
"serial-core",
|
||||||
|
"serial-unix",
|
||||||
|
"serial-windows",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "serial-core"
|
||||||
version = "1.0.16"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
checksum = "3f46209b345401737ae2125fe5b19a77acce90cd53e1658cda928e4fe9a64581"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serial-unix"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f03fbca4c9d866e24a459cbca71283f545a37f8e3e002ad8c70593871453cab7"
|
||||||
|
dependencies = [
|
||||||
|
"ioctl-rs",
|
||||||
|
"libc",
|
||||||
|
"serial-core",
|
||||||
|
"termios",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serial-windows"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15c6d3b776267a75d31bbdfd5d36c0ca051251caafc285827052bc53bcdc8162"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"serial-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.107"
|
version = "2.0.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -104,7 +146,16 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "termios"
|
||||||
version = "1.0.6"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
checksum = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
|
@ -10,3 +10,4 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
enum-ordinalize = "3.1"
|
enum-ordinalize = "3.1"
|
||||||
|
serial = "0.4"
|
||||||
|
|
28
modem-init.txt
Normal file
28
modem-init.txt
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
AT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AT+CFUN?
|
||||||
|
AT+CPIN?
|
||||||
|
AT+CIPMODE=1
|
||||||
|
|
||||||
|
AT+CSTT="internet.telekom","",""
|
||||||
|
AT+CIICR
|
||||||
|
|
||||||
|
|
||||||
|
AT+CIFSR
|
||||||
|
AT+CIPSTART=TCP,"$IP",$PORT
|
|
@ -1,27 +1,89 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io::Read,
|
io::{Read, Write},
|
||||||
io::Write,
|
|
||||||
net::{Shutdown, TcpStream},
|
net::{Shutdown, TcpStream},
|
||||||
thread,
|
thread,
|
||||||
time::{Duration, SystemTime},
|
time::{Duration, SystemTime},
|
||||||
vec,
|
vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{io_sync, PacketType, SocketAdapter};
|
use serial::SerialPort;
|
||||||
|
|
||||||
pub fn client(ip: &str, port: u16, dest_ip: &str, dest_port: u16, key: &str, sleep_delay_ms: u64) {
|
use crate::{io_sync, Connection, PacketType, SocketAdapter};
|
||||||
|
|
||||||
|
pub struct ClientParams<'a> {
|
||||||
|
pub server_ip: &'a str,
|
||||||
|
pub server_port: u16,
|
||||||
|
pub dest_ip: &'a str,
|
||||||
|
pub dest_port: u16,
|
||||||
|
pub key: &'a str,
|
||||||
|
pub sleep_delay_ms: u64,
|
||||||
|
pub modem_port: Option<&'a str>,
|
||||||
|
pub modem_baud: Option<u32>,
|
||||||
|
pub modem_init: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect(params: &ClientParams) -> Connection {
|
||||||
|
if let Some(modem_port) = params.modem_port {
|
||||||
|
let mut serial = serial::open(modem_port).unwrap();
|
||||||
|
serial
|
||||||
|
.configure(&serial::PortSettings {
|
||||||
|
baud_rate: serial::BaudRate::from_speed(
|
||||||
|
params.modem_baud.unwrap_or(115200) as usize
|
||||||
|
),
|
||||||
|
char_size: serial::CharSize::Bits8,
|
||||||
|
parity: serial::Parity::ParityNone,
|
||||||
|
stop_bits: serial::StopBits::Stop1,
|
||||||
|
flow_control: serial::FlowControl::FlowNone,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
if let Some(modem_init) = params.modem_init {
|
||||||
|
serial.set_timeout(Duration::from_millis(200)).unwrap();
|
||||||
|
for line in modem_init.lines() {
|
||||||
|
let line = line
|
||||||
|
.replace("$IP", ¶ms.server_ip.to_string())
|
||||||
|
.replace("$PORT", ¶ms.server_port.to_string());
|
||||||
|
println!("> {line}");
|
||||||
|
serial.write_all((line + "\r\n").as_bytes()).unwrap();
|
||||||
|
let mut s = Vec::new();
|
||||||
|
let _ = serial.read_to_end(&mut s).is_ok();
|
||||||
|
if !s.is_empty() {
|
||||||
|
println!(
|
||||||
|
"< {}",
|
||||||
|
String::from_utf8(s).unwrap().replace("\n", "\n< ").trim()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
thread::sleep(Duration::from_millis(300));
|
||||||
|
}
|
||||||
|
serial.set_timeout(Duration::from_millis(3000)).unwrap();
|
||||||
|
let mut s = Vec::new();
|
||||||
|
let _ = serial.read_to_end(&mut s).is_ok();
|
||||||
|
if !s.is_empty() {
|
||||||
|
println!(
|
||||||
|
"< {}",
|
||||||
|
String::from_utf8(s).unwrap().replace("\n", "\n< ").trim()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serial.set_timeout(Duration::from_millis(10000)).unwrap();
|
||||||
|
return Connection::new_serial(serial);
|
||||||
|
}
|
||||||
|
Connection::new_tcp(TcpStream::connect((params.server_ip, params.server_port)).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn client(params: ClientParams) {
|
||||||
let mut buf1 = [0u8; 1];
|
let mut buf1 = [0u8; 1];
|
||||||
let mut buf4 = [0u8; 4];
|
let mut buf4 = [0u8; 4];
|
||||||
let mut buf8 = [0u8; 8];
|
let mut buf8 = [0u8; 8];
|
||||||
let mut buf16 = [0u8; 16];
|
let mut buf16 = [0u8; 16];
|
||||||
let mut buf = [0; 1024];
|
let mut buf = [0; 1024];
|
||||||
let mut tcp = TcpStream::connect((ip, port)).unwrap();
|
let mut tcp = connect(¶ms);
|
||||||
println!("Syncing...");
|
println!("Syncing...");
|
||||||
tcp.write_all(&[b'R', b'P', b'F', 30]).unwrap();
|
tcp.write_all(&[b'R', b'P', b'F', 30]).unwrap();
|
||||||
println!("Authenticating...");
|
println!("Authenticating...");
|
||||||
tcp.write_all(&(key.len() as u32).to_be_bytes()).unwrap();
|
tcp.write_all(&(params.key.len() as u32).to_be_bytes())
|
||||||
tcp.write_all(key.as_bytes()).unwrap();
|
.unwrap();
|
||||||
|
tcp.write_all(params.key.as_bytes()).unwrap();
|
||||||
|
|
||||||
println!("Syncing...");
|
println!("Syncing...");
|
||||||
tcp.read_exact(&mut buf4).unwrap();
|
tcp.read_exact(&mut buf4).unwrap();
|
||||||
|
@ -77,7 +139,7 @@ pub fn client(ip: &str, port: u16, dest_ip: &str, dest_port: u16, key: &str, sle
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tcp.write(&i.to_be_bytes()).unwrap();
|
tcp.write(&i.to_be_bytes()).unwrap();
|
||||||
if let Some(x) = sockets.remove(&i) {
|
if let Some(x) = sockets.remove(&i) {
|
||||||
let _ = x.internal.shutdown(Shutdown::Both);
|
let _ = x.internal.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +149,7 @@ pub fn client(ip: &str, port: u16, dest_ip: &str, dest_port: u16, key: &str, sle
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
if !did_anything {
|
if !did_anything {
|
||||||
thread::sleep(Duration::from_millis(sleep_delay_ms));
|
thread::sleep(Duration::from_millis(params.sleep_delay_ms));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +159,9 @@ pub fn client(ip: &str, port: u16, dest_ip: &str, dest_port: u16, key: &str, sle
|
||||||
tcp.set_nonblocking(false);
|
tcp.set_nonblocking(false);
|
||||||
match pt {
|
match pt {
|
||||||
PacketType::NewClient => {
|
PacketType::NewClient => {
|
||||||
let mut tcp = SocketAdapter::new(TcpStream::connect((dest_ip, dest_port)).unwrap());
|
let mut tcp = SocketAdapter::new(Connection::new_tcp(
|
||||||
|
TcpStream::connect((params.dest_ip, params.dest_port)).unwrap(),
|
||||||
|
));
|
||||||
tcp.set_nonblocking(true);
|
tcp.set_nonblocking(true);
|
||||||
sockets.insert((id, id += 1).0, tcp);
|
sockets.insert((id, id += 1).0, tcp);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +169,7 @@ pub fn client(ip: &str, port: u16, dest_ip: &str, dest_port: u16, key: &str, sle
|
||||||
PacketType::CloseClient => {
|
PacketType::CloseClient => {
|
||||||
tcp.internal.read_exact(&mut buf8).unwrap();
|
tcp.internal.read_exact(&mut buf8).unwrap();
|
||||||
if let Some(x) = sockets.remove(&u64::from_be_bytes(buf8)) {
|
if let Some(x) = sockets.remove(&u64::from_be_bytes(buf8)) {
|
||||||
let _ = x.internal.shutdown(Shutdown::Both);
|
let _ = x.internal.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
mod client;
|
mod client;
|
||||||
mod packet;
|
mod packet;
|
||||||
mod server;
|
mod server;
|
||||||
|
mod server_connection;
|
||||||
mod socket_adapter;
|
mod socket_adapter;
|
||||||
|
|
||||||
use std::io::{Error, ErrorKind};
|
use std::io::{Error, ErrorKind};
|
||||||
|
@ -8,12 +9,14 @@ use std::io::{Error, ErrorKind};
|
||||||
pub use client::*;
|
pub use client::*;
|
||||||
pub(crate) use packet::*;
|
pub(crate) use packet::*;
|
||||||
pub use server::*;
|
pub use server::*;
|
||||||
|
pub(crate) use server_connection::*;
|
||||||
pub(crate) use socket_adapter::*;
|
pub(crate) use socket_adapter::*;
|
||||||
|
|
||||||
pub(crate) fn io_sync<T>(result: Result<T, Error>) -> Result<Option<T>, Error> {
|
pub(crate) fn io_sync<T>(result: Result<T, Error>) -> Result<Option<T>, Error> {
|
||||||
match result {
|
match result {
|
||||||
Ok(x) => Ok(Some(x)),
|
Ok(x) => Ok(Some(x)),
|
||||||
Err(x) if x.kind() == ErrorKind::WouldBlock => Ok(None),
|
Err(x) if x.kind() == ErrorKind::WouldBlock => Ok(None),
|
||||||
|
Err(x) if x.kind() == ErrorKind::TimedOut => Ok(None),
|
||||||
Err(x) => Err(x),
|
Err(x) => Err(x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
src/main.rs
25
src/main.rs
|
@ -1,22 +1,25 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use revpfw3::{client, server};
|
use revpfw3::{client, server, ClientParams};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Vec<_> = env::args().skip(1).collect();
|
let args: Vec<_> = env::args().skip(1).collect();
|
||||||
if (6..=7).contains(&args.len()) && args[0] == "client" {
|
if (6..=10).contains(&args.len()) && args[0] == "client" {
|
||||||
client(
|
client(ClientParams {
|
||||||
&args[1],
|
server_ip: &args[1],
|
||||||
args[2].parse().unwrap(),
|
server_port: args[2].parse().unwrap(),
|
||||||
&args[3],
|
dest_ip: &args[3],
|
||||||
args[4].parse().unwrap(),
|
dest_port: args[4].parse().unwrap(),
|
||||||
&args[5],
|
key: &args[5],
|
||||||
if args.len() == 7 {
|
sleep_delay_ms: if args.len() == 7 {
|
||||||
args[6].parse().unwrap()
|
args[6].parse().unwrap()
|
||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
},
|
},
|
||||||
);
|
modem_port: args.get(7).map(|x| x.as_str()),
|
||||||
|
modem_baud: args.get(8).map(|x| x.parse().unwrap()),
|
||||||
|
modem_init: args.get(9).map(|x| x.as_str()),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (3..=4).contains(&args.len()) && args[0] == "server" {
|
if (3..=4).contains(&args.len()) && args[0] == "server" {
|
||||||
server(
|
server(
|
||||||
|
@ -31,5 +34,5 @@ fn main() {
|
||||||
}
|
}
|
||||||
eprintln!("Usage: \n\
|
eprintln!("Usage: \n\
|
||||||
\x20 revpfw3 server <port> <key> [<poll delay>]\n\
|
\x20 revpfw3 server <port> <key> [<poll delay>]\n\
|
||||||
\x20 revpfw3 client <server ip> <server port> <destination ip> <destination port> <key> [<poll delay>]");
|
\x20 revpfw3 client <server ip> <server port> <destination ip> <destination port> <key> [<poll delay> [<modem port> <modem baud> <modem init>]]");
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::{
|
||||||
vec,
|
vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{io_sync, PacketType, SocketAdapter};
|
use crate::{io_sync, Connection, PacketType, SocketAdapter};
|
||||||
|
|
||||||
pub fn server(port: u16, key: &str, sleep_delay_ms: u64) {
|
pub fn server(port: u16, key: &str, sleep_delay_ms: u64) {
|
||||||
let mut buf1 = [0u8; 1];
|
let mut buf1 = [0u8; 1];
|
||||||
|
@ -42,7 +42,7 @@ pub fn server(port: u16, key: &str, sleep_delay_ms: u64) {
|
||||||
|
|
||||||
tcpl.set_nonblocking(true).unwrap();
|
tcpl.set_nonblocking(true).unwrap();
|
||||||
|
|
||||||
let mut tcp = SocketAdapter::new(tcp);
|
let mut tcp = SocketAdapter::new(Connection::new_tcp(tcp));
|
||||||
tcp.set_nonblocking(true);
|
tcp.set_nonblocking(true);
|
||||||
let mut sockets: HashMap<u64, SocketAdapter> = HashMap::new();
|
let mut sockets: HashMap<u64, SocketAdapter> = HashMap::new();
|
||||||
let mut id = 0;
|
let mut id = 0;
|
||||||
|
@ -51,7 +51,7 @@ pub fn server(port: u16, key: &str, sleep_delay_ms: u64) {
|
||||||
loop {
|
loop {
|
||||||
let mut did_anything = false;
|
let mut did_anything = false;
|
||||||
|
|
||||||
if last_keep_alive_sent.elapsed().unwrap().as_secs() >= 20 {
|
if last_keep_alive_sent.elapsed().unwrap().as_secs() >= 10 {
|
||||||
last_keep_alive_sent = SystemTime::now();
|
last_keep_alive_sent = SystemTime::now();
|
||||||
tcp.write(&[PacketType::KeepAlive.ordinal() as u8]).unwrap();
|
tcp.write(&[PacketType::KeepAlive.ordinal() as u8]).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ pub fn server(port: u16, key: &str, sleep_delay_ms: u64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(new) = tcpl.accept() {
|
if let Ok(new) = tcpl.accept() {
|
||||||
let mut new = SocketAdapter::new(new.0);
|
let mut new = SocketAdapter::new(Connection::new_tcp(new.0));
|
||||||
new.set_nonblocking(true);
|
new.set_nonblocking(true);
|
||||||
sockets.insert((id, id += 1).0, new);
|
sockets.insert((id, id += 1).0, new);
|
||||||
tcp.write(&[PacketType::NewClient.ordinal() as u8]).unwrap();
|
tcp.write(&[PacketType::NewClient.ordinal() as u8]).unwrap();
|
||||||
|
@ -99,7 +99,7 @@ pub fn server(port: u16, key: &str, sleep_delay_ms: u64) {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tcp.write(&i.to_be_bytes()).unwrap();
|
tcp.write(&i.to_be_bytes()).unwrap();
|
||||||
if let Some(x) = sockets.remove(&i) {
|
if let Some(x) = sockets.remove(&i) {
|
||||||
let _ = x.internal.shutdown(Shutdown::Both);
|
let _ = x.internal.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ pub fn server(port: u16, key: &str, sleep_delay_ms: u64) {
|
||||||
PacketType::CloseClient => {
|
PacketType::CloseClient => {
|
||||||
tcp.internal.read_exact(&mut buf8).unwrap();
|
tcp.internal.read_exact(&mut buf8).unwrap();
|
||||||
if let Some(x) = sockets.remove(&u64::from_be_bytes(buf8)) {
|
if let Some(x) = sockets.remove(&u64::from_be_bytes(buf8)) {
|
||||||
let _ = x.internal.shutdown(Shutdown::Both);
|
let _ = x.internal.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
139
src/server_connection.rs
Normal file
139
src/server_connection.rs
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
use std::{
|
||||||
|
io::{self, ErrorKind, Read, Write},
|
||||||
|
net::{Shutdown, TcpStream},
|
||||||
|
ptr::NonNull,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use serial::SerialPort;
|
||||||
|
|
||||||
|
trait ReadWrite: Write + Read + 'static {}
|
||||||
|
impl<T> ReadWrite for T where T: Write + Read + 'static {}
|
||||||
|
|
||||||
|
pub struct Connection {
|
||||||
|
readwrite: Box<dyn ReadWrite>,
|
||||||
|
data: NonNull<()>,
|
||||||
|
set_nonblocking_thunk: fn(NonNull<()>, bool) -> io::Result<()>,
|
||||||
|
close_thunk: fn(NonNull<()>) -> io::Result<()>,
|
||||||
|
is_nb: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for Connection {
|
||||||
|
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
|
||||||
|
self.as_write().write_vectored(bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_all(&mut self, mut buf: &[u8]) -> io::Result<()> {
|
||||||
|
self.as_write().write_all(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> {
|
||||||
|
self.as_write().write_fmt(fmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn by_ref(&mut self) -> &mut Self
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
self.as_write().write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
self.as_write().flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Read for Connection {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
self.as_read().read(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
|
self.as_read().read_vectored(bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
|
self.as_read().read_to_end(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||||
|
self.as_read().read_to_string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_exact(&mut self, mut buf: &mut [u8]) -> io::Result<()> {
|
||||||
|
while !buf.is_empty() {
|
||||||
|
match self.read(buf) {
|
||||||
|
Ok(0) if self.is_nb => {
|
||||||
|
return Err(io::Error::new(ErrorKind::WouldBlock, "would block"))
|
||||||
|
}
|
||||||
|
Ok(0) => (),
|
||||||
|
Ok(n) => {
|
||||||
|
let tmp = buf;
|
||||||
|
buf = &mut tmp[n..];
|
||||||
|
}
|
||||||
|
Err(ref e) if e.kind() == ErrorKind::Interrupted => (),
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !buf.is_empty() {
|
||||||
|
Err(io::Error::new(
|
||||||
|
ErrorKind::UnexpectedEof,
|
||||||
|
"failed to fill whole buffer",
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Connection {
|
||||||
|
pub fn new_tcp(stream: TcpStream) -> Self {
|
||||||
|
let mut stream = Box::new(stream);
|
||||||
|
Connection {
|
||||||
|
data: NonNull::from(stream.as_mut()).cast(),
|
||||||
|
readwrite: stream,
|
||||||
|
set_nonblocking_thunk: |data, nb| unsafe {
|
||||||
|
data.cast::<TcpStream>().as_ref().set_nonblocking(nb)
|
||||||
|
},
|
||||||
|
close_thunk: |data| unsafe {
|
||||||
|
data.cast::<TcpStream>().as_ref().shutdown(Shutdown::Both)
|
||||||
|
},
|
||||||
|
is_nb: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn new_serial<T: SerialPort + 'static>(serial: T) -> Self {
|
||||||
|
let mut serial = Box::new(serial);
|
||||||
|
Connection {
|
||||||
|
data: NonNull::from(serial.as_mut()).cast(),
|
||||||
|
readwrite: serial,
|
||||||
|
set_nonblocking_thunk: |data, nb| unsafe {
|
||||||
|
data.cast::<T>()
|
||||||
|
.as_mut()
|
||||||
|
.set_timeout(Duration::from_millis(if nb { 1 } else { 10000 }))
|
||||||
|
.map_err(|_| {
|
||||||
|
io::Error::new(io::ErrorKind::ConnectionAborted, "serial port went down")
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// no need to close this.
|
||||||
|
close_thunk: |_data| Ok(()),
|
||||||
|
is_nb: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn as_read(&mut self) -> &mut (dyn Read) {
|
||||||
|
&mut self.readwrite
|
||||||
|
}
|
||||||
|
fn as_write(&mut self) -> &mut (dyn Write) {
|
||||||
|
&mut self.readwrite
|
||||||
|
}
|
||||||
|
pub fn set_nonblocking(&mut self, nonblocking: bool) -> io::Result<()> {
|
||||||
|
self.is_nb = nonblocking;
|
||||||
|
(self.set_nonblocking_thunk)(self.data, nonblocking)
|
||||||
|
}
|
||||||
|
pub fn close(&self) -> io::Result<()> {
|
||||||
|
(self.close_thunk)(self.data)
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ use std::{
|
||||||
time::SystemTime,
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::io_sync;
|
use crate::{io_sync, Connection};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
enum Broken {
|
enum Broken {
|
||||||
|
@ -23,7 +23,7 @@ impl From<Broken> for Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct SocketAdapter {
|
pub(crate) struct SocketAdapter {
|
||||||
pub(crate) internal: TcpStream,
|
pub(crate) internal: Connection,
|
||||||
written: usize,
|
written: usize,
|
||||||
to_write: usize,
|
to_write: usize,
|
||||||
write: [u8; 65536],
|
write: [u8; 65536],
|
||||||
|
@ -34,9 +34,9 @@ pub(crate) struct SocketAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SocketAdapter {
|
impl SocketAdapter {
|
||||||
pub fn new(tcp: TcpStream) -> SocketAdapter {
|
pub fn new(connection: Connection) -> SocketAdapter {
|
||||||
Self {
|
Self {
|
||||||
internal: tcp,
|
internal: connection,
|
||||||
written: 0,
|
written: 0,
|
||||||
to_write: 0,
|
to_write: 0,
|
||||||
write: [0u8; 65536],
|
write: [0u8; 65536],
|
||||||
|
|
Loading…
Add table
Reference in a new issue