#![allow(non_snake_case)]
use std::collections::HashMap as FxHashMap;
use std::sync::Arc;
use std::time::{Duration, Instant};
use async_trait::async_trait;
use tokio::sync::RwLock;
use log::{info, warn, debug};
use crate::core::{RiResult, RiError};
use super::{RiProtocol, RiProtocolType, RiProtocolConfig, RiProtocolConnection,
RiProtocolStats, RiMessageFlags, RiConnectionInfo, RiSecurityLevel};
#[derive(Debug, Clone)]
pub enum RiProtocolStrategy {
SecurityBased(RiSecurityContext),
PerformanceBased(RiPerformanceContext),
Adaptive(RiAdaptiveContext),
Manual(RiProtocolType),
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct RiSecurityContext {
pub required_security_level: RiSecurityLevel,
pub threat_level: RiThreatLevel,
pub data_classification: RiDataClassification,
pub network_environment: RiNetworkEnvironment,
pub compliance_requirements: Vec<RiComplianceRequirement>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct RiPerformanceContext {
pub required_throughput: u64,
pub max_latency_ms: u64,
pub bandwidth_constraints: RiBandwidthConstraints,
pub stability_requirements: RiStabilityRequirements,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct RiAdaptiveContext {
pub security_weight: f32,
pub performance_weight: f32,
pub adaptation_triggers: Vec<RiAdaptationTrigger>,
pub learning_params: RiLearningParameters,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub enum RiThreatLevel {
Normal,
Elevated,
High,
Critical,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub enum RiDataClassification {
Public,
Internal,
Confidential,
Secret,
TopSecret,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub enum RiNetworkEnvironment {
Trusted,
Untrusted,
Hostile,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub enum RiComplianceRequirement {
GDPR,
HIPAA,
SOX,
PCIDSS,
NationalSecurity,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct RiBandwidthConstraints {
pub available_bandwidth: u64,
pub burst_capacity: u64,
pub congestion_level: f32,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct RiStabilityRequirements {
pub max_packet_loss: f32,
pub max_jitter_ms: u64,
pub min_uptime: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub enum RiAdaptationTrigger {
SecurityBreach,
PerformanceDegradation,
NetworkChange,
Manual,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct RiLearningParameters {
pub learning_rate: f32,
pub adaptation_window: Duration,
pub history_size: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub enum RiNetworkCondition {
Excellent,
Good,
Fair,
Poor,
}
#[cfg_attr(feature = "pyo3", pyo3::prelude::pyclass)]
pub struct RiProtocolAdapter {
strategy: Arc<RwLock<Option<RiProtocolStrategy>>>,
protocols: Arc<RwLock<FxHashMap<RiProtocolType, Box<dyn RiProtocol>>>>,
active_protocol: Arc<RwLock<Option<RiProtocolType>>>,
connection_manager: Arc<RiConnectionManager>,
stats: Arc<RwLock<RiProtocolAdapterStats>>,
initialized: Arc<RwLock<bool>>,
}
struct RiConnectionManager {
connections: Arc<RwLock<FxHashMap<String, Arc<dyn RiProtocolConnection>>>>,
metadata: Arc<RwLock<FxHashMap<String, RiConnectionMetadata>>>,
}
#[derive(Debug, Clone)]
struct RiConnectionMetadata {
original_protocol: RiProtocolType,
current_protocol: RiProtocolType,
established_at: Instant,
last_switch: Option<Instant>,
switch_count: u64,
state_data: FxHashMap<String, Vec<u8>>,
}
#[derive(Debug, Default)]
struct RiProtocolAdapterStats {
pub protocol_switches: u64,
pub successful_switches: u64,
pub failed_switches: u64,
pub connection_migrations: u64,
pub strategy_changes: u64,
pub avg_switch_time_ms: u64,
pub protocol_switch_stats: FxHashMap<RiProtocolType, u64>,
}
impl RiProtocolAdapter {
pub fn new() -> Self {
let connection_manager = Arc::new(RiConnectionManager {
connections: Arc::new(RwLock::new(FxHashMap::default())),
metadata: Arc::new(RwLock::new(FxHashMap::default())),
});
Self {
strategy: Arc::new(RwLock::new(None)),
protocols: Arc::new(RwLock::new(FxHashMap::default())),
active_protocol: Arc::new(RwLock::new(None)),
connection_manager,
stats: Arc::new(RwLock::new(RiProtocolAdapterStats::default())),
initialized: Arc::new(RwLock::new(false)),
}
}
pub async fn initialize(&mut self, strategy: RiProtocolStrategy) -> RiResult<()> {
*self.strategy.write().await = Some(strategy.clone());
let initial_protocol = self.select_optimal_protocol(&strategy).await?;
*self.active_protocol.write().await = Some(initial_protocol);
*self.initialized.write().await = true;
Ok(())
}
pub async fn register_protocol(&self, protocol_type: RiProtocolType, protocol: Box<dyn RiProtocol>) -> RiResult<()> {
self.protocols.write().await.insert(protocol_type, protocol);
Ok(())
}
pub async fn connect(&self, target_id: &str) -> RiResult<Box<dyn RiProtocolConnection>> {
if !*self.initialized.read().await {
return Err(RiError::InvalidState("Protocol adapter not initialized".to_string()));
}
let active_protocol = self.active_protocol.read().await;
let protocol_type = active_protocol.ok_or_else(||
RiError::InvalidState("No active protocol selected".to_string()))?;
let protocols = self.protocols.read().await;
let protocol = protocols.get(&protocol_type)
.ok_or_else(|| RiError::NotFound(format!("Protocol {:?} not registered", protocol_type)))?;
let connection = protocol.connect(target_id).await?;
let connection_id = format!("adapter-{}", uuid::Uuid::new_v4());
self.connection_manager.store_connection(
connection_id.clone(),
connection,
protocol_type,
).await?;
Ok(Box::new(RiProtocolConnectionWrapper {
connection_id,
connection_manager: Arc::clone(&self.connection_manager),
stats: Arc::clone(&self.stats),
}))
}
pub async fn switch_protocol(&self, new_protocol_type: RiProtocolType) -> RiResult<()> {
let start_time = Instant::now();
self.stats.write().await.protocol_switches += 1;
let current_protocol = *self.active_protocol.read().await;
if let Some(current) = current_protocol {
if current == new_protocol_type {
debug!("Protocol switch requested but already using {:?}", new_protocol_type);
return Ok(()); }
}
let protocols = self.protocols.read().await;
if !protocols.contains_key(&new_protocol_type) {
self.stats.write().await.failed_switches += 1;
warn!("Protocol {:?} not available for switch", new_protocol_type);
return Err(RiError::NotFound(format!("Protocol {:?} not available", new_protocol_type)));
}
*self.active_protocol.write().await = Some(new_protocol_type);
let mut stats = self.stats.write().await;
stats.successful_switches += 1;
let switch_time = start_time.elapsed().as_millis() as u64;
stats.avg_switch_time_ms = (stats.avg_switch_time_ms + switch_time) / 2;
if let Some(current) = current_protocol {
*stats.protocol_switches.entry(current).or_insert(0) += 1;
}
*stats.protocol_switches.entry(new_protocol_type).or_insert(0) += 1;
let switch_type = match (current_protocol, new_protocol_type) {
(RiProtocolType::Global, RiProtocolType::Private) => "SECURITY_UPGRADE",
(RiProtocolType::Private, RiProtocolType::Global) => "PERFORMANCE_UPGRADE",
_ => "NEUTRAL_SWITCH",
};
info!(
"Protocol switch: {:?} -> {:?} (type: {}, switch_time: {}ms, total_switches: {})",
current_protocol, new_protocol_type, switch_type, switch_time, stats.protocol_switches.values().sum::<u64>()
);
Ok(())
}
pub async fn get_active_protocol(&self) -> RiResult<RiProtocolType> {
self.active_protocol.read().await
.ok_or_else(|| RiError::InvalidState("No active protocol selected".to_string()))
}
pub async fn update_strategy(&self, new_strategy: RiProtocolStrategy) -> RiResult<()> {
*self.strategy.write().await = Some(new_strategy.clone());
let optimal_protocol = self.select_optimal_protocol(&new_strategy).await?;
if let Some(current) = *self.active_protocol.read().await {
if current != optimal_protocol {
self.switch_protocol(optimal_protocol).await?;
}
}
self.stats.write().await.strategy_changes += 1;
Ok(())
}
async fn select_optimal_protocol(&self, strategy: &RiProtocolStrategy) -> RiResult<RiProtocolType> {
match strategy {
RiProtocolStrategy::SecurityBased(context) => {
self.select_security_based_protocol(context).await
}
RiProtocolStrategy::PerformanceBased(context) => {
self.select_performance_based_protocol(context).await
}
RiProtocolStrategy::Adaptive(context) => {
self.select_adaptive_protocol(context).await
}
RiProtocolStrategy::Manual(protocol_type) => {
Ok(*protocol_type)
}
}
}
async fn select_security_based_protocol(&self, context: &RiSecurityContext) -> RiResult<RiProtocolType> {
let protocols = self.protocols.read().await;
let security_score = self.calculate_security_score(context);
debug!("Security-based protocol selection - score: {}, required_level: {:?}, threat_level: {:?}",
security_score, context.required_security_level, context.threat_level);
match security_score {
score if score >= 80 => {
if protocols.contains_key(&RiProtocolType::Private) {
info!("Selected Private protocol for high security requirements (score: {})", security_score);
Ok(RiProtocolType::Private)
} else if protocols.contains_key(&RiProtocolType::Global) {
warn!("Private protocol not available, falling back to Global for high security requirements");
Ok(RiProtocolType::Global)
} else {
Err(RiError::NotFound("No suitable protocol available for high security requirements".to_string()))
}
}
score if score >= 40 => {
if context.threat_level as u8 >= RiThreatLevel::Elevated as u8 ||
context.data_classification as u8 >= RiDataClassification::Confidential as u8 {
if protocols.contains_key(&RiProtocolType::Private) {
info!("Selected Private protocol for medium security with elevated threat/confidential data");
Ok(RiProtocolType::Private)
} else {
warn!("Private protocol not available for medium security requirements, using Global");
Ok(RiProtocolType::Global)
}
} else {
info!("Selected Global protocol for medium security requirements");
Ok(RiProtocolType::Global)
}
}
_ => {
if protocols.contains_key(&RiProtocolType::Global) {
debug!("Selected Global protocol for low security requirements");
Ok(RiProtocolType::Global)
} else if protocols.contains_key(&RiProtocolType::Private) {
warn!("Global protocol not available, using Private for low security requirements");
Ok(RiProtocolType::Private)
} else {
Err(RiError::NotFound("No suitable protocol available for low security requirements".to_string()))
}
}
}
}
fn calculate_security_score(&self, context: &RiSecurityContext) -> u8 {
let mut score = 0u8;
score += match context.required_security_level {
RiSecurityLevel::None => 0,
RiSecurityLevel::Basic => 10,
RiSecurityLevel::Standard => 25,
RiSecurityLevel::High => 35,
RiSecurityLevel::Maximum => 40,
};
score += match context.threat_level {
RiThreatLevel::Normal => 0,
RiThreatLevel::Elevated => 15,
RiThreatLevel::High => 20,
RiThreatLevel::Critical => 25,
};
score += match context.data_classification {
RiDataClassification::Public => 0,
RiDataClassification::Internal => 5,
RiDataClassification::Confidential => 15,
RiDataClassification::Secret => 18,
RiDataClassification::TopSecret => 20,
};
score += match context.network_environment {
RiNetworkEnvironment::Trusted => 0,
RiNetworkEnvironment::Unknown => 5,
RiNetworkEnvironment::Untrusted => 8,
RiNetworkEnvironment::Hostile => 10,
};
if !context.compliance_requirements.is_empty() {
score += 5;
}
score.min(100)
}
async fn select_performance_based_protocol(&self, context: &RiPerformanceContext) -> RiResult<RiProtocolType> {
let protocols = self.protocols.read().await;
let performance_score = self.calculate_performance_score(context);
debug!("Performance-based protocol selection - score: {}, required_throughput: {}, max_latency: {}ms",
performance_score, context.required_throughput, context.max_latency_ms);
match performance_score {
score if score >= 80 => {
if protocols.contains_key(&RiProtocolType::Global) {
info!("Selected Global protocol for high performance requirements (score: {})", performance_score);
Ok(RiProtocolType::Global)
} else if protocols.contains_key(&RiProtocolType::Private) {
warn!("Global protocol not available, using Private for high performance requirements");
Ok(RiProtocolType::Private)
} else {
Err(RiError::NotFound("No suitable protocol available for high performance requirements".to_string()))
}
}
score if score >= 40 => {
if context.required_throughput >= 1000 || context.max_latency_ms <= 50 {
if protocols.contains_key(&RiProtocolType::Global) {
info!("Selected Global protocol for medium performance with high throughput/low latency needs");
Ok(RiProtocolType::Global)
} else {
warn!("Global protocol not available for medium performance requirements, using Private");
Ok(RiProtocolType::Private)
}
} else {
if protocols.contains_key(&RiProtocolType::Private) {
info!("Selected Private protocol for medium performance with stability focus");
Ok(RiProtocolType::Private)
} else {
warn!("Private protocol not available for medium performance requirements, using Global");
Ok(RiProtocolType::Global)
}
}
}
_ => {
if protocols.contains_key(&RiProtocolType::Private) {
debug!("Selected Private protocol for low performance requirements");
Ok(RiProtocolType::Private)
} else if protocols.contains_key(&RiProtocolType::Global) {
warn!("Private protocol not available, using Global for low performance requirements");
Ok(RiProtocolType::Global)
} else {
Err(RiError::NotFound("No suitable protocol available for low performance requirements".to_string()))
}
}
}
}
fn calculate_performance_score(&self, context: &RiPerformanceContext) -> u8 {
let mut score = 0u8;
if context.required_throughput >= 100_000_000 { score += 40;
} else if context.required_throughput >= 50_000_000 { score += 30;
} else if context.required_throughput >= 10_000_000 { score += 20;
} else if context.required_throughput >= 1_000_000 { score += 10;
}
if context.max_latency_ms <= 1 {
score += 30;
} else if context.max_latency_ms <= 5 {
score += 25;
} else if context.max_latency_ms <= 10 {
score += 20;
} else if context.max_latency_ms <= 50 {
score += 10;
}
let bandwidth_score = if context.bandwidth_constraints.available_bandwidth >= 1_000_000_000 { 20
} else if context.bandwidth_constraints.available_bandwidth >= 100_000_000 { 15
} else if context.bandwidth_constraints.available_bandwidth >= 10_000_000 { 10
} else {
5
};
score += bandwidth_score;
let congestion_penalty = (context.bandwidth_constraints.congestion_level * 20.0) as u8;
score = score.saturating_sub(congestion_penalty);
if context.stability_requirements.max_packet_loss <= 0.001 { score += 10;
} else if context.stability_requirements.max_packet_loss <= 0.01 { score += 5;
}
score.min(100)
}
async fn select_adaptive_protocol(&self, context: &RiAdaptiveContext) -> RiResult<RiProtocolType> {
let security_score = self.calculate_security_score(&context.security_context);
let performance_score = self.calculate_performance_score(&context.performance_context);
let adaptive_score = self.calculate_adaptive_score(security_score, performance_score, context);
let protocols = self.protocols.read().await;
let learned_preference = self.get_learned_protocol_preference().await;
debug!("Adaptive protocol selection - security_score: {}, performance_score: {}, adaptive_score: {}, learned_preference: {:?}",
security_score, performance_score, adaptive_score, learned_preference);
match adaptive_score {
score if score >= 70 => {
let selected_protocol = if learned_preference == RiProtocolType::Global {
RiProtocolType::Global
} else {
RiProtocolType::Private
};
if protocols.contains_key(&selected_protocol) {
info!("Selected {:?} protocol based on adaptive learning (score: {}, preference: {:?})",
selected_protocol, adaptive_score, learned_preference);
Ok(selected_protocol)
} else {
let fallback = if protocols.contains_key(&RiProtocolType::Global) {
RiProtocolType::Global
} else if protocols.contains_key(&RiProtocolType::Private) {
RiProtocolType::Private
} else {
return Err(RiError::NotFound("No suitable protocol available for adaptive selection".to_string()));
};
warn!("Preferred protocol {:?} not available, falling back to {:?}", selected_protocol, fallback);
Ok(fallback)
}
}
score if score >= 40 => {
let selected_protocol = if context.security_context.required_security_level as u8 >= RiSecurityLevel::Standard as u8 {
RiProtocolType::Private } else {
learned_preference };
if protocols.contains_key(&selected_protocol) {
info!("Selected {:?} protocol for balanced security/performance (score: {})", selected_protocol, adaptive_score);
Ok(selected_protocol)
} else {
let fallback = if protocols.contains_key(&RiProtocolType::Private) {
RiProtocolType::Private
} else {
RiProtocolType::Global
};
warn!("Balanced selection preferred {:?} not available, using {:?}", selected_protocol, fallback);
Ok(fallback)
}
}
_ => {
if protocols.contains_key(&RiProtocolType::Private) {
info!("Selected Private protocol for low adaptive score with security focus (score: {})", adaptive_score);
Ok(RiProtocolType::Private)
} else if protocols.contains_key(&RiProtocolType::Global) {
warn!("Private protocol not available for low adaptive score, using Global");
Ok(RiProtocolType::Global)
} else {
Err(RiError::NotFound("No suitable protocol available for conservative selection".to_string()))
}
}
}
}
fn calculate_adaptive_score(&self, context: &RiAdaptiveContext) -> u8 {
let mut score = 0u8;
let security_contribution = (context.security_weight * 50.0) as u8;
let performance_contribution = (context.performance_weight * 50.0) as u8;
score += security_contribution;
score += performance_contribution;
for trigger in &context.adaptation_triggers {
match trigger {
RiAdaptationTrigger::SecurityBreach => score = score.saturating_add(20),
RiAdaptationTrigger::PerformanceDegradation => score = score.saturating_sub(15),
RiAdaptationTrigger::NetworkChange => score = score.saturating_sub(10),
RiAdaptationTrigger::Manual => score = score.saturating_add(5),
}
}
if context.learning_params.learning_rate > 0.5 {
score = score.saturating_add(10);
}
score.min(100)
}
async fn get_learned_protocol_preference(&self, context: &RiAdaptiveContext) -> f32 {
let stats = self.stats.read().await;
let global_success_rate = if let Some(global_switches) = stats.protocol_switches.get(&RiProtocolType::Global) {
if *global_switches > 0 {
(stats.successful_switches as f32 / *global_switches as f32) * 100.0
} else {
50.0 }
} else {
50.0
};
let private_success_rate = if let Some(private_switches) = stats.protocol_switches.get(&RiProtocolType::Private) {
if *private_switches > 0 {
(stats.successful_switches as f32 / *private_switches as f32) * 100.0
} else {
50.0
}
} else {
50.0
};
let weighted_score = if context.security_weight > context.performance_weight {
(private_success_rate * 0.7 + global_success_rate * 0.3)
} else if context.performance_weight > context.security_weight {
(global_success_rate * 0.7 + private_success_rate * 0.3)
} else {
(global_success_rate + private_success_rate) / 2.0
};
weighted_score.max(0.0).min(100.0)
}
async fn assess_current_network_conditions(&self) -> RiNetworkCondition {
RiNetworkCondition::Good
}
pub async fn get_stats(&self) -> RiProtocolAdapterStats {
*self.stats.read().await
}
pub async fn shutdown(&mut self) -> RiResult<()> {
self.connection_manager.clear_all_connections().await?;
let mut protocols = self.protocols.write().await;
for (_, mut protocol) in protocols.drain() {
protocol.shutdown().await?;
}
*self.initialized.write().await = false;
Ok(())
}
}
impl Default for RiProtocolAdapter {
fn default() -> Self {
Self::new()
}
}
impl RiConnectionManager {
async fn store_connection(
&self,
connection_id: String,
connection: Box<dyn RiProtocolConnection>,
protocol_type: RiProtocolType,
) -> RiResult<()> {
let metadata = RiConnectionMetadata {
original_protocol: protocol_type,
current_protocol: protocol_type,
established_at: Instant::now(),
last_switch: None,
switch_count: 0,
state_data: FxHashMap::default(),
};
self.connections.write().await.insert(connection_id.clone(), connection.into());
self.metadata.write().await.insert(connection_id, metadata);
Ok(())
}
async fn clear_all_connections(&self) -> RiResult<()> {
self.connections.write().await.clear();
self.metadata.write().await.clear();
Ok(())
}
}
struct RiProtocolConnectionWrapper {
connection_id: String,
connection_manager: Arc<RiConnectionManager>,
stats: Arc<RwLock<RiProtocolAdapterStats>>,
}
#[async_trait]
impl RiProtocolConnection for RiProtocolConnectionWrapper {
async fn send_message(&self, data: &[u8]) -> RiResult<Vec<u8>> {
let connections = self.connection_manager.connections.read().await;
let connection = connections.get(&self.connection_id)
.ok_or_else(|| RiError::NotFound(format!("Connection {} not found", self.connection_id)))?;
connection.send_message(data).await
}
async fn send_message_with_flags(&self, data: &[u8], flags: RiMessageFlags) -> RiResult<Vec<u8>> {
let connections = self.connection_manager.connections.read().await;
let connection = connections.get(&self.connection_id)
.ok_or_else(|| RiError::NotFound(format!("Connection {} not found", self.connection_id)))?;
connection.send_message_with_flags(data, flags).await
}
async fn receive_message(&self) -> RiResult<Vec<u8>> {
let connections = self.connection_manager.connections.read().await;
let connection = connections.get(&self.connection_id)
.ok_or_else(|| RiError::NotFound(format!("Connection {} not found", self.connection_id)))?;
connection.receive_message().await
}
fn is_active(&self) -> bool {
let metadata_guard = self.connection_manager.metadata.blocking_read();
if let Some(metadata) = metadata_guard.get(&self.connection_id) {
let elapsed = metadata.established_at.elapsed();
elapsed.as_secs() < 300
} else {
false
}
}
fn get_connection_info(&self) -> RiConnectionInfo {
RiConnectionInfo {
connection_id: self.connection_id.clone(),
target_id: "adapter-target".to_string(),
protocol_type: RiProtocolType::Global,
established_at: Instant::now(),
last_activity: Instant::now(),
security_level: RiSecurityLevel::Standard,
}
}
async fn close(&self) -> RiResult<()> {
let mut connections = self.connection_manager.connections.write().await;
connections.remove(&self.connection_id);
let mut metadata = self.connection_manager.metadata.write().await;
metadata.remove(&self.connection_id);
Ok(())
}
}