Skip to content

Commit 4e91eea

Browse files
Add protocol version and warnings to hello and welcome packets
Co-authored-by: erikdubbelboer <522870+erikdubbelboer@users.noreply.github.com>
1 parent 7385dbd commit 4e91eea

5 files changed

Lines changed: 161 additions & 8 deletions

File tree

internal/signaling/peer.go

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,37 @@ func (p *Peer) HandleHelloPacket(ctx context.Context, packet HelloPacket) error
226226
}
227227
}
228228

229-
err := p.Send(ctx, WelcomePacket{
230-
Type: "welcome",
231-
ID: p.ID,
232-
Secret: p.Secret,
233-
})
229+
// Prepare warnings based on client version or other conditions
230+
var warnings []string
231+
232+
// Example: warn about deprecated features or compatibility issues
233+
// This demonstrates how to use the warnings field in the future
234+
if packet.Version != "" {
235+
// Example logic for version-based warnings
236+
// In a real scenario, you might parse semantic versions and compare properly
237+
// For now, just demonstrate the capability without complex version parsing
238+
_ = packet.Version // acknowledge we're using the version field
239+
}
240+
241+
// Future examples of when warnings might be added:
242+
// - Protocol version mismatches
243+
// - Deprecated game features
244+
// - Server maintenance notifications
245+
// - Feature flags that might affect client behavior
246+
247+
welcomePacket := WelcomePacket{
248+
Type: "welcome",
249+
ID: p.ID,
250+
Secret: p.Secret,
251+
ProtocolVersion: ProtocolVersion,
252+
}
253+
254+
// Only include warnings if there are any
255+
if len(warnings) > 0 {
256+
welcomePacket.Warnings = warnings
257+
}
258+
259+
err := p.Send(ctx, welcomePacket)
234260
if err != nil {
235261
return err
236262
}

internal/signaling/protocol-notes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
=> `{"type": "hello", "game": "GameUUID", "id?": "previousPeerID", "lobby?": "previousLobby"}`
66

77
## Server responds with:
8-
<= `{"type": "welcome", "id": "newPeerID"}`
8+
<= `{"type": "welcome", "id": "newPeerID", "secret": "peerSecret", "protocolVersion": "1.0.0", "warnings?": ["optional warning messages"]}`
99

1010
## Then the connection idles until client calls create() or join('lobby')
1111

internal/signaling/types.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import (
88
"github.com/poki/netlib/internal/signaling/stores"
99
)
1010

