Cache the PROTOCOLINFO response if it was issued before AUTHENTICATE.

Control clients get one PROTOCOLINFO before they must issue an
AUTHCHALLENGE or AUTHENTICATE, and the Authenticate() implementation
uses PROTOCOLINFO.  This allows users to call ProtocolInfo() before
Authenticate() without mysterious failures.
This commit is contained in:
Yawning Angel 2015-03-22 04:21:23 +00:00
parent b19f84d674
commit 8736a9cd73
3 changed files with 12 additions and 2 deletions

View File

@ -132,7 +132,6 @@ func (c *Conn) Authenticate(password string) error {
_, err = c.Request("%s %s", cmdAuthenticate, passwordStr) _, err = c.Request("%s %s", cmdAuthenticate, passwordStr)
c.isAuthenticated = err == nil c.isAuthenticated = err == nil
return err return err
} else {
return newProtocolError("no supported authentication methods")
} }
return newProtocolError("no supported authentication methods")
} }

View File

@ -23,6 +23,13 @@ type ProtocolInfo struct {
// ProtocolInfo issues a PROTOCOLINFO command and returns the parsed response. // ProtocolInfo issues a PROTOCOLINFO command and returns the parsed response.
func (c *Conn) ProtocolInfo() (*ProtocolInfo, error) { func (c *Conn) ProtocolInfo() (*ProtocolInfo, error) {
// In the pre-authentication state, only one PROTOCOLINFO command
// may be issued. Cache the value returned so that subsequent
// calls continue to work.
if !c.isAuthenticated && c.cachedPI != nil {
return c.cachedPI, nil
}
resp, err := c.Request("PROTOCOLINFO") resp, err := c.Request("PROTOCOLINFO")
if err != nil { if err != nil {
return nil, err return nil, err
@ -79,5 +86,8 @@ func (c *Conn) ProtocolInfo() (*ProtocolInfo, error) {
default: // MUST ignore unsupported InfoLines. default: // MUST ignore unsupported InfoLines.
} }
} }
if !c.isAuthenticated {
c.cachedPI = pi
}
return pi, nil return pi, nil
} }

View File

@ -32,6 +32,7 @@ type Conn struct {
conn *textproto.Conn conn *textproto.Conn
isAuthenticated bool isAuthenticated bool
debugLog bool debugLog bool
cachedPI *ProtocolInfo
asyncReaderLock sync.Mutex asyncReaderLock sync.Mutex
asyncReaderRunning bool asyncReaderRunning bool