in inbound.go [175:228]
func (c *Connection) dispatchInbound(_ uint32, _ uint32, call *InboundCall, frame *Frame) {
if call.log.Enabled(LogLevelDebug) {
call.log.Debugf("Received incoming call for %s from %s", call.ServiceName(), c.remotePeerInfo)
}
if err := call.readMethod(); err != nil {
call.log.WithFields(
LogField{"remotePeer", c.remotePeerInfo},
ErrField(err),
).Error("Couldn't read method.")
c.opts.FramePool.Release(frame)
return
}
call.commonStatsTags["endpoint"] = call.methodString
call.statsReporter.IncCounter("inbound.calls.recvd", call.commonStatsTags, 1)
if span := call.response.span; span != nil {
span.SetOperationName(call.methodString)
}
// TODO(prashant): This is an expensive way to check for cancellation. Use a heap for timeouts.
go func() {
select {
case <-call.mex.ctx.Done():
// checking if message exchange timedout or was cancelled
// only two possible errors at this step:
// context.DeadlineExceeded
// context.Canceled
if call.mex.ctx.Err() != nil {
call.mex.inboundExpired()
}
case <-call.mex.errCh.c:
if c.log.Enabled(LogLevelDebug) {
call.log.Debugf("Wait for timeout/cancellation interrupted by error: %v", call.mex.errCh.err)
}
// when an exchange errors out, mark the exchange as expired
// and call cancel so the server handler's context is canceled
// TODO: move the cancel to the parent context at connnection level
call.response.cancel()
call.mex.inboundExpired()
}
}()
// Internal handlers (e.g., introspection) trump all other user-registered handlers on
// the "tchannel" name.
if call.ServiceName() == "tchannel" {
if h := c.internalHandlers.find(call.Method()); h != nil {
h.Handle(call.mex.ctx, call)
return
}
}
c.handler.Handle(call.mex.ctx, call)
}