~samwhited/xmpp

75e32aa5151568648dd2926a4b4d967959105e8b — Sam Whited 1 year, 9 months ago c517d91
design: update stanza mux

Update the mux proposal to solve the last remaining questions, and
clarify that the token stream will always contain the entire stanzas
stream, including the original start element.

Signed-off-by: Sam Whited <sam@samwhited.com>
2 files changed, 43 insertions(+), 34 deletions(-)

M CHANGELOG.md
M design/25_stanzamux.md
M CHANGELOG.md => CHANGELOG.md +1 -1
@@ 6,7 6,7 @@ All notable changes to this project will be documented in this file.

### Added

- mux: ability to route by IQ payload
- mux: ability to select handlers by stanza payload
- ping: a function for easily encoding pings and handling errors
- ping: a handler and mux option for responding to pings
- stanza: ability to convert stanzas to/from `xml.StartElement`

M design/25_stanzamux.md => design/25_stanzamux.md +42 -33
@@ 1,7 1,7 @@
# Proposal: Implement stanza handlers

**Author(s):** Sam Whited  
**Last updated:** 2020-02-17  
**Last updated:** 2020-02-26  
**Status:** accepted  
**Discussion:** https://mellium.im/issue/25



@@ 19,24 19,22 @@ on their type and payload was introduced.
In practice, registering the IQ muxer ended up being cumbersome, and the
previous proposal did not solve the problem of routing message or presence
stanzas (this was deliberately left for a future proposal).
To solve both of these problems at once the current [multiplexer] can be adapted
using what we learned from the IQ mux experiment such that it can route message
and presence stanzas based on their type, and IQs based on their type and
payload.

[IQ mux proposal]: https://mellium.im/design/18_iqmux
[multiplexer]: https://godoc.org/mellium.im/xmpp/mux#ServeMux
To solve both of these problems at once the current [multiplexer][ServeMux] can
be adapted using what we learned from the IQ mux experiment such that it can
route message and presence stanzas based on their type, and IQs based on their
type and payload.


## Requirements

 - Ability to multiplex IQ stanzas by stanza type and payload name
 - Ability to multiplex message and presence stanzas by type
 - IQ, message, presence, and other general top level elements must have their
 - Ability to multiplex stanzas by stanza type and payload name
 - IQ, message, presence, and general top-level stream elements must have their
   own distinct handler types
 - The handlers must be extensible to add functionality such as replying to IQs
   or other thought of features in the future without making breaking API
   changes to the handler itself
 - The entire stanza and all children must be able to be decoded in one pass
   with [`Decoder.Decode`] or [`Decoder.DecodeElement`]


## Proposal


@@ 58,39 56,50 @@ types would be added for messages and presence:
Adapters for functions with the provided signature would also be made available,
similar to [`HandlerFunc`].

Decoding the entire payload using an [`xml.Decoder`] requires the initial start
token which has already been consumed when creating the [`stanza.Message`],
[`stanza.IQ`], or [`stanza.Presence`].
We can't pass the start element instead of the decoded stanza type because this
limits future extensibility (we can add methods to the stanza type related to
encoding and decoding, replying, etc.), and it is undesirable to pass both
because then we are passing duplicate information to the handler.
Instead, we can prepend the start element to the buffered token stream so that
every handler has access to the entire stanza.

The existing IQ mux would be removed (this is a backwards incompatible change,
however, we are pre-1.0 and the IQ mux was never put into a release) and its
methods and functionality would be added to [`ServeMux`].
however, we are pre-1.0 and the IQ mux was never in a release) and its methods
and functionality would be added to [`ServeMux`][ServeMux].

The options related to registering stanzas would then be modified to take the
new patterns as follows:

    func IQ(typ stanza.IQType, payload xml.Name, h IQHandler) Option
        IQ returns an option that matches IQ stanzas based on their type and the
        name of the payload.
        IQ returns an option that matches IQ stanzas by type and payload name.

    func Message(typ stanza.MessageType, h MessageHandler) Option
        Message returns an option that matches message stanzas by type.
    func Message(typ stanza.MessageType, payload xml.Name, h MessageHandler) Option
        Message returns an option that matches message stanzas by type and
        payload name.

    func Presence(typ stanza.PresenceType, h PresenceHandler) Option
        Presence returns an option that matches presence stanzas by type.
    func Presence(typ stanza.PresenceType, payload xml.Name, h PresenceHandler) Option
        Presence returns an option that matches presence stanzas by type and
        payload name.

Functional versions of these options (taking a `HandlerFunc`) would also be
added.


[`Handler`]: https://godoc.org/mellium.im/xmpp#Handler
[`IQHandler`]: https://godoc.org/mellium.im/xmpp/mux#IQHandler
[`HandlerFunc`]: https://godoc.org/mellium.im/xmpp#HandlerFunc
[`ServeMux`]: https://godoc.org/mellium.im/xmpp/mux#ServeMux
Registering a handler that matches a stanza using the [`Handle`] option will
cause a panic, but this behavior is subject to change in the future.


## Open Questions

- What happens if the normal [`Handle`] options are used to register a handler
  that would match stanzas?
- We still need some way to match on Message/Presence payloads, otherwise how do
  we have different handlers for eg. IBB data payloads or messages with a body.


[`Handle`]: https://godoc.org/mellium.im/xmpp/mux#Handle
[IQ mux proposal]: https://mellium.im/design/18_iqmux
[`Decoder.Decode`]: https://golang.org/pkg/encoding/xml/#Decoder.Decode
[`Decoder.DecodeElement`]: https://golang.org/pkg/encoding/xml/#Decoder.DecodeElement
[`Handler`]: https://pkg.go.dev/mellium.im/xmpp#Handler
[`IQHandler`]: https://pkg.go.dev/mellium.im/xmpp/mux#IQHandler
[`HandlerFunc`]: https://pkg.go.dev/mellium.im/xmpp#HandlerFunc
[`stanza.Message`]: https://pkg.go.dev/mellium.im/xmpp/stanza#Message
[`stanza.IQ`]: https://pkg.go.dev/mellium.im/xmpp/stanza#IQ
[`stanza.Presence`]: https://pkg.go.dev/mellium.im/xmpp/stanza#Presence
[`xml.Decoder`]: https://golang.org/pkg/encoding/xml/#Decoder
[ServeMux]: https://pkg.go.dev/mellium.im/xmpp/mux#ServeMux
[`Handle`]: https://pkg.go.dev/mellium.im/xmpp/mux#Handle