parent
3689448c90
commit
b7461ae97f
20
client.go
20
client.go
|
@ -21,6 +21,7 @@ const (
|
||||||
StateDisconnected ConnState = iota
|
StateDisconnected ConnState = iota
|
||||||
StateConnected
|
StateConnected
|
||||||
StateSessionEstablished
|
StateSessionEstablished
|
||||||
|
StateStreamError
|
||||||
)
|
)
|
||||||
|
|
||||||
// Event is a structure use to convey event changes related to client state. This
|
// Event is a structure use to convey event changes related to client state. This
|
||||||
|
@ -28,6 +29,7 @@ const (
|
||||||
type Event struct {
|
type Event struct {
|
||||||
State ConnState
|
State ConnState
|
||||||
Description string
|
Description string
|
||||||
|
StreamError string
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventHandler is use to pass events about state of the connection to
|
// 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
|
// Client
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
@ -164,8 +173,17 @@ func (c *Client) recv() (err error) {
|
||||||
c.updateState(StateDisconnected)
|
c.updateState(StateDisconnected)
|
||||||
return err
|
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
|
c.RecvChannel <- val
|
||||||
val = nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,12 @@ func (cm *ClientManager) Start() error {
|
||||||
case StateDisconnected:
|
case StateDisconnected:
|
||||||
// Reconnect on disconnection
|
// Reconnect on disconnection
|
||||||
cm.connect()
|
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
|
// TODO: Make it possible to define logger to log disconnect and reconnection attempts
|
||||||
cm.Metrics = initMetrics()
|
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 {
|
if cm.Client.Session, err = cm.Client.Connect(); err != nil {
|
||||||
var actualErr ConnError
|
var actualErr ConnError
|
||||||
if xerrors.As(err, &actualErr) {
|
if xerrors.As(err, &actualErr) {
|
||||||
|
@ -72,7 +76,7 @@ func (cm *ClientManager) connect() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
backoff.Wait()
|
backoff.Wait()
|
||||||
} else {
|
} else { // We are connected, we can leave the retry loop
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ func (streamFeatureDecoder) decode(p *xml.Decoder, se xml.StartElement) (StreamF
|
||||||
type StreamError struct {
|
type StreamError struct {
|
||||||
XMLName xml.Name `xml:"http://etherx.jabber.org/streams error"`
|
XMLName xml.Name `xml:"http://etherx.jabber.org/streams error"`
|
||||||
Error xml.Name `xml:",any"`
|
Error xml.Name `xml:",any"`
|
||||||
|
Text string `xml:"urn:ietf:params:xml:ns:xmpp-streams text"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (StreamError) Name() string {
|
func (StreamError) Name() string {
|
||||||
|
|
Loading…
Reference in a new issue