Prevent race condition when using altHostname (#946)
Fixes #740 by preventing the slower connection from returning a value via goroutine. This prevent the 401 auth errors that break loading data from the api after the first connection.
This commit is contained in:
+28
-12
@@ -237,32 +237,48 @@ func (s *ServerManager) connect(connection ServerConnection, password string) (m
|
|||||||
}
|
}
|
||||||
s.checkSetInsecureSkipVerify(connection.SkipSSLVerify, altCli.(*subsonicMP.SubsonicServer).Client.Client)
|
s.checkSetInsecureSkipVerify(connection.SkipSSLVerify, altCli.(*subsonicMP.SubsonicServer).Client.Client)
|
||||||
}
|
}
|
||||||
var authError error
|
|
||||||
pingChan := make(chan bool, 2) // false for primary hostname, true for alternate
|
// struct to return hostname type in isAlt and connection success on err
|
||||||
pingFunc := func(delay time.Duration, cli mediaprovider.Server, val bool) {
|
type pingResult struct {
|
||||||
<-time.After(delay)
|
isAlt bool
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
pingChan := make(chan pingResult, 2)
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
pingFunc := func(delay time.Duration, cli mediaprovider.Server, isAlt bool) {
|
||||||
|
// delay before connecting or exit if already cancelled
|
||||||
|
select {
|
||||||
|
case <-time.After(delay):
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
resp := cli.Login(connection.Username, password)
|
resp := cli.Login(connection.Username, password)
|
||||||
if resp.Error != nil && !resp.IsAuthError {
|
if resp.Error != nil && !resp.IsAuthError {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
authError = resp.Error
|
|
||||||
pingChan <- val // reached the server
|
// return result or exit if already cancelled
|
||||||
|
select {
|
||||||
|
case pingChan <- pingResult{isAlt: isAlt, err: resp.Error}:
|
||||||
|
case <-ctx.Done():
|
||||||
|
}
|
||||||
}
|
}
|
||||||
go pingFunc(0, cli, false)
|
go pingFunc(0, cli, false)
|
||||||
if connection.AltHostname != "" {
|
if connection.AltHostname != "" {
|
||||||
go pingFunc(333*time.Millisecond, altCli, true) // give primary hostname ping a head start
|
go pingFunc(333*time.Millisecond, altCli, true) // give primary hostname ping a head start
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, ErrUnreachable
|
return nil, ErrUnreachable
|
||||||
case altPing := <-pingChan:
|
case res := <-pingChan:
|
||||||
if altPing {
|
if res.isAlt {
|
||||||
return altCli, authError
|
return altCli, res.err
|
||||||
}
|
}
|
||||||
return cli, authError
|
return cli, res.err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user