Beispiel #1
0
            void IMasterConnection.SendACT_TERM(ASDU asdu)
            {
                asdu.Cot        = CauseOfTransmission.ACTIVATION_TERMINATION;
                asdu.IsNegative = false;

                SendASDU(asdu);
            }
Beispiel #2
0
            void IMasterConnection.SendACT_CON(ASDU asdu, bool negative)
            {
                asdu.Cot        = CauseOfTransmission.ACTIVATION_CON;
                asdu.IsNegative = negative;

                SendASDU(asdu);
            }
Beispiel #3
0
        void IPrimaryLinkLayerCallbacks.UserData(int slaveAddress, byte[] message, int start, int length)
        {
            DebugLog("User data slave " + slaveAddress);

            ASDU asdu;

            try
            {
                asdu = new ASDU(appLayerParameters, message, start, start + length);
            }
            catch (ASDUParsingException e)
            {
                DebugLog("ASDU parsing failed: " + e.Message);
                return;
            }

            bool messageHandled = false;

            if (fileClient != null)
            {
                messageHandled = fileClient.HandleFileAsdu(asdu);
            }

            if (messageHandled == false)
            {
                if (asduReceivedHandler != null)
                {
                    asduReceivedHandler(asduReceivedHandlerParameter, slaveAddress, asdu);
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Callback function for secondary link layer (balanced mode)
        /// </summary>
        private bool HandleApplicationLayer(int address, byte[] msg, int userDataStart, int userDataLength)
        {
            ASDU asdu;

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

            bool messageHandled = false;

            if (fileClient != null)
            {
                messageHandled = fileClient.HandleFileAsdu(asdu);
            }

            if (messageHandled == false)
            {
                if (asduReceivedHandler != null)
                {
                    messageHandled = asduReceivedHandler(asduReceivedHandlerParameter, address, asdu);
                }
            }

            return(messageHandled);
        }
Beispiel #5
0
        public override void SendDelayAcquisitionCommand(CauseOfTransmission cot, int ca, CP16Time2a delay)
        {
            ASDU asdu = new ASDU(appLayerParameters, CauseOfTransmission.ACTIVATION, false, false, (byte)appLayerParameters.OA, ca, false);

            asdu.AddInformationObject(new DelayAcquisitionCommand(0, delay));

            EnqueueUserData(asdu);
        }
Beispiel #6
0
        public override void SendControlCommand(CauseOfTransmission cot, int ca, InformationObject sc)
        {
            ASDU controlCommand = new ASDU(appLayerParameters, cot, false, false, (byte)appLayerParameters.OA, ca, false);

            controlCommand.AddInformationObject(sc);

            EnqueueUserData(controlCommand);
        }
Beispiel #7
0
        public override void SendTestCommand(int ca)
        {
            ASDU asdu = new ASDU(parameters, CauseOfTransmission.ACTIVATION, false, false, (byte)parameters.OA, ca, false);

            asdu.AddInformationObject(new TestCommand());

            EnqueueUserData(asdu);
        }
Beispiel #8
0
        public override void SendReadCommand(int ca, int ioa)
        {
            ASDU asdu = new ASDU(appLayerParameters, CauseOfTransmission.REQUEST, false, false, (byte)appLayerParameters.OA, ca, false);

            asdu.AddInformationObject(new ReadCommand(ioa));

            EnqueueUserData(asdu);
        }
Beispiel #9
0
        public override void SendCounterInterrogationCommand(CauseOfTransmission cot, int ca, byte qcc)
        {
            ASDU asdu = new ASDU(appLayerParameters, cot, false, false, (byte)appLayerParameters.OA, ca, false);

            asdu.AddInformationObject(new CounterInterrogationCommand(0, qcc));

            EnqueueUserData(asdu);
        }
Beispiel #10
0
        public override void SendClockSyncCommand(int ca, CP56Time2a time)
        {
            ASDU asdu = new ASDU(appLayerParameters, CauseOfTransmission.ACTIVATION, false, false, (byte)appLayerParameters.OA, ca, false);

            asdu.AddInformationObject(new ClockSynchronizationCommand(0, time));

            EnqueueUserData(asdu);
        }
Beispiel #11
0
        private ASDU NewAsdu(InformationObject io)
        {
            ASDU asdu = new ASDU(master.GetApplicationLayerParameters(), CauseOfTransmission.FILE_TRANSFER, false, false, 0, ca, false);

            asdu.AddInformationObject(io);

            return(asdu);
        }
Beispiel #12
0
        public override void SendTestCommandWithCP56Time2a(int ca, ushort tsc, CP56Time2a time)
        {
            ASDU asdu = new ASDU(appLayerParameters, CauseOfTransmission.ACTIVATION, false, false, (byte)appLayerParameters.OA, ca, false);

            asdu.AddInformationObject(new TestCommandWithCP56Time2a(tsc, time));

            EnqueueUserData(asdu);
        }
Beispiel #13
0
        public override void SendResetProcessCommand(CauseOfTransmission cot, int ca, byte qrp)
        {
            ASDU asdu = new ASDU(appLayerParameters, CauseOfTransmission.ACTIVATION, false, false, (byte)appLayerParameters.OA, ca, false);

            asdu.AddInformationObject(new ResetProcessCommand(0, qrp));

            EnqueueUserData(asdu);
        }
Beispiel #14
0
        public override void SendInterrogationCommand(CauseOfTransmission cot, int ca, byte qoi)
        {
            ASDU asdu = new ASDU(parameters, cot, false, false, (byte)parameters.OA, ca, false);

            asdu.AddInformationObject(new InterrogationCommand(0, qoi));

            EnqueueUserData(asdu);
        }
Beispiel #15
0
        private void EnqueueUserData(ASDU asdu)
        {
            //TODO problem -> buffer frame needs own buffer so that the message can be stored.
            BufferFrame bf = new BufferFrame(buffer, 0);

            asdu.Encode(bf, parameters);

            linkLayerUnbalanced.SendConfirmed(slaveAddress, bf);
        }
Beispiel #16
0
        private void EnqueueUserData(ASDU asdu)
        {
            lock (userDataQueue) {
                BufferFrame frame = new BufferFrame(new byte[256], 0);

                asdu.Encode(frame, parameters);

                userDataQueue.Enqueue(frame);
            }
        }
Beispiel #17
0
        private void AbortFileTransfer(FileErrorCode errorCode)
        {
            ASDU deactivateFile = NewAsdu(new FileCallOrSelect(ioa, nof, 0, SelectAndCallQualifier.DEACTIVATE_FILE));

            master.SendASDU(deactivateFile);

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

            ResetStateToIdle();
        }
Beispiel #18
0
        public void RequestFile(int ca, int ioa, NameOfFile nof, IFileReceiver fileReceiver)
        {
            this.ca           = ca;
            this.ioa          = ioa;
            this.nof          = nof;
            this.fileReceiver = fileReceiver;

            ASDU selectFile = NewAsdu(new FileCallOrSelect(ioa, nof, 0, SelectAndCallQualifier.SELECT_FILE));

            master.SendASDU(selectFile);

            state = FileClientState.WAITING_FOR_FILE_READY;
        }
Beispiel #19
0
            public void EnqueueUserDataClass2(ASDU asdu)
            {
                lock (userDataClass2Queue) {
                    BufferFrame frame = new BufferFrame(new byte[256], 0);

                    asdu.Encode(frame, parameters);

                    userDataClass2Queue.Enqueue(frame);

                    while (userDataClass2Queue.Count > userDataClass2QueueMaxSize)
                    {
                        userDataClass2Queue.Dequeue();
                    }
                }
            }
Beispiel #20
0
        private void EnqueueUserData(ASDU asdu)
        {
            if (linkLayerUnbalanced != null)
            {
                //TODO problem -> buffer frame needs own buffer so that the message can be stored.
                BufferFrame frame = new BufferFrame(buffer, 0);

                asdu.Encode(frame, appLayerParameters);

                linkLayerUnbalanced.SendConfirmed(slaveAddress, frame);
            }
            else
            {
                lock (userDataQueue) {
                    BufferFrame frame = new BufferFrame(new byte[256], 0);

                    asdu.Encode(frame, appLayerParameters);

                    userDataQueue.Enqueue(frame);
                }
            }
        }
Beispiel #21
0
 public override void SendASDU(ASDU asdu)
 {
     EnqueueUserData(asdu);
 }
Beispiel #22
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);
            }
Beispiel #23
0
            /********************************************
            * IASDUSender
            ********************************************/

            void IMasterConnection.SendASDU(ASDU asdu)
            {
                SendASDU(asdu);
            }
Beispiel #24
0
 /// <summary>
 /// Sends an arbitrary ASDU to the connected slave
 /// </summary>
 /// <param name="asdu">The ASDU to send</param>
 public abstract void SendASDU(ASDU asdu);
Beispiel #25
0
        public void HandleFileTransmission()
        {
            if (transferState != FileServerState.UNSELECTED_IDLE)
            {
                if (transferState == FileServerState.TRANSMIT_SECTION)
                {
                    if (selectedFile != null)
                    {
                        IFileProvider file = selectedFile.provider;

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


                        if (currentSectionOffset == currentSectionSize)
                        {
                            // send last segment

                            fileAsdu.AddInformationObject(
                                new FileLastSegmentOrSection(file.GetIOA(), file.GetNameOfFile(),
                                                             currentSectionNumber,
                                                             LastSectionOrSegmentQualifier.SECTION_TRANSFER_WITHOUT_DEACT,
                                                             sectionChecksum));

                            fileChecksum   += sectionChecksum;
                            sectionChecksum = 0;


                            logger("Send LAST SEGMENT");

                            connection.SendASDU(fileAsdu);

                            transferState = FileServerState.WAITING_FOR_SECTION_ACK;
                        }
                        else
                        {
                            int currentSegmentSize = currentSectionSize - currentSectionOffset;

                            if (currentSegmentSize > maxSegmentSize)
                            {
                                currentSegmentSize = maxSegmentSize;
                            }

                            byte[] segmentData = new byte[currentSegmentSize];

                            file.GetSegmentData(currentSectionNumber,
                                                currentSectionOffset,
                                                currentSegmentSize,
                                                segmentData);

                            fileAsdu.AddInformationObject(
                                new FileSegment(file.GetIOA(), file.GetNameOfFile(), currentSectionNumber,
                                                segmentData));

                            byte checksum = 0;

                            foreach (byte octet in segmentData)
                            {
                                checksum += octet;
                            }



                            connection.SendASDU(fileAsdu);

                            sectionChecksum += checksum;

                            logger("Send SEGMENT (CHS=" + sectionChecksum + ")");
                            currentSectionOffset += currentSegmentSize;
                        }
                    }
                }
            }
        }
Beispiel #26
0
 internal void SendASDU(ASDU asdu)
 {
     EnqueueUserDataClass1(asdu);
 }
Beispiel #27
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);
        }
