Beispiel #1
0
        private void ConnectInit()
        {
            Debug.WriteLine($"{nameof(ConnectInit)} start");

            _n_recv         = 0;
            _n_trans        = 0;
            _n_ack          = 0;
            _sendBuffer     = new ConcurrentQueue <byte>();
            _ackRecvFlag    = false;
            _ackTimerActive = false;
            _ackTimer.Stop();
            _ackTimer.Interval = 2000;
            _ackTimer.Start();

            _sendTimerActive = false;
            _sendTimer.Stop();
            _sendTimer.Interval = 100;
            _sendTimer.Start();

            EyeballCharActive = false;

            _shiftState         = ShiftStates.Unknown;
            _lastSendRecvIdleMs = Helper.GetTicksMs();

            Local = false;

            _connStartTime = DateTime.Now;

            ConnectionState = ConnectionStates.Connected;

            Update?.Invoke();
            Connected?.Invoke();

            Debug.WriteLine($"{nameof(ConnectInit)} end");
        }
Beispiel #2
0
        private void AckTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (_ackTimerActive)
            {
                return;
            }
            _ackTimerActive = true;

            if (CentralexState == CentralexStates.CentralexConnected && !IsConnected)
            {
                SendHeartbeatCmd();
                _ackTimerActive = false;
                return;
            }

            //if (!IsConnected || ConnectionState != ConnectionStates.ItelexTexting)
            if (!IsConnected || ConnectionState != ConnectionStates.AsciiTexting && ConnectionState != ConnectionStates.ItelexTexting)
            {
                _ackTimerActive = false;
                return;
            }

            // check received acks

            lock (_sendLock)
            {
                //Debug.WriteLine(CharsAckCount);
                if (CharsAckCount > 0)
                {
                    string timeout = null;
                    if (_ackRecvFlag && _lastRecvAckValue == _n_ack)
                    {
                        // if ack was received and ack did'n change since the last AckTimer_Elapsed (2 sec)
                        Logging.Instance.Warn(TAG, nameof(AckTimer_Elapsed), $"recv ack value changed timeout");
                        timeout = "nochange";
                    }
                    _ackRecvFlag = false;

                    if (Helper.GetTicksMs() - _lastAckReceived > 5000)
                    {
                        Logging.Instance.Warn(TAG, nameof(AckTimer_Elapsed), $"ack recv timeout");
                        timeout = "timeout";
                    }
                    if (timeout != null)
                    {
                        _n_trans = _n_ack;
                    }
                }
                _lastRecvAckValue = _n_ack;
            }

            SendAckCmd(_n_recv);

            _ackTimerActive = false;
        }
Beispiel #3
0
        private void SendTimer()
        {
            //Debug.WriteLine($"SendTimer: {_sendBuffer.Count} {_itelixSendCount} {CharsAckCount} {_n_trans}/{_n_ack}={CharsAckCount}");
            //Logging.Instance.Log(LogTypes.Info, TAG, nameof(SendTimer), $"SendTimer: {_sendBuffer.Count} {_itelixSendCount} {CharsAckCount} {_n_trans}/{_n_ack}");
            //Debug.WriteLine($"{CharsAckCount}");
            lock (_sendLock)
            {
                int ackCount = CharsAckCount;
                for (int i = 0; !_sendBuffer.IsEmpty && _itelixSendCount < Constants.ITELIX_SENDBUFFER_SIZE && ackCount < Constants.ITELIX_REMOTEBUFFER_SIZE;
                     i++)
                {
                    if (!_sendBuffer.TryDequeue(out byte baudotCode))
                    {
                        break;
                    }

                    _itelixSendBuffer[_itelixSendCount++] = baudotCode;
                    ///Debug.WriteLine($"dequeue {asciiChr}");
                    //Logging.Instance.Debug(TAG, nameof(SendTimer), $"dequeue baudotCode={baudotCode:X02}, _itelixSendCount={_itelixSendCount}, ackCount={ackCount}");
                    ackCount++;
                }
            }

            //Debug.WriteLine($"_itelixSendCount={_itelixSendCount}");

            if (_itelixSendCount == 0)
            {
                //Debug.WriteLine($"#2 _itelixSendCount={_itelixSendCount}");
                //Logging.Instance.Log(LogTypes.Info, TAG, nameof(SendTimer), $"#2 {_itelixSendCount} == 0");
                return;
            }

            // if character count in itelex send buffer is < ITELIX_SENDBUFFER_SIZE wait for WAIT_BEFORE_SEND_MSEC before sending them
            if (_itelixSendCount < Constants.ITELIX_SENDBUFFER_SIZE &&
                Helper.GetTicksMs() - _lastSentMs < Constants.WAIT_BEFORE_SEND_MSEC)
            {
                //Debug.WriteLine($"#1 {_itelixSendCount} < {Constants.ITELIX_SENDBUFFER_SIZE} && {Helper.GetTicksMs() - _lastSentMs} < {Constants.WAIT_BEFORE_SEND_MSEC}");
                //Logging.Instance.Log(LogTypes.Info, TAG, nameof(SendTimer), $"#1 {_itelixSendCount} < {Constants.ITELIX_SENDBUFFER_SIZE} && {Helper.GetTicksMs() - _lastSentMs} < {Constants.WAIT_BEFORE_SEND_MSEC}");
                Debug.WriteLine($"lastsend={Helper.GetTicksMs() - _lastSentMs}");
                return;
            }

            //Debug.WriteLine($"_itelixSendCount={_itelixSendCount}");

            byte[] baudotData = new byte[_itelixSendCount];
            Buffer.BlockCopy(_itelixSendBuffer, 0, baudotData, 0, _itelixSendCount);
            SendCmd(ItelexCommands.BaudotData, baudotData);
            _itelixSendCount    = 0;
            _lastSentMs         = Helper.GetTicksMs();
            _lastSendRecvIdleMs = Helper.GetTicksMs();
        }
