Beispiel #1
0
            public override void Run()
            {
                try
                {
                    var reader = innerConnection.reader;
                    while (true)
                    {
                        if (reader.ReadByte() != 0x68)
                        {
                            throw new IOException("Message does not start with 0x68");
                        }

                        var aPdu = new APdu(reader, innerConnection.settings);
                        switch (aPdu.GetApciType())
                        {
                            case APdu.ApciType.FORMAT:
                                if (innerConnection.receiveSequenceNumber != aPdu.GetSendSeqNumber())
                                {
                                    throw new IOException("Got unexpected send sequence number: " +
                                                          aPdu.GetSendSeqNumber()
                                                          + ", expected: " + innerConnection.receiveSequenceNumber);
                                }

                                innerConnection.receiveSequenceNumber = (aPdu.GetSendSeqNumber() + 1)%32768;
                                innerConnection.HandleReceiveSequenceNumber(aPdu);

                                innerConnection.NewASdu?.Invoke(aPdu.GetASdu());

                                var numUnconfirmedIPdusReceived = innerConnection.GetSequenceNumberDifference(
                                    innerConnection.receiveSequenceNumber,
                                    innerConnection.acknowledgedReceiveSequenceNumber);
                                if (numUnconfirmedIPdusReceived > innerConnection.settings.MaxUnconfirmedIPdusReceived)
                                {
                                    innerConnection.SendSFormatPdu();
                                    if (innerConnection.maxTimeNoAckSentFuture != null)
                                    {
                                        innerConnection.maxTimeNoAckSentFuture.Cancel();
                                        innerConnection.maxTimeNoAckSentFuture = null;
                                    }
                                }
                                else
                                {
                                    if (innerConnection.maxTimeNoAckSentFuture == null)
                                    {
                                        innerConnection.maxTimeNoAckSentFuture =
                                            PeriodicTaskFactory.Start(() => { innerConnection.SendSFormatPdu(); },
                                                innerConnection.settings.MaxTimeNoAckSent);
                                    }
                                }

                                innerConnection.ResetMaxIdleTimeTimer();
                                break;
                            case APdu.ApciType.STARTDT_CON:
                                innerConnection.startdtConSignal?.CountDown();
                                innerConnection.ResetMaxIdleTimeTimer();
                                break;
                            case APdu.ApciType.STARTDT_ACT:
                                innerConnection.startdtactSignal?.CountDown();
                                break;
                            case APdu.ApciType.S_FORMAT:
                                innerConnection.HandleReceiveSequenceNumber(aPdu);
                                innerConnection.ResetMaxIdleTimeTimer();
                                break;
                            case APdu.ApciType.TESTFR_ACT:
                                innerConnection.writer.Write(TestfrConBuffer, 0, TestfrConBuffer.Length);
                                innerConnection.writer.Flush();
                                innerConnection.ResetMaxIdleTimeTimer();
                                break;
                            case APdu.ApciType.TESTFR_CON:
                                if (innerConnection.maxTimeNoTestConReceivedFuture != null)
                                {
                                    innerConnection.maxTimeNoTestConReceivedFuture.Cancel();
                                    innerConnection.maxTimeNoTestConReceivedFuture = null;
                                }
                                innerConnection.ResetMaxIdleTimeTimer();
                                break;
                            default:
                                throw new IOException("Got unexpected message with APCI Type: " + aPdu.GetApciType());
                        }
                    }
                }
                catch (IOException e)
                {
                    innerConnection.closedIoException = e;
                }
                catch (Exception e)
                {
                    innerConnection.closedIoException = new IOException(e.Message);
                }
                finally
                {
                    innerConnection.ConnectionClosed?.Invoke(innerConnection.closedIoException);

                    innerConnection.Close();
                }
            }
Beispiel #2
0
        private void HandleReceiveSequenceNumber(APdu aPdu)
        {
            if (acknowledgedSendSequenceNumber != aPdu.GetReceiveSeqNumber())
            {
                if (GetSequenceNumberDifference(aPdu.GetReceiveSeqNumber(), acknowledgedSendSequenceNumber) >
                    GetNumUnconfirmedIPdusSent())
                {
                    throw new IOException("Got unexpected receive sequence number: " + aPdu.GetReceiveSeqNumber()
                                          + ", expected a number between: " + acknowledgedSendSequenceNumber + " and "
                                          + sendSequenceNumber);
                }

                acknowledgedSendSequenceNumber = aPdu.GetReceiveSeqNumber();

                if (sendSequenceNumber != acknowledgedSendSequenceNumber)
                {
                    ScheduleMaxTimeNoAckReceivedFuture();
                }
            }
        }
Beispiel #3
0
        private void SendSFormatPdu()
        {
            var requestAPdu = new APdu(0, receiveSequenceNumber, APdu.ApciType.S_FORMAT, null);
            requestAPdu.Encode(buffer, settings);

            writer.Write(buffer, 0, 6);
            writer.Flush();

            acknowledgedReceiveSequenceNumber = receiveSequenceNumber;

            ResetMaxIdleTimeTimer();
        }
Beispiel #4
0
        public void Send(ASdu aSdu)
        {
            acknowledgedReceiveSequenceNumber = receiveSequenceNumber;
            var requestAPdu = new APdu(sendSequenceNumber, receiveSequenceNumber, APdu.ApciType.FORMAT, aSdu);
            sendSequenceNumber = (sendSequenceNumber + 1)%32768;

            if (maxTimeNoAckSentFuture != null)
            {
                maxTimeNoAckSentFuture.Cancel();
                maxTimeNoAckSentFuture = null;
            }

            if (maxTimeNoAckReceivedFuture == null)
            {
                ScheduleMaxTimeNoAckReceivedFuture();
            }

            var length = requestAPdu.Encode(buffer, settings);
            writer.Write(buffer, 0, length);
            writer.Flush();

            ResetMaxIdleTimeTimer();
        }