Files
@ 2811715674ea
Branch filter:
Location: CSY/reowolf/src/runtime2/tests/internet.rs
2811715674ea
6.2 KiB
application/rls-services+xml
feat: tcp listener
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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | use super::*;
// silly test to make sure that the PDL will never be an issue when doing TCP
// stuff with the actual components
#[test]
fn test_stdlib_file() {
compile_and_create_component("
import std.internet as inet;
comp fake_listener_once(out<inet::TcpConnection> tx) {
channel cmd_tx -> cmd_rx;
channel data_tx -> data_rx;
new fake_socket(cmd_rx, data_tx);
sync put(tx, inet::TcpConnection{
tx: cmd_tx,
rx: data_rx,
});
}
comp fake_socket(in<inet::ClientCmd> cmds, out<u8[]> tx) {
auto to_send = {};
auto shutdown = false;
while (!shutdown) {
auto keep_going = true;
sync {
while (keep_going) {
auto cmd = get(cmds);
if (let inet::ClientCmd::Send(data) = cmd) {
to_send = data;
keep_going = false;
} else if (let inet::ClientCmd::Receive = cmd) {
put(tx, to_send);
} else if (let inet::ClientCmd::Finish = cmd) {
keep_going = false;
} else if (let inet::ClientCmd::Shutdown = cmd) {
keep_going = false;
shutdown = true;
}
}
}
}
}
comp fake_client(inet::TcpConnection conn) {
sync put(conn.tx, inet::ClientCmd::Send({1, 3, 3, 7}));
sync {
put(conn.tx, inet::ClientCmd::Receive);
auto val = get(conn.rx);
while (val[0] != 1 || val[1] != 3 || val[2] != 3 || val[3] != 7) {
print(\"this is going very wrong\");
}
put(conn.tx, inet::ClientCmd::Finish);
}
sync put(conn.tx, inet::ClientCmd::Shutdown);
}
comp constructor() {
channel conn_tx -> conn_rx;
new fake_listener_once(conn_tx);
// Same crap as before:
channel cmd_tx -> unused_cmd_rx;
channel unused_data_tx -> data_rx;
auto connection = inet::TcpConnection{ tx: cmd_tx, rx: data_rx };
sync {
connection = get(conn_rx);
}
new fake_client(connection);
}
", "constructor", no_args());
}
#[test]
fn test_tcp_listener_and_client() {
compile_and_create_component("
import std.internet::*;
func listen_port() -> u16 {
return 2392;
}
comp server(u32 num_connections, in<()> shutdown) {
// Start tcp listener
channel listen_cmd_tx -> listen_cmd_rx;
channel listen_conn_tx -> listen_conn_rx;
new tcp_listener({}, listen_port(), listen_cmd_rx, listen_conn_tx);
// Fake channels such that we can create a dummy connection variable
channel client_cmd_tx -> unused_client_cmd_rx;
channel unused_client_data_tx -> client_data_rx;
auto new_connection = TcpConnection{
tx: client_cmd_tx,
rx: client_data_rx,
};
auto connection_counter = 0;
while (connection_counter < num_connections) {
// Wait until we get a connection
print(\"server: waiting for an accepted connection\");
sync {
put(listen_cmd_tx, ListenerCmd::Accept);
new_connection = get(listen_conn_rx);
}
// We have a new connection, spawn an 'echoer' for it
print(\"server: spawning an echo'ing component\");
new echo_machine(new_connection);
connection_counter += 1;
}
// Shut down the listener
print(\"server: shutting down listener\");
sync auto v = get(shutdown);
sync put(listen_cmd_tx, ListenerCmd::Shutdown);
}
// Waits for a single TCP byte (to simplify potentially having to
// concatenate requests) and echos it
comp echo_machine(TcpConnection conn) {
auto data_to_echo = {};
// Wait for a message
sync {
print(\"echo: receiving data\");
put(conn.tx, ClientCmd::Receive);
data_to_echo = get(conn.rx);
put(conn.tx, ClientCmd::Finish);
}
// Echo the message
print(\"echo: sending back data\");
sync put(conn.tx, ClientCmd::Send(data_to_echo));
// Ask the tcp connection to shut down
print(\"echo: shutting down\");
sync put(conn.tx, ClientCmd::Shutdown);
}
comp echo_requester(u8 byte_to_send, out<()> done) {
channel cmd_tx -> cmd_rx;
channel data_tx -> data_rx;
new tcp_client({127, 0, 0, 1}, listen_port(), cmd_rx, data_tx);
// Send the message
print(\"requester: sending bytes\");
sync put(cmd_tx, ClientCmd::Send({ byte_to_send }));
// Receive the echo'd byte
auto received_byte = byte_to_send + 1;
sync {
print(\"requester: receiving echo response\");
put(cmd_tx, ClientCmd::Receive);
received_byte = get(data_rx)[0];
put(cmd_tx, ClientCmd::Finish);
}
// Silly check, as always
while (byte_to_send != received_byte) {
print(\"requester: Oh no! The echo is an otherworldly distorter\");
}
// Shut down the TCP connection
print(\"requester: shutting down TCP component\");
sync put(cmd_tx, ClientCmd::Shutdown);
sync put(done, ());
}
comp constructor() {
auto num_connections = 1;
channel shutdown_listener_tx -> shutdown_listener_rx;
new server(num_connections, shutdown_listener_rx);
auto connection_index = 0;
auto all_done = {};
while (connection_index < num_connections) {
channel done_tx -> done_rx;
new echo_requester(cast(connection_index), done_tx);
connection_index += 1;
all_done @= {done_rx};
}
auto counter = 0;
while (counter < length(all_done)) {
print(\"constructor: waiting for requester to exit\");
sync auto v = get(all_done[counter]);
counter += 1;
}
print(\"constructor: instructing listener to exit\");
sync put(shutdown_listener_tx, ());
}
", "constructor", no_args());
}
|