func()

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)
}