예제 #1
0
        public override void Connect(ConnectionData conData)
        {
            if (!TsDnsResolver.TryResolve(conData.Address, out remoteAddress))
            {
                throw new Ts3Exception("Could not read or resolve address.");
            }

            try
            {
                connecting = true;

                tcpClient.Connect(remoteAddress);

                ConnectionData = conData;

                tcpStream = tcpClient.GetStream();
                tcpReader = new StreamReader(tcpStream, Util.Encoder);
                tcpWriter = new StreamWriter(tcpStream, Util.Encoder)
                {
                    NewLine = "\n"
                };

                for (int i = 0; i < 3; i++)
                {
                    tcpReader.ReadLine();
                }
            }
            catch (SocketException ex) { throw new Ts3Exception("Could not connect.", ex); }
            finally { connecting = false; }

            dispatcher.Init(NetworkLoop, InvokeEvent, null);
            OnConnected?.Invoke(this, EventArgs.Empty);
            dispatcher.EnterEventLoop();
        }
예제 #2
0
        /// <summary>Tries to connect to a server.</summary>
        /// <param name="conData">Set the connection information properties as needed.
        /// For further details about each setting see the respective property documentation in <see cref="ConnectionData"/></param>
        /// <exception cref="ArgumentException">When some required values are not set or invalid.</exception>
        /// <exception cref="TsException">When the connection could not be established.</exception>
        public override async CmdR Connect(ConnectionData conData)
        {
            scheduler.VerifyOwnThread();
            if (!(conData is ConnectionDataFull conDataFull))
            {
                throw new ArgumentException($"Use the {nameof(ConnectionDataFull)} derivative to connect with the full client.", nameof(conData));
            }
            if (conDataFull.Identity is null)
            {
                throw new ArgumentNullException(nameof(conDataFull.Identity));
            }
            if (conDataFull.VersionSign is null)
            {
                throw new ArgumentNullException(nameof(conDataFull.VersionSign));
            }

            await Disconnect();

            remoteAddress = await TsDnsResolver.TryResolve(conData.Address);

            if (remoteAddress is null)
            {
                return(CommandError.Custom("Could not read or resolve address."));
            }

            ConnectionData  = conData;
            ServerConstants = TsConst.Default;
            Book.Reset();
            returnCode = 0;

            var ctx = new ConnectionContext(conDataFull);

            context = ctx;

            ctx.PacketHandler.PacketEvent = (ref Packet <S2C> packet) =>
            {
                if (status == TsClientStatus.Disconnected)
                {
                    return;
                }
                PacketEvent(ctx, ref packet);
            };
            ctx.PacketHandler.StopEvent = (closeReason) =>
            {
                _ = scheduler.Invoke(() =>
                {
                    ctx.ExitReason ??= closeReason;
                    ChangeState(ctx, TsClientStatus.Disconnected);
                });
            };

            ChangeState(ctx, TsClientStatus.Connecting);
            if (!ctx.PacketHandler.Connect(remoteAddress).GetOk(out var error))
            {
                ChangeState(ctx, TsClientStatus.Disconnected);
                return(CommandError.Custom(error));
            }
            return(await ctx.ConnectEvent.Task);            // TODO check error state
        }
예제 #3
0
        /// <summary>Tries to connect to a server.</summary>
        /// <param name="conData">Set the connection information properties as needed.
        /// For further details about each setting see the respective property documentation in <see cref="ConnectionData"/></param>
        /// <exception cref="ArgumentException">When some required values are not set or invalid.</exception>
        /// <exception cref="TsException">When the connection could not be established.</exception>
        public override void Connect(ConnectionData conData)
        {
            if (!(conData is ConnectionDataFull conDataFull))
            {
                throw new ArgumentException($"Use the {nameof(ConnectionDataFull)} derivative to connect with the full client.", nameof(conData));
            }
            if (conDataFull.Identity is null)
            {
                throw new ArgumentNullException(nameof(conDataFull.Identity));
            }
            if (conDataFull.VersionSign is null)
            {
                throw new ArgumentNullException(nameof(conDataFull.VersionSign));
            }
            connectionDataFull = conDataFull;
            ConnectionData     = conData;

            Disconnect();

            if (!TsDnsResolver.TryResolve(conData.Address, out remoteAddress))
            {
                throw new TsException("Could not read or resolve address.");
            }

            lock (statusLock)
            {
                returnCode = 0;
                status     = TsClientStatus.Connecting;

                VersionSign      = conDataFull.VersionSign;
                tsCrypt          = new TsCrypt();
                tsCrypt.Identity = conDataFull.Identity;

                var ctx = new ConnectionContext {
                    WasExit = false
                };
                context = ctx;

                packetHandler             = new PacketHandler <S2C, C2S>(tsCrypt, conData.LogId);
                packetHandler.PacketEvent = (ref Packet <S2C> packet) => { PacketEvent(ctx, ref packet); };
                packetHandler.StopEvent   = (closeReason) => { ctx.ExitReason = closeReason; DisconnectInternal(ctx, setStatus: TsClientStatus.Disconnected); };
                packetHandler.Connect(remoteAddress);
                dispatcher = new ExtraThreadEventDispatcher();
                dispatcher.Init(InvokeEvent, conData.LogId);
            }
        }
