I made this websocket server here in Typescript and now I need to migrate it to Rust, but I’m not very good at this language
if the message is a string containing some of these values, I save the connection for later use, for the listeners part.
“main”, “main-crt”, “bot-crt”, “main-rm”, “bot-rm”
is very simple
import WebSocket from 'ws'
let app_web_client: WebSocket | null = null
let crt_web_client: WebSocket | null = null
let crt_bot_client: WebSocket | null = null
let rm_web_client: WebSocket | null = null
let rm_bot_client: WebSocket | null = null
const wss = new WebSocket.Server({ port: 2004 }, () => {
type WsBotEvents = {
botIndex: number
step: number
typeEvent: 'error' | 'success' | 'pending' | 'none'
errorMsg: string
typeFrom: 'botEvent' | 'system' | 'botCrt' | 'webCrt' | 'botRm' | 'webRm'
}
console.log('server started')
wss.on('connection', ws => {
console.log('new client')
ws.on('message', msg => {
console.log(msg)
let data: unknown = JSON.parse(msg as unknown as string)
// registers -------------------------------------
switch (data) {
case 'main':
console.log('main registered')
app_web_client = ws
break
case 'main-crt':
console.log('main-crt registered')
crt_web_client = ws
break
case 'bot-crt':
console.log('bot-crt registered')
crt_bot_client = ws
break
case 'main-rm':
console.log('main-rm registered')
rm_web_client = ws
break
case 'bot-rm':
console.log('bot-rm registered')
rm_bot_client = ws
break
default:
break
}
// listeners -------------------------------------
let data_event: WsBotEvents = data as unknown as WsBotEvents
let data_json = JSON.stringify(data_event)
switch (data_event.typeFrom) {
case 'botEvent':
app_web_client?.send(data_json)
break
case 'webCrt':
crt_bot_client?.send(data_json)
break
case 'botCrt':
crt_web_client?.send(data_json)
break
case 'webRm':
rm_bot_client?.send(data_json)
break
case 'botRm':
rm_web_client?.send(data_json)
break
default:
break
}
})
})
})
wss.on('listening', () => {
console.log('server listening on port 2004')
})
In Rust, I can do almost everything, but when saving the connection it gives me this error
error[E0507]: cannot move out of dereference of `futures_util::lock::MutexGuard<'_, Writer<std::net::TcpStream>>`
--> srcmain.rs:168:56
|
168 | ... *app_web_client = Some(*sender); // <- **error locations**
| ^^^^^^^ move occurs because value has type `Writer<std::net::TcpStream>`, which does not implement the `Copy` trait
the complete code:
async fn ws() {
let app_web_client: Arc<Mutex<Option<Writer<TcpStream>>>> =
Arc::new(Mutex::new(None::<Writer<TcpStream>>));
let crt_web_client: Arc<Mutex<Option<Writer<TcpStream>>>> =
Arc::new(Mutex::new(None::<Writer<TcpStream>>));
let crt_bot_client: Arc<Mutex<Option<Writer<TcpStream>>>> =
Arc::new(Mutex::new(None::<Writer<TcpStream>>));
let rm_web_client: Arc<Mutex<Option<Writer<TcpStream>>>> =
Arc::new(Mutex::new(None::<Writer<TcpStream>>));
let rm_bot_client: Arc<Mutex<Option<Writer<TcpStream>>>> =
Arc::new(Mutex::new(None::<Writer<TcpStream>>));
let addr: String = String::from("127.0.0.1:2004");
let server = Server::bind(&addr).unwrap();
println!("Server started, on {}", addr);
for request in server.filter_map(Result::ok) {
// Spawn a new thread for each connection.
println!("new client");
let app_web_client = Arc::clone(&app_web_client);
let crt_web_client = Arc::clone(&crt_web_client);
let crt_bot_client = Arc::clone(&crt_bot_client);
let rm_web_client = Arc::clone(&rm_web_client);
let rm_bot_client = Arc::clone(&rm_bot_client);
tokio::spawn(async move {
if !request.protocols().contains(&"rust-websocket".to_string()) {
request.reject().unwrap();
return;
}
let client = request.use_protocol("rust-websocket").accept().unwrap();
let ip = client.peer_addr().unwrap();
println!("Connection from {}", ip);
let (mut receiver, mut sender) = client.split().unwrap();
let generic_client: Arc<Mutex<Writer<TcpStream>>> = Arc::new(Mutex::new(sender));
let mut app_web_client = app_web_client.lock().await;
let mut crt_web_client = crt_web_client.lock().await;
let mut crt_bot_client = crt_bot_client.lock().await;
let mut rm_web_client = rm_web_client.lock().await;
let mut rm_bot_client = rm_bot_client.lock().await;
for message in receiver.incoming_messages() {
let sender = Arc::clone(&generic_client);
let mut sender = sender.lock().await;
let message = match message {
Ok(message) => message,
Err(err) => {
println!("Error: {}", err);
println!("Error receiving message from {}", ip);
return;
}
};
match message {
OwnedMessage::Close(_) => {
let _ = sender.send_message(&OwnedMessage::Close(None));
println!("{} disconnected", ip);
return;
}
OwnedMessage::Text(data) => {
// Registers ---------------------------------------
if let Ok(msg) = serde_json::from_str::<String>(&data) {
if msg == "main" {
println!("main registered");
*app_web_client = Some(*sender); // <- **error locations**
continue;
}
}
if let Ok(msg) = serde_json::from_str::<String>(&data) {
if msg == "main-crt" {
println!("main-crt registered");
*crt_web_client = Some(*sender); // <- **error locations**
continue;
}
}
if let Ok(msg) = serde_json::from_str::<String>(&data) {
if msg == "bot-crt" {
println!("bot-crt registered");
*crt_bot_client = Some(*sender); // <- **error locations**
continue;
}
}
if let Ok(msg) = serde_json::from_str::<String>(&data) {
if msg == "main-rm" {
println!("main-rm registered");
*rm_web_client = Some(*sender); // <- **error locations**
continue;
}
}
if let Ok(msg) = serde_json::from_str::<String>(&data) {
if msg == "bot-rm" {
println!("bot-rm registered");
*rm_bot_client = Some(*sender); // <- **error locations**
continue;
}
}
// Registers ---------------------------------------
// Listeners ---------------------------------------
let new_data_result = des(&data);
match new_data_result {
Ok(new_data) => {
if new_data.get("typeFrom") == Some(&"botCrt".to_string()) {
println!("botCrt: {}", data);
if let Some(ref mut crt_web_client) = *crt_web_client {
let data = data.clone();
crt_web_client
.send_message(&OwnedMessage::Text(data))
.expect("error sending message");
} else {
println!("crt_bot_client: does not exist",);
}
continue;
}
if new_data.get("typeFrom") == Some(&"webCrt".to_string()) {
println!("webCrt: {}", data);
if let Some(ref mut crt_bot_client) = *crt_bot_client {
let data = data.clone();
crt_bot_client
.send_message(&OwnedMessage::Text(data))
.expect("error sending message");
} else {
println!("crt_bot_client: does not exist",);
}
continue;
}
if new_data.get("typeFrom") == Some(&"botEvent".to_string()) {
println!("botRm: {}", data);
if let Some(ref mut rm_web_client) = *rm_web_client {
let data = data.clone();
rm_web_client
.send_message(&OwnedMessage::Text(data))
.expect("error sending message");
} else {
println!("app_web_client: does not exist",);
}
continue;
}
if new_data.get("typeFrom") == Some(&"botEvent".to_string()) {
println!("webRm: {}", data);
if let Some(ref mut rm_bot_client) = *rm_bot_client {
let data = data.clone();
rm_bot_client
.send_message(&OwnedMessage::Text(data))
.expect("error sending message");
} else {
println!("app_web_client: does not exist",);
}
continue;
}
if new_data.get("typeFrom") == Some(&"botEvent".to_string()) {
println!("botEvent: {}", data);
if let Some(ref mut app_web_client) = *app_web_client {
let data = data.clone();
app_web_client
.send_message(&OwnedMessage::Text(data))
.expect("error sending message");
} else {
println!("app_web_client: does not exist",);
}
continue;
}
}
Err(err) => {
eprintln!("Error parsing JSON: {}", err);
continue;
}
}
}
_ => {}
}
}
});
}
}