Skip to content

Commit

Permalink
all: implement server side of disco#info
Browse files Browse the repository at this point in the history
This finally closes the long standing need for service discovery by
implementing the new design doc from https://mellium.im/design/28_disco!

Fixes #28

Signed-off-by: Sam Whited <sam@samwhited.com>
  • Loading branch information
SamWhited committed Aug 10, 2021
1 parent 5c60fbf commit 747f792
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 1 deletion.
1 change: 1 addition & 0 deletions disco/disco.go
Expand Up @@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.

//go:generate go run gen.go
//go:generate go run ../internal/genfeature -filename features.go -receiver "h *discoHandler" -vars Feature:NSInfo

// Package disco implements service discovery.
package disco // import "mellium.im/xmpp/disco"
Expand Down
2 changes: 1 addition & 1 deletion disco/handler.go
Expand Up @@ -15,7 +15,7 @@ import (

// Handle returns an option that configures a multiplexer to handle service
// discovery requests by iterating over its own handlers and checking if they
// implement the interfaces from the info package.
// implement info.FeatureIter.
func Handle() mux.Option {
return func(m *mux.ServeMux) {
h := &discoHandler{ServeMux: m}
Expand Down
6 changes: 6 additions & 0 deletions disco/info/feature.go
Expand Up @@ -38,3 +38,9 @@ func (f Feature) TokenReader() xml.TokenReader {
func (f Feature) WriteXML(w xmlstream.TokenWriter) (int, error) {
return xmlstream.Copy(w, f.TokenReader())
}

// FeatureIter is the interface implemented by types that implement disco
// features.
type FeatureIter interface {
ForFeatures(node string, f func(Feature) error) error
}
39 changes: 39 additions & 0 deletions mux/mux.go
Expand Up @@ -17,6 +17,7 @@ import (

"mellium.im/xmlstream"
"mellium.im/xmpp"
"mellium.im/xmpp/disco/info"
"mellium.im/xmpp/internal/ns"
"mellium.im/xmpp/stanza"
)
Expand Down Expand Up @@ -209,6 +210,44 @@ func (m *ServeMux) HandleXMPP(t xmlstream.TokenReadEncoder, start *xml.StartElem
return h.HandleXMPP(t, start)
}

// ForFeatures implements info.FeatureIter for the mux by iterating over all
// child features.
func (m *ServeMux) ForFeatures(node string, f func(info.Feature) error) error {
for _, h := range m.patterns {
if featureIter, ok := h.(info.FeatureIter); ok {
err := featureIter.ForFeatures(node, f)
if err != nil {
return err
}
}
}
for _, h := range m.iqPatterns {
if featureIter, ok := h.(info.FeatureIter); ok {
err := featureIter.ForFeatures(node, f)
if err != nil {
return err
}
}
}
for _, h := range m.msgPatterns {
if featureIter, ok := h.(info.FeatureIter); ok {
err := featureIter.ForFeatures(node, f)
if err != nil {
return err
}
}
}
for _, h := range m.presencePatterns {
if featureIter, ok := h.(info.FeatureIter); ok {
err := featureIter.ForFeatures(node, f)
if err != nil {
return err
}
}
}
return nil
}

type nopHandler struct{}

func (nopHandler) HandleXMPP(t xmlstream.TokenReadEncoder, start *xml.StartElement) error { return nil }
Expand Down
3 changes: 3 additions & 0 deletions mux/mux_test.go
Expand Up @@ -15,13 +15,16 @@ import (
"testing"

"mellium.im/xmlstream"
"mellium.im/xmpp/disco/info"
"mellium.im/xmpp/internal/marshal"
"mellium.im/xmpp/internal/ns"
"mellium.im/xmpp/internal/xmpptest"
"mellium.im/xmpp/mux"
"mellium.im/xmpp/stanza"
)

var _ info.FeatureIter = (*mux.ServeMux)(nil)

var (
errPassTest = errors.New("mux_test: PASSED")
errFailTest = errors.New("mux_test: FAILED")
Expand Down

0 comments on commit 747f792

Please sign in to comment.