Skip to content

Commit e60e9f9

Browse files
author
WayneTsui
committed
first commit
1 parent 50afe5d commit e60e9f9

File tree

4 files changed

+224
-0
lines changed

4 files changed

+224
-0
lines changed

broadcast-server.reb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
REBOL [
2+
title: "A WebSocket Broadcast Server"
3+
date: 22-Sep-2013
4+
file: %broadcast-server.reb
5+
author: "Wayne Tsui"
6+
version: 0.2.1
7+
needs: [ websocket-server-util 0.2.1 ]
8+
]
9+
10+
print "A WebSocket Broadcast Server in Rebol 3"
11+
12+
server: open tcp://:8080
13+
ports: copy []
14+
server/awake: func [ event /local port ] [
15+
if event/type = 'accept [
16+
port: first event/port
17+
append ports port
18+
;print length? ports
19+
port/awake: func [ event /local data request-data ] [
20+
;probe port/type
21+
switch event/type [
22+
read [
23+
data: event/port/data
24+
;print ["Client said:" data ]
25+
either find to-string data "upgrade: websocket" [
26+
handshake data event/port
27+
][
28+
request-data: get-request-data data
29+
;print to-string request-data
30+
foreach port ports [
31+
write port to-binary make-response-data request-data
32+
]
33+
]
34+
]
35+
wrote [
36+
read event/port
37+
]
38+
close [
39+
close event/port
40+
remove find ports event/port
41+
return true
42+
]
43+
]
44+
false
45+
]
46+
read port
47+
]
48+
false
49+
]
50+
51+
wait [ server 1000 ]
52+
close server

echo-server.reb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
REBOL [
2+
title: "A WebSocket Echo Server"
3+
date: 22-Sep-2013
4+
file: %echo-server.reb
5+
author: "Wayne Tsui"
6+
version: 0.2.1
7+
needs: [ websocket-server-util 0.2.1 ]
8+
]
9+
10+
print "A WebSocket Echo Server in Rebol 3"
11+
12+
server: open tcp://:8080
13+
14+
server/awake: func [ event /local port ] [
15+
if event/type = 'accept [
16+
port: first event/port
17+
port/awake: func [ event /local data request-data ] [
18+
;probe port/type
19+
switch event/type [
20+
read [
21+
data: event/port/data
22+
;print ["Client said:" data ]
23+
either find to-string data "upgrade: websocket" [
24+
handshake data event/port
25+
][
26+
request-data: get-request-data data
27+
;print to-string request-data
28+
write event/port to-binary make-response-data request-data
29+
]
30+
]
31+
wrote [
32+
read event/port
33+
]
34+
close [
35+
close event/port
36+
return true
37+
]
38+
]
39+
false
40+
]
41+
read port
42+
]
43+
false
44+
]
45+
46+
wait [ server 1000 ]
47+
close server

websocket-server-util.reb

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
REBOL [
2+
title: "websocket-server-util"
3+
name: "websocket-server-util"
4+
type: 'module
5+
version: 0.2.1
6+
date: 22-Sep-2013
7+
file: %websocket-server-util.reb
8+
author: "Wayne Tsui"
9+
exports: [ compute handshake get-request-data make-response-data ]
10+
11+
]
12+
13+
compute: func [ key [ string! binary! ] /local uuid ] [
14+
uuid: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
15+
enbase checksum/method to-binary join to-string key uuid 'sha1
16+
]
17+
18+
handshake: func [ data [ binary! string! ] port [ port! ] /local key ][
19+
parse data [ thru "Sec-WebSocket-Key: " copy key to "^M^/" ]
20+
write port to-binary rejoin [
21+
{HTTP/1.1 101 Switching Protocols^M^/Upgrade: websocket^M^/Connection: Upgrade^M^/Sec-WebSocket-Accept: } compute key "^M^/^M^/"]
22+
]
23+
24+
get-request-data: func [ raw-data /local len index masks payload request-data ][
25+
len: ( pick raw-data 2 ) & 127
26+
;?? len
27+
request-data: copy #{}
28+
index: 0
29+
case [
30+
len = 126 [
31+
masks: copy/part at raw-data 5 4
32+
payload: copy at raw-data 9
33+
]
34+
len = 127 [
35+
masks: copy/part at raw-data 11 4
36+
payload: copy at raw-data 15
37+
]
38+
true [
39+
masks: copy/part at raw-data 3 4
40+
payload: copy at raw-data 7
41+
]
42+
]
43+
44+
foreach byte payload [
45+
append request-data byte xor (pick masks ((mod index 4) + 1))
46+
++ index
47+
]
48+
request-data
49+
]
50+
51+
make-response-data: func [ data-to-send [ binary! ] /local len response-data ] [
52+
len: length? data-to-send
53+
;print len
54+
case [
55+
len <= 126 [ response-data: rejoin [ copy #{81} len data-to-send ]]
56+
all [ len > 125 len <= 65535 ][
57+
response-data: rejoin [ copy #{81} 126
58+
(shift len -8) & 255
59+
len & 255
60+
data-to-send
61+
]
62+
]
63+
len > 65535 [
64+
response-data: rejoin [ copy #{81} 127
65+
(shift len -56) & 255
66+
(shift len -48) & 255
67+
(shift len -40) & 255
68+
(shift len -32) & 255
69+
(shift len -24) & 255
70+
(shift len -16) & 255
71+
(shift len -8) & 255
72+
len & 255
73+
data-to-send
74+
]
75+
]
76+
]
77+
response-data
78+
]

websocket.html

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<!-- come from http://www.prohtml5.com/ -->
5+
<title>WebSocket Test Page</title>
6+
<script>
7+
8+
var log = function(s) {
9+
if (document.readyState !== "complete") {
10+
log.buffer.push(s);
11+
} else {
12+
document.getElementById("output").innerHTML += (s + "\n")
13+
}
14+
}
15+
log.buffer = [];
16+
17+
url = "ws://localhost:8080/echo";
18+
w = new WebSocket(url);
19+
w.onopen = function() {
20+
log("open");
21+
w.send("thank you for accepting this Web Socket request");
22+
}
23+
w.onmessage = function(e) {
24+
log(e.data);
25+
}
26+
w.onclose = function(e) {
27+
log("closed");
28+
}
29+
30+
window.onload = function() {
31+
log(log.buffer.join("\n"));
32+
document.getElementById("sendButton").onclick = function() {
33+
var value = document.getElementById("inputMessage").value;
34+
w.send(value);
35+
}
36+
}
37+
</script>
38+
</head>
39+
<body>
40+
<input type="text" id="inputMessage" value="Hello, Web Socket!">
41+
<button id="sendButton">Send</button>
42+
<pre id="output"></pre>
43+
</body>
44+
</html>
45+
46+
47+

0 commit comments

Comments
 (0)