compiler/tests/fixtures/runtime/events-tcp-exchange/main.ldn
skip to the library navigation
1-- D485: two fibres exchanging over a loopback TCP connection
2-- under hosted/events. The server accepts and the client connects; each
3-- message is answered before the next is sent, so their lines can only
4-- interleave as the provider lets one fibre run while the other waits in
5-- `receive`. The home stack joins the group, waiting in the loop.
6import core/failure
7import core/fibre
8import core/io
9import core/net
10import hosted/events
11
12mut trace: [64]u8 = zeroed
13mut marks: usize = 0
14
15-- Note one step: a letter and a digit, after a space from the last.
16mark: (letter: u8, digit: usize) -> none =
17 if marks > 0 then
18 trace[marks] = u8(' ')
19 inc marks
20 end if
21 trace[marks] = letter
22 trace[marks + 1] = u8('0') + u8(digit)
23 marks += 2
24end mark
25
26serving: type = struct
27 host: events.host
28 listener: io.file
29end serving
30
31-- Accept one connection and answer three messages, each with its
32-- number doubled.
33serve: (inout state: serving) -> none ! failure.reason =
34 connection: io.file = try net.accept(state.host, state.listener)
35 mut buffer: [1]u8 = zeroed
36 for round in usize(0)..<3 do
37 got: usize = try net.receive(state.host, connection, buffer)
38 fail io.io_failed when got <> 1
39 mark(u8('s'), usize(buffer[0]))
40 buffer[0] = buffer[0] * 2
41 try net.send(state.host, connection, buffer)
42 _ = round
43 end for
44 try net.close_socket(state.host, connection)
45end serve
46
47asking: type = struct
48 host: events.host
49 peer: net.address
50end asking
51
52-- Connect and send three messages, waiting for each answer.
53ask: (inout state: asking) -> none ! failure.reason =
54 connection: io.file = try net.connect(state.host, state.peer)
55 mut buffer: [1]u8 = zeroed
56 for round in usize(1)..<4 do
57 buffer[0] = u8(round)
58 mark(u8('c'), round)
59 try net.send(state.host, connection, buffer)
60 got: usize = try net.receive(state.host, connection, buffer)
61 fail io.io_failed when got <> 1
62 mark(u8('a'), usize(buffer[0]))
63 end for
64 got: usize = try net.receive(state.host, connection, buffer)
65 fail io.io_failed when got <> 0
66 try net.close_socket(state.host, connection)
67end ask
68
69mut backing: [2 * 32768]u8 = zeroed
70
71run: (host: events.host) -> none ! failure.reason =
72 listener: io.file = try net.listen(host, net.loopback(net.ipv4, 0))
73 peer: net.address = try net.local_address(host, listener)
74 mut tasks := try fibre.turns_over(any(addr host), backing, 2)
75 defer fibre.join(tasks) else none
76 server: serving = (host: host, listener: listener)
77 try fibre.admit(tasks, serve, server)
78 client: asking = (host: host, peer: peer)
79 try fibre.admit(tasks, ask, client)
80 try fibre.join(tasks)
81 try net.close_socket(host, listener)
82 try io.write(host, io.out(host), trace[0..<marks])
83 try io.write(host, io.out(host), "\n")
84end run
85
86public main: () -> (code: i32) =
87 code = 1
88 mut state: events.space = zeroed
89 mut entries: [3]usize = zeroed
90 host := events.new(state, entries) else (problem)
91 _ = problem
92 return
93 end
94 code = 2
95 run(host) else (problem)
96 _ = problem
97 return
98 end
99 code = 0
100end main