Exemplo n.º 1
0
        public Yield Invoke(Plug plug, string verb, XUri uri, DreamMessage request, Result <DreamMessage> response)
        {
            // we only support GET as verb
            DreamMessage reply;

            if ((verb != Verb.GET) && (verb != Verb.HEAD))
            {
                reply = new DreamMessage(DreamStatus.MethodNotAllowed, null, null);
                reply.Headers.Allow = Verb.GET + "," + Verb.HEAD;
            }
            else
            {
                bool head = (verb == Verb.HEAD);

                // try to load the assembly
                System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(uri.Host);
                Version  version   = assembly.GetName().Version;
                DateTime timestamp = new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2);

                // check if request is just about re-validation
                if (!head && request.CheckCacheRevalidation(timestamp))
                {
                    reply = DreamMessage.NotModified();
                }
                else
                {
                    try {
                        System.IO.Stream stream = assembly.GetManifestResourceStream(uri.Path.Substring(1));
                        if (stream != null)
                        {
                            MimeType mime = MimeType.New(uri.GetParam(DreamOutParam.TYPE, null)) ?? MimeType.BINARY;
                            reply = new DreamMessage(DreamStatus.Ok, null, mime, stream.Length, head ? System.IO.Stream.Null : stream);
                            if (head)
                            {
                                stream.Close();
                            }
                            else
                            {
                                reply.SetCacheMustRevalidate(timestamp);
                            }
                        }
                        else
                        {
                            reply = DreamMessage.NotFound("could not find resource");
                        }
                    } catch (System.IO.FileNotFoundException) {
                        reply = DreamMessage.NotFound("could not find resource");
                    } catch (Exception e) {
                        reply = DreamMessage.InternalError(e);
                    }
                }
            }
            response.Return(reply);
            yield break;
        }
Exemplo n.º 2
0
 /// <summary>
 /// Create a new instance for a <see cref="DreamStatus.InternalError"/> condition.
 /// </summary>
 /// <param name="innerException">The exception that cause the internal error for the request.</param>
 public DreamInternalErrorException(Exception innerException) : base(DreamMessage.InternalError(innerException), innerException.Message)
 {
 }
Exemplo n.º 3
0
 /// <summary>
 /// Create a new instance for an <see cref="DreamStatus.InternalError"/> failure.
 /// </summary>
 /// <param name="message">Text message to use for <see cref="Exception.Message"/> and the internal <see cref="DreamMessage"/>.</param>
 public DreamInternalErrorException(string message) : base(DreamMessage.InternalError(message), message)
 {
 }
Exemplo n.º 4
0
        //--- Constructors ---

        /// <summary>
        /// Create a new instance for an <see cref="DreamStatus.InternalError"/> failure.
        /// </summary>
        public DreamInternalErrorException() : base(DreamMessage.InternalError())
        {
        }
