Пример #1
0
        private bool HandleHandshake(TcpClient client, out NetworkStream stream, out Guid nodeId)
        {
            var clientEndpoint = (IPEndPoint)client.Client.RemoteEndPoint;

            _log.Info("Got connection from {0}:{1}", clientEndpoint.Address, clientEndpoint.Port);

            stream = client.GetStream();

            var idBytes = new byte[16]; // GUID is 16 bytes

            stream.Read(idBytes, 0, 16);

            nodeId = new Guid(idBytes);

            _log.Info("Node identified as: {0}", nodeId.ToString());

            bool knownGuid = NodesPublicKeys.ContainsKey(nodeId);

            if (!knownGuid && !AllowUnknownGuid)
            {
                _log.Warn("Node GUID not recognized, closing connection.");
                stream.WriteSbyte((sbyte)HandshakeResult.UNKNOWN_GUID_NOT_ALLOWED);
                stream.Close();
                return(false);
            }
            else
            {
                if (knownGuid)
                {
                    stream.WriteSbyte((sbyte)HandshakeResult.ACCEPTED);
                }
                else
                {
                    stream.WriteSbyte((sbyte)HandshakeResult.UNKNOWN_GUID_ACCEPTED);
                }



                return(true);
            }
        }
Пример #2
0
        private void HandleAsyncSendConnection(IAsyncResult result)
        {
            TcpListener   listener = (TcpListener)result.AsyncState;
            TcpClient     client   = listener.EndAcceptTcpClient(result);
            NetworkStream stream;
            Guid          nodeId;

            sendConnectionWaitHandle.Set(); //Inform the main thread this connection is now handled

            if (HandleHandshake(client, out stream, out nodeId))
            {
                var nodeConnection = new NodeConnection()
                {
                    Client       = client,
                    Thread       = Thread.CurrentThread,
                    CommandQueue = new ConcurrentQueue <QueuedCommand>()
                };
                nodeConnections.AddOrUpdate(nodeId, nodeConnection, (g, sc) =>
                {
                    nodeConnection.CommandQueue = sc.CommandQueue; // Preserve the queue if it already exists
                    return(nodeConnection);
                });

                while (!aborted && client.Connected)
                {
                    var commandQueue = nodeConnection.CommandQueue;
                    if (commandQueue.Count > 0) // Sending mode
                    {
                        if (!NodesPublicKeys.ContainsKey(nodeId))
                        {
                            _log.Info(String.Format("Cannot process queue. No public key for server {0}.", nodeId));
                            Thread.Sleep(1000);
                        }
                        else
                        {
                            _log.Debug("Processing command from queue...");
                            QueuedCommand serverCommand;

                            if (commandQueue.TryDequeue(out serverCommand))
                            {
                                try
                                {
                                    handleRemoteCommand(stream, serverCommand);
                                }
                                catch (AggregateException ax)
                                {
                                    ax.Handle((x) =>
                                    {
                                        if (x is System.Security.Cryptography.CryptographicException)
                                        {
                                            _log.Warn(x, $"Cryptographic communication error with node. Check encryption keys.  Details: {x.Message}");
                                        }
                                        else
                                        {
                                            var ix = x.InnerException;
                                            _log.Warn(x, $"Communication error with node. Requeueing command. Details: {x.Message}{(ix != null ? "; " + ix.Message : "")}");
                                            commandQueue.Enqueue(serverCommand);
                                        }
                                        return(true);
                                    });
                                }
                                stream.Close();
                            }
                            else
                            {
                                _log.Warn("Could not dequeue command!");
                            }
                        }
                    }
                    else
                    {
                        Thread.Sleep(1000);
                    }
                }
            }
        }