예제 #4
0
        /// <summary>Tries to connect to a server.</summary>
        /// <param name="conData">Set the connection information properties as needed.
        /// For further details about each setting see the respective property documentation in <see cref="ConnectionData"/></param>
        /// <exception cref="ArgumentException">When not some required values are not set or invalid.</exception>
        /// <exception cref="Ts3Exception">When the connection could not be established.</exception>
        public override void Connect(ConnectionData conData)
        {
            if (!(conData is ConnectionDataFull conDataFull))
            {
                throw new ArgumentException($"Use the {nameof(ConnectionDataFull)} deriverate to connect with the full client.", nameof(conData));
            }
            try { HidePing = File.Exists("noping"); } catch (Exception) { }
            Console.WriteLine("Hidden Ping: {0}", HidePing);
            if (conDataFull.Identity == null)
            {
                throw new ArgumentNullException(nameof(conDataFull.Identity));
            }
            if (conDataFull.VersionSign == null)
            {
                throw new ArgumentNullException(nameof(conDataFull.VersionSign));
            }
            connectionDataFull = conDataFull;
            ConnectionData     = conData;

            Disconnect();

            if (!TsDnsResolver.TryResolve(conData.Address, out remoteAddress))
            {
                throw new Ts3Exception("Could not read or resolve address.");
            }

            lock (statusLock)
            {
                returnCode = 0;
                status     = Ts3ClientStatus.Connecting;
                context    = new ConnectionContext {
                    WasExit = false
                };

                VersionSign = conDataFull.VersionSign;
                ts3Crypt.Reset();
                ts3Crypt.Identity = conDataFull.Identity;

                packetHandler.Connect(remoteAddress);
                dispatcher.Init(NetworkLoop, InvokeEvent, context);
            }
            dispatcher.EnterEventLoop();
        }
예제 #5
0
        public override async CmdR Connect(ConnectionData conData)
        {
            remoteAddress = await TsDnsResolver.TryResolve(conData.Address, TsDnsResolver.TsQueryDefaultPort);

            if (remoteAddress is null)
            {
                return(CommandError.Custom("Could not read or resolve address."));
            }

            NetworkStream tcpStream;

            try
            {
                connecting = true;

                await tcpClient.ConnectAsync(remoteAddress.Address, remoteAddress.Port);

                ConnectionData = conData;

                tcpStream = tcpClient.GetStream();
                tcpReader = new StreamReader(tcpStream, Tools.Utf8Encoder);
                tcpWriter = new StreamWriter(tcpStream, Tools.Utf8Encoder)
                {
                    NewLine = "\n"
                };

                if (await tcpReader.ReadLineAsync() != "TS3")
                {
                    return(CommandError.Custom("Protocol violation. The stream must start with 'TS3'"));
                }
                if (string.IsNullOrEmpty(await tcpReader.ReadLineAsync()))
                {
                    await tcpReader.ReadLineAsync();
                }
            }
            catch (SocketException ex) { return(CommandError.Custom("Could not connect: " + ex.Message)); }
            finally { connecting = false; }

            cts = new CancellationTokenSource();
            dispatcher.Init(InvokeEvent, conData.LogId);
            _ = NetworkLoop(tcpStream, cts.Token);
            return(R.Ok);
        }
