// Either Vala's GirParser needs to learn to handle out caller-allocates
// arrays properly, or libdex should ship a fixup in a metadata file.
namespace DexVapiFixes {
[CCode (cname = "dex_input_stream_read", cheader_filename = "libdex.h")]
static extern Dex.Future input_stream_read (GLib.InputStream self, uint8[:size_t] buffer, int io_priority);
}
async int main () {
var port = 8080;
Dex.init ();
var thread_pool = new Dex.ThreadPoolScheduler ();
var socket_listener = new GLib.SocketListener ();
try {
socket_listener.add_inet_port (port, null);
} catch (Error err) {
error ("Failed to listen on port %u: %s", port, err.message);
}
print ("Listening on 0.0.0.0:%u\n", port);
// Spawn a fiber on current thread for socket loop.
var future = Dex.Scheduler.get_default ().spawn (0, () => {
while (true) {
// Accept an incoming connection.
GLib.SocketConnection connection;
try {
connection = (GLib.SocketConnection) Dex.socket_listener_accept (socket_listener).await_object ();
} catch (Error err) {
return new Dex.Future.for_error ((owned) err);
}
// Spawn a fiber to handle the connection on the thread pool.
thread_pool.spawn (0, () => {
unowned var input = connection.get_input_stream ();
unowned var output = connection.get_output_stream ();
while (true) {
try {
uint8 buffer[1024];
var n_read = DexVapiFixes.input_stream_read (input, buffer, GLib.Priority.DEFAULT).await_int64 ();
int64 n_written = 0;
for (var to_write = n_read; to_write > 0; to_write -= n_written) {
n_written = Dex.output_stream_write (output, buffer[n_read - to_write : n_read], GLib.Priority.DEFAULT).await_int64 ();
if (n_written == 0) {
// EOF.
break;
}
}
} catch (Error err) {
return new Dex.Future.for_error ((owned) err);
}
}
});
}
});
// When it completes, resume the main coroutine.
future = new Dex.Future.finally ((owned) future, _res => {
main.callback ();
return null;
});
yield;
return 0;
}