Chat over a content-centric network

Kragen Javier Sitaker, 02021-01-15 (updated 02021-01-16) (3 minutes)

What would the simplest usable chat program look like? In 1999 IN wrote a chat server in C in a .signature:

char a[99]="  KJ",d[999][16];main(){int s=socket(2,1,0),n=0,z,l,i;*(short*)a=2;
if(!bind(s,a,16))for(;;){z=16;if((l=recvfrom(s,a,99,0,d[n],&z))>0){for(i=0;i<n;
i++){z=(memcmp(d[i],d[n],8))?z:0;while(sendto(s,a,l,0,d[i],16)<0);}z?n++:0;}}}

The client is four lines of C:

char a[99]="  KJ";main(int c,char**v){int s=socket(2,1,0);char*p,*t=strchr(*++v
,'@'),*o=a+4;*(short*)a=2;p=t;while(*p)(*p++&48)-48?*o++=atoi(p):0;connect(s,a,
16);strncpy(a,v[1],7);a[7]=':';a[8]=32;if(fork())while((c=read(0,a+9,90))>0)(
write(s,a,c+9)>0)||exit(0);else while((c=read(s,a,99))>0)write(1,a,c);}

This was for Solaris, where SOCK_DGRAM was 1, rather than 2 as in Linux <bits/socket.h>. Both the client and the server are vulnerable to buffer overflows, the server manifests a single chat channel, there are no private messages, there's no recovery from packet loss, and the server just keeps sending to disconnected clients forever. Nevertheless, under favorable circumstances, these two programs do manifest a usable text chat system over TCP/IP.

If you have a shared Unix filesystem you can use a three-line shell script for a client and need no server:

#!/bin/sh
: ${1?"usage: $0 nick [chan]"} ${chan=${2-/tmp/chat}}
sleep 1; tail -f "$chan" & pid=$?; trap "kill $pid" 0
while read t; do echo "<$1> $t"; done >> "$chan"

This inherits the Unix filesystem’s permissions, the Unix terminal’s line editing, and whatever networking your filesystem supports, and it should be reliable up to messages of PIPE_BUF size.

In 2008 I wrote an IRC client in 40 lines of shell script:

#!/bin/sh
# In the grim future of the Debian netinst disk, there is only nc.
# And dd and sh, of course.
: ${2?"Usage: $0 ircserver nickname"}
ircserver="$1"
nickname="$2"
grimdir="`dirname "$0"`"
case "$grimdir" in /*) ;; *) grimdir="../$grimdir" ;; esac

tmpdir=".tmp.grimirc.$$"
mkdir "$tmpdir"
cd "$tmpdir"
trap 'cd ..; rm -rf "$tmpdir"' 0

(echo user grimirc hostname "$ircserver" :grimirc user
echo nick "$nickname"
> grimirc-responses
tail -f grimirc-responses &
while read command
        do case "$command" in
        /join*) echo "joining">/dev/tty
                set $command; currentchan="$2"
                echo "$command" > .grimtmp
                dd bs=1 skip=1 < .grimtmp 2>/dev/null;;
        /*) echo "$command" > .grimtmp
                 dd bs=1 skip=1 < .grimtmp 2>/dev/null;;
        *) echo "PRIVMSG $currentchan :$command"
        esac
done) | "$grimdir/grimdebuglog" | nc "$ircserver" 6667 | while read response
        do echo "$response"
        case "$response" in
        "PING "*) echo "responding to ping"
                set $response
                shift
                echo "PONG $*" >> grimirc-responses
        esac
done

So, suppose we want to build a small program that implements something like Van Jacobson’s CCN, with “interest” packets that get replied to with matching “data” packets or forwarded to where you think they might find those packets. That would make it pretty easy to implement a chat system, wouldn’t it? One that really worked? How hard would that be to implement?

Topics