Пример #1
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;
            }
        }
Пример #2
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
        }