parent
47976624c9
commit
6aa1e668ee
|
@ -23,6 +23,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190908185732-236ed259b199/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190908185732-236ed259b199/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
@ -102,4 +103,5 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
gotest.tools/gotestsum v0.3.5/go.mod h1:Mnf3e5FUzXbkCfynWBGOwLssY7gTQgCHObK9tMpAriY=
|
gotest.tools/gotestsum v0.3.5/go.mod h1:Mnf3e5FUzXbkCfynWBGOwLssY7gTQgCHObK9tMpAriY=
|
||||||
mvdan.cc/sh v2.6.4+incompatible/go.mod h1:IeeQbZq+x2SUGBensq/jge5lLQbS3XT2ktyp3wrt4x8=
|
mvdan.cc/sh v2.6.4+incompatible/go.mod h1:IeeQbZq+x2SUGBensq/jge5lLQbS3XT2ktyp3wrt4x8=
|
||||||
|
nhooyr.io/websocket v1.6.5 h1:8TzpkldRfefda5JST+CnOH135bzVPz5uzfn/AF+gVKg=
|
||||||
nhooyr.io/websocket v1.6.5/go.mod h1:F259lAzPRAH0htX2y3ehpJe09ih1aSHN7udWki1defY=
|
nhooyr.io/websocket v1.6.5/go.mod h1:F259lAzPRAH0htX2y3ehpJe09ih1aSHN7udWki1defY=
|
||||||
|
|
3
_examples/muc_bot/README.md
Normal file
3
_examples/muc_bot/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# XMPP Multi-User (MUC) chat bot example
|
||||||
|
|
||||||
|
This code shows how to build a simple basic XMPP Multi-User chat bot using Fluux Go XMPP library.
|
|
@ -25,6 +25,7 @@ const (
|
||||||
StateConnected
|
StateConnected
|
||||||
StateSessionEstablished
|
StateSessionEstablished
|
||||||
StateStreamError
|
StateStreamError
|
||||||
|
StatePermanentError
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
||||||
|
|
13
component.go
13
component.go
|
@ -64,6 +64,7 @@ func (c *Component) Connect() error {
|
||||||
var state SMState
|
var state SMState
|
||||||
return c.Resume(state)
|
return c.Resume(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Component) Resume(sm SMState) error {
|
func (c *Component) Resume(sm SMState) error {
|
||||||
var err error
|
var err error
|
||||||
var streamId string
|
var streamId string
|
||||||
|
@ -72,13 +73,13 @@ func (c *Component) Resume(sm SMState) error {
|
||||||
}
|
}
|
||||||
c.transport, err = NewComponentTransport(c.ComponentOptions.TransportConfiguration)
|
c.transport, err = NewComponentTransport(c.ComponentOptions.TransportConfiguration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.updateState(StateStreamError)
|
c.updateState(StatePermanentError)
|
||||||
return err
|
return NewConnError(err, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if streamId, err = c.transport.Connect(); err != nil {
|
if streamId, err = c.transport.Connect(); err != nil {
|
||||||
c.updateState(StateStreamError)
|
c.updateState(StatePermanentError)
|
||||||
return err
|
return NewConnError(err, true)
|
||||||
}
|
}
|
||||||
c.updateState(StateConnected)
|
c.updateState(StateConnected)
|
||||||
|
|
||||||
|
@ -91,7 +92,7 @@ func (c *Component) Resume(sm SMState) error {
|
||||||
// Check server response for authentication
|
// Check server response for authentication
|
||||||
val, err := stanza.NextPacket(c.decoder)
|
val, err := stanza.NextPacket(c.decoder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.updateState(StateDisconnected)
|
c.updateState(StatePermanentError)
|
||||||
return NewConnError(err, true)
|
return NewConnError(err, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +106,7 @@ func (c *Component) Resume(sm SMState) error {
|
||||||
go c.recv()
|
go c.recv()
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
c.updateState(StateStreamError)
|
c.updateState(StatePermanentError)
|
||||||
return NewConnError(errors.New("expecting handshake result, got "+v.Name()), true)
|
return NewConnError(errors.New("expecting handshake result, got "+v.Name()), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,9 +86,12 @@ func (sm *StreamManager) Run() error {
|
||||||
case StateStreamError:
|
case StateStreamError:
|
||||||
sm.client.Disconnect()
|
sm.client.Disconnect()
|
||||||
// Only try reconnecting if we have not been kicked by another session to avoid connection loop.
|
// Only try reconnecting if we have not been kicked by another session to avoid connection loop.
|
||||||
|
// TODO: Make this conflict exception a permanent error
|
||||||
if e.StreamError != "conflict" {
|
if e.StreamError != "conflict" {
|
||||||
sm.connect()
|
sm.connect()
|
||||||
}
|
}
|
||||||
|
case StatePermanentError:
|
||||||
|
// Do not attempt to reconnect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sm.client.SetHandler(handler)
|
sm.client.SetHandler(handler)
|
||||||
|
|
|
@ -116,16 +116,27 @@ func (t XMPPTransport) Ping() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t XMPPTransport) Read(p []byte) (n int, err error) {
|
func (t XMPPTransport) Read(p []byte) (n int, err error) {
|
||||||
|
if t.readWriter == nil {
|
||||||
|
return 0, errors.New("cannot read: not connected, no readwriter")
|
||||||
|
}
|
||||||
return t.readWriter.Read(p)
|
return t.readWriter.Read(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t XMPPTransport) Write(p []byte) (n int, err error) {
|
func (t XMPPTransport) Write(p []byte) (n int, err error) {
|
||||||
|
if t.readWriter == nil {
|
||||||
|
return 0, errors.New("cannot write: not connected, no readwriter")
|
||||||
|
}
|
||||||
return t.readWriter.Write(p)
|
return t.readWriter.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t XMPPTransport) Close() error {
|
func (t XMPPTransport) Close() error {
|
||||||
_, _ = t.readWriter.Write([]byte("</stream:stream>"))
|
if t.readWriter != nil {
|
||||||
return t.conn.Close()
|
_, _ = t.readWriter.Write([]byte("</stream:stream>"))
|
||||||
|
}
|
||||||
|
if t.conn != nil {
|
||||||
|
return t.conn.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *XMPPTransport) LogTraffic(logFile io.Writer) {
|
func (t *XMPPTransport) LogTraffic(logFile io.Writer) {
|
||||||
|
|
Loading…
Reference in a new issue