Interserver communication - VanaDev/Vana GitHub Wiki

Table of Contents

Roles

LoginServer

The role of the LoginServer is exactly what it sounds like; it's a public-facing server that clients initially connect to. There may only be a single LoginServer in operation without advanced configuration that requires multiple ports.

Aside from its functionality as the initial client contact point, it performs a number of internal tasks. It executes the SQL to keep the schema updated, computes rankings and it also manages the configuration information for each world.

Both WorldServer and ChannelServer connect to this server in order to be assigned appropriate identifiers and in the case of ChannelServers, a WorldServer to connect to.

WorldServer

WorldServer's role is a little less clear. Currently, it doesn't do much other than bounce communication around and maintain a store of player data so that it can provide copies of player data to new channels. It may seem as though this could be merged with LoginServer (and it can), but there are a couple problems with that.

One is that it would allow channels to commit a denial of service (DoS) against the LoginServer either intentionally or not. All map updates, level updates, etc. are persisted to the WorldServer. As you start adding more channels, the likelihood of a DoS increases.

Secondly, eventually, I would like the WorldServer to be the only server that interfaces with the database - or separate out database interaction at all into a DatabaseServer. This would make it very easy to ensure that a SQL connection is up and account for the case that it is not. I could move this to the LoginServer, but again, then it's doing way more work than it should be especially considering that it's a public-facing server.

ChannelServer

ChannelServer is a game server, where clients will actually play. There aren't any other special roles or functionalities in the ChannelServer.

Basic Design

Interserver communication can be split into 2 relationships:

  • LoginServer bidirectionally communicating with WorldServer(s)
  • WorldServer bidirectionally communicating with ChannelServer(s)
Anywhere that LoginServer and ChannelServer would communicate is passed via WorldServer. There is one exception and this is the initial channel registration (which is how the channel obtains a world to connect to).

Communication occurs by the source choosing the destination via packet headers. As such, no special code needs to be added to get a message passing through a given server. There is a small list of headers and their usage is fairly straightforward:

 IMSG_TO_LOGIN
 IMSG_TO_WORLD
 IMSG_TO_WORLD_LIST
 IMSG_TO_ALL_WORLDS
 IMSG_TO_CHANNEL
 IMSG_TO_CHANNEL_LIST
 IMSG_TO_ALL_CHANNELS

If you use IMSG_TO_WORLD or IMSG_TO_CHANNEL, you must include a world_id_t or channel_id_t respectively. This conveys which specific one is your destination.

If you use IMSG_TO_WORLD_LIST or IMSG_TO_CHANNEL_LIST, you must include a vector_t of world_id_t or vector_t of channel_id_t.

If you simply want a full broadcast, you would use IMSG_TO_WORLDS or IMSG_TO_CHANNELS.

Synchronization

Built into Vana is a player information synchronization system. The way this works is that the WorldServer holds all the data for players and sends this information to new ChannelServers as they come online. Every ChannelServer also has a local cache of this information.

This means that things like the /find command don't have to go to WorldServer to be distributed. Chat might not have to go to the WorldServer at all if all recipients are on the same channel. It means that when a player logs in or switches channels or maps or levels up, this information is broadcasted to the WorldServer and then distributed to all other channels. In essence, it allows you to "hook into" these events and do what operations you will with them. So updating guilds, parties, buddies, etc. can all be done at the same place in the code.

This also has the consequence that it's much easier to program any things that require player information. It also has the consequence for the future that it's possible for the ChannelServer to not close when its connection to the WorldServer is lost. It could queue these changes and then simply send them off when it comes back.

Currently, the only data that the WorldServer loads at first is player identifier and name. This is consistent with how buddies and guilds work. When the player logs in for a session, the ChannelServer loads all the player data (per normal) and then syncs it to the WorldServer. The database is treated as the authority for player data rather than the existing cache(s).

⚠️ **GitHub.com Fallback** ⚠️