pub mod errors;
pub mod com {
pub mod fundamentum {
pub mod portforwarding {
pub mod v1 {
use crate::Version;
include!(concat!(
env!("OUT_DIR"),
"/com.fundamentum.portforwarding.v1.rs"
));
pub fn get_version() -> Version {
Version::V1
}
}
}
}
}
use std::{fmt::Display, str::FromStr};
use com::fundamentum::portforwarding::v1;
use derive_new::new;
pub use errors::Error;
use serde::Serialize;
use uuid::Uuid;
#[derive(PartialEq, Eq, Debug, new, Clone, Copy)]
pub struct TargetPort(pub u32);
impl Display for TargetPort {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(PartialEq, Eq, Debug, new, Serialize, Clone, Copy)]
pub struct ProxyPort(pub u32);
impl Display for ProxyPort {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug)]
pub enum Version {
V1,
}
impl FromStr for Version {
type Err = errors::Error;
fn from_str(input: &str) -> Result<Version, Self::Err> {
match input {
"V1" => Ok(Version::V1),
_ => Err(errors::Error::InvalidVersion),
}
}
}
impl Display for Version {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
pub struct PortforwardingMsg {
pub session_id: Uuid,
pub target_port: TargetPort,
pub operation: Operation,
}
#[derive(PartialEq, Eq)]
pub enum Operation {
TransferData(Vec<u8>),
Error(i32, String),
Status(Status),
OpenConnection,
CloseConnection,
}
#[derive(PartialEq, Eq)]
pub enum Status {
ConnectionEstablished,
}
impl From<PortforwardingMsg> for v1::PortforwardingMsg {
fn from(val: PortforwardingMsg) -> Self {
v1::PortforwardingMsg {
session_id: val.session_id.to_string(),
target_port: val.target_port.0,
operation: match &val.operation {
Operation::TransferData(payload) => Some(
v1::portforwarding_msg::Operation::TransferData(v1::TransferData {
payload: payload.to_vec(),
}),
),
Operation::Error(code, message) => {
Some(v1::portforwarding_msg::Operation::Error(v1::Error {
code: *code,
message: message.to_string(),
}))
}
Operation::Status(status) => {
Some(v1::portforwarding_msg::Operation::Status(match status {
Status::ConnectionEstablished => v1::Status::ConnectionEstablished.into(),
}))
}
Operation::OpenConnection => Some(
v1::portforwarding_msg::Operation::OpenConnection(v1::OpenConnection {}),
),
Operation::CloseConnection => Some(
v1::portforwarding_msg::Operation::CloseConnection(v1::CloseConnection {}),
),
},
}
}
}
impl TryFrom<v1::PortforwardingMsg> for PortforwardingMsg {
type Error = errors::Error;
fn try_from(value: v1::PortforwardingMsg) -> Result<Self, Self::Error> {
Ok(PortforwardingMsg {
session_id: Uuid::parse_str(&value.session_id)?,
target_port: TargetPort(value.target_port),
operation: match value.operation {
Some(v1::portforwarding_msg::Operation::OpenConnection(_)) => {
Operation::OpenConnection
}
Some(v1::portforwarding_msg::Operation::CloseConnection(_)) => {
Operation::CloseConnection
}
Some(v1::portforwarding_msg::Operation::TransferData(transfer_data)) => {
Operation::TransferData(transfer_data.payload)
}
Some(v1::portforwarding_msg::Operation::Error(error)) => {
Operation::Error(error.code, error.message)
}
Some(v1::portforwarding_msg::Operation::Status(status)) => match status {
1 => Operation::Status(Status::ConnectionEstablished),
_ => return Err(Error::InvalidStatus),
},
None => return Err(Error::NoOperationFound),
},
})
}
}
impl PortforwardingMsg {
#[must_use]
pub const fn new_close_connection(port: TargetPort, id: Uuid) -> Self {
Self {
session_id: id,
target_port: port,
operation: Operation::CloseConnection,
}
}
#[must_use]
pub const fn new_open_connection(port: TargetPort, id: Uuid) -> Self {
Self {
session_id: id,
target_port: port,
operation: Operation::OpenConnection,
}
}
#[must_use]
pub const fn new_transfer_data(port: TargetPort, id: Uuid, payload: Vec<u8>) -> Self {
Self {
session_id: id,
target_port: port,
operation: Operation::TransferData(payload),
}
}
#[must_use]
pub const fn new_connection_established(port: TargetPort, id: Uuid) -> Self {
Self {
session_id: id,
target_port: port,
operation: Operation::Status(Status::ConnectionEstablished),
}
}
}