diff options
Diffstat (limited to 'internal/net/server.go')
| -rw-r--r-- | internal/net/server.go | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/internal/net/server.go b/internal/net/server.go index 66d31e3..78eceb8 100644 --- a/internal/net/server.go +++ b/internal/net/server.go @@ -57,7 +57,7 @@ const ( type Session struct { Conn Conn - State SessionState + state atomic.Int32 Account *player.Account Player *player.Player PendingChar string @@ -116,6 +116,16 @@ type Session struct { seq uint64 } +// State returns the session's current protocol state. Safe on any +// goroutine: the owner writes the state while connection goroutines read +// it in the HandleSessionOnOwner dispatch, so a plain field was a data +// race (reproduced by the logout-countdown input regression test). +func (sess *Session) State() SessionState { return SessionState(sess.state.Load()) } + +// SetState transitions the session to a new protocol state. +// Owner goroutine only. +func (sess *Session) SetState(s SessionState) { sess.state.Store(int32(s)) } + // SetAuthName records the account name offered for password entry. // Owner goroutine only. func (sess *Session) SetAuthName(name string) { @@ -598,9 +608,9 @@ func (s *Server) serveTelnet() { return } sess := &Session{ - Conn: newTCPConn(conn), - State: StateAccountName, + Conn: newTCPConn(conn), } + sess.SetState(StateAccountName) // Queued writes like the websocket transport: a dedicated writer // goroutine performs the I/O with per-message deadlines, so a slow // or stalled telnet client can never block game code. @@ -621,9 +631,9 @@ func (s *Server) serveTelnetTLS() { return } sess := &Session{ - Conn: newTCPConn(conn), - State: StateAccountName, + Conn: newTCPConn(conn), } + sess.SetState(StateAccountName) sess.StartWriter() s.hub.Add(sess) go s.handleSession(sess, s.handler) |
