PeerDefaultCustomResolverClient.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.PeerResolvers
  5. {
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.Diagnostics;
  9. using System.Net;
  10. using System.Runtime;
  11. using System.ServiceModel;
  12. using System.ServiceModel.Channels;
  13. using System.ServiceModel.Description;
  14. using System.Threading;
  15. class PeerDefaultCustomResolverClient : PeerResolver
  16. {
  17. EndpointAddress address;
  18. Binding binding;
  19. TimeSpan defaultLifeTime;
  20. ClientCredentials credentials;
  21. Guid clientId;
  22. Guid registrationId;
  23. IOThreadTimer timer;
  24. bool opened = false;
  25. string meshId;
  26. PeerNodeAddress nodeAddress;
  27. ChannelFactory<IPeerResolverClient> channelFactory;
  28. PeerReferralPolicy referralPolicy;
  29. string bindingName, bindingConfigurationName;
  30. bool? shareReferrals;
  31. int updateSuccessful = 1;
  32. internal PeerDefaultCustomResolverClient()
  33. {
  34. this.address = null;
  35. this.binding = null;
  36. this.defaultLifeTime = TimeSpan.FromHours(1);
  37. clientId = Guid.NewGuid();
  38. timer = new IOThreadTimer(new Action<object>(RegistrationExpired), this, false);
  39. }
  40. public override bool CanShareReferrals
  41. {
  42. get
  43. {
  44. if (this.shareReferrals.HasValue)
  45. return shareReferrals.Value;
  46. if (this.referralPolicy == PeerReferralPolicy.Service && opened)
  47. {
  48. IPeerResolverClient proxy = GetProxy();
  49. try
  50. {
  51. ServiceSettingsResponseInfo settings = proxy.GetServiceSettings();
  52. shareReferrals = !settings.ControlMeshShape;
  53. proxy.Close();
  54. }
  55. finally
  56. {
  57. proxy.Abort();
  58. }
  59. }
  60. else
  61. {
  62. shareReferrals = (PeerReferralPolicy.Share == this.referralPolicy);
  63. }
  64. return shareReferrals.Value;
  65. }
  66. }
  67. public override void Initialize(EndpointAddress address, Binding binding, ClientCredentials credentials, PeerReferralPolicy referralPolicy)
  68. {
  69. this.address = address;
  70. this.binding = binding;
  71. this.credentials = credentials;
  72. Validate();
  73. channelFactory = new ChannelFactory<IPeerResolverClient>(binding, address);
  74. channelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
  75. if (credentials != null)
  76. channelFactory.Endpoint.Behaviors.Add(credentials);
  77. channelFactory.Open();
  78. this.referralPolicy = referralPolicy;
  79. opened = true;
  80. }
  81. IPeerResolverClient GetProxy()
  82. {
  83. return (IPeerResolverClient)channelFactory.CreateChannel();
  84. }
  85. void Validate()
  86. {
  87. if (address == null || binding == null)
  88. PeerExceptionHelper.ThrowArgument_InsufficientResolverSettings();
  89. }
  90. // Register address for a node participating in a mesh identified by meshId with the resolver service
  91. public override object Register(string meshId, PeerNodeAddress nodeAddress, TimeSpan timeout)
  92. {
  93. if (opened)
  94. {
  95. long scopeId = -1;
  96. bool multipleScopes = false;
  97. if (nodeAddress.IPAddresses.Count == 0)
  98. {
  99. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MustRegisterMoreThanZeroAddresses)));
  100. }
  101. foreach (IPAddress address in nodeAddress.IPAddresses)
  102. {
  103. if (address.IsIPv6LinkLocal)
  104. {
  105. if (scopeId == -1)
  106. {
  107. scopeId = address.ScopeId;
  108. }
  109. else if (scopeId != address.ScopeId)
  110. {
  111. multipleScopes = true;
  112. break;
  113. }
  114. }
  115. }
  116. List<IPAddress> addresslist = new List<IPAddress>();
  117. foreach (IPAddress address in nodeAddress.IPAddresses)
  118. {
  119. if (!multipleScopes || (!address.IsIPv6LinkLocal && !address.IsIPv6SiteLocal))
  120. addresslist.Add(address);
  121. }
  122. if (addresslist.Count == 0)
  123. {
  124. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.AmbiguousConnectivitySpec)));
  125. }
  126. ReadOnlyCollection<IPAddress> addresses = new ReadOnlyCollection<IPAddress>(addresslist);
  127. this.meshId = meshId;
  128. this.nodeAddress = new PeerNodeAddress(nodeAddress.EndpointAddress, addresses);
  129. RegisterInfo info = new RegisterInfo(clientId, meshId, this.nodeAddress);
  130. IPeerResolverClient proxy = GetProxy();
  131. try
  132. {
  133. proxy.OperationTimeout = timeout;
  134. RegisterResponseInfo response = proxy.Register(info);
  135. this.registrationId = response.RegistrationId;
  136. timer.Set(response.RegistrationLifetime);
  137. this.defaultLifeTime = response.RegistrationLifetime;
  138. proxy.Close();
  139. }
  140. finally
  141. {
  142. proxy.Abort();
  143. }
  144. }
  145. return registrationId;
  146. }
  147. void RegistrationExpired(object state)
  148. {
  149. if (!opened)
  150. return;
  151. try
  152. {
  153. IPeerResolverClient proxy = GetProxy();
  154. RefreshResponseInfo response;
  155. try
  156. {
  157. int oldValue = Interlocked.Exchange(ref this.updateSuccessful, 1);
  158. if (oldValue == 0)
  159. {
  160. SendUpdate(new UpdateInfo(this.registrationId, this.clientId, this.meshId, this.nodeAddress), ServiceDefaults.SendTimeout);
  161. return;
  162. }
  163. RefreshInfo info = new RefreshInfo(this.meshId, this.registrationId);
  164. response = proxy.Refresh(info);
  165. if (response.Result == RefreshResult.RegistrationNotFound)
  166. {
  167. RegisterInfo registerInfo = new RegisterInfo(clientId, meshId, nodeAddress);
  168. RegisterResponseInfo registerResponse = proxy.Register(registerInfo);
  169. registrationId = registerResponse.RegistrationId;
  170. this.defaultLifeTime = registerResponse.RegistrationLifetime;
  171. }
  172. else
  173. {
  174. Fx.Assert(response.Result == RefreshResult.Success, "Unrecognized value!!");
  175. }
  176. proxy.Close();
  177. }
  178. finally
  179. {
  180. proxy.Abort();
  181. timer.Set(this.defaultLifeTime);
  182. }
  183. }
  184. catch (CommunicationException e)
  185. {
  186. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  187. }
  188. catch (Exception e)
  189. {
  190. if (Fx.IsFatal(e)) throw;
  191. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  192. }
  193. }
  194. // Unregister address for a node from the resolver service
  195. public override void Unregister(object registrationId, TimeSpan timeout)
  196. {
  197. if (opened)
  198. {
  199. UnregisterInfo info = new UnregisterInfo(this.meshId, this.registrationId);
  200. try
  201. {
  202. IPeerResolverClient proxy = GetProxy();
  203. try
  204. {
  205. proxy.OperationTimeout = timeout;
  206. proxy.Unregister(info);
  207. proxy.Close();
  208. }
  209. finally
  210. {
  211. proxy.Abort();
  212. }
  213. }
  214. catch (CommunicationException e)
  215. {
  216. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  217. }
  218. finally
  219. {
  220. opened = false;
  221. timer.Cancel();
  222. }
  223. }
  224. }
  225. // Updates a node's registration with the resolver service.
  226. public override void Update(object registrationId, PeerNodeAddress updatedNodeAddress, TimeSpan timeout)
  227. {
  228. if (opened)
  229. {
  230. UpdateInfo info = new UpdateInfo(this.registrationId, clientId, meshId, updatedNodeAddress);
  231. this.nodeAddress = updatedNodeAddress;
  232. SendUpdate(info, timeout);
  233. }
  234. }
  235. void SendUpdate(UpdateInfo updateInfo, TimeSpan timeout)
  236. {
  237. try
  238. {
  239. RegisterResponseInfo response;
  240. IPeerResolverClient proxy = GetProxy();
  241. try
  242. {
  243. proxy.OperationTimeout = timeout;
  244. response = proxy.Update(updateInfo);
  245. proxy.Close();
  246. this.registrationId = response.RegistrationId;
  247. this.defaultLifeTime = response.RegistrationLifetime;
  248. Interlocked.Exchange(ref this.updateSuccessful, 1);
  249. timer.Set(this.defaultLifeTime);
  250. }
  251. finally
  252. {
  253. proxy.Abort();
  254. }
  255. }
  256. catch (CommunicationException e)
  257. {
  258. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  259. Interlocked.Exchange(ref this.updateSuccessful, 0);
  260. }
  261. catch (Exception e)
  262. {
  263. if (Fx.IsFatal(e)) throw;
  264. Interlocked.Exchange(ref this.updateSuccessful, 0);
  265. throw;
  266. }
  267. }
  268. // Query the resolver service for addresses associated with a mesh ID
  269. public override ReadOnlyCollection<PeerNodeAddress> Resolve(string meshId, int maxAddresses, TimeSpan timeout)
  270. {
  271. ResolveResponseInfo result = null;
  272. IList<PeerNodeAddress> addresses = null;
  273. List<PeerNodeAddress> output_addresses = new List<PeerNodeAddress>();
  274. if (opened)
  275. {
  276. ResolveInfo info = new ResolveInfo(clientId, meshId, maxAddresses);
  277. try
  278. {
  279. IPeerResolverClient proxy = GetProxy();
  280. try
  281. {
  282. proxy.OperationTimeout = timeout;
  283. result = proxy.Resolve(info);
  284. proxy.Close();
  285. }
  286. finally
  287. {
  288. proxy.Abort();
  289. }
  290. // If addresses couldn't be obtained, return empty collection
  291. if (result != null && result.Addresses != null)
  292. addresses = result.Addresses;
  293. }
  294. catch (CommunicationException e)
  295. {
  296. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  297. }
  298. catch (Exception e)
  299. {
  300. if (Fx.IsFatal(e)) throw;
  301. opened = false;
  302. throw;
  303. }
  304. }
  305. if (addresses != null)
  306. {
  307. foreach (PeerNodeAddress nodeaddr in addresses)
  308. {
  309. bool valid = true;
  310. long scopeId = -1;
  311. if (nodeaddr == null) continue;
  312. foreach (IPAddress addr in nodeaddr.IPAddresses)
  313. {
  314. if (addr.IsIPv6LinkLocal)
  315. {
  316. if (scopeId == -1)
  317. {
  318. scopeId = addr.ScopeId;
  319. }
  320. else if (scopeId != addr.ScopeId)
  321. {
  322. valid = false;
  323. break;
  324. }
  325. }
  326. }
  327. if (valid)
  328. {
  329. output_addresses.Add(nodeaddr);
  330. }
  331. }
  332. }
  333. return new ReadOnlyCollection<PeerNodeAddress>(output_addresses);
  334. }
  335. internal string BindingName
  336. {
  337. get { return bindingName; }
  338. set { this.bindingName = value; }
  339. }
  340. internal string BindingConfigurationName
  341. {
  342. get { return bindingName; }
  343. set { this.bindingConfigurationName = value; }
  344. }
  345. public override bool Equals(object other)
  346. {
  347. PeerDefaultCustomResolverClient that = other as PeerDefaultCustomResolverClient;
  348. if ((that == null) ||
  349. (this.referralPolicy != that.referralPolicy) || !this.address.Equals(that.address))
  350. return false;
  351. if (this.BindingName != null || this.BindingConfigurationName != null)
  352. return ((this.BindingName == that.BindingName) && (this.BindingConfigurationName == that.BindingConfigurationName));
  353. else
  354. return this.binding.Equals(that.binding);
  355. }
  356. public override int GetHashCode()
  357. {
  358. return base.GetHashCode();
  359. }
  360. }
  361. }