Compare commits
2 Commits
53094226a9
...
bfa5b6ccbe
Author | SHA1 | Date |
---|---|---|
xfnw | bfa5b6ccbe | |
xfnw | 928780f947 |
|
@ -10,7 +10,7 @@ license = "MIT"
|
|||
[dependencies]
|
||||
clap = { version = "4.5.2", default-features = false, features = ["derive", "std", "help", "usage"] }
|
||||
rustls-pemfile = "2.1.1"
|
||||
tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros", "net", "io-util", "io-std"]}
|
||||
tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros", "net", "time", "io-util", "io-std"]}
|
||||
tokio-rustls = { version = "0.25.0", default-features = false, features = ["ring", "tls12"] }
|
||||
tokio-socks = "0.5.1"
|
||||
|
||||
|
|
27
src/main.rs
27
src/main.rs
|
@ -1,8 +1,9 @@
|
|||
use clap::Parser;
|
||||
use std::{io::Write, net::SocketAddr, path::PathBuf, sync::Arc};
|
||||
use std::{io::Write, net::SocketAddr, path::PathBuf, process::exit, sync::Arc, time::Duration};
|
||||
use tokio::{
|
||||
io::{self, AsyncBufReadExt, AsyncWriteExt, BufReader},
|
||||
net::TcpStream,
|
||||
time::sleep,
|
||||
};
|
||||
use tokio_rustls::{
|
||||
rustls::{self, pki_types},
|
||||
|
@ -34,6 +35,10 @@ struct Opt {
|
|||
#[arg(short, long, value_name = "ADDR")]
|
||||
socks: Option<SocketAddr>,
|
||||
|
||||
/// send pings after inactivity
|
||||
#[arg(short, long, value_name = "SECS")]
|
||||
ping: Option<u64>,
|
||||
|
||||
#[arg(required = true)]
|
||||
host: String,
|
||||
|
||||
|
@ -126,14 +131,14 @@ async fn handle_tls<T: io::AsyncReadExt + io::AsyncWriteExt + std::marker::Unpin
|
|||
} else {
|
||||
let mut root_cert_store = rustls::RootCertStore::empty();
|
||||
let mut pem = std::io::BufReader::new(
|
||||
std::fs::File::open(opt.cafile).expect("cannot open cafile"),
|
||||
std::fs::File::open(&opt.cafile).expect("cannot open cafile"),
|
||||
);
|
||||
for cert in rustls_pemfile::certs(&mut pem) {
|
||||
root_cert_store.add(cert.unwrap()).unwrap();
|
||||
}
|
||||
config.with_root_certificates(root_cert_store)
|
||||
};
|
||||
let config = if let Some(cert) = opt.cert {
|
||||
let config = if let Some(ref cert) = opt.cert {
|
||||
use rustls_pemfile::Item;
|
||||
|
||||
let mut pem = std::io::BufReader::new(
|
||||
|
@ -159,20 +164,21 @@ async fn handle_tls<T: io::AsyncReadExt + io::AsyncWriteExt + std::marker::Unpin
|
|||
config.with_no_client_auth()
|
||||
};
|
||||
let connector = TlsConnector::from(Arc::new(config));
|
||||
let domain = pki_types::ServerName::try_from(opt.host)
|
||||
let domain = pki_types::ServerName::try_from(opt.host.as_str())
|
||||
.expect("invalid server name")
|
||||
.to_owned();
|
||||
let tlsstream = connector
|
||||
.connect(domain, stream)
|
||||
.await
|
||||
.expect("failed to negotiate tls");
|
||||
handle_irc(tlsstream).await;
|
||||
handle_irc(opt, tlsstream).await;
|
||||
} else {
|
||||
handle_irc(stream).await;
|
||||
handle_irc(opt, stream).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_irc<T: io::AsyncReadExt + io::AsyncWriteExt>(stream: T) {
|
||||
async fn handle_irc<T: io::AsyncReadExt + io::AsyncWriteExt>(opt: Opt, stream: T) {
|
||||
let pingdelay = Duration::from_secs(opt.ping.unwrap_or(0));
|
||||
let (read, mut write) = io::split(stream);
|
||||
let mut read = BufReader::new(read);
|
||||
let mut stdin = BufReader::new(io::stdin());
|
||||
|
@ -183,7 +189,7 @@ async fn handle_irc<T: io::AsyncReadExt + io::AsyncWriteExt>(stream: T) {
|
|||
tokio::select! {
|
||||
Ok(len) = stdin.read_until(b'\n', &mut stdbuf) => {
|
||||
if len == 0 {
|
||||
return;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
trim_mut(&mut stdbuf);
|
||||
|
@ -196,7 +202,7 @@ async fn handle_irc<T: io::AsyncReadExt + io::AsyncWriteExt>(stream: T) {
|
|||
}
|
||||
Ok(len) = read.read_until(b'\n', &mut ircbuf) => {
|
||||
if len == 0 {
|
||||
return;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if let Some(pong) = is_pong(&ircbuf) {
|
||||
|
@ -209,6 +215,9 @@ async fn handle_irc<T: io::AsyncReadExt + io::AsyncWriteExt>(stream: T) {
|
|||
|
||||
ircbuf.clear();
|
||||
}
|
||||
() = sleep(pingdelay), if opt.ping.is_some() => {
|
||||
write.write_all(b"PING :boop\r\n").await.expect("cannot send");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue