Client-server architecture for VASSAL 4

I’ve been kicking around some ideas about how to address some of the shortcomings we’ve found with the current client-server model.

Things lacking presently:

P1. Our server is a single point of failure.
P2. Our server is a communications bottleneck.
P3. No straightforward way for anyone else to run their own server.
P4. Clients without the module can’t get it from clients which have it.
P5. Clients can’t leave game state “online” for other clients to pick up.
P6. No public API to let other programs query server status.
P7. No server-client protocol that other clients could be written against.

Some elaboration on these points:

P1 is something we’ve had a problem with repeatedly over the years: There’s a bad storm in Arizona which knocks out the power, a telco junction box fills with water, the router between our host and the world dies, a hard drive in our server dies, etc. All of these result in V3 being unavailable for online play (leaving aside the P2P mode, which I take that hardly anybody knows how to use). That’s frustrating for our users. So, a goal:

G1. There should be no single point of failure for online use of V4.

P2 happens because whenever one client needs to send data to another client, it does that via our server. Presently, the amount of bandwidth we use for our game server is small in relation to what we use for module downloads (this is something I want to measure properly sometime soon, just to be sure, but my guess is that game server traffic is several orders of magnitude less). Nonetheless, our game server has no use for this data itself, and clients could just as well send it to each other (so long as they have some way of connecting to each other).

G2. Let clients send data to each other as much as possible in V4.

P3 is something people have asked us about periodically; I believe the main motivation for wanting to run one’s own game server is to get a more reliable, less congested connection. There’s no reason I can think of for why we’d want to block such a thing—so long as it doesn’t fragment the communities of people looking for games. So, I’d like to address P3 with:

G3. It should be possible for others to run V4 servers. V4 servers should share room information, by default.

P4, that it would be nice to be able to drop in to a room where you don’t yet have the module, is a request I’ve seen numerous times. With G2 met, it would be possible for clients to send modules to each other in most cases, without sending them through the server.

G4. Let clients send modules to other clients.

Regarding P5, it seems that various online game services store game state and history for their players (and also notify them when it is their turn). For a thread on this topic, see this thread on BGG, from here onward. Giving players the ability to store game state online would eliminate the “send files” step of PBEM. I’m not at all in favor of forcing people to do this—I still very much want local storage as well—but I can see the utility of this for some people. How exactly we’d implement it, I’m not sure. I don’t want us to become responsible for storing everybody’s saved games for all eternity. Maybe we could let the user choose what cloud storage to use as a backend, or maybe I’m overestimating the size of logs (not as they currently are, but as they will be for V4). So, there’s some tension here between this goal, and G1, G2:

G5. Let clients store game state online.

Many times we’ve been asked for a way for third parties to ask the game server about its state:

G6. Create a public API for querying game server state.

Finally, P7: There’s no particular reason why the game server should be capable of talking only to the official, reference implementation of the VASSAL client. People have expressed interest in having web-based versions of VASSAL, for example; if we had a documented server-client protocol, then anyone who wanted would be free to create such a thing (or experiment with AI bots, or whatever else people can think up).

G7. Create and document a server-client protocol.

So, I have thoughts on how to accomplish the various goals, but first I want to hear from people about what I’ve left out, whether these make sense, etc.

Also, happy Thanksgiving, everybody.

…or a re-direct. I’ve run several Call of Duty servers and used my own FTP for a file re-direct for my mods and maps. Anyone connects to the server, the re-direct automatically downloads all the necessary files to the client. I would imagine a lot of Vassal developers would like this as it allows them to control the files and, if they make updates or changes, the files can be automatically updated to whatever version the host is running. In other words, they won’t have to go to a module page and download and install the new versions. All they have to do is connect to the host.

Re-directs would also obviously eliminate any download bandwidth on the server.

V3.2 does address this point somewhat, but it is still a patch up of the existing system rather than a redesign. I did several things to help in this area:

  1. Substantially remodelled the user interface to the servers. Add drop-downs to select server type and an Address Book, Using the P2P server should be much, much easier now.
  2. Finished off Rodney’s work on using Jabber Servers as Vassal Servers. This should work (theoretically), allowing any Jabber (XMPP) Server that supports Multi-User Chat (MUC) to host a Vassal game.

I don’t believe the bandwidth used when playing games is particularly significant and running all Commands through a central server has the advantage of single threading the command stream and enforcing a fixed order of commands.

