init
This commit is contained in:
12
Cargo.lock
generated
12
Cargo.lock
generated
@@ -97,6 +97,17 @@ version = "1.7.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-trait"
|
||||||
|
version = "0.1.89"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atoi"
|
name = "atoi"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@@ -1131,6 +1142,7 @@ name = "ox_speak_server"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
"chrono",
|
"chrono",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
|
|||||||
@@ -32,3 +32,4 @@ hyper = "1.7"
|
|||||||
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-rustls", "sqlite", "postgres", "mysql", "uuid", "chrono", "migrate"] }
|
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-rustls", "sqlite", "postgres", "mysql", "uuid", "chrono", "migrate"] }
|
||||||
uuid = { version = "1.18", features = ["v4", "v7", "serde"] }
|
uuid = { version = "1.18", features = ["v4", "v7", "serde"] }
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
async-trait = "0.1.89"
|
||||||
@@ -2,11 +2,19 @@ use std::io;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use crate::app::http::router::configure_routes;
|
use crate::app::http::router::configure_routes;
|
||||||
|
use crate::db::context::DbContext;
|
||||||
use crate::network::http::server::HttpServer;
|
use crate::network::http::server::HttpServer;
|
||||||
use crate::network::udp::server::UdpServer;
|
use crate::network::udp::server::UdpServer;
|
||||||
use crate::utils::config::Config;
|
use crate::utils::config::Config;
|
||||||
use crate::utils::logger::ContextLogger;
|
use crate::utils::logger::ContextLogger;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Context {
|
||||||
|
udp_server: Arc<UdpServer>,
|
||||||
|
http_server: Arc<HttpServer>,
|
||||||
|
db: Arc<DbContext>
|
||||||
|
}
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
config: Config,
|
config: Config,
|
||||||
context: Arc<Context>,
|
context: Arc<Context>,
|
||||||
@@ -33,9 +41,17 @@ impl App {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let db = match DbContext::new("sqlite:ox_speak_server.db").await {
|
||||||
|
Ok(db) => db,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, format!("Failed to create database context: {}", e)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let context = Context {
|
let context = Context {
|
||||||
udp_server,
|
udp_server: Arc::new(udp_server),
|
||||||
http_server,
|
http_server: Arc::new(http_server),
|
||||||
|
db: Arc::new(db)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -47,15 +63,38 @@ impl App {
|
|||||||
|
|
||||||
pub async fn run(self) -> io::Result<()> {
|
pub async fn run(self) -> io::Result<()> {
|
||||||
self.logger.info("Starting application");
|
self.logger.info("Starting application");
|
||||||
self.context.udp_server.run().await?;
|
|
||||||
|
|
||||||
self.context.http_server.run().await?;
|
let udp_server = self.context.udp_server.clone();
|
||||||
|
let http_server = self.context.http_server.clone();
|
||||||
|
let db = self.context.db.clone();
|
||||||
|
|
||||||
|
let udp_handle = tokio::spawn(async move {
|
||||||
|
udp_server.run().await
|
||||||
|
});
|
||||||
|
|
||||||
|
let router = configure_routes(db);
|
||||||
|
let http_handle = tokio::spawn(async move {
|
||||||
|
http_server.run(router).await
|
||||||
|
});
|
||||||
|
|
||||||
|
tokio::select! {
|
||||||
|
result = udp_handle => {
|
||||||
|
match result {
|
||||||
|
Ok(Ok(())) => println!("UDP server terminated"),
|
||||||
|
Ok(Err(e)) => return Err(e),
|
||||||
|
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = http_handle => {
|
||||||
|
match result {
|
||||||
|
Ok(Ok(())) => println!("HTTP server terminated"),
|
||||||
|
Ok(Err(e)) => return Err(e),
|
||||||
|
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Context {
|
|
||||||
udp_server: UdpServer,
|
|
||||||
http_server: HttpServer
|
|
||||||
}
|
|
||||||
42
src/app/http/api/channel.rs
Normal file
42
src/app/http/api/channel.rs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use axum::{Extension, Json, Router};
|
||||||
|
use axum::body::Body;
|
||||||
|
use axum::extract::{Path, State};
|
||||||
|
use axum::http::Request;
|
||||||
|
use axum::response::IntoResponse;
|
||||||
|
use axum::routing::{get, post};
|
||||||
|
use hyper::StatusCode;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
use crate::app::http::request_context::RequestContext;
|
||||||
|
use crate::app::http::router::AppState;
|
||||||
|
use crate::db::{Message, Server};
|
||||||
|
|
||||||
|
pub fn routes() -> Router<Arc<AppState>> {
|
||||||
|
Router::new()
|
||||||
|
.route("/:server_id/", get(channel_list))
|
||||||
|
.route("/create/", post(channel_create))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct CreateServerRequest {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn channel_list(
|
||||||
|
State(state): State<Arc<AppState>>,
|
||||||
|
Extension(ctx): Extension<RequestContext>,
|
||||||
|
Path(server_id): Path<Uuid>
|
||||||
|
) -> Result<Json<Vec<Server>>, StatusCode> {
|
||||||
|
Ok(Json(vec![]))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn channel_create(
|
||||||
|
State(state): State<Arc<AppState>>,
|
||||||
|
Extension(ctx): Extension<RequestContext>,
|
||||||
|
Path(server_id): Path<Uuid>,
|
||||||
|
Json(payload): Json<CreateServerRequest>,
|
||||||
|
) -> Result<Json<Server>, StatusCode> {
|
||||||
|
let server = Server::new("test".to_string(), None);
|
||||||
|
Ok(Json(server))
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::{Json, Router};
|
use axum::{Json, Router};
|
||||||
|
use axum::extract::State;
|
||||||
use axum::routing::get;
|
use axum::routing::get;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
use crate::app::http::router::AppState;
|
||||||
|
|
||||||
pub fn routes() -> Router {
|
pub fn routes() -> Router {
|
||||||
Router::new()
|
Router::new()
|
||||||
|
|||||||
@@ -1,6 +1,22 @@
|
|||||||
use axum::Router;
|
use std::sync::Arc;
|
||||||
|
use axum::extract::{Path, State};
|
||||||
|
use axum::{Json, Router};
|
||||||
|
use axum::routing::get;
|
||||||
|
use axum::http::StatusCode;
|
||||||
|
use crate::app::http::router::AppState;
|
||||||
|
use crate::db::Message;
|
||||||
|
|
||||||
pub fn routes() -> Router {
|
pub fn routes() -> Router<Arc<AppState>> {
|
||||||
Router::new()
|
Router::new()
|
||||||
.nest("/message", Router::new())
|
.route("/message/:channel_id/", get(list_messages))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_messages(
|
||||||
|
State(state): State<Arc<AppState>>,
|
||||||
|
Path(channel_id): Path<i64>
|
||||||
|
) -> Result<Json<Vec<Message>>, StatusCode> {
|
||||||
|
// todo : Récupérer les messages du channel
|
||||||
|
// vérifier les permissions
|
||||||
|
|
||||||
|
Ok(Json(vec![]))
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod message;
|
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
pub mod message;
|
||||||
|
pub mod channel;
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use axum::{Extension, Json, Router};
|
||||||
|
use axum::extract::State;
|
||||||
|
use axum::response::IntoResponse;
|
||||||
|
use axum::routing::get;
|
||||||
|
use hyper::StatusCode;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::app::http::request_context::RequestContext;
|
||||||
|
use crate::app::http::router::AppState;
|
||||||
|
use crate::db::{Message, Server};
|
||||||
|
|
||||||
|
pub fn routes() -> Router<Arc<AppState>> {
|
||||||
|
Router::new()
|
||||||
|
.route("/", get(list_servers))
|
||||||
|
.route("/create", get(create_server))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct CreateServerRequest {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_servers(
|
||||||
|
State(state): State<Arc<AppState>>,
|
||||||
|
Extension(ctx): Extension<RequestContext>,
|
||||||
|
) -> Result<Json<Vec<Server>>, StatusCode> {
|
||||||
|
Ok(Json(vec![]))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_server(
|
||||||
|
State(state): State<Arc<AppState>>,
|
||||||
|
Json(payload): Json<CreateServerRequest>
|
||||||
|
) -> Result<Json<Server>, StatusCode> {
|
||||||
|
let server = Server::new("test".to_string(), None);
|
||||||
|
Ok(Json(server))
|
||||||
|
}
|
||||||
97
src/app/http/middleware/auth_middleware.rs
Normal file
97
src/app/http/middleware/auth_middleware.rs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
use axum::{
|
||||||
|
body::Body,
|
||||||
|
extract::{Request, State},
|
||||||
|
http::header,
|
||||||
|
middleware::Next,
|
||||||
|
response::Response,
|
||||||
|
};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use crate::app::http::request_context::RequestContext;
|
||||||
|
use crate::db::context::DbContext;
|
||||||
|
|
||||||
|
/// Middleware d'authentification.
|
||||||
|
pub async fn auth_middleware(
|
||||||
|
State(db): State<Arc<DbContext>>,
|
||||||
|
req: Request<Body>,
|
||||||
|
next: Next,
|
||||||
|
) -> Response {
|
||||||
|
// Extraire les informations de base
|
||||||
|
let method = req.method().clone();
|
||||||
|
let uri = req.uri().clone();
|
||||||
|
let path = uri.path().to_string();
|
||||||
|
let query_string = uri.query().map(|q| q.to_string());
|
||||||
|
let headers = req.headers().clone();
|
||||||
|
|
||||||
|
// Extraire l'IP du client
|
||||||
|
let ip_address = headers
|
||||||
|
.get("x-forwarded-for")
|
||||||
|
.or_else(|| headers.get("x-real-ip"))
|
||||||
|
.and_then(|h| h.to_str().ok())
|
||||||
|
.map(|s| s.split(',').next().unwrap_or(s).trim().to_string())
|
||||||
|
.or_else(|| {
|
||||||
|
// Fallback sur l'adresse de connexion si disponible
|
||||||
|
req.extensions()
|
||||||
|
.get::<std::net::SocketAddr>()
|
||||||
|
.map(|addr| addr.ip().to_string())
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extraire User-Agent
|
||||||
|
let user_agent = headers
|
||||||
|
.get(header::USER_AGENT)
|
||||||
|
.and_then(|h| h.to_str().ok())
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
|
||||||
|
// Extraire Content-Type
|
||||||
|
let content_type = headers
|
||||||
|
.get(header::CONTENT_TYPE)
|
||||||
|
.and_then(|h| h.to_str().ok())
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
|
||||||
|
// Session simple (vous pouvez l'enrichir avec un vrai système de session)
|
||||||
|
let session = Arc::new(HashMap::new());
|
||||||
|
|
||||||
|
// Extraire le token d'authentification
|
||||||
|
let mut auth_token = None;
|
||||||
|
let mut user = None;
|
||||||
|
|
||||||
|
if let Some(auth_header) = headers.get(header::AUTHORIZATION) {
|
||||||
|
if let Ok(auth_str) = auth_header.to_str() {
|
||||||
|
if let Some(token) = auth_str.strip_prefix("Bearer ") {
|
||||||
|
auth_token = Some(token.to_string());
|
||||||
|
|
||||||
|
// TODO: Récupérer l'utilisateur depuis la DB
|
||||||
|
// match db.repositories().user_repository.find_by_token(token).await {
|
||||||
|
// Ok(found_user) => user = Some(found_user),
|
||||||
|
// Err(e) => log::warn!("Token invalide: {}", e),
|
||||||
|
// }
|
||||||
|
|
||||||
|
log::debug!("Token d'authentification détecté");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construire le contexte complet
|
||||||
|
let context = RequestContext {
|
||||||
|
user,
|
||||||
|
method,
|
||||||
|
uri,
|
||||||
|
path,
|
||||||
|
query_string,
|
||||||
|
headers,
|
||||||
|
session,
|
||||||
|
ip_address,
|
||||||
|
user_agent,
|
||||||
|
content_type,
|
||||||
|
auth_token,
|
||||||
|
};
|
||||||
|
|
||||||
|
log::debug!("Request: {}", context.debug_info());
|
||||||
|
|
||||||
|
// Injecter le contexte dans les extensions
|
||||||
|
let (mut parts, body) = req.into_parts();
|
||||||
|
parts.extensions.insert(context);
|
||||||
|
let req = Request::from_parts(parts, body);
|
||||||
|
|
||||||
|
next.run(req).await
|
||||||
|
}
|
||||||
1
src/app/http/middleware/mod.rs
Normal file
1
src/app/http/middleware/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod auth_middleware;
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
pub mod router;
|
pub mod router;
|
||||||
|
|
||||||
pub mod api;
|
pub mod api;
|
||||||
|
mod request_context;
|
||||||
|
mod middleware;
|
||||||
|
|||||||
40
src/app/http/request_context.rs
Normal file
40
src/app/http/request_context.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
use axum::http::{header::HeaderMap, Method, Uri};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use crate::db::models::User;
|
||||||
|
|
||||||
|
/// Contexte de requête (style Django)
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct RequestContext {
|
||||||
|
pub user: Option<User>,
|
||||||
|
pub method: Method,
|
||||||
|
pub uri: Uri,
|
||||||
|
pub path: String,
|
||||||
|
pub query_string: Option<String>,
|
||||||
|
pub headers: HeaderMap,
|
||||||
|
pub session: Arc<HashMap<String, String>>,
|
||||||
|
pub ip_address: Option<String>,
|
||||||
|
pub user_agent: Option<String>,
|
||||||
|
pub content_type: Option<String>,
|
||||||
|
pub auth_token: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RequestContext {
|
||||||
|
pub fn is_authenticated(&self) -> bool {
|
||||||
|
self.user.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_header(&self, name: &str) -> Option<&str> {
|
||||||
|
self.headers.get(name)?.to_str().ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn debug_info(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"{} {} - User: {} - IP: {}",
|
||||||
|
self.method,
|
||||||
|
self.path,
|
||||||
|
self.user.as_ref().map(|u| u.username.as_str()).unwrap_or("Anonymous"),
|
||||||
|
self.ip_address.as_deref().unwrap_or("unknown"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,29 @@
|
|||||||
use axum::Router;
|
use std::sync::Arc;
|
||||||
|
use axum::{Router, middleware};
|
||||||
use crate::app::http::api;
|
use crate::app::http::api;
|
||||||
use crate::app::http::api::core;
|
use crate::app::http::api::{channel, core, message, server};
|
||||||
|
use crate::app::http::middleware::auth_middleware;
|
||||||
|
use crate::app::http::middleware::auth_middleware::auth_middleware;
|
||||||
|
use crate::db::context::DbContext;
|
||||||
|
|
||||||
pub fn configure_routes() -> Router {
|
#[derive(Clone)]
|
||||||
let api_router = Router::new();
|
pub struct AppState {
|
||||||
|
db: Arc<DbContext>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn configure_routes(db_context: Arc<DbContext>) -> Router {
|
||||||
|
let app_state = Arc::new(AppState {
|
||||||
|
db: db_context.clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
let api_router = Router::new()
|
||||||
|
.nest("/server/", server::routes())
|
||||||
|
.nest("/channel/", channel::routes())
|
||||||
|
.nest("/message/", message::routes())
|
||||||
|
.with_state(app_state);
|
||||||
|
|
||||||
Router::new()
|
Router::new()
|
||||||
.merge(core::routes())
|
.merge(core::routes())
|
||||||
.nest("/api", api_router)
|
.nest("/api", api_router)
|
||||||
|
.layer(middleware::from_fn_with_state(db_context.clone(), auth_middleware))
|
||||||
}
|
}
|
||||||
|
|||||||
0
src/app/http/ws/ws.rs
Normal file
0
src/app/http/ws/ws.rs
Normal file
@@ -15,6 +15,7 @@ struct Repositories {
|
|||||||
channel_user: ChannelUserRepository
|
channel_user: ChannelUserRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct DbContext {
|
pub struct DbContext {
|
||||||
pool: Arc<SqlitePool>,
|
pool: Arc<SqlitePool>,
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
pub mod models;
|
pub mod models;
|
||||||
pub mod repositories;
|
pub mod repositories;
|
||||||
mod context;
|
pub mod context;
|
||||||
|
|
||||||
pub use models::*;
|
pub use models::*;
|
||||||
pub use repositories::*;
|
pub use repositories::*;
|
||||||
@@ -4,6 +4,7 @@ use axum::{Router};
|
|||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use crate::utils::logger::ContextLogger;
|
use crate::utils::logger::ContextLogger;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct HttpServer {
|
pub struct HttpServer {
|
||||||
bind_addr: SocketAddr,
|
bind_addr: SocketAddr,
|
||||||
logger: ContextLogger,
|
logger: ContextLogger,
|
||||||
@@ -20,7 +21,7 @@ impl HttpServer {
|
|||||||
Ok(Self { bind_addr, logger })
|
Ok(Self { bind_addr, logger })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(self, router: Router) -> io::Result<()> {
|
pub async fn run(&self, router: Router) -> io::Result<()> {
|
||||||
self.logger.info(&format!("Starting HTTP server on {}", self.bind_addr));
|
self.logger.info(&format!("Starting HTTP server on {}", self.bind_addr));
|
||||||
|
|
||||||
let listener = TcpListener::bind(self.bind_addr).await?;
|
let listener = TcpListener::bind(self.bind_addr).await?;
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ use tokio::task;
|
|||||||
use crate::utils::shared_store::{SharedArcMap, SharedArcVec};
|
use crate::utils::shared_store::{SharedArcMap, SharedArcVec};
|
||||||
use crate::utils::toolbox::number_of_cpus;
|
use crate::utils::toolbox::number_of_cpus;
|
||||||
use crate::utils::logger::ContextLogger;
|
use crate::utils::logger::ContextLogger;
|
||||||
use crate::{log_info, log_warn, log_error, log_debug};
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct UdpServer {
|
pub struct UdpServer {
|
||||||
// table de routage channel -> socket
|
// table de routage channel -> socket
|
||||||
table_router: SharedArcMap<String, SharedArcVec<SocketAddr>>,
|
table_router: SharedArcMap<String, SharedArcVec<SocketAddr>>,
|
||||||
@@ -52,7 +52,12 @@ impl UdpServer {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(self) -> io::Result<()> {
|
|
||||||
|
pub fn router(&self) -> SharedArcMap<String, SharedArcVec<SocketAddr>> {
|
||||||
|
self.table_router.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(&self) -> io::Result<()> {
|
||||||
// S'assure qu'on est sur une runtime (utile si appelé hors #[tokio::main])
|
// S'assure qu'on est sur une runtime (utile si appelé hors #[tokio::main])
|
||||||
let _ = Handle::try_current().map_err(|e| {
|
let _ = Handle::try_current().map_err(|e| {
|
||||||
self.logger.error(&format!("Runtime Tokio not available: {}", e));
|
self.logger.error(&format!("Runtime Tokio not available: {}", e));
|
||||||
@@ -78,7 +83,7 @@ impl UdpServer {
|
|||||||
// Impl Linux/macOS (SO_REUSEPORT)
|
// Impl Linux/macOS (SO_REUSEPORT)
|
||||||
// -------------------------
|
// -------------------------
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
async fn run_unix(self) -> io::Result<()> {
|
async fn run_unix(&self) -> io::Result<()> {
|
||||||
use socket2::{Domain, Protocol, Socket, Type};
|
use socket2::{Domain, Protocol, Socket, Type};
|
||||||
|
|
||||||
self.logger.info(&format!("Starting UDP server on {} with {} workers - Unix mode", self.bind_addr, self.workers));
|
self.logger.info(&format!("Starting UDP server on {} with {} workers - Unix mode", self.bind_addr, self.workers));
|
||||||
@@ -121,7 +126,7 @@ impl UdpServer {
|
|||||||
// Impl Windows (1 socket partagé, N tâches concurrentes)
|
// Impl Windows (1 socket partagé, N tâches concurrentes)
|
||||||
// -------------------------
|
// -------------------------
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
async fn run_windows(self) -> io::Result<()> {
|
async fn run_windows(&self) -> io::Result<()> {
|
||||||
self.logger.info(&format!("Starting UDP server on {} with {} workers - Win mode", self.bind_addr, self.workers));
|
self.logger.info(&format!("Starting UDP server on {} with {} workers - Win mode", self.bind_addr, self.workers));
|
||||||
|
|
||||||
let udp = UdpSocket::bind(self.bind_addr).await?;
|
let udp = UdpSocket::bind(self.bind_addr).await?;
|
||||||
|
|||||||
Reference in New Issue
Block a user