Пример #1
0
        private async Task OpenSocketAsync()
        {
            _wtoken = new CancellationTokenSource();
            if (string.IsNullOrEmpty(Hostname))
            {
                throw new ArgumentNullException(nameof(Hostname));
            }
            if (Port <= 0 || Port > 65535)
            {
                throw new ArgumentOutOfRangeException(nameof(Port));
            }

            if (!string.IsNullOrEmpty(Proxy?.ProxyHostname))
            {
                var proxy = new SocksTcpClient(Proxy);
                _tcpClient = await proxy.ConnectAsync(Hostname, Port);
            }
            else
            {
                _tcpClient = new TcpClient();
            }

            try
            {
                // try connecting
                State = IrcConnectionState.Connecting;
                var connectTask        = _tcpClient.ConnectAsync(Hostname, Port);
                var connectTimeoutTask =
                    Task.Run(async() => await Task.Delay(5000, _wtoken.Token).ConfigureAwait(false));
                var firstCompletedTask = await Task.WhenAny(connectTask, connectTimeoutTask).ConfigureAwait(false);

                if (firstCompletedTask == connectTimeoutTask)
                {
                    State = IrcConnectionState.Disconnected;
                }
                else
                {
                    await connectTask; // we await the finished task so we can throw the exception
                    await SocketEntryAsync(_wtoken.Token).ConfigureAwait(false);
                    await Socket_OnConnected();
                }
            }
            catch (SocketException e)
            {
                OnConnectionError(new ErrorEventArgs(e));
            }
            catch (SocksException e)
            {
                OnConnectionError(new ErrorEventArgs(e));
            }
            catch (IOException e)
            {
                OnConnectionError(new ErrorEventArgs(e));
            }
        }
Пример #2
0
        private async Task SocketLoopAsync(CancellationToken token)
        {
            if (!string.IsNullOrEmpty(_proxy?.ProxyHostname))
            {
                var proxy = new SocksTcpClient(_proxy);
                _tcpClient = await proxy.ConnectAsync(_server, _port, token);
            }
            else
            {
                _tcpClient = new TcpClient();
                using (token.Register(() => _tcpClient.Dispose()))
                {
                    await _tcpClient.ConnectAsync(_server, _port);
                }
                token.ThrowIfCancellationRequested();
            }

            Stream stream = _tcpClient.GetStream();

            if (_isSecure)
            {
                // Just accept all server certs for now; we'll take advantage of the encryption
                // but not the authentication unless users ask for it.
                var sslStream = new SslStream(stream, true, (sender, cert, chain, sslPolicyErrors) => true);
                await sslStream.AuthenticateAsClientAsync(_server);

                stream = sslStream;
            }

            Dispatch(OnConnected);

            async Task ReadLoopAsync()
            {
                byte[] readBuffer = new byte[512];
                var    gotCR      = false;
                var    input      = new List <byte>(512);

                while (_tcpClient.Connected)
                {
                    var count = await stream.ReadAsync(readBuffer, 0, readBuffer.Length, token);

                    if (count == 0)
                    {
                        _tcpClient.Dispose();
                    }
                    else
                    {
                        for (var i = 0; i < count; i++)
                        {
                            switch (readBuffer[i])
                            {
                            case 0xa:
                                if (gotCR)
                                {
                                    var incoming = IrcMessage.Parse(Encoding.UTF8.GetString(input.ToArray()));
                                    Dispatch(OnMessageReceived, incoming);
                                    input.Clear();
                                }
                                break;

                            case 0xd:
                                break;

                            default:
                                input.Add(readBuffer[i]);
                                break;
                            }
                            gotCR = readBuffer[i] == 0xd;
                        }
                    }
                }
            };

            Task WriteLoopAsync()
            {
                return(Task.Run(async() =>
                {
                    byte[] writeBuffer = new byte[Encoding.UTF8.GetMaxByteCount(512)];

                    while (_tcpClient.Connected)
                    {
                        var outgoing = _writeQueue.Take(token);
                        var output = outgoing.ToString();
                        int count = Encoding.UTF8.GetBytes(output, 0, output.Length, writeBuffer, 0);
                        count = Math.Min(510, count);
                        writeBuffer[count] = 0xd;
                        writeBuffer[count + 1] = 0xa;
                        await stream.WriteAsync(writeBuffer, 0, count + 2);
                        Dispatch(OnMessageSent, outgoing);
                    }
                }, token));
            };

            async Task HeartbeatLoopAsync()
            {
                while (_tcpClient.Connected)
                {
                    await Task.Delay(HeartbeatInterval, token);

                    Dispatch(OnHeartbeat);
                }
            };

            try
            {
                await Task.WhenAll(ReadLoopAsync(), WriteLoopAsync(), HeartbeatLoopAsync());
            }
            finally
            {
                Dispatch(OnDisconnected);
            }
        }