Changeset 168 in code for trunk/downstream.go


Ignore:
Timestamp:
Mar 27, 2020, 6:17:58 PM (5 years ago)
Author:
contact
Message:

Nuke user.lock

Split user.register into two functions, one to make sure the user is
authenticated, the other to send our current state. This allows to get
rid of data races by doing the second part in the user goroutine.

Closes: https://todo.sr.ht/~emersion/soju/22

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/downstream.go

    r167 r168  
    7272        username    string
    7373        rawUsername string
     74        networkName string
    7475        realname    string
    7576        hostname    string
     
    583584}
    584585
    585 func (dc *downstreamConn) setNetwork(networkName string) error {
    586         if networkName == "" {
     586func (dc *downstreamConn) authenticate(username, password string) error {
     587        username, networkName := unmarshalUsername(username)
     588
     589        u := dc.srv.getUser(username)
     590        if u == nil {
     591                dc.logger.Printf("failed authentication for %q: unknown username", username)
     592                return errAuthFailed
     593        }
     594
     595        err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
     596        if err != nil {
     597                dc.logger.Printf("failed authentication for %q: %v", username, err)
     598                return errAuthFailed
     599        }
     600
     601        dc.user = u
     602        dc.networkName = networkName
     603        return nil
     604}
     605
     606func (dc *downstreamConn) register() error {
     607        if dc.registered {
     608                return fmt.Errorf("tried to register twice")
     609        }
     610
     611        password := dc.password
     612        dc.password = ""
     613        if dc.user == nil {
     614                if err := dc.authenticate(dc.rawUsername, password); err != nil {
     615                        return err
     616                }
     617        }
     618
     619        if dc.networkName == "" {
     620                _, dc.networkName = unmarshalUsername(dc.rawUsername)
     621        }
     622
     623        dc.registered = true
     624        dc.username = dc.user.Username
     625        dc.logger.Printf("registration complete for user %q", dc.username)
     626        return nil
     627}
     628
     629func (dc *downstreamConn) loadNetwork() error {
     630        if dc.networkName == "" {
    587631                return nil
    588632        }
    589633
    590         network := dc.user.getNetwork(networkName)
     634        network := dc.user.getNetwork(dc.networkName)
    591635        if network == nil {
    592                 addr := networkName
     636                addr := dc.networkName
    593637                if !strings.ContainsRune(addr, ':') {
    594638                        addr = addr + ":6697"
     
    600644                        return ircError{&irc.Message{
    601645                                Command: irc.ERR_PASSWDMISMATCH,
    602                                 Params:  []string{"*", fmt.Sprintf("Failed to connect to %q", networkName)},
     646                                Params:  []string{"*", fmt.Sprintf("Failed to connect to %q", dc.networkName)},
    603647                        }}
    604648                }
    605649
    606                 dc.logger.Printf("auto-saving network %q", networkName)
     650                dc.logger.Printf("auto-saving network %q", dc.networkName)
    607651                var err error
    608652                network, err = dc.user.createNetwork(&Network{
    609                         Addr: networkName,
     653                        Addr: dc.networkName,
    610654                        Nick: dc.nick,
    611655                })
     
    619663}
    620664
    621 func (dc *downstreamConn) authenticate(username, password string) error {
    622         username, networkName := unmarshalUsername(username)
    623 
    624         u := dc.srv.getUser(username)
    625         if u == nil {
    626                 dc.logger.Printf("failed authentication for %q: unknown username", username)
    627                 return errAuthFailed
    628         }
    629 
    630         err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
    631         if err != nil {
    632                 dc.logger.Printf("failed authentication for %q: %v", username, err)
    633                 return errAuthFailed
    634         }
    635 
    636         dc.user = u
    637 
    638         return dc.setNetwork(networkName)
    639 }
    640 
    641 func (dc *downstreamConn) register() error {
    642         password := dc.password
    643         dc.password = ""
    644         if dc.user == nil {
    645                 if err := dc.authenticate(dc.rawUsername, password); err != nil {
    646                         return err
    647                 }
    648         } else if dc.network == nil {
    649                 _, networkName := unmarshalUsername(dc.rawUsername)
    650                 if err := dc.setNetwork(networkName); err != nil {
    651                         return err
    652                 }
    653         }
    654 
    655         dc.registered = true
    656         dc.username = dc.user.Username
    657         dc.logger.Printf("registration complete for user %q", dc.username)
    658 
    659         dc.user.lock.Lock()
     665func (dc *downstreamConn) welcome() error {
     666        if dc.user == nil || !dc.registered {
     667                panic("tried to welcome an unregistered connection")
     668        }
     669
     670        // TODO: doing this might take some time. We should do it in dc.register
     671        // instead, but we'll potentially be adding a new network and this must be
     672        // done in the user goroutine.
     673        if err := dc.loadNetwork(); err != nil {
     674                return err
     675        }
     676
    660677        firstDownstream := len(dc.user.downstreamConns) == 0
    661         dc.user.lock.Unlock()
    662678
    663679        dc.SendMessage(&irc.Message{
Note: See TracChangeset for help on using the changeset viewer.