fundamentum_portforwarding_proto_rust/
lib.rs1pub mod errors;
9pub mod com {
13 pub mod fundamentum {
17 pub mod portforwarding {
21 pub use v1 as latest;
22 pub mod v1 {
27 use crate::Version;
28
29 include!(concat!(
30 env!("OUT_DIR"),
31 "/com.fundamentum.portforwarding.v1.rs"
32 ));
33
34 pub fn get_version() -> Version {
36 Version::V1
37 }
38 }
39 }
40 }
41}
42use com::fundamentum::portforwarding::v1;
43use derive_new::new;
44use enum_tags::Tag;
45pub use enum_tags_traits::TaggedEnum;
46pub use errors::Error;
47use prost::Message;
48use serde::{Deserialize, Serialize};
49use std::{
50 fmt::{self, Display},
51 str::FromStr,
52};
53use uuid::Uuid;
54
55#[derive(PartialEq, Eq, Debug, new, Clone, Copy)]
56pub struct TargetPort(pub u32);
57
58impl Display for TargetPort {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 write!(f, "{}", self.0)
61 }
62}
63
64#[derive(PartialEq, Eq, Debug, new, Serialize, Deserialize, Clone, Copy)]
65pub struct ProxyPort(pub u32);
66
67impl Display for ProxyPort {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 write!(f, "{}", self.0)
70 }
71}
72
73#[derive(Debug, Clone)]
75pub enum Version {
76 V1,
77}
78
79impl Version {
80 pub fn get_latest() -> Self {
81 com::fundamentum::portforwarding::latest::get_version()
82 }
83}
84
85impl FromStr for Version {
86 type Err = errors::Error;
87
88 fn from_str(input: &str) -> Result<Version, Self::Err> {
89 match input {
90 "1" => Ok(Version::V1),
91 _ => Err(errors::Error::InvalidVersion),
92 }
93 }
94}
95
96impl Display for Version {
97 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
98 match self {
99 Version::V1 => write!(f, "1"),
100 }
101 }
102}
103
104#[derive(Clone, new)]
105pub struct PortForwardingMsg {
106 pub instance_id: Uuid,
107 pub operation: PortforwardingOperation,
108 pub version: Version,
109}
110
111#[derive(Clone, Debug, PartialEq, Eq, Tag)]
113pub enum PortforwardingOperation {
114 Handshake,
115 TransferData(TransferData),
116 Error(ErrorOperation),
117 Status(Status),
118 OpenConnection(OpenConnection),
119 CloseConnection,
120}
121
122#[derive(Clone, Debug, PartialEq, Eq)]
123pub struct TransferData {
124 pub payload: Vec<u8>,
125}
126
127#[derive(Clone, Debug, PartialEq, Eq)]
128pub struct ErrorOperation {
129 pub code: i32,
130 pub message: String,
131}
132
133#[derive(Clone, Debug, PartialEq, Eq)]
134pub struct OpenConnection {
135 pub target_port: TargetPort,
136}
137
138#[derive(PartialEq, Eq, Clone, Debug)]
140pub enum Status {
141 ConnectionEstablished,
142}
143
144impl PortforwardingOperation {
145 #[must_use]
147 pub const fn new_close_connection() -> Self {
148 Self::CloseConnection
149 }
150
151 #[must_use]
153 pub const fn new_open_connection(port: TargetPort) -> Self {
154 Self::OpenConnection(OpenConnection { target_port: port })
155 }
156
157 #[must_use]
159 pub const fn new_transfer_data(payload: Vec<u8>) -> Self {
160 Self::TransferData(TransferData { payload })
161 }
162
163 #[must_use]
165 pub const fn new_connection_established() -> Self {
166 Self::Status(Status::ConnectionEstablished)
167 }
168
169 pub fn encode(self, version: &Version) -> Vec<u8> {
170 match version {
171 Version::V1 => match self {
172 Self::TransferData(transfer_data_msg) => v1::TransferData {
173 payload: transfer_data_msg.payload,
174 }
175 .encode_to_vec(),
176 Self::Error(error_msg) => v1::Error {
177 code: error_msg.code,
178 message: error_msg.message,
179 }
180 .encode_to_vec(),
181 Self::Status(status) => match status {
182 Status::ConnectionEstablished => v1::Status {
183 value: v1::StatusValue::StatusConnectionEstablished.into(),
184 }
185 .encode_to_vec(),
186 },
187 Self::OpenConnection(open_connection_msg) => v1::OpenConnection {
188 target_port: open_connection_msg.target_port.0,
189 }
190 .encode_to_vec(),
191 Self::CloseConnection => v1::CloseConnection {}.encode_to_vec(),
192 Self::Handshake => Vec::new(),
193 },
194 }
195 }
196
197 pub fn decode(
198 version: Version,
199 payload: &[u8],
200 operation: PortforwardingOperationTag,
201 ) -> Result<Self, errors::Error> {
202 use PortforwardingOperationTag as Tag;
203
204 if operation == Tag::Handshake {
205 return Ok(Self::Handshake);
206 }
207 match version {
208 Version::V1 => match operation {
209 Tag::OpenConnection => Ok(Self::OpenConnection(OpenConnection {
210 target_port: TargetPort(v1::OpenConnection::decode(payload)?.target_port),
211 })),
212 Tag::CloseConnection => Ok(Self::CloseConnection),
213 Tag::TransferData => Ok(Self::TransferData(TransferData {
214 payload: v1::TransferData::decode(payload)?.payload,
215 })),
216 Tag::Error => {
217 let v1_error = v1::Error::decode(payload)?;
218 Ok(Self::Error(ErrorOperation {
219 code: v1_error.code,
220 message: v1_error.message,
221 }))
222 }
223 Tag::Status => {
224 let v1_status = v1::Status::decode(payload)?;
225 Ok(Self::Status(match v1_status.value() {
226 v1::StatusValue::StatusConnectionEstablished => {
227 Status::ConnectionEstablished
228 }
229 _ => return Err(errors::Error::InvalidStatus),
230 }))
231 }
232 _ => Err(errors::Error::InvalidOperation),
233 },
234 }
235 }
236}
237
238impl fmt::Display for PortforwardingOperationTag {
239 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
240 match self {
241 Self::CloseConnection => write!(f, "close"),
242 Self::OpenConnection => write!(f, "open"),
243 Self::TransferData => write!(f, "tx"),
244 Self::Handshake => write!(f, "hsk"),
245 Self::Error => write!(f, "error"),
246 Self::Status => write!(f, "status"),
247 }
248 }
249}
250
251impl FromStr for PortforwardingOperationTag {
252 type Err = errors::Error;
253
254 fn from_str(s: &str) -> Result<Self, Self::Err> {
255 match s {
256 "error" => Ok(Self::Error),
257 "status" => Ok(Self::Status),
258 "close" => Ok(Self::CloseConnection),
259 "open" => Ok(Self::OpenConnection),
260 "hsk" => Ok(Self::Handshake),
261 "tx" => Ok(Self::TransferData),
262 _ => Err(errors::Error::InvalidOperation),
263 }
264 }
265}