Ejemplo n.º 1
0
        /// <summary>
        ///     Read line callback
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnReadLine(object sender, ReadLineEventArgs e)
        {
            try
            {
                var command = e.Line.Split(' ')[1];

                if (command.Equals("PING"))
                {
                    var server = e.Line.Split(' ')[2];

                    _irc.WriteLine("PONG " + server, Priority.Critical);
                }
                else if (command.Equals("422") || command.Equals("376")) // 422: motd missing // 376: end of motd
                {
                    _irc.RfcJoin(_ircChannel);
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
        }
Ejemplo n.º 2
0
        /// <inheritdoc />
        public override Task <bool> Connect(CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
        {
            disconnecting = false;
            lock (this)
                try
                {
                    client.Connect(address, port);

                    cancellationToken.ThrowIfCancellationRequested();

                    if (passwordType == IrcPasswordType.Server)
                    {
                        client.Login(nickname, nickname, 0, nickname, password);
                    }
                    else
                    {
                        if (passwordType == IrcPasswordType.Sasl)
                        {
                            client.WriteLine("CAP REQ :sasl", Priority.Critical);                             // needs to be put in the buffer before anything else
                            cancellationToken.ThrowIfCancellationRequested();
                        }

                        client.Login(nickname, nickname, 0, nickname);
                    }

                    if (passwordType == IrcPasswordType.NickServ)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        client.SendMessage(SendType.Message, "NickServ", String.Format(CultureInfo.InvariantCulture, "IDENTIFY {0}", password));
                    }
                    else if (passwordType == IrcPasswordType.Sasl)
                    {
                        // wait for the sasl ack or timeout
                        var recievedAck    = false;
                        var recievedPlus   = false;
                        client.OnReadLine += (sender, e) =>
                        {
                            if (e.Line.Contains("ACK :sasl", StringComparison.Ordinal))
                            {
                                recievedAck = true;
                            }
                            else if (e.Line.Contains("AUTHENTICATE +", StringComparison.Ordinal))
                            {
                                recievedPlus = true;
                            }
                        };

                        var startTime = DateTimeOffset.Now;
                        var endTime   = DateTimeOffset.Now.AddSeconds(TimeoutSeconds);
                        cancellationToken.ThrowIfCancellationRequested();

                        var listenTimeSpan = TimeSpan.FromMilliseconds(10);
                        for (; !recievedAck && DateTimeOffset.Now <= endTime; asyncDelayer.Delay(listenTimeSpan, cancellationToken).GetAwaiter().GetResult())
                        {
                            client.Listen(false);
                        }

                        client.WriteLine("AUTHENTICATE PLAIN", Priority.Critical);
                        cancellationToken.ThrowIfCancellationRequested();

                        for (; !recievedPlus && DateTimeOffset.Now <= endTime; asyncDelayer.Delay(listenTimeSpan, cancellationToken).GetAwaiter().GetResult())
                        {
                            client.Listen(false);
                        }

                        // Stolen! https://github.com/znc/znc/blob/1e697580155d5a38f8b5a377f3b1d94aaa979539/modules/sasl.cpp#L196
                        var authString = String.Format(CultureInfo.InvariantCulture, "{0}{1}{0}{1}{2}", nickname, '\0', password);
                        var b64        = Convert.ToBase64String(Encoding.UTF8.GetBytes(authString));
                        var authLine   = String.Format(CultureInfo.InvariantCulture, "AUTHENTICATE {0}", b64);
                        var chars      = authLine.ToCharArray();
                        client.WriteLine(authLine, Priority.Critical);

                        cancellationToken.ThrowIfCancellationRequested();
                        client.WriteLine("CAP END", Priority.Critical);
                    }

                    client.Listen(false);

                    listenTask = Task.Factory.StartNew(() =>
                    {
                        while (!disconnecting && client.IsConnected && client.Nickname != nickname)
                        {
                            client.ListenOnce(true);
                            if (disconnecting || !client.IsConnected)
                            {
                                break;
                            }
                            client.Listen(false);

                            // ensure we have the correct nick
                            if (client.GetIrcUser(nickname) == null)
                            {
                                client.RfcNick(nickname);
                            }
                        }

                        client.Listen();
                    }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
            catch (Exception e)
            {
                Logger.LogWarning("Unable to connect to IRC: {0}", e);
                return(false);
            }

            return(true);
        }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);