# G2C server/client communication document

There are two channels that the G2C client and server communicate with
each other:

- The main ssl/tls reverse tunnel communication
- A "backchannel" used for the client to issue commands

The protocol of the reverse tunnel is well understood, so this document
doesn't focus on it here; instead, we'll focus on the backchannel
communication.

The communication is established by the client opening a standard TCP
socket to its configured "backport" of the server (by default, port
3014). Once open, the server will listen on this port for messages from
the client, and may respond with its own messages.

The format of a message is simple: it is an ASCII big-endian encoded
text block in JSON format, which ends with a vertical pipe character
("\x03"). Using the vertical pipe allows multiple messages to be send on
the same socket, and easily allows the other side of the channel to know
when the message is complete without having to rely on JSON parsing.

Every block of JSON has a "type" field which is used by the protocol
code on either side to verify that the correct JSON is being sent.

The following are the various message back-and forth communications used
by the server/client.

## Initial handshake

The initial handshake is initiated on the client side immediately after
the backchannel socket is opened. This is used to verify to the server
that the client is who it says it is.

Client:
  ```
  {
    type: 'handshake1'
    handshakeVersion: 1
    registeredId: ["regId1", ...]
  }
  ```

^ First, the client sends a "handshake" message, along with all the
registered IDs that it already thinks that it possesses.

Sever:
  ```
  {
    type: 'shakehand1'
    replacement: ["regId1", ...]
    prompt: "encrypted"
  }
  ```

^ The server responds with a list of "replacement" registered IDs that
are already taken by someone else, and so need to be replaced on the
client. It also sends a "challenge prompt", which is a string encrypted
by the client's public key: only the client which possesses that key
will be able to decrypt it.

Client:
  ```
  {
    type: 'handshake2'
    handshakeVersion: 1
    registeredId: [...]
    response: "decrypted"
  }
  ```

^ The client replies again with its registeredIds (replacing or removing
those that were owned elsewhere), and a "response" to the challenge,
which is the prompt decrypted by its own private key.


Server:
  ```
  {
    type: 'shakehand2'
    bindPort: portNumber
    vitae: { vitae }
  }
  ```

^ If the client successfully responds to the challenge, the server will
respond with the bindPort for the registered ID (this may be an array if
more than one ID were found). It also sends the server vitae, which is a
set of information about the server, including the type of server, and
its URL template.

Client:
  ```
  {
    type: 'handshake3'
    vitae: { vitae }
  }
  ```

^ The client makes a final acknowledgement, sending its own client vitae
(host IP, port, username, etc) for management on the server.

Once this handshake is complete, the server and client will continue to
listen to any further protocols. The client is then responsible to
creating a SSL reverse tunnel on the bindPort for each recognized
registeredID.

## Registration

When the client wishes to obtain another registrationID (usually as a
result of the `register` command), this is what happens:

Client:
  ```
  {
    type: 'register1'
    handshakeVersion: 1
    publicKey: PEM
    preferred: preferredPortNumber
  }
  ```

^ The client sends its initial `register` message with a PEM-formatted
string that contains its public key for that registeredID. It also sends
its preferred port number for that ID as well.

Server:
  ```
  {
    type: 'didRegister1'
    registeredId: registeredId
    registeredPort: actualPortNumber
  }
  ```

^ The server responds with a new registeredID and the actual bindPort
that was assigned to the ID.

Client:
  ```
  {
    type: 'register2'
  }
  ```

^ The client makes a final ack to end this protocol. Once sent, the
client should open a reverse SSL tunnel on its bindport.

## Unregistering an ID

The client starts this protocol when it wants to give up one or more
registered ID.

Client:
  ```
  {
    type: 'unregister1'
    handshakeVersion: 1
    registeredId: regId
  }
  ```

^ The client indicates which registered ID it wants to unregister.

Server:
  ```
  {
    type: 'didUnregister1'
    prompt: "encrypted"
  }
  ```

^ The server responds with a challenge prompt (which is random data
encrypted with that ID's key.

  ```
  {
    type: 'unregister2'
    handshakeVersion: 1
    registeredId: registeredID
    response: "unencrypted"
  }
  ```

^ The client sends its response to the challenge prompt, repeating the
ID it wants to unregister.

Server:
  ```
  {
    type: 'didUnregister2'
  }
  ```

^ The server responds with a simple ack as its success message.

  ```
  {
    type: 'unregister3'
  }
  ```

^ The client sends its own ack in response. Once this is done, the
client should make sure that it any SSL tunnels associated with that ID
are closed.

## Ping

A client can send this simple message to the server to check that the
server is running.

Client:
  ```
  {
    type: 'ping1'
  }
  ```

^ Client sends a simple message

Server:
  ```
  {
    type: 'didPing1'
  }
  ```

^ The server responds, which concludes the protocol.

