summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml11
-rw-r--r--src/lib.rs6
-rw-r--r--src/main.rs84
-rw-r--r--src/protocol/ip.rs61
-rw-r--r--src/protocol/mod.rs7
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;