Skip to content

Commit 322916a

Browse files
authored
fix: PreviousServer is always nil (minekube#541)
* fix: PreviousServer is always nil fixes minekube#539 closes minekube#540 - Added a `previousServer` field to `ServerPreConnectEvent` and `serverConnection` to track the server a player was previously connected to. - Updated constructors and methods to accommodate the new `previousServer` parameter, improving connection request handling and event firing. - Enhanced `createConnectionRequest` to include the previous connection for better context during server transitions. * fix: Prevent storing typed nil pointers for previousServer - Updated the handling of the previousServer field in ServerConnectedEvent and ServerPostConnectEvent to ensure it is only assigned when non-nil, preventing incorrect nil pointer storage. - This change enhances the integrity of event data during server transitions, ensuring accurate tracking of previous connections.
1 parent e423e77 commit 322916a

4 files changed

Lines changed: 52 additions & 24 deletions

File tree

pkg/edition/java/proxy/events.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -442,17 +442,18 @@ func (e *PlayerChooseInitialServerEvent) SetInitialServer(server RegisteredServe
442442

443443
// ServerPreConnectEvent is fired before the player connects to a server.
444444
type ServerPreConnectEvent struct {
445-
player Player
446-
original RegisteredServer
447-
448-
server RegisteredServer
445+
player Player
446+
original RegisteredServer
447+
server RegisteredServer
448+
previousServer RegisteredServer // nil-able
449449
}
450450

451-
func newServerPreConnectEvent(player Player, server RegisteredServer) *ServerPreConnectEvent {
451+
func newServerPreConnectEvent(player Player, server RegisteredServer, previousServer RegisteredServer) *ServerPreConnectEvent {
452452
return &ServerPreConnectEvent{
453-
player: player,
454-
original: server,
455-
server: server,
453+
player: player,
454+
original: server,
455+
server: server,
456+
previousServer: previousServer,
456457
}
457458
}
458459

@@ -489,6 +490,12 @@ func (e *ServerPreConnectEvent) Server() RegisteredServer {
489490
return e.server
490491
}
491492

493+
// PreviousServer returns the server the player was previously connected to.
494+
// May return nil if there was none!
495+
func (e *ServerPreConnectEvent) PreviousServer() RegisteredServer {
496+
return e.previousServer
497+
}
498+
492499
//
493500
//
494501
//

pkg/edition/java/proxy/server.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ type serverConnection struct {
219219
player *connectedPlayer
220220
log logr.Logger
221221

222+
previousServer *registeredServer // nil-able
223+
222224
completedJoin atomic.Bool
223225
gracefulDisconnect atomic.Bool
224226
pendingPings *lru.SyncCache[int64, time.Time]
@@ -228,11 +230,12 @@ type serverConnection struct {
228230
connPhase phase.BackendConnectionPhase
229231
}
230232

231-
func newServerConnection(server *registeredServer, player *connectedPlayer) *serverConnection {
233+
func newServerConnection(server *registeredServer, previousServer *registeredServer, player *connectedPlayer) *serverConnection {
232234
return &serverConnection{
233-
server: server,
234-
player: player,
235-
pendingPings: lru.NewSync[int64, time.Time](lru.WithCapacity(5)),
235+
server: server,
236+
player: player,
237+
previousServer: previousServer,
238+
pendingPings: lru.NewSync[int64, time.Time](lru.WithCapacity(5)),
236239
log: player.log.WithName("serverConn").WithValues(
237240
"serverName", server.info.Name(),
238241
"serverAddr", server.info.Addr()),

pkg/edition/java/proxy/session_backend_transition.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ func (b *backendTransitionSessionHandler) handleJoinGame(pc *proto.PacketContext
163163
if !ok {
164164
return
165165
}
166+
previousServer := b.serverConn.previousServer
166167

167168
failResult := func(format string, a ...any) {
168169
err := fmt.Errorf(format, a...)
@@ -173,9 +174,7 @@ func (b *backendTransitionSessionHandler) handleJoinGame(pc *proto.PacketContext
173174

174175
b.serverConn.player.mu.Lock()
175176
existingConn := b.serverConn.player.connectedServer_
176-
var previousServer RegisteredServer
177177
if existingConn != nil {
178-
previousServer = existingConn.server
179178
// Shut down the existing server connection.
180179
b.serverConn.player.connectedServer_ = nil
181180
b.serverConn.player.mu.Unlock()
@@ -202,9 +201,14 @@ func (b *backendTransitionSessionHandler) handleJoinGame(pc *proto.PacketContext
202201
connectedEvent := &ServerConnectedEvent{
203202
player: b.serverConn.player,
204203
server: b.serverConn.server,
205-
previousServer: previousServer, // nil-able
206204
entityID: p.EntityID,
207205
}
206+
// Assign previousServer only if non-nil to prevent storing a typed nil pointer,
207+
// which would incorrectly make connectedEvent.previousServer not equal to nil,
208+
// as the previousServer field in ServerConnectedEvent is an interface type.
209+
if previousServer != nil {
210+
connectedEvent.previousServer = previousServer
211+
}
208212
// Fire event in same goroutine as we don't want to read
209213
// more incoming packets while we process the JoinGame!
210214
b.eventMgr.Fire(connectedEvent)
@@ -294,7 +298,13 @@ func (b *backendTransitionSessionHandler) handleJoinGame(pc *proto.PacketContext
294298
}
295299

296300
// We're done!
297-
postConnectEvent := newServerPostConnectEvent(b.serverConn.player, previousServer)
301+
postConnectEvent := newServerPostConnectEvent(b.serverConn.player, nil)
302+
// Assign previousServer only if non-nil to prevent storing a typed nil pointer,
303+
// which would incorrectly make postConnectEvent.previousServer not equal to nil,
304+
// as the previousServer field in ServerPostConnectEvent is an interface type.
305+
if previousServer != nil {
306+
postConnectEvent.previousServer = previousServer
307+
}
298308
b.eventMgr.Fire(postConnectEvent)
299309
b.requestCtx.result(plainConnectionResult(SuccessConnectionStatus, b.serverConn.server), nil)
300310
}

pkg/edition/java/proxy/switch.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,20 @@ func (p *connectedPlayer) CreateConnectionRequest(server RegisteredServer) Conne
9797
}
9898

9999
func (p *connectedPlayer) createConnectionRequest(server RegisteredServer) *connectionRequest {
100-
return &connectionRequest{server: server, player: p}
100+
return p.createConnectionRequestWith(server, p.connectedServer())
101+
}
102+
func (p *connectedPlayer) createConnectionRequestWith(server RegisteredServer, previousConn *serverConnection) *connectionRequest {
103+
var previousServer *registeredServer
104+
if previousConn != nil {
105+
previousServer = previousConn.server
106+
}
107+
return &connectionRequest{server: server, player: p, previousServer: previousServer}
101108
}
102109

103110
type connectionRequest struct {
104-
server RegisteredServer // the target server to connect to
105-
player *connectedPlayer // the player to connect to the server
111+
server RegisteredServer // the target server to connect to
112+
player *connectedPlayer // the player to connect to the server
113+
previousServer *registeredServer // nil-able
106114
}
107115

108116
func (c *connectionRequest) connect(ctx context.Context) (*connectionResult, error) {
@@ -225,7 +233,7 @@ func (p *connectedPlayer) handleKickEvent(e *KickedFromServerEvent, friendlyReas
225233

226234
// Make sure we clear the current connected server as the connection is invalid.
227235
p.mu.Lock()
228-
previouslyConnected := p.connectedServer_ != nil
236+
previousConnection := p.connectedServer_
229237
if kickedFromCurrent {
230238
p.connectedServer_ = nil
231239
}
@@ -242,7 +250,7 @@ func (p *connectedPlayer) handleKickEvent(e *KickedFromServerEvent, friendlyReas
242250
case *RedirectPlayerKickResult:
243251
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(p.config().ConnectionTimeout)*time.Millisecond)
244252
defer cancel()
245-
redirect, err := p.createConnectionRequest(result.Server).connect(ctx)
253+
redirect, err := p.createConnectionRequestWith(result.Server, previousConnection).connect(ctx)
246254
if err != nil {
247255
p.handleConnectionErr(result.Server, err, true)
248256
return
@@ -275,7 +283,7 @@ func (p *connectedPlayer) handleKickEvent(e *KickedFromServerEvent, friendlyReas
275283
_ = p.SendMessage(requestedMessage)
276284
}
277285
case *NotifyKickResult:
278-
if e.KickedDuringServerConnect() && previouslyConnected {
286+
if e.KickedDuringServerConnect() && previousConnection != nil {
279287
_ = p.SendMessage(result.Message)
280288
} else {
281289
p.Disconnect(result.Message)
@@ -367,7 +375,7 @@ func (c *connectionRequest) internalConnect(ctx context.Context) (result *connec
367375
return plainConnectionResult(status, c.server), nil
368376
}
369377

370-
connectEvent := newServerPreConnectEvent(c.player, c.server)
378+
connectEvent := newServerPreConnectEvent(c.player, c.server, c.previousServer)
371379
c.event().Fire(connectEvent)
372380
if !connectEvent.Allowed() {
373381
return plainConnectionResult(CanceledConnectionStatus, c.server), nil
@@ -387,7 +395,7 @@ func (c *connectionRequest) internalConnect(ctx context.Context) (result *connec
387395
return plainConnectionResult(CanceledConnectionStatus, newDest), nil
388396
}
389397

390-
conn := newServerConnection(server, c.player)
398+
conn := newServerConnection(server, c.previousServer, c.player)
391399
c.player.setInFlightConnection(conn)
392400
defer c.resetIfInFlightIs(conn)
393401
return conn.connect(ctx)

0 commit comments

Comments
 (0)