xmpp

package module
Version: v0.0.0-...-89e0ba7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2016 License: MIT Imports: 13 Imported by: 0

README

Go package for implementing XMPP clients and components.

See src/xmpp/doc.go for overview.

Documentation

Overview

Package for implementing XMPP clients and components.

The package is built around the concept of an XML stream - a pair of XML documents written to and read from a TCP connection. Top-level elements in the document form the messages processed by either end of the connection.

An XML stream is then configured for an XMPP conversation, as either a client (chat, etc) or component (a sort of server plugin).

Create a client:

jid, err := xmpp.ParseJID("alice@wonderland.lit/some-resource")
addr, err := xmpp.HomeServerAddrs(jid)
stream, err := xmpp.NewStream(addr[0], nil)
X, err := xmpp.NewClientXMPP(stream, jid, "password", nil)

Create a component:

jid, err := xmpp.ParseJID("rabbithole.wonderland.lit")
stream, err := xmpp.NewStream("localhost:5347", nil)
X, err := xmpp.NewComponentXMPP(stream, jid, "secret")

Outgoing XMPP stanzas are sent to the XMPP instance's Out channel, e.g. a client typically announces its presence on the XMPP network as soon as it's connected:

X.Out <- xmpp.Presence{}

Incoming messages are handled by consuming the XMPP instance's In channel. The channel is sent all XMPP stanzas as well as terminating error (io.EOF for clean shutdown or any other error for something unexpected). The channel is also closed after an error.

XMPP defines four types of stanza: <error/>, <iq/>, <message/> and <presence/> represented by Error, Iq, Message (shown below) and Presence structs respectively.

for i := range X.In {
	switch v := i.(type) {
	case error:
		log.Printf("error : %v\n", v)
	case *xmpp.Message:
		log.Printf("msg : %s says %s\n", v.From, v.Body)
	default:
		log.Printf("%T : %v\n", v, v)
	}
}

Note: A "bound" JID is negotatiated during XMPP setup and may be different to the JID passed to the New(Client|Component)XMPP() call. Always use the XMPP instance's JID attribute in any stanzas.

Index

Constants

View Source
const (
	// Standard port for XMPP clients to connect to.
	XMPP_CLIENT_PORT = 5222
)

Variables

View Source
var DiscoPayloadMatcher = MatcherFunc(
	func(v interface{}) bool {
		iq, ok := v.(*Iq)
		if !ok {
			return false
		}
		ns := strings.Split(iq.PayloadName().Space, "#")[0]
		return ns == discoNamespacePrefix
	},
)

Matcher instance to match <iq/> stanzas with a disco payload.

View Source
var (
	FeatureNotImplemented = ErrorCondition{nsErrorStanzas, "feature-not-implemented"}
)

Stanza errors.

Functions

func HomeServerAddrs

func HomeServerAddrs(jid JID) (addr []string, err error)

Perform a DNS SRV lookup and return an ordered list of "host:port" TCP addresses for the JID's home server. If no SRV records are found then assume the JID's domain is also the home server.

func UUID4

func UUID4() string

Generate a UUID4.

Types

type ClientConfig

type ClientConfig struct {
	// Don't upgrade the connection to TLS, even if the server supports it. If
	// the server *requires* TLS then this option is ignored.
	NoTLS bool

	// Skip verification of the server's certificate chain. Probably only
	// useful during development.
	InsecureSkipVerify bool
}

Config structure used to create a new XMPP client connection.

type Disco

type Disco struct {
	XMPP *XMPP
}

Service Discovery (XEP-0030) protocol. "Wraps" XMPP instance to provide a more convenient API for Disco clients.

func (*Disco) Info

func (disco *Disco) Info(to string, from string) (*DiscoInfo, error)

Request information about the service identified by 'to'.

func (*Disco) Items

func (disco *Disco) Items(to string, from string) (*DiscoItems, error)

Request items in the service identified by 'to'.

type DiscoFeature

type DiscoFeature struct {
	Var string `xml:"var,attr"`
}

Feature

type DiscoIdentity

type DiscoIdentity struct {
	Category string `xml:"category,attr"`
	Type     string `xml:"type,attr"`
	Name     string `xml:"name,attr"`
}

