Initial implementation of a signaling server using actix-web.
This commit is contained in:
commit
f61d7b2ca6
22
.gitignore
vendored
Normal file
22
.gitignore
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
debug
|
||||||
|
target
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# These are backup files generated by rustfmt
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Generated by cargo mutants
|
||||||
|
# Contains mutation testing data
|
||||||
|
**/mutants.out*/
|
||||||
|
|
||||||
|
# RustRover
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
1785
Cargo.lock
generated
Normal file
1785
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "niom-signaling"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web = "4.11.0"
|
||||||
|
actix-ws = "0.3.0"
|
||||||
|
futures-util = "0.3"
|
||||||
|
tokio = { version = "1.44.1", features = ["full"] }
|
||||||
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
serde_json = "1.0.143"
|
||||||
|
env_logger = "0.11.8"
|
||||||
80
src/main.rs
Normal file
80
src/main.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
use actix_web::{web, App, Error, HttpRequest, HttpResponse, HttpServer, Result};
|
||||||
|
use futures_util::StreamExt;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::broadcast;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct AppState {
|
||||||
|
broadcaster: Arc<broadcast::Sender<SignalingMessage>>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
struct SignalingMessage {
|
||||||
|
from: String,
|
||||||
|
to: String,
|
||||||
|
msg_type: String, // "offer", "answer", "ice-candidate", "text", "screen-share"
|
||||||
|
data: String // SDP, ICE, Text, Screen-Share metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() -> std::io::Result<()> {
|
||||||
|
env_logger::init();
|
||||||
|
|
||||||
|
let (tx, _rx) = broadcast::channel::<SignalingMessage>(1000);
|
||||||
|
let app_state = AppState {
|
||||||
|
broadcaster: Arc::new(tx)
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("Server is running on http://localhost:8080");
|
||||||
|
HttpServer::new(move || {
|
||||||
|
App::new()
|
||||||
|
.app_data(web::Data::new(app_state.clone()))
|
||||||
|
.route("/ws", web::get().to(websocket_handler))
|
||||||
|
})
|
||||||
|
.bind("127.0.0.1:8080")?
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn websocket_handler(
|
||||||
|
req: HttpRequest,
|
||||||
|
body: web::Payload,
|
||||||
|
data: web::Data<AppState>
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
let (response, mut session, mut msg_stream) = actix_ws::handle(&req, body)?;
|
||||||
|
let broadcaster = data.broadcaster.clone();
|
||||||
|
let mut rx = broadcaster.subscribe();
|
||||||
|
|
||||||
|
// Handle incoming messages
|
||||||
|
let broadcaster_clone = broadcaster.clone();
|
||||||
|
actix_web::rt::spawn(async move {
|
||||||
|
while let Some(Ok(msg)) = msg_stream.next().await {
|
||||||
|
match msg {
|
||||||
|
actix_ws::Message::Text(text) => {
|
||||||
|
println!("Received text message: {}", text);
|
||||||
|
if let Ok(signal_msg) = serde_json::from_str::<SignalingMessage>(&text) {
|
||||||
|
// Broadcast the message to all subscribers (group chat)
|
||||||
|
// or handle private messages based on `to` field
|
||||||
|
let _ = broadcaster_clone.send(signal_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actix_ws::Message::Close(_) => break,
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle outgoing messages
|
||||||
|
actix_web::rt::spawn(async move {
|
||||||
|
while let Ok(msg) = rx.recv().await {
|
||||||
|
if let Ok(json) = serde_json::to_string(&msg) {
|
||||||
|
if session.text(json).await.is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(response)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user