DOOR32.SYS Socket Sharing

A common theme in "modern" (lolololol!) BBSing when it comes to doors is the DOOR32.SYS format and socket file descriptor sharing. Basically, a board dumps out a DOOR32.SYS file with the first line (comm type) set to Telnet (2), and the 2nd line (comm or socket handle) to the socket file descriptor of the connected client. The idea of course is for the door to then do direct I/O on that socket handle.

This works for many cases, but has a many issues -- to name a few:

Under Windows (ironically where this is used most), a socket descriptor must be explicitly shared to a child process (the door). To do this generically (that is, to allow arbitrary child PIDs to pick up the fd), one must call DuplicateHandle. This is technically entering undefined behavior land and depending the state of the socket (or if Microsoft decides to simply not allow it under future Windows updates!) all sorts of things can go wrong. Instead, Windows wants you to call WSADuplicateHandle. OK fine, but then we're into a whole other issue: This API requires IPC between the parent and child process to pass some information over and the child must then call WSASocket to get itself the shared fd. Doh!

Another major issue is handing over a socket fd to an arbitrary (that is, a door that you do not control) process is really asking for a world of pain. What is the door doing with the socket handle? How do we know what I/O is happening? So many questions! Worse, for more modern languages such as Node.js that ENiGMA 1/2 utilizes, direct socket sharing is near impossible -- and if you did pull it off, even more dangerous due to the system utilizing libuv or similar on the socket (ie: it must know about the I/O going on!).

Enter Bivrost!

Due to the problems described above, and users of ENiGMA 1/2 wanting to use DOOR32.SYS doors, I created bivrost! (OK, and I wanted an excuse to learn some Rust as well).

Basically what bivrost! provides is a bridge between a listening socket (ie: ENiGMA 1/2's temporary socket server for doors) and a DOOR32.SYS shared socket. The observer may point out that bivrost! on Windows also utilizes DuplicateHandle(). This is very true, but in this case the exact semantics can be controlled and if anything goes wacky, only bivrost! is effected and your BBS can continue on it's way.

Note that bivrost! can also be used for other purposes outside the DOOR32.SYS and BBSing world, but this was it's original intent.

Check out the bivrost! page for more information or the ENiGMA 1/2 documentation on doors with shared socket descriptors for more information!

comments powered by Disqus