Wasm Builders 🧱

Kieran Jayes
Kieran Jayes

Posted on

Building a C++ chat client using WebAssembly and Enarx

Hi, I'm Kieran, currently in my final year of Computer Science at University of Galway. I had the chance to work with Enarx for one of my modules as part of the Semester of Code initiative.

Here I will describe the process of figuring out how to build a C++ chat client for a Rust-based chat server (https://github.com/enarx/codex/tree/main/demos/chat-server) from scratch.

Initially, I tried to build a C program based around the connect() function in socket.h, but when trying to compile using the wasi-sdk, I realised that the connect() function was not yet supported. Looking through the supported functions, I noticed the most useful supported functions in socket.h were the accept() and read() functions, so I decided to build the main program loop around these functions.

For reference, I looked to see if there was an existing server-based program written using WebAssembly and Enarx in C/C++. Fortunately, Richard Zak, who helped me in my time working with Enarx, had written a C-based webserver which formed the foundation of the C++ chat client. The code is linked here: https://github.com/rjzak/web_wordpuzzle.

The linked code has webserver functionality where the user can connect to the chat client via web browser, but I will ignore it for this article. The C++ chat client with webserver can be found here: https://github.com/kieranjazy/codex/tree/main/demos/chat-client/c%2B%2B.

To connect to the chat-server, we need to add a new connection in the Enarx.toml file. For this project, I used port 50000 to connect to the server, and this is how the code looked:
[[files]]
name = "server"
kind = "connect"
port = 50000
prot = "tcp"
host = "127.0.0.1"

To obtain this file descriptor in the C++ program, you can use std::getenv("FD_COUNT") to get the number of file descriptors available through Enarx, then the file descriptor of the connection is based on the position of the [[files]] section within the Enarx.toml file.

We use a while loop with the condition being std::cin >> input. This allows the loop to run until an End of File marker is input via the std::cin. In the body, the first thing done is to add a '\n' to the input. This is because the chat-server will not recognise any message without a newline at the end. Then, the function that writes the input to the server is as such: write(serverFd, input.c_str(), strlen(input.c_str()))

The server dumps a log of all messages when the while loop of the client has finished, and that is handled through the use of the read() function. In this program, I made an empty char buffer through char buffer[4096] = {0}; and used the read() function as such: read(serverFd, &buffer, 4096). This works for a short chat log which we expect. I then call close on the serverFd to be sure the connection is closed, although Enarx most likely handles this aspect.

You can compile this program via the WASI Clang++ compiler available at https://github.com/WebAssembly/wasi-sdk/releases. Specific compiling instructions are available at https://enarx.dev/docs/WebAssembly/C++. Make sure to pass the Enarx.toml file specifically via the --wasmcfgfile if it is not initially detected.

Oldest comments (1)

Collapse
 
nick profile image
Nick Vidal

Kieran, thank you so much for participating in the Enarx project as part of the Semester of Code initiative! We appreciate your help implementing this demo and we hope you had fun!