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
|
// from https://github.com/gotham-rs/gotham/blob/master/examples/websocket/src/main.rs
use futures::Future as _;
const PROTO_WEBSOCKET: &str = "websocket";
pub fn requested(headers: &hyper::HeaderMap) -> bool {
headers.get(hyper::header::UPGRADE)
== Some(&hyper::header::HeaderValue::from_static(PROTO_WEBSOCKET))
}
pub fn accept(
headers: &hyper::HeaderMap,
body: hyper::Body,
) -> Result<
(
hyper::Response<hyper::Body>,
impl futures::Future<
Item = tokio_tungstenite::WebSocketStream<
hyper::upgrade::Upgraded,
>,
Error = hyper::Error,
>,
),
(),
> {
let res = response(headers)?;
let ws = body.on_upgrade().map(|upgraded| {
tokio_tungstenite::WebSocketStream::from_raw_socket(
upgraded,
tokio_tungstenite::tungstenite::protocol::Role::Server,
None,
)
});
Ok((res, ws))
}
fn response(
headers: &hyper::HeaderMap,
) -> Result<hyper::Response<hyper::Body>, ()> {
let key = headers.get(hyper::header::SEC_WEBSOCKET_KEY).ok_or(())?;
Ok(hyper::Response::builder()
.header(hyper::header::UPGRADE, PROTO_WEBSOCKET)
.header(hyper::header::CONNECTION, "upgrade")
.header(
hyper::header::SEC_WEBSOCKET_ACCEPT,
accept_key(key.as_bytes()),
)
.status(hyper::StatusCode::SWITCHING_PROTOCOLS)
.body(hyper::Body::empty())
.unwrap())
}
fn accept_key(key: &[u8]) -> String {
const WS_GUID: &[u8] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
let mut sha1 = sha1::Sha1::default();
sha1.update(key);
sha1.update(WS_GUID);
base64::encode(&sha1.digest().bytes())
}
|