Documentation ¶
Overview ¶
Fluux XMPP is an modern and full-featured XMPP library that can be used to build clients or server components.
The goal is to make simple to write modern compliant XMPP software:
- For automation (like for example monitoring of an XMPP service),
- For building connected "things" by plugging them on an XMPP server,
- For writing simple chatbots to control a service or a thing.
- For writing XMPP servers components. Fluux XMPP supports:
- XEP-0114: Jabber Component Protocol
- XEP-0355: Namespace Delegation
- XEP-0356: Privileged Entity
The library is designed to have minimal dependencies. For now, the library does not depend on any other library.
The library includes a StreamManager that provides features like autoreconnect exponential back-off.
The library is implementing latest versions of the XMPP specifications (RFC 6120 and RFC 6121), and includes support for many extensions.
Clients ¶
Fluux XMPP can be use to create fully interactive XMPP clients (for example console-based), but it is more commonly used to build automated clients (connected devices, automation scripts, chatbots, etc.).
Components ¶
XMPP components can typically be used to extends the features of an XMPP server, in a portable way, using component protocol over persistent TCP serverConnections.
Component protocol is defined in XEP-114 (https://xmpp.org/extensions/xep-0114.html).
Compliance ¶
Fluux XMPP has been primarily tested with ejabberd (https://www.ejabberd.im) but it should work with any XMPP compliant server.
Index ¶
- Variables
- func IsStreamResumable(c *Client) bool
- func SendMissingStz(lastSent int, s Sender, uaq *stanza.UnAckQueue) error
- type BiDirIterator
- type BiDirIteratorElt
- type Client
- func (c *Client) Connect() error
- func (c *Client) Disconnect() error
- func (c *Client) Resume() error
- func (c *Client) Send(packet stanza.Packet) error
- func (c *Client) SendIQ(ctx context.Context, iq *stanza.IQ) (chan stanza.IQ, error)
- func (c *Client) SendRaw(packet string) error
- func (c *Client) SetHandler(handler EventHandler)
- type ClientHandler
- type Component
- func (c *Component) Connect() error
- func (c *Component) Disconnect() error
- func (c *Component) Resume() error
- func (c *Component) Send(packet stanza.Packet) error
- func (c *Component) SendIQ(ctx context.Context, iq *stanza.IQ) (chan stanza.IQ, error)
- func (c *Component) SendRaw(packet string) error
- func (c *Component) SetHandler(handler EventHandler)
- type ComponentOptions
- type Config
- type ConnError
- type ConnState
- type Credential
- type Event
- type EventHandler
- type EventManager
- type Handler
- type HandlerFunc
- type IQResultHandler
- type IQResultHandlerFunc
- type IQResultRoute
- type Matcher
- type Metrics
- type PostConnect
- type Route
- func (r *Route) AddMatcher(m Matcher) *Route
- func (r *Route) Handler(handler Handler) *Route
- func (r *Route) HandlerFunc(f HandlerFunc) *Route
- func (r *Route) IQNamespaces(namespaces ...string) *Route
- func (r *Route) Match(p stanza.Packet, match *RouteMatch) bool
- func (r *Route) Packet(name string) *Route
- func (r *Route) StanzaType(types ...string) *Route
- type RouteMatch
- type Router
- func (r *Router) Handle(name string, handler Handler) *Route
- func (r *Router) HandleFunc(name string, f func(s Sender, p stanza.Packet)) *Route
- func (r *Router) Match(p stanza.Packet, match *RouteMatch) bool
- func (r *Router) NewIQResultRoute(ctx context.Context, id string) chan stanza.IQ
- func (r *Router) NewRoute() *Route
- type SMState
- type Sender
- type ServerCheck
- type ServerConn
- type ServerMock
- type Session
- type StreamClient
- type StreamManager
- type SyncConnState
- type TimeoutHandlerFunc
- type Transport
- type TransportConfiguration
- type WebsocketTransport
- func (t WebsocketTransport) Close() error
- func (t *WebsocketTransport) Connect() (string, error)
- func (t WebsocketTransport) DoesStartTLS() bool
- func (t WebsocketTransport) GetDecoder() *xml.Decoder
- func (t WebsocketTransport) GetDomain() string
- func (t WebsocketTransport) IsSecure() bool
- func (t *WebsocketTransport) LogTraffic(logFile io.Writer)
- func (t WebsocketTransport) Ping() error
- func (t *WebsocketTransport) Read(p []byte) (int, error)
- func (t *WebsocketTransport) ReceivedStreamClose()
- func (t WebsocketTransport) StartStream() (string, error)
- func (t WebsocketTransport) StartTLS() error
- func (t WebsocketTransport) Write(p []byte) (int, error)
- type XMPPTransport
- func (t *XMPPTransport) Close() error
- func (t *XMPPTransport) Connect() (string, error)
- func (t *XMPPTransport) DoesStartTLS() bool
- func (t *XMPPTransport) GetDecoder() *xml.Decoder
- func (t *XMPPTransport) GetDomain() string
- func (t *XMPPTransport) IsSecure() bool
- func (t *XMPPTransport) LogTraffic(logFile io.Writer)
- func (t *XMPPTransport) Ping() error
- func (t *XMPPTransport) Read(p []byte) (n int, err error)
- func (t *XMPPTransport) ReceivedStreamClose()
- func (t *XMPPTransport) StartStream() (string, error)
- func (t *XMPPTransport) StartTLS() error
- func (t *XMPPTransport) Write(p []byte) (n int, err error)
Constants ¶
This section is empty.
Variables ¶
var ErrCanOnlySendGetOrSetIq = errors.New("SendIQ can only send get and set IQ stanzas")
var ErrTLSNotSupported = errors.New("transport does not support StartTLS")
var ErrTransportProtocolNotSupported = errors.New("transport protocol not supported")
var ServerDoesNotSupportXmppOverWebsocket = errors.New("the websocket server does not support the xmpp subprotocol")
Functions ¶
func IsStreamResumable ¶
IsStreamResumable tells if a stream session is resumable by reading the "config" part of a client. It checks if stream management is enabled, and if stream resumption was set and accepted by the server.
func SendMissingStz ¶
func SendMissingStz(lastSent int, s Sender, uaq *stanza.UnAckQueue) error
SendMissingStz sends all stanzas that did not reach the server, according to the response to an ack request (see XEP-0198, acks)
Types ¶
type BiDirIterator ¶
type BiDirIterator interface { // Next returns the next element of this iterator, if a response is available within t milliseconds Next(t int) (BiDirIteratorElt, error) // Previous returns the previous element of this iterator, if a response is available within t milliseconds Previous(t int) (BiDirIteratorElt, error) }
type BiDirIteratorElt ¶
type BiDirIteratorElt interface {
NoOp()
}
type Client ¶
type Client struct { // Session gather data that can be accessed by users of this library Session *Session // Track and broadcast connection state EventManager // Handle errors from client execution ErrorHandler func(error) // Post connection hook. This will be executed on first connection PostConnectHook func() error // Post resume hook. This will be executed after the client resumes a lost connection using StreamManagement (XEP-0198) PostResumeHook func() error // contains filtered or unexported fields }
Client is the main structure used to connect as a client on an XMPP server.
func NewClient ¶
NewClient generates a new XMPP client, based on Config passed as parameters. If host is not specified, the DNS SRV should be used to find the host from the domain part of the Jid. Default the port to 5222.
func (*Client) Connect ¶
Connect establishes a first time connection to a XMPP server. It calls the PostConnectHook
func (*Client) Disconnect ¶
Disconnect disconnects the client from the server, sending a stream close nonza and closing the TCP connection.
func (*Client) Resume ¶
Resume attempts resuming a Stream Managed session, based on the provided stream management state. See XEP-0198
func (*Client) SendIQ ¶
SendIQ sends an IQ set or get stanza to the server. If a result is received the provided handler function will automatically be called.
The provided context should have a timeout to prevent the client from waiting forever for an IQ result. For example:
ctx, _ := context.WithTimeout(context.Background(), 30 * time.Second) result := <- client.SendIQ(ctx, iq)
func (*Client) SendRaw ¶
SendRaw sends an XMPP stanza as a string to the server. It can be invalid XML or XMPP content. In that case, the server will disconnect the client. It is up to the user of this method to carefully craft the XML content to produce valid XMPP.
func (*Client) SetHandler ¶
func (c *Client) SetHandler(handler EventHandler)
type ClientHandler ¶
type ClientHandler func(t *testing.T, serverConn *ServerConn)
ClientHandler is passed by the test client to provide custom behaviour to the TCP server mock. This allows customizing the server behaviour to allow testing clients under various scenarii.
type Component ¶
type Component struct { ComponentOptions ErrorHandler func(error) // contains filtered or unexported fields }
Component implements an XMPP extension allowing to extend XMPP server using external components. Component specifications are defined in XEP-0114, XEP-0355 and XEP-0356.
func NewComponent ¶
func NewComponent(opts ComponentOptions, r *Router, errorHandler func(error)) (*Component, error)
func (*Component) Connect ¶
Connect triggers component connection to XMPP server component port. TODO: Failed handshake should be a permanent error
func (*Component) Disconnect ¶
func (*Component) SendIQ ¶
SendIQ sends an IQ set or get stanza to the server. If a result is received the provided handler function will automatically be called.
The provided context should have a timeout to prevent the client from waiting forever for an IQ result. For example:
ctx, _ := context.WithTimeout(context.Background(), 30 * time.Second) result := <- client.SendIQ(ctx, iq)
func (*Component) SendRaw ¶
SendRaw sends an XMPP stanza as a string to the server. It can be invalid XML or XMPP content. In that case, the server will disconnect the component. It is up to the user of this method to carefully craft the XML content to produce valid XMPP.
func (*Component) SetHandler ¶
func (c *Component) SetHandler(handler EventHandler)
type ComponentOptions ¶
type ComponentOptions struct { TransportConfiguration // Domain is the XMPP server subdomain that the component will handle Domain string // Secret is the "password" used by the XMPP server to secure component access Secret string // Component human readable name, that will be shown in XMPP discovery Name string // Typical categories and types: https://xmpp.org/registrar/disco-categories.html Category string Type string // Track and broadcast connection state EventManager }
type Config ¶
type Config struct { TransportConfiguration Jid string Credential Credential StreamLogger *os.File // Used for debugging Lang string // TODO: should default to 'en' KeepaliveInterval time.Duration // Interval between keepalive packets ConnectTimeout int // Client timeout in seconds. Default to 15 // Insecure can be set to true to allow to open a session without TLS. If TLS // is supported on the server, we will still try to use it. Insecure bool // Activate stream management process during session StreamManagementEnable bool // contains filtered or unexported fields }
Config & TransportConfiguration must not be modified after having been passed to NewClient. Any changes made after connecting are ignored.
type ConnError ¶
type ConnError struct { // Permanent will be true if error is not recoverable Permanent bool // contains filtered or unexported fields }
func NewConnError ¶
type Credential ¶
type Credential struct {
// contains filtered or unexported fields
}
Credential is used to pass the type of secret that will be used to connect to XMPP server. It can be either a password or an OAuth 2 bearer token.
func OAuthToken ¶
func OAuthToken(token string) Credential
func Password ¶
func Password(pwd string) Credential
type Event ¶
type Event struct { State SyncConnState Description string StreamError string SMState SMState }
Event is a structure use to convey event changes related to client state. This is for example used to notify the client when the client get disconnected.
type EventHandler ¶
EventHandler is use to pass events about state of the connection to client implementation.
type EventManager ¶
type EventManager struct { // Store current state. Please use "getState" and "setState" to access and/or modify this. CurrentState SyncConnState // Callback used to propagate connection state changes Handler EventHandler }
type HandlerFunc ¶
The HandlerFunc type is an adapter to allow the use of ordinary functions as XMPP handlers. If f is a function with the appropriate signature, HandlerFunc(f) is a Handler that calls f.
func (HandlerFunc) HandlePacket ¶
func (f HandlerFunc) HandlePacket(s Sender, p stanza.Packet)
HandlePacket calls f(s, p)
type IQResultHandler ¶
IQResultHandler is a utility interface for IQ result handlers
type IQResultHandlerFunc ¶
IQResultHandlerFunc is an adapter to allow using functions as IQ result handlers.
type IQResultRoute ¶
type IQResultRoute struct {
// contains filtered or unexported fields
}
IQResultRoute is a temporary route to match IQ result stanzas
func NewIQResultRoute ¶
func NewIQResultRoute(ctx context.Context) *IQResultRoute
NewIQResultRoute creates a new IQResultRoute instance
type Matcher ¶
type Matcher interface {
Match(stanza.Packet, *RouteMatch) bool
}
Matchers are used to "specialize" routes and focus on specific packet features. You can register attach them to a route via the AddMatcher method.
type Metrics ¶
type Metrics struct { // LoginTime returns the between client initiation of the TCP/IP // connection to the server and the return of the login result. // This includes ConnectTime, but also XMPP level protocol negotiation // like starttls. LoginTime time.Duration // contains filtered or unexported fields }
type PostConnect ¶
type PostConnect func(c Sender)
type Route ¶
type Route struct {
// contains filtered or unexported fields
}
func (*Route) AddMatcher ¶
AddMatcher adds a matcher to the route
func (*Route) HandlerFunc ¶
func (r *Route) HandlerFunc(f HandlerFunc) *Route
HandlerFunc sets a handler function for the route
func (*Route) IQNamespaces ¶
IQNamespaces adds an IQ matcher, expecting both an IQ and a
func (*Route) Packet ¶
Packet matches on a packet name (iq, message, presence, ...) It matches on the Local part of the xml.Name
func (*Route) StanzaType ¶
IQNamespaces adds an IQ matcher, expecting both an IQ and a
type RouteMatch ¶
RouteMatch extracts and gather match information
type Router ¶
type Router struct { IQResultRoutes map[string]*IQResultRoute IQResultRouteLock sync.RWMutex // contains filtered or unexported fields }
func (*Router) Handle ¶
Handle registers a new route with a matcher for a given packet name (iq, message, presence) See Route.Packet() and Route.Handler().
func (*Router) HandleFunc ¶
HandleFunc registers a new route with a matcher for for a given packet name (iq, message, presence) See Route.Path() and Route.HandlerFunc().
func (*Router) NewIQResultRoute ¶
NewIQResultRoute register a route that will catch an IQ result stanza with the given Id. The route will only match ones, after which it will automatically be unregistered
type SMState ¶
type SMState struct { // Stream Management ID Id string // Inbound stanza count Inbound uint // Error StreamErrorGroup stanza.StanzaErrorGroup // Track sent stanzas *stanza.UnAckQueue // contains filtered or unexported fields }
SMState holds Stream Management information regarding the session that can be used to resume session after disconnect
type Sender ¶
type Sender interface { Send(packet stanza.Packet) error SendIQ(ctx context.Context, iq *stanza.IQ) (chan stanza.IQ, error) SendRaw(packet string) error }
Sender is an interface provided by Stream clients to allow sending XMPP data. It is mostly use in callback to pass a limited subset of the stream client interface
type ServerCheck ¶
type ServerCheck struct {
// contains filtered or unexported fields
}
TODO: Should I move this as an extension of the client?
I should probably make the code more modular, but keep concern separated to keep it simple.
func NewChecker ¶
func NewChecker(address, domain string) (*ServerCheck, error)
func (*ServerCheck) Check ¶
func (c *ServerCheck) Check() error
Check triggers actual TCP connection, based on previously defined parameters.
type ServerConn ¶
type ServerConn struct {
// contains filtered or unexported fields
}
type ServerMock ¶
type ServerMock struct {
// contains filtered or unexported fields
}
ServerMock is a simple TCP server that can be use to mock basic server behaviour to test clients.
func (*ServerMock) Start ¶
func (mock *ServerMock) Start(t *testing.T, addr string, handler ClientHandler)
Start launches the mock TCP server, listening to an actual address / port.
func (*ServerMock) Stop ¶
func (mock *ServerMock) Stop()
type Session ¶
type Session struct { // Session info BindJid string // Jabber ID as provided by XMPP server StreamId string SMState SMState Features stanza.StreamFeatures TlsEnabled bool // contains filtered or unexported fields }
func (*Session) EnableStreamManagement ¶
Enable stream management, with session resumption, if supported.
type StreamClient ¶
type StreamClient interface { Connect() error Resume() error Send(packet stanza.Packet) error SendIQ(ctx context.Context, iq *stanza.IQ) (chan stanza.IQ, error) SendRaw(packet string) error Disconnect() error SetHandler(handler EventHandler) }
StreamClient is an interface used by StreamManager to control Client lifecycle, set callback and trigger reconnection.
type StreamManager ¶
type StreamManager struct { PostConnect PostConnect // Store low level metrics Metrics *Metrics // contains filtered or unexported fields }
StreamManager supervises an XMPP client connection. Its role is to handle connection events and apply reconnection strategy.
func NewStreamManager ¶
func NewStreamManager(client StreamClient, pc PostConnect) *StreamManager
NewStreamManager creates a new StreamManager structure, intended to support handling XMPP client state event changes and auto-trigger reconnection based on StreamManager configuration. TODO: Move parameters to Start and remove factory method
func (*StreamManager) Run ¶
func (sm *StreamManager) Run() error
Run launches the connection of the underlying client or component and wait until Disconnect is called, or for the manager to terminate due to an unrecoverable error.
func (*StreamManager) Stop ¶
func (sm *StreamManager) Stop()
Stop cancels pending operations and terminates existing XMPP client.
type SyncConnState ¶
SyncConnState represents the current connection state.
type TimeoutHandlerFunc ¶
type TimeoutHandlerFunc func(err error)
TimeoutHandlerFunc is a function type for handling IQ result timeouts.
type Transport ¶
type Transport interface { Connect() (string, error) DoesStartTLS() bool StartTLS() error LogTraffic(logFile io.Writer) StartStream() (string, error) GetDecoder() *xml.Decoder IsSecure() bool Ping() error Read(p []byte) (n int, err error) Write(p []byte) (n int, err error) Close() error // ReceivedStreamClose signals to the transport that a </stream:stream> has been received and that the tcp connection // should be closed. ReceivedStreamClose() }
func NewClientTransport ¶
func NewClientTransport(config TransportConfiguration) Transport
NewClientTransport creates a new Transport instance for clients. The type of transport is determined by the address in the configuration: - if the address is a URL with the `ws` or `wss` scheme WebsocketTransport is used - in all other cases a XMPPTransport is used For XMPPTransport it is mandatory for the address to have a port specified.
func NewComponentTransport ¶
func NewComponentTransport(config TransportConfiguration) (Transport, error)
NewComponentTransport creates a new Transport instance for components. Only XMPP transports are allowed. If you try to use any other protocol an error will be returned.
type TransportConfiguration ¶
type TransportConfiguration struct { // Address is the XMPP Host and port to connect to. Host is of // the form 'serverhost:port' i.e "localhost:8888" Address string Domain string ConnectTimeout int // Client timeout in seconds. Default to 15 // tls.Config must not be modified after having been passed to NewClient. Any // changes made after connecting are ignored. TLSConfig *tls.Config CharsetReader func(charset string, input io.Reader) (io.Reader, error) // passed to xml decoder }
TODO: rename to transport config?
type WebsocketTransport ¶
type WebsocketTransport struct { Config TransportConfiguration // contains filtered or unexported fields }
The decoder is expected to be initialized after connecting to a server.
func (WebsocketTransport) Close ¶
func (t WebsocketTransport) Close() error
func (*WebsocketTransport) Connect ¶
func (t *WebsocketTransport) Connect() (string, error)
func (WebsocketTransport) DoesStartTLS ¶
func (t WebsocketTransport) DoesStartTLS() bool
func (WebsocketTransport) GetDecoder ¶
func (t WebsocketTransport) GetDecoder() *xml.Decoder
func (WebsocketTransport) GetDomain ¶
func (t WebsocketTransport) GetDomain() string
func (WebsocketTransport) IsSecure ¶
func (t WebsocketTransport) IsSecure() bool
func (*WebsocketTransport) LogTraffic ¶
func (t *WebsocketTransport) LogTraffic(logFile io.Writer)
func (WebsocketTransport) Ping ¶
func (t WebsocketTransport) Ping() error
func (*WebsocketTransport) ReceivedStreamClose ¶
func (t *WebsocketTransport) ReceivedStreamClose()
ReceivedStreamClose is not used for websockets for now
func (WebsocketTransport) StartStream ¶
func (t WebsocketTransport) StartStream() (string, error)
func (WebsocketTransport) StartTLS ¶
func (t WebsocketTransport) StartTLS() error
type XMPPTransport ¶
type XMPPTransport struct { Config TransportConfiguration TLSConfig *tls.Config // contains filtered or unexported fields }
XMPPTransport implements the XMPP native TCP transport The decoder is expected to be initialized after connecting to a server.
func (*XMPPTransport) Close ¶
func (t *XMPPTransport) Close() error
func (*XMPPTransport) Connect ¶
func (t *XMPPTransport) Connect() (string, error)
func (*XMPPTransport) DoesStartTLS ¶
func (t *XMPPTransport) DoesStartTLS() bool
func (*XMPPTransport) GetDecoder ¶
func (t *XMPPTransport) GetDecoder() *xml.Decoder
func (*XMPPTransport) GetDomain ¶
func (t *XMPPTransport) GetDomain() string
func (*XMPPTransport) IsSecure ¶
func (t *XMPPTransport) IsSecure() bool
func (*XMPPTransport) LogTraffic ¶
func (t *XMPPTransport) LogTraffic(logFile io.Writer)
func (*XMPPTransport) Ping ¶
func (t *XMPPTransport) Ping() error
func (*XMPPTransport) ReceivedStreamClose ¶
func (t *XMPPTransport) ReceivedStreamClose()
func (*XMPPTransport) StartStream ¶
func (t *XMPPTransport) StartStream() (string, error)
func (*XMPPTransport) StartTLS ¶
func (t *XMPPTransport) StartTLS() error