Esempio n. 1
0
        public void ProcessCurrentState(IDownloader downloader, IUploader uploader)
        {
            if (!_timersManager.CheckTimerTimeout(DISABLE_UPLOAD_TIMER_NAME))
            {
                _uploadEnabled = true;
            }

            if (_stream.IsInFaultState && !_stream.Reopen())
            {
                Thread.Sleep(_lowLevelSettings.ConnectionRetryTime);
                return;
            }

            switch (_state)
            {
            case DataLinkStates.Upload:
                try
                {
                    _uploader.ExecuteUploadStep();
                    if (_uploader.Completed)
                    {
                        disableUpload(_lowLevelSettings.DelayUploadAfterUpload);
                        _state = DataLinkStates.Neutral;
                        raiseMessageUploadCompleted(new IOMessageEventArgs(_uploader.Message));
                    }
                }
                catch (DataLinkLayerException ex)
                {
                    _log.LogError(ex.Message);
                    if (ex.InnerException is ContentionErrorException)
                    {
                        _downloader.Reset();
                        _state = DataLinkStates.Download;
                    }
                    else
                    {
                        disableUpload(_lowLevelSettings.DelayUploadAfterUploadError);
                        _state = DataLinkStates.Neutral;
                        raiseMessageUploadCompleted(new IOMessageEventArgs(_uploader.Message, ex));
                    }
                }
                break;

            case DataLinkStates.Download:
                try
                {
                    _downloader.ExecuteDownloadStep();
                    if (_downloader.Completed)
                    {
                        disableUpload(_lowLevelSettings.DelayUploadAfterDownload);
                        _state = DataLinkStates.Neutral;
                        raiseMessageDownloadCompleted(new IOMessageEventArgs(_downloader.Message));
                    }
                }
                catch (TimeoutException)
                {
                    // The Data Link in the neutral state
                    _state = DataLinkStates.Neutral;
                }
                catch (DataLinkLayerException ex)
                {
                    _log.LogError(ex.Message);
                    _state = DataLinkStates.Neutral;
                    raiseMessageDownloadCompleted(new IOMessageEventArgs(_downloader.Message, ex));
                }
                break;

            case DataLinkStates.Neutral:
                if (_uploadQueue.Count > 0 && _uploadEnabled)
                {
                    var message = "";
                    lock (_uploadQueue)
                    {
                        message = _uploadQueue.Dequeue();
                    }
                    _uploader.ResetAndUpload(message);
                    _state = DataLinkStates.Upload;
                }
                else
                {
                    _downloader.Reset();
                    _state = DataLinkStates.Download;
                }
                break;
            }
        }
Esempio n. 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");
            }
        }
Esempio n. 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;
            }
        }