-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuring.ts
More file actions
143 lines (112 loc) · 3.21 KB
/
Copy pathuring.ts
File metadata and controls
143 lines (112 loc) · 3.21 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// io_uring tcp server
if (!io_uring_check_version(2, 5)) {
throw new Error("io_uring version 2.5 or later is required");
}
const SIZE_OF_io_uring = size_of_io_uring();
const ring = new Uint8Array(SIZE_OF_io_uring);
const QUEUE_DEPTH = 128;
/* Initialize the io_uring */
io_uring_queue_init(QUEUE_DEPTH, ring, 0);
function sockaddr_in(ip, port) {
const AF_INET = 2;
const buf = new ArrayBuffer(16);
const dv = new DataView(buf);
dv.setInt16(0, AF_INET, true);
dv.setUint16(2, port & 0xffff);
dv.setUint32(4, inet_aton(ip));
return new Uint8Array(buf);
}
function inet_aton(ip) {
const [b0, b1, b2, b3] = ip.split(".").map((v) => (parseInt(v, 10) & 0xff));
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
}
function setup_socket() {
const PF_INET = 2;
const SOCK_STREAM = 1;
const sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
throw new Error("Failed to create socket");
}
const sv_addr = sockaddr_in("127.0.0.1", 3000);
if (bind(sock, sv_addr, sv_addr.byteLength) < 0) {
throw new Error("Failed to bind");
}
if (listen(sock, 10) < 0) {
throw new Error("Failed to listen");
}
return sock;
}
const sock = setup_socket();
const Accept = 1;
const Read = 2;
const Write = 3;
function add_accept_request(
sock,
addr,
) {
const sqe = io_uring_get_sqe(ring);
if (sqe === 0) {
throw new Error("Failed to get sqe");
}
const addrlen = new Uint8Array(8);
new DataView(addrlen.buffer).setUint32(0, addr.byteLength, true);
io_uring_prep_accept(sqe, sock, addr, addrlen, 0);
io_uring_sqe_set_data(sqe, Accept);
io_uring_submit(ring);
}
function add_read_request(sock) {
const sqe = io_uring_get_sqe(ring);
if (sqe === 0) {
throw new Error("Failed to get sqe");
}
const buf = new ArrayBuffer(1024);
io_uring_prep_readv(sqe, sock, buf, 1, 0);
io_uring_sqe_set_data(sqe, Read);
io_uring_submit(ring);
}
const HTTP_RESPONSE = `HTTP/1.1 200 OK
Content-Length: 12
Content-Type: text/plain
Hello, World`;
const HTTP_RESPONSE_BUF = HTTP_RESPONSE.split("").map((c) => c.charCodeAt(0));
function add_write_request(sock) {
const sqe = io_uring_get_sqe(ring);
if (sqe === 0) {
throw new Error("Failed to get sqe");
}
const iovec = new Uint8Array(16);
const buf = new Uint8Array(HTTP_RESPONSE_BUF);
const buf_ptr = ptr(buf);
const view = new DataView(iovec.buffer);
view.setBigUint64(0, BigInt(buf_ptr), true);
view.setBigUint64(8, BigInt(buf.byteLength), true);
io_uring_prep_writev(sqe, sock, iovec, 1, 0);
io_uring_sqe_set_data(sqe, Write);
io_uring_submit(ring);
}
const cqedata = new Uint8Array(4 * 2);
const cqedata_v = new DataView(cqedata.buffer);
const client_sockaddr = new ArrayBuffer(16);
add_accept_request(sock, client_sockaddr);
let fd = -1;
for (;;) {
io_uring_wait_cqe2(ring, cqedata);
const type = cqedata_v.getUint32(0, true);
switch (type) {
case Accept:
add_accept_request(sock, client_sockaddr);
const req = cqedata_v.getUint32(4, true);
fd = req;
add_read_request(req);
break;
case Read:
add_write_request(fd);
break;
case Write:
close(fd);
break;
default:
print("Unknown type: " + type);
throw new Error("Unknown user data");
}
}