-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathecho.c3
More file actions
67 lines (56 loc) · 2.16 KB
/
echo.c3
File metadata and controls
67 lines (56 loc) · 2.16 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
module echo;
import std::io;
import std::net;
import coroutine;
bool quit = false;
usz server_id = 0;
fn void main() {
coroutine::init();
server_id = coroutine::id();
const String HOST = "localhost";
const uint PORT = 6969;
TcpServerSocket server = tcp::listen(HOST, PORT, 69, REUSEADDR)!!;
server.sock.set_non_blocking(true)!!;
io::printfn("[%d] Server listening to %s:%d", coroutine::id(), HOST, PORT);
while SERVER: (true) {
coroutine::sleep_read(server.sock);
if (quit) break SERVER;
TcpSocket client = tcp::accept(&server)!!;
client.sock.set_non_blocking(true)!!;
coroutine::go(fn void(void *arg) {
io::printfn("[%d] Client connected!", coroutine::id());
TcpSocket* client = (TcpSocket*)arg;
char[] buf = mem::new_array(char, 1024);
defer {
client.close()!!;
free(client);
free(buf.ptr);
}
while OUTER: (true) {
coroutine::sleep_read(client.sock);
usz n = client.read(buf)!!;
if (n == 0) break OUTER;
char[] chunk = buf[0:n];
switch (((String)chunk).trim()) {
case "quit":
io::printfn("[%d] Client requested to quit", coroutine::id(), chunk.len);
return;
case "shutdown":
io::printfn("[%d] Client requested to shutdown the server", coroutine::id());
quit = true;
coroutine::wake_up(server_id);
return;
}
io::printfn("[%d] Client sent %d bytes", coroutine::id(), chunk.len);
while (chunk.len > 0) {
coroutine::sleep_write(client.sock);
usz m = client.write(chunk)!!;
if (m == 0) break OUTER;
chunk = chunk[m..];
}
}
io::printfn("[%d] Client disconnected", coroutine::id());
}, @clone(client));
}
io::printfn("[%d] Server has been shutdown", coroutine::id());
}