Compare commits

...

8 Commits

Author SHA1 Message Date
Matt Goodall efce8dbb97 Merge pull request #9 from emgee/fix-names
Fix various names (some breaking).

Some breaking name changes:

- FilterId -> FilterID
- Id -> ID (various struct types)
- Iq -> IQ and IqResult -> IQResult
- XMPP_CLIENT_PORT -> ClientPort

And a few related, non-breaking cleanups:

- bindIq -> bindIQ
- streamId -> streamID
- nextFilterId -> nextFilterID
2017-04-14 16:32:34 +01:00
Matt Goodall c315cb9d49 Fix un-golang names (mostly case). 2017-04-14 12:21:45 +01:00
Matt Goodall 647313d46c Merge pull request #8 from emgee/lint-cleanup
Various lint cleanups.

* Simplify if/else
* Remove unused and unreachable code
* Improve error message format
* Fix log message
2017-04-14 12:19:01 +01:00
Matt Goodall 519c5a1846 Fix typos in comments. 2017-04-14 12:14:36 +01:00
Matt Goodall 0d9f3a4de5 Improve error message format. 2017-03-30 20:56:11 +01:00
Matt Goodall 19c81df5d6 Simplify. Remove unused/unreachable code. 2017-03-30 20:53:36 +01:00
Matt Goodall 9a399bd692 Fix log message. 2017-03-30 20:40:06 +01:00
Matt Goodall 29a325f2ae Merge pull request #7 from chteufleur/master 2017-03-30 20:04:24 +01:00
11 changed files with 115 additions and 124 deletions

View File

