Pular para o conteúdo

Arcane.Rede

TCP, UDP, DNS e TLS — o que está abaixo do HTTP.

O Kiln fala HTTP e a Malha fala com outro serviço. Abaixo disso não havia nada: um protocolo próprio, um agente que manda uma linha por UDP, ou descobrir para onde um nome aponta pediam sair da linguagem.

E o TLS estava na lista do que não existe, na própria documentação. Ele existe agora, dos dois lados.

TCP#

dataforge
adopt Arcane.Rede as Rede

action atender(conexao):
    pedido := conexao.receber_linha()
    conexao.enviar_linha(pedido.upper())

Rede.servir(atender, host := "0.0.0.0", porta := 9000)
dataforge
cliente := Rede.conectar("127.0.0.1", 9000)
cliente.enviar_linha("forja")
out cliente.receber_linha()        // FORJA
cliente.fechar()

O TCP não tem fronteira de mensagem#

Ele entrega um fluxo de bytes, e não mensagens. O formato mais comum para resolver isso é tamanho + corpo:

dataforge
adopt Arcane.Bytes as Bytes

action mandar(conexao, texto):
    dados := Bytes.de_texto(texto)
    conexao.enviar(Bytes.empacotar(">u32", len(dados)))
    conexao.enviar(dados)

action receber(conexao):
    quanto := Bytes.desempacotar(">u32", conexao.receber_exato(4))[0]
    yield Bytes.para_texto(conexao.receber_exato(quanto))

Ler#

ChamadaFaz
receber(n, prazo)o que chegou, até n bytes
receber_exato(n, prazo)insiste até completar n
receber_linha(prazo, limite)até a quebra, com teto
receber_tudo(prazo, limite)até o outro lado fechar
enviar(dados) · enviar_linha(t)manda tudo, sem devolver pela metade

UDP#

Manda e esquece: sem conexão, sem ordem, sem garantia. É o certo para métrica, descoberta e log — onde perder um pacote custa menos que a espera de confirmar cada um.

dataforge
coletor := Rede.udp(porta := 8125, escutar := yes)
chegou := coletor.receber()
out chegou["host"], chegou["dados"]

agente := Rede.udp()
agente.enviar("pedidos=42", "127.0.0.1", 8125)

DNS#

dataforge
out Rede.resolver("dataforge-lang.vercel.app")
// [{ip: 76.76.21.21, versao: 4}, …]

out Rede.nome_de("8.8.8.8")      // dns.google
out Rede.meu_ip()                // o IP com que esta máquina sai

Portas#

dataforge
porta := Rede.porta_livre()                          // livre agora
given Rede.porta_aberta("db", 5432):
    out "o banco está de pé"

Rede.esperar_porta("api", 8080, prazo := 30.0)       // espera subir

esperar_porta substitui o "sobe o serviço e dorme dois segundos torcendo para dar tempo" de todo script de integração. Quando ela desiste, diz o que costuma ser:

text
erro: api:8080 não abriu em 30s.
  O serviço não subiu, subiu em outra porta, ou subiu em
  127.0.0.1 quando deveria ser 0.0.0.0.

TLS#

dataforge
// cliente
seguro := Rede.conectar("api.exemplo.br", 443, tls := yes)

// servidor
Rede.servir(atender, porta := 443,
    tls := {"certificado": "cert.pem", "chave": "chave.pem"})

O certificado que vence sem avisar#

Um certificado vencido derruba o site inteiro, e o aviso chega pelo cliente reclamando. Isto é o que um monitor pergunta:

dataforge
ficha := Rede.certificado_de("dataforge-lang.vercel.app")
out ficha["emissor"], ficha["valido_ate"], ficha["nomes"]

given Rede.dias_ate_vencer("api.exemplo.br") smaller 14:
    alertar("o certificado vence em menos de duas semanas")