From 39688c8a40136c0cfa1cbcfa6a34b8280add9a23 Mon Sep 17 00:00:00 2001 From: pingqiu Date: Sun, 8 Feb 2026 15:04:39 -0800 Subject: [PATCH] fix(uds): align request wire format with sra-common LocateRequest Go server was parsing fid at bytes 0-15 (Go format), but Rust uds_client sends opcode(1)+pad(3)+request_id(4)+fid(16) per sra-common::uds_proto::LocateRequest repr(C). Now Go parses: opcode at byte 0, request_id at bytes 4-7, fid at bytes 8-23. Matches the Rust wire format exactly. Co-Authored-By: Claude Opus 4.6 --- weed/server/volume_server_uds.go | 18 ++++++++------ weed/server/volume_server_uds_test.go | 35 ++++++++++++++------------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/weed/server/volume_server_uds.go b/weed/server/volume_server_uds.go index e11354051..46dec568c 100644 --- a/weed/server/volume_server_uds.go +++ b/weed/server/volume_server_uds.go @@ -36,10 +36,13 @@ type UdsServer struct { } // LocateRequest represents a UDS locate request +// Wire format matches sra-common::uds_proto::LocateRequest (repr(C)): +// opcode(1) + pad(3) + request_id(4) + fid(16) = 24 bytes type LocateRequest struct { - Fid [16]byte // ASCII fid, null-padded - Version uint32 - Flags uint32 + Opcode uint8 + _pad [3]byte + RequestId uint32 + Fid [16]byte // ASCII fid, null-padded } // LocateResponse represents a UDS locate response @@ -136,11 +139,12 @@ func (u *UdsServer) handleConnection(conn net.Conn) { return } - // Parse request + // Parse request (matches sra-common::uds_proto::LocateRequest repr(C)) + // opcode(1) + pad(3) + request_id(4) + fid(16) = 24 bytes var req LocateRequest - copy(req.Fid[:], reqBuf[0:16]) - req.Version = binary.LittleEndian.Uint32(reqBuf[16:20]) - req.Flags = binary.LittleEndian.Uint32(reqBuf[20:24]) + req.Opcode = reqBuf[0] + req.RequestId = binary.LittleEndian.Uint32(reqBuf[4:8]) + copy(req.Fid[:], reqBuf[8:24]) // Handle request resp := u.handleLocate(&req) diff --git a/weed/server/volume_server_uds_test.go b/weed/server/volume_server_uds_test.go index f860c7b0f..63fddb5ae 100644 --- a/weed/server/volume_server_uds_test.go +++ b/weed/server/volume_server_uds_test.go @@ -21,27 +21,28 @@ func TestLocateRequestResponseSize(t *testing.T) { } func TestLocateRequestSerialization(t *testing.T) { + // Wire format: opcode(1) + pad(3) + request_id(4) + fid(16) = 24 req := LocateRequest{ - Version: 1, - Flags: 0, + Opcode: 1, // VolumeOpcode::Locate + RequestId: 42, } copy(req.Fid[:], "3,01637037") buf := make([]byte, UdsRequestSize) - copy(buf[0:16], req.Fid[:]) - binary.LittleEndian.PutUint32(buf[16:20], req.Version) - binary.LittleEndian.PutUint32(buf[20:24], req.Flags) + buf[0] = req.Opcode + binary.LittleEndian.PutUint32(buf[4:8], req.RequestId) + copy(buf[8:24], req.Fid[:]) - // Verify fid is correctly placed - fid := string(buf[0:10]) + // Verify fid is correctly placed at offset 8 + fid := string(buf[8:18]) if fid != "3,01637037" { t.Errorf("Expected fid='3,01637037', got '%s'", fid) } - // Verify version - version := binary.LittleEndian.Uint32(buf[16:20]) - if version != 1 { - t.Errorf("Expected version=1, got %d", version) + // Verify request_id + requestId := binary.LittleEndian.Uint32(buf[4:8]) + if requestId != 42 { + t.Errorf("Expected request_id=42, got %d", requestId) } } @@ -145,10 +146,11 @@ func TestUdsServerProtocol(t *testing.T) { defer conn.Close() // Send a request (will fail because vs is nil, but we're testing protocol) + // Wire format: opcode(1) + pad(3) + request_id(4) + fid(16) reqBuf := make([]byte, UdsRequestSize) - copy(reqBuf[0:16], "3,01637037") - binary.LittleEndian.PutUint32(reqBuf[16:20], 1) // version - binary.LittleEndian.PutUint32(reqBuf[20:24], 0) // flags + reqBuf[0] = 1 // VolumeOpcode::Locate + binary.LittleEndian.PutUint32(reqBuf[4:8], 1) // request_id + copy(reqBuf[8:24], "3,01637037") // fid at offset 8 _, err = conn.Write(reqBuf) if err != nil { @@ -195,8 +197,8 @@ func TestUdsSocketCleanup(t *testing.T) { func TestFidParsing(t *testing.T) { tests := []struct { - fid string - valid bool + fid string + valid bool }{ {"3,01637037", true}, {"1,abc123", true}, @@ -221,7 +223,6 @@ func TestFidParsing(t *testing.T) { } fid := string(fidBytes[:fidLen]) - // For empty fid, we expect empty string if tt.fid == "" && fid != "" { t.Errorf("Expected empty fid, got '%s'", fid) }