Ejemplo n.º 1
0
        /// <summary>
        ///     Handles incoming messages.
        /// </summary>
        /// <param name="sender">The <see cref="IMessageConnection"/> instance from which the message originated.</param>
        /// <param name="message">The message.</param>
        public async void HandleMessageRead(object sender, byte[] message)
        {
            var connection = (IMessageConnection)sender;
            var code       = new MessageReader <MessageCode.Distributed>(message).ReadCode();

            if (code != MessageCode.Distributed.SearchRequest && code != MessageCode.Distributed.ServerSearchRequest)
            {
                Diagnostic.Debug($"Distributed message received: {code} from {connection.Username} ({connection.IPEndPoint}) (id: {connection.Id})");
            }

            try
            {
                switch (code)
                {
                // if we are connected to a branch root, we get search requests with code DistributedServerSearchRequest.  convert this
                // message to a normal DistributedSearchRequest before forwarding. not sure if this is correct, but it would match the
                // observed behavior.  these messages may also be forwarded from the server message handler if we haven't connected to
                // a distributed parent in a timely manner.
                case MessageCode.Distributed.ServerSearchRequest:
                    var serverSearchRequest = DistributedServerSearchRequest.FromByteArray(message);

                    var forwardedMessage = new DistributedSearchRequest(serverSearchRequest.Username, serverSearchRequest.Token, serverSearchRequest.Query);
                    SoulseekClient.DistributedConnectionManager.BroadcastMessageAsync(forwardedMessage.ToByteArray()).Forget();

                    await TrySendSearchResults(serverSearchRequest.Username, serverSearchRequest.Token, serverSearchRequest.Query).ConfigureAwait(false);

                    break;

                // if we are connected to anyone other than a branch root, we should get search requests with code SearchRequest.
                // forward these requests as is.
                case MessageCode.Distributed.SearchRequest:
                    var searchRequest = DistributedSearchRequest.FromByteArray(message);

                    SoulseekClient.DistributedConnectionManager.BroadcastMessageAsync(message).Forget();

                    await TrySendSearchResults(searchRequest.Username, searchRequest.Token, searchRequest.Query).ConfigureAwait(false);

                    break;

                case MessageCode.Distributed.Ping:
                    Diagnostic.Debug($"PING?");
                    var pingResponse = new DistributedPingResponse(SoulseekClient.GetNextToken());
                    await connection.WriteAsync(pingResponse.ToByteArray()).ConfigureAwait(false);

                    Diagnostic.Debug($"PONG!");
                    break;

                case MessageCode.Distributed.BranchLevel:
                    var branchLevel = DistributedBranchLevel.FromByteArray(message);

                    if ((connection.Username, connection.IPEndPoint) == SoulseekClient.DistributedConnectionManager.Parent)
                    {
                        SoulseekClient.DistributedConnectionManager.SetBranchLevel(branchLevel.Level);
                    }

                    break;

                case MessageCode.Distributed.BranchRoot:
                    var branchRoot = DistributedBranchRoot.FromByteArray(message);

                    if ((connection.Username, connection.IPEndPoint) == SoulseekClient.DistributedConnectionManager.Parent)
                    {
                        SoulseekClient.DistributedConnectionManager.SetBranchRoot(branchRoot.Username);
                    }

                    break;

                case MessageCode.Distributed.ChildDepth:
                    var childDepth = DistributedChildDepth.FromByteArray(message);
                    SoulseekClient.Waiter.Complete(new WaitKey(Constants.WaitKey.ChildDepthMessage, connection.Key), childDepth.Depth);
                    break;

                default:
                    Diagnostic.Debug($"Unhandled distributed message: {code} from {connection.Username} ({connection.IPEndPoint}); {message.Length} bytes");
                    break;
                }
            }
            catch (Exception ex)
            {
                Diagnostic.Warning($"Error handling distributed message: {code} from {connection.Username} ({connection.IPEndPoint}); {ex.Message}", ex);
            }
        }