use anyhow::{Context, Result};
use chrono::Utc;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Command {
RegisterPorts {
client_id: String,
ports: Vec<PortEntry>,
},
UnregisterPorts {
client_id: String,
},
Heartbeat {
client_id: String,
timestamp: i64,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PortEntry {
pub remote_port: u16,
pub local_port: u16,
pub protocol: String,
pub description: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Response {
Ok {
message: String,
},
Error {
message: String,
},
HeartbeatAck {
server_time: i64,
},
}
impl Command {
pub fn to_bytes(&self) -> Result<Vec<u8>> {
serde_json::to_vec(self).context("Failed to serialize command")
}
pub fn from_bytes(data: &[u8]) -> Result<Self> {
serde_json::from_slice(data).context("Failed to deserialize command")
}
}
impl Response {
pub fn to_bytes(&self) -> Result<Vec<u8>> {
serde_json::to_vec(self).context("Failed to serialize response")
}
pub fn from_bytes(data: &[u8]) -> Result<Self> {
serde_json::from_slice(data).context("Failed to deserialize response")
}
}
pub fn heartbeat_command(client_id: &str) -> Command {
Command::Heartbeat {
client_id: client_id.to_string(),
timestamp: Utc::now().timestamp(),
}
}
pub fn register_ports_command(client_id: &str, ports: Vec<PortEntry>) -> Command {
Command::RegisterPorts {
client_id: client_id.to_string(),
ports,
}
}