]> git.r.bdr.sh - rbdr/mobius/blobdiff - hotline/server.go
Refactor and backfill tests for tracker listing
[rbdr/mobius] / hotline / server.go
index f3574dea99e0b047b6ab78776311c0b850269803..392c8f31ac47364f356f77614585753d260d048d 100644 (file)
@@ -43,12 +43,10 @@ const (
 var nostalgiaVersion = []byte{0, 0, 2, 0x2c} // version ID used by the Nostalgia client
 
 type Server struct {
 var nostalgiaVersion = []byte{0, 0, 2, 0x2c} // version ID used by the Nostalgia client
 
 type Server struct {
-       Port         int
-       Accounts     map[string]*Account
-       Agreement    []byte
-       Clients      map[uint16]*ClientConn
-       ThreadedNews *ThreadedNews
-
+       Port          int
+       Accounts      map[string]*Account
+       Agreement     []byte
+       Clients       map[uint16]*ClientConn
        fileTransfers map[[4]byte]*FileTransfer
 
        Config        *Config
        fileTransfers map[[4]byte]*FileTransfer
 
        Config        *Config
@@ -64,6 +62,9 @@ type Server struct {
        outbox chan Transaction
        mux    sync.Mutex
 
        outbox chan Transaction
        mux    sync.Mutex
 
+       threadedNewsMux sync.Mutex
+       ThreadedNews    *ThreadedNews
+
        flatNewsMux sync.Mutex
        FlatNews    []byte
 
        flatNewsMux sync.Mutex
        FlatNews    []byte
 
@@ -342,14 +343,14 @@ func (s *Server) writeBanList() error {
 }
 
 func (s *Server) writeThreadedNews() error {
 }
 
 func (s *Server) writeThreadedNews() error {
-       s.mux.Lock()
-       defer s.mux.Unlock()
+       s.threadedNewsMux.Lock()
+       defer s.threadedNewsMux.Unlock()
 
        out, err := yaml.Marshal(s.ThreadedNews)
        if err != nil {
                return err
        }
 
        out, err := yaml.Marshal(s.ThreadedNews)
        if err != nil {
                return err
        }
-       err = ioutil.WriteFile(
+       err = s.FS.WriteFile(
                filepath.Join(s.ConfigDir, "ThreadedNews.yaml"),
                out,
                0666,
                filepath.Join(s.ConfigDir, "ThreadedNews.yaml"),
                out,
                0666,
@@ -392,7 +393,7 @@ func (s *Server) NewClientConn(conn io.ReadWriteCloser, remoteAddr string) *Clie
 }
 
 // NewUser creates a new user account entry in the server map and config file
 }
 
 // NewUser creates a new user account entry in the server map and config file
-func (s *Server) NewUser(login, name, password string, access []byte) error {
+func (s *Server) NewUser(login, name, password string, access accessBitmap) error {
        s.mux.Lock()
        defer s.mux.Unlock()
 
        s.mux.Lock()
        defer s.mux.Unlock()
 
@@ -400,7 +401,7 @@ func (s *Server) NewUser(login, name, password string, access []byte) error {
                Login:    login,
                Name:     name,
                Password: hashAndSalt([]byte(password)),
                Login:    login,
                Name:     name,
                Password: hashAndSalt([]byte(password)),
-               Access:   &access,
+               Access:   access,
        }
        out, err := yaml.Marshal(&account)
        if err != nil {
        }
        out, err := yaml.Marshal(&account)
        if err != nil {
@@ -411,7 +412,7 @@ func (s *Server) NewUser(login, name, password string, access []byte) error {
        return s.FS.WriteFile(filepath.Join(s.ConfigDir, "Users", login+".yaml"), out, 0666)
 }
 
        return s.FS.WriteFile(filepath.Join(s.ConfigDir, "Users", login+".yaml"), out, 0666)
 }
 
-func (s *Server) UpdateUser(login, newLogin, name, password string, access []byte) error {
+func (s *Server) UpdateUser(login, newLogin, name, password string, access accessBitmap) error {
        s.mux.Lock()
        defer s.mux.Unlock()
 
        s.mux.Lock()
        defer s.mux.Unlock()
 
@@ -426,7 +427,7 @@ func (s *Server) UpdateUser(login, newLogin, name, password string, access []byt
        }
 
        account := s.Accounts[newLogin]
        }
 
        account := s.Accounts[newLogin]
-       account.Access = &access
+       account.Access = access
        account.Name = name
        account.Password = password
 
        account.Name = name
        account.Password = password
 
@@ -651,11 +652,16 @@ func (s *Server) handleNewConnection(ctx context.Context, rwc io.ReadWriteCloser
        )
 
        // Send user access privs so client UI knows how to behave
        )
 
        // Send user access privs so client UI knows how to behave
-       c.Server.outbox <- *NewTransaction(tranUserAccess, c.ID, NewField(fieldUserAccess, *c.Account.Access))
+       c.Server.outbox <- *NewTransaction(tranUserAccess, c.ID, NewField(fieldUserAccess, c.Account.Access[:]))
 
 
-       // Users with accessNoAgreement do not receive the server agreement on login
+       // Accounts with accessNoAgreement do not receive the server agreement on login.  The behavior is different between
+       // client versions.  For 1.2.3 client, we do not send tranShowAgreement.  For other client versions, we send
+       // tranShowAgreement but with the NoServerAgreement field set to 1.
        if c.Authorize(accessNoAgreement) {
        if c.Authorize(accessNoAgreement) {
-               c.Server.outbox <- *NewTransaction(tranShowAgreement, c.ID, NewField(fieldNoServerAgreement, []byte{1}))
+               // If client version is nil, then the client uses the 1.2.3 login behavior
+               if c.Version != nil {
+                       c.Server.outbox <- *NewTransaction(tranShowAgreement, c.ID, NewField(fieldNoServerAgreement, []byte{1}))
+               }
        } else {
                c.Server.outbox <- *NewTransaction(tranShowAgreement, c.ID, NewField(fieldData, s.Agreement))
        }
        } else {
                c.Server.outbox <- *NewTransaction(tranShowAgreement, c.ID, NewField(fieldData, s.Agreement))
        }
@@ -664,7 +670,7 @@ func (s *Server) handleNewConnection(ctx context.Context, rwc io.ReadWriteCloser
        if c.Version == nil || bytes.Equal(c.Version, nostalgiaVersion) {
                c.Agreed = true
                c.logger = c.logger.With("name", string(c.UserName))
        if c.Version == nil || bytes.Equal(c.Version, nostalgiaVersion) {
                c.Agreed = true
                c.logger = c.logger.With("name", string(c.UserName))
-               c.logger.Infow("Login successful", "clientVersion", fmt.Sprintf("%x", c.Version))
+               c.logger.Infow("Login successful", "clientVersion", fmt.Sprintf("%v", func() int { i, _ := byteToInt(c.Version); return i }()))
 
                for _, t := range c.notifyOthers(
                        *NewTransaction(
 
                for _, t := range c.notifyOthers(
                        *NewTransaction(