Пример #1
0
        public bool HandleFileAsdu(ASDU asdu)
        {
            bool asduHandled = true;

            switch (asdu.TypeId)
            {
            case TypeID.F_SC_NA_1:             /* File/Section/Directory Call/Select */

                DebugLog("Received SELECT/CALL");

                if (state == FileClientState.WAITING_FOR_FILE_READY)
                {
                    if (asdu.Cot == CauseOfTransmission.UNKNOWN_TYPE_ID)
                    {
                        if (fileReceiver != null)
                        {
                            fileReceiver.Finished(FileErrorCode.UNKNOWN_SERVICE);
                        }
                    }
                    else if (asdu.Cot == CauseOfTransmission.UNKNOWN_COMMON_ADDRESS_OF_ASDU)
                    {
                        if (fileReceiver != null)
                        {
                            fileReceiver.Finished(FileErrorCode.UNKNOWN_CA);
                        }
                    }
                    else if (asdu.Cot == CauseOfTransmission.UNKNOWN_INFORMATION_OBJECT_ADDRESS)
                    {
                        if (fileReceiver != null)
                        {
                            fileReceiver.Finished(FileErrorCode.UNKNOWN_IOA);
                        }
                    }
                    else
                    {
                        if (fileReceiver != null)
                        {
                            fileReceiver.Finished(FileErrorCode.PROTOCOL_ERROR);
                        }
                    }
                }
                else
                {
                    if (fileReceiver != null)
                    {
                        fileReceiver.Finished(FileErrorCode.PROTOCOL_ERROR);
                    }
                }

                ResetStateToIdle();

                break;

            case TypeID.F_FR_NA_1:             /* File ready */

                DebugLog("Received FILE READY");

                if (state == FileClientState.WAITING_FOR_FILE_READY)
                {
                    //TODO check ca, ioa, nof

                    FileReady fileReady = (FileReady)asdu.GetElement(0);

                    if (fileReady.Positive)
                    {
                        ASDU callFile = NewAsdu(new FileCallOrSelect(ioa, nof, 0, SelectAndCallQualifier.REQUEST_FILE));
                        master.SendASDU(callFile);

                        DebugLog("Send CALL FILE");

                        state = FileClientState.WAITING_FOR_SECTION_READY;
                    }
                    else
                    {
                        if (fileReceiver != null)
                        {
                            fileReceiver.Finished(FileErrorCode.FILE_NOT_READY);
                        }

                        ResetStateToIdle();
                    }
                }
                else if (state == FileClientState.IDLE)
                {
                    //TODO call user callback to

                    //TODO send positive or negative ACK

                    state = FileClientState.WAITING_FOR_SECTION_READY;
                }
                else
                {
                    AbortFileTransfer(FileErrorCode.PROTOCOL_ERROR);
                }

                break;

            case TypeID.F_SR_NA_1:             /* Section ready */

                DebugLog("Received SECTION READY");

                if (state == FileClientState.WAITING_FOR_SECTION_READY)
                {
                    SectionReady sc = (SectionReady)asdu.GetElement(0);

                    if (sc.NotReady == false)
                    {
                        ASDU callSection = NewAsdu(new FileCallOrSelect(ioa, nof, 0, SelectAndCallQualifier.REQUEST_SECTION));
                        master.SendASDU(callSection);

                        DebugLog("Send CALL SECTION");

                        segmentOffset = 0;
                        state         = FileClientState.RECEIVING_SECTION;
                    }
                    else
                    {
                        AbortFileTransfer(FileErrorCode.SECTION_NOT_READY);
                    }
                }
                else if (state == FileClientState.IDLE)
                {
                }
                else
                {
                    if (fileReceiver != null)
                    {
                        fileReceiver.Finished(FileErrorCode.PROTOCOL_ERROR);
                    }

                    ResetStateToIdle();
                }

                break;

            case TypeID.F_SG_NA_1:             /* Segment */

                DebugLog("Received SEGMENT");

                if (state == FileClientState.RECEIVING_SECTION)
                {
                    FileSegment segment = (FileSegment)asdu.GetElement(0);

                    if (fileReceiver != null)
                    {
                        fileReceiver.SegmentReceived(segment.NameOfSection, segmentOffset, segment.LengthOfSegment, segment.SegmentData);
                    }

                    segmentOffset += segment.LengthOfSegment;
                }
                else if (state == FileClientState.IDLE)
                {
                }
                else
                {
                    AbortFileTransfer(FileErrorCode.PROTOCOL_ERROR);
                }

                break;


            case TypeID.F_LS_NA_1:             /* Last segment or section */

                DebugLog("Received LAST SEGMENT/SECTION");

                if (state != FileClientState.IDLE)
                {
                    FileLastSegmentOrSection lastSection = (FileLastSegmentOrSection)asdu.GetElement(0);

                    if (lastSection.LSQ == LastSectionOrSegmentQualifier.SECTION_TRANSFER_WITHOUT_DEACT)
                    {
                        if (state == FileClientState.RECEIVING_SECTION)
                        {
                            ASDU segmentAck = NewAsdu(new FileACK(ioa, nof, lastSection.NameOfSection, AcknowledgeQualifier.POS_ACK_SECTION, FileError.DEFAULT));

                            master.SendASDU(segmentAck);

                            DebugLog("Send SEGMENT ACK");

                            state = FileClientState.WAITING_FOR_SECTION_READY;
                        }
                        else
                        {
                            AbortFileTransfer(FileErrorCode.PROTOCOL_ERROR);
                        }
                    }
                    else if (lastSection.LSQ == LastSectionOrSegmentQualifier.FILE_TRANSFER_WITH_DEACT)
                    {
                        /* slave aborted transfer */

                        if (fileReceiver != null)
                        {
                            fileReceiver.Finished(FileErrorCode.ABORTED_BY_REMOTE);
                        }

                        ResetStateToIdle();
                    }
                    else if (lastSection.LSQ == LastSectionOrSegmentQualifier.FILE_TRANSFER_WITHOUT_DEACT)
                    {
                        if (state == FileClientState.WAITING_FOR_SECTION_READY)
                        {
                            ASDU fileAck = NewAsdu(new FileACK(ioa, nof, lastSection.NameOfSection, AcknowledgeQualifier.POS_ACK_FILE, FileError.DEFAULT));

                            master.SendASDU(fileAck);

                            DebugLog("Send FILE ACK");

                            if (fileReceiver != null)
                            {
                                fileReceiver.Finished(FileErrorCode.SUCCESS);
                            }

                            ResetStateToIdle();
                        }
                        else
                        {
                            DebugLog("Illegal state: " + state.ToString());

                            AbortFileTransfer(FileErrorCode.PROTOCOL_ERROR);
                        }
                    }
                }

                break;

            default:

                asduHandled = false;
                break;
            }


            return(asduHandled);
        }
