Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
01bc71ab86 | |||
cf98c93a89 | |||
d57d0c2db9 | |||
f2ad24655c | |||
9bc700e0f6 |
1339
Cargo.lock
generated
1339
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
21
Cargo.toml
21
Cargo.toml
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rustocat"
|
||||
version = "0.1.12"
|
||||
version = "0.1.13"
|
||||
edition = "2021"
|
||||
description = "Socat in rust with many less features and a configuration file"
|
||||
license = "ISC"
|
||||
@ -8,7 +8,7 @@ license = "ISC"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[features]
|
||||
default = ["consul"]
|
||||
consul = []
|
||||
consul = ["reqwest"]
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
@ -17,14 +17,17 @@ serde_json = "1"
|
||||
serde_yaml = "0.9"
|
||||
rand = "0.8"
|
||||
log = "0.4"
|
||||
fern = "0.6"
|
||||
fern = "0.7"
|
||||
chrono = "0.4"
|
||||
async-trait = "0.1"
|
||||
reqwest = { version = "0.11", features = ["json", "rustls", "hyper-tls"], default-features = false }
|
||||
reqwest = { version = "0.12", optional = true, features = [
|
||||
"json",
|
||||
"default-tls",
|
||||
], default-features = false }
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3 # Optimize for size.
|
||||
lto = true # Enable Link Time Optimization
|
||||
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
|
||||
panic = 'abort' # Abort on panic
|
||||
strip = true # Strip symbols from binary*
|
||||
opt-level = 3 # Optimize for size.
|
||||
lto = true # Enable Link Time Optimization
|
||||
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
|
||||
panic = 'abort' # Abort on panic
|
||||
strip = true # Strip symbols from binary*
|
||||
|
@ -15,8 +15,11 @@ pub struct Target {
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Config {
|
||||
#[cfg(feature = "consul")]
|
||||
pub consul: Option<bool>,
|
||||
#[cfg(feature = "consul")]
|
||||
pub consul_http_addr: Option<String>,
|
||||
#[cfg(feature = "consul")]
|
||||
pub consul_http_token: Option<String>,
|
||||
mappings: Vec<Target>,
|
||||
}
|
||||
@ -41,38 +44,54 @@ impl FileConfigProvider {
|
||||
|
||||
fn load_yaml(&self, path: &Path) -> Result<Config> {
|
||||
let file = File::open(path)?;
|
||||
let config: Config = serde_yaml::from_reader(file).expect("Failed to parse!"); //TODO: Print path
|
||||
let config: Config = serde_yaml::from_reader(file)?; //TODO: Print path
|
||||
|
||||
return Ok(config);
|
||||
}
|
||||
|
||||
fn load_json(&self, path: &Path) -> Result<Config> {
|
||||
let file = File::open(path)?;
|
||||
let config: Config = serde_json::from_reader(file).expect("Failed to parse!"); //TODO: Print path
|
||||
let config: Config = serde_json::from_reader(file)?; //TODO: Print path
|
||||
|
||||
return Ok(config);
|
||||
}
|
||||
|
||||
pub fn load_config(&self) -> Result<Config> {
|
||||
for path in [
|
||||
let configs = [
|
||||
"config.yaml",
|
||||
"config.yml",
|
||||
"config.json",
|
||||
"/etc/rustocat.yaml",
|
||||
"/etc/rustocat.json",
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
// if(p)
|
||||
let config = if path.ends_with(".yaml") {
|
||||
.map(|path| {
|
||||
if std::path::Path::new(path).exists() {
|
||||
return Some(path);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
})
|
||||
.filter(|p| p.is_some())
|
||||
.map(|p| p.unwrap())
|
||||
.map(|path| {
|
||||
if path.ends_with(".yaml") {
|
||||
self.load_yaml(Path::new(path))
|
||||
} else {
|
||||
self.load_json(Path::new(path))
|
||||
};
|
||||
if config.is_ok() {
|
||||
return config;
|
||||
}
|
||||
});
|
||||
|
||||
for config in configs {
|
||||
match config {
|
||||
Ok(c) => return Ok(c),
|
||||
Err(e) => {
|
||||
info!("Error loading config: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err("No config file found".into())
|
||||
|
||||
Err("No (valid) config file found".into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,9 +128,9 @@ async fn run_loop(
|
||||
let (notify_targets, _) = broadcast::channel(1);
|
||||
|
||||
let listener = ActiveListener {
|
||||
notify_shutdown: notify_shutdown,
|
||||
notify_shutdown,
|
||||
targets: Arc::new(RwLock::new(target.targets)),
|
||||
notify_targets: notify_targets,
|
||||
notify_targets,
|
||||
};
|
||||
|
||||
let l = listener::Listener {
|
||||
|
30
src/tcp.rs
30
src/tcp.rs
@ -1,5 +1,5 @@
|
||||
use crate::listener::Listener;
|
||||
use log::{info, trace, warn};
|
||||
use log::{error, info, trace, warn};
|
||||
use rand::seq::SliceRandom;
|
||||
use std::error::Error;
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
@ -24,7 +24,33 @@ pub(crate) async fn start_tcp_listener(
|
||||
mut listener_config: Listener,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
info!("start listening on {}", &listener_config.source);
|
||||
let listener = TcpListener::bind(&listener_config.source).await?;
|
||||
let listener = loop {
|
||||
match TcpListener::bind(&listener_config.source).await {
|
||||
Ok(listener) => break listener,
|
||||
Err(e) => match e.kind() {
|
||||
std::io::ErrorKind::AddrInUse => {
|
||||
warn!("Address in use: {}", &listener_config.source);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||
}
|
||||
std::io::ErrorKind::AddrNotAvailable => {
|
||||
warn!("Address not available: {}", &listener_config.source);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||
}
|
||||
_ => {
|
||||
error!(
|
||||
"Error binding to {}: {} ({})",
|
||||
&listener_config.source,
|
||||
e,
|
||||
e.kind()
|
||||
);
|
||||
trace!("Error: {}", e);
|
||||
return Err(Box::new(e));
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
info!("listening on {}", listener.local_addr()?);
|
||||
|
||||
loop {
|
||||
let (next_socket, _) = tokio::select! {
|
||||
|
24
src/udp.rs
24
src/udp.rs
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||
use std::sync::atomic::AtomicI32;
|
||||
use std::sync::Arc;
|
||||
|
||||
use log::{debug, error, info, trace};
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use rand::seq::SliceRandom;
|
||||
|
||||
use tokio::net::UdpSocket;
|
||||
@ -38,7 +38,27 @@ impl UDPMultiSender {
|
||||
}
|
||||
|
||||
async fn splitted_udp_socket(bind_addr: &str) -> Result<(UdpSocket, UDPMultiSender)> {
|
||||
let listener_std = std::net::UdpSocket::bind(bind_addr)?;
|
||||
let listener_std = loop {
|
||||
match std::net::UdpSocket::bind(bind_addr) {
|
||||
Ok(listener) => break listener,
|
||||
Err(e) => match e.kind() {
|
||||
std::io::ErrorKind::AddrInUse => {
|
||||
warn!("Address in use: {}", bind_addr);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||
}
|
||||
std::io::ErrorKind::AddrNotAvailable => {
|
||||
warn!("Address not available: {}", bind_addr);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||
}
|
||||
_ => {
|
||||
error!("Error binding to {}: {} ({})", bind_addr, e, e.kind());
|
||||
trace!("Error: {}", e);
|
||||
return Err(Box::new(e));
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let responder_std = listener_std.try_clone()?;
|
||||
listener_std.set_nonblocking(true)?;
|
||||
responder_std.set_nonblocking(true)?;
|
||||
|
Reference in New Issue
Block a user