use crate::{
connection::{Connection, ConnectionFactory, Server},
error::TransportError,
protocol::adapter::ConfigError,
};
use async_trait::async_trait;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
#[async_trait]
pub trait ProtocolPlugin: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn features(&self) -> Vec<String>;
fn default_port(&self) -> Option<u16>;
async fn validate_config(&self, config: &dyn std::any::Any) -> Result<(), ConfigError>;
async fn create_server(
&self,
config: Box<dyn std::any::Any>,
) -> Result<Box<dyn Server>, TransportError>;
async fn create_connection_factory(
&self,
config: Box<dyn std::any::Any>,
) -> Result<Box<dyn ConnectionFactory>, TransportError>;
fn config_type_name(&self) -> &str;
}
pub struct PluginRegistry {
plugins: Arc<RwLock<HashMap<String, Arc<dyn ProtocolPlugin>>>>,
}
impl PluginRegistry {
pub fn new() -> Self {
Self {
plugins: Arc::new(RwLock::new(HashMap::new())),
}
}
pub fn register(&self, plugin: Arc<dyn ProtocolPlugin>) -> Result<(), TransportError> {
let mut plugins = self.plugins.write().unwrap();
let name = plugin.name().to_string();
if plugins.contains_key(&name) {
return Err(TransportError::config_error(
"plugin",
format!("Protocol '{}' is already registered", name),
));
}
plugins.insert(name, plugin);
Ok(())
}
pub fn unregister(&self, name: &str) -> Result<(), TransportError> {
let mut plugins = self.plugins.write().unwrap();
if plugins.remove(name).is_some() {
Ok(())
} else {
Err(TransportError::config_error(
"plugin",
format!("Protocol '{}' is not registered", name),
))
}
}
pub fn get(&self, name: &str) -> Option<Arc<dyn ProtocolPlugin>> {
let plugins = self.plugins.read().unwrap();
plugins.get(name).cloned()
}
pub fn list(&self) -> Vec<String> {
let plugins = self.plugins.read().unwrap();
plugins.keys().cloned().collect()
}
pub fn get_plugin_info(&self, name: &str) -> Option<PluginInfo> {
let plugins = self.plugins.read().unwrap();
plugins.get(name).map(|plugin| PluginInfo {
name: plugin.name().to_string(),
description: plugin.description().to_string(),
features: plugin.features(),
default_port: plugin.default_port(),
config_type: plugin.config_type_name().to_string(),
})
}
pub fn get_all_plugin_info(&self) -> Vec<PluginInfo> {
let plugins = self.plugins.read().unwrap();
plugins
.values()
.map(|plugin| PluginInfo {
name: plugin.name().to_string(),
description: plugin.description().to_string(),
features: plugin.features(),
default_port: plugin.default_port(),
config_type: plugin.config_type_name().to_string(),
})
.collect()
}
}
impl Default for PluginRegistry {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct PluginInfo {
pub name: String,
pub description: String,
pub features: Vec<String>,
pub default_port: Option<u16>,
pub config_type: String,
}
pub struct PluginManager {
registry: PluginRegistry,
allow_override: bool,
}
impl PluginManager {
pub fn new() -> Self {
Self {
registry: PluginRegistry::new(),
allow_override: false,
}
}
pub fn with_override() -> Self {
Self {
registry: PluginRegistry::new(),
allow_override: true,
}
}
pub fn register_plugin(&self, plugin: Arc<dyn ProtocolPlugin>) -> Result<(), TransportError> {
let name = plugin.name();
if !self.allow_override && self.is_builtin_protocol(name) {
return Err(TransportError::config_error(
"plugin",
format!(
"Cannot override builtin protocol '{}'. Use with_override() to allow this.",
name
),
));
}
self.registry.register(plugin)
}
pub fn unregister_plugin(&self, name: &str) -> Result<(), TransportError> {
self.registry.unregister(name)
}
pub fn get_plugin(&self, name: &str) -> Option<Arc<dyn ProtocolPlugin>> {
self.registry.get(name)
}
pub fn list_protocols(&self) -> Vec<String> {
let mut protocols = vec![
"tcp".to_string(),
"websocket".to_string(),
"quic".to_string(),
];
protocols.extend(self.registry.list());
protocols.sort();
protocols.dedup();
protocols
}
pub fn get_protocol_info(&self, name: &str) -> Option<PluginInfo> {
if let Some(info) = self.registry.get_plugin_info(name) {
return Some(info);
}
match name {
"tcp" => Some(PluginInfo {
name: "tcp".to_string(),
description:
"Transmission Control Protocol - reliable, ordered, connection-oriented"
.to_string(),
features: vec![
"reliable".to_string(),
"ordered".to_string(),
"connection-oriented".to_string(),
],
default_port: Some(8080),
config_type: "TcpConfig".to_string(),
}),
"websocket" => Some(PluginInfo {
name: "websocket".to_string(),
description: "WebSocket Protocol - full-duplex communication over HTTP".to_string(),
features: vec![
"full-duplex".to_string(),
"http-upgrade".to_string(),
"frame-based".to_string(),
],
default_port: Some(8080),
config_type: "WebSocketConfig".to_string(),
}),
"quic" => Some(PluginInfo {
name: "quic".to_string(),
description: "QUIC Protocol - modern transport with built-in encryption"
.to_string(),
features: vec![
"encrypted".to_string(),
"multiplexed".to_string(),
"low-latency".to_string(),
],
default_port: Some(4433),
config_type: "QuicConfig".to_string(),
}),
_ => None,
}
}
fn is_builtin_protocol(&self, name: &str) -> bool {
matches!(name, "tcp" | "websocket" | "quic")
}
pub async fn create_server_with_plugin(
&self,
protocol: &str,
config: Box<dyn std::any::Any>,
) -> Result<Box<dyn Server>, TransportError> {
if let Some(plugin) = self.get_plugin(protocol) {
plugin.create_server(config).await
} else {
Err(TransportError::config_error(
"plugin",
format!(
"Protocol '{}' not found. Available protocols: {:?}",
protocol,
self.list_protocols()
),
))
}
}
pub async fn create_connection_factory_with_plugin(
&self,
protocol: &str,
config: Box<dyn std::any::Any>,
) -> Result<Box<dyn ConnectionFactory>, TransportError> {
if let Some(plugin) = self.get_plugin(protocol) {
plugin.create_connection_factory(config).await
} else {
Err(TransportError::config_error(
"plugin",
format!(
"Protocol '{}' not found. Available protocols: {:?}",
protocol,
self.list_protocols()
),
))
}
}
}
impl Default for PluginManager {
fn default() -> Self {
Self::new()
}
}
pub struct PluginConnection {
inner: Box<dyn Connection>,
}
impl PluginConnection {
pub fn new(inner: Box<dyn Connection>) -> Self {
Self { inner }
}
}
#[async_trait]
impl Connection for PluginConnection {
async fn send(&mut self, packet: crate::packet::Packet) -> Result<(), TransportError> {
self.inner.send(packet).await
}
async fn close(&mut self) -> Result<(), TransportError> {
self.inner.close().await
}
fn session_id(&self) -> crate::SessionId {
self.inner.session_id()
}
fn set_session_id(&mut self, session_id: crate::SessionId) {
self.inner.set_session_id(session_id)
}
fn connection_info(&self) -> crate::command::ConnectionInfo {
self.inner.connection_info()
}
fn is_connected(&self) -> bool {
self.inner.is_connected()
}
async fn flush(&mut self) -> Result<(), TransportError> {
self.inner.flush().await
}
fn event_stream(
&self,
) -> Option<tokio::sync::broadcast::Receiver<crate::event::TransportEvent>> {
self.inner.event_stream()
}
}