@ -51,8 +51,8 @@ func (r *Router) route(s Sender, p stanza.Packet) {
r . IQResultRouteLock . Lock ( )
r . IQResultRouteLock . Lock ( )
delete ( r . IQResultRoutes , iq . Id )
delete ( r . IQResultRoutes , iq . Id )
r . IQResultRouteLock . Unlock ( )
r . IQResultRouteLock . Unlock ( )
close ( route . matched )
route . result <- iq
route . handler . HandleIQ ( route . context , s , iq )
close ( route . result )
return
return
}
}
}
}
@ -91,29 +91,22 @@ func (r *Router) NewRoute() *Route {
// NewIQResultRoute register a route that will catch an IQ result stanza with
// NewIQResultRoute register a route that will catch an IQ result stanza with
// the given Id. The route will only match ones, after which it will automatically
// the given Id. The route will only match ones, after which it will automatically
// be unregistered
// be unregistered
func ( r * Router ) NewIQResultRoute ( ctx context . Context , id string ) * IQResultRoute {
func ( r * Router ) NewIQResultRoute ( ctx context . Context , id string ) chan stanza . IQ {
route := & IQResultRoute {
route := NewIQResultRoute ( ctx )
context : ctx ,
matched : make ( chan struct { } ) ,
}
r . IQResultRouteLock . Lock ( )
r . IQResultRouteLock . Lock ( )
r . IQResultRoutes [ id ] = route
r . IQResultRoutes [ id ] = route
r . IQResultRouteLock . Unlock ( )
r . IQResultRouteLock . Unlock ( )
// Start a go function to make sure the route is unregistered when the context
// is done.
go func ( ) {
go func ( ) {
select {
<- route . context . Done ( )
case <- route . context . Done ( ) :
r . IQResultRouteLock . Lock ( )
r . IQResultRouteLock . Lock ( )
delete ( r . IQResultRoutes , id )
delete ( r . IQResultRoutes , id )
r . IQResultRouteLock . Unlock ( )
r . IQResultRouteLock . Unlock ( )
if route . timeoutHandler != nil {
route . timeoutHandler ( route . context . Err ( ) )
}
case <- route . matched :
}
} ( )
} ( )
return route
return route . result
}
}
func ( r * Router ) Match ( p stanza . Packet , match * RouteMatch ) bool {
func ( r * Router ) Match ( p stanza . Packet , match * RouteMatch ) bool {
@ -144,28 +137,16 @@ type TimeoutHandlerFunc func(err error)
// IQResultRoute is a temporary route to match IQ result stanzas
// IQResultRoute is a temporary route to match IQ result stanzas
type IQResultRoute struct {
type IQResultRoute struct {
context context . Context
context context . Context
matched chan struct { }
result chan stanza . IQ
handler IQResultHandler
timeoutHandler TimeoutHandlerFunc
}
// Handler adds an IQ handler to the route.
func ( r * IQResultRoute ) Handler ( handler IQResultHandler ) * IQResultRoute {
r . handler = handler
return r
}
// HandlerFunc updates the route to call a handler function when an IQ result is received.
func ( r * IQResultRoute ) HandlerFunc ( f IQResultHandlerFunc ) * IQResultRoute {
return r . Handler ( f )
}
}
// TimeoutHandlerFunc registers a function that will be called automatically when
// NewIQResultRoute creates a new IQResultRoute instance
// the IQ result route is cancelled (most likely due to a timeout on the context).
func NewIQResultRoute ( ctx context . Context ) * IQResultRoute {
func ( r * IQResultRoute ) TimeoutHandlerFunc ( f TimeoutHandlerFunc ) * IQResultRoute {
return & IQResultRoute {
r . timeoutHandler = f
context : ctx ,
return r
result : make ( chan stanza . IQ ) ,
}
}
}
// ============================================================================
// ============================================================================