/// <summary> /// Returns true if the endpoint exists /// </summary> /// <param name="endpoint"></param> /// <returns></returns> public bool TryGetEndpoint(ParticleEndpoint endpoint, out string endpointString) { return KnownEndpoints.TryGetValue(endpoint, out endpointString); }
/// <summary> /// Returns true if the endpoint exists /// </summary> /// <param name="endpoint"></param> /// <returns></returns> public bool ContainsEndpoint(ParticleEndpoint endpoint) { return KnownEndpoints.ContainsKey(endpoint); }
/// <summary> /// Continues to get more information about recipients after all information about endpoints is loaded /// </summary> /// <param name="sender"></param> /// <param name="recipientIdentities"></param> /// <param name="loadedEndpoints"></param> /// <param name="callback"></param> private void GetRecipientInfos( IUserOrGroup sender, bool forceRefresh, HashSet<string> recipientIdentities, LockFreeQueue<Endpoints> loadedEndpoints, ParticleEndpoint particleEndpoint, Action<EndpointInfo> callback, Action<IEnumerable<string>> errorCallback, Action<Exception> exceptionCallback) { try { // All of the unique particle endpoints, with the recipients at each Dictionary<string, List<string>> recipientsAtEndpoints = new Dictionary<string, List<string>>(); Dictionary<string, string> establishTrustEndpoints = new Dictionary<string, string>(); Dictionary<string, string> requestedEndpoints = new Dictionary<string, string>(); Endpoints particleEndpoints; while (loadedEndpoints.Dequeue(out particleEndpoints)) { string endpoint; if (particleEndpoints.TryGetEndpoint(particleEndpoint, out endpoint)) { List<string> users; if (recipientsAtEndpoints.TryGetValue(particleEndpoints[ParticleEndpoint.ReceiveNotification], out users)) users.Add(particleEndpoints.OpenIdOrWebFinger); else { users = new List<string>(); users.Add(particleEndpoints.OpenIdOrWebFinger); recipientsAtEndpoints[particleEndpoints[ParticleEndpoint.ReceiveNotification]] = users; establishTrustEndpoints[particleEndpoints[ParticleEndpoint.ReceiveNotification]] = particleEndpoints[ParticleEndpoint.EstablishTrust]; requestedEndpoints[particleEndpoints[ParticleEndpoint.ReceiveNotification]] = particleEndpoints[particleEndpoint]; } } } if (!forceRefresh) { // Load for situations where trust is already established // copy is to avoid locked the database this.persistedUserManagerData.Read(userManagerData => { var recipientUser = userManagerData.GetUser(sender.Id); foreach (var recipientAndToken in recipientUser.receiveNotificationEndpointsBySenderToken.Where( r => recipientsAtEndpoints.ContainsKey(r.Value))) { var receiveNotificationEndpoint = recipientAndToken.Value; var senderToken = recipientAndToken.Key; string endpoint; if (requestedEndpoints.TryGetValue(receiveNotificationEndpoint, out endpoint)) { var recipientInfo = new EndpointInfo() { RecipientIdentities = recipientsAtEndpoints[receiveNotificationEndpoint], Endpoint = endpoint, SenderToken = senderToken }; recipientsAtEndpoints.Remove(receiveNotificationEndpoint); callback(recipientInfo); } } }); } // For situations where trust isn't established, establish trust and then use the callback foreach (KeyValuePair<string, List<string>> endpointAndRecipients in recipientsAtEndpoints) GetRecipientInfos( sender, endpointAndRecipients.Key, establishTrustEndpoints[endpointAndRecipients.Key], endpointAndRecipients.Value, requestedEndpoints[endpointAndRecipients.Key], callback, errorCallback); } catch (Exception e) { exceptionCallback(e); } }
/// <summary> /// Returns the url for the endpoint, or null if it doesn't exist /// </summary> /// <param name="endpoint"></param> /// <returns></returns> public string this[ParticleEndpoint endpoint] { get { string toReturn; if (KnownEndpoints.TryGetValue(endpoint, out toReturn)) return toReturn; else throw new UnknownEndpoint(endpoint + " isn't a valid endpoint"); } }
// TODO // A lot of the logic in this file that's not tied to the DB should move someplace else so that independent implementations can use it /// <summary> /// Gets information about recipients for sending a notification /// </summary> /// <param name="openIdOrWebFinger"></param> /// <param name="forceRefresh"></param> /// <returns></returns> public void GetEndpointInfos( IUserOrGroup sender, bool forceRefresh, IEnumerable<string> recipientIdentitiesArg, ParticleEndpoint particleEndpoint, Action<EndpointInfo> callback, Action<IEnumerable<string>> errorCallback, Action<Exception> exceptionCallback) { HashSet<string> recipientIdentities = new HashSet<string>(recipientIdentitiesArg); long outstandingRequests = recipientIdentities.Count; LockFreeQueue<Endpoints> loadedEndpoints = new LockFreeQueue<Endpoints>(); Action<Endpoints> endpointLoaded = delegate(Endpoints endpoints) { loadedEndpoints.Enqueue(endpoints); if (0 == Interlocked.Decrement(ref outstandingRequests)) GetRecipientInfos(sender, forceRefresh, recipientIdentities, loadedEndpoints, particleEndpoint, callback, errorCallback, exceptionCallback); }; Action<Exception> endpointException = delegate(Exception e) { if (0 == Interlocked.Decrement(ref outstandingRequests)) GetRecipientInfos(sender, forceRefresh, recipientIdentities, loadedEndpoints, particleEndpoint, callback, errorCallback, exceptionCallback); }; foreach (string openIdOrWebFinger in recipientIdentities) Endpoints.GetEndpoints(openIdOrWebFinger, forceRefresh, endpointLoaded, endpointException); }