33// frame echo loop: read masked client frames, echo them unmasked.
44
55from std.socket import tcp_write, tcp_read
6+ from std.internal.socket import socket
67from response import writeBytes
78
8- // Low 32 bits mask — SHA-1 is 32-bit arithmetic; typev `uint` is 64-bit.
9- let local const M32: uint = 4294967295u
10-
11- let local const B64: byte[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".bytes()
12- let local const WS_GUID: byte[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".bytes()
139let local const WS_101: byte[] = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ".bytes()
1410let local const WS_CRLF2: byte[] = "\r\n\r\n".bytes()
1511let local const WS_BAD: byte[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\nConnection: close\r\n\r\n".bytes()
@@ -36,136 +32,11 @@ local fn wsSend(fd: int, b: byte[], len: uint) -> bool {
3632 return true
3733}
3834
39- // 32-bit rotate-left.
40- local fn rotl32(x: uint, n: uint) -> uint {
41- return ((x << n) | (x >> (32u - n))) & M32
42- }
43-
44- // SHA-1 of data[0..n) — returns the 20-byte digest.
45- local fn sha1(data: byte[], n: uint) -> byte[] {
46- let padded: uint = ((n + 8u) / 64u + 1u) * 64u
47- let msg: byte[] = new byte[](padded)
48- foreach i: uint in 0u, n {
49- msg[i] = data[i]
50- }
51- msg[n] = 128 as byte
52- foreach i: uint in n + 1u, padded {
53- msg[i] = 0 as byte
54- }
55- let bits: uint = n * 8u
56- foreach i: uint in 0u, 8u {
57- msg[padded - 1u - i] = ((bits >> (8u * i)) & 255u) as byte
58- }
59-
60- let h0: uint = 1732584193u
61- let h1: uint = 4023233417u
62- let h2: uint = 2562383102u
63- let h3: uint = 271733878u
64- let h4: uint = 3285377520u
65- let w: uint[] = new uint[](80)
66- let blocks: uint = padded / 64u
67-
68- foreach b: uint in 0u, blocks {
69- let base: uint = b * 64u
70- foreach t: uint in 0u, 16u {
71- let o: uint = base + t * 4u
72- w[t] = (((msg[o] as uint) << 24u) | ((msg[o + 1u] as uint) << 16u)
73- | ((msg[o + 2u] as uint) << 8u) | (msg[o + 3u] as uint)) & M32
74- }
75- foreach t: uint in 16u, 80u {
76- w[t] = rotl32((w[t - 3u] ^ w[t - 8u] ^ w[t - 14u] ^ w[t - 16u]) & M32, 1u)
77- }
78- let a: uint = h0
79- let bb: uint = h1
80- let c: uint = h2
81- let d: uint = h3
82- let e: uint = h4
83- foreach t: uint in 0u, 80u {
84- let f: uint = 0u
85- let k: uint = 0u
86- if t < 20u {
87- f = (bb & c) | ((M32 ^ bb) & d)
88- k = 1518500249u
89- } else if t < 40u {
90- f = bb ^ c ^ d
91- k = 1859775393u
92- } else if t < 60u {
93- f = (bb & c) | (bb & d) | (c & d)
94- k = 2400959708u
95- } else {
96- f = bb ^ c ^ d
97- k = 3395469782u
98- }
99- let tt: uint = (rotl32(a, 5u) + (f & M32) + e + k + w[t]) & M32
100- e = d
101- d = c
102- c = rotl32(bb, 30u)
103- bb = a
104- a = tt
105- }
106- h0 = (h0 + a) & M32
107- h1 = (h1 + bb) & M32
108- h2 = (h2 + c) & M32
109- h3 = (h3 + d) & M32
110- h4 = (h4 + e) & M32
111- }
112-
113- let digest: byte[] = new byte[](20)
114- let hs: uint[] = [h0, h1, h2, h3, h4]
115- foreach i: uint in 0u, 5u {
116- let v: uint = hs[i]
117- digest[i * 4u] = ((v >> 24u) & 255u) as byte
118- digest[i * 4u + 1u] = ((v >> 16u) & 255u) as byte
119- digest[i * 4u + 2u] = ((v >> 8u) & 255u) as byte
120- digest[i * 4u + 3u] = (v & 255u) as byte
121- }
122- return digest
123- }
124-
125- // Base64-encode data[0..n).
126- local fn b64encode(data: byte[], n: uint) -> byte[] {
127- let outLen: uint = ((n + 2u) / 3u) * 4u
128- let out: byte[] = new byte[](outLen)
129- let i: uint = 0u
130- let o: uint = 0u
131- while i + 3u <= n {
132- let x: uint = ((data[i] as uint) << 16u) | ((data[i + 1u] as uint) << 8u) | (data[i + 2u] as uint)
133- out[o] = B64[(x >> 18u) & 63u]
134- out[o + 1u] = B64[(x >> 12u) & 63u]
135- out[o + 2u] = B64[(x >> 6u) & 63u]
136- out[o + 3u] = B64[x & 63u]
137- i = i + 3u
138- o = o + 4u
139- }
140- let rem: uint = n - i
141- if rem == 1u {
142- let x: uint = (data[i] as uint) << 16u
143- out[o] = B64[(x >> 18u) & 63u]
144- out[o + 1u] = B64[(x >> 12u) & 63u]
145- out[o + 2u] = 61 as byte
146- out[o + 3u] = 61 as byte
147- } else if rem == 2u {
148- let x: uint = ((data[i] as uint) << 16u) | ((data[i + 1u] as uint) << 8u)
149- out[o] = B64[(x >> 18u) & 63u]
150- out[o + 1u] = B64[(x >> 12u) & 63u]
151- out[o + 2u] = B64[(x >> 6u) & 63u]
152- out[o + 3u] = 61 as byte
153- }
154- return out
155- }
156-
157- // Sec-WebSocket-Accept = base64(SHA1(key + GUID)).
35+ // Sec-WebSocket-Accept = base64(SHA1(key + GUID)) — computed natively.
15836local fn wsAccept(key: byte[], keyStart: uint, keyEnd: uint) -> byte[] {
159- let keyLen: uint = keyEnd - keyStart
160- let concat: byte[] = new byte[](keyLen + WS_GUID.length)
161- foreach i: uint in 0u, keyLen {
162- concat[i] = key[keyStart + i]
163- }
164- foreach i: uint in 0u, WS_GUID.length {
165- concat[keyLen + i] = WS_GUID[i]
166- }
167- let digest: byte[] = sha1(concat, concat.length)
168- return b64encode(digest, 20u)
37+ let out: byte[] = new byte[](28)
38+ socket.socket_ws_accept(key, keyStart, keyEnd - keyStart, out)
39+ return out
16940}
17041
17142// Send the 101 upgrade response; `scratch` is the caller's output buffer.
0 commit comments