O Protocolo
O modelo do Constrained Application Protocol (CoAP) permite que a interação
Machine-to-Machine seja de uma forma semelhante ao modelo cliente/servidor, porém onde
ambas as máquinas atuem nas duas funções diferente do modelo HTTP. Para definir se a
mensagem enviada é uma solicitação ou resposta o protocolo insere alguns Códigos de Método e de Resposta nas próprias mensagens.
Apesar de o CoAP ser uma camada de aplicação, pode-se pensar em uma abstração de duas camadas,
onde a mais baixa lida com o UDP e as mensagens a outra parte está no nível da aplicação
lidando com as solicitações e respostas.
![](images/figura1.png)
Figura 1: Camadas abstratas do CoAP.
O CoAP realiza troca de mensagens (solicitações e respostas) por meio do UDP entre nós
(pontos) finais, utilizando uma estrutura de cabeçalho com comprimento fixo curto de 4
bytes, podendo conter ainda opções binárias compactas e um payload (carga de conteúdo útil).
Um ID de 16 bits identifica cada mensagem, usado para detectar duplicatas e para
confiabilidade.
A confiabilidade é conseguida marcando-se uma mensagem como
Confirmable (CON), e partir disso, há a retransmissão de uma mensagem de confirmação,
respeitando-se um tempo limite padrão até que o destinatário envie uma mensagem de
Acknowledgement (ACK) com o mesmo ID da mensagem do nó correspondente. Uma mensagem de
Reset (RST) é retornada pelo destinatário se ele não estiver habilitado a fornecer uma
resposta adequada, em vez do ACK.
![](images/figura2.png)
Figura 2: Transmissão de mensagem confiável com ID = 0x7d34.
No caso de uma mensagem que não necessita de transmissão confiável (medições em um sensor, por exemplo), uma mensagem Non-Confirmable (NON) é enviada, que não é replicada pelo destinatário, mas ainda contém um ID que detecta duplicatas. Novamente, se o destinatário não for capaz de processar a mensagem, ele responde com uma mensagem RST.
![](images/figura3.png)
Figura 3: Transmissão de mensagem não confiável com ID = 0x01a0.
As solicitações e respostas são transportadas em mensagens CoAP, incluindo um código de
método ou código de resposta, além de opções que podem conter informações padrões ou
opcionais (como URI e tipos de payload). Um token é incluído para realizar a
correspondência entre solicitações e respostas, independente de mensagens subjacentes.
A solicitação é realizada por meio de mensagens CON ou NON, que é respondida com um ACK
de confirmação se estiver imediatamente disponível. Esse formato é denominado resposta em
Piggybacked.
![](images/figura4.png)
Figura 4: Duas solicitações GET com resposta em Piggybacked, uma bem sucedida e a outra não.
Caso o servidor não possa responder imediatamente a uma requisição com mensagem confirmável,
ele simplesmente responde com uma mensagem vazia para o cliente pare de realizar pedidos.
Quando ele estiver disponível, uma nova mensagem confirmável é retransmitida, sendo assim
chamada de Resposta Separada.
![](images/figura5.png)
Figura 5: Uma solicitação GET com Resposta Separada.
Embora o servidor possa enviar uma mensagem de confirmação,
se uma requisição for realizada com uma mensagem NON, uma nova mensagem NON é repassada como
resposta.
Figura 6: Solicitação e Resposta em mensagens Não-Confirmáveis.
Vale ressaltar que o CoAP, de maneira similar ao HTTP, faz uso de métodos GET, PUT, POST e
DELET. Isso pode ser estendido para além dos quatro, não necessariamente utilizados em pares,
como em casos onde uma única solicitação pode obter múltiplas respostas (por exemplo, em um
Multicast).
O CoAP suporta armazenamento em cache (que pode estar presente num nó final ou intermediário),
carregando informações de validez e recência nas respostas, atendendo de forma mais
eficiente às solicitações. O proxying permite melhorar o desempenho, principalmente em
redes restritas, onde pode ser necessário lidar com segurança ou limitações de tráfego.
O protocolo permite que pedidos sejam feitos a partir de outro ponto de extremidade, onde
o URI (Identificador Uniforme de Recurso) está definido na requisição, ao passo que o IP
está definido para o endereço de proxy.
O UDP lida com a troca de mensagens compactas, onde cada mensagem CoAP ocupa uma seção
de dados de um datagrama UDP, sendo codificada por um formato binário simples. O formato
começa a partir de um cabeçalho de 4 bytes fixos seguido por um token de tamanho variável,
compreendido entre 0 e 8 bytes. Uma sequência de zeros ou opções sucede o token, podendo
ainda conter um payload no resto do datagrama.
![](images/figura7.png)
Figura 7: Formato da Mensagem.
No cabeçalho, os campos são definidos como:
- Ver: indica o número da versão do CoAP em binário.
- T: indica se a mensagem é CON (0), NON (1), ACK (2) ou RST (3).
- TKL: indica o tamanho variável do token (0 a 8 bytes).
- Code: 3 bits mais significativos indicam se é uma solicitação (0), uma resposta bem
sucedida (2), erro de resposta do cliente (4), ou um erro do servidor (5). O resto é
reservado.
- Message ID: usada para detectar duplicatas ou correspondências entre mensagens
ACK/RST e CON/NON.
A troca de mensagens no CoAP é feita de forma assíncrona entre os nós finais que podem
ser de origem e destino. Essa definição de um ponto final vai depender de como ele é
identificado, seja ele sem segurança (através de um endereço IP e um número de porta UDP),
ou com segurança, conforme for definido esse modo.
Pelo fato de o CoAP poder realizar transportes não confiáveis, ele implementa um mecanismo
leve de confiabilidade para tratar mensagens que cheguem fora de ordem, duplicadas ou que
desapareçam sem aviso prévio. Uma mensagem pode conter uma solicitação, uma resposta ou
pode estar vazia, sinalizada pelo campo de código no cabeçalho.
a) Transmissão de forma Confiável
A origem retransmite uma mensagem CON em intervalos de tempos crescentes, até que receba
uma confirmação ACK (ou RST) ou até que acabe o número de tentativas. Uma rejeição pode
ser tratada usando um código reservado no datagrama. Todo este processo é controlado por
um tempo limite e um contador de retransmissão:
Figura 8: Esquema de transmissão confiável entre pontos finais.
b) Transmissão de forma Não Confiável
Como as mensagens não-confirmáveis dispensam reconhecimento, o nó de destino não é capaz
de confirmar se houve ou não recepção. Desta forma, um nó de origem pode enviar múltiplas
cópias da mesma mensagem, ou a própria rede pode duplicar uma mensagem durante a
transmissão. Isto pode ser especificado através do ID da mensagem.
Figura 9: Esquema de transmissão não confiável entre pontos finais.
Figura 9: Uso dos tipos de mensagem. O (*) representa um ping CoAP.
O ID de uma mensagem, conjuntamente com informações de endereços correspondentes a nós finais,
é responsável por correlacionar ACK’s e RST’s a mensagens CON e NON. Ele é um inteiro de
16 bits, gerado pela emissor no cabeçalho CoAP, que precisa ser replicado pelo receptor,
ou seja, os IDs de mensagens precisam ser correspondentes entre a origem e o destino. Vale
ressaltar que um mesmo ID não pode ser reutilizado durante uma mesma troca.
Contudo, um destinatário pode receber várias vezes uma mesma mensagem CON, desde que as
reconheça pelos ACK’s ou RST’s, processando apenas uma única vez a solicitação ou resposta
contida na cópia. Esta situação é útil para quando um reconhecimento se perde ou a mensagem
não atinge o seu destino antes do tempo limite. O mesmo vale para mensagens NON, mas como
não há reconhecimento neste caso, o receptor deve ignorar silenciosamente as mensagens
duplicadas.
O CoAP fornece um limite superior para o tamanho de uma mensagem, de tal forma que, se
ela exceder o tamanho de um pacote na camada de enlace, haverá desfragmentação. Desta
forma, a mensagem deve ser devidamente encapsulada para caber num pacote único IP, e
necessariamente, dentro um datagrama IP.
Diversas aplicações necessitam de um buffer para alocar mensagens recebidas,
principalmente em nós restritos, sendo capazes de determinar e recuperar a porção
perdida de um datagrama. O buffer deve conter ao menos o cabeçalho CoAP e as opções,
senão toda carga útil, por isso a importância do tamanho da mensagem.
Para não haver congestionamento, os clientes devem limitar o número de interações
pendentes simultaneamente que eles tem com um servidor através de NSTART (que tem como
valor padrão igual a 1). Essas interações são definidas como interações onde um pedido
que ainda não recebeu uma resposta ou uma mensagem de reconhecimento, ou um CON que não
recebeu ACK.
O CoAP opera sob um modelo similar ao HTTP no que diz respeito à comunicação, sendo
capaz de atuar como cliente, enviando diversas requisições à um servidor e atendendo às
solicitações a partir do mesmo. A única particularidade reside na troca de mensagens que
é feita de forma assíncrona.
a) Solicitações
Uma solicitação pode ser iniciada configurando-se o campo de código no cabeçalho (que
define a mensagem como CON ou NON) para um código de método que vai ser aplicado a
algum recurso. Como visto anteriormente, o CoAP suporta os métodos GET (que possui
propriedades de recuperação), PUT e DELET (que podem ser invocados diversas vezes e POST
(relacionado a criação ou atualização de um recurso no destino).
b) Respostas
Um servidor responde a uma requisição através de um token correspondente gerado pelo
cliente, sendo a resposta identificada pelo código no cabeçalho, que indica a tentativa
de entender e satisfazer o pedido. Dos 8 bits de código, os 3 mais significativos definem
a classe da resposta, enquanto o restante serve para detalhes adicionais. As classes podem
ser:
- Sucesso: pedido entendido e aceito.
- Erro do cliente: pedido com sintaxe incorreta ou não que pode ser realizado.
- Erro do servidor: falha no servidor ao atender um pedido.
![](images/figura11.png)
Figura 10: Estrutura do código de resposta.
Como visto antes, o token é representado por uma sequência de 0 a 8 bytes e é usado para
diferenciar solicitações do cliente, sendo cada um exclusivo para um determinado par de nós
finais (origem e destino). Um token pode ter comprimento 0 (vazio) quando outros não estão
em uso, ou quando solicitações são feitas em sequência e recebem resposta em Piggybacked.
Por fim, se um token não gerado for recebido no destino, este deve simplesmente ignorá-lo.