diff options
author | pg9182 <96569817+pg9182@users.noreply.github.com> | 2022-10-15 08:17:04 -0400 |
---|---|---|
committer | pg9182 <96569817+pg9182@users.noreply.github.com> | 2022-10-15 08:17:04 -0400 |
commit | e237dad252642b51c96cc50206a0e8962cbcfddb (patch) | |
tree | d3486fd114a98571a70263f651a31a8d0e3bdd7d /pkg/api/api0/serverlist.go | |
parent | 28c0e01c8e54907a3c1bd8efc829ef47bfbccd7c (diff) | |
download | Atlas-e237dad252642b51c96cc50206a0e8962cbcfddb.tar.gz Atlas-e237dad252642b51c96cc50206a0e8962cbcfddb.zip |
pkg/api/api0: Refactor server verification process
* Add an additional pending state for unverified servers.
* This allows verification to be done without knowing ahead of time
if a server is going to be created or updated.
* Also moves more logic into the serverlist.
Diffstat (limited to 'pkg/api/api0/serverlist.go')
-rw-r--r-- | pkg/api/api0/serverlist.go | 68 |
1 files changed, 54 insertions, 14 deletions
diff --git a/pkg/api/api0/serverlist.go b/pkg/api/api0/serverlist.go index ca57280..3248465 100644 --- a/pkg/api/api0/serverlist.go +++ b/pkg/api/api0/serverlist.go @@ -16,11 +16,12 @@ import ( // ServerList stores information about registered game servers. It does not do // any validation of its own except for ensuring ID and addr/port are unique, -// and filtering dead servers. +// and filtering dead/unverified/ghost servers. type ServerList struct { // config (must not be changed after the ServerList is used) - deadTime time.Duration - ghostTime time.Duration + verifyTime time.Duration + deadTime time.Duration + ghostTime time.Duration // servers mu sync.RWMutex // must be held while modifying the order and maps below @@ -56,11 +57,13 @@ type Server struct { AuthPort uint16 Password string // blank for none - LastHeartbeat time.Time - PlayerCount int - MaxPlayers int - Map string - Playlist string + VerificationDeadline time.Time // zero once verified + LastHeartbeat time.Time + + PlayerCount int + MaxPlayers int + Map string + Playlist string ServerAuthToken string // used for authenticating the masterserver to the gameserver authserver @@ -111,6 +114,9 @@ type ServerListLimit struct { // NewServerList initializes a new server list. // +// verifyTime is the amount of time a server has to complete verification after +// it is created. +// // deadTime is the time since the last heartbeat after which a server is // considered dead. A dead server will not be listed on the server list. It must // be >= verifyTime if nonzero. @@ -122,9 +128,15 @@ type ServerListLimit struct { // // If both are nonzero, they must be positive, and deadTime must be less than // ghostTime. Otherwise, NewServerList will panic. -func NewServerList(deadTime, ghostTime time.Duration) *ServerList { +func NewServerList(deadTime, ghostTime, verifyTime time.Duration) *ServerList { + if verifyTime < 0 { + panic("api0: serverlist: verifyTime must be >= 0") + } if deadTime < 0 { - panic("api0: serverlist: deadTime must be >= 0") + panic("api0: serverlist: deadTime must be >= verifyTime") + } + if deadTime != 0 && verifyTime != 0 && deadTime <= verifyTime { + panic("api0: server") } if ghostTime < 0 { panic("api0: serverlist: ghostTime must be >= 0") @@ -133,8 +145,9 @@ func NewServerList(deadTime, ghostTime time.Duration) *ServerList { panic("api0: serverlist: deadTime must be <= ghostTime") } return &ServerList{ - deadTime: deadTime, - ghostTime: ghostTime, + verifyTime: verifyTime, + deadTime: deadTime, + ghostTime: ghostTime, } } @@ -416,6 +429,8 @@ var ( // non-nil) (reviving it if necessary), and if that fails, then attempts to // create/replace a server by the gameserver ip/port instead (if c is non-nil) // while following the limits in l. It returns a copy of the resulting Server. +// If the resulting server's VerificationDeadline is nonzero, the server must be +// verified. // // If the returned error is non-nil, it will either be an unavoidable internal // error (e.g, failure to get random data for the server id) or one of the @@ -427,8 +442,8 @@ var ( // - ErrServerListLimitExceeded - if adding the server would exceed server limits (if c and l) // // When creating a server using the values from c: c.Order, c.ID, -// c.ServerAuthToken, and c.LastHeartbeat will be generated by this function -// (any existing value is ignored). +// c.ServerAuthToken, c.VerificationDeadline, and c.LastHeartbeat will be +// generated by this function (any existing value is ignored). func (s *ServerList) ServerHybridUpdatePut(u *ServerUpdate, c *Server, l ServerListLimit) (*Server, error) { t := s.now() @@ -588,6 +603,11 @@ func (s *ServerList) ServerHybridUpdatePut(u *ServerUpdate, c *Server, l ServerL // set the heartbeat time to the current time nsrv.LastHeartbeat = t + // set the verification deadline + if s.verifyTime != 0 { + nsrv.VerificationDeadline = t.Add(s.verifyTime) + } + // remove the existing server so we can add the new one if toReplace != nil { s.freeServer(toReplace) @@ -612,6 +632,20 @@ func (s *ServerList) ServerHybridUpdatePut(u *ServerUpdate, c *Server, l ServerL return nil, ErrServerListUpdateServerDead } +// VerifyServer marks the server with the provided id as verified. If it does +// not exist, false is returned. +func (s *ServerList) VerifyServer(id string) bool { + // take a write lock on the server list + s.mu.Lock() + defer s.mu.Unlock() + + if srv, exists := s.servers2[id]; exists { + srv.VerificationDeadline = time.Time{} + return true + } + return false +} + // ReapServers deletes dead servers from memory. func (s *ServerList) ReapServers() { t := s.now() @@ -668,6 +702,12 @@ func (s *ServerList) serverState(x *Server, t time.Time) serverListState { if x == nil { return serverListStateGone } + if !x.VerificationDeadline.IsZero() { + if t.After(x.VerificationDeadline) { + return serverListStateGone + } + return serverListStatePending + } d := t.Sub(x.LastHeartbeat) if s.deadTime == 0 || d < s.deadTime { |