Beispiel #4
0
        private void DecodePacket(ItelexPacket packet)
        {
            /*
             * if (packet.CommandType != ItelexCommands.Ack)
             * {
             *      //Logging.Instance.Log(LogTypes.Debug, TAG, nameof(DecodePacket),
             *      //		$"Recv packet {packet.CommandType} {packet.Command:X02} {packet.GetDebugData()}");
             *      Logging.Instance.Debug(TAG, nameof(DecodePacket),
             *              $"Recv packet {packet.CommandType} {packet.GetDebugPacket()}");
             * }
             * if (packet.CommandType != ItelexCommands.Heartbeat && packet.CommandType != ItelexCommands.Ack)
             * {
             *      Debug.WriteLine($"Recv packet {packet.CommandType} {packet.GetDebugPacket()}");
             * }
             */

            switch ((ItelexCommands)packet.Command)
            {
            case ItelexCommands.Heartbeat:
                Logging.Instance.Debug(TAG, nameof(DecodePacket), $"recv heartbeat {packet.GetDebugPacket()}");
                break;

            case ItelexCommands.DirectDial:
                Logging.Instance.Info(TAG, nameof(DecodePacket), $"recv direct dial cmd  {packet.GetDebugPacket()}, number={packet.Data[0]}");
                int directDial = packet.Data[0];
                Message?.Invoke($"received direct dial cmd {directDial}");
                if (directDial == _config.IncomingExtensionNumber)
                {
                    ConnectInit();
                }
                else
                {                           // not connected
                    byte[] data = Encoding.ASCII.GetBytes("nc");
                    SendCmd(ItelexCommands.Reject, data);
                    Message?.Invoke($"send reject ncc");
                    Disconnect();
                }
                break;

            case ItelexCommands.BaudotData:
                if (packet.Len > 0)
                {
                    Logging.Instance.AppendBinary(packet.Data, Logging.BinaryModes.Recv);
                    string asciiStr = CodeManager.BaudotStringToAscii(packet.Data, ref _shiftState, _config.CodeSet, CodeManager.SendRecv.Recv);
                    Logging.Instance.Debug(TAG, nameof(DecodePacket), $"recv baudot data {packet.Len} \"{CodeManager.AsciiToDebugStr(asciiStr)}\"");
                    AddReceivedCharCount(packet.Data.Length);
                    _lastSendRecvIdleMs = Helper.GetTicksMs();
                    Received?.Invoke(asciiStr);
                    BaudotSendRecv?.Invoke(packet.Data);
                    Update?.Invoke();
                }
                break;

            case ItelexCommands.End:
                Logging.Instance.Info(TAG, nameof(DecodePacket), $"recv end cmd {packet.GetDebugPacket()}");
                Disconnect();
                break;

            case ItelexCommands.Reject:
                string reason = Encoding.ASCII.GetString(packet.Data, 0, packet.Data.Length);
                Logging.Instance.Info(TAG, nameof(DecodePacket), $"recv reject cmd {packet.GetDebugPacket()}, reason={reason}");
                Message?.Invoke($"{LngText(LngKeys.Message_Reject)} {reason.ToUpper()} ({ReasonToString(reason).ToUpper()})");
                if (CentralexState == CentralexStates.CentralexConnect && reason == "na")
                {
                    CentralexState = CentralexStates.CentralexRejected;
                }
                else
                {
                    Disconnect();
                }
                break;

            case ItelexCommands.Ack:
                lock (_sendLock)
                {
                    _n_ack           = packet.Data[0];
                    _ackRecvFlag     = true;
                    _lastAckReceived = Helper.GetTicksMs();
                }
                //Debug.WriteLine($"recv ack cmd {_n_ack} ({CharsAckCount})");
                Logging.Instance.Debug(TAG, nameof(DecodePacket), $"recv ack cmd  {packet.GetDebugPacket()} ack={_n_ack} ({CharsAckCount})");
                Update?.Invoke();
                break;

            case ItelexCommands.ProtocolVersion:
                string versionStr = "";
                if (packet.Data.Length > 1)
                {
                    // get version string
                    versionStr = Encoding.ASCII.GetString(packet.Data, 1, packet.Data.Length - 1);
                    versionStr = versionStr.TrimEnd('\x00');                             // remove 00-byte suffix
                }
                Message?.Invoke($"received protocol version {packet.Data[0]:X2} '{versionStr}'");
                Logging.Instance.Log(LogTypes.Info, TAG, nameof(DecodePacket), $"recv protocol version cmd  {packet.GetDebugPacket()}, version={packet.Data[0]} '{versionStr}'");
                if (_connectionDirection == ConnectionDirections.In)
                {
                    // answer with own version
                    SendVersionCodeCmd();
                }
                break;

            case ItelexCommands.SelfTest:
                Logging.Instance.Log(LogTypes.Info, TAG, nameof(DecodePacket), $"recv self test cmd {packet.GetDebugPacket()}");
                break;

            case ItelexCommands.RemoteConfig:
                Logging.Instance.Log(LogTypes.Info, TAG, nameof(DecodePacket), $"recv remote config cmd {packet.GetDebugPacket()}");
                break;

            case ItelexCommands.RemoteConfirm:
                CentralexState = CentralexStates.CentralexConnected;
                break;

            case ItelexCommands.RemoteCall:
                SendAcceptCallRemoteCmd();
                ConnectInit();
                _connectionDirection = ConnectionDirections.In;
                if (_config.IncomingExtensionNumber != 0)
                {
                    // set to connected and wait for direct dial command
                    ConnectionState = ConnectionStates.TcpConnected;
                }
                else
                {
                    // no direct dial command neccessary
                    ConnectInit();
                }
                Message?.Invoke($"{LngText(LngKeys.Message_IncomingConnection)} centralex");
                Logging.Instance.Log(LogTypes.Info, TAG, nameof(Listener), $"incoming connection from centralex");
                Update?.Invoke();
                break;
            }
        }
