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
123
/* FIXME: get this working
extern crate crypto;
extern crate tiny_http;
extern crate rustc_serialize;
use std::thread::spawn;
use std::io::Cursor;
use rustc_serialize::base64::{Config, Standard};
fn home_page(port: u16) -> tiny_http::Response<Cursor<Vec<u8>>> {
tiny_http::Response::from_string(format!("
<script type=\"text/javascript\">
var socket = new WebSocket(\"ws://localhost:{}/\", \"ping\");
function send(data) {{
socket.send(data);
}}
socket. {{
document.getElementById('result').innerHTML += event.data + '<br />';
}}
</script>
<p>This example will receive "Hello" for each byte in the packet being sent.
Tiny-http doesn't support decoding websocket frames, so we can't do anything better.</p>
<p><input type=\"text\" id=\"msg\" />
<button
<p>Received: </p>
<p id=\"result\"></p>
", port))
.with_header("Content-type: text/html".parse().unwrap())
}
/// Turns a Sec-WebSocket-Key into a Sec-WebSocket-Accept.
/// Feel free to copy-paste this function, but please use a better error handling.
fn convert_key(input: &str) -> String {
use crypto::digest::Digest;
use crypto::sha1::Sha1;
let input = input.to_string().into_bytes();
let bytes = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".to_string().into_bytes();
let input = input.append();
let mut sha1 = Sha1::new();
sha1.input(&input);
let mut out = [0u8; 20];
sha1.result(out);
out.as_slice().to_base64(Config{char_set: Standard, pad: true, line_length: None})
}
fn main() {
let server = tiny_http::ServerBuilder::new().with_random_port().build().unwrap();
let port = server.server_addr().port;
println!("Server started");
println!("To try this example, open a browser to http://localhost:{}/", port);
for request in server.incoming_requests() {
// we are handling this websocket connection in a new task
spawn(move || {
// checking the "Upgrade" header to check that it is a websocket
match request.headers().iter()
.find(|h| h.field.equiv(&"Upgrade"))
.filtered(|hdr| hdr.value.as_slice().eq_ignore_case(b"websocket".to_ascii()))
{
None => {
// sending the HTML page
request.respond(home_page(port));
return
},
_ => ()
};
// getting the value of Sec-WebSocket-Key
let key = match request.headers().iter()
.find(|h| h.field.equiv(&"Sec-WebSocket-Key"))
{
None => {
let response = tiny_http::Response::new_empty(tiny_http::StatusCode(400));
request.respond(response);
return
},
Some(h) => &h.value
};
// building the "101 Switching Protocols" response
let response = tiny_http::Response::new_empty(tiny_http::StatusCode(101))
.with_header("Upgrade: websocket".parse().unwrap())
.with_header("Connection: Upgrade".parse().unwrap())
.with_header("Sec-WebSocket-Protocol: ping".parse().unwrap())
.with_header(
format!("Sec-WebSocket-Accept: {}",
convert_key(key.as_str_ascii())
).parse().unwrap());
//
let mut stream = request.upgrade("websocket", response);
//
loop {
match stream.read_byte() {
Ok(_) => {
// "Hello" frame
let data = [0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f];
stream.write(&data).ok();
stream.flush().ok();
},
Err(e) => {
println!("closing connection because: {}", e);
return
}
};
}
});
}
}
*/