diff --git a/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker00Selector.cs b/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker00Selector.cs new file mode 100644 index 000000000..d780a6b75 --- /dev/null +++ b/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker00Selector.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace DotNetty.Codecs.Http.WebSockets.Handshaker +{ + using System; + using DotNetty.Common.Utilities; + + public class WebsocketHandshaker00Selector: WebsocketHandshakerVersionSelector + { + public WebsocketHandshaker00Selector(string webSocketUrl, string subprotocols, bool allowExtensions, int maxFramePayloadLength, bool allowMaskMismatch) + : base(webSocketUrl, subprotocols, allowExtensions, maxFramePayloadLength, allowMaskMismatch){ } + + protected override Func InstanceFactory(string webSocketUrl, string subprotocols, bool allowExtensions, int maxFramePayloadLength, bool allowMaskMismatch) + { + return () => new WebSocketServerHandshaker00(webSocketUrl, subprotocols, maxFramePayloadLength); + } + + protected override bool Selected(ICharSequence version) + { + return version == null; + } + } +} \ No newline at end of file diff --git a/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker07Selector.cs b/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker07Selector.cs new file mode 100644 index 000000000..c3f750e82 --- /dev/null +++ b/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker07Selector.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace DotNetty.Codecs.Http.WebSockets.Handshaker +{ + using System; + using DotNetty.Common.Utilities; + + public class WebsocketHandshaker07Selector: WebsocketHandshakerVersionSelector + { + public WebsocketHandshaker07Selector(string webSocketUrl, string subprotocols, bool allowExtensions, int maxFramePayloadLength, bool allowMaskMismatch) + : base(webSocketUrl, subprotocols, allowExtensions, maxFramePayloadLength, allowMaskMismatch){ } + + protected override Func InstanceFactory(string webSocketUrl, string subprotocols, bool allowExtensions, int maxFramePayloadLength, bool allowMaskMismatch) + { + return () => new WebSocketServerHandshaker07(webSocketUrl, subprotocols, allowExtensions, maxFramePayloadLength); + } + + protected override bool Selected(ICharSequence version) + { + return version.Equals(WebSocketVersion.V07.ToHttpHeaderValue()); + } + } +} \ No newline at end of file diff --git a/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker08Selector.cs b/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker08Selector.cs new file mode 100644 index 000000000..32ce24d32 --- /dev/null +++ b/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker08Selector.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace DotNetty.Codecs.Http.WebSockets.Handshaker +{ + using System; + using DotNetty.Common.Utilities; + + public class WebsocketHandshaker08Selector: WebsocketHandshakerVersionSelector + { + public WebsocketHandshaker08Selector(string webSocketUrl, string subprotocols, bool allowExtensions, int maxFramePayloadLength, bool allowMaskMismatch) + : base(webSocketUrl, subprotocols, allowExtensions, maxFramePayloadLength, allowMaskMismatch){ } + + protected override Func InstanceFactory(string webSocketUrl, string subprotocols, bool allowExtensions, int maxFramePayloadLength, bool allowMaskMismatch) + { + return () => new WebSocketServerHandshaker08(webSocketUrl, subprotocols, allowExtensions, maxFramePayloadLength); + } + + protected override bool Selected(ICharSequence version) + { + return version.Equals(WebSocketVersion.V08.ToHttpHeaderValue()); + } + } +} \ No newline at end of file diff --git a/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker13Selector.cs b/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker13Selector.cs new file mode 100644 index 000000000..ca2c8fdf3 --- /dev/null +++ b/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshaker13Selector.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace DotNetty.Codecs.Http.WebSockets.Handshaker +{ + using System; + using DotNetty.Common.Utilities; + + public class WebsocketHandshaker13Selector : WebsocketHandshakerVersionSelector + { + public WebsocketHandshaker13Selector(string webSocketUrl, string subprotocols, bool allowExtensions, int maxFramePayloadLength, bool allowMaskMismatch) + : base(webSocketUrl, subprotocols, allowExtensions, maxFramePayloadLength, allowMaskMismatch){ } + + protected override Func InstanceFactory(string webSocketUrl, string subprotocols, bool allowExtensions, int maxFramePayloadLength, bool allowMaskMismatch) + { + return () => new WebSocketServerHandshaker13(webSocketUrl, subprotocols, allowExtensions, maxFramePayloadLength); + } + + protected override bool Selected(ICharSequence version) + { + return version.Equals(WebSocketVersion.V13.ToHttpHeaderValue()); + } + } +} \ No newline at end of file diff --git a/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshakerVersionSelector.cs b/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshakerVersionSelector.cs new file mode 100644 index 000000000..7fd2f6085 --- /dev/null +++ b/src/DotNetty.Codecs.Http/WebSockets/Handshaker/WebsocketHandshakerVersionSelector.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace DotNetty.Codecs.Http.WebSockets.Handshaker +{ + using System; + using DotNetty.Common.Utilities; + + public abstract class WebsocketHandshakerVersionSelector + { + protected Func Factory; + + protected WebsocketHandshakerVersionSelector( + string webSocketUrl, + string subprotocols, + bool allowExtensions, + int maxFramePayloadLength, + bool allowMaskMismatch) + { + this.Factory = this.InstanceFactory(webSocketUrl, subprotocols, allowExtensions, maxFramePayloadLength, allowExtensions); + } + + protected abstract Func InstanceFactory( + string webSocketUrl, + string subprotocols, + bool allowExtensions, + int maxFramePayloadLength, + bool allowMaskMismatch); + + protected abstract bool Selected(ICharSequence version); + + + public bool Selector(ICharSequence version, out WebSocketServerHandshaker handshaker) + { + handshaker = null; + if (!this.Selected(version)) + { + return false; + } + + handshaker = this.Factory(); + return true; + } + } +} \ No newline at end of file diff --git a/src/DotNetty.Codecs.Http/WebSockets/WebSocketServerHandshakerFactory.cs b/src/DotNetty.Codecs.Http/WebSockets/WebSocketServerHandshakerFactory.cs index 3c3b4cbc1..7009666ab 100644 --- a/src/DotNetty.Codecs.Http/WebSockets/WebSocketServerHandshakerFactory.cs +++ b/src/DotNetty.Codecs.Http/WebSockets/WebSocketServerHandshakerFactory.cs @@ -4,6 +4,7 @@ namespace DotNetty.Codecs.Http.WebSockets { using System.Threading.Tasks; + using DotNetty.Codecs.Http.WebSockets.Handshaker; using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; @@ -19,6 +20,8 @@ public class WebSocketServerHandshakerFactory readonly bool allowMaskMismatch; + readonly WebsocketHandshakerVersionSelector[] selectors; + public WebSocketServerHandshakerFactory(string webSocketUrl, string subprotocols, bool allowExtensions) : this(webSocketUrl, subprotocols, allowExtensions, 65536) { @@ -38,53 +41,50 @@ public WebSocketServerHandshakerFactory(string webSocketUrl, string subprotocols this.allowExtensions = allowExtensions; this.maxFramePayloadLength = maxFramePayloadLength; this.allowMaskMismatch = allowMaskMismatch; + + this.selectors = new WebsocketHandshakerVersionSelector[] + { + new WebsocketHandshaker00Selector( + this.subprotocols, + this.subprotocols, + this.allowExtensions, + this.maxFramePayloadLength, + this.allowMaskMismatch), + new WebsocketHandshaker07Selector( + this.subprotocols, + this.subprotocols, + this.allowExtensions, + this.maxFramePayloadLength, + this.allowMaskMismatch), + new WebsocketHandshaker08Selector( + this.subprotocols, + this.subprotocols, + this.allowExtensions, + this.maxFramePayloadLength, + this.allowMaskMismatch), + new WebsocketHandshaker13Selector( + this.subprotocols, + this.subprotocols, + this.allowExtensions, + this.maxFramePayloadLength, + this.allowMaskMismatch) + }; } public WebSocketServerHandshaker NewHandshaker(IHttpRequest req) { - if (req.Headers.TryGet(HttpHeaderNames.SecWebsocketVersion, out ICharSequence version) - && version != null) + req.Headers.TryGet(HttpHeaderNames.SecWebsocketVersion, out ICharSequence version); + + WebSocketServerHandshaker result = null; + foreach (WebsocketHandshakerVersionSelector selector in this.selectors) { - if (version.Equals(WebSocketVersion.V13.ToHttpHeaderValue())) + if (selector.Selector(version, out result)) { - // Version 13 of the wire protocol - RFC 6455 (version 17 of the draft hybi specification). - return new WebSocketServerHandshaker13( - this.webSocketUrl, - this.subprotocols, - this.allowExtensions, - this.maxFramePayloadLength, - this.allowMaskMismatch); - } - else if (version.Equals(WebSocketVersion.V08.ToHttpHeaderValue())) - { - // Version 8 of the wire protocol - version 10 of the draft hybi specification. - return new WebSocketServerHandshaker08( - this.webSocketUrl, - this.subprotocols, - this.allowExtensions, - this.maxFramePayloadLength, - this.allowMaskMismatch); - } - else if (version.Equals(WebSocketVersion.V07.ToHttpHeaderValue())) - { - // Version 8 of the wire protocol - version 07 of the draft hybi specification. - return new WebSocketServerHandshaker07( - this.webSocketUrl, - this.subprotocols, - this.allowExtensions, - this.maxFramePayloadLength, - this.allowMaskMismatch); - } - else - { - return null; + break; } } - else - { - // Assume version 00 where version header was not specified - return new WebSocketServerHandshaker00(this.webSocketUrl, this.subprotocols, this.maxFramePayloadLength); - } + + return result; } public static Task SendUnsupportedVersionResponse(IChannel channel)