Exemplo n.º 5
0
        private Dictionary <string, string> CheckServiceLicense()
        {
            // check request validity (unless it's for the @config uri, which is a special case)
            Dictionary <string, string> result = null;

            if ((Feature.Service.Self != null) && (Feature.Service is IDreamServiceLicense) && !(Uri.LastSegment ?? string.Empty).EqualsInvariant("@config"))
            {
                string service_license = ((IDreamServiceLicense)Feature.Service).ServiceLicense;
                if (string.IsNullOrEmpty(service_license))
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license missing"));
                }

                // extract public RSA key for validation
                RSACryptoServiceProvider public_key = RSAUtil.ProviderFrom(Feature.Service.GetType().Assembly);
                if (public_key == null)
                {
                    throw new DreamAbortException(DreamMessage.InternalError("service assembly invalid"));
                }

                // validate the service-license
                try {
                    // parse service-license
                    result = HttpUtil.ParseNameValuePairs(service_license);
                    if (!Encoding.UTF8.GetBytes(service_license.Substring(0, service_license.LastIndexOf(','))).VerifySignature(result["dsig"], public_key))
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("invalid service-license"));
                    }
                } catch (Exception e) {
                    // unexpected error, blame it on the license
                    if (e is DreamAbortException)
                    {
                        throw;
                    }
                    else
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license"));
                    }
                }

                // check license
                string text;
                if ((!result.TryGetValue("licensee", out text) || string.IsNullOrEmpty(text)) && !result.ContainsKey("expire"))
                {
                    // unexpected error, blame it on the license
                    throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license"));
                }

                // determine 'now' date-time
                DateTime now          = GlobalClock.UtcNow;
                DateTime?request_date = Request.Headers.Date;
                if (request_date.HasValue)
                {
                    now = (request_date.Value > now) ? request_date.Value : now;
                }

                // check expiration
                DateTime expire;
                if (result.TryGetValue("expire", out text) && (!DateTimeUtil.TryParseInvariant(text, out expire) || (expire.ToUniversalTime() < now)))
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license has expired"));
                }
            }
            return(result);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Perform startup configuration of a service instance.
        /// </summary>
        /// <remarks>
        /// Should not be manually invoked and should only be overridden if <see cref="Start(MindTouch.Xml.XDoc,Autofac.ILifetimeScope,MindTouch.Tasking.Result)"/> isn't already overriden.
        /// </remarks>
        /// <param name="config">Service configuration.</param>
        /// <param name="result">Synchronization handle for coroutine invocation.</param>
        /// <returns>Iterator used by <see cref="Coroutine"/> execution environment.</returns>
        protected virtual Yield Start(XDoc config, Result result)
        {
            Result <DreamMessage> res;

            // store configuration and uri
            _config = config;
            _self   = Plug.New(config["uri.self"].AsUri);
            if (_self == null)
            {
                throw new ArgumentNullException("config", "Missing element'uri.self'");
            }
            _owner = Plug.New(config["uri.owner"].AsUri);

            // check for service access keys
            var internalAccessKey = config["internal-service-key"].AsText;

            if (!string.IsNullOrEmpty(internalAccessKey))
            {
                _internalAccessKey = internalAccessKey;
            }
            var privateAccessKey = config["private-service-key"].AsText;

            if (!string.IsNullOrEmpty(privateAccessKey))
            {
                _privateAccessKey = privateAccessKey;
            }

            // check for api-key settings
            _apikey = config["apikey"].AsText;

            // process 'set-cookie' entries
            var setCookies = DreamCookie.ParseAllSetCookieNodes(config["set-cookie"]);

            if (setCookies.Count > 0)
            {
                Cookies.Update(setCookies, null);
            }

            // grant private access key to self, host, and owner
            var privateAcccessCookie = DreamCookie.NewSetCookie("service-key", PrivateAccessKey, Self.Uri);

            Cookies.Update(privateAcccessCookie, null);
            yield return(Env.At("@grants").Post(DreamMessage.Ok(privateAcccessCookie.AsSetCookieDocument), new Result <DreamMessage>(TimeSpan.MaxValue)));

            if (Owner != null)
            {
                yield return(res = Owner.At("@grants").Post(DreamMessage.Ok(privateAcccessCookie.AsSetCookieDocument), new Result <DreamMessage>(TimeSpan.MaxValue)));

                if (!res.Value.IsSuccessful)
                {
                    throw new ArgumentException("unexpected failure setting grants on owner service");
                }
            }

            // check if this service requires a service-license to work
            if (this is IDreamServiceLicense)
            {
                string service_license = config["service-license"].AsText;
                if (string.IsNullOrEmpty(service_license))
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license missing"));
                }

                // extract public RSA key for validation
                RSACryptoServiceProvider public_key = RSAUtil.ProviderFrom(GetType().Assembly);
                if (public_key == null)
                {
                    throw new DreamAbortException(DreamMessage.InternalError("service assembly invalid"));
                }

                // validate the service-license
                _license = null;
                Dictionary <string, string> values;
                try {
                    // parse service-license
                    values = HttpUtil.ParseNameValuePairs(service_license);
                    if (!Encoding.UTF8.GetBytes(service_license.Substring(0, service_license.LastIndexOf(','))).VerifySignature(values["dsig"], public_key))
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("invalid service-license (1)"));
                    }

                    // check if the SID matches
                    string sid;
                    if (!values.TryGetValue("sid", out sid) || !SID.HasPrefix(XUri.TryParse(sid), true))
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("invalid service-license (2)"));
                    }
                    _license = service_license;
                } catch (Exception e) {
                    // unexpected error, blame it on the license
                    if (e is DreamAbortException)
                    {
                        throw;
                    }
                    throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license (1)"));
                }

                // validate expiration date
                string expirationtext;
                if (values.TryGetValue("expire", out expirationtext))
                {
                    try {
                        DateTime expiration = DateTime.Parse(expirationtext);
                        if (expiration < DateTime.UtcNow)
                        {
                            _license = null;
                        }
                    } catch (Exception e) {
                        _license = null;

                        // unexpected error, blame it on the license
                        if (e is DreamAbortException)
                        {
                            throw;
                        }
                        throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license (2)"));
                    }
                }

                // check if a license was assigned
                if (_license == null)
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license has expired"));
                }
            }
            else
            {
                config["service-license"].RemoveAll();
            }

            // create built-in services
            _storage = Plug.New(config["uri.storage"].AsUri);
            _pubsub  = Plug.New(config["uri.pubsub"].AsUri);

            // done
            _log.Debug("Start");
            result.Return();
        }
