DNS, Math, and Sitix

Author:

Howdy, folks! It’s been a while since I last screamed into the void here.

In recent weeks, the inevitable ramping-up of classes as we move into the exam-heavy second half of the semester has been intense to say the least. I’ve actually started up another website, https://deadlyboringmath.us/, just to get my study habits in order. I’m doing some moderately interesting stuff with deadly boring math, but I’ll get into that later.

Having new websites (now there are four…) to maintain has been interesting. My vhost config is pretty solid Traefik magic and server utilization stays pretty low, but nothing ever works, and my entire infosphere has been crumbling. Oftentimes my websites will take an absurd amount of time to load, if they load at all; more often than not, they will entirely fail. This was bad.

I did a bunch of network debugging. The router (a shitty Asus with 256mb of ram) was my obvious choice, but utilization on that stays pretty low- probably because all the cpu has to do is shunt data between ports on the network card, and the card is designed to shovel multiple gbps. I confirmed my suspicions that network utilization was not the problem by sending a couple standard requests while tracking load on the router: no unexpected spikes, and utilization stayed at a nice low 0.45mbps. Pocket lint.

The next thing I tried found the problem quickly and I feel rather stupid for not having realized this before. See, for DDNS I use Asus’ asuscomm.com ddns service, which works nicely with the router. Every time my WAN lease is renegotiated, the router immediately ships the new ip addresses (it even has ipv6 support!) to the asuscomm dns servers, and I never have to worry about the fact that I’m on shitty residential.

I had a suspicion that maybe the problem was in DNS resolution. I fired off a curl swaous.asuscomm.com and it hung as expected, eventually terminating in a timeout. However, a curl <my_ipv4_address> responded snappily. This was fishy, so I checked dns resolution with dig swaous.asuscomm.com… and got a server timeout. Fuck you, Asus.

Apparently, relying on an obscure Asus service to work reliably was my problem. Who woulda thunkit? So now it’s time to fix! There’s always the option of just using FreeDNS, which is a good solution because FreeDNS is awesome. Seriously, can’t give those guys enough love. To do that, I would just have to register another freedns subdomain and set up a Cron job to automatically update my ip addresses in their servers. Changing my CNAMEs to the freedns domain (and setting up a landing page for people who unwittingly actually navigate there) would pretty much clear the whole thing up. However, this is still relying on external DDNS services. FreeDNS has been pretty reliable for me before, but principle of least power: if I can do this without adding another service, I should do this without adding another service. And lucky I didn’t, because a quick Google shows that Namecheap actually has a free DDNS service!

Much to my dismay, my router (fuck you, Asus) doesn’t support DDNS through all but a few select services, and Namecheap’s is not on that list. However, Namecheap does provide an HTTPS endpoint with a nice token interface, and getting a token is theoretically as simple as clicking the button labeled “enable DDNS”. As promised, Namecheap actually does have such a feature, and setting up automatically updating DDNS was a snap! A cron job on my control plane server regularly pings the update endpoint for www.clarkeis.com, and most of my CNAMES are now to www.clarkeis.com. I tested from my campus internet and, as expected, swaous.asuscomm.com loads really slowly and www.clarkeis.com (and assorted CNAMEs) loads quickly!

Now that my load times are deshittified, I’ve spent some effort actually using that beautiful latency reduction. And so we have https://deadlyboringmath.us! It’s literally just where I’m throwing math notes, and it’s been helpful to exactly one person so far (me), but hopefully I can increase that number.

To build deadlyboringmath, I dredged up Sitix, a static site generator I built in early 2024. Sitix has a simple pattern of declarative structures with a few pieces of pseudo-imperative magic that allow things like automatic index generation and such. Sitix is pretty cool and is, in my absolutely biased opinion, the best piece of software around for static site generation (although admittedly this is probably just me, and not an opinion that any normal person would hold).

Sitix is convenient for blog-like tasks such as deadlyboringmath, but also has a number of annoying bugs, especially the markdown renderer. For instance: in order to make my ASCIIMath annotations work, I have to write everything in pure HTML, because the markdown renderer will misunderstand everything and the escape literal support is… less than ideal. I want to move this blog over to Sitix eventually, but without reliable markdown support I won’t be able to keep my sanity writing these posts. Also, fancier scripting is done either through a defunct and broken Lua extension or a really garbage esolang I called “Evals”. That means now I have a task list!

As for the parser bugs- at the moment, the core of Sitix is a finite state machine that handles things character-by-character. This was easy to build initially, but as Sitix gained features, it became a horrible behemoth. That means that, first, I need to build… a PEG parser! Chumsky’s parser combinator magic is really, really nice, but Sitix is written in C++ and I’m unwilling to move over. So it’s time to build a parser combinator library!

Sitix’ memory model means wind/rewind for parsers is essentially free- everything is memory mapped, so I get to pretend that the files are fully loaded into memory at any given time, without that actually being true. This means that the logic for a single depth-first parse check is simple:

  • Create a view into the file at hand and pass it into the first parser to check.
  • IF it returns a successfully parsed AST, return that AST.
  • IF it returns a parse failure, check the next one.
  • Continue doing this until there are no more parsers to check.
  • If we haven’t returned a success, return a failure.

Creating those views is incredibly cheap, meaning this should be quite fast. Now for the interface! I haven’t actually decided on a final design, but I expect it’ll use polymorphism and be more OOP than Chumsky.

On the side of fixing the markdown parser and scripting support, I think a much more major change is due. Instead of keeping markdown, minification, and scripting built in, I want to move towards a modular approach where Sitix invokes a script file, passes commands and data through STDIN, and receives commands and data through STDOUT. At minimum this will need to support defining new Sitix block types that stream their contents into the script with a certain behavior (post-render OR chunk, methinks). This will allow for the dynamic creation of, say, a [md] block which renders all the contents as markdown. Eventually, I’ll have to write a Sitix library for C++ and Python, but a text-based rather than bitbanged format should make it doable without a proper library for now.

Inline scripting will also be overhauled and moved entirely to LuaJIT, as soon as I figure out how the hell to statically link it into Sitix; I will never expose the Sitix scripting API to the Lua code, as that would get messy quickly.

Spring break is soon, so expect to hear from me again!

P.S: Earlier I teased about something called “PCP”. This is, in fact, a humorous PHP replacement; the goal is to eventually be Sitix for dynamic webapps. Unfortunately, due to the pressing needs of school and Sitix, PCP will not be finished for a while, and once Sitix is in working order, I rather expect PCP won’t replace it for most of my purposes.