One aspect that does use a fair slice of bandwidth is Synchonizing with a game in progress. This could be handled by direct client to client communication, though sychonizing happens relatively rarely in general play.

The model I had in mind that addresses both P1 and P2, is that every client has the capability of becoming the server for a game. Like the online play of shooters, anyone can start up a server on their PC and this notifies a central ‘tracker’ server that lists all available game servers, what module is running, is it open/closed/password protected etc. If the Server goes down during a session, the other attached clients ‘talk’ among themselves and ‘elect’ one of them to become the new Server. The current central VASSAL server would no longer host games, but take over the centralised ‘tracker’ role.

If I could run my own server (G3), then I could take the responsibility of storing the game states (P5) on my own server for my own hosted game(s), without needing (to purchase) online cloud space.

A big opportunity with server-stored gamestates would be to store the history of the game, rather than only the last logfile. Exchanging log files is pretty straightforward in a one-on-one game, but with multiplayer games it quickly becomes difficult to keep track of who did what. If all previous “logs” are stored in a sequential timeline on the server, you could jump in at any point and replay what happened from that point.

Thus spake Brent Easton:

G2. Let clients send data to each other as much as possible in V4.

I don’t believe the bandwidth used when playing games is particularly
significant and running all Commands through a central server has the
advantage of single threading the command stream and enforcing a fixed
order of commands.

There are some known ways of handling event ordering. One way is what
real-time strategy games do, another quite different one is what first-
person shooters do. It was long enough ago that I read about how these
are done that I can’t summon the details at the moment, but I can tell
you that it’s not necessary to have this stuff go through our server.
(On the other hand, it might not matter much in practice, as you say.)

One aspect that does use a fair slice of bandwidth is Synchonizing with
a game in progress. This could be handled by direct client to client
communication, though sychonizing happens relatively rarely in general
play.

The model I had in mind that addresses both P1 and P2, is that every
client has the capability of becoming the server for a game. Like the
online play of shooters, anyone can start up a server on their PC and
this notifies a central ‘tracker’ server that lists all available game
servers, what module is running, is it open/closed/password protected
etc. If the Server goes down during a session, the other attached
clients ‘talk’ among themselves and ‘elect’ one of them to become the
new Server. The current central VASSAL server would no longer host
games, but take over the centralised ‘tracker’ role.

This is about the same as what I came up with myself:

A client creates a room on our server. Other clients can join that room.
Our server knows the IP addresses of the clients in a room, and notifies
each client of the IP addresses of the others. Each client tries to
connect to each other client (perhaps using a NAT traversal library). If
any client receives connections from all the others, it’s capable of
being the game server. (I believe it should be the case that if any other
client is able to connect to a particular client, then all of them will
be able to, but I suppose it’s safer to have them all try.) The clients
can elect an eligible client to be the game server, which they would
repeat in the event that the client hosting the game disconnects. If no
client is able to recieve connections from all others, then our server
can act as the game server.

The one problem I see here is that this doesn’t actually solve P1, since
clients still have to talk to our server to find other clients. We need
more than one tracker, and then some way for each tracker to inform the
others about who is in what rooms. I can think of a few ways this could
be done—use a distributed database as a backend, have each tracker
notify others when an event occurs. Now, this pushes P1 back a bit
further, but still doesn’t completely solve it—how does a client find
out the names of the trackers? We could hard-code them into VASSAL, but
that’s a crap solution. My initial thought is to say that trackers will
have domain names like n.tracker.vassalengine.org, where n = 0 for our
tracker, and n > 0 for other ones. With that setup, we could even do
things like create DNS records on the fly to temporarily promote clients
to be trackers (which I understand is something like what Skype does for
routing traffic).


J.

Why there has to be the one server for a game. What if that server happens to be down?

All the server nodes could be running together a DHT-style (or like diaspora, Usenet) database. Clients would insert those commands (or log files) to that storage by connecting through any server. So, every client can connect every server and get the latest data for his game. Any server can go down at any time. This is close to the jabber-idea.

Pros:

  • There wouldn’t be any central tracker.
  • client can connect to closest server
  • client can act as a server
  • server outages are not a problem
  • API is about sending and reading data from/to the network

Cons:

  • clients still would have to know where to connect (bootstrap)
  • the health of the network is measured by the amount of good server nodes
  • is there still some “master” client on a game or should everyone just be running the same module version
  • syncing lag (maybe not a problem with boardgamex

how does this sound?


Juho