# Transports

Um *transporte* é uma interface do lado do cliente que pode conectar-se a um URI de comms e trocar mensagens em tempo real com pares ou serviços.

{% hint style="info" %}
Você pode ver o protocolo de comms em ação e experimentá-lo usando o código aberto [Comms Station](https://decentraland.github.io/comms-station/).
{% endhint %}

Os clientes são livres para implementar transportes como julgarem melhor (desde que sigam o protocolo esperado por outros clientes e serviços), mas o [design recomendado](#recommended) descrito abaixo foi testado na prática e comprovou integrar-se bem com diferentes projetos.\`

### Transportes Padrão <a href="#types" id="types"></a>

Existem 5 tipos de transporte definidos pelo protocolo:

* [Websocket](https://github.com/decentraland/docs/blob/main/contributor/communications/transport-types/websocket/README.md) (`ws-room`) usa um fluxo websocket padrão.
* [LiveKit](https://github.com/decentraland/docs/blob/main/contributor/communications/transport-types/livekit/README.md) (`livekit`) usa o framework open-source LiveKit, baseado em WebRTC.
* [SignedLogin](https://github.com/decentraland/docs/blob/main/contributor/communications/transport-types/signed_login/README.md) (`signed-login`) faz uma requisição HTTPS assinada para obter um transporte atribuído dinamicamente de um servidor.
* [Offline](https://github.com/decentraland/docs/blob/main/contributor/communications/transport-types/offline/README.md) (`offline`) é um transporte dummy que indica que não há comms no ambiente atual.
* [Simulator](https://github.com/decentraland/docs/blob/main/contributor/communications/transport-types/simulator/README.md) (`simulator`) é um transporte dummy com comportamento completamente customizado, principalmente para desenvolvedores depurarem suas implementações.

Mensagens enviadas e recebidas através de uma interface de transporte são sempre as mesmas (veja [mensagens](https://github.com/decentraland/docs/blob/main/contributor/communications/messages/README.md)). Alguns transportes podem encapsulá-las em estruturas de controle para transmissão, mas estas devem ser desempacotadas antes de cruzar a `Transport` interface.

### Design Recomendado <a href="#recommended" id="recommended"></a>

Esta é uma `Transport` interface mínima escrita em TypeScript:

```ts
interface Transport {
  // Inicializa o Transport com um URI:
  constructor(private uriWithConnectionParams: string)

  // Abre uma conexão usando o URI fornecido no construtor:
  connect(): Promise<void>

  // Fecha a conexão:
  disconnect(): Promise<void>

  // Envia uma carga arbitrária para o serviço e todos os pares:
  send(packet: Packet): Promise<void>

  // Inscreve-se para mensagens recebidas tanto do serviço quanto de todos os pares:
  on(event: 'receive', callback: (packet: Packet) => void): void
}
```

Implementações reais comumente estendem isto, adicionando eventos de conexão/desconexão e join/leave, envio não-broadcast, tipagem mais rígida ou adaptações específicas da linguagem.

#### URIs de Transporte

Os valores de `uriWithConnectionParams` são sempre da forma:

```
<type>:<type connection parameters>
```

O `<type>` corresponde a um listado acima, e o formato para `<type connection parameters>` depende do transporte específico. Pode ser uma URL, um token opaco ou qualquer dado arbitrário.

O [LiveKit](https://github.com/decentraland/docs/blob/main/contributor/communications/transport-types/livekit/README.md) o transporte, por exemplo, usa uma `wss` URL com um `access_token` parâmetro para estabelecer uma conexão autenticada:

```
livekit:wss://comms.example.com?access_token=eyJhbGciOiJI...
```

Para comparação, o [Websocket](https://github.com/decentraland/docs/blob/main/contributor/communications/transport-types/websocket/README.md) transporte também usa uma `wss` URL, mas sem um token pré-gerado. Requer um fluxo de autenticação uma vez conectado.

#### Criando Transportes

Como cada `Transport` classe suportará um tipo particular de URI, é uma boa ideia ter um método factory que retorne um `Transport` válido ou falhe imediatamente. Por exemplo:

```ts
function createTransport(uriWithConnectionParams: string) {
  const type = getPrefix(urlWithConnectionParams)

  switch (type) {
    case 'ws-room': return new WsRoomTransport(uriWithConnectionParams)
    case 'livekit': return new LiveKitTransport(uriWithConnectionParams)
    // ... outras implementações suportadas ...
  }

  throw new Error(`Unsupported transport type: ${type}`)
}
```

Os clientes não são obrigados a implementar todos os transportes padrão. Se pretendem usar apenas um subconjunto dos tipos definidos sem visar lidar com todos os URIs, são livres para rejeitar os tipos que não suportam.

Clientes com mais recursos, como um World Explorer, são aconselhados a implementar pelo menos os [websocket](https://github.com/decentraland/docs/blob/main/contributor/communications/transport-types/websocket/README.md) e [LiveKit](https://github.com/decentraland/docs/blob/main/contributor/communications/transport-types/livekit/README.md) transportes, que estão atualmente em uso por todos os principais realms.

### Saiba mais

Vá até um [tipo de transporte específico](#types) seção, leia sobre os diferentes [tipos de mensagem](https://github.com/decentraland/docs/blob/main/contributor/communications/messages/README.md) ou confira o \[\[Comms Demo Station]].
