예제 #1
0
        /// <summary>
        /// Processes the packet within the context. Returns true whether the packet was processed or throttled.
        /// </summary>
        /// <param name="channel">The through which the packet is coming/going out.</param>
        /// <param name="context">The packet context for this operation.</param>
        /// <returns>True whether the packet was processed or throttled, false otherwise.</returns>
        public static ProcessingState Process(Emitter.Connection channel, ProcessingContext context)
        {
            // Only handle stuff with HTTP Context
            var httpContext = context.GetSession <HttpContext>();

            if (httpContext == null)
            {
                return(ProcessingState.Failure);
            }

            // Must have Upgrade: websocket
            string upgradeType;

            if (!httpContext.Request.TryGetHeader("Upgrade", out upgradeType))
            {
                return(ProcessingState.Failure);
            }
            if (String.IsNullOrWhiteSpace(upgradeType))
            {
                return(ProcessingState.Failure);
            }
            if (upgradeType.ToLowerInvariant() != "websocket")
            {
                return(ProcessingState.Failure);
            }

            // This should not be tested with Fiddler2 or another proxy
            NetTrace.WriteLine("Websocket transport requested", channel, NetTraceCategory.WebSocket);

            // Get the websocket handler
            var handler = WebSocketFactory.GetHandler(httpContext.Request, channel, null, null);

            if (handler == null)
            {
                throw new WebSocketException("Requested websocket version is not supported");
            }

            // Upgrade to websocket (handshake)
            var upgrade = handler.Upgrade(context, httpContext);

            // Trace the websocket upgrade
            NetTrace.WriteLine("WebSocket upgrade done", channel, NetTraceCategory.WebSocket);

            // If it's socket.io 1.x, setup the transport

            /*if (httpContext.Request.IsFabric)
             * {
             *  // Set the pipeline
             *  channel.Encoding.PipelineAddBeforeOrLast(
             *      upgrade.Encoder,
             *      Encode.WebSocket);
             *  channel.Decoding.PipelineAddAfterOrFirst(
             *      upgrade.Decoder,
             *      Decode.WebSocket);
             *
             *  // Make sure the session is set
             *  var session = FabricRegistry.Get(httpContext);
             *  if (session != null)
             *  {
             *      // Unbind the old one
             *      channel.Client.UnbindChannel(channel);
             *
             *      // Set the session
             *      channel.Client = session;
             *      channel.FabricSession = session.Handle;
             *      channel.FabricEncoding = httpContext.GetFabricEncoding();
             *  }
             * }*/

            // Trace the channel upgrade
            NetTrace.WriteLine(channel + " was upgraded to websocket transport", channel, NetTraceCategory.Channel);

            // There still might be SSL encoding in the pipeline
            return(ProcessingState.Stop);
        }
예제 #2
0
        /// <summary>
        /// Processes the packet within the context. Returns true whether the packet was processed or throttled.
        /// </summary>
        /// <param name="channel">The through which the packet is coming/going out.</param>
        /// <param name="context">The packet context for this operation.</param>
        /// <returns>True whether the packet was processed or throttled, false otherwise.</returns>
        public static ProcessingState Process(Connection channel, ProcessingContext context)
        {
            // Only handle stuff with HTTP Context
            var httpContext = context.GetSession <HttpContext>();

            if (httpContext == null)
            {
                return(ProcessingState.Failure);
            }

            try
            {
                // Get request
                var request = httpContext.Request;

                // We should apply cross-origin resource sharing first
                if (CorsPolicy.OnRequest(httpContext) == CorsType.Preflight)
                {
                    // Send pending preflight response. It should be empty.
                    context.Channel.Send(HttpHeaders.Create(httpContext.Response));
                    return(ProcessingState.Stop);
                }

                // Try to handle the incoming request
                var handler = Service.Http.GetHandler(httpContext, request.Verb, request.Path);
                if (handler == null)
                {
                    // Send the error as HTTP 404
                    HttpResponse.Send404((Emitter.Connection)context.Channel);
                    return(ProcessingState.Stop);
                }

                // Trace HTTP request
                NetTrace.WriteLine(request.HttpVerb.ToString().ToUpper() + " " + request.Path + " handled by " + handler.GetType().ToString(), channel, NetTraceCategory.Http);

                // Check if session id is present in the cookie. If there is no session id
                // we create a new session.
                HttpSession.OnRequest(httpContext);

                // Check the security and process the request
                if (handler is ISecureHttpHandler)
                {
                    ISecureHttpHandler secure = handler as ISecureHttpHandler;
                    if (secure.Security == null || secure.Security.Authorize(httpContext))
                    {
                        handler.ProcessRequest(httpContext);
                        context.Channel.Send(httpContext.Response); // Send pending
                    }
                }
                else
                {
                    handler.ProcessRequest(httpContext);
                    context.Channel.Send(httpContext.Response); // Send pending
                }

                // Keep-Alive or close?
                if (!httpContext.Response.KeepAlive)
                {
                    channel.Close();
                }

                return(ProcessingState.Stop);
            }
            catch (NonAuthorizedException ex)
            {
                // Send the error as HTTP 500
                HttpResponse.Send401((Emitter.Connection)context.Channel, ex);
                return(ProcessingState.Stop);
            }
            catch (HttpRedirectException)
            {
                // Send the response as it contains the redirect headers
                context.Channel.Send(httpContext.Response);
                return(ProcessingState.Stop);
            }
            catch (Exception ex)
            {
                // Send the error as HTTP 500
                HttpResponse.Send500((Emitter.Connection)context.Channel, ex);
                return(ProcessingState.Stop);
            }
            finally
            {
                // Release the HTTP context back to the pool
                httpContext.TryRelease();
            }
        }