Identity

type DiscoInfo

type DiscoInfo struct {
	XMLName  xml.Name        `xml:"http://jabber.org/protocol/disco#info query"`
	Identity []DiscoIdentity `xml:"identity"`
	Feature  []DiscoFeature  `xml:"feature"`
}

Iq get/result payload for "info" requests.

type DiscoItem

type DiscoItem struct {
	JID  string `xml:"jid,attr"`
	Node string `xml:"node,attr"`
	Name string `xml:"name,attr"`
}

Item.

type DiscoItems

type DiscoItems struct {
	XMLName xml.Name    `xml:"http://jabber.org/protocol/disco#items query"`
	Item    []DiscoItem `xml:"item"`
}

Iq get/result payload for "items" requests.

type Error

type Error struct {
	XMLName xml.Name `xml:"error"`
	Type    string   `xml:"type,attr"`
	Payload string   `xml:",innerxml"`
}

XMPP <error/>. May occur as a top-level stanza or embedded in another stanza, e.g. an <iq type="error"/>.

func NewError

func NewError(errorType string, condition ErrorCondition, text string) *Error

Create a new Error instance using the args as the payload.

func (Error) Condition

func (e Error) Condition() ErrorCondition

Return the error condition from the payload.

func (Error) Error

func (e Error) Error() string

func (Error) Text

func (e Error) Text() string

Return the error text from the payload, or "" if not present.

type ErrorCondition

type ErrorCondition xml.Name

Error condition.

type FilterId

type FilterId int64

Uniquly identifies a stream fiter. Used to remove a filter that's no longer needed.

func (FilterId) Error

func (fid FilterId) Error() string

Implements the error interface for a FilterId.

type Iq

type Iq struct {
	XMLName xml.Name `xml:"iq"`
	Id      string   `xml:"id,attr"`
	Type    string   `xml:"type,attr"`
	To      string   `xml:"to,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
	Payload string   `xml:",innerxml"`
	Error   *Error   `xml:"error"`
}

XMPP <iq/> stanza.

func (*Iq) PayloadDecode

func (iq *Iq) PayloadDecode(v interface{}) error

Decode the payload (an XML string) into the given value. See xml.Unmarshal for how the value is decoded.

func (*Iq) PayloadEncode

func (iq *Iq) PayloadEncode(v interface{}) error

Encode the value to an XML string and set as the payload. See xml.Marshal for how the value is encoded.

func (*Iq) PayloadName

func (iq *Iq) PayloadName() (name xml.Name)

Return the name of the payload element.

func (*Iq) Response

func (iq *Iq) Response(type_ string) *Iq

Create a response Iq. The Id is kept, To and From are reversed, Type is set to the given value.

type JID

type JID struct {
	// Node/local component e.g. the alice of alice@example.com/foo.
	Node string

	// Domain component, e.g. the example.com of alice@example.com/foo for a
	// client or the whole JID of a component.
	Domain string

	// Resource component, e.g. the foo of alice@example.com/foo.
	Resource string
}

Jabber Identifier - uniquely identifies an individual entity in a XMPP/Jabber network.

func ParseJID

func ParseJID(s string) (jid JID, err error)

Parse a string into a JID structure.

func (JID) Bare

func (jid JID) Bare() string

Return the "bare" JID, i.e. no resource component.

func (JID) Full

func (jid JID) Full() string

Return the full JID as a string.

func (JID) String

func (jid JID) String() string

Return full JID as a string.

type Matcher

type Matcher interface {
	// Return true if the stanza, v, matches.
	Match(v interface{}) (match bool)
}

Interface used to test if a stanza matches some application-defined conditions.

func IqResult

func IqResult(id string) Matcher

Matcher to identify a <iq id="..." type="result" /> stanza with the given id.

type MatcherFunc

type MatcherFunc func(v interface{}) bool

Adapter to allow a plain func to be used as a Matcher.

func (MatcherFunc) Match

func (fn MatcherFunc) Match(v interface{}) bool

Implement Matcher by calling the adapted func.

type Message

type Message struct {
	XMLName xml.Name `xml:"message"`
	Id      string   `xml:"id,attr,omitempty"`
	Type    string   `xml:"type,attr,omitempty"`
	To      string   `xml:"to,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
	Subject string   `xml:"subject,omitempty"`
	Body    string   `xml:"body,omitempty"`
}