@ -50,7 +50,7 @@ func main() {
// Get disco#info for home server. // Get disco#info for home server.
info := &DiscoInfo{} info := &DiscoInfo{}
iq := xmpp.Iq{Id: xmpp.UUID4(), Type: "get", To: client.JID.Domain} iq := xmpp.IQ{ID: xmpp.UUID4(), Type: "get", To: client.JID.Domain}
iq.PayloadEncode(info) iq.PayloadEncode(info)
reply, _ := client.SendRecv(&iq) reply, _ := client.SendRecv(&iq)
reply.PayloadDecode(info) reply.PayloadDecode(info)

View File

@ -93,14 +93,13 @@ func startClient(stream *Stream, jid JID) error {
}, },
} }
if rstart, err := stream.SendStart(&start); err != nil { rstart, err := stream.SendStart(&start)
if err != nil {
return err return err
} else {
if rstart.Name != (xml.Name{nsStreams, "stream"}) {
return fmt.Errorf("unexpected start element: %s", rstart.Name)
}
} }
if rstart.Name != (xml.Name{nsStreams, "stream"}) {
return fmt.Errorf("unexpected start element: %s", rstart.Name)
}
return nil return nil
} }
@ -137,7 +136,7 @@ func authenticate(stream *Stream, mechanisms []string, user, password string) er
return nil return nil
} }
} }
return errors.New("No supported SASL mechanism found.") return errors.New("no supported SASL mechanism found")
} }
type authHandler struct { type authHandler struct {
@ -158,26 +157,26 @@ func authenticatePlain(stream *Stream, user, password string) error {
} }
func authenticateResponse(stream *Stream) error { func authenticateResponse(stream *Stream) error {
if se, err := stream.Next(); err != nil { se, err := stream.Next()
if err != nil {
return err return err
} else {
switch se.Name.Local {
case "success":
if err := stream.Skip(); err != nil {
return err
}
return nil
case "failure":
f := new(saslFailure)
if err := stream.Decode(f, se); err != nil {
return err
}
return fmt.Errorf("Authentication failed: %s", f.Reason.Local)
default:
return fmt.Errorf("Unexpected: %s", se.Name)
}
} }
panic("unreachable")
switch se.Name.Local {
case "success":
if err := stream.Skip(); err != nil {
return err
}
return nil
case "failure":
f := new(saslFailure)
if err := stream.Decode(f, se); err != nil {
return err
}
return fmt.Errorf("Authentication failed: %s", f.Reason.Local)
default:
return fmt.Errorf("Unexpected: %s", se.Name)
}
} }
type saslAuth struct { type saslAuth struct {
@ -188,29 +187,29 @@ type saslAuth struct {
func bindResource(stream *Stream, jid JID) (JID, error) { func bindResource(stream *Stream, jid JID) (JID, error) {
req := Iq{Id: UUID4(), Type: "set"} req := IQ{ID: UUID4(), Type: "set"}
if jid.Resource == "" { if jid.Resource == "" {
req.PayloadEncode(bindIq{}) req.PayloadEncode(bindIQ{})
} else { } else {
req.PayloadEncode(bindIq{Resource: jid.Resource}) req.PayloadEncode(bindIQ{Resource: jid.Resource})
} }
if err := stream.Send(req); err != nil { if err := stream.Send(req); err != nil {
return JID{}, err return JID{}, err
} }
resp := Iq{} resp := IQ{}
err := stream.Decode(&resp, nil) err := stream.Decode(&resp, nil)
if err != nil { if err != nil {
return JID{}, err return JID{}, err
} }
bindResp := bindIq{} bindResp := bindIQ{}
resp.PayloadDecode(&bindResp) resp.PayloadDecode(&bindResp)
boundJID, err := ParseJID(bindResp.JID) boundJID, err := ParseJID(bindResp.JID)
return boundJID, nil return boundJID, nil
} }
type bindIq struct { type bindIQ struct {
XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-bind bind"` XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-bind bind"`
Resource string `xml:"resource,omitempty"` Resource string `xml:"resource,omitempty"`
JID string `xml:"jid,omitempty"` JID string `xml:"jid,omitempty"`
@ -218,13 +217,13 @@ type bindIq struct {
func establishSession(stream *Stream, domain string) error { func establishSession(stream *Stream, domain string) error {
req := Iq{Id: UUID4(), Type: "set", To: domain} req := IQ{ID: UUID4(), Type: "set", To: domain}
req.PayloadEncode(&session{}) req.PayloadEncode(&session{})
if err := stream.Send(req); err != nil { if err := stream.Send(req); err != nil {
return err return err
} }
resp := Iq{} resp := IQ{}
if err := stream.Decode(&resp, nil); err != nil { if err := stream.Decode(&resp, nil); err != nil {
return err return err
} else if resp.Error != nil { } else if resp.Error != nil {

View File

@ -10,12 +10,12 @@ import (
// Create a component XMPP connection over the stream. // Create a component XMPP connection over the stream.
func NewComponentXMPP(stream *Stream, jid JID, secret string) (*XMPP, error) { func NewComponentXMPP(stream *Stream, jid JID, secret string) (*XMPP, error) {
streamId, err := startComponent(stream, jid) streamID, err := startComponent(stream, jid)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := handshake(stream, streamId, secret); err != nil { if err := handshake(stream, streamID, secret); err != nil {
return nil, err return nil, err
} }
@ -33,34 +33,33 @@ func startComponent(stream *Stream, jid JID) (string, error) {
}, },
} }
var streamId string var streamID string
if rstart, err := stream.SendStart(&start); err != nil { rstart, err := stream.SendStart(&start)
if err != nil {
return "", err return "", err
} else { }
if rstart.Name != (xml.Name{nsStreams, "stream"}) { if rstart.Name != (xml.Name{nsStreams, "stream"}) {
return "", fmt.Errorf("unexpected start element: %s", rstart.Name) return "", fmt.Errorf("unexpected start element: %s", rstart.Name)
} }
// Find the stream id. // Find the stream id.
for _, attr := range rstart.Attr { for _, attr := range rstart.Attr {
if attr.Name.Local == "id" { if attr.Name.Local == "id" {
streamId = attr.Value streamID = attr.Value
break break
}
} }
} }
if streamID == "" {
if streamId == "" {
return "", errors.New("Missing stream id") return "", errors.New("Missing stream id")
} }
return streamId, nil return streamID, nil
} }
func handshake(stream *Stream, streamId, secret string) error { func handshake(stream *Stream, streamID, secret string) error {
hash := sha1.New() hash := sha1.New()
hash.Write([]byte(streamId)) hash.Write([]byte(streamID))
hash.Write([]byte(secret)) hash.Write([]byte(secret))
// Send handshake. // Send handshake.
@ -70,18 +69,14 @@ func handshake(stream *Stream, streamId, secret string) error {
} }
// Get handshake response. // Get handshake response.
if start, err := stream.Next(); err != nil { start, err := stream.Next()
return err if err != nil {
} else {
if start.Name != (xml.Name{nsComponentAccept, "handshake"}) {
return fmt.Errorf("Expected <handshake/>, for %s", start.Name)
}
}
if err := stream.Skip(); err != nil {
return err return err
} }
if start.Name != (xml.Name{nsComponentAccept, "handshake"}) {
return nil return fmt.Errorf("Expected <handshake/>, for %s", start.Name)
}
return stream.Skip()
} }
type saslHandshake struct { type saslHandshake struct {

View File

@ -16,7 +16,7 @@ type Disco struct {
XMPP *XMPP XMPP *XMPP
} }
// Iq get/result payload for "info" requests. // IQ get/result payload for "info" requests.
type DiscoInfo struct { type DiscoInfo struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info query"` XMLName xml.Name `xml:"http://jabber.org/protocol/disco#info query"`
Node string `xml:"node,attr"` Node string `xml:"node,attr"`
@ -36,7 +36,7 @@ type DiscoFeature struct {
Var string `xml:"var,attr"` Var string `xml:"var,attr"`
} }
// Iq get/result payload for "items" requests. // IQ get/result payload for "items" requests.
type DiscoItems struct { type DiscoItems struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/disco#items query"` XMLName xml.Name `xml:"http://jabber.org/protocol/disco#items query"`
Node string `xml:"node,attr"` Node string `xml:"node,attr"`
@ -57,7 +57,7 @@ func (disco *Disco) Info(to, from string) (*DiscoInfo, error) {
from = disco.XMPP.JID.Full() from = disco.XMPP.JID.Full()
} }
req := &Iq{Id: UUID4(), Type: IQTypeGet, To: to, From: from} req := &IQ{ID: UUID4(), Type: IQTypeGet, To: to, From: from}
req.PayloadEncode(&DiscoInfo{}) req.PayloadEncode(&DiscoInfo{})
resp, err := disco.XMPP.SendRecv(req) resp, err := disco.XMPP.SendRecv(req)
@ -80,7 +80,7 @@ func (disco *Disco) Items(to, from, node string) (*DiscoItems, error) {
from = disco.XMPP.JID.Full() from = disco.XMPP.JID.Full()
} }
req := &Iq{Id: UUID4(), Type: IQTypeGet, To: to, From: from} req := &IQ{ID: UUID4(), Type: IQTypeGet, To: to, From: from}
req.PayloadEncode(&DiscoItems{Node: node}) req.PayloadEncode(&DiscoItems{Node: node})
resp, err := disco.XMPP.SendRecv(req) resp, err := disco.XMPP.SendRecv(req)
@ -101,7 +101,7 @@ var discoNamespacePrefix = strings.Split(NSDiscoInfo, "#")[0]
// Matcher instance to match <iq/> stanzas with a disco payload. // Matcher instance to match <iq/> stanzas with a disco payload.
var DiscoPayloadMatcher = MatcherFunc( var DiscoPayloadMatcher = MatcherFunc(
func(v interface{}) bool { func(v interface{}) bool {
iq, ok := v.(*Iq) iq, ok := v.(*IQ)
if !ok { if !ok {
return false return false
} }

View File

@ -8,7 +8,7 @@ import (
const ( const (
// Standard port for XMPP clients to connect to. // Standard port for XMPP clients to connect to.
XMPP_CLIENT_PORT = 5222 ClientPort = 5222
) )
// Perform a DNS SRV lookup and return an ordered list of "host:port" TCP // Perform a DNS SRV lookup and return an ordered list of "host:port" TCP
@ -22,7 +22,7 @@ func HomeServerAddrs(jid JID) (addr []string, err error) {
// If there's nothing in DNS then assume the JID's domain and the standard // If there's nothing in DNS then assume the JID's domain and the standard
// port will work. // port will work.
if len(addrs) == 0 { if len(addrs) == 0 {
addr = []string{fmt.Sprintf("%s:%d", jid.Domain, XMPP_CLIENT_PORT)} addr = []string{fmt.Sprintf("%s:%d", jid.Domain, ClientPort)}
return return
} }

View File

@ -33,7 +33,7 @@ shutdown or any other error for something unexpected). The channel is also
closed after an error. closed after an error.
XMPP defines four types of stanza: <error/>, <iq/>, <message/> and <presence/> XMPP defines four types of stanza: <error/>, <iq/>, <message/> and <presence/>
represented by Error, Iq, Message (shown below) and Presence structs represented by Error, IQ, Message (shown below) and Presence structs
respectively. respectively.
for i := range X.In { for i := range X.In {

View File

@ -11,7 +11,7 @@ const (
// XEP-0070: Verifying HTTP Requests via XMPP // XEP-0070: Verifying HTTP Requests via XMPP
type Confirm struct { type Confirm struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/http-auth confirm"` XMLName xml.Name `xml:"http://jabber.org/protocol/http-auth confirm"`
Id string `xml:"id,attr"` ID string `xml:"id,attr"`
Method string `xml:"method,attr"` Method string `xml:"method,attr"`
URL string `xml:"url,attr"` URL string `xml:"url,attr"`
} }

View File

@ -18,9 +18,9 @@ const (
) )
// XMPP <iq/> stanza. // XMPP <iq/> stanza.
type Iq struct { type IQ struct {
XMLName xml.Name `xml:"iq"` XMLName xml.Name `xml:"iq"`
Id string `xml:"id,attr"` ID string `xml:"id,attr"`
Type string `xml:"type,attr"` Type string `xml:"type,attr"`
To string `xml:"to,attr,omitempty"` To string `xml:"to,attr,omitempty"`
From string `xml:"from,attr,omitempty"` From string `xml:"from,attr,omitempty"`
@ -30,7 +30,7 @@ type Iq struct {
// Encode the value to an XML string and set as the payload. See xml.Marshal // Encode the value to an XML string and set as the payload. See xml.Marshal
// for how the value is encoded. // for how the value is encoded.
func (iq *Iq) PayloadEncode(v interface{}) error { func (iq *IQ) PayloadEncode(v interface{}) error {
bytes, err := xml.Marshal(v) bytes, err := xml.Marshal(v)
if err != nil { if err != nil {
return err return err
@ -41,12 +41,12 @@ func (iq *Iq) PayloadEncode(v interface{}) error {
// Decode the payload (an XML string) into the given value. See xml.Unmarshal // Decode the payload (an XML string) into the given value. See xml.Unmarshal
// for how the value is decoded. // for how the value is decoded.
func (iq *Iq) PayloadDecode(v interface{}) error { func (iq *IQ) PayloadDecode(v interface{}) error {
return xml.Unmarshal([]byte(iq.Payload), v) return xml.Unmarshal([]byte(iq.Payload), v)
} }
// Return the name of the payload element. // Return the name of the payload element.
func (iq *Iq) PayloadName() (name xml.Name) { func (iq *IQ) PayloadName() (name xml.Name) {
dec := xml.NewDecoder(bytes.NewBufferString(iq.Payload)) dec := xml.NewDecoder(bytes.NewBufferString(iq.Payload))
tok, err := dec.Token() tok, err := dec.Token()
if err != nil { if err != nil {
@ -59,16 +59,16 @@ func (iq *Iq) PayloadName() (name xml.Name) {
return start.Name return start.Name
} }
// Create a response Iq. The Id is kept, To and From are reversed, Type is set // Create a response IQ. The ID is kept, To and From are reversed, Type is set
// to the given value. // to the given value.
func (iq *Iq) Response(type_ string) *Iq { func (iq *IQ) Response(iqType string) *IQ {
return &Iq{Id: iq.Id, Type: type_, From: iq.To, To: iq.From} return &IQ{ID: iq.ID, Type: iqType, From: iq.To, To: iq.From}
} }
// XMPP <message/> stanza. // XMPP <message/> stanza.
type Message struct { type Message struct {
XMLName xml.Name `xml:"message"` XMLName xml.Name `xml:"message"`
Id string `xml:"id,attr,omitempty"` ID string `xml:"id,attr,omitempty"`
Type string `xml:"type,attr,omitempty"` Type string `xml:"type,attr,omitempty"`
To string `xml:"to,attr,omitempty"` To string `xml:"to,attr,omitempty"`
From string `xml:"from,attr,omitempty"` From string `xml:"from,attr,omitempty"`
@ -95,7 +95,7 @@ type MessageBody struct {
// XMPP <presence/> stanza. // XMPP <presence/> stanza.
type Presence struct { type Presence struct {
XMLName xml.Name `xml:"presence"` XMLName xml.Name `xml:"presence"`
Id string `xml:"id,attr,omitempty"` ID string `xml:"id,attr,omitempty"`
Type string `xml:"type,attr,omitempty"` Type string `xml:"type,attr,omitempty"`
To string `xml:"to,attr,omitempty"` To string `xml:"to,attr,omitempty"`
From string `xml:"from,attr,omitempty"` From string `xml:"from,attr,omitempty"`
@ -115,12 +115,11 @@ type Error struct {
} }
func (e Error) Error() string { func (e Error) Error() string {
if text := e.Text(); text == "" { text := e.Text()
if text == "" {
return fmt.Sprintf("[%s] %s", e.Type, e.Condition().Local) return fmt.Sprintf("[%s] %s", e.Type, e.Condition().Local)
} else {
return fmt.Sprintf("[%s] %s, %s", e.Type, e.Condition().Local, text)
} }
panic("unreachable") return fmt.Sprintf("[%s] %s, %s", e.Type, e.Condition().Local, text)
} }
type errorText struct { type errorText struct {

View File

@ -30,7 +30,7 @@ type Stream struct {
incomingNamespace nsMap incomingNamespace nsMap
} }
// Create a XML stream connection. A Steam is used by an XMPP instance to // Create a XML stream connection. A Stream is used by an XMPP instance to
// handle sending and receiving XML data over the net connection. // handle sending and receiving XML data over the net connection.
func NewStream(addr string, config *StreamConfig) (*Stream, error) { func NewStream(addr string, config *StreamConfig) (*Stream, error) {
@ -148,11 +148,11 @@ func (stream *Stream) Next() (*xml.StartElement, error) {
} }
if stream.config.LogStanzas { if stream.config.LogStanzas {
if xml, err := collectElement(stream.dec, start, stream.incomingNamespace); err != nil { xml, err := collectElement(stream.dec, start, stream.incomingNamespace)
if err != nil {
return nil, err return nil, err
} else {
stream.stanzaBuf = xml
} }
stream.stanzaBuf = xml
log.Println("recv:", stream.stanzaBuf) log.Println("recv:", stream.stanzaBuf)
} }
@ -170,7 +170,7 @@ func nextStartElement(dec *xml.Decoder) (*xml.StartElement, error) {
} }
switch e := t.(type) { switch e := t.(type) {
case xml.StartElement: case xml.StartElement:
for i, _ := range e.Attr { for i := range e.Attr {
// Replace URL namespace to xml in order to avoid error on Unmarshal // Replace URL namespace to xml in order to avoid error on Unmarshal
// It's quite ugly, but working for now // It's quite ugly, but working for now
if e.Attr[i].Name.Space == "http://www.w3.org/XML/1998/namespace" { if e.Attr[i].Name.Space == "http://www.w3.org/XML/1998/namespace" {
@ -183,7 +183,6 @@ func nextStartElement(dec *xml.Decoder) (*xml.StartElement, error) {
return nil, io.EOF return nil, io.EOF
} }
} }
panic("Unreachable")
} }
// Skip reads tokens until it reaches the end element of the most recent start // Skip reads tokens until it reaches the end element of the most recent start
@ -205,11 +204,11 @@ func (stream *Stream) Decode(v interface{}, start *xml.StartElement) error {
// Explicity lookup next start element to ensure stream is validated, // Explicity lookup next start element to ensure stream is validated,
// stanza is logged, etc. // stanza is logged, etc.
if start == nil { if start == nil {
if se, err := stream.Next(); err != nil { se, err := stream.Next()
if err != nil {
return err return err
} else {
start = se
} }
start = se
} }
if stream.config.LogStanzas { if stream.config.LogStanzas {

View File

@ -76,14 +76,13 @@ func writeXMLAttr(w io.Writer, attr xml.Attr) error {
func startElementIter(dec *xml.Decoder) func() *xml.StartElement { func startElementIter(dec *xml.Decoder) func() *xml.StartElement {
return func() *xml.StartElement { return func() *xml.StartElement {
for { for {
if tok, err := dec.Token(); err != nil { tok, err := dec.Token()
if err != nil {
return nil return nil
} else { }
if start, ok := tok.(xml.StartElement); ok { if start, ok := tok.(xml.StartElement); ok {
return &start return &start
}
} }
} }
return nil
} }
} }

View File

@ -18,19 +18,19 @@ type XMPP struct {
JID JID JID JID
stream *Stream stream *Stream
// Channel of incoming messages. Values will be one of Iq, Message, // 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 // Presence, Error or error. Will be closed at the end when the stream is
// closed or the stream's net connection dies. // closed or the stream's net connection dies.
In chan interface{} In chan interface{}
// Channel of outgoing messages. Messages must be able to be marshaled by // 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, // the standard xml package, however you should try to send one of IQ,
// Message or Presence. // Message or Presence.
Out chan interface{} Out chan interface{}
// Incoming stanza filters. // Incoming stanza filters.
filterLock sync.Mutex filterLock sync.Mutex
nextFilterId FilterId nextFilterID FilterID
filters []filter filters []filter
} }
@ -46,17 +46,17 @@ func newXMPP(jid JID, stream *Stream) *XMPP {
return x return x
} }
func (x *XMPP) SendRecv(iq *Iq) (*Iq, error) { func (x *XMPP) SendRecv(iq *IQ) (*IQ, error) {
fid, ch := x.AddFilter(IqResult(iq.Id)) fid, ch := x.AddFilter(IQResult(iq.ID))
defer x.RemoveFilter(fid) defer x.RemoveFilter(fid)
x.Out <- iq x.Out <- iq
stanza := <-ch stanza := <-ch
reply, ok := stanza.(*Iq) reply, ok := stanza.(*IQ)
if !ok { if !ok {
return nil, fmt.Errorf("Expected Iq, for %T", stanza) return nil, fmt.Errorf("Expected IQ, for %T", stanza)
} }
return reply, nil return reply, nil
} }
@ -76,25 +76,25 @@ func (fn MatcherFunc) Match(v interface{}) bool {
return fn(v) return fn(v)
} }
// Uniquly identifies a stream fiter. Used to remove a filter that's no longer // Uniquely identifies a stream filter. Used to remove a filter that's no
// needed. // longer needed.
type FilterId int64 type FilterID int64
// Implements the error interface for a FilterId. // Implements the error interface for a FilterID.
func (fid FilterId) Error() string { func (fid FilterID) Error() string {
return fmt.Sprintf("Invalid filter id: %d", fid) return fmt.Sprintf("Invalid filter id: %d", fid)
} }
type filter struct { type filter struct {
id FilterId id FilterID
m Matcher m Matcher
ch chan interface{} ch chan interface{}
} }
// Add a filter that routes matching stanzas to the returned channel. A // 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 // FilterID is also returned and can be pased to RemoveFilter to remove the
// filter again. // filter again.
func (x *XMPP) AddFilter(m Matcher) (FilterId, chan interface{}) { func (x *XMPP) AddFilter(m Matcher) (FilterID, chan interface{}) {
// Protect against concurrent access. // Protect against concurrent access.
x.filterLock.Lock() x.filterLock.Lock()
@ -102,8 +102,8 @@ func (x *XMPP) AddFilter(m Matcher) (FilterId, chan interface{}) {
// Allocate chan and id. // Allocate chan and id.
ch := make(chan interface{}) ch := make(chan interface{})
id := x.nextFilterId id := x.nextFilterID
x.nextFilterId++ x.nextFilterID++
// Insert at head of filters list. // Insert at head of filters list.
filters := make([]filter, len(x.filters)+1) filters := make([]filter, len(x.filters)+1)
@ -115,7 +115,7 @@ func (x *XMPP) AddFilter(m Matcher) (FilterId, chan interface{}) {
} }
// Remove a filter previously added with AddFilter. // Remove a filter previously added with AddFilter.
func (x *XMPP) RemoveFilter(id FilterId) error { func (x *XMPP) RemoveFilter(id FilterID) error {
// Protect against concurrent access. // Protect against concurrent access.
x.filterLock.Lock() x.filterLock.Lock()
@ -145,14 +145,14 @@ func (x *XMPP) RemoveFilter(id FilterId) error {
// Matcher to identify a <iq id="..." type="result" /> stanza with the given // Matcher to identify a <iq id="..." type="result" /> stanza with the given
// id. // id.
func IqResult(id string) Matcher { func IQResult(id string) Matcher {
return MatcherFunc( return MatcherFunc(
func(v interface{}) bool { func(v interface{}) bool {
iq, ok := v.(*Iq) iq, ok := v.(*IQ)
if !ok { if !ok {
return false return false
} }
if iq.Id != id { if iq.ID != id {
return false return false
} }
return true return true
@ -193,13 +193,13 @@ func (x *XMPP) receiver() {
case "error": case "error":
v = &Error{} v = &Error{}
case "iq": case "iq":
v = &Iq{} v = &IQ{}
case "message": case "message":
v = &Message{} v = &Message{}
case "presence": case "presence":
v = &Presence{} v = &Presence{}
default: default:
log.Println("Error. Unexected element: %T %v", start, start) log.Printf("Error. Unexected element: %T %v", start, start)
} }
err = x.stream.Decode(v, start) err = x.stream.Decode(v, start)