use super::Server;
use super::server_core::ServerCore;
use crate::common::config_types::TransportProtocol;
use crate::common::error::Result;
use crate::common::protocol::Frame;
use crate::server::config::ServerConfig;
use crate::server::handle::ServerHandle;
use async_trait::async_trait;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::sync::Mutex;
use tracing::error;
#[cfg(feature = "quic")]
use super::quic::QUICServer;
#[cfg(feature = "tcp")]
use super::tcp::TCPServer;
#[cfg(feature = "websocket")]
use super::websocket::WebSocketServer;
pub struct HybridServer {
servers: Vec<Arc<Mutex<Box<dyn Server>>>>,
protocols: Vec<TransportProtocol>,
is_running: Arc<AtomicBool>,
core: Option<Arc<ServerCore>>,
config: ServerConfig,
}
impl HybridServer {
pub fn new(config: ServerConfig) -> Result<Self> {
Self::with_connection_manager(config, None, None, None, None)
}
pub fn with_connection_manager(
config: ServerConfig,
connection_manager: Option<Arc<crate::server::connection::ConnectionManager>>,
device_manager: Option<Arc<crate::server::device::DeviceManager>>,
event_handler: Option<Arc<dyn crate::server::events::handler::ServerEventHandler>>,
authenticator: Option<Arc<dyn crate::server::auth::Authenticator>>,
) -> Result<Self> {
Self::with_connection_manager_and_pipeline(
config,
connection_manager,
device_manager,
event_handler,
authenticator,
Vec::new(),
Vec::new(),
)
}
pub fn with_connection_manager_and_pipeline(
config: ServerConfig,
connection_manager: Option<Arc<crate::server::connection::ConnectionManager>>,
device_manager: Option<Arc<crate::server::device::DeviceManager>>,
event_handler: Option<Arc<dyn crate::server::events::handler::ServerEventHandler>>,
authenticator: Option<Arc<dyn crate::server::auth::Authenticator>>,
middlewares: Vec<crate::common::message::pipeline::ArcMessageMiddleware>,
processors: Vec<crate::common::message::pipeline::ArcMessageProcessor>,
) -> Result<Self> {
let mut core = ServerCore::new(&config, connection_manager.clone());
let final_device_manager = if let Some(dm) = device_manager {
Some(dm)
} else if config.device_conflict_strategy
!= crate::common::device::DeviceConflictStrategy::AllowAll
{
Some(Arc::new(crate::server::device::DeviceManager::new(
config.device_conflict_strategy.clone(),
)))
} else {
None
};
core = core
.with_device_manager(final_device_manager)
.with_event_handler(event_handler)
.with_authenticator(authenticator);
if !middlewares.is_empty() || !processors.is_empty() {
tokio::task::block_in_place(|| {
let handle = tokio::runtime::Handle::try_current().map_err(|_| {
crate::common::error::FlareError::general_error(
"Tokio runtime not available".to_string(),
)
})?;
handle.block_on(async {
for middleware in middlewares {
core.add_middleware(middleware).await;
}
for processor in processors {
core.add_processor(processor).await;
}
});
Ok::<(), crate::common::error::FlareError>(())
})
.map_err(|e| {
crate::common::error::FlareError::general_error(format!(
"Failed to add middlewares/processors: {}",
e
))
})?;
}
let shared_core = Arc::new(core);
let protocols = config.get_protocols();
let mut servers = Vec::new();
let mut effective_protocols = Vec::new();
let has_websocket = protocols.contains(&TransportProtocol::WebSocket);
for protocol in &protocols {
let mut server_config = config.clone();
server_config.transport = *protocol;
server_config.transports = None;
let bind_address = config.get_protocol_address(protocol);
server_config.bind_address = bind_address;
let server_result: Result<Box<dyn Server>> = match protocol {
TransportProtocol::WebSocket => {
#[cfg(feature = "websocket")]
{
Ok(Box::new(WebSocketServer::with_shared_core(
server_config,
shared_core.clone(),
)))
}
#[cfg(not(feature = "websocket"))]
{
let _ = (server_config, &shared_core);
Err(crate::common::error::FlareError::operation_not_supported(
"WebSocket server feature is disabled",
))
}
}
TransportProtocol::QUIC => {
#[cfg(feature = "quic")]
{
QUICServer::with_shared_core(server_config, shared_core.clone())
.map(|s| Box::new(s) as Box<dyn Server>)
}
#[cfg(not(feature = "quic"))]
{
let _ = (server_config, &shared_core);
Err(crate::common::error::FlareError::operation_not_supported(
"QUIC server feature is disabled",
))
}
}
TransportProtocol::TCP => {
#[cfg(feature = "tcp")]
{
Ok(Box::new(TCPServer::with_shared_core(
server_config,
shared_core.clone(),
)))
}
#[cfg(not(feature = "tcp"))]
{
let _ = (server_config, &shared_core);
Err(crate::common::error::FlareError::operation_not_supported(
"TCP server feature is disabled",
))
}
}
};
match server_result {
Ok(server) => {
servers.push(Arc::new(Mutex::new(server)));
effective_protocols.push(*protocol);
}
Err(e) if *protocol == TransportProtocol::QUIC && has_websocket => {
tracing::warn!(
"QUIC server unavailable ({e}), continuing with WebSocket only (set FLARE_WS_ONLY=1 to skip QUIC bind attempts)"
);
}
Err(e) => return Err(e),
}
}
if effective_protocols.is_empty() {
return Err(crate::common::error::FlareError::connection_failed(
"No transport servers could be started".to_string(),
));
}
Ok(Self {
servers,
protocols: effective_protocols,
is_running: Arc::new(AtomicBool::new(false)),
core: Some(shared_core),
config,
})
}
pub fn protocols(&self) -> &[TransportProtocol] {
&self.protocols
}
pub fn core(&self) -> Option<&Arc<ServerCore>> {
self.core.as_ref()
}
pub fn core_mut(&mut self) -> Option<&mut Arc<ServerCore>> {
self.core.as_mut()
}
}
#[async_trait::async_trait]
impl Server for HybridServer {
async fn start(&mut self) -> Result<()> {
if let Some(ref mut core) = self.core {
core.start_heartbeat(&self.config);
}
let mut started_count = 0;
let mut errors = Vec::new();
for server in &self.servers {
let mut s = server.lock().await;
match s.start().await {
Ok(_) => {
started_count += 1;
}
Err(e) => {
error!("Failed to start server: {:?}", e);
errors.push(e);
}
}
}
if started_count == 0 && !errors.is_empty() {
self.is_running.store(false, Ordering::SeqCst);
return Err(errors.remove(0));
}
if started_count > 0 {
self.is_running.store(true, Ordering::SeqCst);
}
Ok(())
}
async fn stop(&mut self) -> Result<()> {
self.is_running.store(false, Ordering::SeqCst);
if let Some(ref mut core) = self.core {
core.stop_heartbeat();
}
for server in &self.servers {
let mut s = server.lock().await;
if let Err(e) = s.stop().await {
error!("Failed to stop server: {:?}", e);
}
}
Ok(())
}
fn is_running(&self) -> bool {
self.is_running.load(Ordering::SeqCst)
}
}
#[async_trait]
impl ServerHandle for HybridServer {
async fn send_to(&self, connection_id: &str, frame: &Frame) -> Result<()> {
if let Some(ref core) = self.core {
return ServerHandle::send_to(&**core, connection_id, frame).await;
}
Err(crate::common::error::FlareError::protocol_error(
"ServerCore not initialized".to_string(),
))
}
async fn send_to_user(&self, user_id: &str, frame: &Frame) -> Result<()> {
if let Some(ref core) = self.core {
return ServerHandle::send_to_user(&**core, user_id, frame).await;
}
Err(crate::common::error::FlareError::protocol_error(
"ServerCore not initialized".to_string(),
))
}
async fn broadcast(&self, frame: &Frame) -> Result<()> {
if let Some(ref core) = self.core {
return ServerHandle::broadcast(&**core, frame).await;
}
Err(crate::common::error::FlareError::protocol_error(
"ServerCore not initialized".to_string(),
))
}
async fn broadcast_except(&self, frame: &Frame, exclude_connection_id: &str) -> Result<()> {
if let Some(ref core) = self.core {
return ServerHandle::broadcast_except(&**core, frame, exclude_connection_id).await;
}
Err(crate::common::error::FlareError::protocol_error(
"ServerCore not initialized".to_string(),
))
}
async fn disconnect(&self, connection_id: &str) -> Result<()> {
if let Some(ref core) = self.core {
return ServerHandle::disconnect(&**core, connection_id).await;
}
Err(crate::common::error::FlareError::protocol_error(
"ServerCore not initialized".to_string(),
))
}
fn connection_count(&self) -> usize {
if let Some(ref core) = self.core {
return ServerHandle::connection_count(&**core);
}
0
}
fn user_count(&self) -> usize {
if let Some(ref core) = self.core {
return ServerHandle::user_count(&**core);
}
0
}
}