public WorkflowState Provider(WorkflowContinuation <ContextWrapper> workflowContinuation, ContextWrapper wrapper)
        {
            Session   session;
            IPAddress endpointAddress = wrapper.Context.EndpointAddress();

            if (!sessionMap.TryGetValue(endpointAddress, out session))
            {
                session = new Session(endpointAddress);
                session[CsrfTokenName]      = Guid.NewGuid().ToString();
                sessionMap[endpointAddress] = session;
            }
            else
            {
                // If the session exists, set the expired flag before we update the last connection date/time.
                // Once set, stays set until explicitly cleared.
                session.Expired |= session.IsExpired(ExpireInSeconds);
            }

            wrapper.Session = session;

            session.UpdateLastConnectionTime();
            WorkflowState ret = CheckExpirationAndAuthorization(workflowContinuation, wrapper, session);

            return(ret);
        }
        protected WorkflowState CheckExpirationAndAuthorization(WorkflowContinuation <ContextWrapper> workflowContinuation, ContextWrapper wrapper, Session session)
        {
            // Inspect the route to see if we should do session expiration and/or session authorization checks.
            WorkflowState ret   = WorkflowState.Continue;
            RouteEntry    entry = null;
            PathParams    parms = null;

            if (routeTable.TryGetRouteEntry(wrapper.Context.Verb(), wrapper.Context.Path(), out entry, out parms))
            {
                if (entry.SessionExpirationHandler != null)
                {
                    ret = entry.SessionExpirationHandler(workflowContinuation, wrapper, session, parms);
                }

                if (ret == WorkflowState.Continue)
                {
                    if (entry.AuthorizationHandler != null)
                    {
                        ret = entry.AuthorizationHandler(workflowContinuation, wrapper, session, parms);
                    }
                }
            }

            return(ret);
        }
        /// <summary>
        /// A workflow item implementing the ContextWrapper handler.
        /// </summary>
        public WorkflowState Process(WorkflowContinuation <ContextWrapper> workflowContinuation, ContextWrapper context)
        {
            // Create a workflow context and queue it.
            requests.Enqueue(new WorkflowContext(workflowContinuation, context));
            semQueue.Release();

            return(WorkflowState.Defer);
        }
        /// <summary>
        /// A workflow item implementing the HttpListenerContext handler.
        /// </summary>
        public WorkflowState Process(WorkflowContinuation <HttpListenerContext> workflowContinuation, HttpListenerContext context)
        {
            // Create a workflow context and queue it.
            requests.Enqueue(new WorkflowContext(workflowContinuation, context));
            semQueue.Release();

            return(WorkflowState.Defer);
        }
 /// <summary>
 /// Continue a deferred workflow, unless it is aborted.
 /// </summary>
 public void Continue(WorkflowContinuation <T> wc, T data)
 {
     if (!wc.Abort)
     {
         wc.Defer = false;
         InternalContinue(wc, data);
     }
 }
 /// <summary>
 /// Continue a deferred workflow, unless it is aborted.
 /// </summary>
 public void Continue(WorkflowContinuation <T> wc, T data)
 {
     // TODO: Throw exception instead?
     if ((!wc.Abort) && (!wc.Done))
     {
         wc.Defer = false;
         InternalContinue(wc, data);
     }
 }
        /// <summary>
        /// Route the request.  If no route exists, the workflow continues, otherwise, we return the route handler's continuation state.
        /// </summary>
        public WorkflowState Route(WorkflowContinuation <HttpListenerContext> workflowContinuation, HttpListenerContext context)
        {
            WorkflowState ret   = WorkflowState.Continue;
            RouteEntry    entry = null;

            if (routeTable.TryGetRouteEntry(context.Verb(), context.Path(), out entry))
            {
                if (entry.RouteProvider != null)
                {
                    ret = entry.RouteProvider(workflowContinuation, context);
                }
            }

            return(ret);
        }
