private void Listener() { while (true) { try { if (!RecvOn) { return; } // wait for connection _client = _tcpListener.AcceptTcpClient(); if (_config.IncomingExtensionNumber != 0) { // set to connected and wait for direct dial command ConnectionState = ConnectionStates.TcpConnected; } else { // no direct dial command neccessary ConnectInit(); } _connectionDirection = ConnectionDirections.In; StartReceive(); IPAddress remoteAddr = ((IPEndPoint)_client.Client.RemoteEndPoint).Address; Message?.Invoke($"{LngText(LngKeys.Message_IncomingConnection)} {remoteAddr}"); Logging.Instance.Log(LogTypes.Info, TAG, nameof(Listener), $"incoming connection from {remoteAddr}"); Update?.Invoke(); while (true) { if (_client == null) { return; } if (!_client.Connected) { break; } } Disconnect(); _connectionDirection = ConnectionDirections.Out; } catch (Exception ex) { if (ex.HResult != -2147467259) { Logging.Instance.Error(TAG, nameof(Listener), "", ex); } Disconnect(); } } }
public async Task <bool> ConnectOut(string host, int port, int extensionNumber, bool asciiMode = false) { bool status = false; await Task.Run(() => { try { _client = new TcpClient(host, port); if (_client == null || !_client.Connected) { Logging.Instance.Log(LogTypes.Info, TAG, nameof(ConnectOut), $"outgoing connection {host}:{port} failed"); return(false); } } catch (Exception ex) { Logging.Instance.Error(TAG, nameof(ConnectOut), "", ex); return(false); } ConnectInit(); ConnectionState = ConnectionStates.TcpConnected; _connectionDirection = ConnectionDirections.Out; StartReceive(); // wait for cr/lf Stopwatch sw = new Stopwatch(); sw.Start(); while (sw.ElapsedMilliseconds < 2000 && ConnectionState == ConnectionStates.TcpConnected) { Thread.Sleep(100); } sw.Stop(); Update?.Invoke(); if (!asciiMode) { //SendVersionCodeCmd(); } if (!asciiMode) { SendVersionCodeCmd(); Thread.Sleep(200); SendDirectDialCmd(extensionNumber); Thread.Sleep(200); } if (ConnectionState == ConnectionStates.Disconnected) { status = true; return(true); } ConnectionState = ConnectionStates.Connected; Logging.Instance.Info(TAG, nameof(ConnectOut), $"outgoing connection {host}:{port}"); if (asciiMode) { ConnectionState = ConnectionStates.AsciiTexting; SendAsciiText("\n\r"); } else { SendCode(CodeManager.BAU_LTRS, ref _shiftState); } Update?.Invoke(); status = true; return(true); }); return(status); }
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; } }