ircd: irc server support tls protocol

This commit is contained in:
ghassmo
2022-04-29 18:33:48 +03:00
parent cdaadfc9fa
commit f625dc23eb
7 changed files with 81 additions and 38 deletions

2
Cargo.lock generated
View File

@@ -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]]

View File

@@ -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"

View File

@@ -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"

View File

@@ -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);
"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();
}
}
executor_cloned
.spawn(process(
raft_receiver.clone(),
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);

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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;