| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.PeerResolvers
- {
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Diagnostics;
- using System.Net;
- using System.Runtime;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Description;
- using System.Threading;
- class PeerDefaultCustomResolverClient : PeerResolver
- {
- EndpointAddress address;
- Binding binding;
- TimeSpan defaultLifeTime;
- ClientCredentials credentials;
- Guid clientId;
- Guid registrationId;
- IOThreadTimer timer;
- bool opened = false;
- string meshId;
- PeerNodeAddress nodeAddress;
- ChannelFactory<IPeerResolverClient> channelFactory;
- PeerReferralPolicy referralPolicy;
- string bindingName, bindingConfigurationName;
- bool? shareReferrals;
- int updateSuccessful = 1;
- internal PeerDefaultCustomResolverClient()
- {
- this.address = null;
- this.binding = null;
- this.defaultLifeTime = TimeSpan.FromHours(1);
- clientId = Guid.NewGuid();
- timer = new IOThreadTimer(new Action<object>(RegistrationExpired), this, false);
- }
- public override bool CanShareReferrals
- {
- get
- {
- if (this.shareReferrals.HasValue)
- return shareReferrals.Value;
- if (this.referralPolicy == PeerReferralPolicy.Service && opened)
- {
- IPeerResolverClient proxy = GetProxy();
- try
- {
- ServiceSettingsResponseInfo settings = proxy.GetServiceSettings();
- shareReferrals = !settings.ControlMeshShape;
- proxy.Close();
- }
- finally
- {
- proxy.Abort();
- }
- }
- else
- {
- shareReferrals = (PeerReferralPolicy.Share == this.referralPolicy);
- }
- return shareReferrals.Value;
- }
- }
- public override void Initialize(EndpointAddress address, Binding binding, ClientCredentials credentials, PeerReferralPolicy referralPolicy)
- {
- this.address = address;
- this.binding = binding;
- this.credentials = credentials;
- Validate();
- channelFactory = new ChannelFactory<IPeerResolverClient>(binding, address);
- channelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
- if (credentials != null)
- channelFactory.Endpoint.Behaviors.Add(credentials);
- channelFactory.Open();
- this.referralPolicy = referralPolicy;
- opened = true;
- }
- IPeerResolverClient GetProxy()
- {
- return (IPeerResolverClient)channelFactory.CreateChannel();
- }
- void Validate()
- {
- if (address == null || binding == null)
- PeerExceptionHelper.ThrowArgument_InsufficientResolverSettings();
- }
- // Register address for a node participating in a mesh identified by meshId with the resolver service
- public override object Register(string meshId, PeerNodeAddress nodeAddress, TimeSpan timeout)
- {
- if (opened)
- {
- long scopeId = -1;
- bool multipleScopes = false;
- if (nodeAddress.IPAddresses.Count == 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MustRegisterMoreThanZeroAddresses)));
- }
- foreach (IPAddress address in nodeAddress.IPAddresses)
- {
- if (address.IsIPv6LinkLocal)
- {
- if (scopeId == -1)
- {
- scopeId = address.ScopeId;
- }
- else if (scopeId != address.ScopeId)
- {
- multipleScopes = true;
- break;
- }
- }
- }
- List<IPAddress> addresslist = new List<IPAddress>();
- foreach (IPAddress address in nodeAddress.IPAddresses)
- {
- if (!multipleScopes || (!address.IsIPv6LinkLocal && !address.IsIPv6SiteLocal))
- addresslist.Add(address);
- }
- if (addresslist.Count == 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.AmbiguousConnectivitySpec)));
- }
- ReadOnlyCollection<IPAddress> addresses = new ReadOnlyCollection<IPAddress>(addresslist);
- this.meshId = meshId;
- this.nodeAddress = new PeerNodeAddress(nodeAddress.EndpointAddress, addresses);
- RegisterInfo info = new RegisterInfo(clientId, meshId, this.nodeAddress);
- IPeerResolverClient proxy = GetProxy();
- try
- {
- proxy.OperationTimeout = timeout;
- RegisterResponseInfo response = proxy.Register(info);
- this.registrationId = response.RegistrationId;
- timer.Set(response.RegistrationLifetime);
- this.defaultLifeTime = response.RegistrationLifetime;
- proxy.Close();
- }
- finally
- {
- proxy.Abort();
- }
- }
- return registrationId;
- }
- void RegistrationExpired(object state)
- {
- if (!opened)
- return;
- try
- {
- IPeerResolverClient proxy = GetProxy();
- RefreshResponseInfo response;
- try
- {
- int oldValue = Interlocked.Exchange(ref this.updateSuccessful, 1);
- if (oldValue == 0)
- {
- SendUpdate(new UpdateInfo(this.registrationId, this.clientId, this.meshId, this.nodeAddress), ServiceDefaults.SendTimeout);
- return;
- }
- RefreshInfo info = new RefreshInfo(this.meshId, this.registrationId);
- response = proxy.Refresh(info);
- if (response.Result == RefreshResult.RegistrationNotFound)
- {
- RegisterInfo registerInfo = new RegisterInfo(clientId, meshId, nodeAddress);
- RegisterResponseInfo registerResponse = proxy.Register(registerInfo);
- registrationId = registerResponse.RegistrationId;
- this.defaultLifeTime = registerResponse.RegistrationLifetime;
- }
- else
- {
- Fx.Assert(response.Result == RefreshResult.Success, "Unrecognized value!!");
- }
- proxy.Close();
- }
- finally
- {
- proxy.Abort();
- timer.Set(this.defaultLifeTime);
- }
- }
- catch (CommunicationException e)
- {
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e)) throw;
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- }
- }
- // Unregister address for a node from the resolver service
- public override void Unregister(object registrationId, TimeSpan timeout)
- {
- if (opened)
- {
- UnregisterInfo info = new UnregisterInfo(this.meshId, this.registrationId);
- try
- {
- IPeerResolverClient proxy = GetProxy();
- try
- {
- proxy.OperationTimeout = timeout;
- proxy.Unregister(info);
- proxy.Close();
- }
- finally
- {
- proxy.Abort();
- }
- }
- catch (CommunicationException e)
- {
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- }
- finally
- {
- opened = false;
- timer.Cancel();
- }
- }
- }
- // Updates a node's registration with the resolver service.
- public override void Update(object registrationId, PeerNodeAddress updatedNodeAddress, TimeSpan timeout)
- {
- if (opened)
- {
- UpdateInfo info = new UpdateInfo(this.registrationId, clientId, meshId, updatedNodeAddress);
- this.nodeAddress = updatedNodeAddress;
- SendUpdate(info, timeout);
- }
- }
- void SendUpdate(UpdateInfo updateInfo, TimeSpan timeout)
- {
- try
- {
- RegisterResponseInfo response;
- IPeerResolverClient proxy = GetProxy();
- try
- {
- proxy.OperationTimeout = timeout;
- response = proxy.Update(updateInfo);
- proxy.Close();
- this.registrationId = response.RegistrationId;
- this.defaultLifeTime = response.RegistrationLifetime;
- Interlocked.Exchange(ref this.updateSuccessful, 1);
- timer.Set(this.defaultLifeTime);
- }
- finally
- {
- proxy.Abort();
- }
- }
- catch (CommunicationException e)
- {
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- Interlocked.Exchange(ref this.updateSuccessful, 0);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e)) throw;
- Interlocked.Exchange(ref this.updateSuccessful, 0);
- throw;
- }
- }
- // Query the resolver service for addresses associated with a mesh ID
- public override ReadOnlyCollection<PeerNodeAddress> Resolve(string meshId, int maxAddresses, TimeSpan timeout)
- {
- ResolveResponseInfo result = null;
- IList<PeerNodeAddress> addresses = null;
- List<PeerNodeAddress> output_addresses = new List<PeerNodeAddress>();
- if (opened)
- {
- ResolveInfo info = new ResolveInfo(clientId, meshId, maxAddresses);
- try
- {
- IPeerResolverClient proxy = GetProxy();
- try
- {
- proxy.OperationTimeout = timeout;
- result = proxy.Resolve(info);
- proxy.Close();
- }
- finally
- {
- proxy.Abort();
- }
- // If addresses couldn't be obtained, return empty collection
- if (result != null && result.Addresses != null)
- addresses = result.Addresses;
- }
- catch (CommunicationException e)
- {
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e)) throw;
- opened = false;
- throw;
- }
- }
- if (addresses != null)
- {
- foreach (PeerNodeAddress nodeaddr in addresses)
- {
- bool valid = true;
- long scopeId = -1;
- if (nodeaddr == null) continue;
- foreach (IPAddress addr in nodeaddr.IPAddresses)
- {
- if (addr.IsIPv6LinkLocal)
- {
- if (scopeId == -1)
- {
- scopeId = addr.ScopeId;
- }
- else if (scopeId != addr.ScopeId)
- {
- valid = false;
- break;
- }
- }
- }
- if (valid)
- {
- output_addresses.Add(nodeaddr);
- }
- }
- }
- return new ReadOnlyCollection<PeerNodeAddress>(output_addresses);
- }
- internal string BindingName
- {
- get { return bindingName; }
- set { this.bindingName = value; }
- }
- internal string BindingConfigurationName
- {
- get { return bindingName; }
- set { this.bindingConfigurationName = value; }
- }
- public override bool Equals(object other)
- {
- PeerDefaultCustomResolverClient that = other as PeerDefaultCustomResolverClient;
- if ((that == null) ||
- (this.referralPolicy != that.referralPolicy) || !this.address.Equals(that.address))
- return false;
- if (this.BindingName != null || this.BindingConfigurationName != null)
- return ((this.BindingName == that.BindingName) && (this.BindingConfigurationName == that.BindingConfigurationName));
- else
- return this.binding.Equals(that.binding);
- }
- public override int GetHashCode()
- {
- return base.GetHashCode();
- }
- }
- }
|