Creating websocket connections via 9front's webfs
With the following patch (note: work in progress, contains bugs), 9front's webfs can be used to create websocket connections. The patch is available here.
The idea
Creating a websocket connection is done just like creating a http request is, except the url must use scheme wss://
or ws://
, and the body
file must be opened read-write to allow both sending and receiving.
The very first message to be read from body
is always "websocket ready", meaning the connection has been established. After that the actual communication begins.
Webfs itself takes care of the control messages, so only the data messages gets delivered to the user, in a textual format that is easy to parse. Each message read and writen to body
consists of a 22 byte header in the following format
b nnnnnnnnnnnnnnnnnnnn
or
t nnnnnnnnnnnnnnnnnnnn
for binary and text messages respectively. The 20 last bytes are a 0-padded ascii number in base 10, telling the size of the message body, which follows directly after the header.
Example program
To demonstrate, the following rc script connects to wss://echo.websocket.org
which is a service that echos everything back to the user.
#!/bin/rc
rfork en
webfs
fn sendtextmsg{
awk 'BEGIN{printf "t %0.20d%s", length(ARGV[1]), ARGV[1]}' $1 >[1=0]
}
fn readheader{
header=`{read -c 22}
length=`{echo $header(2) p | dc}
echo $header(1) $length
}
fn handlemsg{
echo Handling message:
echo ' TYPE :' $1
echo ' LENGTH:' $2
echo ' BODY :' $3
}
<>/mnt/web/clone {
d=/mnt/web/^`{sed 1q}
echo url wss://echo.websocket.org >[1=0]
<>$d/body {
read -n 1 # Read the ready message
sendtextmsg 'First message sent'
while(header=`{readheader}){
echo Header: $header
body=`''{read -c $header(2)}
handlemsg $header(1) $header(2) $body
sleep 2
sendtextmsg 'Echo test'
}
}
}
Bugs
Yes. The code doesn't really handle errors or connection shutdowns yet. Also, I need to add proper cleanup code around in different places.