Files
90CNServer/server/internal/services/dnfbridge/party_udp_relay_test.go
T
hanfuit 645b64fe21 DNF90 服务端与启动器完整源码(含 GM 工具功能增强)
服务端(Go):
- GM 塞背包/带属性装备发放:在线角色推送 op14 增量物品行,背包实时刷新,无需回角色选择界面
- GM 改金币/改等级:去掉在线拒绝,落库后推送 op14 钱包/op37 等级状态,在线实时刷新
- 等级端点统一切换到新版 GMSetCharacterLevel(自带在线刷新)
- 无限/锁死疲劳模式 + 燃烧疲劳:每房间消耗 2 点、打怪与通关经验双倍
- 燃烧疲劳开关时给所有在线角色推送系统提示(op12 mode 0)
- 深渊史诗掉率:GM 全局倍率 + 城镇增益药剂窗口倍率,真实接入掉落结算

启动器(Python/JS):
- 标题栏自绘、窗口 1204x717、禁止拖拽改大小、仅最小化/关闭
- GM 工具:疲劳与燃烧、深渊史诗掉率、拍卖行上架(单一定价对齐)
- 拍卖行上架前端对齐服务端单一价格语义,修复 400 报错
2026-11-04 14:31:55 +08:00

332 lines
12 KiB
Go

