1 // <copyright> 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 // </copyright> 4 5 namespace System.ServiceModel.Channels 6 { 7 using System; 8 using System.ComponentModel; 9 using System.Net.WebSockets; 10 using System.Runtime; 11 using System.Threading; 12 13 public sealed class WebSocketTransportSettings : IEquatable<WebSocketTransportSettings> 14 { 15 public const string ConnectionOpenedAction = "http://schemas.microsoft.com/2011/02/session/onopen"; 16 public const string BinaryMessageReceivedAction = "http://schemas.microsoft.com/2011/02/websockets/onbinarymessage"; 17 public const string TextMessageReceivedAction = "http://schemas.microsoft.com/2011/02/websockets/ontextmessage"; 18 public const string SoapContentTypeHeader = "soap-content-type"; 19 public const string BinaryEncoderTransferModeHeader = "microsoft-binary-transfer-mode"; 20 internal const string WebSocketMethod = "WEBSOCKET"; 21 internal const string SoapSubProtocol = "soap"; 22 internal const string TransportUsageMethodName = "TransportUsage"; 23 24 WebSocketTransportUsage transportUsage; 25 bool createNotificationOnConnection; 26 TimeSpan keepAliveInterval; 27 string subProtocol; 28 bool disablePayloadMasking; 29 int maxPendingConnections; 30 WebSocketTransportSettings()31 public WebSocketTransportSettings() 32 { 33 this.transportUsage = WebSocketDefaults.TransportUsage; 34 this.createNotificationOnConnection = WebSocketDefaults.CreateNotificationOnConnection; 35 this.keepAliveInterval = WebSocketDefaults.DefaultKeepAliveInterval; 36 this.subProtocol = WebSocketDefaults.SubProtocol; 37 this.disablePayloadMasking = WebSocketDefaults.DisablePayloadMasking; 38 this.maxPendingConnections = WebSocketDefaults.DefaultMaxPendingConnections; 39 } 40 WebSocketTransportSettings(WebSocketTransportSettings settings)41 WebSocketTransportSettings(WebSocketTransportSettings settings) 42 { 43 Fx.Assert(settings != null, "settings should not be null."); 44 this.TransportUsage = settings.TransportUsage; 45 this.SubProtocol = settings.SubProtocol; 46 this.KeepAliveInterval = settings.KeepAliveInterval; 47 this.DisablePayloadMasking = settings.DisablePayloadMasking; 48 this.CreateNotificationOnConnection = settings.CreateNotificationOnConnection; 49 this.MaxPendingConnections = settings.MaxPendingConnections; 50 } 51 52 [DefaultValue(WebSocketDefaults.TransportUsage)] 53 public WebSocketTransportUsage TransportUsage 54 { 55 get 56 { 57 return this.transportUsage; 58 } 59 60 set 61 { 62 WebSocketTransportUsageHelper.Validate(value); 63 this.transportUsage = value; 64 } 65 } 66 67 [DefaultValue(WebSocketDefaults.CreateNotificationOnConnection)] 68 public bool CreateNotificationOnConnection 69 { 70 get 71 { 72 return this.createNotificationOnConnection; 73 } 74 75 set 76 { 77 this.createNotificationOnConnection = value; 78 } 79 } 80 81 [DefaultValue(typeof(TimeSpan), WebSocketDefaults.DefaultKeepAliveIntervalString)] 82 public TimeSpan KeepAliveInterval 83 { 84 get 85 { 86 return this.keepAliveInterval; 87 } 88 89 set 90 { 91 if (value < TimeSpan.Zero && value != Timeout.InfiniteTimeSpan) 92 { 93 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException( 94 "value", 95 value, 96 SR.GetString(SR.SFxTimeoutOutOfRange0))); 97 } 98 99 if (TimeoutHelper.IsTooLarge(value)) 100 { 101 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException( 102 "value", 103 value, 104 SR.GetString(SR.SFxTimeoutOutOfRangeTooBig))); 105 } 106 107 this.keepAliveInterval = value; 108 } 109 } 110 111 [DefaultValue(WebSocketDefaults.SubProtocol)] 112 public string SubProtocol 113 { 114 get 115 { 116 return this.subProtocol; 117 } 118 119 set 120 { 121 if (value != null) 122 { 123 if (value == string.Empty) 124 { 125 throw FxTrace.Exception.Argument("value", SR.GetString(SR.WebSocketInvalidProtocolEmptySubprotocolString)); 126 } 127 128 if (value.Split(WebSocketHelper.ProtocolSeparators).Length > 1) 129 { 130 throw FxTrace.Exception.Argument("value", SR.GetString(SR.WebSocketInvalidProtocolContainsMultipleSubProtocolString, value)); 131 } 132 133 string invalidChar; 134 if (WebSocketHelper.IsSubProtocolInvalid(value, out invalidChar)) 135 { 136 throw FxTrace.Exception.Argument("value", SR.GetString(SR.WebSocketInvalidProtocolInvalidCharInProtocolString, value, invalidChar)); 137 } 138 } 139 140 this.subProtocol = value; 141 } 142 } 143 144 [DefaultValue(WebSocketDefaults.DisablePayloadMasking)] 145 public bool DisablePayloadMasking 146 { 147 get 148 { 149 return this.disablePayloadMasking; 150 } 151 152 set 153 { 154 this.disablePayloadMasking = value; 155 } 156 } 157 158 [DefaultValue(WebSocketDefaults.DefaultMaxPendingConnections)] 159 public int MaxPendingConnections 160 { 161 get 162 { 163 return this.maxPendingConnections; 164 } 165 166 set 167 { 168 if (value < 0) 169 { 170 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException( 171 "value", 172 value, 173 SR.GetString(SR.ValueMustBePositive))); 174 } 175 176 this.maxPendingConnections = value; 177 } 178 } 179 Equals(WebSocketTransportSettings other)180 public bool Equals(WebSocketTransportSettings other) 181 { 182 if (other == null) 183 { 184 return false; 185 } 186 187 return this.TransportUsage == other.TransportUsage 188 && this.CreateNotificationOnConnection == other.CreateNotificationOnConnection 189 && this.KeepAliveInterval == other.KeepAliveInterval 190 && this.DisablePayloadMasking == other.DisablePayloadMasking 191 && StringComparer.OrdinalIgnoreCase.Compare(this.SubProtocol, other.SubProtocol) == 0 192 && this.MaxPendingConnections == other.MaxPendingConnections; 193 } 194 Equals(object obj)195 public override bool Equals(object obj) 196 { 197 if (obj == null) 198 { 199 return base.Equals(obj); 200 } 201 202 WebSocketTransportSettings settings = obj as WebSocketTransportSettings; 203 return this.Equals(settings); 204 } 205 GetHashCode()206 public override int GetHashCode() 207 { 208 int hashcode = this.TransportUsage.GetHashCode() 209 ^ this.CreateNotificationOnConnection.GetHashCode() 210 ^ this.KeepAliveInterval.GetHashCode() 211 ^ this.DisablePayloadMasking.GetHashCode() 212 ^ this.MaxPendingConnections.GetHashCode(); 213 if (this.SubProtocol != null) 214 { 215 hashcode ^= this.SubProtocol.ToLowerInvariant().GetHashCode(); 216 } 217 218 return hashcode; 219 } 220 Clone()221 internal WebSocketTransportSettings Clone() 222 { 223 return new WebSocketTransportSettings(this); 224 } 225 GetEffectiveKeepAliveInterval()226 internal TimeSpan GetEffectiveKeepAliveInterval() 227 { 228 return this.keepAliveInterval == TimeSpan.Zero ? WebSocket.DefaultKeepAliveInterval : this.keepAliveInterval; 229 } 230 } 231 } 232