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]]
|
||||
name = "enum-ordinalize"
|
||||
version = "3.1.12"
|
||||
version = "3.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a62bb1df8b45ecb7ffa78dca1c17a438fb193eb083db0b1b494d2a61bcb5096a"
|
||||
checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.3"
|
||||
name = "ioctl-rs"
|
||||
version = "0.1.6"
|
||||
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 = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
|
@ -45,27 +59,27 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.50"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
|
||||
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -75,28 +89,56 @@ name = "revpfw3"
|
|||
version = "0.3.1"
|
||||
dependencies = [
|
||||
"enum-ordinalize",
|
||||
"serial",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
name = "serial"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
checksum = "a1237a96570fc377c13baa1b88c7589ab66edced652e43ffb17088f003db3e86"
|
||||
dependencies = [
|
||||
"semver",
|
||||
"serial-core",
|
||||
"serial-unix",
|
||||
"serial-windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.16"
|
||||
name = "serial-core"
|
||||
version = "0.4.0"
|
||||
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]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
version = "2.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -104,7 +146,16 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
name = "termios"
|
||||
version = "0.2.2"
|
||||
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]
|
||||
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::{
|
||||
collections::HashMap,
|
||||
io::Read,
|
||||
io::Write,
|
||||
io::{Read, Write},
|
||||
net::{Shutdown, TcpStream},
|
||||
thread,
|
||||
time::{Duration, SystemTime},
|
||||
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 buf4 = [0u8; 4];
|
||||
let mut buf8 = [0u8; 8];
|
||||
let mut buf16 = [0u8; 16];
|
||||
let mut buf = [0; 1024];
|
||||
let mut tcp = TcpStream::connect((ip, port)).unwrap();
|
||||
let mut tcp = connect(¶ms);
|
||||
println!("Syncing...");
|
||||
tcp.write_all(&[b'R', b'P', b'F', 30]).unwrap();
|
||||
println!("Authenticating...");
|
||||
tcp.write_all(&(key.len() as u32).to_be_bytes()).unwrap();
|
||||
tcp.write_all(key.as_bytes()).unwrap();
|
||||
tcp.write_all(&(params.key.len() as u32).to_be_bytes())
|
||||
.unwrap();
|
||||
tcp.write_all(params.key.as_bytes()).unwrap();
|
||||
|
||||
println!("Syncing...");
|
||||
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();
|
||||
tcp.write(&i.to_be_bytes()).unwrap();
|
||||
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()
|
||||
{
|
||||
if !did_anything {
|
||||
thread::sleep(Duration::from_millis(sleep_delay_ms));
|
||||
thread::sleep(Duration::from_millis(params.sleep_delay_ms));
|
||||
}
|
||||
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);
|
||||
match pt {
|
||||
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);
|
||||
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 => {
|
||||
tcp.internal.read_exact(&mut buf8).unwrap();
|
||||
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 packet;
|
||||
mod server;
|
||||
mod server_connection;
|
||||
mod socket_adapter;
|
||||
|
||||
use std::io::{Error, ErrorKind};
|
||||
|
@ -8,12 +9,14 @@ use std::io::{Error, ErrorKind};
|
|||
pub use client::*;
|
||||
pub(crate) use packet::*;
|
||||
pub use server::*;
|
||||
pub(crate) use server_connection::*;
|
||||
pub(crate) use socket_adapter::*;
|
||||
|
||||
pub(crate) fn io_sync<T>(result: Result<T, Error>) -> Result<Option<T>, Error> {
|
||||
match result {
|
||||
Ok(x) => Ok(Some(x)),
|
||||
Err(x) if x.kind() == ErrorKind::WouldBlock => Ok(None),
|
||||
Err(x) if x.kind() == ErrorKind::TimedOut => Ok(None),
|
||||
Err(x) => Err(x),
|
||||
}
|
||||
}
|
||||
|
|
25
src/main.rs
25
src/main.rs
|
@ -1,22 +1,25 @@
|
|||
use std::env;
|
||||
|
||||
use revpfw3::{client, server};
|
||||
use revpfw3::{client, server, ClientParams};
|
||||
|
||||
fn main() {
|
||||
let args: Vec<_> = env::args().skip(1).collect();
|
||||
if (6..=7).contains(&args.len()) && args[0] == "client" {
|
||||
client(
|
||||
&args[1],
|
||||
args[2].parse().unwrap(),
|
||||
&args[3],
|
||||
args[4].parse().unwrap(),
|
||||
&args[5],
|
||||
if args.len() == 7 {
|
||||
if (6..=10).contains(&args.len()) && args[0] == "client" {
|
||||
client(ClientParams {
|
||||
server_ip: &args[1],
|
||||
server_port: args[2].parse().unwrap(),
|
||||
dest_ip: &args[3],
|
||||
dest_port: args[4].parse().unwrap(),
|
||||
key: &args[5],
|
||||
sleep_delay_ms: if args.len() == 7 {
|
||||
args[6].parse().unwrap()
|
||||
} else {
|
||||
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" {
|
||||
server(
|
||||
|
@ -31,5 +34,5 @@ fn main() {
|
|||
}
|
||||
eprintln!("Usage: \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,
|
||||
};
|
||||
|
||||
use crate::{io_sync, PacketType, SocketAdapter};
|
||||
use crate::{io_sync, Connection, PacketType, SocketAdapter};
|
||||
|
||||
pub fn server(port: u16, key: &str, sleep_delay_ms: u64) {
|
||||
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();
|
||||
|
||||
let mut tcp = SocketAdapter::new(tcp);
|
||||
let mut tcp = SocketAdapter::new(Connection::new_tcp(tcp));
|
||||
tcp.set_nonblocking(true);
|
||||
let mut sockets: HashMap<u64, SocketAdapter> = HashMap::new();
|
||||
let mut id = 0;
|
||||
|
@ -51,7 +51,7 @@ pub fn server(port: u16, key: &str, sleep_delay_ms: u64) {
|
|||
loop {
|
||||
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();
|
||||
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() {
|
||||
let mut new = SocketAdapter::new(new.0);
|
||||
let mut new = SocketAdapter::new(Connection::new_tcp(new.0));
|
||||
new.set_nonblocking(true);
|
||||
sockets.insert((id, id += 1).0, new);
|
||||
tcp.write(&[PacketType::NewClient.ordinal() as u8]).unwrap();
|
||||
|
@ -99,7 +99,7 @@ pub fn server(port: u16, key: &str, sleep_delay_ms: u64) {
|
|||
.unwrap();
|
||||
tcp.write(&i.to_be_bytes()).unwrap();
|
||||
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 => {
|
||||
tcp.internal.read_exact(&mut buf8).unwrap();
|
||||
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,
|
||||
};
|
||||
|
||||
use crate::io_sync;
|
||||
use crate::{io_sync, Connection};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Broken {
|
||||
|
@ -23,7 +23,7 @@ impl From<Broken> for Error {
|
|||
}
|
||||
|
||||
pub(crate) struct SocketAdapter {
|
||||
pub(crate) internal: TcpStream,
|
||||
pub(crate) internal: Connection,
|
||||
written: usize,
|
||||
to_write: usize,
|
||||
write: [u8; 65536],
|
||||
|
@ -34,9 +34,9 @@ pub(crate) struct SocketAdapter {
|
|||
}
|
||||
|
||||
impl SocketAdapter {
|
||||
pub fn new(tcp: TcpStream) -> SocketAdapter {
|
||||
pub fn new(connection: Connection) -> SocketAdapter {
|
||||
Self {
|
||||
internal: tcp,
|
||||
internal: connection,
|
||||
written: 0,
|
||||
to_write: 0,
|
||||
write: [0u8; 65536],
|
||||
|
|
Loading…
Add table
Reference in a new issue