trillium_websockets/
websocket_connection.rs1use crate::{
2 Result, Role, WebSocketConfig,
3 driver::{Driver, MessageResult, default_config},
4};
5use futures_lite::{Stream, future};
6use split_compat::DriverSlot;
7use std::{
8 fmt::Debug,
9 net::IpAddr,
10 pin::Pin,
11 sync::Arc,
12 task::{self, Poll},
13};
14use swansong::Swansong;
15use trillium::{Headers, Method, TypeSet, Upgrade};
16use trillium_http::{HttpContext, type_set::entry::Entry};
17use tungstenite::Message;
18
19mod split_compat;
20
21pub struct WebSocketConn {
29 request_headers: Headers,
30 path: String,
31 querystring: String,
32 method: Method,
33 state: TypeSet,
34 peer_ip: Option<IpAddr>,
35 context: Arc<HttpContext>,
36 driver: DriverSlot,
37}
38
39impl Debug for WebSocketConn {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 f.debug_struct("WebSocketConn")
42 .field("request_headers", &self.request_headers)
43 .field("path", &self.path)
44 .field("querystring", &self.querystring)
45 .field("method", &self.method)
46 .field("state", &self.state)
47 .field("peer_ip", &self.peer_ip)
48 .field("context", &self.context)
49 .finish_non_exhaustive()
50 }
51}
52
53impl WebSocketConn {
54 pub async fn send_string(&mut self, string: String) -> Result<()> {
56 self.send(Message::text(string)).await
57 }
58
59 pub async fn send_bytes(&mut self, bin: Vec<u8>) -> Result<()> {
61 self.send(Message::binary(bin)).await
62 }
63
64 #[cfg(feature = "json")]
65 pub async fn send_json(&mut self, json: &impl serde::Serialize) -> Result<()> {
68 self.send_string(serde_json::to_string(json)?).await
69 }
70
71 pub async fn send(&mut self, message: Message) -> Result<()> {
76 self.feed(message).await?;
77 self.flush().await
78 }
79
80 pub async fn feed(&mut self, message: Message) -> Result<()> {
87 future::poll_fn(|cx| self.driver.poll_ready_to_write(cx)).await?;
88 self.driver.write(message)?;
89 Ok(())
90 }
91
92 pub async fn flush(&mut self) -> Result<()> {
94 future::poll_fn(|cx| self.driver.poll_flush(cx))
95 .await
96 .map_err(Into::into)
97 }
98
99 #[doc(hidden)]
104 pub async fn new(
106 upgrade: impl Into<Upgrade>,
107 config: Option<WebSocketConfig>,
108 role: Role,
109 ) -> Self {
110 let mut upgrade = upgrade.into();
111 let request_headers = upgrade.take_request_headers();
112 let path = upgrade.path().to_string();
113 let querystring = upgrade.querystring().to_string();
114 let method = upgrade.method();
115 let state = upgrade.take_state();
116 let context = upgrade.context().clone();
117 let peer_ip = upgrade.peer_ip();
118 let (buffer, transport) = upgrade.into_transport();
119
120 let driver = Driver::new(
121 transport,
122 buffer,
123 role,
124 config.unwrap_or_else(default_config),
125 );
126 let driver = DriverSlot::Owned(context.swansong().interrupt(driver));
127
128 Self {
129 request_headers,
130 path,
131 querystring,
132 method,
133 state,
134 peer_ip,
135 context,
136 driver,
137 }
138 }
139
140 pub fn swansong(&self) -> Swansong {
142 self.context.swansong().clone()
143 }
144
145 pub async fn close(&mut self) -> Result<()> {
150 self.driver.close()?;
151 self.flush().await
152 }
153
154 pub fn headers(&self) -> &Headers {
156 &self.request_headers
157 }
158
159 pub fn peer_ip(&self) -> Option<IpAddr> {
161 self.peer_ip
162 }
163
164 pub fn set_peer_ip(&mut self, peer_ip: Option<IpAddr>) -> &mut Self {
166 self.peer_ip = peer_ip;
167 self
168 }
169
170 pub fn path(&self) -> &str {
173 &self.path
174 }
175
176 pub fn querystring(&self) -> &str {
179 &self.querystring
180 }
181
182 pub fn method(&self) -> Method {
184 self.method
185 }
186
187 pub fn state<T: Send + Sync + 'static>(&self) -> Option<&T> {
192 self.state.get()
193 }
194
195 pub fn state_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
197 self.state.get_mut()
198 }
199
200 pub fn insert_state<T: Send + Sync + 'static>(&mut self, state: T) -> Option<T> {
204 self.state.insert(state)
205 }
206
207 pub fn state_entry<T: Send + Sync + 'static>(&mut self) -> Entry<'_, T> {
210 self.state.entry()
211 }
212
213 pub fn take_state<T: Send + Sync + 'static>(&mut self) -> Option<T> {
218 self.state.take()
219 }
220}
221
222impl AsMut<TypeSet> for WebSocketConn {
223 fn as_mut(&mut self) -> &mut TypeSet {
224 &mut self.state
225 }
226}
227
228impl AsRef<TypeSet> for WebSocketConn {
229 fn as_ref(&self) -> &TypeSet {
230 &self.state
231 }
232}
233
234impl Stream for WebSocketConn {
235 type Item = MessageResult;
236
237 fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
238 self.driver.poll_inbound(cx)
239 }
240}