Ejemplo n.º 1
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);
                }

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

                acknowledgedSendSequenceNumber = aPdu.GetReceiveSeqNumber();

                if (sendSequenceNumber != acknowledgedSendSequenceNumber)
                {
                    ScheduleMaxTimeNoAckReceivedFuture();
                }
            }
        }
Ejemplo n.º 2
0
        public void Send(ASdu aSdu)
        {
            acknowledgedReceiveSequenceNumber = receiveSequenceNumber;
            var requestAPdu = new APdu(sendSequenceNumber, receiveSequenceNumber, APdu.ApciType.I_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();
        }
Ejemplo n.º 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();
        }
Ejemplo n.º 4
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.I_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.maxTimeNoAckSentFuture = null;
                                    }, 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:
                            try
                            {
                                innerConnection.writer.Write(TestfrConBuffer, 0, TestfrConBuffer.Length);
                                innerConnection.writer.Flush();
                            }
                            catch (Exception e)
                            {
                                throw new IOException(e.Message);
                            }

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