void IMasterConnection.SendACT_TERM(ASDU asdu) { asdu.Cot = CauseOfTransmission.ACTIVATION_TERMINATION; asdu.IsNegative = false; SendASDU(asdu); }
void IMasterConnection.SendACT_CON(ASDU asdu, bool negative) { asdu.Cot = CauseOfTransmission.ACTIVATION_CON; asdu.IsNegative = negative; SendASDU(asdu); }
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); } } }
/// <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); }
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); }
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); }
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); }
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); }
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); }
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); }
private ASDU NewAsdu(InformationObject io) { ASDU asdu = new ASDU(master.GetApplicationLayerParameters(), CauseOfTransmission.FILE_TRANSFER, false, false, 0, ca, false); asdu.AddInformationObject(io); return(asdu); }
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); }
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); }
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); }
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); }
private void EnqueueUserData(ASDU asdu) { lock (userDataQueue) { BufferFrame frame = new BufferFrame(new byte[256], 0); asdu.Encode(frame, parameters); userDataQueue.Enqueue(frame); } }
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(); }
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; }
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(); } } }
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); } } }
public override void SendASDU(ASDU asdu) { EnqueueUserData(asdu); }
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); }
/******************************************** * IASDUSender ********************************************/ void IMasterConnection.SendASDU(ASDU asdu) { SendASDU(asdu); }
/// <summary> /// Sends an arbitrary ASDU to the connected slave /// </summary> /// <param name="asdu">The ASDU to send</param> public abstract void SendASDU(ASDU asdu);
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; } } } } }
internal void SendASDU(ASDU asdu) { EnqueueUserDataClass1(asdu); }
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); }
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); } } }
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); }