11+
// ProtocolVersion defines the current protocol version
12+
// This should be incremented when backwards incompatible changes are made
13+
const ProtocolVersion = "1.0.0"
14+
1115
type PingPacket struct {
1216
Type string `json:"type"`
1317
}
@@ -24,8 +28,10 @@ type HelloPacket struct {
2428
type WelcomePacket struct {
2529
Type string `json:"type"`
2630

27-
ID string `json:"id"`
28-
Secret string `json:"secret"`
31+
ID string `json:"id"`
32+
Secret string `json:"secret"`
33+
ProtocolVersion string `json:"protocolVersion"`
34+
Warnings []string `json:"warnings,omitempty"`
2935
}
3036

3137
type ListPacket struct {

internal/signaling/welcome_test.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package signaling
2+
3+
import (
4+
"encoding/json"
5+
"strings"
6+
"testing"
7+
)
8+
9+
func TestWelcomePacketStructure(t *testing.T) {
10+
// Test that WelcomePacket includes protocol version
11+
packet := WelcomePacket{
12+
Type: "welcome",
13+
ID: "test-id",
14+
Secret: "test-secret",
15+
ProtocolVersion: ProtocolVersion,
16+
Warnings: []string{"test warning"},
17+
}
18+
19+
// Marshal to JSON to verify the structure
20+
data, err := json.Marshal(packet)
21+
if err != nil {
22+
t.Fatalf("Failed to marshal WelcomePacket: %v", err)
23+
}
24+
25+
// Unmarshal back to verify structure
26+
var unmarshaled WelcomePacket
27+
err = json.Unmarshal(data, &unmarshaled)
28+
if err != nil {
29+
t.Fatalf("Failed to unmarshal WelcomePacket: %v", err)
30+
}
31+
32+
// Verify all fields are preserved
33+
if unmarshaled.Type != "welcome" {
34+
t.Errorf("Expected Type 'welcome', got %s", unmarshaled.Type)
35+
}
36+
if unmarshaled.ID != "test-id" {
37+
t.Errorf("Expected ID 'test-id', got %s", unmarshaled.ID)
38+
}
39+
if unmarshaled.Secret != "test-secret" {
40+
t.Errorf("Expected Secret 'test-secret', got %s", unmarshaled.Secret)
41+
}
42+
if unmarshaled.ProtocolVersion != ProtocolVersion {
43+
t.Errorf("Expected ProtocolVersion %s, got %s", ProtocolVersion, unmarshaled.ProtocolVersion)
44+
}
45+
if len(unmarshaled.Warnings) != 1 || unmarshaled.Warnings[0] != "test warning" {
46+
t.Errorf("Expected Warnings ['test warning'], got %v", unmarshaled.Warnings)
47+
}
48+
}
49+
50+
func TestWelcomePacketWithoutWarnings(t *testing.T) {
51+
// Test that warnings field is omitted when empty
52+
packet := WelcomePacket{
53+
Type: "welcome",
54+
ID: "test-id",
55+
Secret: "test-secret",
56+
ProtocolVersion: ProtocolVersion,
57+
}
58+
59+
// Marshal to JSON
60+
data, err := json.Marshal(packet)
61+
if err != nil {
62+
t.Fatalf("Failed to marshal WelcomePacket: %v", err)
63+
}
64+
65+
// Verify warnings field is not in JSON when empty
66+
var jsonMap map[string]interface{}
67+
err = json.Unmarshal(data, &jsonMap)
68+
if err != nil {
69+
t.Fatalf("Failed to unmarshal to map: %v", err)
70+
}
71+
72+
if _, hasWarnings := jsonMap["warnings"]; hasWarnings {
73+
t.Errorf("Warnings field should be omitted when empty, but was present in JSON: %s", string(data))
74+
}
75+
76+
// Verify protocol version is always present
77+
if _, hasProtocolVersion := jsonMap["protocolVersion"]; !hasProtocolVersion {
78+
t.Errorf("ProtocolVersion field should always be present in JSON: %s", string(data))
79+
}
80+
}
81+
82+
func TestProtocolVersionConstant(t *testing.T) {
83+
// Verify protocol version is defined and not empty
84+
if ProtocolVersion == "" {
85+
t.Error("ProtocolVersion constant should not be empty")
86+
}
87+
88+
// Verify it follows semver-like pattern (basic check)
89+
if len(ProtocolVersion) < 5 { // At minimum "1.0.0"
90+
t.Errorf("ProtocolVersion should be a proper version string, got: %s", ProtocolVersion)
91+
}
92+
}
93+
94+
func TestWelcomePacketWarningsExample(t *testing.T) {
95+
// Test how warnings could be used in practice
96+
packet := WelcomePacket{
97+
Type: "welcome",
98+
ID: "test-id",
99+
Secret: "test-secret",
100+
ProtocolVersion: ProtocolVersion,
101+
Warnings: []string{"Example warning: This feature will be deprecated in version 2.0.0"},
102+
}
103+
104+
// Marshal to JSON
105+
data, err := json.Marshal(packet)
106+
if err != nil {
107+
t.Fatalf("Failed to marshal WelcomePacket with warnings: %v", err)
108+
}
109+
110+
// Verify the JSON contains the warning
111+
jsonStr := string(data)
112+
if !strings.Contains(jsonStr, "Example warning") {
113+
t.Errorf("Expected JSON to contain warning message, got: %s", jsonStr)
114+
}
115+
116+
if !strings.Contains(jsonStr, "protocolVersion") {
117+
t.Errorf("Expected JSON to contain protocolVersion, got: %s", jsonStr)
118+
}
119+
}

lib/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ export interface WelcomePacket extends Base {
8282
type: 'welcome'
8383
id: string
8484
secret: string
85+
protocolVersion: string
86+
warnings?: string[]
8587
}
8688

8789
export interface ListPacket extends Base {

0 commit comments

Comments
 (0)