package dnfbridge
import (
"bytes"
"errors"
"net"
"os"
"testing"
"time"
)
func TestCurrentPartyUDPRelayDatagramTraceIsBounded(t *testing.T) {
for count := uint64(0); count <= 1025; count++ {
want := count >= 1 && count <= 8 || count >= 16 && count&(count-1) == 0
if got := currentPartyUDPRelayTraceDatagram(count); got != want {
t.Fatalf("trace count %d=%t want %t", count, got, want)
}
}
}
func TestCurrentPartyUDPRelayForwardsOnlyAuthenticatedDirectedLegs(t *testing.T) {
portStart := testCurrentPartyUDPRelayPortStart(t)
relay, err := newCurrentPartyUDPRelay(true, "127.0.0.1", portStart, testCurrentPartyUDPRelayPortSpan, nil)
if err != nil {
t.Fatalf("new UDP relay: %v", err)
}
defer func() {
if err := relay.Close(); err != nil {
t.Fatalf("close UDP relay: %v", err)
}
}()
bindings := []currentPartyUDPRelayBinding{
{characterID: 101, generation: 1, address: [4]byte{127, 0, 0, 1}},
{characterID: 202, generation: 1, address: [4]byte{127, 0, 0, 1}},
}
if !relay.Sync(77, bindings) {
t.Fatal("relay did not create a complete two-member room")
}
addressAB, portAB, ok := relay.Endpoint(77, 101, 202)
if !ok {
t.Fatal("missing A-to-B relay endpoint")
}
addressBA, portBA, ok := relay.Endpoint(77, 202, 101)
if !ok || portAB == portBA {
t.Fatalf("invalid directed relay endpoints: AB=%d BA=%d ok=%v", portAB, portBA, ok)
}
clientA := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
defer clientA.Close()
clientB := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
defer clientB.Close()
wrongSource := testCurrentPartyUDPClient(t, "127.0.0.2", portStart)
defer wrongSource.Close()
endpointAB := &net.UDPAddr{IP: net.IPv4(addressAB[0], addressAB[1], addressAB[2], addressAB[3]), Port: int(portAB)}
endpointBA := &net.UDPAddr{IP: net.IPv4(addressBA[0], addressBA[1], addressBA[2], addressBA[3]), Port: int(portBA)}
if _, err := wrongSource.WriteToUDP([]byte("forged"), endpointAB); err != nil {
t.Fatalf("send forged endpoint registration: %v", err)
}
if _, err := clientB.WriteToUDP([]byte("b-ready"), endpointBA); err != nil {
t.Fatalf("send B handshake: %v", err)
}
if _, err := clientA.WriteToUDP([]byte("A-payload"), endpointAB); err != nil {
t.Fatalf("send A payload: %v", err)
}
// B's handshake and A's payload travel on separate sockets, and UDP gives
// no cross-socket ordering: on a loaded machine the payload can reach the
// relay before the handshake registers B's leg, and the relay rightly
// drops it. Resending the payload until it arrives keeps the assertion
// about WHAT is forwarded while tolerating WHEN registration wins.
buffer := make([]byte, 128)
var n int
overall := time.Now().Add(5 * time.Second)
for {
if err := clientB.SetReadDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
t.Fatalf("set client B deadline: %v", err)
}
var err error
n, _, err = clientB.ReadFromUDP(buffer)
if err == nil {
break
}
if !errors.Is(err, os.ErrDeadlineExceeded) || time.Now().After(overall) {
t.Fatalf("receive relayed payload: %v", err)
}
if _, err := clientA.WriteToUDP([]byte("A-payload"), endpointAB); err != nil {
t.Fatalf("resend A payload: %v", err)
}
}
if !bytes.Equal(buffer[:n], []byte("A-payload")) {
t.Fatalf("relayed payload = %q, want A-payload", buffer[:n])
}
}
func TestCurrentPartyUDPRelayForwardsFirstHandshakeToRegisteredPeerPort(t *testing.T) {
portStart := testCurrentPartyUDPRelayPortStart(t)
relay, err := newCurrentPartyUDPRelay(true, "127.0.0.1", portStart, testCurrentPartyUDPRelayPortSpan, nil)
if err != nil {
t.Fatalf("new UDP relay: %v", err)
}
defer relay.Close()
clientA := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
defer clientA.Close()
clientB := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
defer clientB.Close()
bindings := []currentPartyUDPRelayBinding{
{characterID: 101, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(clientA.LocalAddr().(*net.UDPAddr).Port)},
{characterID: 202, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(clientB.LocalAddr().(*net.UDPAddr).Port)},
}
if !relay.Sync(78, bindings) {
t.Fatal("relay did not create registered two-member room")
}
addressAB, portAB, ok := relay.Endpoint(78, 101, 202)
if !ok {
t.Fatal("missing A-to-B relay endpoint")
}
endpointAB := &net.UDPAddr{IP: net.IPv4(addressAB[0], addressAB[1], addressAB[2], addressAB[3]), Port: int(portAB)}
if _, err := clientA.WriteToUDP([]byte("first-handshake"), endpointAB); err != nil {
t.Fatalf("send first handshake: %v", err)
}
buffer := make([]byte, 128)
if err := clientB.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
t.Fatalf("set client B deadline: %v", err)
}
n, _, err := clientB.ReadFromUDP(buffer)
if err != nil {
t.Fatalf("receive first relayed handshake: %v", err)
}
if !bytes.Equal(buffer[:n], []byte("first-handshake")) {
t.Fatalf("first relayed handshake = %q", buffer[:n])
}
}
func TestCurrentPartyUDPRelayLearnsActivePartySocketAfterSeededProbePort(t *testing.T) {
portStart := testCurrentPartyUDPRelayPortStart(t)
relay, err := newCurrentPartyUDPRelay(true, "127.0.0.1", portStart, testCurrentPartyUDPRelayPortSpan, nil)
if err != nil {
t.Fatalf("new UDP relay: %v", err)
}
defer relay.Close()
probeA := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
defer probeA.Close()
partyA := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
defer partyA.Close()
clientB := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
defer clientB.Close()
bindings := []currentPartyUDPRelayBinding{
{characterID: 101, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(probeA.LocalAddr().(*net.UDPAddr).Port)},
{characterID: 202, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(clientB.LocalAddr().(*net.UDPAddr).Port)},
}
if !relay.Sync(79, bindings) {
t.Fatal("relay did not create seeded two-member room")
}
addressAB, portAB, ok := relay.Endpoint(79, 101, 202)
if !ok {
t.Fatal("missing A-to-B relay endpoint")
}
addressBA, portBA, ok := relay.Endpoint(79, 202, 101)
if !ok {
t.Fatal("missing B-to-A relay endpoint")
}
endpointAB := &net.UDPAddr{IP: net.IPv4(addressAB[0], addressAB[1], addressAB[2], addressAB[3]), Port: int(portAB)}
endpointBA := &net.UDPAddr{IP: net.IPv4(addressBA[0], addressBA[1], addressBA[2], addressBA[3]), Port: int(portBA)}
if _, err := partyA.WriteToUDP([]byte("A-live-source"), endpointAB); err != nil {
t.Fatalf("send A live-source handshake: %v", err)
}
buffer := make([]byte, 128)
if err := clientB.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
t.Fatalf("set B read deadline: %v", err)
}
if _, _, err := clientB.ReadFromUDP(buffer); err != nil {
t.Fatalf("receive A handshake at seeded B endpoint: %v", err)
}
if _, err := clientB.WriteToUDP([]byte("B-reply"), endpointBA); err != nil {
t.Fatalf("send B reply: %v", err)
}
if err := partyA.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
t.Fatalf("set A live socket deadline: %v", err)
}
n, _, err := partyA.ReadFromUDP(buffer)
if err != nil {
t.Fatalf("receive B reply at learned A party socket: %v", err)
}
if !bytes.Equal(buffer[:n], []byte("B-reply")) {
t.Fatalf("learned A party socket payload=%q", buffer[:n])
}
if err := probeA.SetReadDeadline(time.Now().Add(50 * time.Millisecond)); err != nil {
t.Fatalf("set A probe deadline: %v", err)
}
if _, _, err := probeA.ReadFromUDP(buffer); err == nil {
t.Fatal("B reply was still delivered to the inactive seeded probe socket")
}
}
func TestCurrentPartyUDPRelayPreservesLargeRealtimeActorDatagram(t *testing.T) {
portStart := testCurrentPartyUDPRelayPortStart(t)
relay, err := newCurrentPartyUDPRelay(true, "127.0.0.1", portStart, testCurrentPartyUDPRelayPortSpan, nil)
if err != nil {
t.Fatalf("new UDP relay: %v", err)
}
defer relay.Close()
clientA := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
defer clientA.Close()
clientB := testCurrentPartyUDPClient(t, "127.0.0.1", portStart)
defer clientB.Close()
bindings := []currentPartyUDPRelayBinding{
{characterID: 101, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(clientA.LocalAddr().(*net.UDPAddr).Port)},
{characterID: 202, generation: 1, address: [4]byte{127, 0, 0, 1}, port: uint16(clientB.LocalAddr().(*net.UDPAddr).Port)},
}
if !relay.Sync(80, bindings) {
t.Fatal("relay did not create large-datagram test room")
}
addressAB, portAB, ok := relay.Endpoint(80, 101, 202)
if !ok {
t.Fatal("missing A-to-B relay endpoint")
}
// Exceeds the former 2 KiB buffer and models one complete reliable actor
// snapshot containing riding/transform plus combat state.
payload := make([]byte, 32*1024)
for index := range payload {
payload[index] = byte(index*31 + 7)
}
endpointAB := &net.UDPAddr{
IP: net.IPv4(addressAB[0], addressAB[1], addressAB[2], addressAB[3]),
Port: int(portAB),
}
if _, err := clientA.WriteToUDP(payload, endpointAB); err != nil {
t.Fatalf("send large actor datagram: %v", err)
}
buffer := make([]byte, len(payload)+1)
if err := clientB.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
t.Fatalf("set client B deadline: %v", err)
}
n, _, err := clientB.ReadFromUDP(buffer)
if err != nil {
t.Fatalf("receive large actor datagram: %v", err)
}
if n != len(payload) || !bytes.Equal(buffer[:n], payload) {
t.Fatalf("large actor datagram bytes=%d want=%d equal=%t", n, len(payload), bytes.Equal(buffer[:n], payload))
}
}
func TestCurrentPartyUDPRelaySyncRemovesFormerMemberLegs(t *testing.T) {
portStart := testCurrentPartyUDPRelayPortStart(t)
relay, err := newCurrentPartyUDPRelay(true, "127.0.0.1", portStart, testCurrentPartyUDPRelayPortSpan, nil)
if err != nil {
t.Fatalf("new UDP relay: %v", err)
}
defer relay.Close()
first := []currentPartyUDPRelayBinding{
{characterID: 101, generation: 1, address: [4]byte{127, 0, 0, 1}},
{characterID: 202, generation: 1, address: [4]byte{127, 0, 0, 1}},
{characterID: 303, generation: 1, address: [4]byte{127, 0, 0, 1}},
}
if !relay.Sync(77, first) {
t.Fatal("initial relay sync failed")
}
if _, _, ok := relay.Endpoint(77, 101, 303); !ok {
t.Fatal("initial member endpoint missing")
}
if !relay.Sync(77, first[:2]) {
t.Fatal("member removal relay sync failed")
}
if _, _, ok := relay.Endpoint(77, 101, 303); ok {
t.Fatal("former member endpoint remained routable")
}
if _, _, ok := relay.Endpoint(77, 101, 202); !ok {
t.Fatal("remaining pair endpoint was removed")
}
}
// testCurrentPartyUDPRelayPortSpan is how many ports the relay may bind its legs
// from in these tests. It is shared with testCurrentPartyUDPClient so that a test
// client socket can never land on one of the legs' port numbers.
const testCurrentPartyUDPRelayPortSpan = 12
func testCurrentPartyUDPRelayPortStart(t *testing.T) int {
t.Helper()
for attempt := 0; attempt < 20; attempt++ {
listener, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0})
if err != nil {
t.Fatalf("allocate test UDP port: %v", err)
}
port := listener.LocalAddr().(*net.UDPAddr).Port
_ = listener.Close()
if port <= 65523 {
return port
}
}
t.Fatal("could not allocate a usable twelve-port UDP test range")
return 0
}
// testCurrentPartyUDPClient listens on an ephemeral loopback port that is kept
// outside the relay's own port window.
//
// The relay binds its legs on the wildcard address (0.0.0.0:port, deliberately:
// see newCurrentPartyUDPRelay) while this helper binds a specific address
// (127.0.0.1:port). Windows lets both exist, and the specific bind wins delivery,
// so a client socket that happened to land on a leg's port number silently
// swallowed every datagram addressed to that leg -- the relay then looked like it
// had failed to forward when in fact nothing ever reached it. The window start is
// handed in by the caller so the two allocations can never overlap.
func testCurrentPartyUDPClient(t *testing.T, ip string, windowStart int) *net.UDPConn {
t.Helper()
for attempt := 0; attempt < 64; attempt++ {
conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.ParseIP(ip), Port: 0})
if err != nil {
t.Fatalf("listen UDP client %s: %v", ip, err)
}
port := conn.LocalAddr().(*net.UDPAddr).Port
if port < windowStart || port >= windowStart+testCurrentPartyUDPRelayPortSpan {
return conn
}
// Give the port back: the relay is about to bind this same number on the
// wildcard address, and holding it here would shadow that leg.
_ = conn.Close()
}
t.Fatalf("could not place UDP client %s outside relay window %d..%d",
ip, windowStart, windowStart+testCurrentPartyUDPRelayPortSpan-1)
return nil
}