1 //------------------------------------------------------------ 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //------------------------------------------------------------ 4 namespace System.ServiceModel.Channels 5 { 6 using System.Collections.Generic; 7 using System.ComponentModel; 8 using System.Diagnostics; 9 using System.Globalization; 10 using System.Net; 11 using System.Runtime; 12 using System.Runtime.InteropServices; 13 using System.Runtime.Serialization; 14 using System.ServiceModel; 15 using System.ServiceModel.Description; 16 using System.ServiceModel.Dispatcher; 17 using System.ServiceModel.PeerResolvers; 18 using System.ServiceModel.Security; 19 using System.Threading; 20 using System.Xml; 21 22 class PeerQuotaHelper 23 { 24 int enqueuedCount = 0; 25 int quota = 64; 26 AutoResetEvent waiter = new AutoResetEvent(false); 27 PeerQuotaHelper(int limit)28 public PeerQuotaHelper(int limit) 29 { 30 this.quota = limit; 31 } 32 ReadyToEnqueueItem()33 public void ReadyToEnqueueItem() 34 { 35 int value = Interlocked.Increment(ref enqueuedCount); 36 if (value > quota) 37 { 38 waiter.WaitOne(); 39 } 40 } 41 ItemDequeued()42 public void ItemDequeued() 43 { 44 int value = Interlocked.Decrement(ref enqueuedCount); 45 Fx.Assert(value >= 0, "queue below empty"); 46 if (value >= quota) 47 { 48 waiter.Set(); 49 } 50 } 51 52 } 53 54 class PeerNodeConfig 55 { 56 int connectTimeout; 57 MessageEncoder encoder; 58 PeerNodeAddress listenAddress; // EPR + IP addresses 59 IPAddress listenIPAddress; 60 Uri listenUri; 61 long maxReceivedMessageSize; 62 int minNeighbors; //Neighbor parameters 63 int idealNeighbors; 64 int maxNeighbors; 65 int maxReferrals; 66 int maxReferralCacheSize; 67 int maxResolveAddresses; 68 string meshId; 69 PeerMessagePropagationFilter messagePropagationFilter; 70 ulong nodeId; 71 int port; 72 PeerResolver resolver; 73 int maintainerInterval; 74 TimeSpan maintainerRetryInterval; 75 TimeSpan maintainerTimeout; 76 TimeSpan unregisterTimeout; 77 PeerSecurityManager securityManager; 78 int maxIncomingConcurrentCalls = 128; 79 int maxConcurrentSessions = 64; 80 XmlDictionaryReaderQuotas readerQuotas = new XmlDictionaryReaderQuotas(); 81 long maxBufferPoolSize; 82 int maxSendQueueSize = 128; 83 PeerNodeConfig(string meshId, ulong nodeId, PeerResolver resolver, PeerMessagePropagationFilter messagePropagationFilter, MessageEncoder encoder, Uri listenUri, IPAddress listenIPAddress, int port, long maxReceivedMessageSize, int minNeighbors, int idealNeighbors, int maxNeighbors, int maxReferrals, int connectTimeout, int maintainerInterval, PeerSecurityManager securityManager, XmlDictionaryReaderQuotas readerQuotas, long maxBufferPool, int maxSendQueueSize, int maxReceiveQueueSize)84 public PeerNodeConfig(string meshId, ulong nodeId, 85 PeerResolver resolver, 86 PeerMessagePropagationFilter messagePropagationFilter, 87 MessageEncoder encoder, 88 Uri listenUri, IPAddress listenIPAddress, int port, 89 long maxReceivedMessageSize, 90 int minNeighbors, int idealNeighbors, int maxNeighbors, 91 int maxReferrals, 92 int connectTimeout, 93 int maintainerInterval, 94 PeerSecurityManager securityManager, 95 XmlDictionaryReaderQuotas readerQuotas, 96 long maxBufferPool, 97 int maxSendQueueSize, 98 int maxReceiveQueueSize) 99 { 100 this.connectTimeout = connectTimeout; 101 this.listenIPAddress = listenIPAddress; 102 this.listenUri = listenUri; 103 this.maxReceivedMessageSize = maxReceivedMessageSize; 104 this.minNeighbors = minNeighbors; 105 this.idealNeighbors = idealNeighbors; 106 this.maxNeighbors = maxNeighbors; 107 this.maxReferrals = maxReferrals; 108 this.maxReferralCacheSize = PeerTransportConstants.MaxReferralCacheSize; 109 this.maxResolveAddresses = PeerTransportConstants.MaxResolveAddresses; 110 this.meshId = meshId; 111 this.encoder = encoder; 112 this.messagePropagationFilter = messagePropagationFilter; 113 this.nodeId = nodeId; 114 this.port = port; 115 this.resolver = resolver; 116 this.maintainerInterval = maintainerInterval; 117 this.maintainerRetryInterval = new TimeSpan(PeerTransportConstants.MaintainerRetryInterval * 10000); 118 this.maintainerTimeout = new TimeSpan(PeerTransportConstants.MaintainerTimeout * 10000); 119 this.unregisterTimeout = new TimeSpan(PeerTransportConstants.UnregisterTimeout * 10000); 120 this.securityManager = securityManager; 121 readerQuotas.CopyTo(this.readerQuotas); 122 this.maxBufferPoolSize = maxBufferPool; 123 this.maxIncomingConcurrentCalls = maxReceiveQueueSize; 124 this.maxSendQueueSize = maxSendQueueSize; 125 } 126 127 internal PeerSecurityManager SecurityManager 128 { 129 get { return securityManager; } 130 } 131 132 public int ConnectTimeout 133 { 134 get { return connectTimeout; } 135 } 136 137 public IPAddress ListenIPAddress 138 { 139 get { return listenIPAddress; } 140 } 141 142 public int ListenerPort 143 { 144 get { return listenAddress.EndpointAddress.Uri.Port; } 145 } 146 147 public Uri ListenUri 148 { 149 get { return listenUri; } 150 } 151 152 public int IdealNeighbors 153 { 154 get { return idealNeighbors; } 155 } 156 157 public int MaintainerInterval 158 { 159 get { return maintainerInterval; } 160 } 161 162 public TimeSpan MaintainerRetryInterval 163 { 164 get { return maintainerRetryInterval; } 165 } 166 167 public TimeSpan MaintainerTimeout 168 { 169 get { return maintainerTimeout; } 170 } 171 172 public long MaxBufferPoolSize 173 { 174 get { return maxBufferPoolSize; } 175 } 176 177 public long MaxReceivedMessageSize 178 { 179 get { return maxReceivedMessageSize; } 180 } 181 182 public int MaxNeighbors 183 { 184 get { return maxNeighbors; } 185 } 186 187 public int MaxReferrals 188 { 189 get { return maxReferrals; } 190 } 191 192 public int MaxReferralCacheSize 193 { 194 get { return maxReferralCacheSize; } 195 } 196 197 public int MaxResolveAddresses 198 { 199 get { return maxResolveAddresses; } 200 } 201 202 public int MaxPendingIncomingCalls 203 { 204 get { return this.maxIncomingConcurrentCalls; } 205 } 206 207 public int MaxPendingOutgoingCalls 208 { 209 get { return this.maxSendQueueSize; } 210 } 211 212 public int MaxConcurrentSessions 213 { 214 get { return this.maxConcurrentSessions; } 215 } 216 public int MinNeighbors 217 { 218 get { return minNeighbors; } 219 } 220 221 public string MeshId 222 { 223 get { return meshId; } 224 } 225 226 public MessageEncoder MessageEncoder 227 { 228 get { return encoder; } 229 } 230 231 public PeerMessagePropagationFilter MessagePropagationFilter 232 { 233 get { return messagePropagationFilter; } 234 } 235 236 public ulong NodeId 237 { 238 get { return nodeId; } 239 } 240 241 public int Port 242 { 243 get { return port; } 244 } 245 246 public XmlDictionaryReaderQuotas ReaderQuotas 247 { 248 get { return this.readerQuotas; } 249 } 250 251 public PeerResolver Resolver 252 { 253 get { return resolver; } 254 } 255 256 public TimeSpan UnregisterTimeout 257 { 258 get { return unregisterTimeout; } 259 } 260 261 // Returns the actual address that the node service is listening on. 262 // If retrieving the address in order to send it over the wire, maskScopeId should be true 263 // (scope IDs are not sent over the wire). GetListenAddress(bool maskScopeId)264 public PeerNodeAddress GetListenAddress(bool maskScopeId) 265 { 266 PeerNodeAddress localAddress = this.listenAddress; 267 return new PeerNodeAddress(localAddress.EndpointAddress, PeerIPHelper.CloneAddresses(localAddress.IPAddresses, maskScopeId)); 268 } 269 SetListenAddress(PeerNodeAddress address)270 public void SetListenAddress(PeerNodeAddress address) 271 { 272 this.listenAddress = address; 273 } 274 BuildUri(string host, int port, Guid guid)275 static Uri BuildUri(string host, int port, Guid guid) 276 { 277 UriBuilder uriBuilder = new UriBuilder(); 278 uriBuilder.Host = host; 279 if (port > 0) 280 uriBuilder.Port = port; 281 uriBuilder.Path = PeerStrings.KnownServiceUriPrefix + '/' + guid; 282 uriBuilder.Scheme = Uri.UriSchemeNetTcp; 283 TcpChannelListener.FixIpv6Hostname(uriBuilder, uriBuilder.Uri); 284 return uriBuilder.Uri; 285 } 286 GetSelfUri()287 public Uri GetSelfUri() 288 { 289 Uri uri = null; 290 Guid serviceGuid = Guid.NewGuid(); 291 292 if (this.listenIPAddress == null) 293 { 294 uri = BuildUri(DnsCache.MachineName, port, serviceGuid); 295 } 296 else 297 { 298 uri = BuildUri(this.listenIPAddress.ToString(), port, serviceGuid); 299 } 300 return uri; 301 } 302 GetMeshUri()303 public Uri GetMeshUri() 304 { 305 UriBuilder uriBuilder = new UriBuilder(); 306 uriBuilder.Host = this.meshId; 307 uriBuilder.Scheme = PeerStrings.Scheme; 308 return uriBuilder.Uri; 309 } 310 } 311 312 static class PeerMessageHelpers 313 { 314 // delegates used to call the callback to process an incoming message CleanupCallback(IPeerNeighbor neighbor, PeerCloseReason reason, Exception exception)315 public delegate void CleanupCallback(IPeerNeighbor neighbor, PeerCloseReason reason, Exception exception); 316 GetHeaderString(MessageHeaders headers, string name, string ns)317 public static string GetHeaderString(MessageHeaders headers, string name, string ns) 318 { 319 string result = null; 320 int index = headers.FindHeader(name, ns); 321 if (index >= 0) 322 { 323 using (XmlDictionaryReader reader = headers.GetReaderAtHeader(index)) 324 { 325 result = reader.ReadElementString(); 326 } 327 headers.UnderstoodHeaders.Add(headers[index]); 328 } 329 return result; 330 } 331 GetHeaderUri(MessageHeaders headers, string name, string ns)332 public static Uri GetHeaderUri(MessageHeaders headers, string name, string ns) 333 { 334 Uri result = null; 335 string rawString = GetHeaderString(headers, name, ns); 336 if (rawString != null) 337 result = new Uri(rawString); 338 return result; 339 } 340 GetHeaderULong(MessageHeaders headers, int index)341 public static ulong GetHeaderULong(MessageHeaders headers, int index) 342 { 343 ulong result = PeerTransportConstants.MaxHopCount; 344 if (index >= 0) 345 { 346 using (XmlDictionaryReader reader = headers.GetReaderAtHeader(index)) 347 { 348 result = XmlConvert.ToUInt64(reader.ReadElementString()); 349 } 350 headers.UnderstoodHeaders.Add(headers[index]); 351 } 352 return result; 353 } 354 GetHeaderUniqueId(MessageHeaders headers, string name, string ns)355 public static UniqueId GetHeaderUniqueId(MessageHeaders headers, string name, string ns) 356 { 357 UniqueId result = null; 358 int index = headers.FindHeader(name, ns); 359 if (index >= 0) 360 { 361 using (XmlDictionaryReader reader = headers.GetReaderAtHeader(index)) 362 { 363 result = reader.ReadElementContentAsUniqueId(); 364 } 365 headers.UnderstoodHeaders.Add(headers[index]); 366 } 367 return result; 368 } 369 370 } 371 372 static class PeerStrings 373 { 374 public static Dictionary<string, string> protocolActions; 375 376 // Namespace for infrastructure messages 377 public const string Namespace = "http://schemas.microsoft.com/net/2006/05/peer"; 378 379 // PeerService contract name 380 public const string ServiceContractName = "PeerService"; 381 382 // Infrastructure message actions 383 // PeerConnector 384 public const string ConnectAction = Namespace + "/Connect"; 385 public const string WelcomeAction = Namespace + "/Welcome"; 386 public const string RefuseAction = Namespace + "/Refuse"; 387 public const string DisconnectAction = Namespace + "/Disconnect"; 388 389 // PeerFlooder 390 public const string FloodAction = Namespace + "/Flood"; 391 public const string InternalFloodAction = Namespace + "/IntFlood"; 392 public const string LinkUtilityAction = Namespace + "/LinkUtility"; 393 public const string RequestSecurityTokenAction = "RequestSecurityToken"; 394 public const string RequestSecurityTokenResponseAction = "RequestSecurityTokenResponse"; 395 public const string HopCountElementName = "Hops"; 396 public const string HopCountElementNamespace = Namespace + "/HopCount"; 397 public const string PingAction = Namespace + "/Ping"; 398 399 // Uri 400 public const string Scheme = "net.p2p"; 401 public const string KnownServiceUriPrefix = "PeerChannelEndpoints"; 402 public const string PeerCustomResolver = "PeerCustomResolver"; 403 404 public const string SkipLocalChannels = "SkipLocalChannels"; 405 public const string Via = "PeerVia"; 406 public const string MessageVerified = "MessageVerified"; 407 public const string CacheMiss = "CacheMiss"; 408 public const string PeerProperty = "PeerProperty"; 409 public const string MessageId = "MessageID"; 410 PeerStrings()411 static PeerStrings() 412 { 413 protocolActions = new Dictionary<string, string>(); 414 PopulateProtocolActions(); 415 } 416 PopulateProtocolActions()417 static void PopulateProtocolActions() 418 { 419 protocolActions.Add(PeerStrings.ConnectAction, PeerOperationNames.Connect); 420 protocolActions.Add(PeerStrings.WelcomeAction, PeerOperationNames.Welcome); 421 protocolActions.Add(PeerStrings.RefuseAction, PeerOperationNames.Refuse); 422 protocolActions.Add(PeerStrings.DisconnectAction, PeerOperationNames.Disconnect); 423 protocolActions.Add(PeerStrings.RequestSecurityTokenAction, PeerOperationNames.ProcessRequestSecurityToken); 424 protocolActions.Add(PeerStrings.RequestSecurityTokenResponseAction, PeerOperationNames.RequestSecurityTokenResponse); 425 protocolActions.Add(PeerStrings.LinkUtilityAction, PeerOperationNames.LinkUtility); 426 protocolActions.Add(Addressing10Strings.FaultAction, PeerOperationNames.Fault); 427 protocolActions.Add(PeerStrings.PingAction, PeerOperationNames.Ping); 428 } 429 FindAction(string action)430 public static string FindAction(string action) 431 { 432 string result = null; 433 protocolActions.TryGetValue(action, out result); 434 return result; 435 } 436 437 438 } 439 440 class PeerOperationNames 441 { 442 public const string Connect = "Connect"; 443 public const string Disconnect = "Disconnect"; 444 public const string Refuse = "Refuse"; 445 public const string Welcome = "Welcome"; 446 public const string LinkUtility = "LinkUtility"; 447 public const string ProcessRequestSecurityToken = "ProcessRequestSecurityToken"; 448 public const string RequestSecurityTokenResponse = "RequestSecurityTokenResponse"; 449 public const string Flood = "FloodMessage"; 450 public const string Demuxer = "PeerFlooder"; 451 public const string PeerVia = "PeerVia"; 452 public const string Fault = "Fault"; 453 public const string PeerTo = "PeerTo"; 454 public const string Ping = "Ping"; 455 456 } 457 458 class PeerResolverStrings 459 { 460 public const string Namespace = PeerStrings.Namespace + "/resolver"; 461 public const string RegisterAction = Namespace + "/Register"; 462 public const string RegisterResponseAction = Namespace + "/RegisterResponse"; 463 public const string UnregisterAction = Namespace + "/Unregister"; 464 public const string ResolveAction = Namespace + "/Resolve"; 465 public const string ResolveResponseAction = Namespace + "/ResolveResponse"; 466 public const string UpdateAction = Namespace + "/Update"; 467 public const string UpdateResponseAction = Namespace + "/UpdateResponse"; 468 public const string RefreshAction = Namespace + "/Refresh"; 469 public const string RefreshResponseAction = Namespace + "/RefreshResponse"; 470 public const string GetServiceSettingsAction = Namespace + "/GetServiceSettings"; 471 public const string GetServiceSettingsResponseAction = Namespace + "/GetServiceSettingsResponse"; 472 } 473 474 // constants used by more than one component 475 static class PeerTransportConstants 476 { 477 public const int ConnectTimeout = 60 * 1000; // 1 minute 478 public const ulong InvalidNodeId = 0; 479 public const int MinNeighbors = 2; 480 public const int IdealNeighbors = 3; 481 public const int MaxResolveAddresses = IdealNeighbors; // We only to resolve Ideal connections 482 483 public const int MaxNeighbors = 7; 484 public const int MaxReferrals = 10; 485 public const int MaxReferralCacheSize = 50; // Cache no more than 50 referrals 486 487 public const int MaintainerInterval = 5 * 60 * 1000; // 5 Minutes 488 public const int MaintainerRetryInterval = 10000; // 10 seconds 489 public const int MaintainerTimeout = 2 * 60 * 1000; // 2 Minutes 490 public const int UnregisterTimeout = 2 * 60 * 1000; // 2 Minutes 491 492 //how long do we want wait before sending each batch of acks? 493 public const int AckTimeout = 30 * 1000; 494 495 //how many acks do we want max in each ack message? 496 public const uint AckWindow = 32; 497 498 public const long MinMessageSize = 16384; 499 500 public const int MinPort = IPEndPoint.MinPort; 501 public const int MaxPort = IPEndPoint.MaxPort; 502 public const ulong MaxHopCount = ulong.MaxValue; 503 public static TimeSpan ForwardInterval = TimeSpan.FromSeconds(10); 504 public static TimeSpan ForwardTimeout = TimeSpan.FromSeconds(60); 505 public static int MaxOutgoingMessages = 128; 506 public const int MessageThreshold = 32; 507 } 508 509 static class PeerValidateHelper 510 { ValidateListenIPAddress(IPAddress address)511 public static void ValidateListenIPAddress(IPAddress address) 512 { 513 // null is Okay 514 if (address == null) 515 return; 516 517 // If an incorrect IP address is given throw. 518 if (address.Equals(IPAddress.Any) || 519 address.Equals(IPAddress.IPv6Any) || 520 address.Equals(IPAddress.IPv6None) || 521 address.Equals(IPAddress.None) || 522 address.Equals(IPAddress.Broadcast) || 523 address.IsIPv6Multicast || 524 IPAddress.IsLoopback(address)) 525 { 526 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 527 new ArgumentException(SR.GetString(SR.PeerListenIPAddressInvalid, address), "address", null)); 528 } 529 } 530 ValidateMaxMessageSize(long value)531 public static void ValidateMaxMessageSize(long value) 532 { 533 if (value < PeerTransportConstants.MinMessageSize) 534 { 535 string message = SR.GetString(SR.ArgumentOutOfRange, PeerTransportConstants.MinMessageSize, long.MaxValue); 536 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, message)); 537 } 538 } 539 ValidatePort(int value)540 public static void ValidatePort(int value) 541 { 542 if (value < PeerTransportConstants.MinPort || value > PeerTransportConstants.MaxPort) 543 { 544 string message = SR.GetString(SR.ArgumentOutOfRange, PeerTransportConstants.MinPort, PeerTransportConstants.MaxPort); 545 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, message)); 546 } 547 } 548 ValidNodeAddress(PeerNodeAddress address)549 public static bool ValidNodeAddress(PeerNodeAddress address) 550 { 551 return (address != null 552 && address.EndpointAddress != null 553 && address.EndpointAddress.Uri != null 554 && address.IPAddresses != null 555 && address.IPAddresses.Count > 0 556 && string.Compare(address.EndpointAddress.Uri.Scheme, Uri.UriSchemeNetTcp, StringComparison.OrdinalIgnoreCase) == 0 557 ); 558 } 559 ValidReferralNodeAddress(PeerNodeAddress address)560 public static bool ValidReferralNodeAddress(PeerNodeAddress address) 561 { 562 bool valid = true; 563 long scopeId = -1; 564 565 foreach (IPAddress addr in address.IPAddresses) 566 { 567 if (addr.IsIPv6LinkLocal) 568 { 569 if (scopeId == -1) 570 { 571 scopeId = addr.ScopeId; 572 } 573 else if (scopeId != addr.ScopeId) 574 { 575 valid = false; 576 break; 577 } 578 } 579 } 580 return valid; 581 } 582 } 583 584 // Indicates which side initiated neighbor close 585 enum PeerCloseInitiator 586 { 587 LocalNode, 588 RemoteNode 589 } 590 591 // Reason for closing a neighbor 592 // WARNING: If you add another enum value, consider whether a corresponding value 593 // should be added to PeerConnector.RefuseReason and PeerConnector.DisconnectReason. 594 // WARNING: Upon adding a new enum value, consider if PeerCloseReasonHelper.IsDefined 595 // should be updated. 596 enum PeerCloseReason 597 { 598 None = 0, // Reserved value - never serialized used internally. 599 InvalidNeighbor, // used when protocol violations are detected 600 LeavingMesh, // Closing because the node is leaving the mesh 601 NotUsefulNeighbor, // Closing because the neighbor is not useful 602 DuplicateNeighbor, // The node already has a neighbor session to this node 603 DuplicateNodeId, // The neighbor has the same node ID as the local node 604 NodeBusy, // The node has too many neighbor sessions to accept a new session 605 ConnectTimedOut, // Connect processing timedout 606 Faulted, // When neighbor faults 607 Closed, // When neighbor closes without Disconnect or Refuse 608 InternalFailure, // Eg: an infrastructure msg send fails and requires closing the channel 609 AuthenticationFailure, // Eg, when in secure mode, wrong credentials. 610 NodeTooSlow, //remote neighbor is too slow 611 } 612 613 // Neighbor event args 614 // EventArgs when a neighbor is closing or closed 615 class PeerNeighborCloseEventArgs : EventArgs 616 { 617 PeerCloseInitiator closeInitiator; 618 Exception exception; 619 PeerCloseReason reason; 620 PeerNeighborCloseEventArgs(PeerCloseReason reason, PeerCloseInitiator closeInitiator, Exception exception)621 public PeerNeighborCloseEventArgs(PeerCloseReason reason, 622 PeerCloseInitiator closeInitiator, Exception exception) 623 { 624 this.reason = reason; 625 this.closeInitiator = closeInitiator; 626 this.exception = exception; 627 } 628 629 public PeerCloseInitiator CloseInitiator 630 { 631 get { return this.closeInitiator; } 632 } 633 634 public Exception Exception 635 { 636 get { return this.exception; } 637 } 638 639 public PeerCloseReason Reason 640 { 641 get { return this.reason; } 642 } 643 } 644 645 class PeerExceptionHelper 646 { ThrowInvalidOperation_InsufficientCryptoSupport(Exception innerException)647 static internal void ThrowInvalidOperation_InsufficientCryptoSupport(Exception innerException) 648 { 649 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InsufficientCryptoSupport), innerException)); 650 } ThrowArgument_InsufficientCredentials(string property)651 static internal void ThrowArgument_InsufficientCredentials(string property) 652 { 653 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InsufficientCredentials, property))); 654 } ThrowArgumentOutOfRange_InvalidTransportCredentialType(int value)655 static internal void ThrowArgumentOutOfRange_InvalidTransportCredentialType(int value) 656 { 657 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("CredentialType", value, 658 SR.GetString(SR.ValueMustBeInRange, PeerTransportCredentialType.Password, PeerTransportCredentialType.Certificate))); 659 } 660 ThrowArgumentOutOfRange_InvalidSecurityMode(int value)661 static internal void ThrowArgumentOutOfRange_InvalidSecurityMode(int value) 662 { 663 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("Mode", value, 664 SR.GetString(SR.ValueMustBeInRange, SecurityMode.None, SecurityMode.TransportWithMessageCredential))); 665 } 666 ThrowInvalidOperation_UnexpectedSecurityTokensDuringHandshake()667 static internal void ThrowInvalidOperation_UnexpectedSecurityTokensDuringHandshake() 668 { 669 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnexpectedSecurityTokensDuringHandshake))); 670 } 671 ThrowArgument_PnrpAddressesExceedLimit()672 static internal void ThrowArgument_PnrpAddressesExceedLimit() 673 { 674 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.PnrpAddressesExceedLimit))); 675 } ThrowInvalidOperation_PnrpNoClouds()676 static internal void ThrowInvalidOperation_PnrpNoClouds() 677 { 678 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.PnrpNoClouds))); 679 } ThrowInvalidOperation_PnrpAddressesUnsupported()680 static internal void ThrowInvalidOperation_PnrpAddressesUnsupported() 681 { 682 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.PnrpAddressesUnsupported))); 683 } ThrowArgument_InsufficientResolverSettings()684 static internal void ThrowArgument_InsufficientResolverSettings() 685 { 686 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InsufficientResolverSettings))); 687 } ThrowArgument_MustOverrideInitialize()688 static internal void ThrowArgument_MustOverrideInitialize() 689 { 690 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MustOverrideInitialize))); 691 } ThrowArgument_InvalidResolverMode(PeerResolverMode mode)692 static internal void ThrowArgument_InvalidResolverMode(PeerResolverMode mode) 693 { 694 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidResolverMode, mode))); 695 } 696 ThrowInvalidOperation_NotValidWhenOpen(string operation)697 static internal void ThrowInvalidOperation_NotValidWhenOpen(string operation) 698 { 699 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NotValidWhenOpen, operation))); 700 } 701 ThrowInvalidOperation_NotValidWhenClosed(string operation)702 static internal void ThrowInvalidOperation_NotValidWhenClosed(string operation) 703 { 704 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NotValidWhenClosed, operation))); 705 } 706 ThrowInvalidOperation_DuplicatePeerRegistration(string servicepath)707 static internal void ThrowInvalidOperation_DuplicatePeerRegistration(string servicepath) 708 { 709 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.DuplicatePeerRegistration, servicepath))); 710 } ThrowPnrpError(int errorCode, string cloud)711 static internal void ThrowPnrpError(int errorCode, string cloud) 712 { 713 ThrowPnrpError(errorCode, cloud, true); 714 } ThrowPnrpError(int errorCode, string cloud, bool trace)715 static internal void ThrowPnrpError(int errorCode, string cloud, bool trace) 716 { 717 throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new System.ServiceModel.Channels.PnrpPeerResolver.PnrpException(errorCode, cloud), trace ? TraceEventType.Error : TraceEventType.Information); 718 } 719 ThrowInvalidOperation_PeerConflictingPeerNodeSettings(string propertyName)720 static internal void ThrowInvalidOperation_PeerConflictingPeerNodeSettings(string propertyName) 721 { 722 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.PeerConflictingPeerNodeSettings, propertyName))); 723 } 724 ThrowInvalidOperation_PeerCertGenFailure(Exception innerException)725 static internal void ThrowInvalidOperation_PeerCertGenFailure(Exception innerException) 726 { 727 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.PeerCertGenFailure), innerException)); 728 } ThrowInvalidOperation_ConflictingHeader(string headerName)729 static internal void ThrowInvalidOperation_ConflictingHeader(string headerName) 730 { 731 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.PeerConflictingHeader, headerName, PeerStrings.Namespace))); 732 } 733 GetLastException()734 public static Exception GetLastException() 735 { 736 return new Win32Exception(Marshal.GetLastWin32Error()); 737 } 738 739 } 740 741 class PeerBindingPropertyNames 742 { 743 public static readonly string ListenUri = "ListenUri"; 744 public static readonly string Port = "Port"; 745 public static readonly string MaxReceivedMessageSize = "MaxReceivedMessageSize"; 746 public static readonly string Resolver = "Resolver"; 747 public static readonly string Security = "Security"; 748 public static readonly string SecurityDotMode = "Security.Mode"; 749 public static readonly string ListenIPAddress = "ListenIPAddress"; 750 public static readonly string Credentials = "Credentials"; 751 public static readonly string ResolverSettings = "ResolverSettings"; 752 public static readonly string Password = "Password"; 753 public static readonly string Certificate = "Certificate"; 754 public static readonly string MaxBufferPoolSize = "MaxBufferPoolSize"; 755 public static readonly string ReaderQuotasDotArrayLength = "ReaderQuotas.MaxArrayLength"; 756 public static readonly string ReaderQuotasDotStringLength = "ReaderQuotas.MaxStringContentLength"; 757 public static readonly string ReaderQuotasDotMaxDepth = "ReaderQuotas.MaxDepth"; 758 public static readonly string ReaderQuotasDotMaxCharCount = "ReaderQuotas.MaxNameTableCharCount"; 759 public static readonly string ReaderQuotasDotMaxBytesPerRead = "ReaderQuotas.MaxBytesPerRead"; 760 } 761 762 class PeerPropertyNames 763 { 764 public static readonly string MessageSenderAuthentication = "Credentials.Peer.MessageSenderAuthentication"; 765 public static readonly string Credentials = "SecurityCredentialsManager"; 766 public static readonly string Password = "Credentials.Peer.MeshPassword"; 767 public static readonly string Certificate = "Credentials.Peer.Certificate"; 768 public static readonly string PeerAuthentication = "Credentials.Peer.PeerAuthentication"; 769 } 770 771 class OperationSelector : IDispatchOperationSelector 772 { 773 IPeerNodeMessageHandling messageHandler; 774 OperationSelector(IPeerNodeMessageHandling messageHandler)775 public OperationSelector(IPeerNodeMessageHandling messageHandler) 776 { 777 this.messageHandler = messageHandler; 778 } 779 TurnOffSecurityHeader(Message message)780 public static void TurnOffSecurityHeader(Message message) 781 { 782 int i = message.Headers.FindHeader(SecurityJan2004Strings.Security, SecurityJan2004Strings.Namespace); 783 if (i >= 0) 784 { 785 message.Headers.AddUnderstood(i); 786 } 787 } 788 SelectOperation(ref Message message)789 public string SelectOperation(ref Message message) 790 { 791 792 string action = message.Headers.Action; 793 string demux = null; 794 byte[] id = PeerNodeImplementation.DefaultId; 795 string operation = PeerStrings.FindAction(action); 796 Uri via = null; 797 Uri to = null; 798 bool skipped = false; 799 PeerMessageProperty peerProperty = new PeerMessageProperty(); 800 801 if (operation != null) 802 return operation; 803 try 804 { 805 demux = PeerMessageHelpers.GetHeaderString(message.Headers, PeerOperationNames.Flood, PeerStrings.Namespace); 806 via = PeerMessageHelpers.GetHeaderUri(message.Headers, PeerStrings.Via, PeerStrings.Namespace); 807 to = PeerMessageHelpers.GetHeaderUri(message.Headers, PeerOperationNames.PeerTo, PeerStrings.Namespace); 808 } 809 catch (MessageHeaderException e) 810 { 811 DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); 812 return PeerOperationNames.Fault; 813 } 814 catch (SerializationException e) 815 { 816 DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); 817 return PeerOperationNames.Fault; 818 } 819 catch (XmlException e) 820 { 821 DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); 822 return PeerOperationNames.Fault; 823 } 824 peerProperty.PeerVia = via; 825 peerProperty.PeerTo = to; 826 message.Properties.Add(PeerStrings.PeerProperty, peerProperty); 827 if (demux == PeerOperationNames.Demuxer) 828 { 829 try 830 { 831 if (!this.messageHandler.ValidateIncomingMessage(ref message, via)) 832 { 833 peerProperty.SkipLocalChannels = true; 834 skipped = true; 835 TurnOffSecurityHeader(message); 836 } 837 if (this.messageHandler.IsNotSeenBefore(message, out id, out peerProperty.CacheMiss)) 838 { 839 peerProperty.MessageVerified = true; 840 } 841 else 842 { 843 if (!skipped) 844 { 845 peerProperty.SkipLocalChannels = true; 846 } 847 } 848 //means that the message doesnt contain legal id 849 if (id == PeerNodeImplementation.DefaultId) 850 return PeerOperationNames.Fault; 851 } 852 catch (MessageHeaderException e) 853 { 854 DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); 855 return PeerOperationNames.Fault; 856 } 857 catch (SerializationException e) 858 { 859 DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); 860 return PeerOperationNames.Fault; 861 } 862 catch (XmlException e) 863 { 864 DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); 865 return PeerOperationNames.Fault; 866 } 867 catch (MessageSecurityException e) 868 { 869 if (!e.ReplayDetected) 870 return PeerOperationNames.Fault; 871 else 872 DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); 873 } 874 return PeerOperationNames.Flood; 875 } 876 else 877 return null; 878 } 879 } 880 881 internal class PeerOperationSelectorBehavior : IContractBehavior 882 { 883 IPeerNodeMessageHandling messageHandler; 884 PeerOperationSelectorBehavior(IPeerNodeMessageHandling messageHandler)885 internal PeerOperationSelectorBehavior(IPeerNodeMessageHandling messageHandler) 886 { 887 this.messageHandler = messageHandler; 888 } 889 IContractBehavior.AddBindingParameters(ContractDescription description, ServiceEndpoint endpoint, BindingParameterCollection parameters)890 void IContractBehavior.AddBindingParameters(ContractDescription description, ServiceEndpoint endpoint, BindingParameterCollection parameters) 891 { 892 } 893 IContractBehavior.Validate(ContractDescription description, ServiceEndpoint endpoint)894 void IContractBehavior.Validate(ContractDescription description, ServiceEndpoint endpoint) 895 { 896 } 897 IContractBehavior.ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, DispatchRuntime dispatch)898 void IContractBehavior.ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, DispatchRuntime 899 dispatch) 900 { 901 dispatch.OperationSelector = new OperationSelector(this.messageHandler); 902 903 if (dispatch.ClientRuntime != null) 904 { 905 dispatch.ClientRuntime.OperationSelector = new OperationSelectorBehavior.MethodInfoOperationSelector(description, MessageDirection.Output); 906 } 907 } 908 IContractBehavior.ApplyClientBehavior(ContractDescription description, ServiceEndpoint endpoint, ClientRuntime proxy)909 void IContractBehavior.ApplyClientBehavior(ContractDescription description, ServiceEndpoint endpoint, ClientRuntime proxy) 910 { 911 proxy.OperationSelector = new OperationSelectorBehavior.MethodInfoOperationSelector(description, MessageDirection.Input); 912 proxy.CallbackDispatchRuntime.OperationSelector = new OperationSelector(this.messageHandler); 913 } 914 915 } 916 917 class PeerDictionaryHeader : DictionaryHeader 918 { 919 string value; 920 XmlDictionaryString name; 921 XmlDictionaryString nameSpace; 922 923 924 public override XmlDictionaryString DictionaryName 925 { 926 get { return name; } 927 } 928 929 public override XmlDictionaryString DictionaryNamespace 930 { 931 get { return nameSpace; } 932 } 933 PeerDictionaryHeader(XmlDictionaryString name, XmlDictionaryString nameSpace, string value)934 public PeerDictionaryHeader(XmlDictionaryString name, XmlDictionaryString nameSpace, string value) 935 { 936 this.name = name; 937 this.nameSpace = nameSpace; 938 this.value = value; 939 } 940 941 942 PeerDictionaryHeader(XmlDictionaryString name, XmlDictionaryString nameSpace, XmlDictionaryString value)943 public PeerDictionaryHeader(XmlDictionaryString name, XmlDictionaryString nameSpace, XmlDictionaryString value) 944 { 945 this.name = name; 946 this.nameSpace = nameSpace; 947 this.value = value.Value; 948 } 949 OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)950 protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion) 951 { 952 writer.WriteString(this.value); 953 } 954 CreateHopCountHeader(ulong hopcount)955 static internal PeerDictionaryHeader CreateHopCountHeader(ulong hopcount) 956 { 957 return new PeerDictionaryHeader(XD.PeerWireStringsDictionary.HopCount, XD.PeerWireStringsDictionary.HopCountNamespace, hopcount.ToString(CultureInfo.InvariantCulture)); 958 } 959 CreateViaHeader(Uri via)960 static internal PeerDictionaryHeader CreateViaHeader(Uri via) 961 { 962 return new PeerDictionaryHeader(XD.PeerWireStringsDictionary.PeerVia, XD.PeerWireStringsDictionary.Namespace, via.ToString()); 963 } 964 CreateFloodRole()965 static internal PeerDictionaryHeader CreateFloodRole() 966 { 967 return new PeerDictionaryHeader(XD.PeerWireStringsDictionary.FloodAction, XD.PeerWireStringsDictionary.Namespace, XD.PeerWireStringsDictionary.Demuxer); 968 } 969 CreateToHeader(Uri to)970 static internal PeerDictionaryHeader CreateToHeader(Uri to) 971 { 972 return new PeerDictionaryHeader(XD.PeerWireStringsDictionary.PeerTo, XD.PeerWireStringsDictionary.Namespace, to.ToString()); 973 } CreateMessageIdHeader(System.Xml.UniqueId messageId)974 static internal PeerDictionaryHeader CreateMessageIdHeader(System.Xml.UniqueId messageId) 975 { 976 return new PeerDictionaryHeader(XD.AddressingDictionary.MessageId, XD.PeerWireStringsDictionary.Namespace, messageId.ToString()); 977 } 978 979 } 980 981 class PeerMessageProperty 982 { 983 984 public bool MessageVerified; 985 public bool SkipLocalChannels; 986 public Uri PeerVia; 987 public Uri PeerTo; 988 public int CacheMiss; 989 } 990 } 991 992