O que é o DataServer?

No WYD2, o DataServer é o processo responsável por persistir e servir o estado das contas. Ele gerencia:

  • Contas e personagens — arquivos binários Account.bin (9364 bytes) e Chars/0..3.bin (1892 bytes)
  • Guildas — criação, alianças e guerras
  • Selos de alma — persistência em XML
  • Loja de donate — compras, reload e disponibilidade
  • Amigos e mensagens — lista de amigos e chat entre canais
  • Imports em lote — criação de contas, itens e cash em massa

Nenhum cliente conecta diretamente no DataServer — ele se comunica exclusivamente com os GameServers através de um protocolo binário com cifra de stream proprietária.

Por que Rust?

Segurança de memória sem concessões

O código original em C++ (TMLinux) tem bugs latentes de corrupção de memória. Durante a auditoria linha a linha do port, encontramos um off-by-one em arrays de guildas: o código C++ indexava g_pGuildAlly[65535] — uma posição fora do array que causa corrupção silenciosa em C++ mas é impossível por construção em Rust.

Com Rust, índices fora dos limites são detectados em runtime e o compilador rejeita a maioria desses casos em tempo de compilação. Não existe uso-após-free, double-free ou race condition de dados entre threads. O estado global é protegido por Arc<Mutex<>> — sem variáveis globais mutáveis que são a raiz de tantos bugs em C.

Input de rede tratado como hostil

O C++ original confia cegamente em tamanhos de pacote e índices recebidos da rede. O port em Rust valida cada byte:

  • Tamanho do pacote entre 12 e 20000 bytes (bounds check antes de alocar)
  • ClientId e índices validados antes de indexar arrays
  • Checksum de integridade verificado (o C++ original nem verificava!)
  • Nenhum caminho de rede pode causar corrupção de estado — o processo sobrevive a pacotes malformados

Build determinístico e deployment trivial

cargo build --release produz um único binário estático com zero dependências de runtime além da libc do sistema. Nada de Wine, DLLs ou toolchain MSVC. O mesmo código compila para Windows e Linux. O binário atual é simplesmente copiado para a pasta Release/DataServer/ e executado.

4 bugs reais encontrados e corrigidos

A auditoria comparou o port Rust com três referências: o binário de produção (disassemblagem i686), a árvore MSVC original e o TMLinux (fonte do port). Cada bug tem teste de regressão automatizado.

1. "Servidor em Manutenção" para contas normais (crítico)

O port copiou um bloco de manutenção que estava ativo no TMLinux mas comentado na produção real. Resultado: qualquer conta normal recebia erro de manutenção e não conseguia logar. Corrigido com bloco comentado, mantendo o handler de protocolo inócuo.

2. Off-by-one em guildas (panic/DoS)

Arrays de guildas têm tamanho 65535, mas o código acessava o índice 65535 — out-of-bounds que em Rust derrubava o processo. Corrigido com guarda correta nos handlers de aliança e guerra de guilda.

3. Expiração de conta bloqueava para sempre

O port emitia erro de expiração incondicionalmente para qualquer conta com data de expiração preenchida, sem comparar com a data atual. Toda conta que já teve expiração ficava presa eternamente. Corrigido com localtime_r comparando ano e dia do ano.

4. Banimento expirava horas antes (UTC × local)

O cálculo de tempo restante de ban usava UTC civil; o C++ original usa mktime no fuso local. Em servidor UTC-3, um ban que expira à meia-noite local era encerrado 3 horas antes. Corrigido com libc::mktime local.

Qualidade e desempenho

44 testes de regressão

Cobrem cifra (round-trip, pacotes >256 bytes, invariante do checksum), framing de rede, XML round-trip byte-a-byte, selos, tamanhos binários, login (senha errada, Staff, expiração, ban) e todos os bugs corrigidos. cargo test roda em menos de 0,1 segundo.

Ferramentas de qualidade

  • cargo clippy (análise estática oficial do Rust) — zero warnings
  • cargo build --release — zero warnings
  • Tipagem forte (u16, i32, tamanhos de array) pega erros que no C++ só aparecem em produção
  • Serialização wire explícita — sem #pragma pack nem padding implícito

Desempenho

opt-level 2 + LTO, sem GC e sem runtime pesado. Medido ao vivo: login real com p50 ≈ 2,3 ms por request. Para um daemon que faz I/O de arquivo e passa a maior parte do tempo esperando rede, a latência é dominada pelo socket e pelo disco — não pelo runtime.

Manutenibilidade

  • Cada divergência do C++ original está comentada com referência exata (arquivo:linha)
  • Ferramentas Python (bench_login.py, dbg_staff.py) para validação ao vivo
  • ~7.400 linhas em 13 módulos bem definidos
  • Novos desenvolvedores podem contribuir sem medo de quebrar algo — os testes pegam regressões instantaneamente

Como testar

cd dbsrv_rust
cargo build --release --offline
cargo test --offline
cargo clippy --offline --all-targets

cp target/release/dbsrv_rust ../Release/DataServer/dbsrv_rust
cd ../Release/DataServer
./dbsrv_rust

O código fonte completo está disponível na página de downloads.