Răsfoiți Sursa

ircd: irc server support tls protocol

ghassmo 4 ani în urmă
părinte
comite
f625dc23eb

+ 2 - 0
Cargo.lock

@@ -2266,6 +2266,7 @@ dependencies = [
  "darkfi",
  "easy-parallel",
  "futures",
+ "futures-rustls",
  "fxhash",
  "log",
  "rand",
@@ -2275,6 +2276,7 @@ dependencies = [
  "smol",
  "structopt",
  "structopt-toml",
+ "url",
 ]
 
 [[package]]

+ 2 - 0
bin/ircd/Cargo.toml

@@ -13,6 +13,7 @@ darkfi = {path = "../../", features = ["net", "rpc", "raft"]}
 # Async
 smol = "1.2.5"
 futures = "0.3.21"
+futures-rustls = "0.22.1"
 async-std = "1.11.0"
 async-trait = "0.1.53"
 async-channel = "1.6.1"
@@ -28,6 +29,7 @@ log = "0.4.16"
 simplelog = "0.12.0-alpha1"
 fxhash = "0.2.1"
 ctrlc-async = {version= "3.2.2", default-features = false, features = ["async-std", "termination"]}
+url = "2.2.2"
 
 # Encoding and parsing
 serde_json = "1.0.79"

+ 1 - 1
bin/ircd/ircd_config.toml

@@ -2,7 +2,7 @@
 #rpc_listen="127.0.0.1:11055"
 
 ## IRC listen URL
-#irc_listen="127.0.0.1:11066"
+#irc_listen="tcp://127.0.0.1:11066"
 
 ## Sets Datastore Path
 #datastore="~/.config/ircd"

+ 72 - 32
bin/ircd/src/main.rs

@@ -1,13 +1,24 @@
 use async_std::{
-    net::{TcpListener, TcpStream},
+    net::TcpStream,
     sync::{Arc, Mutex},
 };
 use std::net::SocketAddr;
 
 use async_channel::{Receiver, Sender};
 use async_executor::Executor;
+use easy_parallel::Parallel;
+use futures::{
+    io::BufReader, AsyncBufReadExt, AsyncRead, AsyncReadExt, AsyncWrite, FutureExt, StreamExt,
+};
+use futures_rustls::TlsStream;
+use log::{debug, error, info, warn};
+use simplelog::{ColorChoice, TermLogger, TerminalMode};
+use smol::future;
+use structopt_toml::StructOptToml;
+
 use darkfi::{
     async_daemonize,
+    net::transport::{TcpTransport, TlsTransport, Transport},
     raft::Raft,
     rpc::rpcserver::{listen_and_serve, RpcServerConfig},
     util::{
@@ -16,12 +27,6 @@ use darkfi::{
     },
     Error, Result,
 };
-use easy_parallel::Parallel;
-use futures::{io::BufReader, AsyncBufReadExt, AsyncReadExt, FutureExt};
-use log::{debug, error, info, warn};
-use simplelog::{ColorChoice, TermLogger, TerminalMode};
-use smol::future;
-use structopt_toml::StructOptToml;
 
 pub mod privmsg;
 pub mod rpc;
@@ -35,6 +40,12 @@ use crate::{
     settings::{Args, CONFIG_FILE, CONFIG_FILE_CONTENTS},
 };
 
+// TODO should using Stream from net3 instead
+pub trait Stream: AsyncWrite + AsyncRead + Unpin + Send + Sync {}
+
+impl Stream for TcpStream {}
+impl<T: Stream> Stream for TlsStream<T> {}
+
 pub type SeenMsgIds = Arc<Mutex<Vec<u32>>>;
 
 fn build_irc_msg(msg: &Privmsg) -> String {
@@ -79,7 +90,7 @@ async fn broadcast_msg(
 
 async fn process(
     raft_receiver: Receiver<Privmsg>,
-    stream: TcpStream,
+    stream: Box<dyn Stream>,
     peer_addr: SocketAddr,
     raft_sender: Sender<Privmsg>,
     seen_msg_id: SeenMsgIds,
@@ -98,7 +109,7 @@ async fn process(
 
                 let mut smi = seen_msg_id.lock().await;
                 if smi.contains(&msg.id) {
-                   continue
+                    continue
                 }
                 smi.push(msg.id);
                 drop(smi);
@@ -124,10 +135,6 @@ async fn process(
 
 async_daemonize!(realmain);
 async fn realmain(settings: Args, executor: Arc<Executor<'_>>) -> Result<()> {
-    let listener = TcpListener::bind(settings.irc_listen).await?;
-    let local_addr = listener.local_addr()?;
-    info!("IRC listening on {}", local_addr);
-
     let seen_msg_id: SeenMsgIds = Arc::new(Mutex::new(vec![]));
 
     //
@@ -160,27 +167,60 @@ async fn realmain(settings: Args, executor: Arc<Executor<'_>>) -> Result<()> {
     //
     let executor_cloned = executor.clone();
     let irc_task: smol::Task<Result<()>> = executor.spawn(async move {
-        loop {
-            let (stream, peer_addr) = match listener.accept().await {
-                Ok((s, a)) => (s, a),
-                Err(e) => {
-                    error!("Failed listening for connections: {}", e);
-                    return Err(Error::ServiceStopped)
+        let irc_listen_url = url::Url::parse(&settings.irc_listen)?;
+
+        match irc_listen_url.scheme() {
+            "tcp" => {
+                let transport = TcpTransport::new(None, 1024);
+                let listener = transport.listen_on(irc_listen_url.clone()).unwrap().await.unwrap();
+                let mut incoming = listener.incoming();
+                info!("IRC start a TCP connection {}", &irc_listen_url.to_string());
+                while let Some(stream) = incoming.next().await {
+                    let stream = stream.unwrap();
+                    let peer_addr = stream.peer_addr()?;
+                    info!("IRC Accepted TCP connection {}", peer_addr);
+                    executor_cloned
+                        .spawn(process(
+                            raft_receiver.clone(),
+                            Box::new(stream),
+                            peer_addr,
+                            raft_sender.clone(),
+                            seen_msg_id.clone(),
+                        ))
+                        .detach();
                 }
-            };
-
-            info!("IRC Accepted client: {}", peer_addr);
-
-            executor_cloned
-                .spawn(process(
-                    raft_receiver.clone(),
-                    stream,
-                    peer_addr,
-                    raft_sender.clone(),
-                    seen_msg_id.clone(),
-                ))
-                .detach();
+            }
+
+            "tls" => {
+                let transport = TlsTransport::new(None, 1024);
+                let (acceptor, listener) =
+                    transport.listen_on(irc_listen_url.clone()).unwrap().await.unwrap();
+                let mut incoming = listener.incoming();
+                info!("IRC bind a TLS connection {}", &irc_listen_url.to_string());
+                while let Some(stream) = incoming.next().await {
+                    let stream = stream.unwrap();
+                    let peer_addr = stream.peer_addr()?;
+                    info!("IRC Accepted TLS connection {}", peer_addr);
+                    let stream = acceptor.accept(stream).await?;
+                    executor_cloned
+                        .spawn(process(
+                            raft_receiver.clone(),
+                            Box::new(TlsStream::Server(stream)),
+                            peer_addr,
+                            raft_sender.clone(),
+                            seen_msg_id.clone(),
+                        ))
+                        .detach();
+                }
+            }
+
+            x => {
+                error!("Transport protocol '{}' isn't implemented", x);
+                return Err(Error::UnsupportedTransport(x.to_string()))
+            }
         }
+
+        Ok(())
     });
 
     let (signal, shutdown) = async_channel::bounded::<()>(1);

+ 3 - 4
bin/ircd/src/server.rs

@@ -1,14 +1,13 @@
-use async_std::net::TcpStream;
 use futures::{io::WriteHalf, AsyncWriteExt};
 use log::{debug, info, warn};
 use rand::{rngs::OsRng, RngCore};
 
 use darkfi::{Error, Result};
 
-use crate::{privmsg::Privmsg, SeenMsgIds};
+use crate::{privmsg::Privmsg, SeenMsgIds, Stream};
 
 pub struct IrcServerConnection {
-    write_stream: WriteHalf<TcpStream>,
+    write_stream: WriteHalf<Box<dyn Stream>>,
     is_nick_init: bool,
     is_user_init: bool,
     is_registered: bool,
@@ -20,7 +19,7 @@ pub struct IrcServerConnection {
 
 impl IrcServerConnection {
     pub fn new(
-        write_stream: WriteHalf<TcpStream>,
+        write_stream: WriteHalf<Box<dyn Stream>>,
         seen_msg_id: SeenMsgIds,
         p2p_sender: async_channel::Sender<Privmsg>,
     ) -> Self {

+ 2 - 2
bin/ircd/src/settings.rs

@@ -21,8 +21,8 @@ pub struct Args {
     #[structopt(long = "rpc", default_value = "127.0.0.1:11055")]
     pub rpc_listen: SocketAddr,
     /// IRC listen URL
-    #[structopt(long = "irc", default_value = "127.0.0.1:11066")]
-    pub irc_listen: SocketAddr,
+    #[structopt(long = "irc", default_value = "tcp://127.0.0.1:11066")]
+    pub irc_listen: String,
     /// Sets Datastore Path
     #[structopt(long, default_value = "~/.config/ircd")]
     pub datastore: String,

+ 1 - 1
src/net3/mod.rs

@@ -89,7 +89,7 @@ pub mod settings;
 pub mod transport;
 
 pub use acceptor::{Acceptor, AcceptorPtr};
-pub use channel::{Channel, ChannelPtr};
+pub use channel::{Channel, ChannelPtr, Stream};
 pub use connector::Connector;
 pub use hosts::{Hosts, HostsPtr};
 pub use message::Message;