protected async void ReadLoop()
        {
            while (Client != null && Client.Connected)
            {
                string message = await ReadLineAsync(false).ConfigureAwait(false);

                if (message == null)
                {
                    continue;
                }

                if (message.StartsWith("error", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (!AtLeastOneResponseReceived)
                    {
                        AtLeastOneResponseReceived = true;
                        // Remove welcome messages after connect
                        ReceivedLines.Clear();
                    }

                    string responseText = string.Join("\n\r", ReceivedLines.Concat(new[] { message }));
                    MessageResponses.Enqueue(responseText);
                    ReceivedLines.Clear();

                    SimpleResponse response = SimpleResponse.Parse(responseText);

                    if (response.IsBanned)
                    {
                        BanDetected?.Invoke(this, new EventArgs <SimpleResponse>(response));
                        DisconnectForced("Banned!");
                        return;
                    }
                }
                else if (message.StartsWith("notify", StringComparison.CurrentCultureIgnoreCase))
                {
                    ThreadPool.QueueUserWorkItem(OnNotificationReceived, message);
                }
                else
                {
                    if (!AtLeastOneResponseReceived)
                    {
                        const string LastServerConnectionHandlerIdText = "selected schandlerid=";

                        if (message.StartsWith(LastServerConnectionHandlerIdText, StringComparison.InvariantCultureIgnoreCase) && int.TryParse(message.Substring(LastServerConnectionHandlerIdText.Length).Trim(), out int handlerId))
                        {
                            LastServerConnectionHandlerId = handlerId;
                        }
                    }

                    ReceivedLines.Add(message);
                }
            }
        }
Ejemplo n.º 2
0
        public async Task <ConnectResponse> ConnectAsync()
        {
            if (Client != null)
            {
                return(new ConnectResponse(message: "Already connected!"));
            }

            Client = new TcpClient();
            await Client.ConnectAsync(Host, Port).ConfigureAwait(false);

            if (!Client.Connected)
            {
                throw new IOException($"Could not connect to {Host} on port {Port}.");
            }

            ReceivedLines.Clear();
            AtLeastOneResponseReceived = false;
            ClientStream = Client.GetStream();
            ClientReader = new StreamReader(ClientStream);
            ClientWriter = new StreamWriter(ClientStream)
            {
                NewLine = "\n"
            };

            string message = await ReadLineAsync().ConfigureAwait(false);

            CommunicationLog.RawMessageReceived(message);

            QueryType queryType;

            if (message.StartsWith("TS3", StringComparison.OrdinalIgnoreCase))
            {
                queryType = QueryType.Server;
            }
            else if (message.StartsWith("TS3 Client", StringComparison.OrdinalIgnoreCase))
            {
                queryType = QueryType.Client;
            }
            else
            {
                string statusMessage = $"Invalid greeting received: {message}";
                DisconnectForced(statusMessage);
                return(new ConnectResponse(statusMessage));
            }

            Connected     = true;
            ReadLoopTask  = Task.Factory.StartNew(ReadLoop, TaskCreationOptions.LongRunning);
            KeepAliveTask = Task.Factory.StartNew(KeepAliveLoop, TaskCreationOptions.LongRunning);
            return(new ConnectResponse(message, queryType, true));
        }
Ejemplo n.º 3
0
        private void DisconnectForced(string reason)
        {
            bool clientWasConnected = Client?.Connected == true;

            ReceivedLines.Clear();
            Client?.Dispose();
            ClientStream?.Dispose();
            ClientReader?.Dispose();
            ClientWriter?.Dispose();

            Client       = null;
            ClientStream = null;
            ClientReader = null;
            ClientWriter = null;

            Connected     = false;
            ReadLoopTask  = null;
            KeepAliveTask = null;

            if (clientWasConnected)
            {
                ConnectionClosed?.Invoke(this, new EventArgs <string>(reason));
            }
        }
Ejemplo n.º 4
0
        protected async void ReadLoop()
        {
            while (Client != null && Client.Connected)
            {
                string message = await ReadLineAsync(false).ConfigureAwait(false);

                CommunicationLog.RawMessageReceived(message);

                if (message == null)
                {
                    continue;
                }

                if (message.StartsWith("error", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (!AtLeastOneResponseReceived)
                    {
                        AtLeastOneResponseReceived = true;
                        // Remove welcome messages after connect
                        ReceivedLines.Clear();
                    }

                    string responseText = string.Join(Util.QUERY_LINE_BREAK, ReceivedLines.Concat(new[] { message }));
                    MessageResponses.Enqueue(responseText);
                    ReceivedLines.Clear();

                    CommandResponse commandResponse = new CommandResponse();
                    commandResponse.ApplyResponseText(responseText);

                    if (commandResponse.IsBanned)
                    {
                        BanDetected?.Invoke(this, new EventArgs <ICommandResponse>(commandResponse));
                        DisconnectForced("Banned!");
                        return;
                    }
                }
                else if (message.StartsWith("notify", StringComparison.CurrentCultureIgnoreCase))
                {
                    // If 2 or more notifications are equal in a 200ms range, consider just one of them.
                    if (LastRawNotification == message && (DateTime.Now - LastNotificationTime).TotalMilliseconds < 200)
                    {
                        continue;
                    }

                    LastRawNotification  = message;
                    LastNotificationTime = DateTime.Now;

                    int    indexOfFirstWhitespace = message.IndexOf(' ');
                    string notificationName       = message.Substring(0, indexOfFirstWhitespace);

                    NotificationHub?.HandleRawNotification(this, notificationName, message);
                }
                else
                {
                    if (!AtLeastOneResponseReceived)
                    {
                        const string LastServerConnectionHandlerIdText = "selected schandlerid=";

                        if (message.StartsWith(LastServerConnectionHandlerIdText, StringComparison.CurrentCultureIgnoreCase) && int.TryParse(message.Substring(LastServerConnectionHandlerIdText.Length).Trim(), out int handlerId))
                        {
                            LastServerConnectionHandlerId = handlerId;
                        }
                    }

                    ReceivedLines.Add(message);
                }
            }
        }