parent
3689448c90
commit
b7461ae97f
20
client.go
20
client.go
|
@ -21,6 +21,7 @@ const (
|
|||
StateDisconnected ConnState = iota
|
||||
StateConnected
|
||||
StateSessionEstablished
|
||||
StateStreamError
|
||||
)
|
||||
|
||||
// Event is a structure use to convey event changes related to client state. This
|
||||
|
@ -28,6 +29,7 @@ const (
|
|||
type Event struct {
|
||||
State ConnState
|
||||
Description string
|
||||
StreamError string
|
||||
}
|
||||
|
||||
// EventHandler is use to pass events about state of the connection to
|
||||
|
@ -49,6 +51,13 @@ func (em EventManager) updateState(state ConnState) {
|
|||
}
|
||||
}
|
||||
|
||||
func (em EventManager) streamError(error, desc string) {
|
||||
em.CurrentState = StateStreamError
|
||||
if em.Handler != nil {
|
||||
em.Handler(Event{State: em.CurrentState, StreamError: error, Description: desc})
|
||||
}
|
||||
}
|
||||
|
||||
// Client
|
||||
// ============================================================================
|
||||
|
||||
|
@ -164,8 +173,17 @@ func (c *Client) recv() (err error) {
|
|||
c.updateState(StateDisconnected)
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle stream errors
|
||||
switch packet := val.(type) {
|
||||
case StreamError:
|
||||
c.RecvChannel <- val
|
||||
close(c.RecvChannel)
|
||||
c.streamError(packet.Error.Local, packet.Text)
|
||||
return errors.New("stream error: " + packet.Error.Local)
|
||||
}
|
||||
|
||||
c.RecvChannel <- val
|
||||
val = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,12 @@ func (cm *ClientManager) Start() error {
|
|||
case StateDisconnected:
|
||||
// Reconnect on disconnection
|
||||
cm.connect()
|
||||
case StateStreamError:
|
||||
cm.Client.Disconnect()
|
||||
// Only try reconnecting if we have not been kicked by another session to avoid connection loop.
|
||||
if e.StreamError != "conflict" {
|
||||
cm.connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,8 +68,6 @@ func (cm *ClientManager) connect() error {
|
|||
// TODO: Make it possible to define logger to log disconnect and reconnection attempts
|
||||
cm.Metrics = initMetrics()
|
||||
|
||||
// TODO: Test for non recoverable errors (invalid username and password) and return an error
|
||||
// to start caller. We do not want to retry on non recoverable errors.
|
||||
if cm.Client.Session, err = cm.Client.Connect(); err != nil {
|
||||
var actualErr ConnError
|
||||
if xerrors.As(err, &actualErr) {
|
||||
|
@ -72,7 +76,7 @@ func (cm *ClientManager) connect() error {
|
|||
}
|
||||
}
|
||||
backoff.Wait()
|
||||
} else {
|
||||
} else { // We are connected, we can leave the retry loop
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ func (streamFeatureDecoder) decode(p *xml.Decoder, se xml.StartElement) (StreamF
|
|||
type StreamError struct {
|
||||
XMLName xml.Name `xml:"http://etherx.jabber.org/streams error"`
|
||||
Error xml.Name `xml:",any"`
|
||||
Text string `xml:"urn:ietf:params:xml:ns:xmpp-streams text"`
|
||||
}
|
||||
|
||||
func (StreamError) Name() string {
|
||||
|
|
Loading…
Reference in a new issue