Versão: 1.0 Projeto: TCP/IP do Zero — Capture the Flag Status: Experimental / Didático
A LibPhysical fornece uma API em C para acesso a um meio físico simulado, implementado por um nó central chamado physical_medium.
A biblioteca abstrai a comunicação UDP real entre o programa do aluno e o nó central. O aluno interage apenas com uma API simples para:
- conectar-se ao meio físico simulado;
- obter MAC virtual;
- obter IP virtual;
- consultar se o meio está livre;
- enviar bytes brutos;
- receber bytes brutos;
- medir latência com o nó central;
- encerrar a conexão.
A LibPhysical não implementa Ethernet, IEEE 802, IP ou TCP. Esses protocolos serão implementados pelos alunos sobre os bytes transportados pela biblioteca.
Toda a API pública da LibPhysical usa host byte order.
Isso significa que o usuário da biblioteca não deve chamar htonl() ou ntohl() ao usar:
PHY_SERVER_IP
phy_virtual_ip()
phy_send()
phy_recv()A conversão para network byte order acontece internamente na biblioteca.
Exemplo correto:
phy_send(h, PHY_SERVER_IP, data, len);Exemplo incorreto:
phy_send(h, htonl(PHY_SERVER_IP), data, len);Programa escrito pelo aluno usando libphysical.h.
Servidor physical_medium, responsável por:
- registrar grupos;
- atribuir MAC virtual;
- atribuir IP virtual;
- encaminhar mensagens;
- simular ocupação do meio;
- responder a diagnósticos;
- receber encerramento de conexão.
| Nome | Valor | Direção |
|---|---|---|
| HELLO | 0x01 |
Cliente → Nó |
| HELLO_ACK | 0x02 |
Nó → Cliente |
| DATA | 0x03 |
Cliente → Nó |
| DELIVER | 0x04 |
Nó → Cliente |
| MEDIUM | 0x05 |
Cliente → Nó |
| MEDIUM_OK | 0x06 |
Nó → Cliente |
| PING | 0x07 |
Cliente → Nó |
| PONG | 0x08 |
Nó → Cliente |
| BYE | 0x09 |
Cliente → Nó |
| ERROR | 0xFF |
Nó → Cliente |
Antes de transmitir dados, o cliente deve se registrar no nó central.
Esse processo é realizado automaticamente por:
PhysicalHandle *phy_connect(const char *group_id,
const char *host,
uint16_t port);Formato:
+--------+------------------+
| Type | Group ID |
+--------+------------------+
| 1 byte | 16 bytes |
+--------+------------------+
Campos:
| Campo | Tamanho | Descrição |
|---|---|---|
| Type | 1 byte | Valor 0x01 |
| Group ID | 16 bytes | Identificador do grupo, preenchido com zeros |
O group_id deve possuir no máximo 16 caracteres.
Formato:
+--------+---------+------------+
| Type | MAC | Virtual IP |
+--------+---------+------------+
| 1 byte | 6 bytes | 4 bytes |
+--------+---------+------------+
Campos:
| Campo | Tamanho | Descrição |
|---|---|---|
| Type | 1 byte | Valor 0x02 |
| MAC | 6 bytes | MAC virtual atribuído ao grupo |
| Virtual IP | 4 bytes | IP virtual atribuído, em network byte order |
A biblioteca converte o IP recebido para host byte order antes de armazená-lo.
O envio de bytes brutos é feito por:
int phy_send(PhysicalHandle *h,
uint32_t dst_ip,
const uint8_t *data,
size_t len);O parâmetro dst_ip deve estar em host byte order.
A biblioteca encapsula os dados na mensagem DATA.
Formato:
+--------+------------+----------+
| Type | Dst IP | Payload |
+--------+------------+----------+
| 1 byte | 4 bytes | N bytes |
+--------+------------+----------+
Campos:
| Campo | Tamanho | Descrição |
|---|---|---|
| Type | 1 byte | Valor 0x03 |
| Dst IP | 4 bytes | IP virtual de destino, em network byte order |
| Payload | N bytes | Bytes brutos enviados pelo usuário |
A LibPhysical não interpreta o payload.
A recepção é feita por:
ssize_t phy_recv(PhysicalHandle *h,
uint32_t *src_ip,
uint8_t *buf,
size_t buf_len,
int timeout_ms);A função bloqueia até receber um pacote de dados ou até o timeout expirar.
Mensagens de controle, como MEDIUM_OK e PONG, são descartadas por phy_recv().
Formato:
+--------+------------+----------+
| Type | Src IP | Payload |
+--------+------------+----------+
| 1 byte | 4 bytes | N bytes |
+--------+------------+----------+
Campos:
| Campo | Tamanho | Descrição |
|---|---|---|
| Type | 1 byte | Valor 0x04 |
| Src IP | 4 bytes | IP virtual de origem, em network byte order |
| Payload | N bytes | Bytes entregues ao usuário |
A biblioteca converte Src IP para host byte order antes de preencher src_ip.
Retornos de phy_recv():
| Retorno | Significado |
|---|---|
> 0 |
Número de bytes recebidos |
0 |
Timeout |
-1 |
Erro |
A função:
int phy_medium_free(PhysicalHandle *h);consulta se o meio físico simulado está livre.
Ela é usada como base para implementação de CSMA/CA pelos alunos.
Formato:
+--------+
| Type |
+--------+
| 1 byte |
+--------+
Valor:
0x05
Formato:
+--------+--------+
| Type | Free |
+--------+--------+
| 1 byte | 1 byte |
+--------+--------+
Campos:
| Campo | Valor | Significado |
|---|---|---|
| Type | 0x06 |
Resposta à consulta |
| Free | 0x00 |
Meio ocupado |
| Free | 0x01 |
Meio livre |
Retornos de phy_medium_free():
| Retorno | Significado |
|---|---|
1 |
Meio livre |
0 |
Meio ocupado |
-1 |
Erro |
A função:
long phy_ping(PhysicalHandle *h);mede o RTT até o nó central.
Ela envia uma mensagem PING e aguarda uma mensagem PONG.
Formato:
+--------+
| Type |
+--------+
| 1 byte |
+--------+
Valor:
0x07
Formato:
+--------+----------+
| Type | RTT Hint |
+--------+----------+
| 1 byte | 2 bytes |
+--------+----------+
Campos:
| Campo | Tamanho | Descrição |
|---|---|---|
| Type | 1 byte | Valor 0x08 |
| RTT Hint | 2 bytes | Campo reservado para sugestão de RTT em microssegundos |
A implementação atual mede o RTT localmente no cliente usando relógio monotônico.
Retornos de phy_ping():
| Retorno | Significado |
|---|---|
>= 0 |
RTT medido em microssegundos |
-1 |
Erro ou timeout |
A função:
void phy_disconnect(PhysicalHandle *h);envia uma mensagem BYE ao nó central, fecha o socket e libera a memória do handle.
O envio de BYE é best-effort: falhas no envio são ignoradas.
Formato:
+--------+
| Type |
+--------+
| 1 byte |
+--------+
Valor:
0x09
O nó central pode usar essa mensagem para liberar imediatamente o group_id.
O nó central pode enviar uma mensagem ERROR.
Formato:
+--------+----------+
| Type | Message |
+--------+----------+
| 1 byte | N bytes |
+--------+----------+
Campos:
| Campo | Tamanho | Descrição |
|---|---|---|
| Type | 1 byte | Valor 0xFF |
| Message | N bytes | Texto UTF-8 descrevendo o erro |
A biblioteca atual não expõe diretamente mensagens ERROR pela API pública.
PhysicalHandle *phy_connect(const char *group_id,
const char *host,
uint16_t port);Conecta ao nó central e registra o grupo.
Retorna:
| Retorno | Significado |
|---|---|
| Ponteiro válido | Sucesso |
NULL |
Erro |
void phy_mac_addr(PhysicalHandle *h,
uint8_t mac_out[6]);Copia o MAC virtual para mac_out.
uint32_t phy_virtual_ip(PhysicalHandle *h);Retorna o IP virtual do grupo em host byte order.
Exemplo:
uint32_t ip = phy_virtual_ip(h);Para imprimir com inet_ntoa(), converta para network byte order:
struct in_addr addr;
addr.s_addr = htonl(ip);
printf("%s\n", inet_ntoa(addr));long phy_ping(PhysicalHandle *h);Mede o RTT até o nó central.
Retorna:
| Retorno | Significado |
|---|---|
>= 0 |
RTT em microssegundos |
-1 |
Erro ou timeout |
int phy_medium_free(PhysicalHandle *h);Consulta se o meio está livre.
Retorna:
| Retorno | Significado |
|---|---|
1 |
Meio livre |
0 |
Meio ocupado |
-1 |
Erro |
int phy_send(PhysicalHandle *h,
uint32_t dst_ip,
const uint8_t *data,
size_t len);Envia bytes brutos para um IP virtual.
Retorna:
| Retorno | Significado |
|---|---|
0 |
Sucesso |
-1 |
Erro |
ssize_t phy_recv(PhysicalHandle *h,
uint32_t *src_ip,
uint8_t *buf,
size_t buf_len,
int timeout_ms);Recebe bytes brutos.
Retorna:
| Retorno | Significado |
|---|---|
> 0 |
Bytes recebidos |
0 |
Timeout |
-1 |
Erro |
void phy_disconnect(PhysicalHandle *h);Encerra a conexão com o nó central e libera recursos.
Após esta chamada, o handle não deve ser usado novamente.
#define PHY_SERVER_IP 0x0A000001uRepresenta o IP virtual:
10.0.0.1
A constante está em host byte order.
A versão atual possui as seguintes limitações:
phy_ping()possui timeout fixo de 2 segundos.phy_recv()usa buffer interno de 2048 bytes.- Payloads recebidos acima do tamanho do buffer do usuário são truncados.
ERRORnão é exposto como mensagem estruturada para a aplicação.BYEé enviado em modo best-effort.- A biblioteca não implementa confiabilidade, ordenação, retransmissão ou verificação de integridade.