1extern crate rand;
4
5pub mod names {
7 pub const PROTOCOL: &str = "Sec-WebSocket-Protocol";
8 pub const ACCEPT: &str = "Sec-WebSocket-Accept";
9 pub const EXTENSIONS: &str = "Sec-WebSocket-Extensions";
10 pub const KEY: &str = "Sec-WebSocket-Key";
11}
12
13extern crate base64;
14extern crate sha1;
15use sha1::{Digest, Sha1};
16
17use crate::result::{WebSocketError, WebSocketResult};
18use std::fmt::{self, Debug};
19
20use std::str::FromStr;
21
22#[derive(PartialEq, Clone, Copy, Default)]
24pub struct WebSocketKey(pub [u8; 16]);
25
26impl Debug for WebSocketKey {
27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28 write!(f, "WebSocketKey({})", self.serialize())
29 }
30}
31
32impl FromStr for WebSocketKey {
33 type Err = WebSocketError;
34
35 fn from_str(key: &str) -> WebSocketResult<WebSocketKey> {
36 match base64::decode(key) {
37 Ok(vec) => {
38 if vec.len() != 16 {
39 return Err(WebSocketError::ProtocolError(
40 "Sec-WebSocket-Key must be 16 bytes",
41 ));
42 }
43 let mut array = [0u8; 16];
44 array[..16].clone_from_slice(&vec[..16]);
45 Ok(WebSocketKey(array))
46 }
47 Err(_) => Err(WebSocketError::ProtocolError(
48 "Invalid Sec-WebSocket-Accept",
49 )),
50 }
51 }
52}
53
54impl WebSocketKey {
55 pub fn new() -> WebSocketKey {
57 let key = rand::random();
58 WebSocketKey(key)
59 }
60 pub fn serialize(&self) -> String {
62 let WebSocketKey(key) = *self;
63 base64::encode(&key)
64 }
65}
66
67static MAGIC_GUID: &str = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
68
69#[derive(PartialEq, Clone, Copy)]
71pub struct WebSocketAccept([u8; 20]);
72
73impl Debug for WebSocketAccept {
74 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75 write!(f, "WebSocketAccept({})", self.serialize())
76 }
77}
78
79impl FromStr for WebSocketAccept {
80 type Err = WebSocketError;
81
82 fn from_str(accept: &str) -> WebSocketResult<WebSocketAccept> {
83 match base64::decode(accept) {
84 Ok(vec) => {
85 if vec.len() != 20 {
86 return Err(WebSocketError::ProtocolError(
87 "Sec-WebSocket-Accept must be 20 bytes",
88 ));
89 }
90 let mut array = [0u8; 20];
91 array[..20].clone_from_slice(&vec[..20]);
92 Ok(WebSocketAccept(array))
93 }
94 Err(_) => Err(WebSocketError::ProtocolError(
95 "Invalid Sec-WebSocket-Accept ",
96 )),
97 }
98 }
99}
100
101impl WebSocketAccept {
102 pub fn new(key: &WebSocketKey) -> WebSocketAccept {
104 let serialized = key.serialize();
105 let mut concat_key = String::with_capacity(serialized.len() + 36);
106 concat_key.push_str(&serialized[..]);
107 concat_key.push_str(MAGIC_GUID);
108 let hash = Sha1::digest(concat_key.as_bytes());
109 WebSocketAccept(hash.into())
110 }
111 pub fn serialize(&self) -> String {
113 let WebSocketAccept(accept) = *self;
114 base64::encode(&accept)
115 }
116}