XMPP <message/> stanza.

type Presence

type Presence struct {
	XMLName xml.Name `xml:"presence"`
	Id      string   `xml:"id,attr,omitempty"`
	Type    string   `xml:"type,attr,omitempty"`
	To      string   `xml:"to,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
}

XMPP <presence/> stanza.

type Stream

type Stream struct {
	// contains filtered or unexported fields
}

func NewStream

func NewStream(addr string, config *StreamConfig) (*Stream, error)

Create a XML stream connection. A Steam is used by an XMPP instance to handle sending and receiving XML data over the net connection.

func (*Stream) Decode

func (stream *Stream) Decode(v interface{}, start *xml.StartElement) error

Decode a stanza. If start is not nil, the stanza for the start element that's already been consumed is read. A nil start will read the next stanza in the stream. See xml.Decoder.DecodeElement for decoding rules.

func (*Stream) Next

func (stream *Stream) Next() (*xml.StartElement, error)

Find start of next stanza. Bad things are very likely to happen if a call to Next() is successful but you don't actually decode or skip the element.

func (*Stream) Send

func (stream *Stream) Send(v interface{}) error

Send a stanza. Used to write a complete, top-level element.

func (*Stream) SendEnd

func (stream *Stream) SendEnd(end *xml.EndElement) error

Send the end element that closes the stream.

func (*Stream) SendStart

func (stream *Stream) SendStart(start *xml.StartElement) (*xml.StartElement, error)

Send the element's start tag. Typically used to open the stream's document.

func (*Stream) Skip

func (stream *Stream) Skip() error

Skip reads tokens until it reaches the end element of the most recent start element that has already been read.

func (*Stream) UpgradeTLS

func (stream *Stream) UpgradeTLS(config *tls.Config) error

Upgrade the stream's underlying net connection to TLS.

type StreamConfig

type StreamConfig struct {
	// Log all sent and received stanzas.
	// Enabling this option causes stanzas to be buffered in memory before they
	// are either sent to the server or delivered to the application. It also
	// causes incoming stanzas to be XML-parsed a second time.
	LogStanzas bool
}

Stream configuration.

type XMPP

type XMPP struct {

	// JID associated with the stream. Note: this may be negotiated with the
	// server during setup and so must be used for all messages.
	JID JID

	// Channel of incoming messages. Values will be one of Iq, Message,
	// Presence, Error or error. Will be closed at the end when the stream is
	// closed or the stream's net connection dies.
	In chan interface{}

	// Channel of outgoing messages. Messages must be able to be marshaled by
	// the standard xml package, however you should try to send one of Iq,
	// Message or Presence.
	Out chan interface{}
	// contains filtered or unexported fields
}

Handles XMPP conversations over a Stream. Use NewClientXMPP or NewComponentXMPP to create and configure a XMPP instance. Close the conversation by closing the Out channel, the In channel will be closed when the remote server closes its stream.

func NewClientXMPP

func NewClientXMPP(stream *Stream, jid JID, password string, config *ClientConfig) (*XMPP, error)

Create a client XMPP over the stream.

func NewComponentXMPP

func NewComponentXMPP(stream *Stream, jid JID, secret string) (*XMPP, error)

Create a component XMPP connection over the stream.

func (*XMPP) AddFilter

func (x *XMPP) AddFilter(m Matcher) (FilterId, chan interface{})

Add a filter that routes matching stanzas to the returned channel. A FilterId is also returned and can be pased to RemoveFilter to remove the filter again.

func (*XMPP) RemoveFilter

func (x *XMPP) RemoveFilter(id FilterId) error

Remove a filter previously added with AddFilter.

func (*XMPP) SendRecv

func (x *XMPP) SendRecv(iq *Iq) (*Iq, error)

Notes

Bugs

  • authentication incorrectly reports, "No supported SASL mechanism found", for authentication attemtps that fail due to invalid credentials.

  • ParseJID should fail for incorrectly formatted JIDs.

  • Filter channels are not closed when the stream is closed.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL