pubkey => ip */ private array $peers = []; private int $next = 2; public string $endpointValue = 'vpn.clupilot.test:51820'; public string $publicKeyValue = 'HUBPUBLICKEY0000000000000000000000000000000='; /** Snapshots the tests can shape; defaults to "configured, never handshaked". */ public array $snapshots = []; public function allocateIp(int $from = 1): string { // Der Zähler springt nach vorn, wenn ab einer höheren Stelle gesucht // wird, und läuft danach von dort weiter — sonst gäbe die Attrappe // zweimal dieselbe Adresse aus, sobald jemand einmal mit Versatz fragt. $this->next = max($this->next, $from); return '10.66.0.'.$this->next++; } public function addPeer(string $publicKey, string $ip): void { $this->peers[$publicKey] = $ip; } public function removePeer(string $publicKey): void { unset($this->peers[$publicKey]); } public function peers(): array { $peers = []; foreach ($this->peers as $publicKey => $ip) { $peers[$publicKey] = $this->snapshots[$publicKey] ?? new PeerSnapshot( publicKey: $publicKey, endpoint: null, allowedIps: $ip.'/32', latestHandshake: null, rxBytes: 0, txBytes: 0, ); } return $peers; } public function endpoint(): string { return $this->endpointValue; } public function publicKey(): string { return $this->publicKeyValue; } /** Raw pubkey => ip map — what the tests assert on. Not the interface's * peers(), which returns live snapshots. */ public function peerIps(): array { return $this->peers; } }