Пример #1
0
        private void HandleMessage(GcMessage message)
        {
            MessageHandler handler;

            _messageHandlers.TryGetValue(message.OpCode, out handler);

            if (handler == null && message.RequiresResponse)
            {
                // No handler, but message requires a response
                message.Respond(ResponseStatus.NotHandled, "Not handled");
                return;
            }

            // No handler, but don't need to respond
            if (handler == null)
            {
                return;
            }

            Task.Run(async() =>
            {
                try
                {
                    await handler.Invoke(message);
                }
                catch (Exception e)
                {
                    _logger.LogError("Exception while handling a request", e);

                    try
                    {
                        if (message.RequiresResponse)
                        {
                            message.Respond(ResponseStatus.Error, "Internal error");
                        }
                    }
                    catch (Exception responseException)
                    {
                        _logger.LogError("Exception while trying to respond after " +
                                         "catching an exception", responseException);
                    }
                }
            });
        }
Пример #2
0
        private async Task HandleEstablishPeer(GcMessage message)
        {
            var    peerId          = message.Reader.ReadInt32();
            var    isDirectMessage = peerId < 0;
            GcPeer peer            = null;

            if (isDirectMessage)
            {
                // This is a direct message from client
                // who can't know his peer id
                peerId = message.Peer.PeerId;
                peer   = message.Peer;
            }
            else
            {
                // This is a message that was already relayed at least once
                // We need to create a virtual peer which will be used in this server
                var vPeer = new GcPeer(Interlocked.Increment(ref _peerIdGenerator), message.Peer);

                _peers.TryAdd(vPeer.PeerId, vPeer);
                PeerJoined?.Invoke(vPeer);

                // Add the newly created peer id
                peerId = vPeer.PeerId;
                peer   = vPeer;
            }

            // Send messages to all of the relayed servers to establish a peer in them
            var connections = _relayConnections.Values.Distinct().Where(c => c.IsConnected);

            var allSuccessful = true;

            // Do it "linearly" (one by one) because it's a lot easier to handle
            foreach (var connection in connections)
            {
                var response =
                    await connection.SendRequest((short)InternalOpCodes.EstablishPeer, w => w.Write(peerId));

                if (response.Status != ResponseStatus.Success)
                {
                    _logger.LogWarning("Failed to establish a peer in connection: " + connection);
                    allSuccessful = false;
                    continue;
                }

                var assignedPeerId = response.Reader.ReadInt32();

                // For forwarding messages
                peer.SetPeerIdInRelayedServer(assignedPeerId, connection);

                // For "backwarding" messages
                connection.SaveRelayedPeer(assignedPeerId, peer);
            }

            if (isDirectMessage)
            {
                message.Respond(allSuccessful ? ResponseStatus.Success : ResponseStatus.Failed);
            }
            else
            {
                message.Respond(ResponseStatus.Success, w => w.Write(peerId));
            }
        }