NetworkDesign
Please note: This page explains the low level network communication. You don't need to bother with these implementation details if you want to use Marauroa to write a game. We document the network design anyway for contributor to Marauroa itself. And it is helpful for people porting Marauroa to other programming languages.
Messages
Marauroa uses messages to communicate between client and server. The messages sent from the client to the server are prefixed with C2S and the ones sent from the server to the client use the prefix S2C.
Each message is implemented in its own Java class in the package marauroa.common.net.message. You can lookup up the details about every message in the javadoc. If you want to port Marauroa to another programming language, you will need know how the message are serialized exactly. The easiest way to learn that is to look at the source code of the readObject() and writeObject() methods.
There are for different client states of the game: connected, logged in, in game, logged out. Depending on the state different messages are valid:
State connected

The login process is a bit complicated because of security requirements. Don't be scared, just follow it step by step.
Onces the TCP connection is established the clients requests the RSA public key from the server using C2SLoginRequestKey. The server checks the protocol version implicitly included in every message. If it is compatible, it replies with a S2CLoginSendKey including the RSA public key. It is composed of two bytes arrays: The first one contains the value of 'n', and the second the value of 'e'.
The client now computes a nonce (a random number) and sends its hash as byte array to the server in a C2SLoginPromise message.
TODO: Message S2C Login Send Nonce
The server responds to the client promise by computing a nonce and sending it in this message. This message contains the nonce as a bytes array. Message C2S Login Send Nonce Name and Password
The client now sends its nonce, its username and the value Crypt(xor(xor(client nonce, server nonce), password). This message contains 3 fields. The first one is a bytes array containing the client nonce, the second one a string containing the username and the third one a bytes array containing the encrypted password. On reception, the server checks that the hash he received at first is the hash of the nonce he just received. It then decodes the password field, and having the value of the client nonce and its nonce, it gets the value of the password. If the username/password combination is correct then the Server must send a Login ACK Message to indicate to the Client that the message has been correctly processed. However, if the username/password is wrong the Server will send a Login NACK (Not ACKnoledge). Message S2C Login ACK
The LoginACK Message is sent from the Server to the Client to indicate that the login process has been completed correctly and that it can proceed to the next step. It has no params. Message S2C Login NACK
The LoginNACK Message is sent from the Server to the Client to tell the Client that its login message is incorrect because either the username or password is wrong or because Server has decided to reject the login request, e.g. if the Server is full or because the IP is banned.
The message is composed of: Message indicating the resolution.
State logged in

State in game

Logging Out

Transmitting Messages over TCP
The idea behind Arianne's network protocol is to use a single TCP stream between the server and the clients. Different kinds of in-game actions create different types of messages that are then interpreted at the opposite side in to meaningful data. TCP takes care of sorting the packets and retransmitting lost ones.
Each message has a general header:
- Size of message (4 bytes)
- Protocol version (1 byte)
- Type of message (1 byte)
- Client ID (4 bytes)
- Timestamp (4 bytes)
This header is followed by message specific data. Have a look at the source code of the methods readObject() and writeObject() of the message in question.
Network Manager
The Network Manager is our router that sends and receives messages to and from the network. The manager exposes the interfaces that allow:
- Reading a message from the network
- Sending a message to the network
- Finalizing the manager
The read operation is a blocking type operation so we have two options, either polling (i.e. continually checking if data is there) or blocking (i.e. only processing when data is actually available, otherwise sleeping).
We choose blocking because we don't want to waste CPU time polling the network for messages, we just want to sleep until messages are available. Hence we create a Thread to read from the Network, let's call it NetworkManagerRead.
Writing messages to the network can be simply coded as a method of Network Manager, as write is an operation that is non blocking by nature.
The NetworkManager opens a Socket from which it will receive all the messages from the network. It will also write all the outbound messages to the network from this same socket. Note: Both write and read use the same Socket.
To encapsulate all this we create both the Read and Write methods as inner classes of Network Manager.
NetworkManager
{
socket
messages
pendingToSendMessages
NetworkManagerRead isa Thread
{
read socket
build message
store in messages
}
NetworkManagerWrite isa Thread
{
get from pendingToSendMessages
serialize message
send socket
}
}
As you can see, messages are stored in a list when they are received. Hence access to the list must be synchronized.
Now lets get back to the interface as exposed to other objects. The write method is immediate, just call it with the message to send, making sure that you have correctly filled SourceAddress and ClientID. The message will then be sent to the Client.
The read method is blocking, when you call the read method it either returns a message from the queue or if the queue is empty the thread blocks (sleeps) until one arrives.
That is the basic idea of the Network Manager. Note that the manager just sends the stream of packets once and doesn't confirm if any of the messages are received. TCP takes care of that.