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); }
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; } } } } }