예제 #1
0
        /// <summary>
        ///     Sends the pending response matching the specified <paramref name="responseToken"/>, if one exists.
        /// </summary>
        /// <remarks>
        ///     This overload is called by the listener when an incoming connection is established with a pierce firewall token,
        ///     and if that token doesn't match a pending solicitation, and if the token matches a cached search response.  In this case,
        ///     the connection is retrieved from the cache and used to send the response.
        /// </remarks>
        /// <param name="responseToken">The token matching the pending response to send.</param>
        /// <returns>The operation context, including a value indicating whether a response was successfully sent.</returns>
        public async Task <bool> TryRespondAsync(int responseToken)
        {
            if (SoulseekClient.Options.SearchResponseCache != default)
            {
                bool cached;
                (string Username, int Token, string Query, SearchResponse SearchResponse)record;

                try
                {
                    cached = SoulseekClient.Options.SearchResponseCache.TryRemove(responseToken, out record);
                }
                catch (Exception ex)
                {
                    Diagnostic.Warning($"Error retrieving cached search response {responseToken}: {ex.Message}", ex);
                    return(false);
                }

                if (cached)
                {
                    var(username, token, query, searchResponse) = record;

                    try
                    {
                        var peerConnection = await SoulseekClient.PeerConnectionManager.GetCachedMessageConnectionAsync(username).ConfigureAwait(false);

                        await peerConnection.WriteAsync(searchResponse.ToByteArray()).ConfigureAwait(false);

                        Diagnostic.Debug($"Sent cached response {responseToken} containing {searchResponse.FileCount + searchResponse.LockedFileCount} files to {username} for query '{query}' with token {token}");
                        ResponseDelivered?.Invoke(this, new SearchRequestResponseEventArgs(username, token, query, searchResponse));
                        return(true);
                    }
                    catch (Exception ex)
                    {
                        Diagnostic.Debug($"Failed to send cached search response {responseToken} to {username} for query '{query}' with token {token}: {ex.Message}", ex);
                        ResponseDeliveryFailed?.Invoke(this, new SearchRequestResponseEventArgs(username, token, query, searchResponse));
                    }
                }
            }

            return(false);
        }
예제 #2
0
        /// <summary>
        ///     Discards the cached response matching the specified <paramref name="responseToken"/>, if one exists.
        /// </summary>
        /// <param name="responseToken">The token matching the cached response to discard.</param>
        /// <returns>A value indicating whether the cached response was discarded.</returns>
        public bool TryDiscard(int responseToken)
        {
            if (SoulseekClient.Options.SearchResponseCache != default)
            {
                try
                {
                    if (SoulseekClient.Options.SearchResponseCache.TryRemove(responseToken, out var response))
                    {
                        var(username, token, query, searchResponse) = response;

                        Diagnostic.Debug($"Discarded cached search response {responseToken} to {username} for query '{query}' with token {token}");
                        ResponseDeliveryFailed?.Invoke(this, new SearchRequestResponseEventArgs(username, token, query, searchResponse));
                        return(true);
                    }
                }
                catch (Exception ex)
                {
                    Diagnostic.Warning($"Error removing cached search response {responseToken}: {ex.Message}", ex);
                    return(false);
                }
            }

            return(false);
        }