Skip to content

Commit 85a2879

Browse files
committed
typev: use native sha1 & b64
1 parent 442a3fe commit 85a2879

3 files changed

Lines changed: 9 additions & 137 deletions

File tree

frameworks/typev/bundle/benchmark-code/src/ws.tc

Lines changed: 5 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@
33
// frame echo loop: read masked client frames, echo them unmasked.
44

55
from std.socket import tcp_write, tcp_read
6+
from std.internal.socket import socket
67
from 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()
139
let local const WS_101: byte[] = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ".bytes()
1410
let local const WS_CRLF2: byte[] = "\r\n\r\n".bytes()
1511
let 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.
15836
local 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.

frameworks/typev/bundle/benchmark-code/stdlib/internal/socket.tc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,9 @@ extern socket from "stdsocket" = {
236236
fn count_http_terminators(buf: uint[], n: uint) -> uint
237237

238238
/**
239-
* SHA-1 of data[0..len) into the 20-byte `out` buffer. Native — keeps the
240-
* 80-round hash off the bytecode path. Returns 0, or -1 if out < 20.
239+
* WebSocket Sec-WebSocket-Accept = base64(SHA1(key + GUID)), written as
240+
* 28 bytes into `out`. Native — the whole handshake digest in one call.
241+
* Returns 0, or -1 if out < 28.
241242
*/
242-
fn socket_sha1(data: uint[], len: uint, out: uint[]) -> int
243+
fn socket_ws_accept(key: uint[], start: uint, len: uint, out: uint[]) -> int
243244
}
-2.13 KB
Binary file not shown.

0 commit comments

Comments
 (0)