# Websocket

El transporte websocket es uno de los transportes de mensajería de isla compatibles con el protocolo de comms de Decentraland. Los clientes deben usarlo cuando reciban una cadena de conexión apropiada desde el [Archipelago](https://github.com/decentraland/docs/blob/main/contributor/archipelago/README.md) o si está indicado como un transporte fijo.

En el contexto del transporte websocket, una isla se denomina *sala*. Cualquiera de los dos nombres indica lo mismo: un grupo de jugadores cercanos que intercambian actualizaciones y chat.

Las cadenas de conexión comienzan con el `ws-room:` prefijo, seguido de un `wss://` URI para la sala específica. Se ven así:

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

En ausencia de un protocolo explícito para el URI websocket, `wss://` se asume.

### Conexión

El transporte usa el protocolo websocket regular sobre HTTPS. Los clientes pueden abrir una conexión usando cualquier implementación estándar a su disposición.

### Paquetes Websocket

Todos los mensajes del transporte websocket se serializan usando la [`WsPacket`](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L78) estructura. Implementan un conjunto de mensajes a nivel de protocolo para conectividad y autenticación, además de un tipo contenedor para mensajes de cliente.

{% hint style="info" %}
El [`WsPacket`](#WsPacket) La estructura no debe confundirse con el mensaje \[`El`]\[Packet]. Es una capa adicional de envoltura específica del transporte websocket. Los mensajes reales de comms están contenidos en el [`WsPeerUpdate`](#WsPeerUpdate) tipo.
{% endhint %}

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

### Autenticación

Antes de que puedan empezar a retransmitir mensajes a otros, los clientes deben autenticarse firmando una cadena de desafío. Esto es obligatorio incluso cuando el URI del transporte se obtuvo desde [Archipelago](https://github.com/decentraland/docs/blob/main/contributor/archipelago/README.md) tras una ronda previa de autenticación.

El primer mensaje que un cliente envía al unirse a una isla es [`WsIdentification`](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc5/ws_comms.proto#L64), que contiene una dirección pública. Será respondido con [`WsChallengeRequired`](#WsChallengeRequired), y los clientes envían un [`WsSignedChallenge`](#WsSignedChallenge) en respuesta.

```
  .----------.                .--------.
  |  Servidor  |                | Cliente |
  '----+-----'                '---+----'
       ⋮                          |
       ⋮                  Conectar |
       o - - - - - - - - - - - - -|
       |                          |
       |                          |
       |         WsIdentification |
       |<-------------------------+
       +------------------------->|
       | WsChallengeRequired      |
       |                          |
       |                          |
       |        WsSignedChallenge |
       |<-------------------------+
       +------------------------->|
       | WsWelcome                |
       |                          |

```

Si el flujo se completa con éxito, el cliente recibirá un [`WsWelcome`](#WsWelcome) y podrá empezar a enviar mensajes a los pares.

***

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

| Campo     | Tipo     | Valor                                        |
| --------- | -------- | -------------------------------------------- |
| `address` | `string` | La dirección pública de Ethereum del cliente |

***

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

| Campo                                        | Tipo     | Valor                                                                                                 |
| -------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------- |
| `Enviado por Archipelago en respuesta a un`  | `string` | La cadena proporcionada por el servidor que debe firmarse como prueba de identidad                    |
| `Una cadena generada para firmar y crear un` | `string` | Una indicación del servidor a los clientes, que indica que las conexiones anteriores pueden cerrarse. |

***

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

| Campo             | Tipo     | Valor                                                                                                                                              |
| ----------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `auth_chain_json` | `string` | Un [auth chain](https://github.com/decentraland/docs/blob/main/auth/authchain/README.md) serializado en JSON que termina con la firma del desafío. |

***

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

| Campo             | Tipo                  | Valor                                                            |
| ----------------- | --------------------- | ---------------------------------------------------------------- |
| `alias`           | `uint32`              | Un ID generado por el servidor para la sesión del cliente        |
| `peer_identities` | `map<uint32, string>` | Las direcciones de todos los pares actuales, indexadas por alias |

### Conectividad

Se definen tres mensajes para ayudar a los clientes a mantener el seguimiento de sus pares y de su propio estado.

[`WsPeerJoin`](#WsPeerJoin) se recibe cuando otro cliente se conecta a la sala y se autentica con éxito, mientras que [`WsPeerLeave`](#WsPeerLeave) se recibe cuando los pares se desconectan.

También existe el [`WsKicked`](#WsKicked) mensaje, que informa a los clientes que su conexión está a punto de cerrarse y la razón de ello. En la práctica actual, la principal razón por la que un servidor puede expulsar a un cliente de una sala es porque se han conectado simultáneamente a otra sala, cuando eso está prohibido por la política del servidor.

***

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

| Campo     | Tipo     | Valor                                                               |
| --------- | -------- | ------------------------------------------------------------------- |
| `alias`   | `uint32` | El ID generado por el servidor enviado en [`WsWelcome`](#WsWelcome) |
| `address` | `string` | La dirección Ethereum del nuevo par                                 |

***

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

| Campo   | Tipo     | Valor                                               |
| ------- | -------- | --------------------------------------------------- |
| `alias` | `uint32` | El ID generado por el servidor del par desconectado |

***

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

| Campo           | Tipo     | Valor                                                           |
| --------------- | -------- | --------------------------------------------------------------- |
| `KickedMessage` | `string` | La explicación del servidor de por qué la conexión será cerrada |

### Mensajes del cliente

Para enviar comms [messages](https://github.com/decentraland/docs/blob/main/contributor/messages/README.md), los clientes los envuelven en la [`WsPeerUpdate`](#WsPeerUpdate) estructura. Esto diferencia los tipos de mensajes de control del transporte de los mensajes reales enviados entre pares.

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

```

***

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

| Campo        | Tipo                | Valor                                                                                                                           |
| ------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `from_alias` | `uint32`            | El ID generado por el servidor del remitente                                                                                    |
| `body`       | `bytes`             | El [message](https://github.com/decentraland/docs/blob/main/contributor/messages/README.md) serializado que se está envolviendo |
| `no fiable`  | `already_connected` | Si el remitente priorizó velocidad o fiabilidad para la entrega de este mensaje                                                 |

Los clientes deben establecer el `from_alias` campo a `0` al enviar, y el servidor lo rellenará con el identificador correcto antes de entregarlo a los pares.