예제 #6
0
        public override void Connect(ConnectionData conData)
        {
            if (!TsDnsResolver.TryResolve(conData.Address, out remoteAddress, TsDnsResolver.TsQueryDefaultPort))
            {
                throw new TsException("Could not read or resolve address.");
            }

            try
            {
                connecting = true;

                tcpClient = new TcpClient(remoteAddress.AddressFamily);
                tcpClient.Connect(remoteAddress);

                ConnectionData = conData;

                tcpStream = tcpClient.GetStream();
                tcpReader = new StreamReader(tcpStream, Tools.Utf8Encoder);
                tcpWriter = new StreamWriter(tcpStream, Tools.Utf8Encoder)
                {
                    NewLine = "\n"
                };

                if (tcpReader.ReadLine() != "TS3")
                {
                    throw new TsException("Protocol violation. The stream must start with 'TS3'");
                }
                if (string.IsNullOrEmpty(tcpReader.ReadLine()))
                {
                    tcpReader.ReadLine();
                }
            }
            catch (SocketException ex) { throw new TsException("Could not connect.", ex); }
            finally { connecting = false; }

            cts = new CancellationTokenSource();
            dispatcher.Init(InvokeEvent, conData.LogId);
            NetworkLoop(cts.Token).ConfigureAwait(false);
            OnConnected?.Invoke(this, EventArgs.Empty);
        }
예제 #7
0
        /// <summary>Tries to connect to a server.</summary>
        /// <param name="conData">Set the connection information properties as needed.
        /// For further details about each setting see the respective property documentation in <see cref="ConnectionData"/></param>
        /// <exception cref="ArgumentException">When not some required values are not set or invalid.</exception>
        /// <exception cref="Ts3Exception">When the connection could not be established.</exception>
        public override void Connect(ConnectionData conData)
        {
            if (!(conData is ConnectionDataFull conDataFull))
            {
                throw new ArgumentException($"Use the {nameof(ConnectionDataFull)} deriverate to connect with the full client.", nameof(conData));
            }
            if (conDataFull.Identity == null)
            {
                throw new ArgumentNullException(nameof(conDataFull.Identity));
            }
            if (conDataFull.VersionSign == null)
            {
                throw new ArgumentNullException(nameof(conDataFull.VersionSign));
            }
            connectionDataFull = conDataFull;
            ConnectionData     = conData;

            Disconnect();

            if (!TsDnsResolver.TryResolve(conData.Address, out remoteAddress))
            {
                throw new Ts3Exception("Could not read or resolve address.");
            }

            lock (statusLock)
            {
                returnCode = 0;
                wasExit    = false;

                VersionSign       = conDataFull.VersionSign;
                ts3Crypt.Identity = conDataFull.Identity;

                packetHandler.Connect(remoteAddress);
                dispatcher.Init(NetworkLoop, InvokeEvent);
            }
            dispatcher.EnterEventLoop();
        }
예제 #8
0
        public async Task RunBots(bool interactive)
        {
            var botConfigList = confRoot.GetAllBots();

            if (botConfigList is null)
            {
                return;
            }

            if (botConfigList.Length == 0)
            {
                if (!interactive)
                {
                    Log.Warn("No bots are configured in the load list.");
                    return;
                }

                Console.WriteLine("It seems like there are no bots configured.");
                Console.WriteLine("Fill out this quick setup to get started.");

                var newBot = CreateNewBot();
                newBot.Run.Value = true;

                var address = await Interactive.LoopActionAsync("Please enter the ip, domain or nickname (with port; default: 9987) where to connect to:", async addr =>
                {
                    if (await TsDnsResolver.TryResolve(addr) != null)
                    {
                        return(true);
                    }
                    Console.WriteLine("The address seems invalid or could not be resolved, continue anyway? [y/N]");
                    return(Interactive.UserAgree(defaultTo: false));
                });

                if (address is null)
                {
                    return;
                }
                newBot.Connect.Address.Value = address;
                Console.WriteLine("Please enter the server password (or leave empty for none):");
                newBot.Connect.ServerPassword.Password.Value = Console.ReadLine();

                if (!newBot.SaveNew(ConfigHelper.DefaultBotName))
                {
                    Log.Error("Could not save new bot. Ensure that the bot has access to the directory.");
                    return;
                }

                if (!confRoot.Save())
                {
                    Log.Error("Could not save root config. The bot won't start by default.");
                }

                var runResult = await RunBot(newBot);

                if (!runResult.Ok)
                {
                    Log.Error("Could not run bot ({0})", runResult.Error);
                }
                return;
            }

            var launchBotTasks = new List <Task <R <BotInfo, string> > >(botConfigList.Length);

            foreach (var instance in botConfigList)
            {
                if (!instance.Run)
                {
                    continue;
                }
                launchBotTasks.Add(RunBot(instance).ContinueWith(async t =>
                {
                    var result = await t;
                    if (!result.Ok)
                    {
                        Log.Error("Could not instantiate bot: {0}", result.Error);
                    }
                    return(result);
                }).Unwrap());
            }
            await Task.WhenAll(launchBotTasks);
        }