Exemplo n.º 7
0
        //--- Methods ---
        internal void Handler(Result <DreamMessage> result)
        {
            DreamMessage request;

            // check if previous feature handler threw an exception
            try {
                if (result.HasException)
                {
                    DreamAbortException abort = result.Exception as DreamAbortException;
                    if (abort != null)
                    {
                        // extract contained message
                        request = abort.Response;
                    }
                    else
                    {
                        // check if this is a cached response we need to forward
                        DreamCachedResponseException cached = result.Exception as DreamCachedResponseException;
                        if (cached != null)
                        {
                            _response.Throw(cached);
                            return;
                        }

                        // convert exception into message
                        DreamMessage          exceptionMessage = null;
                        ExceptionTranslator[] translators      = _context.Feature.ExceptionTranslators;
                        if (translators != null)
                        {
                            bool locallyAttachedContext = false;
                            try {
                                if (DreamContext.CurrentOrNull == null)
                                {
                                    _context.AttachToCurrentTaskEnv();
                                    locallyAttachedContext = true;
                                }
                                foreach (var translate in translators)
                                {
                                    exceptionMessage = translate(_context, result.Exception);
                                    if (exceptionMessage != null)
                                    {
                                        break;
                                    }
                                }
                            } finally {
                                if (locallyAttachedContext)
                                {
                                    _context.DetachFromTaskEnv();
                                }
                            }
                        }
                        if (exceptionMessage == null)
                        {
                            _log.ErrorExceptionFormat(result.Exception, "handler for {0}:{1} failed ({2})", _context.Verb, _context.Uri.ToString(false), _previousName);
                            exceptionMessage = DreamMessage.InternalError(result.Exception);
                        }
                        request = exceptionMessage;
                    }
                }
                else
                {
                    request = result.Value;
                }
            } catch (Exception e) {
                if (result.HasException)
                {
                    _log.ErrorExceptionFormat(result.Exception, "handler for {0}:{1} failed ({2}), cascading via processing exception '{3}'", _context.Verb, _context.Uri.ToString(false), _previousName, e);
                    request = DreamMessage.InternalError(result.Exception);
                }
                else
                {
                    _log.ErrorExceptionFormat(e, "handler for {0}:{1} failed completing stage '{2}'", _context.Verb, _context.Uri.ToString(false), _previousName);
                    request = DreamMessage.InternalError(e);
                }
            }

            // check if feature handler can handle this message
            if (!MainStage || request.IsSuccessful)
            {
                TaskEnv.ExecuteNew(() => Handler_DreamMessage(request));
            }
            else
            {
                // non-success messages skip the main stage
                _response.Return(request);
            }
        }