diff options
| -rw-r--r-- | Cargo.toml | 11 | ||||
| -rw-r--r-- | src/lib.rs | 6 | ||||
| -rw-r--r-- | src/main.rs | 84 | ||||
| -rw-r--r-- | src/protocol/ip.rs | 61 | ||||
| -rw-r--r-- | src/protocol/mod.rs | 7 |
5 files changed, 169 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..4f620bb --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "rust_unix_server" +version = "0.1.0" +edition = "2021" + +[dependencies] +bytes = "1.0" +nom = "7" +tokio-util = { version = "0.6", features = ["codec"] } +tokio-stream = { version = "0.1" } +tokio = { version = "1", features = ["macros", "net", "rt-multi-thread"] }
\ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..9618ba3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,6 @@ +pub mod codec_eth; +pub mod codec_ipv4; +pub mod codec_pkt; +pub mod codec_tcp; + +pub mod protocol;
\ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..9df3beb --- /dev/null +++ b/src/main.rs @@ -0,0 +1,84 @@ +use bytes::BytesMut; +//use rust_unix_server::codec_eth::EthCodec; +//use rust_unix_server::codec_ipv4::IPv4Codec; +//use rust_unix_server::codec_tcp::TcpCodec; +use rust_unix_server::codec_pkt::PktCodec; +use std::io; +use tokio::net::UnixListener; +use tokio_stream::StreamExt; +use tokio_util::codec::Decoder; +use tokio_util::codec::Encoder; + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Default)] +pub struct MyCodec<C>(C); + +impl<C> MyCodec<C> { + pub fn new(c: C) -> Self { + MyCodec(c) + } +} + +impl<C> Decoder for MyCodec<C> +where + C: Decoder, + std::io::Error: From<<C as Decoder>::Error>, +{ + type Item = C::Item; + type Error = io::Error; + + fn decode(&mut self, data: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> { + if !data.is_empty() { + println!("MyCodec -> decode(), handle data len: {}", data.len()); + + let decoded = self.0.decode(data)?; + match decoded { + None => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("Frame of length {} is too large.", 111), + )); + } + Some(inner) => Ok(Some(inner)), + } + } else { + Ok(None) + } + } +} + +impl<C, T> Encoder<T> for MyCodec<C> +where + C: Encoder<T>, + std::io::Error: From<C::Error>, +{ + type Error = io::Error; + + fn encode(&mut self, _item: T, _buf: &mut BytesMut) -> Result<(), io::Error> { + // TODO + Ok(()) + } +} + +// nc -U /Users/lwp/Downloads/temp.sock +#[tokio::main] +async fn main() -> Result<(), Box<dyn std::error::Error>> { + let listener = UnixListener::bind("/Users/lwp/Downloads/temp.sock")?; + loop { + let (socket, _) = listener.accept().await?; + + tokio::spawn(async move { + let mut framed = tokio_util::codec::Framed::new( + socket, + // MyCodec::new(EthCodec::new(IPv4Codec::new(TcpCodec::new()))), + PktCodec::new(), + ); + while let Some(message) = framed.next().await { + match message { + Ok(bytes) => println!("bytes: {:?}", bytes), + Err(err) => println!("Socket closed with error: {:?}", err), + } + } + println!("Client closed the connection"); + }); + } +} diff --git a/src/protocol/ip.rs b/src/protocol/ip.rs new file mode 100644 index 0000000..4c6dddf --- /dev/null +++ b/src/protocol/ip.rs @@ -0,0 +1,61 @@ +use nom::number; +use nom::IResult; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum IPProtocol { + HOPOPT, + ICMP, + IGMP, + GGP, + IPINIP, + ST, + TCP, + CBT, + EGP, + IGP, + BBNRCCMON, + NVPII, + PUP, + ARGUS, + EMCON, + XNET, + CHAOS, + UDP, + IPV6, + ICMP6, + Other(u8), +} + +impl From<u8> for IPProtocol { + fn from(raw: u8) -> Self { + match raw { + 0 => IPProtocol::HOPOPT, + 1 => IPProtocol::ICMP, + 2 => IPProtocol::IGMP, + 3 => IPProtocol::GGP, + 4 => IPProtocol::IPINIP, + 5 => IPProtocol::ST, + 6 => IPProtocol::TCP, + 7 => IPProtocol::CBT, + 8 => IPProtocol::EGP, + 9 => IPProtocol::IGP, + 10 => IPProtocol::BBNRCCMON, + 11 => IPProtocol::NVPII, + 12 => IPProtocol::PUP, + 13 => IPProtocol::ARGUS, + 14 => IPProtocol::EMCON, + 15 => IPProtocol::XNET, + 16 => IPProtocol::CHAOS, + 17 => IPProtocol::UDP, + 41 => IPProtocol::IPV6, + 58 => IPProtocol::ICMP6, + other => IPProtocol::Other(other), + } + } +} + +pub(crate) fn protocol(input: &[u8]) -> IResult<&[u8], IPProtocol> { + let (input, protocol) = number::streaming::be_u8(input)?; + + Ok((input, protocol.into())) +} diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs new file mode 100644 index 0000000..ec0d292 --- /dev/null +++ b/src/protocol/mod.rs @@ -0,0 +1,7 @@ +pub mod dns; +pub mod ethernet; +pub mod ip; +pub mod ipv4; +pub mod ipv6; +pub mod tcp; +pub mod udp; |
