Alright. Time’s up. What did I do last week ?
Remember how I chose UDP over TCP as my underlying transport protocol ? Well I’m sticking to it, but the handling of the login phase was… erhm… interesting to code.
It seems to be commonly admitted that one should never attempt to code anything security or encryption related. Not because it’s forbidden, but because it’s an expert’s job. You just cannot do something very secure by yourself, when even state-of-the-art algorithms eventually get broken at some point. MD5 for example has been widely used as a handy cryptographic hash function, yet Wikipedia lists some recent dates of successful (as in, faster than brute-force) attacks against it.
And this is just a hash algorithm. For a whole protocol, a one-man-attempt at designing anything hacker-proof is just doomed to fail.
So, the no less commonly admitted solution to provide some security over user authentication in you application seems to be using well designed protocols. You know, “by professionals for professionals” kind of stuff. And by “using protocols” I don’t mean following the specifications (pages over pages of dry text full of references to other pages of dry text, 5 levels deep) and coding them by yourself. You would just need to suck it up and use a damn library that does the job for you.
Thing is, I don’t like damn libraries that do the job for you.
Anyway, if you’ve read some of Glenn Fiedler’s stuff about networking, you know what motivated my choice of UDP. I mean, the whole point of using it was to be in control of the packet flow. In control, as in, as close to the wire as possible. So close that you could almost see the fibers blink.
Even though I didn’t explore the issue very deeply, I’ve got a feeling that using such an unwieldy thing as a full-featured DTLS library for UDP (the ones that are available seem even messier than the TCP counterpart) would require me to relinquish some of this control.
Geez, I just need to code some thin reliability layer over UDP. And this, only during a very short phase at the start, when the user logs in. Surely that shouldn’t be such a hassle ?
Turns out, it was.
My initial plan was to spend the week sucking the power out of UDP from an “in-game” point of view, as is revealed in this very nice paper from Tribes developers. I wanted in particular to try to implement a sliding window with time sensitive data, and my own shot for a message queue which would support on the fly data reevaluation when resending. For example, if the server decided that it wants to send a player’s current avatar position to another player address, but the UDP packet where this information was described was lost, then it will try resending that same thing : the avatar’s position, but with a different value, as it will be reevaluated to the current position. So we don’t lose time trying to resend obsolete data.
But I had very few coding time left when I finally came up with an implementation of… *coughs* a connection manager which could handle a simple authentication phase. Granted, I tried – maybe for longer than needed be – to keep this in a clean architecture. By now, the resulting code is indeed quite well decoupled and may be used for something else than NeREIDS. I think it’s quite easily modifiable too, and when the time comes to change the implementation for some other login paradigm, like using some asymmetric key authentication, this should be achievable with a few local modifications which won’t break the whole thing.
At this point, the authentication code is meant to make the impersonation of another player reasonably hard on a given server, and tries to provide servers with a way to be password protected, should a community want to restrict access to their permanent server, or should a given user want to set up a server for himself and his friends only.
That homemade implementation is thus, in no way, meant to be super-secure. Neither does it provide any kind of a commercial reinsurance that a given user is “allowed” to play.
I plan on releasing the FLNetwork library source (even if messed with my custom ‘FLCore’ types, I guess it would still be readable). But that would be part of another post, better suited for the technical side of this blog.
Well, I also had to fight a very specific Windows issue with sockets… I had to dig deep into Google to find that it was an old issue in some Windows 2000 version, which seems to arise again, surprisingly, with recent 64b Windows on some conditions…
It goes basically like this :
“Hey guys, we folks on Windows dev team, back in Y2K, felt like it would be a good idea for you people messing with sockets to be notified that you’ve sent something to an unreachable location. You know, as you worked hard to devise a way to handle the fact that UDP packets are, in essence, fire and forget messages, why not just throw some kind of OS-based notifications in the mix ? Hmm ? To cheer things up. Everyone is good with it, right ? Perfect. Oh, how will you be notified ? Well, it’s very simple. See, just after you sent the packet, your next “recv()” call on that socket will fail with error 10054. What could be simpler than this ? We “could” have tried to make this kinda useful by giving you a way to know, erhm… which address was unreachable when that happens, but we decided to go for a simple plain old failure. How does that sound ? Ah, for those weirdos who would prefer the old behavior, or those going by the non-Windows-2000-rest-of-the world behavior (poor fellows), you’ll need to perform a few tricks : please insert somewhere in your code an initialization of your socket with this cryptic control code right here. Ah, yes, in the case you’re fool enough not to use our brand new Windows 2000 headers, simply add a define with that magic number there. Sorry ? Why, of course you’ll need to recompile your code. But that doesn’t bother you as you’re currently in development, now, does it ? Not like the guys back in Y2K. Now, have a nice week-end and happy coding !”
Man, I hate those time holes…
Strange thing is, when sending to the loopback address at exactly the same port with my bare (“hello world”) test application for sending through a socket, I didn’t run into the issue… Oh well, now that I added the Windows dirty fix, I don’t think I’ll have the motivation to investigate this issue any further.
Enough with me complaining about tedious networking stuff for now. What’s for you to see this week ?
Well, not much.
I realized I had not devised a way to handle Z-Ordering on my sprites (and text, as I display characters as some kind of spritish thingies)… And just on Sunday, when it was time to throw some ugly-looking buttons for the sake of having a main menu and start some real testing of my connection managers, I noticed I could not see the button labels…
They got displayed behind the button sprites.
I had not seen this before, as it depended on the relative position of the texture addresses (one for the buttons and one for the text font). It just so happened that this time, the map iterator on which this stuff was based was drawing the text first…
So, I tried to restart NeREIDS repeatedly in the hope that I could trick you with a working screenie, but I had no luck in doing so.
And when I tried to simply leave the depth test active when rendering sprites, and adding a real z-value, I ran into issues with transparency… of course. So, it was time to dig back into my sprite manager code and add some Z-sorting mechanism.
It was 1 a.m. I made it kick.
But in the end, I’ve got said ugly-looking buttons to show, I can launch the server process when clicking “start”, and at least the two applications send UDP packets to each other.
I need to test both managers in protocol extensively, as for now the server is like an empty shell. And that’s the plan for this week.
First week and I’m running behind schedule… Well, that’s not as if you were a whole lot to attend to this stuff, anyway. That leaves me as the only one being upset about it, so I guess we’re still in good terms. You and me. Right ?
Hey, why did he leave a button with a masked label, you ask.
Well, this button will be the Open Sesame to a large part of the game concept. And to some extent, to what NeREIDS is all about. I know, right ? I did not tell you much about it… And I still won’t tell you much today.
But the day will come…
Have a nice week 🙂