Example #8
0
        /// <summary>
        /// Internally, we execute workflow steps until:
        /// 1. we reach the end of the workflow chain
        /// 2. we are instructed to abort the workflow
        /// 3. we are instructed to defer execution until later.
        /// </summary>
        protected void InternalContinue(WorkflowContinuation <T> wc, T data)
        {
            while ((wc.WorkflowStep < items.Count) && !wc.Abort && !wc.Defer && !wc.Done)
            {
                try
                {
                    WorkflowState state = items[wc.WorkflowStep++].Execute(wc, data);

                    switch (state)
                    {
                    case WorkflowState.Abort:
                        wc.Abort = true;
                        wc.Workflow.AbortHandler(data);
                        break;

                    case WorkflowState.Defer:
                        wc.Defer = true;
                        break;

                    case WorkflowState.Done:
                        wc.Done = true;
                        break;
                    }
                }
                catch (Exception ex)
                {
                    // Yes, the user's exception handler could itself through an exception
                    // from which we need to protect ourselves.
                    try
                    {
                        wc.Workflow.ExceptionHandler(data, ex);
                    }
                    catch { /* Now what? */ }
                    // TODO: Should we use a different flag, like "Exception"?  Can't be Abort, as this invokes an app-specific handler.
                    wc.Done = true;
                }
            }

            if (wc.Defer)
            {
                // Synchronization, we're done with this loop and the workflow can now continue on another thread.
                wc.Deferred = true;
            }
        }
        /// <summary>
        /// Route the request.  If no route exists, the workflow continues, otherwise, we return the route handler's continuation state.
        /// </summary>
        public WorkflowState Route(WorkflowContinuation <ContextWrapper> workflowContinuation, ContextWrapper wrapper)
        {
            WorkflowState ret     = WorkflowState.Continue;
            RouteEntry    entry   = null;
            Session       session = sessionManager != null ? sessionManager[wrapper.Context] : null;
            PathParams    parms   = null;

            // Makes debugging easier to declare these variable here.
            string verb = wrapper.Context.Verb();
            string path = wrapper.Context.Path();

            if (routeTable.TryGetRouteEntry(verb, path, wrapper.Context.Request.ContentType, out entry, out parms))
            {
                if (entry.RouteHandler != null)
                {
                    ret = entry.RouteHandler(workflowContinuation, wrapper, session, parms);
                }
            }

            return(ret);
        }
        public WorkflowState GetContent(WorkflowContinuation <ContextWrapper> workflowContinuation, ContextWrapper wrapper)
        {
            // Only try to get the file if we DO NOT have a pending page response that some route handler or other workflow step created.
            if (wrapper.PendingResponse == null)
            {
                // Get the request.
                HttpListenerRequest  request  = wrapper.Context.Request;
                HttpListenerResponse response = wrapper.Context.Response;

                // Get the path, everything up to the first ? and excluding the leading "/"
                string path = wrapper.Context.Path();
                string ext  = wrapper.Context.Extension();

                // Console.WriteLine(path);

                // Default to index.html if only the URL is provided with no additional page information.
                if (String.IsNullOrEmpty(path))
                {
                    path = "index.html";
                    ext  = "html";
                }

                if (String.IsNullOrEmpty(ext))
                {
                    path = path + ".html";
                }

                path = websitePath + "\\" + path;
                FileExtensionHandler extHandler;

                if (extensionLoaderMap.TryGetValue(ext, out extHandler))
                {
                    extHandler.Loader(wrapper, path, ext);
                    wrapper.PendingResponse.MimeType = extHandler.ContentType;
                }
            }

            return(WorkflowState.Continue);
        }
        public WorkflowState GetContent(WorkflowContinuation <HttpListenerContext> workflowContinuation, HttpListenerContext context)
        {
            // Get the request.
            HttpListenerRequest  request  = context.Request;
            HttpListenerResponse response = context.Response;

            // Get the path, everything up to the first ? and excluding the leading "/"
            string path = context.Path();
            string ext  = context.Extension();

            // Default to index.html if only the URL is provided with no additional page information.
            if (String.IsNullOrEmpty(path))
            {
                path = "index.html";
                ext  = "html";
            }

            if (String.IsNullOrEmpty(ext))
            {
                path = path + ".html";
            }

            path = websitePath + "\\" + path;
            FileExtensionHandler extHandler;

            if (extensionLoaderMap.TryGetValue(ext, out extHandler))
            {
                byte[] data = extHandler.Loader(context, path, ext);
                response.ContentEncoding         = Encoding.UTF8;
                context.Response.ContentType     = extHandler.ContentType;
                context.Response.ContentLength64 = data.Length;
                context.Response.OutputStream.Write(data, 0, data.Length);
                response.StatusCode = 200;                                      // OK
                response.OutputStream.Close();
            }

            return(WorkflowState.Done);
        }
Example #12
0
        protected WorkflowState CheckExpirationAndAuthorization(WorkflowContinuation <HttpListenerContext> workflowContinuation, HttpListenerContext context, Session session)
        {
            // Inspect the route to see if we should do session expiration and/or session authorization checks.
            WorkflowState ret   = WorkflowState.Continue;
            RouteEntry    entry = null;

            if (routeTable.TryGetRouteEntry(context.Verb(), context.Path(), out entry))
            {
                if (entry.SessionExpirationProvider != null)
                {
                    ret = entry.SessionExpirationProvider(workflowContinuation, context, session);
                }

                if (ret == WorkflowState.Continue)
                {
                    if (entry.AuthorizationProvider != null)
                    {
                        ret = entry.AuthorizationProvider(workflowContinuation, context, session);
                    }
                }
            }

            return(ret);
        }
 public WorkflowContext(WorkflowContinuation <ContextWrapper> workflowContinuation, ContextWrapper context)
 {
     this.workflowContinuation = workflowContinuation;
     this.context = context;
 }
 /// <summary>
 /// Execute the workflow item method.
 /// </summary>
 public WorkflowState Execute(WorkflowContinuation <T> workflowContinuation, T data)
 {
     return(doWork(workflowContinuation, data));
 }
 public WorkflowContext(WorkflowContinuation <HttpListenerContext> workflowContinuation, HttpListenerContext context)
 {
     this.workflowContinuation = workflowContinuation;
     this.context = context;
 }
        /// <summary>
        /// Execute the workflow from the beginning.
        /// </summary>
        public void Execute(T data)
        {
            WorkflowContinuation <T> continuation = new WorkflowContinuation <T>(this);

            InternalContinue(continuation, data);
        }