public void incomingApdu(APDU apdu, Address address, OctetString linkService) throws BACnetException {
        // if (apdu.expectsReply() != npci.isExpectingReply())
        // throw new MessageValidationAssertionException("Inconsistent message: APDU expectsReply="+
        // apdu.expectsReply() +" while NPCI isExpectingReply="+ npci.isExpectingReply());

        if (apdu instanceof ConfirmedRequest) {
            ConfirmedRequest confAPDU = (ConfirmedRequest) apdu;
            byte invokeId = confAPDU.getInvokeId();

            if (confAPDU.isSegmentedMessage() && confAPDU.getSequenceNumber() > 0)
                // This is a subsequent part of a segmented message. Notify the waiting room.
                waitingRoom.notifyMember(address, linkService, invokeId, false, confAPDU);
            else {
                if (confAPDU.isSegmentedMessage()) {
                    // This is the initial part of a segmented message. Go and receive the subsequent parts.
                    WaitingRoomKey key = waitingRoom.enterServer(address, linkService, invokeId);
                    try {
                        receiveSegmented(key, confAPDU);
                    }
                    finally {
                        waitingRoom.leave(key);
                    }
                }

                // Handle the request.
                try {
                    confAPDU.parseServiceData();
                    AcknowledgementService ackService = handleConfirmedRequest(address, linkService, invokeId,
                            confAPDU.getServiceRequest());
                    sendResponse(address, linkService, confAPDU, ackService);
                }
                catch (BACnetErrorException e) {
                    network.sendAPDU(address, linkService, new Error(invokeId, e.getError()), false);
                }
                catch (BACnetRejectException e) {
                    network.sendAPDU(address, linkService, new Reject(invokeId, e.getRejectReason()), false);
                }
                catch (BACnetException e) {
                    Error error = new Error(confAPDU.getInvokeId(), new BaseError((byte) 127, new BACnetError(
                            ErrorClass.services, ErrorCode.inconsistentParameters)));
                    network.sendAPDU(address, linkService, error, false);
                    ExceptionDispatch.fireReceivedException(e);
                }
            }
        }
        else if (apdu instanceof UnconfirmedRequest) {
            UnconfirmedRequest ur = (UnconfirmedRequest) apdu;

            try {
                ur.getService().handle(localDevice, address, linkService);
            }
            catch (BACnetException e) {
                ExceptionDispatch.fireReceivedException(e);
            }
        }
        else {
            // An acknowledgement.
            AckAPDU ack = (AckAPDU) apdu;

            // Used for testing only. This is required to test the parsing of service data in an ack.
            // ((ComplexACK) ack).parseServiceData();

            waitingRoom.notifyMember(address, linkService, ack.getOriginalInvokeId(), ack.isServer(), ack);
        }
    }