Beispiel #28
0
        internal void SendDirectoy(IMasterConnection masterConnection, bool spontaneous)
        {
            CauseOfTransmission cot;

            if (spontaneous)
            {
                cot = CauseOfTransmission.SPONTANEOUS;
            }
            else
            {
                cot = CauseOfTransmission.REQUEST;
            }

            lock (availableFiles) {
                int size = availableFiles.Count;
                int i    = 0;

                int currentCa  = -1;
                int currentIOA = -1;

                ASDU directoryAsdu = null;

                foreach (CS101n104File file in availableFiles)
                {
                    bool newAsdu = false;

                    if (file.provider.GetCA() != currentCa)
                    {
                        currentCa = file.provider.GetCA();
                        newAsdu   = true;
                    }

                    if (currentIOA != (file.provider.GetIOA() - 1))
                    {
                        newAsdu = true;
                    }

                    if (newAsdu)
                    {
                        if (directoryAsdu != null)
                        {
                            masterConnection.SendASDU(directoryAsdu);
                            directoryAsdu = null;
                        }
                    }

                    currentIOA = file.provider.GetIOA();

                    i++;

                    if (directoryAsdu == null)
                    {
                        directoryAsdu = new ASDU(masterConnection.GetApplicationLayerParameters(), cot, false, false, 0, currentCa, true);
                    }

                    bool lastFile = (i == size);

                    byte sof = 0;

                    if (lastFile)
                    {
                        sof = 0x20;
                    }

                    InformationObject io = new FileDirectory(currentIOA, file.provider.GetNameOfFile(), file.provider.GetFileSize(), sof, new CP56Time2a(file.provider.GetFileDate()));

                    if (!directoryAsdu.AddInformationObject(io) == false)
                    {
                        masterConnection.SendASDU(directoryAsdu);

                        directoryAsdu = new ASDU(masterConnection.GetApplicationLayerParameters(), cot, false, false, 0, currentCa, true);
                        directoryAsdu.AddInformationObject(io);
                    }
                }

                if (directoryAsdu != null)
                {
                    masterConnection.SendASDU(directoryAsdu);
                }
            }
        }
Beispiel #29
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);
        }