1 //----------------------------------------------------------------------------- 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //----------------------------------------------------------------------------- 4 5 namespace System.ServiceModel 6 { 7 using System; 8 using System.Collections.Generic; 9 using System.Collections.ObjectModel; 10 using System.ComponentModel; 11 using System.Diagnostics; 12 using System.Globalization; 13 using System.Net; 14 using System.Runtime; 15 using System.Security; 16 using System.ServiceModel.Administration; 17 using System.ServiceModel.Channels; 18 using System.ServiceModel.Configuration; 19 using System.ServiceModel.Description; 20 using System.ServiceModel.Diagnostics; 21 using System.ServiceModel.Dispatcher; 22 using System.Text; 23 using System.Runtime.Diagnostics; 24 using System.Threading; 25 using System.ServiceModel.Activation; 26 using System.ServiceModel.Diagnostics.Application; 27 using System.Reflection; 28 using System.Linq.Expressions; 29 30 public abstract class ServiceHostBase : CommunicationObject, IExtensibleObject<ServiceHostBase>, IDisposable 31 { 32 internal static readonly Uri EmptyUri = new Uri(string.Empty, UriKind.RelativeOrAbsolute); 33 34 bool initializeDescriptionHasFinished; 35 UriSchemeKeyedCollection baseAddresses; 36 ChannelDispatcherCollection channelDispatchers; 37 TimeSpan closeTimeout = ServiceDefaults.ServiceHostCloseTimeout; 38 ServiceDescription description; 39 ExtensionCollection<ServiceHostBase> extensions; 40 ReadOnlyCollection<Uri> externalBaseAddresses; 41 IDictionary<string, ContractDescription> implementedContracts; 42 IInstanceContextManager instances; 43 TimeSpan openTimeout = ServiceDefaults.OpenTimeout; 44 ServicePerformanceCountersBase servicePerformanceCounters; 45 DefaultPerformanceCounters defaultPerformanceCounters; 46 ServiceThrottle serviceThrottle; 47 ServiceCredentials readOnlyCredentials; 48 ServiceAuthorizationBehavior readOnlyAuthorization; 49 ServiceAuthenticationBehavior readOnlyAuthentication; 50 Dictionary<DispatcherBuilder.ListenUriInfo, Collection<ServiceEndpoint>> endpointsByListenUriInfo; 51 int busyCount; 52 EventTraceActivity eventTraceActivity; 53 54 internal event EventHandler BusyCountIncremented; 55 56 public event EventHandler<UnknownMessageReceivedEventArgs> UnknownMessageReceived; 57 ServiceHostBase()58 protected ServiceHostBase() 59 { 60 TraceUtility.SetEtwProviderId(); 61 this.baseAddresses = new UriSchemeKeyedCollection(this.ThisLock); 62 this.channelDispatchers = new ChannelDispatcherCollection(this, this.ThisLock); 63 this.extensions = new ExtensionCollection<ServiceHostBase>(this, this.ThisLock); 64 this.instances = new InstanceContextManager(this.ThisLock); 65 this.serviceThrottle = new ServiceThrottle(this); 66 this.TraceOpenAndClose = true; 67 this.Faulted += new EventHandler(OnServiceHostFaulted); 68 } 69 70 71 internal EventTraceActivity EventTraceActivity 72 { 73 get 74 { 75 if (this.eventTraceActivity == null) 76 { 77 this.eventTraceActivity = new EventTraceActivity(); 78 } 79 80 return eventTraceActivity; 81 } 82 } 83 84 public ServiceAuthorizationBehavior Authorization 85 { 86 get 87 { 88 if (this.Description == null) 89 { 90 return null; 91 } 92 else if (this.State == CommunicationState.Created || this.State == CommunicationState.Opening) 93 { 94 return EnsureAuthorization(this.Description); 95 } 96 else 97 { 98 return this.readOnlyAuthorization; 99 } 100 } 101 } 102 103 public ServiceAuthenticationBehavior Authentication 104 { 105 get 106 { 107 if (this.Description == null) 108 { 109 return null; 110 } 111 else if (this.State == CommunicationState.Created || this.State == CommunicationState.Opening) 112 { 113 return EnsureAuthentication(this.Description); 114 } 115 else 116 { 117 return this.readOnlyAuthentication; 118 } 119 } 120 } 121 122 public ReadOnlyCollection<Uri> BaseAddresses 123 { 124 get 125 { 126 externalBaseAddresses = new ReadOnlyCollection<Uri>(new List<Uri>(this.baseAddresses)); 127 return externalBaseAddresses; 128 } 129 } 130 131 public ChannelDispatcherCollection ChannelDispatchers 132 { 133 get { return this.channelDispatchers; } 134 } 135 136 public TimeSpan CloseTimeout 137 { 138 get { return this.closeTimeout; } 139 set 140 { 141 if (value < TimeSpan.Zero) 142 { 143 string message = SR.GetString(SR.SFxTimeoutOutOfRange0); 144 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", message)); 145 } 146 if (TimeoutHelper.IsTooLarge(value)) 147 { 148 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.SFxTimeoutOutOfRangeTooBig))); 149 } 150 151 lock (this.ThisLock) 152 { 153 this.ThrowIfClosedOrOpened(); 154 this.closeTimeout = value; 155 } 156 } 157 } 158 159 internal ServicePerformanceCountersBase Counters 160 { 161 get 162 { 163 return this.servicePerformanceCounters; 164 } 165 set 166 { 167 this.servicePerformanceCounters = value; 168 this.serviceThrottle.SetServicePerformanceCounters(this.servicePerformanceCounters); 169 } 170 } 171 172 internal DefaultPerformanceCounters DefaultCounters 173 { 174 get 175 { 176 return this.defaultPerformanceCounters; 177 } 178 set 179 { 180 this.defaultPerformanceCounters = value; 181 } 182 } 183 184 public ServiceCredentials Credentials 185 { 186 get 187 { 188 if (this.Description == null) 189 { 190 return null; 191 } 192 else if (this.State == CommunicationState.Created || this.State == CommunicationState.Opening) 193 { 194 return EnsureCredentials(this.Description); 195 } 196 else 197 { 198 return this.readOnlyCredentials; 199 } 200 } 201 } 202 203 protected override TimeSpan DefaultCloseTimeout 204 { 205 get { return this.CloseTimeout; } 206 } 207 208 protected override TimeSpan DefaultOpenTimeout 209 { 210 get { return this.OpenTimeout; } 211 } 212 213 public ServiceDescription Description 214 { 215 get { return this.description; } 216 } 217 218 public IExtensionCollection<ServiceHostBase> Extensions 219 { 220 get { return this.extensions; } 221 } 222 223 protected internal IDictionary<string, ContractDescription> ImplementedContracts 224 { 225 get { return this.implementedContracts; } 226 } 227 228 internal UriSchemeKeyedCollection InternalBaseAddresses 229 { 230 get { return this.baseAddresses; } 231 } 232 233 public int ManualFlowControlLimit 234 { 235 get { return this.ServiceThrottle.ManualFlowControlLimit; } 236 set { this.ServiceThrottle.ManualFlowControlLimit = value; } 237 } 238 239 public TimeSpan OpenTimeout 240 { 241 get { return this.openTimeout; } 242 set 243 { 244 if (value < TimeSpan.Zero) 245 { 246 string message = SR.GetString(SR.SFxTimeoutOutOfRange0); 247 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", message)); 248 } 249 if (TimeoutHelper.IsTooLarge(value)) 250 { 251 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.SFxTimeoutOutOfRangeTooBig))); 252 } 253 254 lock (this.ThisLock) 255 { 256 this.ThrowIfClosedOrOpened(); 257 this.openTimeout = value; 258 } 259 } 260 } 261 262 internal ServiceThrottle ServiceThrottle 263 { 264 get 265 { 266 return this.serviceThrottle; 267 } 268 } 269 270 internal virtual object DisposableInstance 271 { 272 get 273 { 274 return null; 275 } 276 } 277 278 internal Dictionary<DispatcherBuilder.ListenUriInfo, Collection<ServiceEndpoint>> EndpointsByListenUriInfo 279 { 280 get 281 { 282 if (this.endpointsByListenUriInfo == null) 283 { 284 this.endpointsByListenUriInfo = this.GetEndpointsByListenUriInfo(); 285 } 286 return this.endpointsByListenUriInfo; 287 } 288 } 289 GetEndpointsByListenUriInfo()290 Dictionary<DispatcherBuilder.ListenUriInfo, Collection<ServiceEndpoint>> GetEndpointsByListenUriInfo() 291 { 292 Dictionary<DispatcherBuilder.ListenUriInfo, Collection<ServiceEndpoint>> endpointDictionary = new Dictionary<DispatcherBuilder.ListenUriInfo, Collection<ServiceEndpoint>>(); 293 foreach (ServiceEndpoint endpoint in this.Description.Endpoints) 294 { 295 DispatcherBuilder.ListenUriInfo listenUriInfo = DispatcherBuilder.GetListenUriInfoForEndpoint(this, endpoint); 296 if (!endpointDictionary.ContainsKey(listenUriInfo)) 297 { 298 endpointDictionary.Add(listenUriInfo, new Collection<ServiceEndpoint>()); 299 } 300 endpointDictionary[listenUriInfo].Add(endpoint); 301 } 302 return endpointDictionary; 303 } 304 AddBaseAddress(Uri baseAddress)305 protected void AddBaseAddress(Uri baseAddress) 306 { 307 if (this.initializeDescriptionHasFinished) 308 { 309 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 310 SR.GetString(SR.SFxCannotCallAddBaseAddress))); 311 } 312 this.baseAddresses.Add(baseAddress); 313 } 314 AddServiceEndpoint(string implementedContract, Binding binding, string address)315 public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address) 316 { 317 return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null); 318 } 319 AddServiceEndpoint(string implementedContract, Binding binding, string address, Uri listenUri)320 public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address, Uri listenUri) 321 { 322 if (address == null) 323 { 324 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("address")); 325 } 326 327 ServiceEndpoint endpoint = this.AddServiceEndpoint(implementedContract, binding, new Uri(address, UriKind.RelativeOrAbsolute)); 328 if (listenUri != null) 329 { 330 endpoint.UnresolvedListenUri = listenUri; 331 listenUri = MakeAbsoluteUri(listenUri, binding); 332 endpoint.ListenUri = listenUri; 333 } 334 return endpoint; 335 } 336 AddServiceEndpoint(string implementedContract, Binding binding, Uri address)337 public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address) 338 { 339 return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null); 340 } 341 AddServiceEndpoint(string implementedContract, Binding binding, Uri address, Uri listenUri)342 public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address, Uri listenUri) 343 { 344 if (address == null) 345 { 346 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("address")); 347 } 348 349 if (binding == null) 350 { 351 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("binding")); 352 } 353 354 if (implementedContract == null) 355 { 356 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("implementedContract")); 357 } 358 359 if (this.State != CommunicationState.Created && this.State != CommunicationState.Opening) 360 { 361 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotAddEndpointAfterOpen))); 362 } 363 364 if (this.Description == null) 365 { 366 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotAddEndpointWithoutDescription))); 367 } 368 369 Uri via = this.MakeAbsoluteUri(address, binding); 370 371 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.implementedContracts)); 372 ContractDescription contract = configLoader.LookupContract(implementedContract, this.Description.Name); 373 374 ServiceEndpoint serviceEndpoint = new ServiceEndpoint(contract, binding, new EndpointAddress(via)); 375 this.Description.Endpoints.Add(serviceEndpoint); 376 serviceEndpoint.UnresolvedAddress = address; 377 378 if (listenUri != null) 379 { 380 serviceEndpoint.UnresolvedListenUri = listenUri; 381 listenUri = MakeAbsoluteUri(listenUri, binding); 382 serviceEndpoint.ListenUri = listenUri; 383 } 384 return serviceEndpoint; 385 } 386 AddServiceEndpoint(ServiceEndpoint endpoint)387 public virtual void AddServiceEndpoint(ServiceEndpoint endpoint) 388 { 389 if (endpoint == null) 390 { 391 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint"); 392 } 393 if (this.State != CommunicationState.Created && this.State != CommunicationState.Opening) 394 { 395 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotAddEndpointAfterOpen))); 396 } 397 if (this.Description == null) 398 { 399 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotAddEndpointWithoutDescription))); 400 } 401 if (endpoint.Address == null) 402 { 403 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxEndpointAddressNotSpecified)); 404 } 405 if (endpoint.Contract == null) 406 { 407 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxEndpointContractNotSpecified)); 408 } 409 if (endpoint.Binding == null) 410 { 411 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxEndpointBindingNotSpecified)); 412 } 413 if (!endpoint.IsSystemEndpoint || endpoint.Contract.ContractType == typeof(IMetadataExchange)) 414 { 415 ConfigLoader loader = new ConfigLoader(GetContractResolver(this.implementedContracts)); 416 loader.LookupContract(endpoint.Contract.ConfigurationName, this.Description.Name); 417 } 418 this.Description.Endpoints.Add(endpoint); 419 } 420 SetEndpointAddress(ServiceEndpoint endpoint, string relativeAddress)421 public void SetEndpointAddress(ServiceEndpoint endpoint, string relativeAddress) 422 { 423 if (endpoint == null) 424 { 425 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint"); 426 } 427 if (relativeAddress == null) 428 { 429 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("relativeAddress"); 430 } 431 if (endpoint.Binding == null) 432 { 433 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SFxEndpointBindingNotSpecified)); 434 } 435 Uri absoluteUri = MakeAbsoluteUri(new Uri(relativeAddress, UriKind.Relative), endpoint.Binding); 436 endpoint.Address = new EndpointAddress(absoluteUri); 437 } 438 MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding)439 internal Uri MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding) 440 { 441 return MakeAbsoluteUri(relativeOrAbsoluteUri, binding, this.InternalBaseAddresses); 442 } 443 MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding, UriSchemeKeyedCollection baseAddresses)444 internal static Uri MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding, UriSchemeKeyedCollection baseAddresses) 445 { 446 Uri result = relativeOrAbsoluteUri; 447 if (!result.IsAbsoluteUri) 448 { 449 if (binding.Scheme == string.Empty) 450 { 451 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCustomBindingWithoutTransport))); 452 } 453 result = GetVia(binding.Scheme, result, baseAddresses); 454 if (result == null) 455 { 456 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxEndpointNoMatchingScheme, binding.Scheme, binding.Name, GetBaseAddressSchemes(baseAddresses)))); 457 } 458 } 459 return result; 460 } 461 ApplyConfiguration()462 protected virtual void ApplyConfiguration() 463 { 464 if (this.Description == null) 465 { 466 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotApplyConfigurationWithoutDescription))); 467 } 468 469 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(implementedContracts)); 470 471 // Call the overload of LoadConfigurationSectionInternal which looks up the serviceElement from ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None) 472 LoadConfigurationSectionInternal(configLoader, this.Description, this.Description.ConfigurationName); 473 474 EnsureAuthenticationAuthorizationDebug(this.Description); 475 } 476 EnsureAuthenticationAuthorizationDebug(ServiceDescription description)477 internal void EnsureAuthenticationAuthorizationDebug(ServiceDescription description) 478 { 479 EnsureAuthentication(description); 480 EnsureAuthorization(description); 481 EnsureDebug(description); 482 } 483 AddDefaultEndpoints()484 public virtual ReadOnlyCollection<ServiceEndpoint> AddDefaultEndpoints() 485 { 486 List<ServiceEndpoint> defaultEndpoints = new List<ServiceEndpoint>(); 487 foreach (Uri baseAddress in this.InternalBaseAddresses) 488 { 489 ProtocolMappingItem protocolMappingItem = ConfigLoader.LookupProtocolMapping(baseAddress.Scheme); 490 if (protocolMappingItem != null) 491 { 492 Binding defaultBinding = ConfigLoader.LookupBinding(protocolMappingItem.Binding, protocolMappingItem.BindingConfiguration); 493 if (defaultBinding != null) 494 { 495 AddDefaultEndpoints(defaultBinding, defaultEndpoints); 496 } 497 else 498 { 499 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Exception(SR.GetString(SR.BindingProtocolMappingNotDefined, baseAddress.Scheme))); 500 } 501 } 502 } 503 if (DiagnosticUtility.ShouldTraceInformation && defaultEndpoints.Count > 0) 504 { 505 Dictionary<string, string> dictionary = new Dictionary<string, string>(); 506 dictionary["ServiceConfigurationName"] = this.description.ConfigurationName; 507 TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.DefaultEndpointsAdded, SR.GetString(SR.TraceCodeDefaultEndpointsAdded), new DictionaryTraceRecord(dictionary)); 508 } 509 return new ReadOnlyCollection<ServiceEndpoint>(defaultEndpoints); 510 } 511 AddDefaultEndpoints(Binding defaultBinding, List<ServiceEndpoint> defaultEndpoints)512 internal virtual void AddDefaultEndpoints(Binding defaultBinding, List<ServiceEndpoint> defaultEndpoints) 513 { 514 } 515 BindInstance(InstanceContext instance)516 internal virtual void BindInstance(InstanceContext instance) 517 { 518 this.instances.Add(instance); 519 if (null != this.servicePerformanceCounters) 520 { 521 lock (this.ThisLock) 522 { 523 if (null != this.servicePerformanceCounters) 524 { 525 this.servicePerformanceCounters.ServiceInstanceCreated(); 526 } 527 } 528 } 529 } 530 IDisposable.Dispose()531 void IDisposable.Dispose() 532 { 533 Close(); 534 } 535 CreateDescription(out IDictionary<string, ContractDescription> implementedContracts)536 protected abstract ServiceDescription CreateDescription(out IDictionary<string, ContractDescription> implementedContracts); 537 InitializeRuntime()538 protected virtual void InitializeRuntime() 539 { 540 if (this.Description == null) 541 { 542 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotInitializeRuntimeWithoutDescription))); 543 } 544 545 if (this.Description.Endpoints.Count == 0) 546 { 547 this.AddDefaultEndpoints(); 548 } 549 550 this.EnsureAuthenticationSchemes(); 551 552 DispatcherBuilder dispatcherBuilder = new DispatcherBuilder(); 553 dispatcherBuilder.InitializeServiceHost(description, this); 554 555 SecurityValidationBehavior.Instance.AfterBuildTimeValidation(description); 556 } 557 AfterInitializeRuntime(TimeSpan timeout)558 internal virtual void AfterInitializeRuntime(TimeSpan timeout) 559 { 560 } 561 BeginAfterInitializeRuntime(TimeSpan timeout, AsyncCallback callback, object state)562 internal virtual IAsyncResult BeginAfterInitializeRuntime(TimeSpan timeout, AsyncCallback callback, object state) 563 { 564 return new CompletedAsyncResult(callback, state); 565 } 566 EndAfterInitializeRuntime(IAsyncResult result)567 internal virtual void EndAfterInitializeRuntime(IAsyncResult result) 568 { 569 CompletedAsyncResult.End(result); 570 } 571 EnsureAuthorization(ServiceDescription description)572 ServiceAuthorizationBehavior EnsureAuthorization(ServiceDescription description) 573 { 574 Fx.Assert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, ""); 575 ServiceAuthorizationBehavior a = description.Behaviors.Find<ServiceAuthorizationBehavior>(); 576 577 if (a == null) 578 { 579 a = new ServiceAuthorizationBehavior(); 580 description.Behaviors.Add(a); 581 } 582 583 return a; 584 } 585 EnsureAuthentication(ServiceDescription description)586 ServiceAuthenticationBehavior EnsureAuthentication(ServiceDescription description) 587 { 588 Fx.Assert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, ""); 589 ServiceAuthenticationBehavior a = description.Behaviors.Find<ServiceAuthenticationBehavior>(); 590 591 if (a == null) 592 { 593 a = new ServiceAuthenticationBehavior(); 594 description.Behaviors.Add(a); 595 } 596 return a; 597 } 598 EnsureDebug(ServiceDescription description)599 ServiceDebugBehavior EnsureDebug(ServiceDescription description) 600 { 601 Fx.Assert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, ""); 602 ServiceDebugBehavior m = description.Behaviors.Find<ServiceDebugBehavior>(); 603 604 if (m == null) 605 { 606 m = new ServiceDebugBehavior(); 607 description.Behaviors.Add(m); 608 } 609 610 return m; 611 } 612 EnsureCredentials(ServiceDescription description)613 ServiceCredentials EnsureCredentials(ServiceDescription description) 614 { 615 Fx.Assert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, ""); 616 ServiceCredentials c = description.Behaviors.Find<ServiceCredentials>(); 617 618 if (c == null) 619 { 620 c = new ServiceCredentials(); 621 description.Behaviors.Add(c); 622 } 623 624 return c; 625 } 626 FaultInternal()627 internal void FaultInternal() 628 { 629 this.Fault(); 630 } 631 GetBaseAddressSchemes()632 internal string GetBaseAddressSchemes() 633 { 634 return GetBaseAddressSchemes(baseAddresses); 635 } 636 GetBaseAddressSchemes(UriSchemeKeyedCollection uriSchemeKeyedCollection)637 internal static String GetBaseAddressSchemes(UriSchemeKeyedCollection uriSchemeKeyedCollection) 638 { 639 StringBuilder buffer = new StringBuilder(); 640 bool firstScheme = true; 641 foreach (Uri address in uriSchemeKeyedCollection) 642 { 643 if (firstScheme) 644 { 645 buffer.Append(address.Scheme); 646 firstScheme = false; 647 } 648 else 649 { 650 buffer.Append(CultureInfo.CurrentCulture.TextInfo.ListSeparator).Append(address.Scheme); 651 } 652 } 653 return buffer.ToString(); 654 } 655 GetBindingParameters()656 internal BindingParameterCollection GetBindingParameters() 657 { 658 return DispatcherBuilder.GetBindingParameters(this, new Collection<ServiceEndpoint>()); 659 } 660 GetBindingParameters(ServiceEndpoint inputEndpoint)661 internal BindingParameterCollection GetBindingParameters(ServiceEndpoint inputEndpoint) 662 { 663 Collection<ServiceEndpoint> endpoints; 664 if (inputEndpoint == null) 665 { 666 endpoints = new Collection<ServiceEndpoint>(); 667 } 668 else if (!this.EndpointsByListenUriInfo.TryGetValue(DispatcherBuilder.GetListenUriInfoForEndpoint(this, inputEndpoint), out endpoints) || !endpoints.Contains(inputEndpoint)) 669 { 670 endpoints = new Collection<ServiceEndpoint>(); 671 endpoints.Add(inputEndpoint); 672 } 673 674 return DispatcherBuilder.GetBindingParameters(this, endpoints); 675 } 676 GetBindingParameters(Collection<ServiceEndpoint> endpoints)677 internal BindingParameterCollection GetBindingParameters(Collection<ServiceEndpoint> endpoints) 678 { 679 return DispatcherBuilder.GetBindingParameters(this, endpoints); 680 } 681 GetInstanceContexts()682 internal ReadOnlyCollection<InstanceContext> GetInstanceContexts() 683 { 684 return Array.AsReadOnly<InstanceContext>(this.instances.ToArray()); 685 } 686 GetContractResolver(IDictionary<string, ContractDescription> implementedContracts)687 internal virtual IContractResolver GetContractResolver(IDictionary<string, ContractDescription> implementedContracts) 688 { 689 ServiceAndBehaviorsContractResolver resolver = new ServiceAndBehaviorsContractResolver(new ImplementedContractsContractResolver(implementedContracts)); 690 resolver.AddBehaviorContractsToResolver(this.description == null ? null : this.description.Behaviors); 691 return resolver; 692 } 693 GetUri(Uri baseUri, Uri relativeUri)694 internal static Uri GetUri(Uri baseUri, Uri relativeUri) 695 { 696 return GetUri(baseUri, relativeUri.OriginalString); 697 } 698 GetUri(Uri baseUri, string path)699 internal static Uri GetUri(Uri baseUri, string path) 700 { 701 if (path.StartsWith("/", StringComparison.Ordinal) || path.StartsWith("\\", StringComparison.Ordinal)) 702 { 703 int i = 1; 704 for (; i < path.Length; ++i) 705 { 706 if (path[i] != '/' && path[i] != '\\') 707 { 708 break; 709 } 710 } 711 path = path.Substring(i); 712 } 713 714 // VSWhidbey#541152: new Uri(Uri, string.Empty) is broken 715 if (path.Length == 0) 716 return baseUri; 717 718 if (!baseUri.AbsoluteUri.EndsWith("/", StringComparison.Ordinal)) 719 { 720 baseUri = new Uri(baseUri.AbsoluteUri + "/"); 721 } 722 return new Uri(baseUri, path); 723 } 724 GetVia(string scheme, Uri address)725 internal Uri GetVia(string scheme, Uri address) 726 { 727 return ServiceHost.GetVia(scheme, address, InternalBaseAddresses); 728 } 729 GetVia(string scheme, Uri address, UriSchemeKeyedCollection baseAddresses)730 internal static Uri GetVia(string scheme, Uri address, UriSchemeKeyedCollection baseAddresses) 731 { 732 Uri via = address; 733 if (!via.IsAbsoluteUri) 734 { 735 if (!baseAddresses.Contains(scheme)) 736 { 737 return null; 738 } 739 740 via = GetUri(baseAddresses[scheme], address); 741 } 742 return via; 743 } 744 IncrementManualFlowControlLimit(int incrementBy)745 public int IncrementManualFlowControlLimit(int incrementBy) 746 { 747 return this.ServiceThrottle.IncrementManualFlowControlLimit(incrementBy); 748 } 749 InitializeDescription(UriSchemeKeyedCollection baseAddresses)750 protected void InitializeDescription(UriSchemeKeyedCollection baseAddresses) 751 { 752 foreach (Uri baseAddress in baseAddresses) 753 { 754 this.baseAddresses.Add(baseAddress); 755 } 756 IDictionary<string, ContractDescription> implementedContracts = null; 757 ServiceDescription description = CreateDescription(out implementedContracts); 758 this.description = description; 759 this.implementedContracts = implementedContracts; 760 761 ApplyConfiguration(); 762 this.initializeDescriptionHasFinished = true; 763 } 764 LoadConfigurationSection(ServiceElement serviceSection)765 protected void LoadConfigurationSection(ServiceElement serviceSection) 766 { 767 if (serviceSection == null) 768 { 769 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceSection"); 770 } 771 if (this.Description == null) 772 { 773 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotLoadConfigurationSectionWithoutDescription))); 774 } 775 776 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts)); 777 LoadConfigurationSectionInternal(configLoader, this.Description, serviceSection); 778 } 779 LoadConfigurationSectionHelper(Uri baseAddress)780 internal void LoadConfigurationSectionHelper(Uri baseAddress) 781 { 782 this.AddBaseAddress(baseAddress); 783 } 784 785 [Fx.Tag.SecurityNote(Critical = "Calls LookupService which is critical.", 786 Safe = "Doesn't leak ServiceElement out of SecurityCritical code.")] 787 [SecuritySafeCritical] LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName)788 void LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName) 789 { 790 ServiceElement serviceSection = configLoader.LookupService(configurationName); 791 LoadConfigurationSectionInternal(configLoader, description, serviceSection); 792 } 793 794 [Fx.Tag.SecurityNote(Critical = "Handles a ServiceElement, which should not be leaked out of SecurityCritical code.", 795 Safe = "Doesn't leak ServiceElement out of SecurityCritical code.")] 796 [SecuritySafeCritical] LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, ServiceElement serviceSection)797 void LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, ServiceElement serviceSection) 798 { 799 // caller must validate arguments before calling 800 configLoader.LoadServiceDescription(this, description, serviceSection, this.LoadConfigurationSectionHelper); 801 } 802 OnAbort()803 protected override void OnAbort() 804 { 805 this.instances.Abort(); 806 807 foreach (ChannelDispatcherBase dispatcher in this.ChannelDispatchers) 808 { 809 if (dispatcher.Listener != null) 810 { 811 dispatcher.Listener.Abort(); 812 } 813 dispatcher.Abort(); 814 } 815 ThreadTrace.StopTracing(); 816 } 817 OnAddChannelDispatcher(ChannelDispatcherBase channelDispatcher)818 internal void OnAddChannelDispatcher(ChannelDispatcherBase channelDispatcher) 819 { 820 lock (this.ThisLock) 821 { 822 this.ThrowIfClosedOrOpened(); 823 channelDispatcher.AttachInternal(this); 824 channelDispatcher.Faulted += new EventHandler(OnChannelDispatcherFaulted); 825 } 826 } 827 OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)828 protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) 829 { 830 return new CloseAsyncResult(timeout, callback, state, this); 831 } 832 OnBeginOpen()833 void OnBeginOpen() 834 { 835 this.TraceServiceHostOpenStart(); 836 this.TraceBaseAddresses(); 837 MessageLogger.EnsureInitialized(); //force config validation instead of waiting for the first message exchange 838 InitializeRuntime(); 839 } 840 OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)841 protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 842 { 843 this.OnBeginOpen(); 844 return new OpenAsyncResult(this, timeout, callback, state); 845 } 846 BeginOpenChannelDispatchers(TimeSpan timeout, AsyncCallback callback, object state)847 IAsyncResult BeginOpenChannelDispatchers(TimeSpan timeout, AsyncCallback callback, object state) 848 { 849 return new OpenCollectionAsyncResult(timeout, callback, state, this.SnapshotChannelDispatchers()); 850 } 851 OnClose(TimeSpan timeout)852 protected override void OnClose(TimeSpan timeout) 853 { 854 try 855 { 856 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 857 858 if (ManagementExtension.IsEnabled && null != this.Description) 859 { 860 ManagementExtension.OnServiceClosing(this); 861 } 862 863 for (int i = 0; i < this.ChannelDispatchers.Count; i++) 864 { 865 ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i]; 866 if (dispatcher.Listener != null) 867 { 868 dispatcher.Listener.Close(timeoutHelper.RemainingTime()); 869 } 870 } 871 872 for (int i = 0; i < this.ChannelDispatchers.Count; i++) 873 { 874 ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i]; 875 dispatcher.CloseInput(timeoutHelper.RemainingTime()); 876 } 877 878 // Wait for existing work to complete 879 this.instances.CloseInput(timeoutHelper.RemainingTime()); 880 881 // Close instances (closes contexts/channels) 882 this.instances.Close(timeoutHelper.RemainingTime()); 883 884 // Close dispatchers 885 for (int i = 0; i < this.ChannelDispatchers.Count; i++) 886 { 887 ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i]; 888 dispatcher.Close(timeoutHelper.RemainingTime()); 889 } 890 891 this.ReleasePerformanceCounters(); 892 893 this.TraceBaseAddresses(); 894 ThreadTrace.StopTracing(); 895 } 896 catch (TimeoutException e) 897 { 898 if (TD.CloseTimeoutIsEnabled()) 899 { 900 TD.CloseTimeout(SR.GetString(SR.TraceCodeServiceHostTimeoutOnClose)); 901 } 902 if (DiagnosticUtility.ShouldTraceWarning) 903 { 904 TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.ServiceHostTimeoutOnClose, SR.GetString(SR.TraceCodeServiceHostTimeoutOnClose), this, e); 905 } 906 this.Abort(); 907 } 908 909 } 910 OnClosed()911 protected override void OnClosed() 912 { 913 try 914 { 915 for (int i = 0; i < this.ChannelDispatchers.Count; i++) 916 { 917 ChannelDispatcher dispatcher = this.ChannelDispatchers[i] as ChannelDispatcher; 918 if (dispatcher != null) 919 { 920 dispatcher.ReleasePerformanceCounters(); 921 } 922 } 923 } 924 finally 925 { 926 base.OnClosed(); 927 } 928 } 929 TraceBaseAddresses()930 void TraceBaseAddresses() 931 { 932 if (DiagnosticUtility.ShouldTraceInformation && this.baseAddresses != null 933 && this.baseAddresses.Count > 0) 934 { 935 TraceUtility.TraceEvent(TraceEventType.Information, 936 TraceCode.ServiceHostBaseAddresses, 937 SR.GetString(SR.TraceCodeServiceHostBaseAddresses), 938 new CollectionTraceRecord("BaseAddresses", "Address", this.baseAddresses), 939 this, null); 940 } 941 } 942 TraceServiceHostOpenStart()943 void TraceServiceHostOpenStart() 944 { 945 if (TD.ServiceHostOpenStartIsEnabled()) 946 { 947 TD.ServiceHostOpenStart(this.EventTraceActivity); 948 } 949 } 950 OnEndClose(IAsyncResult result)951 protected override void OnEndClose(IAsyncResult result) 952 { 953 try 954 { 955 CloseAsyncResult.End(result); 956 this.TraceBaseAddresses(); 957 ThreadTrace.StopTracing(); 958 } 959 catch (TimeoutException e) 960 { 961 if (TD.CloseTimeoutIsEnabled()) 962 { 963 TD.CloseTimeout(SR.GetString(SR.TraceCodeServiceHostTimeoutOnClose)); 964 } 965 if (DiagnosticUtility.ShouldTraceWarning) 966 { 967 TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.ServiceHostTimeoutOnClose, 968 SR.GetString(SR.TraceCodeServiceHostTimeoutOnClose), this, e); 969 } 970 this.Abort(); 971 } 972 } 973 OnEndOpen(IAsyncResult result)974 protected override void OnEndOpen(IAsyncResult result) 975 { 976 OpenAsyncResult.End(result); 977 } 978 EndOpenChannelDispatchers(IAsyncResult result)979 void EndOpenChannelDispatchers(IAsyncResult result) 980 { 981 OpenCollectionAsyncResult.End(result); 982 } 983 EnsureAuthenticationSchemes()984 void EnsureAuthenticationSchemes() 985 { 986 if (this.Authentication == null) 987 { 988 return; 989 } 990 991 //Exit immediately when not hosted in IIS or if VirtualPathExtension is not set. VirtualPathExtension is used as a flag to indicate whether a ServiceHost 992 // is webhosted (WsDualHttpBinding-ChannelFactory is using HttpListener instead of IIS even when running in IIS) 993 if (!AspNetEnvironment.Enabled || 994 this.Extensions.Find<VirtualPathExtension>() == null) 995 { 996 return; 997 } 998 999 foreach (ServiceEndpoint serviceEndpoint in this.Description.Endpoints) 1000 { 1001 if (serviceEndpoint.Binding != null && 1002 serviceEndpoint.ListenUri != null && 1003 ("http".Equals(serviceEndpoint.ListenUri.Scheme, StringComparison.OrdinalIgnoreCase) || "https".Equals(serviceEndpoint.ListenUri.Scheme, StringComparison.OrdinalIgnoreCase)) && 1004 this.baseAddresses.Contains(serviceEndpoint.ListenUri.Scheme)) 1005 { 1006 HttpTransportBindingElement httpTransportBindingElement = serviceEndpoint.Binding.CreateBindingElements().Find<HttpTransportBindingElement>(); 1007 1008 if (httpTransportBindingElement != null) 1009 { 1010 AuthenticationSchemes hostSupportedAuthenticationSchemes = AspNetEnvironment.Current.GetAuthenticationSchemes(this.baseAddresses[serviceEndpoint.ListenUri.Scheme]); 1011 1012 if (hostSupportedAuthenticationSchemes != AuthenticationSchemes.None) 1013 { 1014 //If no authentication schemes are explicitly defined for the ServiceHost... 1015 if (this.Authentication.AuthenticationSchemes == AuthenticationSchemes.None) 1016 { 1017 //Inherit authentication schemes from IIS 1018 this.Authentication.AuthenticationSchemes = hostSupportedAuthenticationSchemes; 1019 } 1020 else 1021 { 1022 // Build intersection between authenticationSchemes on the ServiceHost and in IIS 1023 this.Authentication.AuthenticationSchemes &= hostSupportedAuthenticationSchemes; 1024 } 1025 } 1026 } 1027 1028 break; 1029 } 1030 } 1031 } 1032 OnOpen(TimeSpan timeout)1033 protected override void OnOpen(TimeSpan timeout) 1034 { 1035 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 1036 this.OnBeginOpen(); 1037 1038 AfterInitializeRuntime(timeoutHelper.RemainingTime()); 1039 1040 for (int i = 0; i < this.ChannelDispatchers.Count; i++) 1041 { 1042 ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i]; 1043 dispatcher.Open(timeoutHelper.RemainingTime()); 1044 } 1045 } 1046 OnOpened()1047 protected override void OnOpened() 1048 { 1049 if (this.Description != null) 1050 { 1051 ServiceCredentials c = description.Behaviors.Find<ServiceCredentials>(); 1052 if (c != null) 1053 { 1054 ServiceCredentials credentialsCopy = c.Clone(); 1055 credentialsCopy.MakeReadOnly(); 1056 this.readOnlyCredentials = credentialsCopy; 1057 } 1058 1059 ServiceAuthorizationBehavior authorization = description.Behaviors.Find<ServiceAuthorizationBehavior>(); 1060 if (authorization != null) 1061 { 1062 ServiceAuthorizationBehavior authorizationCopy = authorization.Clone(); 1063 authorizationCopy.MakeReadOnly(); 1064 this.readOnlyAuthorization = authorizationCopy; 1065 } 1066 1067 ServiceAuthenticationBehavior authentication = description.Behaviors.Find<ServiceAuthenticationBehavior>(); 1068 if (authentication != null) 1069 { 1070 ServiceAuthenticationBehavior authenticationCopy = authentication.Clone(); 1071 authentication.MakeReadOnly(); 1072 this.readOnlyAuthentication = authenticationCopy; 1073 } 1074 1075 if (ManagementExtension.IsEnabled) 1076 { 1077 ManagementExtension.OnServiceOpened(this); 1078 } 1079 1080 // log telemetry data for the current WCF service. 1081 TelemetryTraceLogging.LogSeriveKPIData(this.Description); 1082 } 1083 base.OnOpened(); 1084 1085 if (TD.ServiceHostOpenStopIsEnabled()) 1086 { 1087 TD.ServiceHostOpenStop(this.EventTraceActivity); 1088 } 1089 } 1090 OnRemoveChannelDispatcher(ChannelDispatcherBase channelDispatcher)1091 internal void OnRemoveChannelDispatcher(ChannelDispatcherBase channelDispatcher) 1092 { 1093 lock (this.ThisLock) 1094 { 1095 this.ThrowIfClosedOrOpened(); 1096 channelDispatcher.DetachInternal(this); 1097 } 1098 } 1099 OnChannelDispatcherFaulted(object sender, EventArgs e)1100 void OnChannelDispatcherFaulted(object sender, EventArgs e) 1101 { 1102 this.Fault(); 1103 } 1104 OnServiceHostFaulted(object sender, EventArgs args)1105 void OnServiceHostFaulted(object sender, EventArgs args) 1106 { 1107 if (TD.ServiceHostFaultedIsEnabled()) 1108 { 1109 TD.ServiceHostFaulted(this.EventTraceActivity, this); 1110 } 1111 1112 if (DiagnosticUtility.ShouldTraceWarning) 1113 { 1114 TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.ServiceHostFaulted, 1115 SR.GetString(SR.TraceCodeServiceHostFaulted), this); 1116 } 1117 1118 foreach (ICommunicationObject channelDispatcher in this.SnapshotChannelDispatchers()) 1119 { 1120 if (channelDispatcher.State == CommunicationState.Opened) 1121 { 1122 channelDispatcher.Abort(); 1123 } 1124 } 1125 } 1126 RaiseUnknownMessageReceived(Message message)1127 internal void RaiseUnknownMessageReceived(Message message) 1128 { 1129 try 1130 { 1131 EventHandler<UnknownMessageReceivedEventArgs> handler = UnknownMessageReceived; 1132 if (handler != null) 1133 { 1134 handler(this, new UnknownMessageReceivedEventArgs(message)); 1135 } 1136 } 1137 catch (Exception e) 1138 { 1139 if (Fx.IsFatal(e)) 1140 throw; 1141 1142 throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e); 1143 } 1144 } 1145 ReleasePerformanceCounters()1146 protected void ReleasePerformanceCounters() 1147 { 1148 if (this.servicePerformanceCounters != null) 1149 { 1150 lock (this.ThisLock) 1151 { 1152 if (this.servicePerformanceCounters != null) 1153 { 1154 this.servicePerformanceCounters.Dispose(); 1155 this.servicePerformanceCounters = null; 1156 } 1157 } 1158 } 1159 if (this.defaultPerformanceCounters != null) 1160 { 1161 lock (this.ThisLock) 1162 { 1163 if (this.defaultPerformanceCounters != null) 1164 { 1165 this.defaultPerformanceCounters.Dispose(); 1166 this.defaultPerformanceCounters = null; 1167 } 1168 } 1169 } 1170 } 1171 SnapshotChannelDispatchers()1172 ICommunicationObject[] SnapshotChannelDispatchers() 1173 { 1174 lock (this.ThisLock) 1175 { 1176 ICommunicationObject[] array = new ICommunicationObject[this.ChannelDispatchers.Count]; 1177 for (int i = 0; i < array.Length; i++) 1178 { 1179 array[i] = this.ChannelDispatchers[i]; 1180 } 1181 return array; 1182 } 1183 } 1184 UnbindInstance(InstanceContext instance)1185 internal virtual void UnbindInstance(InstanceContext instance) 1186 { 1187 this.instances.Remove(instance); 1188 if (null != this.servicePerformanceCounters) 1189 { 1190 lock (this.ThisLock) 1191 { 1192 if (null != this.servicePerformanceCounters) 1193 { 1194 this.servicePerformanceCounters.ServiceInstanceRemoved(); 1195 } 1196 } 1197 } 1198 } 1199 IncrementBusyCount()1200 internal void IncrementBusyCount() 1201 { 1202 if (AspNetEnvironment.Enabled) 1203 { 1204 AspNetEnvironment.Current.IncrementBusyCount(); 1205 Interlocked.Increment(ref this.busyCount); 1206 } 1207 1208 EventHandler handler = this.BusyCountIncremented; 1209 if (handler != null) 1210 { 1211 try 1212 { 1213 handler(this, EventArgs.Empty); 1214 } 1215 catch (Exception exception) 1216 { 1217 if (Fx.IsFatal(exception)) 1218 throw; 1219 1220 throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(exception); 1221 } 1222 } 1223 } 1224 DecrementBusyCount()1225 internal void DecrementBusyCount() 1226 { 1227 if (AspNetEnvironment.Enabled) 1228 { 1229 Interlocked.Decrement(ref this.busyCount); 1230 AspNetEnvironment.Current.DecrementBusyCount(); 1231 } 1232 } 1233 1234 internal int BusyCount 1235 { 1236 get 1237 { 1238 return this.busyCount; 1239 } 1240 } 1241 1242 class OpenAsyncResult : AsyncResult 1243 { 1244 static AsyncCompletion handleEndAfterInitializeRuntime = new AsyncCompletion(HandleEndAfterInitializeRuntime); 1245 static AsyncCompletion handleEndOpenChannelDispatchers = new AsyncCompletion(HandleEndOpenChannelDispatchers); 1246 1247 TimeoutHelper timeoutHelper; 1248 ServiceHostBase host; 1249 OpenAsyncResult(ServiceHostBase host, TimeSpan timeout, AsyncCallback callback, object state)1250 public OpenAsyncResult(ServiceHostBase host, TimeSpan timeout, AsyncCallback callback, object state) 1251 : base(callback, state) 1252 { 1253 this.timeoutHelper = new TimeoutHelper(timeout); 1254 this.host = host; 1255 1256 if (ProcessAfterInitializeRuntime()) 1257 { 1258 Complete(true); 1259 } 1260 } 1261 ProcessAfterInitializeRuntime()1262 bool ProcessAfterInitializeRuntime() 1263 { 1264 IAsyncResult result = this.host.BeginAfterInitializeRuntime( 1265 this.timeoutHelper.RemainingTime(), PrepareAsyncCompletion(handleEndAfterInitializeRuntime), this); 1266 1267 return SyncContinue(result); 1268 } 1269 HandleEndAfterInitializeRuntime(IAsyncResult result)1270 static bool HandleEndAfterInitializeRuntime(IAsyncResult result) 1271 { 1272 OpenAsyncResult thisPtr = (OpenAsyncResult)result.AsyncState; 1273 thisPtr.host.EndAfterInitializeRuntime(result); 1274 1275 return thisPtr.ProcessOpenChannelDispatchers(); 1276 } 1277 ProcessOpenChannelDispatchers()1278 bool ProcessOpenChannelDispatchers() 1279 { 1280 IAsyncResult result = this.host.BeginOpenChannelDispatchers( 1281 this.timeoutHelper.RemainingTime(), PrepareAsyncCompletion(handleEndOpenChannelDispatchers), this); 1282 1283 return SyncContinue(result); 1284 } 1285 HandleEndOpenChannelDispatchers(IAsyncResult result)1286 static bool HandleEndOpenChannelDispatchers(IAsyncResult result) 1287 { 1288 OpenAsyncResult thisPtr = (OpenAsyncResult)result.AsyncState; 1289 thisPtr.host.EndOpenChannelDispatchers(result); 1290 1291 return true; 1292 } 1293 End(IAsyncResult result)1294 public static void End(IAsyncResult result) 1295 { 1296 AsyncResult.End<OpenAsyncResult>(result); 1297 } 1298 } 1299 1300 class CloseAsyncResult : AsyncResult 1301 { 1302 ServiceHostBase serviceHost; 1303 TimeoutHelper timeoutHelper; 1304 CloseAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, ServiceHostBase serviceHost)1305 public CloseAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, ServiceHostBase serviceHost) 1306 : base(callback, state) 1307 { 1308 this.timeoutHelper = new TimeoutHelper(timeout); 1309 this.serviceHost = serviceHost; 1310 1311 if (ManagementExtension.IsEnabled && null != serviceHost.Description) 1312 { 1313 ManagementExtension.OnServiceClosing(serviceHost); 1314 } 1315 1316 this.CloseListeners(true); 1317 } 1318 CloseListeners(bool completedSynchronously)1319 void CloseListeners(bool completedSynchronously) 1320 { 1321 List<ICommunicationObject> listeners = new List<ICommunicationObject>(); 1322 for (int i = 0; i < this.serviceHost.ChannelDispatchers.Count; i++) 1323 { 1324 if (this.serviceHost.ChannelDispatchers[i].Listener != null) 1325 { 1326 listeners.Add(this.serviceHost.ChannelDispatchers[i].Listener); 1327 } 1328 } 1329 1330 AsyncCallback callback = Fx.ThunkCallback(this.CloseListenersCallback); 1331 TimeSpan timeout = this.timeoutHelper.RemainingTime(); 1332 Exception exception = null; 1333 IAsyncResult result = null; 1334 try 1335 { 1336 result = new CloseCollectionAsyncResult(timeout, callback, this, listeners); 1337 } 1338 catch (Exception e) 1339 { 1340 if (Fx.IsFatal(e) || completedSynchronously) 1341 { 1342 throw; 1343 } 1344 exception = e; 1345 } 1346 1347 if (exception != null) 1348 { 1349 this.CallComplete(completedSynchronously, exception); 1350 } 1351 else if (result.CompletedSynchronously) 1352 { 1353 this.FinishCloseListeners(result, completedSynchronously); 1354 } 1355 } 1356 CloseListenersCallback(IAsyncResult result)1357 void CloseListenersCallback(IAsyncResult result) 1358 { 1359 if (!result.CompletedSynchronously) 1360 { 1361 ((CloseAsyncResult)result.AsyncState).FinishCloseListeners(result, false); 1362 } 1363 } 1364 FinishCloseListeners(IAsyncResult result, bool completedSynchronously)1365 void FinishCloseListeners(IAsyncResult result, bool completedSynchronously) 1366 { 1367 Exception exception = null; 1368 try 1369 { 1370 CloseCollectionAsyncResult.End(result); 1371 } 1372 catch (Exception e) 1373 { 1374 if (Fx.IsFatal(e) || completedSynchronously) 1375 { 1376 throw; 1377 } 1378 exception = e; 1379 } 1380 1381 if (exception != null) 1382 { 1383 this.CallComplete(completedSynchronously, exception); 1384 } 1385 else 1386 { 1387 this.CloseInput(completedSynchronously); 1388 } 1389 } 1390 1391 // Wait for existing work to complete CloseInput(bool completedSynchronously)1392 void CloseInput(bool completedSynchronously) 1393 { 1394 AsyncCallback callback = Fx.ThunkCallback(this.CloseInputCallback); 1395 Exception exception = null; 1396 IAsyncResult result = null; 1397 1398 try 1399 { 1400 for (int i = 0; i < this.serviceHost.ChannelDispatchers.Count; i++) 1401 { 1402 ChannelDispatcherBase dispatcher = this.serviceHost.ChannelDispatchers[i]; 1403 dispatcher.CloseInput(this.timeoutHelper.RemainingTime()); 1404 } 1405 1406 result = this.serviceHost.instances.BeginCloseInput(this.timeoutHelper.RemainingTime(), callback, this); 1407 } 1408 catch (Exception e) 1409 { 1410 if (Fx.IsFatal(e) || completedSynchronously) 1411 { 1412 throw; 1413 } 1414 1415 exception = e; 1416 } 1417 1418 if (exception != null) 1419 { 1420 // Any exception during async processing causes this 1421 // async callback to report the error and then relies on 1422 // Abort to cleanup any unclosed channels or instance contexts. 1423 FxTrace.Exception.AsWarning(exception); 1424 this.CallComplete(completedSynchronously, exception); 1425 } 1426 else if (result.CompletedSynchronously) 1427 { 1428 this.FinishCloseInput(result, completedSynchronously); 1429 } 1430 } 1431 CloseInputCallback(IAsyncResult result)1432 void CloseInputCallback(IAsyncResult result) 1433 { 1434 if (!result.CompletedSynchronously) 1435 { 1436 ((CloseAsyncResult)result.AsyncState).FinishCloseInput(result, false); 1437 } 1438 } 1439 FinishCloseInput(IAsyncResult result, bool completedSynchronously)1440 void FinishCloseInput(IAsyncResult result, bool completedSynchronously) 1441 { 1442 Exception exception = null; 1443 try 1444 { 1445 serviceHost.instances.EndCloseInput(result); 1446 } 1447 catch (Exception e) 1448 { 1449 if (Fx.IsFatal(e) || completedSynchronously) 1450 { 1451 throw; 1452 } 1453 exception = e; 1454 } 1455 1456 if (exception != null) 1457 { 1458 this.CallComplete(completedSynchronously, exception); 1459 } 1460 else 1461 { 1462 this.CloseInstances(completedSynchronously); 1463 } 1464 } 1465 1466 // Close instances (closes contexts/channels) CloseInstances(bool completedSynchronously)1467 void CloseInstances(bool completedSynchronously) 1468 { 1469 AsyncCallback callback = Fx.ThunkCallback(this.CloseInstancesCallback); 1470 TimeSpan timeout = this.timeoutHelper.RemainingTime(); 1471 Exception exception = null; 1472 IAsyncResult result = null; 1473 1474 try 1475 { 1476 result = this.serviceHost.instances.BeginClose(timeout, callback, this); 1477 } 1478 catch (Exception e) 1479 { 1480 if (Fx.IsFatal(e) || completedSynchronously) 1481 { 1482 throw; 1483 } 1484 exception = e; 1485 } 1486 1487 if (exception != null) 1488 { 1489 this.CallComplete(completedSynchronously, exception); 1490 } 1491 else if (result.CompletedSynchronously) 1492 { 1493 this.FinishCloseInstances(result, completedSynchronously); 1494 } 1495 } 1496 CloseInstancesCallback(IAsyncResult result)1497 void CloseInstancesCallback(IAsyncResult result) 1498 { 1499 if (!result.CompletedSynchronously) 1500 { 1501 ((CloseAsyncResult)result.AsyncState).FinishCloseInstances(result, false); 1502 } 1503 } 1504 FinishCloseInstances(IAsyncResult result, bool completedSynchronously)1505 void FinishCloseInstances(IAsyncResult result, bool completedSynchronously) 1506 { 1507 Exception exception = null; 1508 try 1509 { 1510 this.serviceHost.instances.EndClose(result); 1511 } 1512 catch (Exception e) 1513 { 1514 if (Fx.IsFatal(e) || completedSynchronously) 1515 { 1516 throw; 1517 } 1518 exception = e; 1519 } 1520 1521 if (exception != null) 1522 { 1523 this.CallComplete(completedSynchronously, exception); 1524 } 1525 else 1526 { 1527 this.CloseChannelDispatchers(completedSynchronously); 1528 } 1529 } 1530 CloseChannelDispatchers(bool completedSynchronously)1531 void CloseChannelDispatchers(bool completedSynchronously) 1532 { 1533 IList<ICommunicationObject> channelDispatchers = this.serviceHost.SnapshotChannelDispatchers(); 1534 AsyncCallback callback = Fx.ThunkCallback(this.CloseChannelDispatchersCallback); 1535 TimeSpan timeout = this.timeoutHelper.RemainingTime(); 1536 Exception exception = null; 1537 IAsyncResult result = null; 1538 try 1539 { 1540 result = new CloseCollectionAsyncResult(timeout, callback, this, channelDispatchers); 1541 } 1542 catch (Exception e) 1543 { 1544 if (Fx.IsFatal(e) || completedSynchronously) 1545 { 1546 throw; 1547 } 1548 exception = e; 1549 } 1550 1551 if (exception != null) 1552 { 1553 this.CallComplete(completedSynchronously, exception); 1554 } 1555 else if (result.CompletedSynchronously) 1556 { 1557 this.FinishCloseChannelDispatchers(result, completedSynchronously); 1558 } 1559 } 1560 CloseChannelDispatchersCallback(IAsyncResult result)1561 void CloseChannelDispatchersCallback(IAsyncResult result) 1562 { 1563 if (!result.CompletedSynchronously) 1564 { 1565 ((CloseAsyncResult)result.AsyncState).FinishCloseChannelDispatchers(result, false); 1566 } 1567 } 1568 FinishCloseChannelDispatchers(IAsyncResult result, bool completedSynchronously)1569 void FinishCloseChannelDispatchers(IAsyncResult result, bool completedSynchronously) 1570 { 1571 Exception exception = null; 1572 try 1573 { 1574 CloseCollectionAsyncResult.End(result); 1575 } 1576 catch (Exception e) 1577 { 1578 if (Fx.IsFatal(e) || completedSynchronously) 1579 { 1580 throw; 1581 } 1582 exception = e; 1583 } 1584 1585 this.CallComplete(completedSynchronously, exception); 1586 } 1587 CallComplete(bool completedSynchronously, Exception exception)1588 void CallComplete(bool completedSynchronously, Exception exception) 1589 { 1590 this.Complete(completedSynchronously, exception); 1591 } 1592 End(IAsyncResult result)1593 public static void End(IAsyncResult result) 1594 { 1595 AsyncResult.End<CloseAsyncResult>(result); 1596 } 1597 } 1598 1599 class ImplementedContractsContractResolver : IContractResolver 1600 { 1601 IDictionary<string, ContractDescription> implementedContracts; 1602 ImplementedContractsContractResolver(IDictionary<string, ContractDescription> implementedContracts)1603 public ImplementedContractsContractResolver(IDictionary<string, ContractDescription> implementedContracts) 1604 { 1605 this.implementedContracts = implementedContracts; 1606 } 1607 ResolveContract(string contractName)1608 public ContractDescription ResolveContract(string contractName) 1609 { 1610 return this.implementedContracts != null && this.implementedContracts.ContainsKey(contractName) ? this.implementedContracts[contractName] : null; 1611 } 1612 } 1613 1614 internal class ServiceAndBehaviorsContractResolver : IContractResolver 1615 { 1616 IContractResolver serviceResolver; 1617 Dictionary<string, ContractDescription> behaviorContracts; 1618 1619 public Dictionary<string, ContractDescription> BehaviorContracts 1620 { 1621 get { return behaviorContracts; } 1622 } 1623 ServiceAndBehaviorsContractResolver(IContractResolver serviceResolver)1624 public ServiceAndBehaviorsContractResolver(IContractResolver serviceResolver) 1625 { 1626 this.serviceResolver = serviceResolver; 1627 behaviorContracts = new Dictionary<string, ContractDescription>(); 1628 } 1629 ResolveContract(string contractName)1630 public ContractDescription ResolveContract(string contractName) 1631 { 1632 ContractDescription contract = serviceResolver.ResolveContract(contractName); 1633 1634 if (contract == null) 1635 { 1636 contract = this.behaviorContracts.ContainsKey(contractName) ? this.behaviorContracts[contractName] : null; 1637 } 1638 1639 return contract; 1640 } 1641 AddBehaviorContractsToResolver(KeyedByTypeCollection<IServiceBehavior> behaviors)1642 public void AddBehaviorContractsToResolver(KeyedByTypeCollection<IServiceBehavior> behaviors) 1643 { 1644 // It would be nice to make this loop over all Behaviors... someday. 1645 if (behaviors != null && behaviors.Contains(typeof(ServiceMetadataBehavior))) 1646 { 1647 behaviors.Find<ServiceMetadataBehavior>().AddImplementedContracts(this); 1648 } 1649 } 1650 } 1651 } 1652 1653 public class ServiceHost : ServiceHostBase 1654 { 1655 object singletonInstance; 1656 Type serviceType; 1657 ReflectedContractCollection reflectedContracts; 1658 IDisposable disposableInstance; 1659 ServiceHost()1660 protected ServiceHost() 1661 { 1662 } 1663 ServiceHost(Type serviceType, params Uri[] baseAddresses)1664 public ServiceHost(Type serviceType, params Uri[] baseAddresses) 1665 { 1666 if (serviceType == null) 1667 { 1668 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serviceType")); 1669 } 1670 1671 this.serviceType = serviceType; 1672 using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null) 1673 { 1674 if (DiagnosticUtility.ShouldUseActivity) 1675 { 1676 ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructServiceHost, serviceType.FullName), ActivityType.Construct); 1677 } 1678 1679 InitializeDescription(serviceType, new UriSchemeKeyedCollection(baseAddresses)); 1680 } 1681 } 1682 ServiceHost(object singletonInstance, params Uri[] baseAddresses)1683 public ServiceHost(object singletonInstance, params Uri[] baseAddresses) 1684 { 1685 if (singletonInstance == null) 1686 { 1687 throw new ArgumentNullException("singletonInstance"); 1688 } 1689 1690 this.singletonInstance = singletonInstance; 1691 this.serviceType = singletonInstance.GetType(); 1692 using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null) 1693 { 1694 if (DiagnosticUtility.ShouldUseActivity) 1695 { 1696 ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructServiceHost, serviceType.FullName), ActivityType.Construct); 1697 } 1698 1699 InitializeDescription(singletonInstance, new UriSchemeKeyedCollection(baseAddresses)); 1700 } 1701 } 1702 1703 public object SingletonInstance 1704 { 1705 get 1706 { 1707 return this.singletonInstance; 1708 } 1709 } 1710 1711 internal override object DisposableInstance 1712 { 1713 get 1714 { 1715 return this.disposableInstance; 1716 } 1717 } 1718 AddServiceEndpoint(Type implementedContract, Binding binding, string address)1719 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address) 1720 { 1721 return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null); 1722 } 1723 AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri)1724 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri) 1725 { 1726 if (address == null) 1727 { 1728 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("address")); 1729 } 1730 1731 ServiceEndpoint endpoint = this.AddServiceEndpoint(implementedContract, binding, new Uri(address, UriKind.RelativeOrAbsolute)); 1732 if (listenUri != null) 1733 { 1734 listenUri = MakeAbsoluteUri(listenUri, binding); 1735 endpoint.ListenUri = listenUri; 1736 } 1737 return endpoint; 1738 } 1739 AddServiceEndpoint(Type implementedContract, Binding binding, Uri address)1740 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address) 1741 { 1742 return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null); 1743 } 1744 ValidateContractType(Type implementedContract, ReflectedAndBehaviorContractCollection reflectedAndBehaviorContracts)1745 void ValidateContractType(Type implementedContract, ReflectedAndBehaviorContractCollection reflectedAndBehaviorContracts) 1746 { 1747 if (!implementedContract.IsDefined(typeof(ServiceContractAttribute), false)) 1748 { 1749 #pragma warning suppress 56506 // implementedContract is never null at this point 1750 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxServiceContractAttributeNotFound, implementedContract.FullName))); 1751 } 1752 if (!reflectedAndBehaviorContracts.Contains(implementedContract)) 1753 { 1754 if (implementedContract == typeof(IMetadataExchange)) 1755 #pragma warning suppress 56506 // ServiceType is never null at this point 1756 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFoundIMetadataExchange, this.serviceType.FullName))); 1757 else 1758 #pragma warning suppress 56506 // implementedContract and ServiceType are never null at this point 1759 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFound2, implementedContract.FullName, this.serviceType.FullName))); 1760 } 1761 } 1762 AddServiceEndpoint(Type implementedContract, Binding binding, Uri address, Uri listenUri)1763 public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address, Uri listenUri) 1764 { 1765 if (implementedContract == null) 1766 { 1767 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("implementedContract")); 1768 } 1769 if (this.reflectedContracts == null) 1770 { 1771 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractsNotInitialized1, implementedContract.FullName))); 1772 } 1773 ReflectedAndBehaviorContractCollection reflectedAndBehaviorContracts = new ReflectedAndBehaviorContractCollection(this.reflectedContracts, this.Description.Behaviors); 1774 ValidateContractType(implementedContract, reflectedAndBehaviorContracts); 1775 ServiceEndpoint endpoint = AddServiceEndpoint(reflectedAndBehaviorContracts.GetConfigKey(implementedContract), binding, address); 1776 if (listenUri != null) 1777 { 1778 listenUri = MakeAbsoluteUri(listenUri, binding); 1779 endpoint.ListenUri = listenUri; 1780 } 1781 return endpoint; 1782 } 1783 AddDefaultEndpoints(Binding defaultBinding, List<ServiceEndpoint> defaultEndpoints)1784 internal override void AddDefaultEndpoints(Binding defaultBinding, List<ServiceEndpoint> defaultEndpoints) 1785 { 1786 // don't generate endpoints for contracts that serve as the base type for other reflected contracts 1787 List<ContractDescription> mostSpecificContracts = new List<ContractDescription>(); 1788 for (int i = 0; i < this.reflectedContracts.Count; i++) 1789 { 1790 bool addContractEndpoint = true; 1791 ContractDescription contract = this.reflectedContracts[i]; 1792 Type contractType = contract.ContractType; 1793 if (contractType != null) 1794 { 1795 for (int j = 0; j < this.reflectedContracts.Count; j++) 1796 { 1797 ContractDescription otherContract = this.reflectedContracts[j]; 1798 Type otherContractType = otherContract.ContractType; 1799 if (i == j || otherContractType == null) 1800 { 1801 continue; 1802 } 1803 if (contractType.IsAssignableFrom(otherContractType)) 1804 { 1805 addContractEndpoint = false; 1806 break; 1807 } 1808 } 1809 } 1810 if (addContractEndpoint) 1811 { 1812 mostSpecificContracts.Add(contract); 1813 } 1814 } 1815 1816 foreach (ContractDescription contract in mostSpecificContracts) 1817 { 1818 ServiceEndpoint endpoint = AddServiceEndpoint(contract.ConfigurationName, defaultBinding, string.Empty); 1819 ConfigLoader.LoadDefaultEndpointBehaviors(endpoint); 1820 defaultEndpoints.Add(endpoint); 1821 } 1822 } 1823 1824 // Run static Configure method on service type if it exists, else load configuration from Web.config/App.config ApplyConfiguration()1825 protected override void ApplyConfiguration() 1826 { 1827 // Load from static Configure method if it exists with the right signature 1828 Type serviceType = this.Description.ServiceType; 1829 if (serviceType != null) 1830 { 1831 MethodInfo configure = GetConfigureMethod(serviceType); 1832 if (configure != null) 1833 { 1834 // load <host> config 1835 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts)); 1836 LoadHostConfigurationInternal(configLoader, this.Description, this.Description.ConfigurationName); 1837 1838 // Invoke configure method for service 1839 ServiceConfiguration configuration = new ServiceConfiguration(this); 1840 InvokeConfigure(configure, configuration); 1841 1842 return; 1843 } 1844 } 1845 1846 // else just load from Web.config/App.config 1847 base.ApplyConfiguration(); 1848 } 1849 1850 // Find the Configure method with the required signature, closest to serviceType in the type hierarchy GetConfigureMethod(Type serviceType)1851 static MethodInfo GetConfigureMethod(Type serviceType) 1852 { 1853 // Use recursion instead of BindingFlags.FlattenHierarchy because we require return type to be void 1854 1855 // base case: all Types are rooted in object eventually 1856 if (serviceType == typeof(object)) 1857 { 1858 return null; 1859 } 1860 1861 // signature: "public static void Configure(ServiceConfiguration)" 1862 MethodInfo configure = serviceType.GetMethod("Configure", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(ServiceConfiguration) }, null); 1863 1864 if (configure != null && configure.ReturnType == typeof(void)) 1865 { 1866 return configure; 1867 } 1868 else 1869 { 1870 return GetConfigureMethod(serviceType.BaseType); 1871 } 1872 } 1873 InvokeConfigure(MethodInfo configureMethod, ServiceConfiguration configuration)1874 static void InvokeConfigure(MethodInfo configureMethod, ServiceConfiguration configuration) 1875 { 1876 Action<ServiceConfiguration> call = Delegate.CreateDelegate(typeof(Action<ServiceConfiguration>), configureMethod) as Action<ServiceConfiguration>; 1877 call(configuration); 1878 } 1879 1880 // called from ServiceConfiguration.LoadFromConfiguration() LoadFromConfiguration()1881 internal void LoadFromConfiguration() 1882 { 1883 if (this.Description == null) 1884 { 1885 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotApplyConfigurationWithoutDescription))); 1886 } 1887 1888 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts)); 1889 1890 // Call the overload of LoadConfigurationSectionInternal which looks up the serviceElement from ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None) 1891 LoadConfigurationSectionExceptHostInternal(configLoader, this.Description, this.Description.ConfigurationName); 1892 EnsureAuthenticationAuthorizationDebug(this.Description); 1893 } 1894 1895 // called from ServiceConfiguration.LoadFromConfiguration(configuration) LoadFromConfiguration(System.Configuration.Configuration configuration)1896 internal void LoadFromConfiguration(System.Configuration.Configuration configuration) 1897 { 1898 if (this.Description == null) 1899 { 1900 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotApplyConfigurationWithoutDescription))); 1901 } 1902 1903 ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts)); 1904 1905 // Look up the serviceElement explicitly on configuration, then call the overload of LoadConfigurationSectionInternal that loads the rest of the config from the same configuration as serviceElement 1906 ServicesSection servicesSection = (ServicesSection)configuration.GetSection(ConfigurationStrings.ServicesSectionPath); 1907 ServiceElement serviceElement = configLoader.LookupService(this.Description.ConfigurationName, servicesSection); 1908 configLoader.LoadServiceDescription(this, this.Description, serviceElement, this.LoadConfigurationSectionHelper, skipHost: true); 1909 1910 EnsureAuthenticationAuthorizationDebug(this.Description); 1911 } 1912 1913 // Load only "host" section within "service" tag 1914 [Fx.Tag.SecurityNote(Critical = "Calls LookupService which is critical.", 1915 Safe = "Doesn't leak ServiceElement out of SecurityCritical code.")] 1916 [SecuritySafeCritical] LoadHostConfigurationInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName)1917 void LoadHostConfigurationInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName) 1918 { 1919 ServiceElement serviceSection = configLoader.LookupService(configurationName); 1920 if (serviceSection != null) 1921 { 1922 configLoader.LoadHostConfig(serviceSection, this, (addr => this.InternalBaseAddresses.Add(addr))); 1923 } 1924 } 1925 1926 // Load service description for service from config, but skip "host" section within "service" tag 1927 [Fx.Tag.SecurityNote(Critical = "Calls LookupService which is critical.", 1928 Safe = "Doesn't leak ServiceElement out of SecurityCritical code.")] 1929 [SecuritySafeCritical] LoadConfigurationSectionExceptHostInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName)1930 void LoadConfigurationSectionExceptHostInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName) 1931 { 1932 ServiceElement serviceSection = configLoader.LookupService(configurationName); 1933 configLoader.LoadServiceDescription(this, description, serviceSection, this.LoadConfigurationSectionHelper, skipHost: true); 1934 } 1935 1936 internal override string CloseActivityName 1937 { 1938 get { return SR.GetString(SR.ActivityCloseServiceHost, this.serviceType.FullName); } 1939 } 1940 1941 internal override string OpenActivityName 1942 { 1943 get { return SR.GetString(SR.ActivityOpenServiceHost, this.serviceType.FullName); } 1944 } 1945 CreateDescription(out IDictionary<string, ContractDescription> implementedContracts)1946 protected override ServiceDescription CreateDescription(out IDictionary<string, ContractDescription> implementedContracts) 1947 { 1948 if (this.serviceType == null) 1949 { 1950 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostCannotCreateDescriptionWithoutServiceType))); 1951 } 1952 1953 ServiceDescription description; 1954 if (this.SingletonInstance != null) 1955 { 1956 description = ServiceDescription.GetService(this.SingletonInstance); 1957 } 1958 else 1959 { 1960 description = ServiceDescription.GetService(this.serviceType); 1961 } 1962 ServiceBehaviorAttribute serviceBehavior = description.Behaviors.Find<ServiceBehaviorAttribute>(); 1963 object serviceInstanceUsedAsABehavior = serviceBehavior.GetWellKnownSingleton(); 1964 if (serviceInstanceUsedAsABehavior == null) 1965 { 1966 serviceInstanceUsedAsABehavior = serviceBehavior.GetHiddenSingleton(); 1967 this.disposableInstance = serviceInstanceUsedAsABehavior as IDisposable; 1968 } 1969 1970 if ((typeof(IServiceBehavior).IsAssignableFrom(this.serviceType) || typeof(IContractBehavior).IsAssignableFrom(this.serviceType)) 1971 && serviceInstanceUsedAsABehavior == null) 1972 { 1973 serviceInstanceUsedAsABehavior = ServiceDescription.CreateImplementation(this.serviceType); 1974 this.disposableInstance = serviceInstanceUsedAsABehavior as IDisposable; 1975 } 1976 1977 if (this.SingletonInstance == null) 1978 { 1979 if (serviceInstanceUsedAsABehavior is IServiceBehavior) 1980 { 1981 description.Behaviors.Add((IServiceBehavior)serviceInstanceUsedAsABehavior); 1982 } 1983 } 1984 1985 ReflectedContractCollection reflectedContracts = new ReflectedContractCollection(); 1986 List<Type> interfaces = ServiceReflector.GetInterfaces(this.serviceType); 1987 for (int i = 0; i < interfaces.Count; i++) 1988 { 1989 Type contractType = interfaces[i]; 1990 if (!reflectedContracts.Contains(contractType)) 1991 { 1992 ContractDescription contract = null; 1993 if (serviceInstanceUsedAsABehavior != null) 1994 { 1995 contract = ContractDescription.GetContract(contractType, serviceInstanceUsedAsABehavior); 1996 } 1997 else 1998 { 1999 contract = ContractDescription.GetContract(contractType, this.serviceType); 2000 } 2001 2002 reflectedContracts.Add(contract); 2003 Collection<ContractDescription> inheritedContracts = contract.GetInheritedContracts(); 2004 for (int j = 0; j < inheritedContracts.Count; j++) 2005 { 2006 ContractDescription inheritedContract = inheritedContracts[j]; 2007 if (!reflectedContracts.Contains(inheritedContract.ContractType)) 2008 { 2009 reflectedContracts.Add(inheritedContract); 2010 } 2011 } 2012 } 2013 } 2014 this.reflectedContracts = reflectedContracts; 2015 2016 implementedContracts = reflectedContracts.ToImplementedContracts(); 2017 return description; 2018 } 2019 InitializeDescription(object singletonInstance, UriSchemeKeyedCollection baseAddresses)2020 protected void InitializeDescription(object singletonInstance, UriSchemeKeyedCollection baseAddresses) 2021 { 2022 if (singletonInstance == null) 2023 { 2024 throw new ArgumentNullException("singletonInstance"); 2025 } 2026 2027 this.singletonInstance = singletonInstance; 2028 InitializeDescription(singletonInstance.GetType(), baseAddresses); 2029 } 2030 InitializeDescription(Type serviceType, UriSchemeKeyedCollection baseAddresses)2031 protected void InitializeDescription(Type serviceType, UriSchemeKeyedCollection baseAddresses) 2032 { 2033 if (serviceType == null) 2034 { 2035 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serviceType")); 2036 } 2037 2038 this.serviceType = serviceType; 2039 2040 base.InitializeDescription(baseAddresses); 2041 } 2042 OnClosed()2043 protected override void OnClosed() 2044 { 2045 base.OnClosed(); 2046 if (this.disposableInstance != null) 2047 { 2048 this.disposableInstance.Dispose(); 2049 } 2050 } 2051 2052 class ReflectedContractCollection : KeyedCollection<Type, ContractDescription> 2053 { ReflectedContractCollection()2054 public ReflectedContractCollection() 2055 : base(null, 4) 2056 { 2057 } 2058 GetKeyForItem(ContractDescription item)2059 protected override Type GetKeyForItem(ContractDescription item) 2060 { 2061 if (item == null) 2062 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("item"); 2063 2064 return item.ContractType; 2065 } 2066 ToImplementedContracts()2067 public IDictionary<string, ContractDescription> ToImplementedContracts() 2068 { 2069 Dictionary<string, ContractDescription> implementedContracts = new Dictionary<string, ContractDescription>(); 2070 foreach (ContractDescription contract in this.Items) 2071 { 2072 implementedContracts.Add(GetConfigKey(contract), contract); 2073 } 2074 return implementedContracts; 2075 } 2076 GetConfigKey(ContractDescription contract)2077 internal static string GetConfigKey(ContractDescription contract) 2078 { 2079 return contract.ConfigurationName; 2080 } 2081 } 2082 2083 class ReflectedAndBehaviorContractCollection 2084 { 2085 ReflectedContractCollection reflectedContracts; 2086 KeyedByTypeCollection<IServiceBehavior> behaviors; ReflectedAndBehaviorContractCollection(ReflectedContractCollection reflectedContracts, KeyedByTypeCollection<IServiceBehavior> behaviors)2087 public ReflectedAndBehaviorContractCollection(ReflectedContractCollection reflectedContracts, KeyedByTypeCollection<IServiceBehavior> behaviors) 2088 { 2089 this.reflectedContracts = reflectedContracts; 2090 this.behaviors = behaviors; 2091 } 2092 Contains(Type implementedContract)2093 internal bool Contains(Type implementedContract) 2094 { 2095 if (this.reflectedContracts.Contains(implementedContract)) 2096 { 2097 return true; 2098 } 2099 2100 if (this.behaviors.Contains(typeof(ServiceMetadataBehavior)) && ServiceMetadataBehavior.IsMetadataImplementedType(implementedContract)) 2101 { 2102 return true; 2103 } 2104 2105 return false; 2106 } 2107 GetConfigKey(Type implementedContract)2108 internal string GetConfigKey(Type implementedContract) 2109 { 2110 if (this.reflectedContracts.Contains(implementedContract)) 2111 { 2112 return ReflectedContractCollection.GetConfigKey(reflectedContracts[implementedContract]); 2113 } 2114 2115 if (this.behaviors.Contains(typeof(ServiceMetadataBehavior)) && ServiceMetadataBehavior.IsMetadataImplementedType(implementedContract)) 2116 { 2117 return ServiceMetadataBehavior.MexContractName; 2118 } 2119 2120 Fx.Assert("Calls to GetConfigKey are preceeded by calls to Contains."); 2121 #pragma warning suppress 56506 // implementedContract is never null at this point 2122 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFound2, implementedContract.FullName, string.Empty))); 2123 2124 } 2125 } 2126 } 2127 } 2128