/// <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);
        }
Exemple #2
0
        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);
        }
Exemple #6
0
        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>()));
 }