Interserver communication - VanaDev/Vana GitHub Wiki
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'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 is a game server, where clients will actually play. There aren't any other special roles or functionalities in the ChannelServer.
Interserver communication can be split into 2 relationships:
- LoginServer bidirectionally communicating with WorldServer(s)
- WorldServer bidirectionally communicating with ChannelServer(s)
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.
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).