Beispiel #5
0
        private void DataReceived(IAsyncResult ar)
        {
            if (ConnectionState == ConnectionStates.Disconnected && CentralexState == CentralexStates.None)
            {
                return;
            }
            if (_client.Client == null)
            {
                Disconnect();
                return;
            }

            int dataReadCount;

            try
            {
                dataReadCount = _client.Client.EndReceive(ar);
            }
            catch
            {
                Disconnect();
                return;
            }

            if (dataReadCount == 0)
            {
                Disconnect();
                return;
            }

            byte[] byteData = ar.AsyncState as byte[];
            byte[] newData  = byteData.Take(dataReadCount).ToArray();

            if (ConnectionState == ConnectionStates.Connected)
            {
                if (newData[0] <= 0x09 || newData[0] >= 0x10 && newData[0] < 0x1F)
                {
                    ConnectionState = ConnectionStates.ItelexTexting;
                }
                else
                {
                    ConnectionState = ConnectionStates.AsciiTexting;
                }
                Update?.Invoke();
            }

            if (ConnectionState == ConnectionStates.AsciiTexting)
            {                   // ascii
                string asciiText = Encoding.ASCII.GetString(newData, 0, newData.Length);
                asciiText = asciiText.Replace('@', CodeManager.ASC_WRU);
                Received?.Invoke(asciiText);
                _lastSendRecvIdleMs = Helper.GetTicksMs();
            }
            else
            {                   // i-telex
                int dataPos = 0;
                while (dataPos + 2 <= newData.Length)
                {
                    //Debug.WriteLine($"datapos={dataPos} cmd={newData[dataPos]:X02}");
                    int packetLen = newData[dataPos + 1] + 2;
                    if (dataPos + packetLen > newData.Length)
                    {
                        // short packet data
                        break;
                    }

                    byte[] packetData = new byte[packetLen];
                    Buffer.BlockCopy(newData, dataPos, packetData, 0, packetLen);
                    dataPos += packetLen;

                    if (packetData.Length >= 2 && packetData.Length >= packetData[1] + 2)
                    {
                        ItelexPacket packet = new ItelexPacket(packetData);
                        //Debug.WriteLine($"packet={packet}");
                        DecodePacket(packet);
                    }
                }
            }
            StartReceive();

#if false
            // if data comes in different frame (untested)
            if (newData.Length > 0)
            {
                // append newData to _incommingData
                byte[] newIncomingData = new byte[_incomingData.Length + newData.Length];
                Buffer.BlockCopy(_incomingData, 0, newIncomingData, 0, _incomingData.Length);
                Buffer.BlockCopy(newData, 0, newIncomingData, _incomingData.Length, newData.Length);
                _incomingData = newData;
            }

            bool exitWhile = false;
            while (exitWhile)
            {
                exitWhile = true;
                if (_incomingData.Length > 2)
                {
                    if (_incomingData[1] <= _incomingData.Length + 2)
                    {
                        // telegram complete
                    }
                }
            }
#endif
        }