-
-
Notifications
You must be signed in to change notification settings - Fork 56
/
handlers.rs
122 lines (107 loc) · 3.35 KB
/
handlers.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use std::sync::{atomic::Ordering, Arc};
use anyhow::anyhow;
use serde::{Deserialize, Serialize};
use socketioxide::extract::{Data, Extension, SocketRef, State};
use uuid::Uuid;
use crate::store::{Message, Messages, Session, Sessions};
#[derive(Debug, Deserialize)]
pub struct Auth {
#[serde(rename = "sessionID")]
session_id: Option<Uuid>,
username: Option<String>,
}
/// Request/Response Types
#[derive(Debug, Serialize, Clone)]
struct UserConnectedRes<'a> {
#[serde(rename = "userID")]
user_id: &'a Uuid,
username: &'a String,
connected: bool,
messages: Vec<Message>,
}
#[derive(Debug, Serialize, Clone)]
struct UserDisconnectedRes<'a> {
#[serde(rename = "userID")]
user_id: &'a Uuid,
username: &'a str,
}
impl<'a> UserConnectedRes<'a> {
fn new(session: &'a Session, messages: Vec<Message>) -> Self {
Self {
user_id: &session.user_id,
username: &session.username,
connected: session.connected.load(Ordering::SeqCst),
messages,
}
}
}
#[derive(Debug, Deserialize, Serialize, Clone)]
struct PrivateMessageReq {
to: Uuid,
content: String,
}
pub fn on_connection(
s: SocketRef,
Extension::<Arc<Session>>(session): Extension<Arc<Session>>,
State(sessions): State<Sessions>,
State(msgs): State<Messages>,
) {
s.emit("session", &*session).unwrap();
let other_sessions = sessions.get_all_other_sessions(session.user_id);
let users = other_sessions
.iter()
.map(|session| {
let messages = msgs.get_all_for_user(session.user_id);
UserConnectedRes::new(session, messages)
})
.collect::<Vec<_>>();
s.emit("users", &users).unwrap();
let res = UserConnectedRes::new(&session, vec![]);
s.broadcast().emit("user connected", &res).unwrap();
s.on(
"private message",
|s: SocketRef,
Data(PrivateMessageReq { to, content }),
State::<Messages>(msgs),
Extension::<Arc<Session>>(session)| {
let message = Message {
from: session.user_id,
to,
content,
};
s.within(to.to_string())
.emit("private message", &message)
.ok();
msgs.add(message);
},
);
s.on_disconnect(|s: SocketRef, Extension::<Arc<Session>>(session)| {
session.set_connected(false);
let res = UserDisconnectedRes {
user_id: &session.user_id,
username: &session.username,
};
s.broadcast().emit("user disconnected", &res).ok();
});
}
/// Handles the connection of a new user.
/// Be careful to not emit anything to the user before the authentication is done.
pub fn authenticate_middleware(
s: SocketRef,
Data(auth): Data<Auth>,
State(sessions): State<Sessions>,
) -> Result<(), anyhow::Error> {
let session = if let Some(session) = auth.session_id.and_then(|id| sessions.get(id)) {
session.set_connected(true);
s.extensions.insert(session.clone());
session
} else {
let username = auth.username.ok_or(anyhow!("invalid username"))?;
let session = Arc::new(Session::new(username));
s.extensions.insert(session.clone());
sessions.add(session.clone());
session
};
s.join(session.user_id.to_string())?;
Ok(())
}