public APdu(BinaryReader reader, ConnectionSettings settings) { var length = reader.ReadByte() & 0xff; if (length < 4 || length > 253) { throw new IOException("APDU contain invalid length: " + length); } var aPduHeader = reader.ReadBytes(4); if ((aPduHeader[0] & 0x01) == 0) { apciType = ApciType.FORMAT; sendSeqNum = ((aPduHeader[0] & 0xfe) >> 1) + ((aPduHeader[1] & 0xff) << 7); receiveSeqNum = ((aPduHeader[2] & 0xfe) >> 1) + ((aPduHeader[3] & 0xff) << 7); aSdu = new ASdu(reader, settings, length - 4); } else if ((aPduHeader[0] & 0x02) == 0) { apciType = ApciType.S_FORMAT; receiveSeqNum = ((aPduHeader[2] & 0xfe) >> 1) + ((aPduHeader[3] & 0xff) << 7); } else { if (aPduHeader[0] == 0x83) { apciType = ApciType.TESTFR_CON; } else if (aPduHeader[0] == 0x43) { apciType = ApciType.TESTFR_ACT; } else if (aPduHeader[0] == 0x23) { apciType = ApciType.STOPDT_CON; } else if (aPduHeader[0] == 0x13) { apciType = ApciType.STOPDT_ACT; } else if (aPduHeader[0] == 0x0B) { apciType = ApciType.STARTDT_CON; } else { apciType = ApciType.STARTDT_ACT; } } }
public Connection(Socket socket, ConnectionSettings settings) { this.settings = settings; var ns = new NetworkStream(socket); writer = new BinaryWriter(ns); reader = new BinaryReader(ns); startdtactSignal = new CountDownLatch(1); var connectionReader = new ConnectionReader(this); connectionReader.Start(); }
private static void Main(string[] args) { try { var socket = Connect("127.0.0.1", 2404); var settings = new ConnectionSettings(); var connection = new Connection(socket, settings); connection.NewASdu += asdu => { Console.WriteLine("\nReceived ASDU:\n" + asdu.ToString()); }; connection.ConnectionClosed += Console.WriteLine; connection.StartDataTransfer(); } catch (Exception e) { Console.WriteLine(e); } Console.ReadLine(); }
public ServerThread(Socket serverSocket, ConnectionSettings settings, int maxConnections) : base() { _maxConnections = maxConnections; _serverSocket = serverSocket; _settings = settings; }
public ConnectionHandler(Socket socket, ConnectionSettings settings): base() { _socket = socket; _settings = settings; }
public ASdu(BinaryReader reader, ConnectionSettings settings, int aSduLength) { int typeIdCode = reader.ReadByte(); typeId = (TypeId) typeIdCode; int tempbyte = reader.ReadByte(); IsSequenceOfElements = (tempbyte & 0x80) == 0x80; int numberOfSequenceElements; int numberOfInformationObjects; sequenceLength = tempbyte & 0x7f; if (IsSequenceOfElements) { numberOfSequenceElements = sequenceLength; numberOfInformationObjects = 1; } else { numberOfInformationObjects = sequenceLength; numberOfSequenceElements = 1; } tempbyte = reader.ReadByte(); causeOfTransmission = (CauseOfTransmission) (tempbyte & 0x3f); test = (tempbyte & 0x80) == 0x80; negativeConfirm = (tempbyte & 0x40) == 0x40; if (settings.CotFieldLength == 2) { originatorAddress = reader.ReadByte(); aSduLength--; } else { originatorAddress = -1; } if (settings.CommonAddressFieldLength == 1) { commonAddress = reader.ReadByte(); } else { commonAddress = reader.ReadByte() + (reader.ReadByte() << 8); aSduLength--; } if (typeIdCode < 128) { informationObjects = new InformationObject[numberOfInformationObjects]; for (var i = 0; i < numberOfInformationObjects; i++) { informationObjects[i] = new InformationObject(reader, typeId, numberOfSequenceElements, settings); } privateInformation = null; } else { informationObjects = null; privateInformation = reader.ReadBytes(aSduLength - 4); } }
public int Encode(byte[] buffer, int i, ConnectionSettings settings) { var origi = i; buffer[i++] = (byte) typeId; if (IsSequenceOfElements) { buffer[i++] = (byte) (sequenceLength | 0x80); } else { buffer[i++] = (byte) sequenceLength; } if (test) { if (negativeConfirm) { buffer[i++] = (byte) ((byte) causeOfTransmission | 0xC0); } else { buffer[i++] = (byte) ((byte) causeOfTransmission | 0x80); } } else { if (negativeConfirm) { buffer[i++] = (byte) ((byte) causeOfTransmission | 0x40); } else { buffer[i++] = (byte) causeOfTransmission; } } if (settings.CotFieldLength == 2) { buffer[i++] = (byte) originatorAddress; } buffer[i++] = (byte) commonAddress; if (settings.CommonAddressFieldLength == 2) { buffer[i++] = (byte) (commonAddress >> 8); } if (informationObjects != null) { i = informationObjects.Aggregate(i, (current, informationObject) => current + informationObject.Encode(buffer, current, settings)); } else { Array.Copy(privateInformation, 0, buffer, i, privateInformation.Length); i += privateInformation.Length; } return i - origi; }
public int Encode(byte[] buffer, ConnectionSettings settings) { buffer[0] = 0x68; var length = 4; if (apciType == ApciType.FORMAT) { buffer[2] = (byte) (sendSeqNum << 1); buffer[3] = (byte) (sendSeqNum >> 7); buffer[4] = (byte) (receiveSeqNum << 1); buffer[5] = (byte) (receiveSeqNum >> 7); length += aSdu.Encode(buffer, 6, settings); } else if (apciType == ApciType.STARTDT_ACT) { buffer[2] = 0x07; buffer[3] = 0x00; buffer[4] = 0x00; buffer[5] = 0x00; } else if (apciType == ApciType.STARTDT_CON) { buffer[2] = 0x0b; buffer[3] = 0x00; buffer[4] = 0x00; buffer[5] = 0x00; } else if (apciType == ApciType.S_FORMAT) { buffer[2] = 0x01; buffer[3] = 0x00; buffer[4] = (byte) (receiveSeqNum << 1); buffer[5] = (byte) (receiveSeqNum >> 7); } buffer[1] = (byte) length; return length + 2; }
public int Encode(byte[] buffer, int i, ConnectionSettings settings) { var origi = i; buffer[i++] = (byte) informationObjectAddress; if (settings.IoaFieldLength > 1) { buffer[i++] = (byte) (informationObjectAddress >> 8); if (settings.IoaFieldLength > 2) { buffer[i++] = (byte) (informationObjectAddress >> 16); } } i = informationElements.SelectMany(informationElementCombination => informationElementCombination) .Aggregate(i, (current, informationElement) => current + informationElement.Encode(buffer, current)); return i - origi; }
public InformationObject(BinaryReader reader, TypeId typeId, int numberOfSequenceElements, ConnectionSettings settings) { if (settings.IoaFieldLength == 1) { informationObjectAddress = reader.ReadByte(); } else if (settings.IoaFieldLength == 2) { informationObjectAddress = reader.ReadByte() + (reader.ReadByte() << 8); } else if (settings.IoaFieldLength == 3) { informationObjectAddress = reader.ReadByte() + (reader.ReadByte() << 8) + (reader.ReadByte() << 16); } switch (typeId) { // 1 case TypeId.M_SP_NA_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[1]; informationElements[i][0] = new IeSinglePointWithQuality(reader); } break; // 2 case TypeId.M_SP_TA_1: informationElements = new[] {new InformationElement[] {new IeSinglePointWithQuality(reader), new IeTime24(reader)}}; break; // 3 case TypeId.M_DP_NA_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[1]; informationElements[i][0] = new IeDoublePointWithQuality(reader); } break; // 4 case TypeId.M_DP_TA_1: informationElements = new[] {new InformationElement[] {new IeDoublePointWithQuality(reader), new IeTime24(reader)}}; break; // 5 case TypeId.M_ST_NA_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[2]; informationElements[i][0] = new IeValueWithTransientState(reader); informationElements[i][1] = new IeQuality(reader); } break; // 6 case TypeId.M_ST_TA_1: informationElements = new[] { new InformationElement[] {new IeValueWithTransientState(reader), new IeQuality(reader), new IeTime24(reader)} }; break; // 7 case TypeId.M_BO_NA_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[2]; informationElements[i][0] = new IeBinaryStateInformation(reader); informationElements[i][1] = new IeQuality(reader); } break; // 8 case TypeId.M_BO_TA_1: informationElements = new[] { new InformationElement[] {new IeBinaryStateInformation(reader), new IeQuality(reader), new IeTime24(reader)} }; break; // 9 case TypeId.M_ME_NA_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[2]; informationElements[i][0] = new IeNormalizedValue(reader); informationElements[i][1] = new IeQuality(reader); } break; // 10 case TypeId.M_ME_TA_1: informationElements = new[] { new InformationElement[] {new IeNormalizedValue(reader), new IeQuality(reader), new IeTime24(reader)} }; break; // 11 case TypeId.M_ME_NB_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[2]; informationElements[i][0] = new IeScaledValue(reader); informationElements[i][1] = new IeQuality(reader); } break; // 12 case TypeId.M_ME_TB_1: informationElements = new[] {new InformationElement[] {new IeScaledValue(reader), new IeQuality(reader), new IeTime24(reader)}}; break; // 13 case TypeId.M_ME_NC_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[2]; informationElements[i][0] = new IeShortFloat(reader); informationElements[i][1] = new IeQuality(reader); } break; // 14 case TypeId.M_ME_TC_1: informationElements = new[] {new InformationElement[] {new IeShortFloat(reader), new IeQuality(reader), new IeTime24(reader)}}; break; // 15 case TypeId.M_IT_NA_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[1]; informationElements[i][0] = new IeBinaryCounterReading(reader); } break; // 16 case TypeId.M_IT_TA_1: informationElements = new[] {new InformationElement[] {new IeBinaryCounterReading(reader), new IeTime24(reader)}}; break; // 17 case TypeId.M_EP_TA_1: informationElements = new[] { new InformationElement[] {new IeSingleProtectionEvent(reader), new IeTime16(reader), new IeTime24(reader)} }; break; // 18 case TypeId.M_EP_TB_1: informationElements = new[] { new InformationElement[] { new IeProtectionStartEvent(reader), new IeProtectionQuality(reader), new IeTime16(reader), new IeTime24(reader) } }; break; // 19 case TypeId.M_EP_TC_1: informationElements = new[] { new InformationElement[] { new IeProtectionOutputCircuitInformation(reader), new IeProtectionQuality(reader), new IeTime16(reader), new IeTime24(reader) } }; break; // 20 case TypeId.M_PS_NA_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[2]; informationElements[i][0] = new IeStatusAndStatusChanges(reader); informationElements[i][1] = new IeQuality(reader); } break; // 21 case TypeId.M_ME_ND_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[1]; informationElements[i][0] = new IeNormalizedValue(reader); } break; // 30 case TypeId.M_SP_TB_1: informationElements = new[] {new InformationElement[] {new IeSinglePointWithQuality(reader), new IeTime56(reader)}}; break; // 31 case TypeId.M_DP_TB_1: informationElements = new[] {new InformationElement[] {new IeDoublePointWithQuality(reader), new IeTime56(reader)}}; break; // 32 case TypeId.M_ST_TB_1: informationElements = new[] { new InformationElement[] {new IeValueWithTransientState(reader), new IeQuality(reader), new IeTime56(reader)} }; break; // 33 case TypeId.M_BO_TB_1: informationElements = new[] { new InformationElement[] {new IeBinaryStateInformation(reader), new IeQuality(reader), new IeTime56(reader)} }; break; // 34 case TypeId.M_ME_TD_1: informationElements = new[] { new InformationElement[] {new IeNormalizedValue(reader), new IeQuality(reader), new IeTime56(reader)} }; break; // 35 case TypeId.M_ME_TE_1: informationElements = new[] {new InformationElement[] {new IeScaledValue(reader), new IeQuality(reader), new IeTime56(reader)}}; break; // 36 case TypeId.M_ME_TF_1: informationElements = new[] {new InformationElement[] {new IeShortFloat(reader), new IeQuality(reader), new IeTime56(reader)}}; break; // 37 case TypeId.M_IT_TB_1: informationElements = new[] {new InformationElement[] {new IeBinaryCounterReading(reader), new IeTime56(reader)}}; break; // 38 case TypeId.M_EP_TD_1: informationElements = new[] { new InformationElement[] {new IeSingleProtectionEvent(reader), new IeTime16(reader), new IeTime56(reader)} }; break; // 39 case TypeId.M_EP_TE_1: informationElements = new[] { new InformationElement[] { new IeProtectionStartEvent(reader), new IeProtectionQuality(reader), new IeTime16(reader), new IeTime56(reader) } }; break; // 40 case TypeId.M_EP_TF_1: informationElements = new[] { new InformationElement[] { new IeProtectionOutputCircuitInformation(reader), new IeProtectionQuality(reader), new IeTime16(reader), new IeTime56(reader) } }; break; // 45 case TypeId.C_SC_NA_1: informationElements = new[] {new InformationElement[] {new IeSingleCommand(reader)}}; break; // 46 case TypeId.C_DC_NA_1: informationElements = new[] {new InformationElement[] {new IeDoubleCommand(reader)}}; break; // 47 case TypeId.C_RC_NA_1: informationElements = new[] {new InformationElement[] {new IeRegulatingStepCommand(reader)}}; break; // 48 case TypeId.C_SE_NA_1: informationElements = new[] {new InformationElement[] {new IeNormalizedValue(reader), new IeQualifierOfSetPointCommand(reader)}}; break; // 49 case TypeId.C_SE_NB_1: informationElements = new[] {new InformationElement[] {new IeScaledValue(reader), new IeQualifierOfSetPointCommand(reader)}}; break; // 50 case TypeId.C_SE_NC_1: informationElements = new[] {new InformationElement[] {new IeShortFloat(reader), new IeQualifierOfSetPointCommand(reader)}}; break; // 51 case TypeId.C_BO_NA_1: informationElements = new[] {new InformationElement[] {new IeBinaryStateInformation(reader)}}; break; // 58 case TypeId.C_SC_TA_1: informationElements = new[] {new InformationElement[] {new IeSingleCommand(reader), new IeTime56(reader)}}; break; // 59 case TypeId.C_DC_TA_1: informationElements = new[] {new InformationElement[] {new IeDoubleCommand(reader), new IeTime56(reader)}}; break; // 60 case TypeId.C_RC_TA_1: informationElements = new[] {new InformationElement[] {new IeBinaryStateInformation(reader), new IeTime56(reader)}}; break; // 61 case TypeId.C_SE_TA_1: informationElements = new[] { new InformationElement[] { new IeNormalizedValue(reader), new IeQualifierOfSetPointCommand(reader), new IeTime56(reader) } }; break; // 62 case TypeId.C_SE_TB_1: informationElements = new[] { new InformationElement[] { new IeScaledValue(reader), new IeQualifierOfSetPointCommand(reader), new IeTime56(reader) } }; break; // 63 case TypeId.C_SE_TC_1: informationElements = new[] { new InformationElement[] { new IeShortFloat(reader), new IeQualifierOfSetPointCommand(reader), new IeTime56(reader) } }; break; // 64 case TypeId.C_BO_TA_1: informationElements = new[] {new InformationElement[] {new IeBinaryStateInformation(reader), new IeTime56(reader)}}; break; // 70 case TypeId.M_EI_NA_1: informationElements = new[] {new InformationElement[] {new IeCauseOfInitialization(reader)}}; break; // 100 case TypeId.C_IC_NA_1: informationElements = new[] {new InformationElement[] {new IeQualifierOfInterrogation(reader)}}; break; // 101 case TypeId.C_CI_NA_1: informationElements = new[] {new InformationElement[] {new IeQualifierOfCounterInterrogation(reader)}}; break; // 102 case TypeId.C_RD_NA_1: informationElements = new InformationElement[0][]; break; // 103 case TypeId.C_CS_NA_1: informationElements = new[] {new InformationElement[] {new IeTime56(reader)}}; break; // 104 case TypeId.C_TS_NA_1: informationElements = new[] {new InformationElement[] {new IeFixedTestBitPattern(reader)}}; break; // 105 case TypeId.C_RP_NA_1: informationElements = new[] {new InformationElement[] {new IeQualifierOfResetProcessCommand(reader)}}; break; // 106 case TypeId.C_CD_NA_1: informationElements = new[] {new InformationElement[] {new IeTime16(reader)}}; break; // 107 case TypeId.C_TS_TA_1: informationElements = new[] {new InformationElement[] {new IeTestSequenceCounter(reader), new IeTime56(reader)}}; break; // 110 case TypeId.P_ME_NA_1: informationElements = new[] { new InformationElement[] { new IeNormalizedValue(reader), new IeQualifierOfParameterOfMeasuredValues(reader) } }; break; // 111 case TypeId.P_ME_NB_1: informationElements = new[] { new InformationElement[] { new IeScaledValue(reader), new IeQualifierOfParameterOfMeasuredValues(reader) } }; break; // 112 case TypeId.P_ME_NC_1: informationElements = new[] { new InformationElement[] { new IeShortFloat(reader), new IeQualifierOfParameterOfMeasuredValues(reader) } }; break; // 113 case TypeId.P_AC_NA_1: informationElements = new[] {new InformationElement[] {new IeQualifierOfParameterActivation(reader)}}; break; // 120 case TypeId.F_FR_NA_1: informationElements = new[] { new InformationElement[] { new IeNameOfFile(reader), new IeLengthOfFileOrSection(reader), new IeFileReadyQualifier(reader) } }; break; // 121 case TypeId.F_SR_NA_1: informationElements = new[] { new InformationElement[] { new IeNameOfFile(reader), new IeNameOfSection(reader), new IeLengthOfFileOrSection(reader), new IeSectionReadyQualifier(reader) } }; break; // 122 case TypeId.F_SC_NA_1: informationElements = new[] { new InformationElement[] { new IeNameOfFile(reader), new IeNameOfSection(reader), new IeSelectAndCallQualifier(reader) } }; break; // 123 case TypeId.F_LS_NA_1: informationElements = new[] { new InformationElement[] { new IeNameOfFile(reader), new IeNameOfSection(reader), new IeLastSectionOrSegmentQualifier(reader), new IeChecksum(reader) } }; break; // 124 case TypeId.F_AF_NA_1: informationElements = new[] { new InformationElement[] { new IeNameOfFile(reader), new IeNameOfSection(reader), new IeAckFileOrSectionQualifier(reader) } }; break; // 125 case TypeId.F_SG_NA_1: informationElements = new[] { new InformationElement[] { new IeNameOfFile(reader), new IeNameOfSection(reader), new IeFileSegment(reader) } }; break; // 126 case TypeId.F_DR_TA_1: informationElements = new InformationElement[numberOfSequenceElements][]; for (var i = 0; i < numberOfSequenceElements; i++) { informationElements[i] = new InformationElement[4]; informationElements[i][0] = new IeNameOfFile(reader); informationElements[i][1] = new IeLengthOfFileOrSection(reader); informationElements[i][2] = new IeStatusOfFile(reader); informationElements[i][3] = new IeTime56(reader); } break; // 127 case TypeId.F_SC_NB_1: informationElements = new[] {new InformationElement[] {new IeNameOfFile(reader), new IeTime56(reader), new IeTime56(reader)}}; break; default: throw new IOException( "Unable to parse Information Object because of unknown Type Identification: " + typeId); } }