#![feature(str_as_str)]
use rumtk_core::core::RUMResult;
use rumtk_core::dependencies::clap;
use rumtk_core::net::tcp::LOCALHOST;
use rumtk_core::strings::{RUMArrayConversions, RUMString};
use rumtk_core::types::RUMCLIParser;
use rumtk_core::{rumtk_read_stdin, rumtk_write_stdout};
use rumtk_hl7_v2::hl7_v2_mllp::mllp_v2::{SafeAsyncMLLP, SafeMLLPChannel, MLLP_FILTER_POLICY};
use rumtk_hl7_v2::{
rumtk_v2_mllp_connect, rumtk_v2_mllp_get_ip_port, rumtk_v2_mllp_iter_channels,
rumtk_v2_mllp_listen, rumtk_v2_mllp_receive,
};
use std::process::exit;
#[derive(RUMCLIParser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct RUMTKInterfaceArgs {
#[arg(short, long)]
ip: Option<RUMString>,
#[arg(short, long)]
port: Option<u16>,
#[arg(short, long, default_value_t = RUMString::from("none"))]
filter_policy: RUMString,
#[arg(short, long, default_value_t = 1)]
threads: usize,
#[arg(short, long)]
outbound: bool,
#[arg(short, long)]
local: bool,
#[arg(short, long)]
daemon: bool,
}
fn outbound_send(channel: &SafeMLLPChannel) -> RUMResult<()> {
let stdin_msg = rumtk_read_stdin!()?;
if !stdin_msg.is_empty() {
eprintln!("MLLP Sending {} bytes", stdin_msg.len());
return channel
.lock()
.unwrap()
.send_message(&stdin_msg.as_slice().to_rumstring());
exit(0);
}
Ok(())
}
fn outbound_loop(channel: &SafeMLLPChannel) {
loop {
match outbound_send(channel) {
Ok(()) => continue,
Err(e) => println!("{}", e), };
}
}
fn inbound_receive(channel: &SafeAsyncMLLP) -> RUMResult<()> {
for (endpoint, raw_msgs) in rumtk_v2_mllp_receive!(channel)? {
for raw_msg in raw_msgs {
if !raw_msg.is_empty() {
eprintln!("MLLP Received {} bytes", raw_msg.len());
let _ = rumtk_write_stdout!(raw_msg);
}
}
}
Ok(())
}
fn inbound_loop(listener: &SafeAsyncMLLP) {
loop {
inbound_receive(listener);
}
}
fn main() {
let args = RUMTKInterfaceArgs::parse();
let mllp_filter_policy = match args.filter_policy.as_str() {
"escape" => MLLP_FILTER_POLICY::ESCAPE_INPUT,
"filter" => MLLP_FILTER_POLICY::FILTER_INPUT,
"none" => MLLP_FILTER_POLICY::NONE,
_ => MLLP_FILTER_POLICY::ESCAPE_INPUT,
};
if args.outbound {
let ip = match args.local {
true => args.ip.unwrap_or_else(|| LOCALHOST.parse().unwrap()),
false => args.ip.expect("Must provide an IP address"),
};
let port = args.port.expect("Must provide a port number");
let client =
rumtk_v2_mllp_connect!(&ip, port, mllp_filter_policy).expect("MLLP connection failed");
let channel_option = rumtk_v2_mllp_iter_channels!(client)
.expect("Issue getting list of outbound connections.");
let channel = channel_option.get(0).expect("No MLLP Connections");
eprintln!(
"Connected from {} to {}:{}",
channel.lock().unwrap().get_address_info().unwrap(),
&ip,
port
);
if args.daemon {
outbound_loop(&channel);
} else {
outbound_send(&channel);
}
} else {
let mut listener: RUMResult<SafeAsyncMLLP> = Err(RUMString::new(""));
if args.ip.is_none() && args.port.is_none() {
listener = rumtk_v2_mllp_listen!(mllp_filter_policy, args.local);
} else if args.ip.is_none() && !args.port.is_none() {
listener = rumtk_v2_mllp_listen!(args.port.unwrap(), mllp_filter_policy, args.local);
} else if !args.ip.is_none() && !args.port.is_none() {
listener = rumtk_v2_mllp_listen!(
&args.ip.unwrap(),
args.port.unwrap(),
mllp_filter_policy,
args.local
);
} else {
listener = rumtk_v2_mllp_listen!(mllp_filter_policy, args.local);
}
let listener_handle =
listener.expect("MLLP listening connection failed to bind a network interface!");
let connection_info = rumtk_v2_mllp_get_ip_port!(listener_handle).unwrap();
eprintln!("Listening on {}:{}", connection_info.0, connection_info.1);
inbound_loop(&listener_handle);
}
}