Пример #2
0
        public bool HandleFileAsdu(ASDU asdu)
        {
            bool handled = true;

            switch (asdu.TypeId)
            {
            case TypeID.F_AF_NA_1:             /*  124 - ACK file, ACK section */

                logger("Received file/section ACK F_AF_NA_1");

                if (asdu.Cot == CauseOfTransmission.FILE_TRANSFER)
                {
                    if (transferState != FileServerState.UNSELECTED_IDLE)
                    {
                        IFileProvider file = selectedFile.provider;

                        FileACK ack = (FileACK)asdu.GetElement(0);

                        if (ack.AckQualifier == AcknowledgeQualifier.POS_ACK_FILE)
                        {
                            logger("Received positive file ACK");

                            if (transferState == FileServerState.WAITING_FOR_FILE_ACK)
                            {
                                selectedFile.provider.TransferComplete(true);

                                availableFiles.RemoveFile(selectedFile.provider);

                                selectedFile = null;

                                transferState = FileServerState.UNSELECTED_IDLE;
                            }
                            else
                            {
                                logger("Unexpected file transfer state --> abort file transfer");

                                transferState = FileServerState.SEND_ABORT;
                            }
                        }
                        else if (ack.AckQualifier == AcknowledgeQualifier.NEG_ACK_FILE)
                        {
                            logger("Received negative file ACK - stop transfer");

                            if (transferState == FileServerState.WAITING_FOR_FILE_ACK)
                            {
                                selectedFile.provider.TransferComplete(false);

                                selectedFile.selectedBy = null;
                                selectedFile            = null;

                                transferState = FileServerState.UNSELECTED_IDLE;
                            }
                            else
                            {
                                logger("Unexpected file transfer state --> abort file transfer");

                                transferState = FileServerState.SEND_ABORT;
                            }
                        }
                        else if (ack.AckQualifier == AcknowledgeQualifier.NEG_ACK_SECTION)
                        {
                            logger("Received negative file section ACK - repeat section");

                            if (transferState == FileServerState.WAITING_FOR_SECTION_ACK)
                            {
                                currentSectionOffset = 0;
                                sectionChecksum      = 0;

                                ASDU sectionReady = new ASDU(alParameters, CauseOfTransmission.FILE_TRANSFER, false, false, 0, file.GetCA(), false);

                                sectionReady.AddInformationObject(
                                    new SectionReady(selectedFile.provider.GetIOA(), selectedFile.provider.GetNameOfFile(), currentSectionNumber, currentSectionSize, false));

                                connection.SendASDU(sectionReady);


                                transferState = FileServerState.TRANSMIT_SECTION;
                            }
                            else
                            {
                                logger("Unexpected file transfer state --> abort file transfer");

                                transferState = FileServerState.SEND_ABORT;
                            }
                        }
                        else if (ack.AckQualifier == AcknowledgeQualifier.POS_ACK_SECTION)
                        {
                            if (transferState == FileServerState.WAITING_FOR_SECTION_ACK)
                            {
                                currentSectionNumber++;

                                int nextSectionSize =
                                    selectedFile.provider.GetSectionSize(currentSectionNumber);

                                ASDU responseAsdu = new ASDU(alParameters, CauseOfTransmission.FILE_TRANSFER, false, false, 0, file.GetCA(), false);

                                if (nextSectionSize == -1)
                                {
                                    logger("Reveived positive file section ACK - send last section indication");

                                    responseAsdu.AddInformationObject(
                                        new FileLastSegmentOrSection(file.GetIOA(), file.GetNameOfFile(),
                                                                     (byte)currentSectionNumber,
                                                                     LastSectionOrSegmentQualifier.FILE_TRANSFER_WITHOUT_DEACT,
                                                                     fileChecksum));

                                    transferState = FileServerState.WAITING_FOR_FILE_ACK;
                                }
                                else
                                {
                                    logger("Reveived positive file section ACK - send next section ready indication");

                                    currentSectionSize = nextSectionSize;

                                    responseAsdu.AddInformationObject(
                                        new SectionReady(selectedFile.provider.GetIOA(), selectedFile.provider.GetNameOfFile(), currentSectionNumber, currentSectionSize, false));

                                    transferState = FileServerState.WAITING_FOR_SECTION_CALL;
                                }

                                connection.SendASDU(responseAsdu);

                                sectionChecksum = 0;
                            }
                            else
                            {
                                logger("Unexpected file transfer state --> abort file transfer");

                                transferState = FileServerState.SEND_ABORT;
                            }
                        }
                    }
                    else
                    {
                        // No file transmission in progress --> what to do?
                        logger("Unexpected File ACK message -> ignore");
                    }
                }
                else
                {
                    asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION;
                    connection.SendASDU(asdu);
                }
                break;

            case TypeID.F_SC_NA_1:             /* 122 - Call/Select directoy/file/section */

                logger("Received call/select F_SC_NA_1");

                if (asdu.Cot == CauseOfTransmission.FILE_TRANSFER)
                {
                    FileCallOrSelect sc = (FileCallOrSelect)asdu.GetElement(0);


                    if (sc.SCQ == SelectAndCallQualifier.SELECT_FILE)
                    {
                        if (transferState == FileServerState.UNSELECTED_IDLE)
                        {
                            logger("Received SELECT FILE");

                            CS101n104File file = availableFiles.GetFile(asdu.Ca, sc.ObjectAddress, sc.NOF);

                            if (file == null)
                            {
                                asdu.Cot = CauseOfTransmission.UNKNOWN_INFORMATION_OBJECT_ADDRESS;
                                connection.SendASDU(asdu);
                            }
                            else
                            {
                                ASDU fileReady = new ASDU(alParameters, CauseOfTransmission.FILE_TRANSFER, false, false, 0, asdu.Ca, false);

                                // check if already selected
                                if (file.selectedBy == null)
                                {
                                    file.selectedBy = this;

                                    fileReady.AddInformationObject(new FileReady(sc.ObjectAddress, sc.NOF, file.provider.GetFileSize(), true));
                                }
                                else
                                {
                                    fileReady.AddInformationObject(new FileReady(sc.ObjectAddress, sc.NOF, 0, false));
                                }

                                connection.SendASDU(fileReady);

                                selectedFile = file;

                                transferState = FileServerState.WAITING_FOR_FILE_CALL;
                            }
                        }
                        else
                        {
                            logger("Unexpected SELECT FILE message");
                        }
                    }
                    else if (sc.SCQ == SelectAndCallQualifier.DEACTIVATE_FILE)
                    {
                        logger("Received DEACTIVATE FILE");

                        if (transferState != FileServerState.UNSELECTED_IDLE)
                        {
                            if (selectedFile != null)
                            {
                                selectedFile.selectedBy = null;
                                selectedFile            = null;
                            }

                            transferState = FileServerState.UNSELECTED_IDLE;
                        }
                        else
                        {
                            logger("Unexpected DEACTIVATE FILE message");
                        }
                    }

                    else if (sc.SCQ == SelectAndCallQualifier.REQUEST_FILE)
                    {
                        logger("Received CALL FILE");

                        if (transferState == FileServerState.WAITING_FOR_FILE_CALL)
                        {
                            if (selectedFile.provider.GetIOA() != sc.ObjectAddress)
                            {
                                logger("Unkown IOA");

                                asdu.Cot = CauseOfTransmission.UNKNOWN_INFORMATION_OBJECT_ADDRESS;
                                connection.SendASDU(asdu);
                            }
                            else
                            {
                                ASDU sectionReady = new ASDU(alParameters, CauseOfTransmission.FILE_TRANSFER, false, false, 0, asdu.Ca, false);

                                sectionReady.AddInformationObject(new SectionReady(sc.ObjectAddress, selectedFile.provider.GetNameOfFile(), 0, 0, false));

                                connection.SendASDU(sectionReady);

                                logger("Send SECTION READY");

                                currentSectionNumber = 0;
                                currentSectionOffset = 0;
                                currentSectionSize   = selectedFile.provider.GetSectionSize(0);

                                transferState = FileServerState.WAITING_FOR_SECTION_CALL;
                            }
                        }
                        else
                        {
                            logger("Unexpected FILE CALL message");
                        }
                    }
                    else if (sc.SCQ == SelectAndCallQualifier.REQUEST_SECTION)
                    {
                        logger("Received CALL SECTION");

                        if (transferState == FileServerState.WAITING_FOR_SECTION_CALL)
                        {
                            if (selectedFile.provider.GetIOA() != sc.ObjectAddress)
                            {
                                logger("Unkown IOA");

                                asdu.Cot = CauseOfTransmission.UNKNOWN_INFORMATION_OBJECT_ADDRESS;
                                connection.SendASDU(asdu);
                            }
                            else
                            {
                                transferState = FileServerState.TRANSMIT_SECTION;
                            }
                        }
                        else
                        {
                            logger("Unexpected SECTION CALL message");
                        }
                    }
                }
                else if (asdu.Cot == CauseOfTransmission.REQUEST)
                {
                    logger("Call directory received");

                    availableFiles.SendDirectoy(connection, false);
                }
                else
                {
                    asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION;
                    connection.SendASDU(asdu);
                }
                break;

            default:
                handled = false;
                break;
            }


            return(handled);
        }
