mirror of
https://github.com/FluuxIO/go-xmpp.git
synced 2024-11-24 19:42:00 -08:00
parent
d45dd6a44a
commit
2d8d4516fd
6
auth.go
6
auth.go
@ -18,7 +18,8 @@ func authSASL(socket io.ReadWriter, decoder *xml.Decoder, f StreamFeatures, user
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !havePlain {
|
if !havePlain {
|
||||||
return fmt.Errorf("PLAIN authentication is not supported by server: %v", f.Mechanisms.Mechanism)
|
err := fmt.Errorf("PLAIN authentication is not supported by server: %v", f.Mechanisms.Mechanism)
|
||||||
|
return NewConnError(err, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return authPlain(socket, decoder, user, password)
|
return authPlain(socket, decoder, user, password)
|
||||||
@ -41,7 +42,8 @@ func authPlain(socket io.ReadWriter, decoder *xml.Decoder, user string, password
|
|||||||
case SASLSuccess:
|
case SASLSuccess:
|
||||||
case SASLFailure:
|
case SASLFailure:
|
||||||
// v.Any is type of sub-element in failure, which gives a description of what failed.
|
// v.Any is type of sub-element in failure, which gives a description of what failed.
|
||||||
return errors.New("auth failure: " + v.Any.Local)
|
err := errors.New("auth failure: " + v.Any.Local)
|
||||||
|
return NewConnError(err, true)
|
||||||
default:
|
default:
|
||||||
return errors.New("expected SASL success or failure, got " + v.Name())
|
return errors.New("expected SASL success or failure, got " + v.Name())
|
||||||
}
|
}
|
||||||
|
@ -78,17 +78,18 @@ Setting up the client / Checking the parameters
|
|||||||
func NewClient(config Config) (c *Client, err error) {
|
func NewClient(config Config) (c *Client, err error) {
|
||||||
// TODO: If option address is nil, use the Jid domain to compose the address
|
// TODO: If option address is nil, use the Jid domain to compose the address
|
||||||
if config.Address, err = checkAddress(config.Address); err != nil {
|
if config.Address, err = checkAddress(config.Address); err != nil {
|
||||||
return
|
return nil, NewConnError(err, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Password == "" {
|
if config.Password == "" {
|
||||||
err = errors.New("missing password")
|
err = errors.New("missing password")
|
||||||
return
|
return nil, NewConnError(err, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse JID
|
// Parse JID
|
||||||
if config.parsedJid, err = NewJid(c.config.Jid); err != nil {
|
if config.parsedJid, err = NewJid(config.Jid); err != nil {
|
||||||
return
|
err = errors.New("missing jid")
|
||||||
|
return nil, NewConnError(err, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
c = new(Client)
|
c = new(Client)
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package xmpp // import "gosrc.io/xmpp"
|
package xmpp // import "gosrc.io/xmpp"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PostConnect func(c *Client)
|
type PostConnect func(c *Client)
|
||||||
@ -29,7 +30,7 @@ func NewClientManager(client *Client, pc PostConnect) *ClientManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start launch the connection loop
|
// Start launch the connection loop
|
||||||
func (cm *ClientManager) Start() {
|
func (cm *ClientManager) Start() error {
|
||||||
cm.Client.Handler = func(e Event) {
|
cm.Client.Handler = func(e Event) {
|
||||||
switch e.State {
|
switch e.State {
|
||||||
case StateConnected:
|
case StateConnected:
|
||||||
@ -41,7 +42,8 @@ func (cm *ClientManager) Start() {
|
|||||||
cm.connect()
|
cm.connect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cm.connect()
|
|
||||||
|
return cm.connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop cancels pending operations and terminates existing XMPP client.
|
// Stop cancels pending operations and terminates existing XMPP client.
|
||||||
@ -52,17 +54,23 @@ func (cm *ClientManager) Stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// connect manages the reconnection loop and apply the define backoff to avoid overloading the server.
|
// connect manages the reconnection loop and apply the define backoff to avoid overloading the server.
|
||||||
func (cm *ClientManager) connect() {
|
func (cm *ClientManager) connect() error {
|
||||||
var backoff Backoff // TODO: Group backoff calculation features with connection manager?
|
var backoff Backoff // TODO: Group backoff calculation features with connection manager?
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var err error
|
var err error
|
||||||
|
// 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
|
// 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.
|
// 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 {
|
||||||
log.Printf("Connection error: %v\n", err)
|
var actualErr ConnError
|
||||||
|
if xerrors.As(err, &actualErr) {
|
||||||
|
if actualErr.Permanent {
|
||||||
|
return xerrors.Errorf("unrecoverable connect error %w", actualErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
backoff.Wait()
|
backoff.Wait()
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
@ -72,6 +80,7 @@ func (cm *ClientManager) connect() {
|
|||||||
if cm.PostConnect != nil {
|
if cm.PostConnect != nil {
|
||||||
cm.PostConnect(cm.Client)
|
cm.PostConnect(cm.Client)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client Metrics
|
// Client Metrics
|
||||||
|
@ -23,13 +23,16 @@ func main() {
|
|||||||
|
|
||||||
client, err := xmpp.NewClient(config)
|
client, err := xmpp.NewClient(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error: ", err)
|
log.Fatalf("%+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cm := xmpp.NewClientManager(client, nil)
|
cm := xmpp.NewClientManager(client, nil)
|
||||||
cm.Start()
|
err = cm.Start()
|
||||||
// connection can be stopped with cm.Stop()
|
// connection can be stopped with cm.Stop()
|
||||||
// connection state can be checked by reading cm.Client.CurrentState
|
// connection state can be checked by reading cm.Client.CurrentState
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
// Iterator to receive packets coming from our XMPP connection
|
// Iterator to receive packets coming from our XMPP connection
|
||||||
for packet := range client.Recv() {
|
for packet := range client.Recv() {
|
||||||
|
33
conn_error.go
Normal file
33
conn_error.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package xmpp // import "gosrc.io/xmpp"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConnError struct {
|
||||||
|
frame xerrors.Frame
|
||||||
|
err error
|
||||||
|
// Permanent will be true if error is not recoverable
|
||||||
|
Permanent bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConnError(err error, permanent bool) ConnError {
|
||||||
|
return ConnError{err: err, frame: xerrors.Caller(1), Permanent: permanent}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ConnError) Format(s fmt.State, verb rune) {
|
||||||
|
xerrors.FormatError(e, s, verb)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ConnError) FormatError(p xerrors.Printer) error {
|
||||||
|
e.frame.Format(p)
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ConnError) Error() string {
|
||||||
|
return fmt.Sprint(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ConnError) Unwrap() error { return e.err }
|
1
go.mod
1
go.mod
@ -6,4 +6,5 @@ require (
|
|||||||
github.com/google/go-cmp v0.2.0
|
github.com/google/go-cmp v0.2.0
|
||||||
github.com/processone/mpg123 v1.0.0
|
github.com/processone/mpg123 v1.0.0
|
||||||
github.com/processone/soundcloud v1.0.0
|
github.com/processone/soundcloud v1.0.0
|
||||||
|
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522
|
||||||
)
|
)
|
||||||
|
6
go.sum
6
go.sum
@ -1,12 +1,10 @@
|
|||||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/processone/mpg123 v0.0.0-20160212185547-a17074c7ddc0 h1:7Sb9wi06laajixrlpOJACEtAsnbDYlH8/bRTfLKAiF4=
|
|
||||||
github.com/processone/mpg123 v0.0.0-20160212185547-a17074c7ddc0/go.mod h1:e9Ud3cx6fZEPqmEYDqjIsRvgFRPvXWhb0H1Cmu+LUtk=
|
|
||||||
github.com/processone/mpg123 v1.0.0 h1:o2WOyGZRM255or1Zc/LtF/jARn51B+9aQl72Qace0GA=
|
github.com/processone/mpg123 v1.0.0 h1:o2WOyGZRM255or1Zc/LtF/jARn51B+9aQl72Qace0GA=
|
||||||
github.com/processone/mpg123 v1.0.0/go.mod h1:X/FeL+h8vD1bYsG9tIWV3M2c4qNTZOficyvPVBP08go=
|
github.com/processone/mpg123 v1.0.0/go.mod h1:X/FeL+h8vD1bYsG9tIWV3M2c4qNTZOficyvPVBP08go=
|
||||||
github.com/processone/soundcloud v0.0.0-20160217145628-430ee371ebce h1:lDqQi4xGLeS5mZYpVeyle5num0mWdyy37QmsQiFSX1Y=
|
|
||||||
github.com/processone/soundcloud v0.0.0-20160217145628-430ee371ebce/go.mod h1:QfHw5V3JsrdJoYH4aD2+lr18v97eA6wyHaV0Zi+FuOI=
|
|
||||||
github.com/processone/soundcloud v1.0.0 h1:/+i6+Yveb7Y6IFGDSkesYI+HddblzcRTQClazzVHxoE=
|
github.com/processone/soundcloud v1.0.0 h1:/+i6+Yveb7Y6IFGDSkesYI+HddblzcRTQClazzVHxoE=
|
||||||
github.com/processone/soundcloud v1.0.0/go.mod h1:kDLeWpkRtN3C8kIReQdxoiRi92P9xR6yW6qLOJnNWfY=
|
github.com/processone/soundcloud v1.0.0/go.mod h1:kDLeWpkRtN3C8kIReQdxoiRi92P9xR6yW6qLOJnNWfY=
|
||||||
golang.org/x/net v0.0.0-20190110200230-915654e7eabc h1:Yx9JGxI1SBhVLFjpAkWMaO1TF+xyqtHLjZpvQboJGiM=
|
golang.org/x/net v0.0.0-20190110200230-915654e7eabc h1:Yx9JGxI1SBhVLFjpAkWMaO1TF+xyqtHLjZpvQboJGiM=
|
||||||
golang.org/x/net v0.0.0-20190110200230-915654e7eabc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190110200230-915654e7eabc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 h1:bhOzK9QyoD0ogCnFro1m2mz41+Ib0oOhfJnBp5MR4K4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
@ -43,7 +43,7 @@ func NewSession(conn net.Conn, o Config) (net.Conn, *Session, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !s.TlsEnabled && !o.Insecure {
|
if !s.TlsEnabled && !o.Insecure {
|
||||||
return nil, nil, errors.New("failed to negotiate TLS")
|
return nil, nil, NewConnError(errors.New("failed to negotiate TLS session"), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// auth
|
// auth
|
||||||
|
Loading…
Reference in New Issue
Block a user