func (r *Route) AddMatcher(m Matcher) *Route {
	r.matchers = append(r.matchers, m)
	return r
}
AddMatcher adds a matcher to the route
package xmpp
import (
	"context"
	"encoding/xml"
	"strings"
	"sync"
	"gosrc.io/xmpp/stanza"
)
type Router struct {
	routes []*Route
	IQResultRoutes    map[string]*IQResultRoute
	IQResultRouteLock sync.RWMutex
}
func NewRouter() *Router {
	return &Router{
		IQResultRoutes: make(map[string]*IQResultRoute),
	}
}
func (r *Router) route(s Sender, p stanza.Packet) {
	a, isA := p.(stanza.SMAnswer)
	if isA {
		switch tt := s.(type) {
		case *Client:
			lastAcked := a.H
			SendMissingStz(int(lastAcked), s, tt.Session.SMState.UnAckQueue)
		case *Component:
		default:
		}
	}
	iq, isIq := p.(*stanza.IQ)
	if isIq {
		r.IQResultRouteLock.RLock()
		route, ok := r.IQResultRoutes[iq.Id]
		r.IQResultRouteLock.RUnlock()
		if ok {
			r.IQResultRouteLock.Lock()
			delete(r.IQResultRoutes, iq.Id)
			r.IQResultRouteLock.Unlock()
			route.result <- *iq
			close(route.result)
			return
		}
	}
	var match RouteMatch
	if r.Match(p, &match) {
		match.Handler.HandlePacket(s, p)
		return
	}
	if isIq && (iq.Type == stanza.IQTypeGet || iq.Type == stanza.IQTypeSet) {
		iqNotImplemented(s, iq)
	}
}
func SendMissingStz(lastSent int, s Sender, uaq *stanza.UnAckQueue) error {
	uaq.RWMutex.Lock()
	if len(uaq.Uslice) <= 0 {
		uaq.RWMutex.Unlock()
		return nil
	}
	last := uaq.Uslice[len(uaq.Uslice)-1]
	if last.Id > lastSent {
		uaq.PopN(lastSent - last.Id)
		for _, elt := range uaq.PopN(len(uaq.Uslice)) {
			eltStz := elt.(*stanza.UnAckedStz)
			err := s.SendRaw(eltStz.Stz)
			if err != nil {
				return err
			}
		}
		s.Send(stanza.SMRequest{})
	}
	uaq.RWMutex.Unlock()
	return nil
}
func iqNotImplemented(s Sender, iq *stanza.IQ) {
	err := stanza.Err{
		XMLName: xml.Name{Local: "error"},
		Code:    501,
		Type:    "cancel",
		Reason:  "feature-not-implemented",
	}
	reply := iq.MakeError(err)
	_ = s.Send(reply)
}
func (r *Router) NewRoute() *Route {
	route := &Route{}
	r.routes = append(r.routes, route)
	return route
}
func (r *Router) NewIQResultRoute(ctx context.Context, id string) chan stanza.IQ {
	route := NewIQResultRoute(ctx)
	r.IQResultRouteLock.Lock()
	r.IQResultRoutes[id] = route
	r.IQResultRouteLock.Unlock()
	go func() {
		<-route.context.Done()
		r.IQResultRouteLock.Lock()
		delete(r.IQResultRoutes, id)
		r.IQResultRouteLock.Unlock()
	}()
	return route.result
}
func (r *Router) Match(p stanza.Packet, match *RouteMatch) bool {
	for _, route := range r.routes {
		if route.Match(p, match) {
			return true
		}
	}
	return false
}
func (r *Router) Handle(name string, handler Handler) *Route {
	return r.NewRoute().Packet(name).Handler(handler)
}
func (r *Router) HandleFunc(name string, f func(s Sender, p stanza.Packet)) *Route {
	return r.NewRoute().Packet(name).HandlerFunc(f)
}
type TimeoutHandlerFunc func(err error)
type IQResultRoute struct {
	context context.Context
	result  chan stanza.IQ
}
func NewIQResultRoute(ctx context.Context) *IQResultRoute {
	return &IQResultRoute{
		context: ctx,
		result:  make(chan stanza.IQ),
	}
}
type IQResultHandler interface {
	HandleIQ(ctx context.Context, s Sender, iq stanza.IQ)
}
type IQResultHandlerFunc func(ctx context.Context, s Sender, iq stanza.IQ)
func (f IQResultHandlerFunc) HandleIQ(ctx context.Context, s Sender, iq stanza.IQ) {
	f(ctx, s, iq)
}
type Handler interface {
	HandlePacket(s Sender, p stanza.Packet)
}
type Route struct {
	handler Handler
	matchers []Matcher
}
func (r *Route) Handler(handler Handler) *Route {
	r.handler = handler
	return r
}
type HandlerFunc func(s Sender, p stanza.Packet)
func (f HandlerFunc) HandlePacket(s Sender, p stanza.Packet) {
	f(s, p)
}
func (r *Route) HandlerFunc(f HandlerFunc) *Route {
	return r.Handler(f)
}