Пример #3
0
            private bool HandleApplicationLayer(byte[] msg, int userDataStart, int userDataLength)
            {
                ASDU asdu;

                try {
                    asdu = new ASDU(parameters, buffer, userDataStart, userDataStart + userDataLength);
                }
                catch (ASDUParsingException e) {
                    DebugLog("ASDU parsing failed: " + e.Message);
                    return(false);
                }


                bool messageHandled = false;

                switch (asdu.TypeId)
                {
                case TypeID.C_IC_NA_1:                 /* 100 - interrogation command */

                    DebugLog("Rcvd interrogation command C_IC_NA_1");

                    if ((asdu.Cot == CauseOfTransmission.ACTIVATION) || (asdu.Cot == CauseOfTransmission.DEACTIVATION))
                    {
                        if (this.interrogationHandler != null)
                        {
                            InterrogationCommand irc = (InterrogationCommand)asdu.GetElement(0);

                            if (this.interrogationHandler(this.InterrogationHandlerParameter, this, asdu, irc.QOI))
                            {
                                messageHandled = true;
                            }
                        }
                    }
                    else
                    {
                        asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION;
                        this.SendASDU(asdu);
                    }

                    break;

                case TypeID.C_CI_NA_1:                 /* 101 - counter interrogation command */

                    DebugLog("Rcvd counter interrogation command C_CI_NA_1");

                    if ((asdu.Cot == CauseOfTransmission.ACTIVATION) || (asdu.Cot == CauseOfTransmission.DEACTIVATION))
                    {
                        if (this.counterInterrogationHandler != null)
                        {
                            CounterInterrogationCommand cic = (CounterInterrogationCommand)asdu.GetElement(0);

                            if (this.counterInterrogationHandler(this.counterInterrogationHandlerParameter, this, asdu, cic.QCC))
                            {
                                messageHandled = true;
                            }
                        }
                    }
                    else
                    {
                        asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION;
                        this.SendASDU(asdu);
                    }

                    break;

                case TypeID.C_RD_NA_1:                 /* 102 - read command */

                    DebugLog("Rcvd read command C_RD_NA_1");

                    if (asdu.Cot == CauseOfTransmission.REQUEST)
                    {
                        DebugLog("Read request for object: " + asdu.Ca);

                        if (this.readHandler != null)
                        {
                            ReadCommand rc = (ReadCommand)asdu.GetElement(0);

                            if (this.readHandler(this.readHandlerParameter, this, asdu, rc.ObjectAddress))
                            {
                                messageHandled = true;
                            }
                        }
                    }
                    else
                    {
                        asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION;
                        this.SendASDU(asdu);
                    }

                    break;

                case TypeID.C_CS_NA_1:                 /* 103 - Clock synchronization command */

                    DebugLog("Rcvd clock sync command C_CS_NA_1");

                    if (asdu.Cot == CauseOfTransmission.ACTIVATION)
                    {
                        if (this.clockSynchronizationHandler != null)
                        {
                            ClockSynchronizationCommand csc = (ClockSynchronizationCommand)asdu.GetElement(0);

                            if (this.clockSynchronizationHandler(this.clockSynchronizationHandlerParameter,
                                                                 this, asdu, csc.NewTime))
                            {
                                messageHandled = true;
                            }
                        }
                    }
                    else
                    {
                        asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION;
                        this.SendASDU(asdu);
                    }

                    break;

                case TypeID.C_TS_NA_1:                 /* 104 - test command */

                    DebugLog("Rcvd test command C_TS_NA_1");

                    if (asdu.Cot != CauseOfTransmission.ACTIVATION)
                    {
                        asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION;
                    }
                    else
                    {
                        asdu.Cot = CauseOfTransmission.ACTIVATION_CON;
                    }

                    this.SendASDU(asdu);

                    messageHandled = true;

                    break;

                case TypeID.C_RP_NA_1:                 /* 105 - Reset process command */

                    DebugLog("Rcvd reset process command C_RP_NA_1");

                    if (asdu.Cot == CauseOfTransmission.ACTIVATION)
                    {
                        if (this.resetProcessHandler != null)
                        {
                            ResetProcessCommand rpc = (ResetProcessCommand)asdu.GetElement(0);

                            if (this.resetProcessHandler(this.resetProcessHandlerParameter,
                                                         this, asdu, rpc.QRP))
                            {
                                messageHandled = true;
                            }
                        }
                    }
                    else
                    {
                        asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION;
                        this.SendASDU(asdu);
                    }


                    break;

                case TypeID.C_CD_NA_1:                 /* 106 - Delay acquisition command */

                    DebugLog("Rcvd delay acquisition command C_CD_NA_1");

                    if ((asdu.Cot == CauseOfTransmission.ACTIVATION) || (asdu.Cot == CauseOfTransmission.SPONTANEOUS))
                    {
                        if (this.delayAcquisitionHandler != null)
                        {
                            DelayAcquisitionCommand dac = (DelayAcquisitionCommand)asdu.GetElement(0);

                            if (this.delayAcquisitionHandler(this.delayAcquisitionHandlerParameter,
                                                             this, asdu, dac.Delay))
                            {
                                messageHandled = true;
                            }
                        }
                    }
                    else
                    {
                        asdu.Cot = CauseOfTransmission.UNKNOWN_CAUSE_OF_TRANSMISSION;
                        this.SendASDU(asdu);
                    }

                    break;
                }

                if (messageHandled == false)
                {
                    messageHandled = fileServer.HandleFileAsdu(asdu);
                }

                if ((messageHandled == false) && (this.asduHandler != null))
                {
                    if (this.asduHandler(this.asduHandlerParameter, this, asdu))
                    {
                        messageHandled = true;
                    }
                }

                if (messageHandled == false)
                {
                    asdu.Cot = CauseOfTransmission.UNKNOWN_TYPE_ID;
                    this.SendASDU(asdu);
                }

                return(true);
            }