/// <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); }
/// <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); }