I Accidentally Wrote A Gemini Server

A couple of weeks ago I moved my Gemini game SpellBinding to my own VPS server.

For context, my games are absolutely minimal CGIs, under 40Kb written in C binaries. I wrote them that way because I am a minimalist, and my plan was to run them on a tilde I had an account on; as a good neighbor I wanted to use the absolute smallest amount of resources.

Unfortunately, not all tilde users feel the same way (or realize that running their Python script is eating a sizeable chunk of the CPU). And tildes are run by people doing other things, who often don't notice (or care) that the Gemini server is down or that system utilization is way out of control. And sometimes they just decide to shut it down.

After a few years I got tired of frantically moving my game around, and got a VPS server from AWS. It took me about 20 minutes to set it up -- all but the Gemini server.

There are a bunch of them on the Awsome Gemini list, but my hope was to find one written in C. And it has to support CGI. It took me a week to go through a lot of them (I even gave up on C and tried ones in other languages) but none worked correctly.

Eventually, @ingrix contacted me on BBS and suggested his server, polluxd. After a few rounds of debugging, the games are up here:

gemini://spell.ddns.net/games/index.gmi

But in the meantime

This took a bit too long for my liking, and a couple of days in with my VPS idling, I started sketching out an idea for my own server.

CGI is an atrocious solution -- spinning up a process to run a tiny program, then killing it, two times per user click. And inside the CGI, I have to load the game, then look up the user in the database, then load and update global game stats. That's been annoying me since the beginning.

There is fast CGI which doesn't do that, but I still have to rely on a server I don't understand, deal with synchronization issues, and well, I would still have to find one that works well.

Again, my needs are really trivial. I can keep the game state and the user database in memory, so there are no disk accesses. I don't need to and really don't want to run in multiple processes and deal with synchronization issues and interprocess communication. So I need a minimal single-process server that can deal with slow connections gracefully.

Fornax, the server

It took me a day to write it, and a few more to clean up and debug it to the point where it works serving files. If you are reading it, it works.

As it stands today, it is a 28Kb binary, single-process, non-blocking server capable of 64 simultaneous in-flight connections while queuing up maybe hundreds more -- sufficient for my needs, considering I don't think I've ever needed more than 2.

It's memory footprint is around 8MB on my system, and I do not allocate any memory (although OpenSSL does).

I am going to bang on it for a bit, then I will post the source on tildegit.

Thank you for reading this, which helps me debug the server.

gemini://bbs.geminispace.org/s/Fornax

index