/// <summary> /// Performs the opening handshake /// When call this method you <c>MUST NOT</c> retain the <see cref="IFullHttpRequest"/> which is passed in. /// </summary> /// <param name="channel">Channel</param> /// <param name="req">HTTP Request</param> /// <param name="responseHeaders">Extra headers to add to the handshake response or <code>null</code> if no extra headers should be added</param> /// <param name="completion">the <see cref="IPromise"/> to be notified when the opening handshake is done</param> public void Handshake(IChannel channel, IFullHttpRequest req, HttpHeaders responseHeaders, IPromise completion) { #if DEBUG if (Logger.DebugEnabled) { Logger.WebSocketVersionServerHandshake(channel, _version); } #endif IFullHttpResponse response = NewHandshakeResponse(req, responseHeaders); IChannelPipeline p = channel.Pipeline; if (p.Get <HttpObjectAggregator>() is object) { _ = p.Remove <HttpObjectAggregator>(); } if (p.Get <HttpContentCompressor>() is object) { _ = p.Remove <HttpContentCompressor>(); } if (p.Get <CorsHandler>() is object) { _ = p.Remove <CorsHandler>(); } if (p.Get <HttpServerExpectContinueHandler>() is object) { _ = p.Remove <HttpServerExpectContinueHandler>(); } if (p.Get <HttpServerKeepAliveHandler>() is object) { _ = p.Remove <HttpServerKeepAliveHandler>(); } IChannelHandlerContext ctx = p.Context <HttpRequestDecoder>(); string encoderName; if (ctx is null) { // this means the user use an HttpServerCodec ctx = p.Context <HttpServerCodec>(); if (ctx is null) { _ = completion.TrySetException(ThrowHelper.GetInvalidOperationException_NoHttpDecoderAndServerCodec()); return; } encoderName = ctx.Name; _ = p.AddBefore(encoderName, "wsencoder", NewWebSocketEncoder()); _ = p.AddBefore(encoderName, "wsdecoder", NewWebsocketDecoder()); } else { _ = p.Replace(ctx.Name, "wsdecoder", NewWebsocketDecoder()); encoderName = p.Context <HttpResponseEncoder>().Name; _ = p.AddBefore(encoderName, "wsencoder", NewWebSocketEncoder()); } _ = channel.WriteAndFlushAsync(response).ContinueWith(RemoveHandlerAfterWriteAction, (completion, p, encoderName), TaskContinuationOptions.ExecuteSynchronously); }
public void Handshake(IChannel channel, IFullHttpRequest req, HttpHeaders responseHeaders, TaskCompletionSource completion) { if (Logger.DebugEnabled) { Logger.Debug("{} WebSocket version {} server handshake", channel, this.version); } IFullHttpResponse response = this.NewHandshakeResponse(req, responseHeaders); IChannelPipeline p = channel.Pipeline; if (p.Get <HttpObjectAggregator>() != null) { p.Remove <HttpObjectAggregator>(); } if (p.Get <HttpContentCompressor>() != null) { p.Remove <HttpContentCompressor>(); } IChannelHandlerContext ctx = p.Context <HttpRequestDecoder>(); string encoderName; if (ctx == null) { // this means the user use a HttpServerCodec ctx = p.Context <HttpServerCodec>(); if (ctx == null) { completion.TrySetException(new InvalidOperationException("No HttpDecoder and no HttpServerCodec in the pipeline")); return; } p.AddBefore(ctx.Name, "wsdecoder", this.NewWebsocketDecoder()); p.AddBefore(ctx.Name, "wsencoder", this.NewWebSocketEncoder()); encoderName = ctx.Name; } else { p.Replace(ctx.Name, "wsdecoder", this.NewWebsocketDecoder()); encoderName = p.Context <HttpResponseEncoder>().Name; p.AddBefore(encoderName, "wsencoder", this.NewWebSocketEncoder()); } channel.WriteAndFlushAsync(response).ContinueWith(t => { if (t.Status == TaskStatus.RanToCompletion) { p.Remove(encoderName); completion.TryComplete(); } else { completion.TrySetException(t.Exception); } }); }
/// <summary> /// Inserts a ChannelHandler before an existing handler of this pipeline. // The name of the handlers is taken from the NameAttribute of the handler class. /// </summary> /// <typeparam name="TBefore"></typeparam> /// <param name="channelPipeline"></param> /// <param name="handler"></param> /// <returns></returns> public static IChannelPipeline AddBefore <TBefore>(this IChannelPipeline channelPipeline, IChannelHandler handler) { var name = handler.GetType().GetTypeInfo().GetCustomAttribute <NameAttribute>(false).Name; var baseName = typeof(TBefore).GetTypeInfo().GetCustomAttribute <NameAttribute>(false).Name; return(channelPipeline.AddBefore(baseName, name, handler)); }
protected internal override void addCodec(IChannelHandlerContext ctx) { IChannelPipeline p = ctx.Channel.Pipeline; string name = ctx.Name; p.AddBefore(name, null, codec); }
protected override void AddCodec(IChannelHandlerContext ctx) { IChannelPipeline p = ctx.Channel.Pipeline; string name = ctx.Name; p.AddBefore(name, null, _codecWrapper); }
public override void HandlerAdded(IChannelHandlerContext ctx) { IChannelPipeline cp = ctx.Pipeline; if (cp.Get <WebSocketServerProtocolHandshakeHandler>() is null) { // Add the WebSocketHandshakeHandler before this one. _ = cp.AddBefore(ctx.Name, nameof(WebSocketServerProtocolHandshakeHandler), new WebSocketServerProtocolHandshakeHandler(_serverConfig)); } if (_serverConfig.DecoderConfig.WithUTF8Validator && cp.Get <Utf8FrameValidator>() is null) { // Add the UFT8 checking before this one. _ = cp.AddBefore(ctx.Name, nameof(Utf8FrameValidator), new Utf8FrameValidator()); } }
/// <summary> /// Inserts a ChannelHandler before an existing handler of this pipeline. // The name of the handlers is taken from the NameAttribute of the handler class. /// </summary> /// <typeparam name="TNewHandler">The type of the new handler.</typeparam> /// <typeparam name="TBefore">The type of the handler to be added before.</typeparam> /// <param name="channelPipeline">The channel pipeline.</param> /// <returns></returns> public static IChannelPipeline AddBefore <TNewHandler, TBefore>(this IChannelPipeline channelPipeline) where TNewHandler : class, IChannelHandler { return(channelPipeline.AddBefore <TBefore>(Activator.CreateInstance <TNewHandler>())); }