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 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); }
private void ResetStateToIdle() { fileReceiver = null; state = FileClientState.IDLE; }