Beispiel #1
0
        private static Command ParseResponse(APIResponse response)
        {
            // Make sure there was a tag on the response
            if (response.Tag == null)
            {
                Console.WriteLine($"No tag ({response})");
                return(null);
            }

            // Find command using tag
            Command command = CommandsWaitingForResponse[response.Tag];

            // Don't need to proceed if this is the response to our KeepAlive ping
            if (response.Tag == _keepAliveTag)
            {
                // TODO do NAT stuff here instead of where we sent this ping, since we have the port the API sees
                AniDB.InvokeKeepAlivePong();
                return(null);
            }

            if (command != null)
            {
                return(command);
            }

            // We should always have a command here, since we set a tag on every command we send
            // Raise an error saying we're missing a command
            AniDB.InvokeClientError(
                new ClientErrorArgs($"Command is null; tag is probably not set on reply\nData: {response}")
                );

            return(null);
        }
Beispiel #2
0
        private static ICommandResult WaitForResponse(CommandTag tag)
        {
            int waitTime = 0;

            while (CommandsWithResponse.ContainsKey(tag) == false)
            {
                if (waitTime > 20_000)
                {
                    // Note: I *think* that this should fix itself it it encounters a race condition.
                    lock (rlLock) {
                        _timeOutsSinceLastResponse++;
                        if (_timeOutsSinceLastResponse > 5)
                        {
                            // we're probably rate limited
                            _rateLimited = true;
                        }
                    }

                    return(new CommandResult(ReturnCode.RequestTimedOut));
                }

                Thread.Sleep(50);
                waitTime += 50;
            }

            lock (rlLock) {
                _timeOutsSinceLastResponse = 0;
            }

            AniDB.InvokeCommandResultReceived(new CommandResultReceivedArgs());
            tag.Release();
            return(CommandsWithResponse[tag]);
        }
Beispiel #3
0
        public static Task <ICommandResult> QueueCommand(Command command)
        {
            if (Connected == false)
            {
                AniDB.InvokeClientError(
                    new ClientErrorArgs(
                        $"Connection must be initialized before queueing commands! {command.CommandBase}"));
            }

            CommandQueue.Enqueue(command);
            return(Task.Run(() => WaitForResponse(command.Tag)));
        }
Beispiel #4
0
        private static void KeepConnectionAlive(DateTime lastCommandSentTime)
        {
            // Check if last command we sent was more than 5 minutes ago so we can keep connection alive (for NAT)
            if (lastCommandSentTime < DateTime.Now.AddMinutes(-5) && lastCommandSentTime != DateTime.MinValue)
            {
                PingCommand pingCommand  = new PingCommand();
                bool        parameterSet = pingCommand.SetOptionalParameter("nat", "1", out string error);
                if (parameterSet == false)
                {
                    AniDB.InvokeClientError(new ClientErrorArgs($"Setting parameter failed ({error})"));
                    return;
                }

                _keepAliveTag = pingCommand.Tag;

                Task <ICommandResult> _ = pingCommand.Send();
                AniDB.InvokeKeepAlivePing();
            }

            Thread.Sleep(150); // small timeout
        }
Beispiel #5
0
        private static void SendCommand(Command command)
        {
            if (ShouldSendCommand(command) == false)
            {
                return;
            }

            string commandString = $"{command.CommandBase} {command.GetParameters()}".Trim();

            if (command.RequiresSession)
            {
                commandString += $"&{Session.SessionKey}";
            }

            // TEMP
            Console.WriteLine("Sending data: " + commandString);

            AniDB.InvokeCommandSent(new CommandSentArgs(command));

            byte[] bytes = Encoding.ASCII.GetBytes(commandString);
            _connection.Send(bytes, bytes.Length);
            CommandsWaitingForResponse.Add(command.Tag, command);
        }