summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2013-02-09 15:31:56 -0800
committerAndrew Arnott <andrewarnott@gmail.com>2013-02-09 15:31:56 -0800
commit794a08cc9a84f4a1b6ec233e7733704de1fc04cb (patch)
tree91a9dcb2c3aa90560330f860b23e733c46cdfa29
parent2e177b1c58ccd1c8edc2cc78e0c629784173a95c (diff)
downloadDotNetOpenAuth-794a08cc9a84f4a1b6ec233e7733704de1fc04cb.zip
DotNetOpenAuth-794a08cc9a84f4a1b6ec233e7733704de1fc04cb.tar.gz
DotNetOpenAuth-794a08cc9a84f4a1b6ec233e7733704de1fc04cb.tar.bz2
Assocations with providers when OpenID discovery yields multiple endpoints can now happen in parallel.
-rw-r--r--src/DotNetOpenAuth.Core/Util.cs18
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs22
2 files changed, 29 insertions, 11 deletions
diff --git a/src/DotNetOpenAuth.Core/Util.cs b/src/DotNetOpenAuth.Core/Util.cs
index d4204a0..a23b4d8 100644
--- a/src/DotNetOpenAuth.Core/Util.cs
+++ b/src/DotNetOpenAuth.Core/Util.cs
@@ -7,10 +7,12 @@ namespace DotNetOpenAuth {
using System;
using System.Collections.Generic;
using System.Globalization;
+ using System.Linq;
using System.Net;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text;
+ using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using DotNetOpenAuth.Configuration;
@@ -226,6 +228,22 @@ namespace DotNetOpenAuth {
}
/// <summary>
+ /// Creates a dictionary of a sequence of elements and the result of an asynchronous transform,
+ /// allowing the async work to proceed concurrently.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source.</typeparam>
+ /// <typeparam name="TResult">The type of the result.</typeparam>
+ /// <param name="source">The source.</param>
+ /// <param name="transform">The transform.</param>
+ /// <returns></returns>
+ internal static async Task<Dictionary<TSource, TResult>> ToDictionaryAsync<TSource, TResult>(
+ this IEnumerable<TSource> source, Func<TSource, Task<TResult>> transform) {
+ var taskResults = source.ToDictionary(s => s, transform);
+ await Task.WhenAll(taskResults.Values);
+ return taskResults.ToDictionary(p => p.Key, p => p.Value.Result);
+ }
+
+ /// <summary>
/// Manages an individual deferred ToString call.
/// </summary>
/// <typeparam name="T">The type of object to be serialized as a string.</typeparam>
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs
index f9abc37..0fb5b4a 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -424,14 +424,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Logger.Yadis.InfoFormat("Performing discovery on user-supplied identifier: {0}", userSuppliedIdentifier);
IEnumerable<IdentifierDiscoveryResult> endpoints = FilterAndSortEndpoints(serviceEndpoints, relyingParty);
- var results = new List<AuthenticationRequest>();
- // Maintain a list of endpoints that we could not form an association with.
- // We'll fallback to generating requests to these if the ones we CAN create
- // an association with run out.
- var failedAssociationEndpoints = new List<IdentifierDiscoveryResult>(0);
-
- foreach (var endpoint in endpoints) {
+ var authRequestResults = await endpoints.ToDictionaryAsync(async endpoint => {
Logger.OpenId.DebugFormat("Creating authentication request for user supplied Identifier: {0}", userSuppliedIdentifier);
// The strategy here is to prefer endpoints with whom we can create associations.
@@ -446,13 +440,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// No association could be created. Add it to the list of failed association
// endpoints and skip to the next available endpoint.
- failedAssociationEndpoints.Add(endpoint);
- continue;
+ return null;
}
}
- results.Add(new AuthenticationRequest(endpoint, realm, returnToUrl, relyingParty));
- }
+ return new AuthenticationRequest(endpoint, realm, returnToUrl, relyingParty);
+ });
+
+ var results = (from pair in authRequestResults where pair.Value != null select pair.Value).ToList();
+
+ // Maintain a list of endpoints that we could not form an association with.
+ // We'll fallback to generating requests to these if the ones we CAN create
+ // an association with run out.
+ var failedAssociationEndpoints = (from pair in authRequestResults where pair.Value == null select pair.Key).ToList();
// Now that we've run out of endpoints that respond to association requests,
// since we apparently are still running, the caller must want another request.