public override void ChannelRead(IChannelHandlerContext ctx, object msg) { if (msg is IHttpResponse response && WebSocketExtensionUtil.IsWebsocketUpgrade(response.Headers)) { string extensionsHeader = null; if (response.Headers.TryGet(HttpHeaderNames.SecWebsocketExtensions, out ICharSequence value)) { extensionsHeader = value.ToString(); } var pipeline = ctx.Pipeline; if (extensionsHeader is object) { List <WebSocketExtensionData> extensions = WebSocketExtensionUtil.ExtractExtensions(extensionsHeader); var validExtensions = new List <IWebSocketClientExtension>(extensions.Count); int rsv = 0; foreach (WebSocketExtensionData extensionData in extensions) { IWebSocketClientExtension validExtension = null; foreach (IWebSocketClientExtensionHandshaker extensionHandshaker in this.extensionHandshakers) { validExtension = extensionHandshaker.HandshakeExtension(extensionData); if (validExtension is object) { break; } } if (validExtension is object && 0u >= (uint)(validExtension.Rsv & rsv)) { rsv = rsv | validExtension.Rsv; validExtensions.Add(validExtension); } else { ThrowHelper.ThrowCodecException_InvalidWSExHandshake(extensionsHeader); } } foreach (IWebSocketClientExtension validExtension in validExtensions) { WebSocketExtensionDecoder decoder = validExtension.NewExtensionDecoder(); WebSocketExtensionEncoder encoder = validExtension.NewExtensionEncoder(); _ = pipeline.AddAfter(ctx.Name, decoder.GetType().Name, decoder); _ = pipeline.AddAfter(ctx.Name, encoder.GetType().Name, encoder); } } _ = pipeline.Remove(ctx.Name); } base.ChannelRead(ctx, msg); }
public override Task WriteAsync(IChannelHandlerContext ctx, object msg) { Action <Task> continuationAction = null; if (msg is IHttpResponse response && WebSocketExtensionUtil.IsWebsocketUpgrade(response.Headers) && this.validExtensions != null) { string headerValue = null; if (response.Headers.TryGet(HttpHeaderNames.SecWebsocketExtensions, out ICharSequence value)) { headerValue = value?.ToString(); } foreach (IWebSocketServerExtension extension in this.validExtensions) { WebSocketExtensionData extensionData = extension.NewReponseData(); headerValue = WebSocketExtensionUtil.AppendExtension(headerValue, extensionData.Name, extensionData.Parameters); } continuationAction = promise => { if (promise.Status == TaskStatus.RanToCompletion) { foreach (IWebSocketServerExtension extension in this.validExtensions) { WebSocketExtensionDecoder decoder = extension.NewExtensionDecoder(); WebSocketExtensionEncoder encoder = extension.NewExtensionEncoder(); ctx.Channel.Pipeline.AddAfter(ctx.Name, decoder.GetType().Name, decoder); ctx.Channel.Pipeline.AddAfter(ctx.Name, encoder.GetType().Name, encoder); } } ctx.Channel.Pipeline.Remove(ctx.Name); }; if (headerValue != null) { response.Headers.Set(HttpHeaderNames.SecWebsocketExtensions, headerValue); } } return(continuationAction == null ? base.WriteAsync(ctx, msg) : base.WriteAsync(ctx, msg) .ContinueWith(continuationAction, TaskContinuationOptions.ExecuteSynchronously)); }
private static void SwitchWebSocketExtensionHandler(Task promise, object state) { var wrapped = (Tuple <IChannelHandlerContext, List <IWebSocketServerExtension> >)state; var ctx = wrapped.Item1; var validExtensions = wrapped.Item2; var pipeline = ctx.Pipeline; if (promise.IsSuccess()) { for (int i = 0; i < validExtensions.Count; i++) { IWebSocketServerExtension extension = validExtensions[i]; WebSocketExtensionDecoder decoder = extension.NewExtensionDecoder(); WebSocketExtensionEncoder encoder = extension.NewExtensionEncoder(); _ = pipeline .AddAfter(ctx.Name, decoder.GetType().Name, decoder) .AddAfter(ctx.Name, encoder.GetType().Name, encoder); } } }