Message dispatcher -- de-serialize message into PDU

def receiveMessage(self, snmpEngine, transportDomain,
                       transportAddress, wholeMsg):
        """Message dispatcher -- de-serialize message into PDU"""
        mibBuilder = self.mibInstrumController.mibBuilder

        # 4.2.1.1
        snmpInPkts, = mibBuilder.importSymbols(
            '__SNMPv2-MIB', 'snmpInPkts')
        snmpInPkts.syntax += 1

        restOfWholeMsg = null  # XXX fix decoder non-recursive return

        # 4.2.1.2
        try:
            msgVersion = verdec.decodeMessageVersion(wholeMsg)

        except error.ProtocolError:
            snmpInASNParseErrs, = mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInASNParseErrs')
            snmpInASNParseErrs.syntax += 1

            return null  # n.b the whole buffer gets dropped

        debug.logger & debug.FLAG_DSP and debug.logger(
            'receiveMessage: msgVersion %s, msg decoded' % msgVersion)

        messageProcessingModel = msgVersion

        try:
            mpHandler = snmpEngine.messageProcessingSubsystems[
                int(messageProcessingModel)]

        except KeyError:
            snmpInBadVersions, = mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInBadVersions')
            snmpInBadVersions.syntax += 1

            return restOfWholeMsg

        # 4.2.1.3 -- no-op

        # 4.2.1.4
        try:
            (messageProcessingModel,
             securityModel,
             securityName,
             securityLevel,
             contextEngineId,
             contextName,
             pduVersion,
             PDU,
             pduType,
             sendPduHandle,
             maxSizeResponseScopedPDU,
             statusInformation,
             stateReference) = mpHandler.prepareDataElements(
                snmpEngine, transportDomain, transportAddress, wholeMsg)

            debug.logger & debug.FLAG_DSP and debug.logger(
                'receiveMessage: MP succeded')

        except error.StatusInformation as exc:
            statusInformation = exc

            if 'sendPduHandle' in statusInformation:
                # Dropped REPORT -- re-run pending reqs queue as some
                # of them may be waiting for this REPORT
                debug.logger & debug.FLAG_DSP and debug.logger(
                    'receiveMessage: MP failed, statusInformation %s, '
                    'forcing retry' % statusInformation)

                self.__expireRequest(
                    statusInformation['sendPduHandle'],
                    self._cache.pop(statusInformation['sendPduHandle']),
                    snmpEngine,
                    statusInformation)

            return restOfWholeMsg

        except PyAsn1Error as exc:
            debug.logger & debug.FLAG_MP and debug.logger(
                'receiveMessage: %s' % exc)
            snmpInASNParseErrs, = mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInASNParseErrs')
            snmpInASNParseErrs.syntax += 1

            return restOfWholeMsg

        debug.logger & debug.FLAG_DSP and debug.logger(
            'receiveMessage: PDU %s' % PDU.prettyPrint())

        # 4.2.2
        if sendPduHandle is None:
            # 4.2.2.1 (request or notification)

            debug.logger & debug.FLAG_DSP and debug.logger(
                'receiveMessage: pduType %s' % pduType)

            # 4.2.2.1.1
            processPdu = self.getRegisteredApp(contextEngineId, pduType)

            # 4.2.2.1.2
            if processPdu is None:
                # 4.2.2.1.2.a
                snmpUnknownPDUHandlers, = importSymbols(
                    '__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax += 1

                # 4.2.2.1.2.b
                statusInformation = {
                    'errorIndication': errind.unknownPDUHandler,
                    'oid': snmpUnknownPDUHandlers.name,
                    'val': snmpUnknownPDUHandlers.syntax
                }

                debug.logger & debug.FLAG_DSP and debug.logger(
                    'receiveMessage: unhandled PDU type')

                # 4.2.2.1.2.c
                try:
                    (destTransportDomain,
                     destTransportAddress,
                     outgoingMessage) = mpHandler.prepareResponseMessage(
                        snmpEngine, messageProcessingModel,
                        securityModel, securityName, securityLevel,
                        contextEngineId, contextName, pduVersion,
                        PDU, maxSizeResponseScopedPDU, stateReference,
                        statusInformation)

                    snmpEngine.transportDispatcher.sendMessage(
                        outgoingMessage, destTransportDomain,
                        destTransportAddress)

                except PySnmpError as exc:
                    debug.logger & debug.FLAG_DSP and debug.logger(
                        'receiveMessage: report failed, statusInformation %s' % exc)

                else:
                    debug.logger & debug.FLAG_DSP and debug.logger(
                        'receiveMessage: reporting succeeded')

                # 4.2.2.1.2.d
                return restOfWholeMsg

            else:
                snmpEngine.observer.storeExecutionContext(
                    snmpEngine, 'rfc3412.receiveMessage:request',
                    dict(transportDomain=transportDomain,
                         transportAddress=transportAddress,
                         wholeMsg=wholeMsg,
                         messageProcessingModel=messageProcessingModel,
                         securityModel=securityModel,
                         securityName=securityName,
                         securityLevel=securityLevel,
                         contextEngineId=contextEngineId,
                         contextName=contextName,
                         pdu=PDU))

                # pass transport info to app (legacy)
                if stateReference is not None:
                    self._transportInfo[stateReference] = (
                        transportDomain, transportAddress)

                # 4.2.2.1.3 (asynchronous function)
                processPdu(
                    snmpEngine, messageProcessingModel, securityModel,
                    securityName, securityLevel, contextEngineId,
                    contextName, pduVersion, PDU, maxSizeResponseScopedPDU,
                    stateReference)

                snmpEngine.observer.clearExecutionContext(
                    snmpEngine, 'rfc3412.receiveMessage:request')

                # legacy
                if stateReference is not None:
                    del self._transportInfo[stateReference]

                debug.logger & debug.FLAG_DSP and debug.logger(
                    'receiveMessage: processPdu initiated')

                return restOfWholeMsg

        else:
            # 4.2.2.2 (response)

            # 4.2.2.2.1
            cachedParams = self._cache.pop(sendPduHandle)

            # 4.2.2.2.2
            if cachedParams is None:
                snmpUnknownPDUHandlers, = mibBuilder.importSymbols(
                    '__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax += 1

                return restOfWholeMsg

            debug.logger & debug.FLAG_DSP and debug.logger(
                'receiveMessage: cache read by sendPduHandle %s' % sendPduHandle)

            # 4.2.2.2.3
            # no-op ? XXX

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc3412.receiveMessage:response',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     wholeMsg=wholeMsg,
                     messageProcessingModel=messageProcessingModel,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     pdu=PDU))

            # 4.2.2.2.4
            processResponsePdu = cachedParams['cbFun']

            processResponsePdu(
                snmpEngine, messageProcessingModel, securityModel,
                securityName, securityLevel, contextEngineId, contextName,
                pduVersion, PDU, statusInformation,
                cachedParams['sendPduHandle'],
                cachedParams['cbCtx'])

            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc3412.receiveMessage:response')

            debug.logger & debug.FLAG_DSP and debug.logger(
                'receiveMessage: processResponsePdu succeeded')

            return restOfWholeMsg