2022-07-16 23:23:01 -04:00
|
|
|
use crate::{
|
|
|
|
common::{first_bytes_match, outgoing::OutgoingConfig, shuffle_rd_wr_filter_only, stream_preamble},
|
|
|
|
context::Context,
|
|
|
|
in_out::{StanzaRead, StanzaWrite},
|
|
|
|
slicesubsequence::SliceSubsequence,
|
|
|
|
srv::srv_connect,
|
|
|
|
stanzafilter::StanzaFilter,
|
|
|
|
};
|
|
|
|
use anyhow::Result;
|
|
|
|
use log::{error, info};
|
|
|
|
use tokio::{net::TcpListener, task::JoinHandle};
|
2021-04-27 02:02:02 -04:00
|
|
|
|
2022-02-17 00:14:40 -05:00
|
|
|
async fn handle_outgoing_connection(stream: tokio::net::TcpStream, client_addr: &mut Context<'_>, config: OutgoingConfig) -> Result<()> {
|
2021-07-24 01:53:00 -04:00
|
|
|
info!("{} connected", client_addr.log_from());
|
2021-04-27 02:02:02 -04:00
|
|
|
|
2022-02-17 00:14:40 -05:00
|
|
|
let mut in_filter = StanzaFilter::new(config.max_stanza_size_bytes);
|
2021-04-27 02:02:02 -04:00
|
|
|
|
2022-07-16 16:27:41 -04:00
|
|
|
#[cfg(feature = "websocket")]
|
|
|
|
let (mut in_rd, mut in_wr) = if first_bytes_match(&stream, &mut in_filter.buf[0..3], |p| p == b"GET").await? {
|
2022-07-16 23:23:01 -04:00
|
|
|
crate::websocket::incoming_websocket_connection(Box::new(stream), config.max_stanza_size_bytes).await?
|
2022-03-25 01:32:10 -04:00
|
|
|
} else {
|
|
|
|
let (in_rd, in_wr) = tokio::io::split(stream);
|
|
|
|
(StanzaRead::new(in_rd), StanzaWrite::new(in_wr))
|
|
|
|
};
|
2021-04-27 02:02:02 -04:00
|
|
|
|
2022-07-16 16:27:41 -04:00
|
|
|
#[cfg(not(feature = "websocket"))]
|
|
|
|
let (mut in_rd, mut in_wr) = {
|
|
|
|
let (in_rd, in_wr) = tokio::io::split(stream);
|
|
|
|
(StanzaRead::new(in_rd), StanzaWrite::new(in_wr))
|
|
|
|
};
|
|
|
|
|
2021-04-27 02:02:02 -04:00
|
|
|
// now read to figure out client vs server
|
2022-02-10 01:18:35 -05:00
|
|
|
let (stream_open, is_c2s) = stream_preamble(&mut in_rd, &mut in_wr, client_addr.log_to(), &mut in_filter).await?;
|
2021-07-24 01:53:00 -04:00
|
|
|
client_addr.set_c2s_stream_open(is_c2s, &stream_open);
|
2021-04-27 02:02:02 -04:00
|
|
|
|
2021-07-24 01:53:00 -04:00
|
|
|
// we require a valid to= here or we fail
|
|
|
|
let to = std::str::from_utf8(stream_open.extract_between(b" to='", b"'").or_else(|_| stream_open.extract_between(b" to=\"", b"\""))?)?;
|
2021-04-27 02:02:02 -04:00
|
|
|
|
2022-02-17 00:14:40 -05:00
|
|
|
let max_stanza_size_bytes = config.max_stanza_size_bytes;
|
|
|
|
let (out_wr, out_rd, stream_open) = srv_connect(to, is_c2s, &stream_open, &mut in_filter, client_addr, config).await?;
|
2021-04-27 02:02:02 -04:00
|
|
|
// send server response to client
|
2022-02-10 01:18:35 -05:00
|
|
|
in_wr.write_all(is_c2s, &stream_open, 0, client_addr.log_from()).await?;
|
2021-04-27 02:02:02 -04:00
|
|
|
in_wr.flush().await?;
|
|
|
|
drop(stream_open);
|
|
|
|
|
2022-02-10 01:18:35 -05:00
|
|
|
shuffle_rd_wr_filter_only(in_rd, in_wr, out_rd, out_wr, is_c2s, max_stanza_size_bytes, client_addr, in_filter).await
|
2021-04-27 02:02:02 -04:00
|
|
|
}
|
|
|
|
|
2022-07-18 01:49:56 -04:00
|
|
|
pub fn spawn_outgoing_listener(listener: TcpListener, config: OutgoingConfig) -> JoinHandle<Result<()>> {
|
2021-04-27 02:02:02 -04:00
|
|
|
tokio::spawn(async move {
|
|
|
|
loop {
|
|
|
|
let (stream, client_addr) = listener.accept().await?;
|
2022-02-17 00:14:40 -05:00
|
|
|
let config = config.clone();
|
2021-04-27 02:02:02 -04:00
|
|
|
tokio::spawn(async move {
|
2021-07-24 01:53:00 -04:00
|
|
|
let mut client_addr = Context::new("unk-out", client_addr);
|
2022-02-17 00:14:40 -05:00
|
|
|
if let Err(e) = handle_outgoing_connection(stream, &mut client_addr, config).await {
|
2021-07-24 01:53:00 -04:00
|
|
|
error!("{} {}", client_addr.log_from(), e);
|
2021-04-27 02:02:02 -04:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|