Exemplo n.º 1
0
        public async Task <CQConnection> ConnectTo(string hostport)
        {
            var parts      = hostport.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
            var hostName   = parts[0];
            var portNumber = parts.Length > 1 ? int.Parse(parts[1]) : 18593;

            var connection = await CQConnection.Create(_crypt, hostName, portNumber, _rsa, _onStatusChange);

            ValidateWhitelistAndSetAlias(connection);

            lock (_connections)
            {
                // NOTE: prior connections to same peer are not removed, by design
                _connections.Add(connection);
            }
            try
            {
                NewConnection?.Invoke(this, new CQConnectionEventArgs
                {
                    Connection = connection
                });
            }
            catch (Exception ex)
            {
                ex.Log();
            }
            $"Connected to [{connection}]".Log();

            return(connection);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Used to create a CQConnection not-yet-connected to a remote.
        /// </summary>
        /// <returns>
        /// The returned <see cref="CQConnection"/> is valid for all uses.
        /// </returns>
        public static async Task <CQConnection> Create(
            Crypt crypt,
            string hostName,
            int portNumber,
            RSA rsa,
            Action <string> onStatusChange)
        {
            var connection = new CQConnection(crypt, hostName, portNumber, onStatusChange);

            $"Establishing connection to [{hostName}:{portNumber}]..".Log();
            var tcpClient = new TcpClient();

            tcpClient.NoDelay           = true;
            tcpClient.ReceiveBufferSize = 16;
            await tcpClient.ConnectAsync(hostName, portNumber);

            connection._tcpClient = tcpClient;

            $"Initiating conversation with [{hostName}:{portNumber}]..".Log();
            await connection.InitiateConversation(rsa);

            // NOTE: the returned connection is valid for all uses. ha
            //       thumbprint, alias, and is actively sending/receiving data..
            return(connection);
        }
Exemplo n.º 3
0
        private void ValidateWhitelistAndSetAlias(CQConnection connection)
        {
            $"Checking whitelist for {connection}".Log();
            // check thumbprint against whitelist, if not in whitelist then
            // force a disconnect
            if (_whitelist.TryGetAlias(connection.Peer.Thumbprint, out string alias))
            {
                connection.Peer.Alias = alias;
                _onStatusChange($"{connection} whitelisted as '{connection.Peer.Alias}' ({connection.Peer.Thumbprint})".Log());
            }
            else
            {
                connection.Peer.Alias = connection.Peer.Thumbprint;
                var err = $@"Rejecting {connection.Peer.Thumbprint} -- not authorized.
Use `/WHITELIST <thumbprint>` and `/BAN <thumbprint>` to authorized/deauthorize.".Log();
                _onStatusChange(err);
                throw new Exception(err);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Used to create a CQConnection for a TcpClient accepted by a listener.
        /// </summary>
        /// <param name="tcpClient"></param>
        /// <returns></returns>
        public static async Task <CQConnection> Create(
            Crypt crypt,
            TcpClient tcpClient,
            RSA rsa,
            Action <string> onStatusChange)
        {
            var ipEndPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint;
            var hostName   = ipEndPoint.Address.ToString(); // TODO: reverse dns?
            var portNumber = ipEndPoint.Port;
            var connection = new CQConnection(crypt, hostName, portNumber, onStatusChange);

            connection._tcpClient = tcpClient;

            $"Accepting conversation with [{hostName}:{portNumber}]..".Log();
            await connection.AcceptConversation(rsa);

            // NOTE: the returned connection is valid for all uses. ha
            //       thumbprint, alias, and is actively sending/receiving data..
            return(connection);
        }
Exemplo n.º 5
0
        public async Task OnConnectionAccepted(TcpClient tcpClient)
        {
            var connection = await CQConnection.Create(
                _crypt,
                tcpClient,
                _rsa,
                _onStatusChange);

            connection.ConversationEnded += (s, e) =>
            {
                lock (_connections)
                {
                    if (_connections.Remove(connection))
                    {
                        $"Removed {connection}".Log();
                    }
                }
            };

            ValidateWhitelistAndSetAlias(connection);

            $"Accepted [{connection}]".Log();
            lock (_connections)
            {
                _connections.Add(connection);
                try
                {
                    NewConnection?.Invoke(this, new CQConnectionEventArgs
                    {
                        Connection = connection
                    });
                }
                catch (Exception ex)
                {
                    ex.Log();
                }
            }
        }