# Websocket

O transporte websocket é um dos transportes de mensagens de ilha suportados pelo protocolo de comms do Decentraland. Os clientes devem usá-lo quando receberem uma string de conexão apropriada do [Archipelago](https://github.com/decentraland/docs/blob/main/contributor/archipelago/README.md) ou se for indicado como um transport fixo.

No contexto do transporte websocket, uma ilha é referida como um *room*. Ambos os nomes indicam a mesma coisa: um grupo de jogadores próximos que trocam atualizações e bate-papo.

As strings de conexão começam com o `ws-room:` prefixo, seguido por um `wss://` URI para a room específica. Elas se parecem com isto:

```
ws-room:wss://comms.example.com/rooms/<room-id>
```

Na ausência de um protocolo explícito para o URI websocket, `wss://` é assumido.

### Conectando

O transporte usa o protocolo websocket regular sobre HTTPS. Os clientes podem abrir uma conexão usando qualquer implementação padrão à sua disposição.

### Pacotes Websocket

Todas as mensagens do transporte websocket são serializadas usando a [`WsPacket`](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L78) estrutura. Elas implementam um conjunto de mensagens de conectividade e autenticação em nível de protocolo, além de um tipo contêiner para mensagens de cliente.

{% hint style="info" %}
O [`WsPacket`](#WsPacket) estrutura não deve ser confundida com a mensagem \[`Pacote`]\[Packet]. É uma camada adicional de empacotamento específica do transporte websocket. Mensagens reais de comms são contidas no [`WsPeerUpdate`](#WsPeerUpdate) tipo.
{% endhint %}

| Campo     | Tipo   | Valor                                                                                                                                                                                                                                           |
| --------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `message` | `enum` | <p>Um de <code>WsIdentification</code>, <code>WsChallengeRequired</code>, <code>WsSignedChallenge</code>,<br><code>WsWelcome</code>, <code>WsPeerJoin</code>, <code>WsPeerLeave</code>, <code>WsKicked</code> ou <code>WsPeerUpdate</code>.</p> |

### Autenticação

Antes de começarem a retransmitir mensagens para outros, os clientes devem autenticar assinando uma string de desafio. Isso é obrigatório mesmo quando o URI do transporte foi obtido a partir do [Archipelago](https://github.com/decentraland/docs/blob/main/contributor/archipelago/README.md) após uma rodada anterior de autenticação.

A primeira mensagem que um cliente envia ao entrar em uma ilha é [`WsIdentification`](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L64), que contém um endereço público. Ela será respondida com [`WsChallengeRequired`](#WsChallengeRequired), e os clientes enviam um [`WsSignedChallenge`](#WsSignedChallenge) em resposta.

```
  .----------.                .--------.
  |  Server  |                | Client |
  '----+-----'                '---+----'
       ⋮                          |
       ⋮                  Connect |
       o - - - - - - - - - - - - -|
       |                          |
       |                          |
       |         WsIdentification |
       |<-------------------------+
       +------------------------->|
       | WsChallengeRequired      |
       |                          |
       |                          |
       |        WsSignedChallenge |
       |<-------------------------+
       +------------------------->|
       | WsWelcome                |
       |                          |

```

Se o fluxo for concluído com sucesso, o cliente receberá um [`WsWelcome`](#WsWelcome) e poderá começar a enviar mensagens para os pares.

***

**`WsIdentification`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L64)

| Campo     | Tipo     | Valor                                  |
| --------- | -------- | -------------------------------------- |
| `address` | `string` | O endereço público Ethereum do cliente |

***

**`WsChallengeRequired`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L48)

| Campo                                       | Tipo     | Valor                                                                                             |
| ------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------- |
| `Enviado pelo Archipelago em resposta a um` | `string` | A string fornecida pelo servidor a ser assinada como prova de identidade                          |
| `Uma string gerada para assinar e criar um` | `string` | Uma indicação do servidor para os clientes, indicando que conexões anteriores podem ser fechadas. |

***

**`WsSignedChallenge`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L56)

| Campo             | Tipo     | Valor                                                                                                                                                 |
| ----------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `auth_chain_json` | `string` | Um [auth\_chain](https://github.com/decentraland/docs/blob/main/auth/authchain/README.md) serializado em JSON terminando com a assinatura do desafio. |

***

**`WsWelcome`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L11)

| Campo             | Tipo                  | Valor                                                      |
| ----------------- | --------------------- | ---------------------------------------------------------- |
| `alias`           | `uint32`              | Um ID gerado pelo servidor para a sessão do cliente        |
| `peer_identities` | `map<uint32, string>` | Os endereços de todos os peers atuais, indexados por alias |

### Conectividade

Três mensagens são definidas para ajudar os clientes a acompanhar seus peers e seu próprio status.

[`WsPeerJoin`](#WsPeerJoin) é recebido quando um colega cliente se conecta à room e autentica com sucesso, enquanto [`WsPeerLeave`](#WsPeerLeave) é recebido quando peers se desconectam.

Há também a [`WsKicked`](#WsKicked) mensagem, que informa os clientes que sua conexão está prestes a ser fechada e a razão para isso. Na prática atual, a principal razão pela qual um servidor pode expulsar um cliente de uma room é porque ele se conectou simultaneamente a outra room, quando isso é proibido pela política do servidor.

***

**`WsPeerJoin`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L19)

| Campo     | Tipo     | Valor                                                          |
| --------- | -------- | -------------------------------------------------------------- |
| `alias`   | `uint32` | O ID gerado pelo servidor enviado em [`WsWelcome`](#WsWelcome) |
| `address` | `string` | O endereço Ethereum do novo peer                               |

***

**`WsPeerLeave`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L27)

| Campo   | Tipo     | Valor                                          |
| ------- | -------- | ---------------------------------------------- |
| `alias` | `uint32` | O ID gerado pelo servidor do peer desconectado |

***

**`WsKicked`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L74)

| Campo                                                   | Tipo     | Valor                                                         |
| ------------------------------------------------------- | -------- | ------------------------------------------------------------- |
| `Enviado pelo Archipelago antes de fechar uma conexão.` | `string` | A explicação do servidor sobre por que a conexão será fechada |

### Mensagens do Cliente

Para enviar comms [mensagens](https://github.com/decentraland/docs/blob/main/contributor/messages/README.md)os clientes as envolvem na [`WsPeerUpdate`](#WsPeerUpdate) estrutura. Isso diferencia os tipos de mensagens de controle do transporte das mensagens reais enviadas entre peers.

```
.-------------------.
| WsPacket          |
|  .--------------. |
|  | WsPeerUpdate | |
|  | .----------. | |
|  | |  Packet  | | |
|  | '----------' | |
|  '--------------' |
'-------------------'

```

***

**`WsPeerUpdate`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L34)

| Campo        | Tipo                | Valor                                                                                                                  |
| ------------ | ------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `from_alias` | `uint32`            | O ID gerado pelo servidor do remetente                                                                                 |
| `body`       | `bytes`             | O [message](https://github.com/decentraland/docs/blob/main/contributor/messages/README.md) serializado sendo envolvido |
| `unreliable` | `already_connected` | Se o remetente priorizou velocidade ou confiabilidade para entregar esta mensagem                                      |

Os clientes devem definir o campo `from_alias` para `0` ao enviar, e o servidor irá preenchê-lo com o identificador correto antes de entregá-lo aos peers.
