Beispiel #1
0
        private void ProcessReceivedFrame()
        {
            Frame     frame      = null;
            Exception frameError = null;

            try
            {
                var decodedString = Encoding.ASCII.GetString(_buf.ToArray(), 0, _buf.Count);
                _log.LogInformation("[receive]{0}", ControlCodesUtility.ReplaceControlCodesToLoggingCodes(decodedString));
                frame = Frame.Parse(decodedString, _lowLevelSettings);
                var expectedFN = (_previousFN + 1) % 8;
                if (frame.FN != expectedFN)
                {
                    frameError = new FrameNumberException("Expected frame number {0} but was {1}", expectedFN, frame.FN);
                }

                _previousFN = frame.FN;
            }
            catch (FrameParseException frameParseException)
            {
                _log.LogError(frameParseException.Message);
                frameError = frameParseException;
            }

            _buf.Clear();
            if (frameError == null)
            {
                // Ok
                _currentRecord += frame.Body;
                if (frame.FrameType == FrameTypes.TerminationFrame)
                {
                    _message      += _currentRecord + "\r\n";
                    _currentRecord = "";
                }

                if (!_completed)
                {
                    _stream.WriteByte((byte)DataLinkControlCodes.ACK);
                    _log.LogInformation("[send]{0}", ControlCodesUtility.ToControlCode((byte)DataLinkControlCodes.ACK));
                }
            }
            else
            {
                if (_completed)
                {
                    // Frame error
                    _stream.WriteByte((byte)DataLinkControlCodes.NAK);
                    _log.LogInformation("[send]{0}", ControlCodesUtility.ToControlCode((byte)DataLinkControlCodes.NAK));
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Читает максимум один фрейм и возвращает управление. При этом сохраняет свое состояние и ждет повторного вызова
        /// чтобы выкачать все сообщение.
        /// </summary>
        /// <exception cref="ASTMIOException">Любая ошибка упаковывается в этот класс как InnerException</exception>
        /// <exception cref="TimeoutException">Тихо в лесу</exception>
        public void ExecuteDownloadStep()
        {
            if (Completed)
            {
                throw new InvalidOperationException("Download has been completed already");
            }

            switch (_state)
            {
            case States.WaitEstablishmentPhase:
                _stream.ReadTimeout = 100;
                var b = (byte)_stream.ReadByte();
                if (b == (byte)DataLinkControlCodes.ENQ)
                {
                    _log.LogInformation($"[receive]{ControlCodesUtility.ToControlCode(b)}");
                    _stream.WriteByte((byte)DataLinkControlCodes.ACK);
                    _log.LogInformation($"[send]{ControlCodesUtility.ToControlCode((byte) DataLinkControlCodes.ACK)}");
                    _state = States.ReceiveFrame;
                }
                else
                {
                    _log.LogDebug($"[receive]{(char) b}");
                }

                break;

            case States.ReceiveFrame:
                if (!_timersManager.IsTimerInStartedState(WAIT_FRAME_TIMER_NAME))
                {
                    _timersManager.StartTimer(WAIT_FRAME_TIMER_NAME, _lowLevelSettings.WaitFrameTimeout);
                }

                try
                {
                    _stream.ReadTimeout = 100;
                    b = (byte)_stream.ReadByte();
                    if (b == (byte)DataLinkControlCodes.EOT)
                    {
                        _timersManager.StopTimer(WAIT_FRAME_TIMER_NAME);
                        _log.LogInformation("[receive]{0}", ControlCodesUtility.ToControlCode(b));
                        _state     = States.Completed;
                        _completed = true;
                        break;
                    }

                    _buf.Add(b);
                    if (b == (byte)DataLinkControlCodes.LF)
                    {
                        ProcessReceivedFrame();
                        _timersManager.StopTimer(WAIT_FRAME_TIMER_NAME);
                    }

                    _state = States.ReceiveFrame;
                }
                catch (TimeoutException timeoutException)
                {
                    if (_timersManager.CheckTimerTimeout(WAIT_FRAME_TIMER_NAME))
                    {
                        throw new DataLinkLayerException(timeoutException, "Wait frame timeout");
                    }
                }

                break;

            case States.Completed:
                throw new InvalidOperationException("Download has been completed already");
            }
        }
Beispiel #3
0
        /// <summary>
        /// Закачивает максимум один фрейм и возвращает управление. При этом сохраняет свое состояние и ждет повторного вызова,
        /// для того что бы закончить upload.
        /// </summary>
        /// <exception cref="UploadException">Выгрузка прервана из-за ошибок</exception>
        /// <exception cref="InvalidOperationException">Выгрузка уже закончена</exception>
        public void ExecuteUploadStep()
        {
            byte[] buf = null;

            if (Completed)
            {
                throw new InvalidOperationException("Upload has been completed already");
            }

            if (!_timersManager.CheckTimerTimeout(WAIT_DELAY_TIMER_NAME))
            {
                return;
            }

            switch (_state)
            {
            case States.EstablishmentPhaseBegin:
                _stream.WriteByte((byte)DataLinkControlCodes.ENQ);
                _log.LogInformation("[send]{0}", ControlCodesUtility.ToControlCode((byte)DataLinkControlCodes.ENQ));
                _timersManager.StartTimer(WAIT_ANSWER_TIMER_NAME, _lowLevelSettings.EnqWaitTimeout);
                _state = States.EstablishmentPhaseWaitAnswer;
                break;

            case States.EstablishmentPhaseWaitAnswer:
                try
                {
                    _stream.ReadTimeout = 100;
                    var b = (byte)_stream.ReadByte();
                    _timersManager.StopTimer(WAIT_ANSWER_TIMER_NAME);
                    _log.LogInformation("[receive]{0}", ControlCodesUtility.ToControlCode(b));
                    if (b == (byte)DataLinkControlCodes.ACK)
                    {
                        _state = States.TransferPhaseSendFrame;
                    }
                    else if (b == (byte)DataLinkControlCodes.ENQ)
                    {
                        if (_havePriority)
                        {
                            _errorCounterENQ++;
                            if (_errorCounterENQ >= 2)
                            {
                                throw new DataLinkLayerException(new UnexpectedENQException(), "Remote system is stupid cow");
                            }

                            _timersManager.StartTimer(WAIT_DELAY_TIMER_NAME, 1000);
                            _state = States.EstablishmentPhaseBegin;
                        }
                        else
                        {
                            throw new DataLinkLayerException(new ContentionErrorException(), "Contention error occured");
                        }
                    }
                    else if (b == (byte)DataLinkControlCodes.NAK)
                    {
                        _errorCounterNAK++;
                        if (_errorCounterNAK >= 6)
                        {
                            _exceptionOccured = new DataLinkLayerException(new BusyException(), "Remote system busy while Establishment Phase");
                            _state            = States.TerminationPhase;
                        }
                        else
                        {
                            _state = States.EstablishmentPhaseBegin;
                            _timersManager.StartTimer(WAIT_DELAY_TIMER_NAME, 1000);
                        }
                    }
                    else
                    {
                        _exceptionOccured = new DataLinkLayerException(new DefectiveResponseException(), "Defective response error occured while Establishment Phase");
                        _state            = States.TerminationPhase;
                    }
                }
                catch (TimeoutException timeoutException)
                {
                    if (_timersManager.CheckTimerTimeout(WAIT_ANSWER_TIMER_NAME))
                    {
                        _exceptionOccured = new DataLinkLayerException(timeoutException, "Remote device doesn't response while Establishment Phase");
                        _state            = States.TerminationPhase;
                    }
                }

                break;

            case States.TransferPhaseSendFrame:
                _errorCounterDefective = 0;
                _errorCounterNAK       = 0;
                _frameCounter++;
                if (_frameCounter >= _frames.Length)
                {
                    _state = States.TerminationPhase;
                    break;
                }

                _currentFrame = _frames[_frameCounter];
                buf           = Encoding.ASCII.GetBytes(_currentFrame.ToString());
                _stream.Write(buf, 0, buf.Length);
                _log.LogInformation("[send]{0}", ControlCodesUtility.ReplaceControlCodesToLoggingCodes(_currentFrame.ToString()));
                _timersManager.StartTimer(WAIT_ANSWER_TIMER_NAME, 15000);
                _state = States.TransferPhaseWaitAnswer;
                break;

            case States.TransferPhaseResendFrame:
                buf = Encoding.ASCII.GetBytes(_currentFrame.ToString());
                _stream.Write(buf, 0, buf.Length);
                _log.LogInformation("[send]{0}", ControlCodesUtility.ReplaceControlCodesToLoggingCodes(_currentFrame.ToString()));
                _timersManager.StartTimer(WAIT_ANSWER_TIMER_NAME, 15000);
                _state = States.TransferPhaseWaitAnswer;
                break;

            case States.TransferPhaseWaitAnswer:
                try
                {
                    _stream.ReadTimeout = 100;
                    var b = (byte)_stream.ReadByte();
                    _timersManager.StopTimer(WAIT_ANSWER_TIMER_NAME);
                    _log.LogInformation("[receive]{0}", ControlCodesUtility.ToControlCode(b));
                    if (b == (byte)DataLinkControlCodes.ACK)
                    {
                        _state = States.TransferPhaseSendFrame;
                    }
                    else if (b == (byte)DataLinkControlCodes.NAK || b == (byte)DataLinkControlCodes.EOT)
                    {
                        _errorCounterNAK++;
                        if (_errorCounterNAK >= 6)
                        {
                            _state            = States.TerminationPhase;
                            _exceptionOccured = new DataLinkLayerException(new BusyException(), "Remote system busy while Transfer Phase");
                        }
                        else
                        {
                            _state = States.TransferPhaseResendFrame;
                            _timersManager.StartTimer(WAIT_DELAY_TIMER_NAME, 10000);
                        }
                    }
                    else
                    {
                        _errorCounterDefective++;
                        if (_errorCounterDefective >= 6)
                        {
                            _state            = States.TerminationPhase;
                            _exceptionOccured = new DataLinkLayerException(new DefectiveResponseException(), "Remote system response defective while Transfer Phase");
                        }
                        else
                        {
                            _state = States.TransferPhaseResendFrame;
                        }
                    }
                }
                catch (TimeoutException timeoutException)
                {
                    if (_timersManager.CheckTimerTimeout(WAIT_ANSWER_TIMER_NAME))
                    {
                        _state            = States.TerminationPhase;
                        _exceptionOccured = new DataLinkLayerException(timeoutException, "Remote device doesn't response while Transfer Phase");
                    }
                }

                break;

            case States.TerminationPhase:
                _stream.WriteByte((byte)DataLinkControlCodes.EOT);
                _log.LogInformation("[send]{0}", ControlCodesUtility.ToControlCode((byte)DataLinkControlCodes.EOT));
                if (_exceptionOccured != null)
                {
                    throw _exceptionOccured;
                }
                else
                {
                    _uploadCompleted = true;
                }

                break;
            }
        }