예제 #1
0
        public async Task Should_unload_db_and_send_notification_on_catastrophic_failure()
        {
            UseNewLocalServer();
            using (var store = GetDocumentStore())
            {
                var notifications = new AsyncQueue <DynamicJsonValue>();

                using (Server.ServerStore.NotificationCenter.TrackActions(notifications, null))
                {
                    var database = await GetDatabase(store.Database);

                    Assert.Equal(1, Server.ServerStore.DatabasesLandlord.DatabasesCache.Count());

                    try
                    {
                        throw new Exception("Catastrophy");
                    }
                    catch (Exception e)
                    {
                        database.GetAllStoragesEnvironment().First().Environment.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e));
                    }

                    var ex = Assert.Throws <Exception>(() =>
                    {
                        using (var context = DocumentsOperationContext.ShortTermSingleUse(database))
                        {
                            using (var tx = context.OpenWriteTransaction())
                            {
                                var dynamicJsonValue = new DynamicJsonValue();
                                using (var doc = context.ReadObject(dynamicJsonValue, "users/1", BlittableJsonDocumentBuilder.UsageMode.ToDisk))
                                {
                                    database.DocumentsStorage.Put(context, "users/1", null, doc);
                                }

                                tx.Commit();
                            }
                        }
                    });

                    Assert.Equal("Catastrophy", ex.Message);

                    // db unloaded
                    Assert.True(SpinWait.SpinUntil(() => Server.ServerStore.DatabasesLandlord.DatabasesCache.Any() == false, TimeSpan.FromMinutes(1)));

                    Tuple <bool, DynamicJsonValue> alert;
                    do
                    {
                        alert = await notifications.TryDequeueAsync(TimeSpan.Zero);
                    } while (alert.Item2["Type"].ToString() != NotificationType.AlertRaised.ToString());


                    Assert.Equal(AlertType.CatastrophicDatabaseFailure, alert.Item2[nameof(AlertRaised.AlertType)]);
                    Assert.Contains(database.Name, alert.Item2[nameof(AlertRaised.Title)] as string);
                }

                using (var session = store.OpenSession())
                {
                    session.Store(new User());

                    session.SaveChanges();
                }

                // db loaded again
                Assert.Equal(1, Server.ServerStore.DatabasesLandlord.DatabasesCache.Count());
            }
        }
예제 #2
0
        // Direct copy of the above RunInternal overload, except that it passes the state into the callback strongly-typed and by ref.
        internal static void RunInternal <TState>(ExecutionContext executionContext, ContextCallback <TState> callback, ref TState state)
        {
            // Note: ExecutionContext.RunInternal is an extremely hot function and used by every await, ThreadPool execution, etc.
            // Note: Manual enregistering may be addressed by "Exception Handling Write Through Optimization"
            //       https://github.com/dotnet/coreclr/blob/master/Documentation/design-docs/eh-writethru.md

            // Enregister variables with 0 post-fix so they can be used in registers without EH forcing them to stack
            // Capture references to Thread Contexts
            Thread           currentThread0        = Thread.CurrentThread;
            Thread           currentThread         = currentThread0;
            ExecutionContext previousExecutionCtx0 = currentThread0.ExecutionContext;

            if (previousExecutionCtx0 != null && previousExecutionCtx0.m_isDefault)
            {
                // Default is a null ExecutionContext internally
                previousExecutionCtx0 = null;
            }

            // Store current ExecutionContext and SynchronizationContext as "previousXxx".
            // This allows us to restore them and undo any Context changes made in callback.Invoke
            // so that they won't "leak" back into caller.
            // These variables will cross EH so be forced to stack
            ExecutionContext       previousExecutionCtx = previousExecutionCtx0;
            SynchronizationContext previousSyncCtx      = currentThread0.SynchronizationContext;

            if (executionContext != null && executionContext.m_isDefault)
            {
                // Default is a null ExecutionContext internally
                executionContext = null;
            }

            if (previousExecutionCtx0 != executionContext)
            {
                RestoreChangedContextToThread(currentThread0, executionContext, previousExecutionCtx0);
            }

            ExceptionDispatchInfo edi = null;

            try
            {
                callback.Invoke(ref state);
            }
            catch (Exception ex)
            {
                // Note: we have a "catch" rather than a "finally" because we want
                // to stop the first pass of EH here.  That way we can restore the previous
                // context before any of our callers' EH filters run.
                edi = ExceptionDispatchInfo.Capture(ex);
            }

            // Re-enregistrer variables post EH with 1 post-fix so they can be used in registers rather than from stack
            SynchronizationContext previousSyncCtx1 = previousSyncCtx;
            Thread currentThread1 = currentThread;

            // The common case is that these have not changed, so avoid the cost of a write barrier if not needed.
            if (currentThread1.SynchronizationContext != previousSyncCtx1)
            {
                // Restore changed SynchronizationContext back to previous
                currentThread1.SynchronizationContext = previousSyncCtx1;
            }

            ExecutionContext previousExecutionCtx1 = previousExecutionCtx;
            ExecutionContext currentExecutionCtx1  = currentThread1.ExecutionContext;

            if (currentExecutionCtx1 != previousExecutionCtx1)
            {
                RestoreChangedContextToThread(currentThread1, previousExecutionCtx1, currentExecutionCtx1);
            }

            // If exception was thrown by callback, rethrow it now original contexts are restored
            edi?.Throw();
        }
        protected override async Task <AuthenticationTicket> AuthenticateCoreAsync()
        {
            // Allow login to be constrained to a specific path.
            if (Options.CallbackPath.HasValue && Options.CallbackPath != Request.Path)
            {
                return(null);
            }

            // assumption: if the ContentType is "application/x-www-form-urlencoded" it should be safe to read as it is small.
            if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase) &&
                !string.IsNullOrWhiteSpace(Request.ContentType)
                // May have media/type; charset=utf-8, allow partial match.
                && Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) &&
                Request.Body.CanRead)
            {
                if (!Request.Body.CanSeek)
                {
                    // Buffer in case this body was not meant for us.
                    MemoryStream memoryStream = new MemoryStream();
                    await Request.Body.CopyToAsync(memoryStream);

                    memoryStream.Seek(0, SeekOrigin.Begin);
                    Request.Body = memoryStream;
                }
                IFormCollection form = await Request.ReadFormAsync();

                // Post preview release: a delegate on WsFederationAuthenticationOptions would allow for users to hook their own custom message.
                WsFederationMessage wsFederationMessage = new WsFederationMessage(form);
                if (!wsFederationMessage.IsSignInMessage)
                {
                    Request.Body.Seek(0, SeekOrigin.Begin);
                    return(null);
                }

                MessageReceivedNotification <WsFederationMessage> messageReceivedNotification = null;
                if (Options.Notifications != null && Options.Notifications.MessageReceived != null)
                {
                    messageReceivedNotification = new MessageReceivedNotification <WsFederationMessage> {
                        ProtocolMessage = wsFederationMessage
                    };
                    await Options.Notifications.MessageReceived(messageReceivedNotification);
                }

                if (messageReceivedNotification != null && messageReceivedNotification.Cancel)
                {
                    return(null);
                }

                if (wsFederationMessage.Wresult != null)
                {
                    string token = wsFederationMessage.GetToken();
                    if (Options.Notifications != null && Options.Notifications.SecurityTokenReceived != null)
                    {
                        SecurityTokenReceivedNotification securityTokenReceivedNotification = new SecurityTokenReceivedNotification {
                            SecurityToken = token
                        };
                        await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification);

                        if (securityTokenReceivedNotification.Cancel)
                        {
                            return(null);
                        }
                    }

                    ExceptionDispatchInfo authFailedEx = null;
                    try
                    {
                        ClaimsPrincipal principal      = Options.SecurityTokenHandlers.ValidateToken(token, Options.TokenValidationParameters);
                        ClaimsIdentity  claimsIdentity = principal.Identity as ClaimsIdentity;

                        // Retrieve our cached redirect uri
                        string state = wsFederationMessage.Wctx;
                        AuthenticationProperties properties = GetPropertiesFromWctx(state);

                        AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, properties);

                        Request.Context.Authentication.SignIn(claimsIdentity);
                        if (Options.Notifications != null && Options.Notifications.SecurityTokenValidated != null)
                        {
                            await Options.Notifications.SecurityTokenValidated(new SecurityTokenValidatedNotification { AuthenticationTicket = ticket });
                        }

                        return(ticket);
                    }
                    catch (Exception exception)
                    {
                        // We can't await inside a catch block, capture and handle outside.
                        authFailedEx = ExceptionDispatchInfo.Capture(exception);
                    }

                    if (authFailedEx != null)
                    {
                        if (Options.Notifications != null && Options.Notifications.AuthenticationFailed != null)
                        {
                            // Post preview release: user can update metadata, need consistent messaging.
                            var authenticationFailedNotification = new AuthenticationFailedNotification <WsFederationMessage>()
                            {
                                ProtocolMessage = wsFederationMessage,
                                Exception       = authFailedEx.SourceException
                            };

                            await Options.Notifications.AuthenticationFailed(authenticationFailedNotification);

                            if (!authenticationFailedNotification.Cancel)
                            {
                                authFailedEx.Throw();
                            }
                        }
                        else
                        {
                            authFailedEx.Throw();
                        }
                    }
                }
            }

            return(null);
        }
예제 #4
0
        private async Task ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool async)
        {
            int attempt = 0;
            List <Exception>?exceptions = null;

            while (true)
            {
                Exception?lastException = null;

                try
                {
                    if (async)
                    {
                        await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
                    }
                    else
                    {
                        ProcessNext(message, pipeline);
                    }
                }
                catch (Exception ex)
                {
                    if (exceptions == null)
                    {
                        exceptions = new List <Exception>();
                    }

                    exceptions.Add(ex);

                    lastException = ex;
                }

                TimeSpan delay;

                attempt++;

                var shouldRetry = attempt <= _maxRetries;

                if (lastException != null)
                {
                    if (shouldRetry && message.ResponseClassifier.IsRetriableException(lastException))
                    {
                        GetDelay(attempt, out delay);
                    }
                    else
                    {
                        // Rethrow a singular exception
                        if (exceptions?.Count == 1)
                        {
                            ExceptionDispatchInfo.Capture(lastException).Throw();
                        }

                        throw new AggregateException($"Retry failed after {attempt} tries.", exceptions);
                    }
                }
                else if (message.ResponseClassifier.IsErrorResponse(message.Response))
                {
                    if (shouldRetry && message.ResponseClassifier.IsRetriableResponse(message.Response))
                    {
                        GetDelay(message, attempt, out delay);
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }

                if (delay > TimeSpan.Zero)
                {
                    if (async)
                    {
                        await WaitAsync(delay, message.CancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        Wait(delay, message.CancellationToken);
                    }
                }

                HttpPipelineEventSource.Singleton.RequestRetrying(message.Request, attempt);
            }
        }
예제 #5
0
        /// <summary>Adds the exception to the fault list.</summary>
        /// <param name="exceptionObject">The exception to store.</param>
        /// <remarks>
        /// Must be called under lock.
        /// </remarks>
        private void AddFaultException(object exceptionObject)
        {
            Contract.Requires(exceptionObject != null, "AddFaultException(): Expected a non-null exceptionObject");

            // Initialize the exceptions list if necessary.  The list should be non-null iff it contains exceptions.
            var exceptions = m_faultExceptions;

            if (exceptions == null)
            {
                m_faultExceptions = exceptions = new List <ExceptionDispatchInfo>(1);
            }
            else
            {
                Contract.Assert(exceptions.Count > 0, "Expected existing exceptions list to have > 0 exceptions.");
            }

            // Handle Exception by capturing it into an ExceptionDispatchInfo and storing that
            var exception = exceptionObject as Exception;

            if (exception != null)
            {
                exceptions.Add(ExceptionDispatchInfo.Capture(exception));
            }
            else
            {
                // Handle ExceptionDispatchInfo by storing it into the list
                var edi = exceptionObject as ExceptionDispatchInfo;
                if (edi != null)
                {
                    exceptions.Add(edi);
                }
                else
                {
                    // Handle enumerables of exceptions by capturing each of the contained exceptions into an EDI and storing it
                    var exColl = exceptionObject as IEnumerable <Exception>;
                    if (exColl != null)
                    {
#if DEBUG
                        int numExceptions = 0;
#endif
                        foreach (var exc in exColl)
                        {
#if DEBUG
                            Contract.Assert(exc != null, "No exceptions should be null");
                            numExceptions++;
#endif
                            exceptions.Add(ExceptionDispatchInfo.Capture(exc));
                        }
#if DEBUG
                        Contract.Assert(numExceptions > 0, "Collection should contain at least one exception.");
#endif
                    }
                    else
                    {
                        // Handle enumerables of EDIs by storing them directly
                        var ediColl = exceptionObject as IEnumerable <ExceptionDispatchInfo>;
                        if (ediColl != null)
                        {
                            exceptions.AddRange(ediColl);
#if DEBUG
                            Contract.Assert(exceptions.Count > 0, "There should be at least one dispatch info.");
                            foreach (var tmp in exceptions)
                            {
                                Contract.Assert(tmp != null, "No dispatch infos should be null");
                            }
#endif
                        }
                        // Anything else is a programming error
                        else
                        {
                            throw new ArgumentException(Environment.GetResourceString("TaskExceptionHolder_UnknownExceptionType"), "exceptionObject");
                        }
                    }
                }
            }


            // If all of the exceptions are ThreadAbortExceptions and/or
            // AppDomainUnloadExceptions, we do not want the finalization
            // probe to propagate them, so we consider the holder to be
            // handled.  If a subsequent exception comes in of a different
            // kind, we will reactivate the holder.
            for (int i = 0; i < exceptions.Count; i++)
            {
                var t = exceptions[i].SourceException.GetType();
                if (t != typeof(ThreadAbortException) && t != typeof(AppDomainUnloadedException))
                {
                    MarkAsUnhandled();
                    break;
                }
                else if (i == exceptions.Count - 1)
                {
                    MarkAsHandled(false);
                }
            }
        }
예제 #6
0
        internal static InboundFrame ReadFrom(Stream reader, byte[] frameHeaderBuffer)
        {
            int type = default;

            try
            {
                type = reader.ReadByte();
            }
            catch (IOException ioe)
            {
                // If it's a WSAETIMEDOUT SocketException, unwrap it.
                // This might happen when the limit of half-open connections is
                // reached.
                if (ioe.InnerException is null ||
                    !(ioe.InnerException is SocketException exception) ||
                    exception.SocketErrorCode != SocketError.TimedOut)
                {
                    throw;
                }

                ExceptionDispatchInfo.Capture(ioe.InnerException).Throw();
            }

            switch (type)
            {
            case -1:
                throw new EndOfStreamException("Reached the end of the stream. Possible authentication failure.");

            case 'A':
                // Probably an AMQP protocol header, otherwise meaningless
                ProcessProtocolHeader(reader);
                break;
            }

            reader.Read(frameHeaderBuffer, 0, frameHeaderBuffer.Length);
            int channel     = NetworkOrderDeserializer.ReadUInt16(new ReadOnlySpan <byte>(frameHeaderBuffer));
            int payloadSize = NetworkOrderDeserializer.ReadInt32(new ReadOnlySpan <byte>(frameHeaderBuffer, 2, 4)); // FIXME - throw exn on unreasonable value

            const int EndMarkerLength = 1;
            // Is returned by InboundFrame.ReturnPayload in Connection.MainLoopIteration
            int readSize = payloadSize + EndMarkerLength;

            byte[] payloadBytes = ArrayPool <byte> .Shared.Rent(readSize);

            int bytesRead = 0;

            try
            {
                while (bytesRead < readSize)
                {
                    bytesRead += reader.Read(payloadBytes, bytesRead, readSize - bytesRead);
                }
            }
            catch (Exception)
            {
                // Early EOF.
                ArrayPool <byte> .Shared.Return(payloadBytes);

                throw new MalformedFrameException($"Short frame - expected to read {readSize} bytes, only got {bytesRead} bytes");
            }

            if (payloadBytes[payloadSize] != Constants.FrameEnd)
            {
                ArrayPool <byte> .Shared.Return(payloadBytes);

                throw new MalformedFrameException($"Bad frame end marker: {payloadBytes[payloadSize]}");
            }

            return(new InboundFrame((FrameType)type, channel, new Memory <byte>(payloadBytes, 0, payloadSize), payloadBytes));
        }
예제 #7
0
 /// <nodoc />
 public RecoverableExceptionFailure(BuildXLException exception)
 {
     Contract.RequiresNotNull(exception);
     m_exceptionDispatchInfo = ExceptionDispatchInfo.Capture(exception);
 }
예제 #8
0
        public static void Do <TResult1, TResult2>(RemoteWebDriver browser,
                                                   Func <IWebElement> webElementSource,
                                                   Action <Func <IWebElement> > seleniumAction,
                                                   Func <Func <IWebElement>, TResult1> expectedConditionAfterAction,
                                                   Func <IWebDriver, TResult2> errorWaitCondition = null,
                                                   int maxRetries    = 10,
                                                   WaitTime waitTime = WaitTime.Short,
                                                   [CallerMemberName] string caller    = "",
                                                   StubbornConfiguration configuration = null,
                                                   string logMessage = null)
        {
            configuration = configuration ?? StubbornConfiguration.Default;

            configuration.Log.Info(logMessage ?? caller);

            var wait      = new WebDriverWait(browser, waitTime.ToTimeSpan());
            int attemptNo = 0;

            while (true)
            {
                configuration.BeforeDoActions.ForEach(action => action(browser));

                var actionException = Try(() => seleniumAction(webElementSource));

                configuration.BetweenDoActions.ForEach(action => action(browser));

                var expectedConditionException = Try(() => wait.Until(expectedConditionAfterAction, webElementSource));

                if (actionException == null && expectedConditionException == null)
                {
                    return;
                }

                if (attemptNo > 0 && actionException != null && expectedConditionException == null)
                {
                    configuration.Log.Warning($"Action threw exception (\"{actionException.Message}\") but excepted condition is met");
                    return;
                }

                var relevantException = actionException ?? expectedConditionException;
                if (attemptNo >= maxRetries)
                {
                    ExceptionDispatchInfo.Capture(relevantException).Throw();
                }

                attemptNo++;
                try
                {
                    if (errorWaitCondition != null)
                    {
                        wait.Until(errorWaitCondition);
                    }
                    else
                    {
                        Thread.Sleep(WaitTime.Short.ToTimeSpan());
                    }
                }
                catch (Exception)
                {
                    // Ignore wait errors - just try to perform the core action again
                }

                configuration.Log.Warning($"Repeating {caller}");
            }
        }
예제 #9
0
        /// <summary>
        /// Searches the 'Authorization' header for a 'Bearer' token. If the 'Bearer' token is found, it is validated using <see cref="T:Microsoft.IdentityModel.Tokens.TokenValidationParameters" /> set in the options.
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string    token;
            Exception obj;
            AuthenticationFailedContext authenticationFailedContext;
            int num;

            try
            {
                var messageReceivedContext = new MessageReceivedContext(Context, Scheme, Options);
                await Events.MessageReceived(messageReceivedContext);

                if (messageReceivedContext.Result != null)
                {
                    return(messageReceivedContext.Result);
                }
                token = messageReceivedContext.Token;
                if (string.IsNullOrEmpty(token))
                {
                    string header = Request.Headers["Authorization"];
                    if (string.IsNullOrEmpty(header))
                    {
                        return(AuthenticateResult.NoResult());
                    }
                    if (header.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
                    {
                        token = header.Substring("Bearer ".Length).Trim();
                    }
                    if (string.IsNullOrEmpty(token))
                    {
                        return(AuthenticateResult.NoResult());
                    }
                }
                if (_configuration == null && Options.ConfigurationManager != null)
                {
                    var configurationAsync = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);

                    _configuration = configurationAsync;
                }
                var validationParameters1 = Options.TokenValidationParameters.Clone();
                if (_configuration != null)
                {
                    var strArray = new string[1]
                    {
                        _configuration.Issuer
                    };
                    var validationParameters2 = validationParameters1;
                    var validIssuers          = validationParameters1.ValidIssuers;
                    var obj1 = (validIssuers != null ? validIssuers.Concat(strArray) : null) ?? strArray;
                    validationParameters2.ValidIssuers = obj1;
                    var validationParameters3 = validationParameters1;
                    var issuerSigningKeys     = validationParameters1.IssuerSigningKeys;
                    var securityKeys          = (issuerSigningKeys != null ? issuerSigningKeys.Concat(_configuration.SigningKeys) : null) ?? _configuration.SigningKeys;
                    validationParameters3.IssuerSigningKeys = securityKeys;
                }
                List <Exception> exceptionList = null;
                foreach (var securityTokenValidator in Options.SecurityTokenValidators)
                {
                    if (securityTokenValidator.CanReadToken(token))
                    {
                        SecurityToken   securityToken;
                        ClaimsPrincipal claimsPrincipal;
                        try
                        {
                            claimsPrincipal = securityTokenValidator.ValidateToken(token, validationParameters1, out securityToken);
                        }
                        catch (Exception ex)
                        {
                            //Logger.TokenValidationFailed(ex);
                            if (Options.RefreshOnIssuerKeyNotFound && Options.ConfigurationManager != null && ex is SecurityTokenSignatureKeyNotFoundException)
                            {
                                Options.ConfigurationManager.RequestRefresh();
                            }
                            if (exceptionList == null)
                            {
                                exceptionList = new List <Exception>(1);
                            }
                            exceptionList.Add(ex);
                            continue;
                        }
                        //Logger.TokenValidationSucceeded();
                        var validatedContext = new TokenValidatedContext(Context, Scheme, Options);
                        validatedContext.Principal     = claimsPrincipal;
                        validatedContext.SecurityToken = securityToken;
                        var tokenValidatedContext = validatedContext;
                        await Events.TokenValidated(tokenValidatedContext);

                        if (tokenValidatedContext.Result != null)
                        {
                            return(tokenValidatedContext.Result);
                        }
                        if (Options.SaveToken)
                        {
                            tokenValidatedContext.Properties.StoreTokens(new AuthenticationToken[1]
                            {
                                new AuthenticationToken()
                                {
                                    Name  = "access_token",
                                    Value = token
                                }
                            });
                        }
                        tokenValidatedContext.Success();
                        return(tokenValidatedContext.Result);
                    }
                }
                if (exceptionList == null)
                {
                    return(AuthenticateResult.Fail("No SecurityTokenValidator available for token: " + token ?? "[null]"));
                }
                authenticationFailedContext = new AuthenticationFailedContext(Context, Scheme, Options)
                {
                    Exception = exceptionList.Count == 1 ? exceptionList[0] : new AggregateException(exceptionList)
                };
                await Events.AuthenticationFailed(authenticationFailedContext);

                return(authenticationFailedContext.Result == null?AuthenticateResult.Fail(authenticationFailedContext.Exception) : authenticationFailedContext.Result);
            }
            catch (Exception ex)
            {
                obj = ex;
                num = 1;
            }
            if (num == 1)
            {
                var ex = obj;
                //Logger.ErrorProcessingMessage(ex);
                authenticationFailedContext = new AuthenticationFailedContext(Context, Scheme, Options)
                {
                    Exception = ex
                };
                await Events.AuthenticationFailed(authenticationFailedContext);

                if (authenticationFailedContext.Result != null)
                {
                    return(authenticationFailedContext.Result);
                }
                var source = obj as Exception;
                if (source == null)
                {
                    throw obj;
                }
                ExceptionDispatchInfo.Capture(source).Throw();
                authenticationFailedContext = null;
            }

            return(null);
        }
예제 #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="messages"></param>
        /// <param name="timeout"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        internal async Task <long[]> ScheduleMessageInternalAsync(
            IList <ServiceBusMessage> messages,
            TimeSpan timeout,
            CancellationToken cancellationToken = default)
        {
            var sendLink = default(SendingAmqpLink);

            try
            {
                var request = AmqpRequestMessage.CreateRequest(
                    ManagementConstants.Operations.ScheduleMessageOperation,
                    timeout,
                    null);

                if (_sendLink.TryGetOpenedObject(out sendLink))
                {
                    request.AmqpMessage.ApplicationProperties.Map[ManagementConstants.Request.AssociatedLinkName] = sendLink.Name;
                }

                List <AmqpMap> entries = new List <AmqpMap>();
                foreach (ServiceBusMessage message in messages)
                {
                    using AmqpMessage amqpMessage = AmqpMessageConverter.SBMessageToAmqpMessage(message);
                    var entry = new AmqpMap();
                    ArraySegment <byte>[] payload = amqpMessage.GetPayload();
                    var buffer = new BufferListStream(payload);
                    ArraySegment <byte> value = buffer.ReadBytes((int)buffer.Length);
                    entry[ManagementConstants.Properties.Message]   = value;
                    entry[ManagementConstants.Properties.MessageId] = message.MessageId;

                    if (!string.IsNullOrWhiteSpace(message.SessionId))
                    {
                        entry[ManagementConstants.Properties.SessionId] = message.SessionId;
                    }

                    if (!string.IsNullOrWhiteSpace(message.PartitionKey))
                    {
                        entry[ManagementConstants.Properties.PartitionKey] = message.PartitionKey;
                    }

                    if (!string.IsNullOrWhiteSpace(message.ViaPartitionKey))
                    {
                        entry[ManagementConstants.Properties.ViaPartitionKey] = message.ViaPartitionKey;
                    }

                    entries.Add(entry);
                }

                request.Map[ManagementConstants.Properties.Messages] = entries;

                AmqpResponseMessage amqpResponseMessage = await ManagementUtilities.ExecuteRequestResponseAsync(
                    _connectionScope,
                    _managementLink,
                    request,
                    timeout).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                if (amqpResponseMessage.StatusCode == AmqpResponseStatusCode.OK)
                {
                    var sequenceNumbers = amqpResponseMessage.GetValue <long[]>(ManagementConstants.Properties.SequenceNumbers);
                    if (sequenceNumbers == null || sequenceNumbers.Length < 1)
                    {
                        throw new ServiceBusException(true, "Could not schedule message successfully.");
                    }

                    return(sequenceNumbers);
                }
                else
                {
                    throw amqpResponseMessage.ToMessagingContractException();
                }
            }
            catch (Exception exception)
            {
                ExceptionDispatchInfo.Capture(AmqpExceptionHelper.TranslateException(
                                                  exception,
                                                  sendLink?.GetTrackingId(),
                                                  null,
                                                  HasLinkCommunicationError(sendLink)))
                .Throw();

                throw; // will never be reached
            }
        }
예제 #11
0
        internal void ValidateCreateContext(
            string package,
            bool isServer,
            NetworkCredential credential,
            string servicePrincipalName,
            ChannelBinding channelBinding,
            ProtectionLevel protectionLevel,
            TokenImpersonationLevel impersonationLevel)
        {
            if (_exception != null && !_canRetryAuthentication)
            {
                ExceptionDispatchInfo.Capture(_exception).Throw();
            }

            if (_context != null && _context.IsValidContext)
            {
                throw new InvalidOperationException(SR.net_auth_reauth);
            }

            if (credential == null)
            {
                throw new ArgumentNullException(nameof(credential));
            }

            if (servicePrincipalName == null)
            {
                throw new ArgumentNullException(nameof(servicePrincipalName));
            }

            NegotiateStreamPal.ValidateImpersonationLevel(impersonationLevel);
            if (_context != null && IsServer != isServer)
            {
                throw new InvalidOperationException(SR.net_auth_client_server);
            }

            _exception = null;
            _remoteOk  = false;
            _framer    = new StreamFramer(_innerStream);
            _framer.WriteHeader.MessageId = FrameHeader.HandshakeId;

            _expectedProtectionLevel    = protectionLevel;
            _expectedImpersonationLevel = isServer ? impersonationLevel : TokenImpersonationLevel.None;
            _writeSequenceNumber        = 0;
            _readSequenceNumber         = 0;

            ContextFlagsPal flags = ContextFlagsPal.Connection;

            // A workaround for the client when talking to Win9x on the server side.
            if (protectionLevel == ProtectionLevel.None && !isServer)
            {
                package = NegotiationInfoClass.NTLM;
            }
            else if (protectionLevel == ProtectionLevel.EncryptAndSign)
            {
                flags |= ContextFlagsPal.Confidentiality;
            }
            else if (protectionLevel == ProtectionLevel.Sign)
            {
                // Assuming user expects NT4 SP4 and above.
                flags |= (ContextFlagsPal.ReplayDetect | ContextFlagsPal.SequenceDetect | ContextFlagsPal.InitIntegrity);
            }

            if (isServer)
            {
                if (_extendedProtectionPolicy.PolicyEnforcement == PolicyEnforcement.WhenSupported)
                {
                    flags |= ContextFlagsPal.AllowMissingBindings;
                }

                if (_extendedProtectionPolicy.PolicyEnforcement != PolicyEnforcement.Never &&
                    _extendedProtectionPolicy.ProtectionScenario == ProtectionScenario.TrustedProxy)
                {
                    flags |= ContextFlagsPal.ProxyBindings;
                }
            }
            else
            {
                // Server side should not request any of these flags.
                if (protectionLevel != ProtectionLevel.None)
                {
                    flags |= ContextFlagsPal.MutualAuth;
                }

                if (impersonationLevel == TokenImpersonationLevel.Identification)
                {
                    flags |= ContextFlagsPal.InitIdentify;
                }

                if (impersonationLevel == TokenImpersonationLevel.Delegation)
                {
                    flags |= ContextFlagsPal.Delegate;
                }
            }

            _canRetryAuthentication = false;

            try
            {
                _context = new NTAuthentication(isServer, package, credential, servicePrincipalName, flags, channelBinding);
            }
            catch (Win32Exception e)
            {
                throw new AuthenticationException(SR.net_auth_SSPI, e);
            }
        }
예제 #12
0
        /// <summary>
        ///    Sends a set of messages to the associated Queue/Topic using a batched approach.
        /// </summary>
        ///
        /// <param name="messageFactory"></param>
        /// <param name="timeout"></param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        internal virtual async Task SendBatchInternalAsync(
            Func <AmqpMessage> messageFactory,
            TimeSpan timeout,
            CancellationToken cancellationToken)
        {
            var stopWatch = ValueStopwatch.StartNew();
            var link      = default(SendingAmqpLink);

            try
            {
                using (AmqpMessage batchMessage = messageFactory())
                {
                    string messageHash = batchMessage.GetHashCode().ToString(CultureInfo.InvariantCulture);

                    ArraySegment <byte> transactionId      = AmqpConstants.NullBinary;
                    Transaction         ambientTransaction = Transaction.Current;
                    if (ambientTransaction != null)
                    {
                        transactionId = await AmqpTransactionManager.Instance.EnlistAsync(
                            ambientTransaction,
                            _connectionScope,
                            timeout).ConfigureAwait(false);
                    }

                    link = await _sendLink.GetOrCreateAsync(UseMinimum(_connectionScope.SessionTimeout, timeout)).ConfigureAwait(false);

                    // Validate that the message is not too large to send.  This is done after the link is created to ensure
                    // that the maximum message size is known, as it is dictated by the service using the link.

                    if (batchMessage.SerializedMessageSize > MaxMessageSize)
                    {
                        throw new ServiceBusException(string.Format(CultureInfo.InvariantCulture, Resources.MessageSizeExceeded, messageHash, batchMessage.SerializedMessageSize, MaxMessageSize, _entityPath), ServiceBusFailureReason.MessageSizeExceeded);
                    }

                    // Attempt to send the message batch.

                    var     deliveryTag = new ArraySegment <byte>(BitConverter.GetBytes(Interlocked.Increment(ref _deliveryCount)));
                    Outcome outcome     = await link.SendMessageAsync(
                        batchMessage,
                        deliveryTag,
                        transactionId, timeout.CalculateRemaining(stopWatch.GetElapsedTime())).ConfigureAwait(false);

                    cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();

                    if (outcome.DescriptorCode != Accepted.Code)
                    {
                        throw (outcome as Rejected)?.Error.ToMessagingContractException();
                    }

                    cancellationToken.ThrowIfCancellationRequested <TaskCanceledException>();
                }
            }
            catch (Exception exception)
            {
                ExceptionDispatchInfo.Capture(AmqpExceptionHelper.TranslateException(
                                                  exception,
                                                  link?.GetTrackingId(),
                                                  null,
                                                  HasLinkCommunicationError(link)))
                .Throw();

                throw; // will never be reached
            }
        }
예제 #13
0
 public void ReportError(Parser recognizer, RecognitionException e)
 {
     ExceptionDispatchInfo.Capture(e).Throw();
 }
예제 #14
0
        /// <inheritdoc />
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            _logger.AttemptingToBindModel(bindingContext);

            var modelName           = bindingContext.ModelName;
            var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);

            if (valueProviderResult == ValueProviderResult.None)
            {
                _logger.FoundNoValueInRequest(bindingContext);

                // no entry
                _logger.DoneAttemptingToBindModel(bindingContext);
                return(Task.CompletedTask);
            }

            var modelState = bindingContext.ModelState;

            modelState.SetModelValue(modelName, valueProviderResult);

            var metadata = bindingContext.ModelMetadata;
            var type     = metadata.UnderlyingOrModelType;

            try
            {
                var value = valueProviderResult.FirstValue;

                object model;
                if (string.IsNullOrWhiteSpace(value))
                {
                    // Parse() method trims the value (with common NumberStyles) then throws if the result is empty.
                    model = null;
                }
                else if (type == typeof(decimal))
                {
                    model = decimal.Parse(value, _supportedStyles, valueProviderResult.Culture);
                }
                else
                {
                    // unreachable
                    throw new NotSupportedException();
                }

                // When converting value, a null model may indicate a failed conversion for an otherwise required
                // model (can't set a ValueType to null). This detects if a null model value is acceptable given the
                // current bindingContext. If not, an error is logged.
                if (model == null && !metadata.IsReferenceOrNullableType)
                {
                    modelState.TryAddModelError(
                        modelName,
                        metadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor(
                            valueProviderResult.ToString()));
                }
                else
                {
                    bindingContext.Result = ModelBindingResult.Success(model);
                }
            }
            catch (Exception exception)
            {
                var isFormatException = exception is FormatException;
                if (!isFormatException && exception.InnerException != null)
                {
                    // Unlike TypeConverters, floating point types do not seem to wrap FormatExceptions. Preserve
                    // this code in case a cursory review of the CoreFx code missed something.
                    exception = ExceptionDispatchInfo.Capture(exception.InnerException).SourceException;
                }

                modelState.TryAddModelError(modelName, exception, metadata);

                // Conversion failed.
            }

            _logger.DoneAttemptingToBindModel(bindingContext);
            return(Task.CompletedTask);
        }
예제 #15
0
        /// <summary>
        /// Rethrows an exception without losing stack information.
        /// </summary>
        /// <param name="ex"></param>
        /// <remarks>
        /// Copied from http://stackoverflow.com/questions/4555599/how-to-rethrow-the-inner-exception-of-a-targetinvocationexception-without-losing.
        /// </remarks>
        public static void Rethrow(Exception ex)
        {
            var exceptionDispatchInfo = ExceptionDispatchInfo.Capture(ex);

            exceptionDispatchInfo.Throw();
        }
예제 #16
0
        /// <summary>Adds the exception to the fault list.</summary>
        /// <param name="exceptionObject">The exception to store.</param>
        /// <remarks>
        /// Must be called under lock.
        /// </remarks>
        private void AddFaultException(object exceptionObject)
        {
            Contract.Requires(exceptionObject != null, "AddFaultException(): Expected a non-null exceptionObject");

            // Initialize the exceptions list if necessary.  The list should be non-null iff it contains exceptions.
            var exceptions = m_faultExceptions;

            if (exceptions == null)
            {
                m_faultExceptions = exceptions = new List <ExceptionDispatchInfo>(1);
            }
            else
            {
                Contract.Assert(exceptions.Count > 0, "Expected existing exceptions list to have > 0 exceptions.");
            }

            // Handle Exception by capturing it into an ExceptionDispatchInfo and storing that
            var exception = exceptionObject as Exception;

            if (exception != null)
            {
                exceptions.Add(ExceptionDispatchInfo.Capture(exception));
            }
            else
            {
                // Handle ExceptionDispatchInfo by storing it into the list
                var edi = exceptionObject as ExceptionDispatchInfo;
                if (edi != null)
                {
                    exceptions.Add(edi);
                }
                else
                {
                    // Handle enumerables of exceptions by capturing each of the contained exceptions into an EDI and storing it
                    var exColl = exceptionObject as IEnumerable <Exception>;
                    if (exColl != null)
                    {
#if DEBUG
                        int numExceptions = 0;
#endif
                        foreach (var exc in exColl)
                        {
#if DEBUG
                            Contract.Assert(exc != null, "No exceptions should be null");
                            numExceptions++;
#endif
                            exceptions.Add(ExceptionDispatchInfo.Capture(exc));
                        }
#if DEBUG
                        Contract.Assert(numExceptions > 0, "Collection should contain at least one exception.");
#endif
                    }
                    else
                    {
                        // Handle enumerables of EDIs by storing them directly
                        var ediColl = exceptionObject as IEnumerable <ExceptionDispatchInfo>;
                        if (ediColl != null)
                        {
                            exceptions.AddRange(ediColl);
#if DEBUG
                            Contract.Assert(exceptions.Count > 0, "There should be at least one dispatch info.");
                            foreach (var tmp in exceptions)
                            {
                                Contract.Assert(tmp != null, "No dispatch infos should be null");
                            }
#endif
                        }
                        // Anything else is a programming error
                        else
                        {
                            throw new ArgumentException(SR.TaskExceptionHolder_UnknownExceptionType, "exceptionObject");
                        }
                    }
                }
            }

            if (exceptions.Count > 0)
            {
                MarkAsUnhandled();
            }
        }
        /// <summary>
        /// B層の一般的な例外による異常終了の後処理を実装するUOCメソッド。
        /// </summary>
        /// <param name="parameterValue">引数クラス</param>
        /// <param name="returnValue">戻り値クラス</param>
        /// <param name="ex">Exception</param>
        /// <remarks>業務コード親クラス1から利用される派生の末端</remarks>
        protected override void UOC_ABEND(BaseParameterValue parameterValue, ref BaseReturnValue returnValue, Exception ex)
        {
            // 一般的な例外発生時の処理を実装
            // TODO:

            // nullチェック
            if (this.perfRec == null)
            {
                // なにもしない

                // スタックトレースを保って InnerException を throw
                ExceptionDispatchInfo.Capture(ex).Throw();
            }
            else
            {
                // 性能測定終了
                this.perfRec.EndsPerformanceRecord();

                // キャスト
                MyParameterValue myPV = (MyParameterValue)parameterValue;

                // システム例外に振り替える用のワーク
                bool   sysErrorFlag      = false;
                string sysErrorMessageID = "";
                string sysErrorMessage   = "";

                #region 例外の振替処理のIF文

                if (ex.Message == "Other-Business")
                {
                    // 業務例外へ変換
                    returnValue.ErrorFlag      = true;
                    returnValue.ErrorMessageID = "振替後";
                    returnValue.ErrorMessage   = "振替後";
                    returnValue.ErrorInfo      = "振り替える場合は、基本的にここを利用。";
                }
                else if (ex.Message == "Other-System")
                {
                    // システム例外へ振替
                    sysErrorFlag      = true;
                    sysErrorMessageID = "振替後";
                    sysErrorMessage   = "振替後";
                }

                #endregion

                #region ACCESSログ出力、リスローする・しない

                if (returnValue.ErrorFlag)
                {
                    // 業務例外へ変換

                    // ------------
                    // メッセージ部
                    // ------------
                    // ユーザ名, IPアドレス, レイヤ,
                    // 画面名, コントロール名, メソッド名, 処理名
                    // 処理時間(実行時間), 処理時間(CPU時間)
                    // エラーメッセージID, エラーメッセージ等
                    // ------------
                    string strLogMessage =
                        "," + myPV.User.UserName +
                        "," + myPV.User.IPAddress +
                        "," + "<<-----" +
                        "," + myPV.ScreenId +
                        "," + myPV.ControlId +
                        "," + myPV.MethodName +
                        "," + myPV.ActionType +
                        "," + this.perfRec.ExecTime +
                        "," + this.perfRec.CpuTime +
                        "," + returnValue.ErrorMessageID +
                        "," + returnValue.ErrorMessage; // baEX

                    // Log4Netへログ出力
                    LogIF.WarnLog("ACCESS", strLogMessage);
                }
                else if (sysErrorFlag)
                {
                    // システム例外へ振替

                    // ------------
                    // メッセージ部
                    // ------------
                    // ユーザ名, IPアドレス, レイヤ,
                    // 画面名, コントロール名, メソッド名, 処理名
                    // 処理時間(実行時間), 処理時間(CPU時間)
                    // エラーメッセージID, エラーメッセージ等
                    // ------------
                    string strLogMessage =
                        "," + myPV.User.UserName +
                        "," + myPV.User.IPAddress +
                        "," + "<<-----" +
                        "," + myPV.ScreenId +
                        "," + myPV.ControlId +
                        "," + myPV.MethodName +
                        "," + myPV.ActionType +
                        "," + this.perfRec.ExecTime +
                        "," + this.perfRec.CpuTime +
                        "," + sysErrorMessageID +
                        "," + sysErrorMessage +
                        "\r\n" + ex.StackTrace; // bsEX

                    // Log4Netへログ出力
                    LogIF.ErrorLog("ACCESS", strLogMessage);

                    // 振替てスロー
                    throw new BusinessSystemException(sysErrorMessageID, sysErrorMessage);
                }
                else
                {
                    // そのまま

                    // ------------
                    // メッセージ部
                    // ------------
                    // ユーザ名, IPアドレス, レイヤ,
                    // 画面名, コントロール名, メソッド名, 処理名
                    // 処理時間(実行時間), 処理時間(CPU時間)
                    // エラーメッセージID, エラーメッセージ等
                    // ------------
                    string strLogMessage =
                        "," + myPV.User.UserName +
                        "," + myPV.User.IPAddress +
                        "," + "<<-----" +
                        "," + myPV.ScreenId +
                        "," + myPV.ControlId +
                        "," + myPV.MethodName +
                        "," + myPV.ActionType +
                        "," + this.perfRec.ExecTime +
                        "," + this.perfRec.CpuTime +
                        "," + "other Exception" +
                        "," + ex.Message +
                        "\r\n" + ex.ToString(); // ex

                    // Log4Netへログ出力
                    LogIF.ErrorLog("ACCESS", strLogMessage);

                    // スタックトレースを保って InnerException を throw
                    ExceptionDispatchInfo.Capture(ex).Throw();
                }

                #endregion
            }
        }
예제 #18
0
        public static void Execute(StorageEnvironmentOptions srcOptions,
                                   StorageEnvironmentOptions.DirectoryStorageEnvironmentOptions compactOptions,
                                   Action <StorageCompactionProgress> progressReport = null,
                                   CancellationToken token = default(CancellationToken))
        {
            if (srcOptions.IncrementalBackupEnabled)
            {
                throw new InvalidOperationException(CannotCompactBecauseOfIncrementalBackup);
            }

            long minimalCompactedDataFileSize;

            srcOptions.ManualFlushing     = true; // prevent from flushing during compaction - we shouldn't touch any source files
            compactOptions.ManualFlushing = true; // let us flush manually during data copy

            using (var existingEnv = new StorageEnvironment(srcOptions))
                using (var compactedEnv = new StorageEnvironment(compactOptions))
                {
                    CopyTrees(existingEnv, compactedEnv, progressReport, token);

                    compactedEnv.FlushLogToDataFile();
                    bool synced;

                    const int maxNumberOfRetries = 100;

                    var syncRetries = 0;

                    while (true)
                    {
                        token.ThrowIfCancellationRequested();
                        using (var op = new WriteAheadJournal.JournalApplicator.SyncOperation(compactedEnv.Journal.Applicator))
                        {
                            try
                            {
                                synced = op.SyncDataFile();

                                if (synced || ++syncRetries >= maxNumberOfRetries)
                                {
                                    break;
                                }

                                Thread.Sleep(100);
                            }
                            catch (Exception e)
                            {
                                existingEnv.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e));
                                throw;
                            }
                        }
                    }

                    if (synced)
                    {
                        compactedEnv.Journal.Applicator.DeleteCurrentAlreadyFlushedJournal();
                    }

                    compactedEnv.Cleanup();

                    minimalCompactedDataFileSize = compactedEnv.NextPageNumber * Constants.Storage.PageSize;
                }

            using (var compactedDataFile = SafeFileStream.Create(compactOptions.BasePath.Combine(Constants.DatabaseFilename).FullPath, FileMode.Open, FileAccess.ReadWrite))
            {
                compactedDataFile.SetLength(minimalCompactedDataFileSize);
            }
        }
예제 #19
0
        public static void RunGameTest(GameBase game)
        {
            // Prepare finish callback
            var tcs = new TaskCompletionSource <bool>();
            EventHandler <EventArgs> gameFinishedCallback = (sender, e) =>
            {
                // Notify waiter that game has exited
                Logger.Info("Game finished.");
                tcs.TrySetResult(true);
            };

            EventHandler <GameUnhandledExceptionEventArgs> exceptionhandler = (sender, e) =>
            {
                Logger.Info("Game finished with exception ={0}.", e);
                tcs.TrySetException((Exception)e.ExceptionObject);
            };

            // Transmit data to activity
            // TODO: Avoid static with string intent + Dictionary?
            try
            {
                game.UnhandledException += exceptionhandler;

                Logger.Info(@"Starting activity");

#if SILICONSTUDIO_PLATFORM_IOS
                game.Exiting += gameFinishedCallback;

                UIApplication.SharedApplication.InvokeOnMainThread(() =>
                {
                    var window = UIApplication.SharedApplication.KeyWindow;
                    var rootNavigationController = (UINavigationController)window.RootViewController;

                    // create the paradox game view
                    var bounds          = UIScreen.MainScreen.Bounds;
                    var paradoxGameView = new Starter.ParadoxApplicationDelegate.iOSParadoxView((System.Drawing.RectangleF)bounds)
                    {
                        ContentScaleFactor = UIScreen.MainScreen.Scale
                    };

                    // create the view controller used to display the paradox game
                    var paradoxGameController = new iOSGameTestController(game)
                    {
                        View = paradoxGameView
                    };

                    // create the game context
                    var gameContext = new GameContext(window, paradoxGameView, paradoxGameController);

                    // push view
                    rootNavigationController.PushViewController(gameContext.GameViewController, false);

                    // launch the game
                    game.Run(gameContext);
                });
#elif SILICONSTUDIO_PLATFORM_ANDROID
                // Start activity
                AndroidGameTestActivity.Game       = game;
                AndroidGameTestActivity.Destroyed += gameFinishedCallback;
                PlatformAndroid.Context.StartActivity(typeof(AndroidGameTestActivity));
#endif

                // Wait for completion of task
                // TODO: Should we put a timeout and issue a Game.Exit() in main thread if too long?
                tcs.Task.Wait();

                Logger.Info(@"Activity ended");
            }
            catch (AggregateException e)
            {
                // Unwrap aggregate exceptions
                if (e.InnerExceptions.Count == 1)
                {
                    ExceptionDispatchInfo.Capture(e.InnerException).Throw();
                }
            }
            finally
            {
#if SILICONSTUDIO_PLATFORM_IOS
                // iOS Cleanup
                UIApplication.SharedApplication.InvokeOnMainThread(() =>
                {
                    var window = UIApplication.SharedApplication.KeyWindow;
                    var rootNavigationController = (UINavigationController)window.RootViewController;

                    rootNavigationController.PopViewController(false);
                });
#elif SILICONSTUDIO_PLATFORM_ANDROID
                AndroidGameTestActivity.Game       = null;
                AndroidGameTestActivity.Destroyed -= gameFinishedCallback;
#endif

                // Cleanup
                game.Exiting            -= gameFinishedCallback;
                game.UnhandledException -= exceptionhandler;
            }
        }
예제 #20
0
파일: Router.cs 프로젝트: santoshna/xenko-1
        /// <summary>
        /// Handles ClientRequestServer messages.
        /// It will try to find a matching service (spawn it if not started yet), and ask it to establish a new "server" connection back to us.
        /// </summary>
        /// <param name="clientSocket">The client socket context.</param>
        /// <returns></returns>
        private async Task HandleMessageClientRequestServer(SimpleSocket clientSocket)
        {
            // Check for an existing server
            // TODO: Proper Url parsing (query string)
            var url = await clientSocket.ReadStream.ReadStringAsync();

            Log.Info($"Client {clientSocket.RemoteAddress}:{clientSocket.RemotePort} sent message ClientRequestServer with URL {url}");

            string[] urlSegments;
            string   urlParameters;

            RouterHelper.ParseUrl(url, out urlSegments, out urlParameters);
            if (urlSegments.Length == 0)
            {
                throw new InvalidOperationException("No URL Segments");
            }

            SimpleSocket          serverSocket = null;
            ExceptionDispatchInfo serverSocketCapturedException = null;

            try
            {
                // For now, we handle only "service" URL
                switch (urlSegments[0])
                {
                case "service":
                {
                    // From the URL, start service (if not started yet) and ask it to provide a server
                    serverSocket = await SpawnServerFromService(url, false);

                    break;
                }

                case "task":
                {
                    // From the URL, start service (if not started yet) and ask it to provide a server
                    serverSocket = await SpawnServerFromService(url, true);
                }
                break;

                case "redirect":
                {
                    // Redirect to a IP/port
                    serverSocket = new SimpleSocket();
                    var host = urlSegments[1];
                    var port = int.Parse(urlSegments[2]);

                    // Note: for security reasons, we currently use a whitelist
                    //if (host == "xenkobuild.xenko.com" && port == 1832)
                    //    await serverSocket.StartClient(host, port, false);
                    //else
                    throw new InvalidOperationException("Trying to redirect to a non-whitelisted host/port");
                    break;
                }

                default:
                    throw new InvalidOperationException("This type of URL is not supported");
                }
            }
            catch (Exception e)
            {
                serverSocketCapturedException = ExceptionDispatchInfo.Capture(e);
            }


            if (serverSocketCapturedException != null)
            {
                try
                {
                    // Notify client that there was an error
                    await clientSocket.WriteStream.WriteInt16Async((short)RouterMessage.ClientServerStarted);

                    await clientSocket.WriteStream.WriteInt32Async(1); // error code Failure

                    await clientSocket.WriteStream.WriteStringAsync(serverSocketCapturedException.SourceException.Message);

                    await clientSocket.WriteStream.FlushAsync();
                }
                finally
                {
                    serverSocketCapturedException.Throw();
                }
            }

            try
            {
                // Notify client that we've found a server for it
                await clientSocket.WriteStream.WriteInt16Async((short)RouterMessage.ClientServerStarted);

                await clientSocket.WriteStream.WriteInt32Async(0); // error code OK

                await clientSocket.WriteStream.FlushAsync();

                // Let's forward clientSocketContext and serverSocketContext
                await await Task.WhenAny(
                    ForwardSocket(clientSocket, serverSocket),
                    ForwardSocket(serverSocket, clientSocket));
            }
            catch
            {
                serverSocket.Dispose();
                throw;
            }
        }
예제 #21
0
 public static void RethrowToKeepStackTrace(this Exception ex)
 {
     ExceptionDispatchInfo.Capture(ex).Throw();
 }
예제 #22
0
        /// <summary>
        /// If instances of the underlying <see cref="DbContext" /> type can be created, returns
        /// a new instance; otherwise returns null.
        /// </summary>
        /// <returns>
        /// A <see cref="DbContext" /> instance.
        /// </returns>
        public virtual DbContext CreateInstance()
        {
            var configPushed = DbConfigurationManager.Instance.PushConfiguration(_appConfig, _contextType);

            CurrentInfo = this;

            DbContext context = null;

            try
            {
                try
                {
                    context = _activator == null ? null : _activator();
                }
                catch (TargetInvocationException ex)
                {
                    Debug.Assert(ex.InnerException != null);
#if !NET40
                    ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
#endif
                    throw ex.InnerException;
                }

                if (context == null)
                {
                    return(null);
                }

                context.InternalContext.OnDisposing += (_, __) => CurrentInfo = null;

                if (configPushed)
                {
                    context.InternalContext.OnDisposing +=
                        (_, __) => DbConfigurationManager.Instance.PopConfiguration(_appConfig);
                }

                context.InternalContext.ApplyContextInfo(this);

                return(context);
            }
            catch (Exception)
            {
                if (context != null)
                {
                    context.Dispose();
                }

                throw;
            }
            finally
            {
                if (context == null)
                {
                    CurrentInfo = null;

                    if (configPushed)
                    {
                        DbConfigurationManager.Instance.PopConfiguration(_appConfig);
                    }
                }
            }
        }
 public void SetException(Exception error)
 {
     _error = ExceptionDispatchInfo.Capture(error);
     SignalCompletion();
 }
예제 #24
0
        private HubMessage ParseMessage(Utf8BufferTextReader textReader, IInvocationBinder binder)
        {
            try
            {
                // We parse using the JsonTextReader directly but this has a problem. Some of our properties are dependent on other properties
                // and since reading the json might be unordered, we need to store the parsed content as JToken to re-parse when true types are known.
                // if we're lucky and the state we need to directly parse is available, then we'll use it.

                int?     type           = null;
                string   invocationId   = null;
                string   streamId       = null;
                string   target         = null;
                string   error          = null;
                var      hasItem        = false;
                object   item           = null;
                JToken   itemToken      = null;
                var      hasResult      = false;
                object   result         = null;
                JToken   resultToken    = null;
                var      hasArguments   = false;
                object[] arguments      = null;
                JArray   argumentsToken = null;
                ExceptionDispatchInfo       argumentBindingException = null;
                Dictionary <string, string> headers = null;
                var completed = false;

                using (var reader = JsonUtils.CreateJsonTextReader(textReader))
                {
                    reader.DateParseHandling = DateParseHandling.None;

                    JsonUtils.CheckRead(reader);

                    // We're always parsing a JSON object
                    JsonUtils.EnsureObjectStart(reader);

                    do
                    {
                        switch (reader.TokenType)
                        {
                        case JsonToken.PropertyName:
                            var memberName = reader.Value.ToString();

                            switch (memberName)
                            {
                            case TypePropertyName:
                                var messageType = JsonUtils.ReadAsInt32(reader, TypePropertyName);

                                if (messageType == null)
                                {
                                    throw new InvalidDataException($"Missing required property '{TypePropertyName}'.");
                                }

                                type = messageType.Value;
                                break;

                            case InvocationIdPropertyName:
                                invocationId = JsonUtils.ReadAsString(reader, InvocationIdPropertyName);
                                break;

                            case StreamIdPropertyName:
                                streamId = JsonUtils.ReadAsString(reader, StreamIdPropertyName);
                                break;

                            case TargetPropertyName:
                                target = JsonUtils.ReadAsString(reader, TargetPropertyName);
                                break;

                            case ErrorPropertyName:
                                error = JsonUtils.ReadAsString(reader, ErrorPropertyName);
                                break;

                            case ResultPropertyName:
                                hasResult = true;

                                if (string.IsNullOrEmpty(invocationId))
                                {
                                    JsonUtils.CheckRead(reader);

                                    // If we don't have an invocation id then we need to store it as a JToken so we can parse it later
                                    resultToken = JToken.Load(reader);
                                }
                                else
                                {
                                    // If we have an invocation id already we can parse the end result
                                    var returnType = binder.GetReturnType(invocationId);

                                    if (!JsonUtils.ReadForType(reader, returnType))
                                    {
                                        throw new JsonReaderException("Unexpected end when reading JSON");
                                    }

                                    result = PayloadSerializer.Deserialize(reader, returnType);
                                }
                                break;

                            case ItemPropertyName:
                                JsonUtils.CheckRead(reader);

                                hasItem = true;


                                string id = null;
                                if (!string.IsNullOrEmpty(invocationId))
                                {
                                    id = invocationId;
                                }
                                else if (!string.IsNullOrEmpty(streamId))
                                {
                                    id = streamId;
                                }
                                else
                                {
                                    // If we don't have an id yetmthen we need to store it as a JToken to parse later
                                    itemToken = JToken.Load(reader);
                                    break;
                                }

                                Type itemType = binder.GetStreamItemType(id);

                                try
                                {
                                    item = PayloadSerializer.Deserialize(reader, itemType);
                                }
                                catch (JsonSerializationException ex)
                                {
                                    return(new StreamBindingFailureMessage(id, ExceptionDispatchInfo.Capture(ex)));
                                }
                                break;

                            case ArgumentsPropertyName:
                                JsonUtils.CheckRead(reader);

                                int initialDepth = reader.Depth;
                                if (reader.TokenType != JsonToken.StartArray)
                                {
                                    throw new InvalidDataException($"Expected '{ArgumentsPropertyName}' to be of type {JTokenType.Array}.");
                                }

                                hasArguments = true;

                                if (string.IsNullOrEmpty(target))
                                {
                                    // We don't know the method name yet so just parse an array of generic JArray
                                    argumentsToken = JArray.Load(reader);
                                }
                                else
                                {
                                    try
                                    {
                                        var paramTypes = binder.GetParameterTypes(target);
                                        arguments = BindArguments(reader, paramTypes);
                                    }
                                    catch (Exception ex)
                                    {
                                        argumentBindingException = ExceptionDispatchInfo.Capture(ex);

                                        // Could be at any point in argument array JSON when an error is thrown
                                        // Read until the end of the argument JSON array
                                        while (reader.Depth == initialDepth && reader.TokenType == JsonToken.StartArray ||
                                               reader.Depth > initialDepth)
                                        {
                                            JsonUtils.CheckRead(reader);
                                        }
                                    }
                                }
                                break;

                            case HeadersPropertyName:
                                JsonUtils.CheckRead(reader);
                                headers = ReadHeaders(reader);
                                break;

                            default:
                                // Skip read the property name
                                JsonUtils.CheckRead(reader);
                                // Skip the value for this property
                                reader.Skip();
                                break;
                            }
                            break;

                        case JsonToken.EndObject:
                            completed = true;
                            break;
                        }
                    }while (!completed && JsonUtils.CheckRead(reader));
                }

                HubMessage message;

                switch (type)
                {
                case HubProtocolConstants.InvocationMessageType:
                {
                    if (argumentsToken != null)
                    {
                        // We weren't able to bind the arguments because they came before the 'target', so try to bind now that we've read everything.
                        try
                        {
                            var paramTypes = binder.GetParameterTypes(target);
                            arguments = BindArguments(argumentsToken, paramTypes);
                        }
                        catch (Exception ex)
                        {
                            argumentBindingException = ExceptionDispatchInfo.Capture(ex);
                        }
                    }

                    message = argumentBindingException != null
                                ? new InvocationBindingFailureMessage(invocationId, target, argumentBindingException)
                                : BindInvocationMessage(invocationId, target, arguments, hasArguments, binder);
                }
                break;

                case HubProtocolConstants.StreamInvocationMessageType:
                {
                    if (argumentsToken != null)
                    {
                        // We weren't able to bind the arguments because they came before the 'target', so try to bind now that we've read everything.
                        try
                        {
                            var paramTypes = binder.GetParameterTypes(target);
                            arguments = BindArguments(argumentsToken, paramTypes);
                        }
                        catch (Exception ex)
                        {
                            argumentBindingException = ExceptionDispatchInfo.Capture(ex);
                        }
                    }

                    message = argumentBindingException != null
                                ? new InvocationBindingFailureMessage(invocationId, target, argumentBindingException)
                                : BindStreamInvocationMessage(invocationId, target, arguments, hasArguments, binder);
                }
                break;

                case HubProtocolConstants.StreamDataMessageType:
                    if (itemToken != null)
                    {
                        var itemType = binder.GetStreamItemType(streamId);
                        try
                        {
                            item = itemToken.ToObject(itemType, PayloadSerializer);
                        }
                        catch (JsonSerializationException ex)
                        {
                            return(new StreamBindingFailureMessage(streamId, ExceptionDispatchInfo.Capture(ex)));
                        }
                    }
                    message = BindParamStreamMessage(streamId, item, hasItem, binder);
                    break;

                case HubProtocolConstants.StreamItemMessageType:
                    if (itemToken != null)
                    {
                        var returnType = binder.GetStreamItemType(invocationId);
                        try
                        {
                            item = itemToken.ToObject(returnType, PayloadSerializer);
                        }
                        catch (JsonSerializationException ex)
                        {
                            return(new StreamBindingFailureMessage(invocationId, ExceptionDispatchInfo.Capture(ex)));
                        };
                    }

                    message = BindStreamItemMessage(invocationId, item, hasItem, binder);
                    break;

                case HubProtocolConstants.CompletionMessageType:
                    if (resultToken != null)
                    {
                        var returnType = binder.GetReturnType(invocationId);
                        result = resultToken.ToObject(returnType, PayloadSerializer);
                    }

                    message = BindCompletionMessage(invocationId, error, result, hasResult, binder);
                    break;

                case HubProtocolConstants.CancelInvocationMessageType:
                    message = BindCancelInvocationMessage(invocationId);
                    break;

                case HubProtocolConstants.PingMessageType:
                    return(PingMessage.Instance);

                case HubProtocolConstants.CloseMessageType:
                    return(BindCloseMessage(error));

                case HubProtocolConstants.StreamCompleteMessageType:
                    message = BindStreamCompleteMessage(streamId, error);
                    break;

                case null:
                    throw new InvalidDataException($"Missing required property '{TypePropertyName}'.");

                default:
                    // Future protocol changes can add message types, old clients can ignore them
                    return(null);
                }

                return(ApplyHeaders(message, headers));
            }
            catch (JsonReaderException jrex)
            {
                throw new InvalidDataException("Error reading JSON.", jrex);
            }
        }
예제 #25
0
        private async Task <object> InvokeCore(HttpServiceRequest request, Type resultReturnType, JsonSerializerSettings jsonSettings)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            request.TracingData = new TracingData
            {
                HostName         = CurrentApplicationInfo.HostName?.ToUpperInvariant(),
                ServiceName      = CurrentApplicationInfo.Name,
                RequestID        = TracingContext.TryGetRequestID(),
                SpanID           = Guid.NewGuid().ToString("N"), //Each call is new span
                ParentSpanID     = TracingContext.TryGetSpanID(),
                SpanStartTime    = DateTimeOffset.UtcNow,
                AbandonRequestBy = TracingContext.AbandonRequestBy
            };
            PrepareRequest?.Invoke(request);

            while (true)
            {
                var config          = GetConfig();
                var clientCallEvent = EventPublisher.CreateEvent();
                clientCallEvent.TargetService = ServiceName;
                clientCallEvent.RequestId     = request.TracingData?.RequestID;
                clientCallEvent.TargetMethod  = request.Target.MethodName;
                clientCallEvent.SpanId        = request.TracingData?.SpanID;
                clientCallEvent.ParentSpanId  = request.TracingData?.ParentSpanID;

                string responseContent;
                HttpResponseMessage response;
                var nodeAndLoadBalancer = await ServiceDiscovery.GetNode().ConfigureAwait(false); // can throw

                int?effectivePort = GetEffectivePort(nodeAndLoadBalancer.Node, config);
                if (effectivePort == null)
                {
                    throw new ConfigurationException("Cannot access service. Service Port not configured. See tags to find missing configuration", unencrypted: new Tags {
                        { "ServiceName", ServiceName },
                        { "Required configuration key", $"Discovery.{ServiceName}.DefaultPort" }
                    });
                }

                // The URL is only for a nice experience in Fiddler, it's never parsed/used for anything.
                var uri = BuildUri(nodeAndLoadBalancer.Node.Hostname, effectivePort.Value, config) + ServiceName;
                if (request.Target.MethodName != null)
                {
                    uri += $".{request.Target.MethodName}";
                }
                if (request.Target.Endpoint != null)
                {
                    uri += $"/{request.Target.Endpoint}";
                }

                try
                {
                    Log.Debug(_ => _("ServiceProxy: Calling remote service. See tags for details.",
                                     unencryptedTags: new
                    {
                        remoteEndpoint    = nodeAndLoadBalancer.Node.Hostname,
                        remotePort        = effectivePort,
                        remoteServiceName = ServiceName,
                        remoteMethodName  = request.Target.MethodName
                    }));

                    clientCallEvent.TargetHostName    = nodeAndLoadBalancer.Node.Hostname;
                    clientCallEvent.TargetPort        = effectivePort.Value;
                    clientCallEvent.TargetEnvironment = nodeAndLoadBalancer.TargetEnvironment;

                    request.Overrides = TracingContext.TryGetOverrides()?.ShallowCloneWithDifferentPreferredEnvironment(nodeAndLoadBalancer.PreferredEnvironment)
                                        ?? new RequestOverrides {
                        PreferredEnvironment = nodeAndLoadBalancer.PreferredEnvironment
                    };
                    string requestContent = _serializationTime.Time(() => JsonConvert.SerializeObject(request, jsonSettings));

                    var httpContent = new StringContent(requestContent, Encoding.UTF8, "application/json");
                    httpContent.Headers.Add(GigyaHttpHeaders.ProtocolVersion, HttpServiceRequest.ProtocolVersion);

                    clientCallEvent.RequestStartTimestamp = Stopwatch.GetTimestamp();
                    try
                    {
                        response = await GetHttpClient(config).PostAsync(uri, httpContent).ConfigureAwait(false);

                        responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    }
                    finally
                    {
                        clientCallEvent.ResponseEndTimestamp = Stopwatch.GetTimestamp();
                    }
                    if (response.Headers.TryGetValues(GigyaHttpHeaders.ExecutionTime, out IEnumerable <string> values))
                    {
                        var time = values.FirstOrDefault();
                        if (TimeSpan.TryParse(time, out TimeSpan executionTime))
                        {
                            clientCallEvent.ServerTimeMs = executionTime.TotalMilliseconds;
                        }
                    }
                }
                catch (HttpRequestException ex)
                {
                    Log.Error("The remote service failed to return a valid HTTP response. Continuing to next " +
                              "host. See tags for URL and exception for details.",
                              exception: ex,
                              unencryptedTags: new { uri });
                    _hostFailureCounter.Increment("RequestFailure");
                    clientCallEvent.Exception = ex;
                    EventPublisher.TryPublish(clientCallEvent); // fire and forget!

                    if (nodeAndLoadBalancer.LoadBalancer != null)
                    {
                        nodeAndLoadBalancer.LoadBalancer.ReportUnreachable(nodeAndLoadBalancer.Node, ex);
                        continue;
                    }

                    throw;
                }
                catch (TaskCanceledException ex)
                {
                    _failureCounter.Increment("RequestTimeout");

                    Exception rex = new RemoteServiceException("The request to the remote service exceeded the " +
                                                               "allotted timeout. See the 'RequestUri' property on this exception for the URL that was " +
                                                               "called and the tag 'requestTimeout' for the configured timeout.",
                                                               uri,
                                                               ex,
                                                               unencrypted: new Tags
                    {
                        { "requestTimeout", LastHttpClient?.Timeout.ToString() },
                        { "requestUri", uri }
                    });

                    clientCallEvent.Exception = rex;

                    EventPublisher.TryPublish(clientCallEvent); // fire and forget!
                    throw rex;
                }

                if (response.Headers.Contains(GigyaHttpHeaders.ServerHostname) || response.Headers.Contains(GigyaHttpHeaders.ProtocolVersion))
                {
                    try
                    {
                        if (response.IsSuccessStatusCode)
                        {
                            var returnObj = _deserializationTime.Time(() => JsonConvert.DeserializeObject(responseContent, resultReturnType, jsonSettings));

                            clientCallEvent.ErrCode = 0;
                            EventPublisher.TryPublish(clientCallEvent); // fire and forget!
                            _successCounter.Increment();

                            return(returnObj);
                        }
                        else
                        {
                            Exception remoteException;

                            try
                            {
                                remoteException = _deserializationTime.Time(() => ExceptionSerializer.Deserialize(responseContent));
                            }
                            catch (Exception ex)
                            {
                                _applicationExceptionCounter.Increment("ExceptionDeserializationFailure");

                                throw new RemoteServiceException("The remote service returned a failure response " +
                                                                 "that failed to deserialize.  See the 'RequestUri' property on this exception " +
                                                                 "for the URL that was called, the inner exception for the exact error and the " +
                                                                 "'responseContent' encrypted tag for the original response content.",
                                                                 uri,
                                                                 ex,
                                                                 unencrypted: new Tags {
                                    { "requestUri", uri }
                                },
                                                                 encrypted: new Tags {
                                    { "responseContent", responseContent }
                                });
                            }

                            _applicationExceptionCounter.Increment();

                            clientCallEvent.Exception = remoteException;
                            EventPublisher.TryPublish(clientCallEvent); // fire and forget!

                            if (remoteException is RequestException || remoteException is EnvironmentException)
                            {
                                ExceptionDispatchInfo.Capture(remoteException).Throw();
                            }

                            if (remoteException is UnhandledException)
                            {
                                remoteException = remoteException.InnerException;
                            }

                            throw new RemoteServiceException("The remote service returned a failure response. See " +
                                                             "the 'RequestUri' property on this exception for the URL that was called, and the " +
                                                             "inner exception for details.",
                                                             uri,
                                                             remoteException,
                                                             unencrypted: new Tags {
                                { "requestUri", uri }
                            });
                        }
                    }
                    catch (JsonException ex)
                    {
                        _failureCounter.Increment("Serialization");

                        Log.Error("The remote service returned a response with JSON that failed " +
                                  "deserialization. See the 'uri' tag for the URL that was called, the exception for the " +
                                  "exact error and the 'responseContent' encrypted tag for the original response content.",
                                  exception: ex,
                                  unencryptedTags: new { uri },
                                  encryptedTags: new { responseContent });

                        clientCallEvent.Exception = ex;
                        EventPublisher.TryPublish(clientCallEvent); // fire and forget!
                        throw new RemoteServiceException("The remote service returned a response with JSON that " +
                                                         "failed deserialization. See the 'RequestUri' property on this exception for the URL " +
                                                         "that was called, the inner exception for the exact error and the 'responseContent' " +
                                                         "encrypted tag for the original response content.",
                                                         uri,
                                                         ex,
                                                         new Tags {
                            { "responseContent", responseContent }
                        },
                                                         new Tags {
                            { "requestUri", uri }
                        });
                    }
                }
                else
                {
                    var exception = response.StatusCode == HttpStatusCode.ServiceUnavailable ?
                                    new Exception($"The remote service is unavailable (503) and is not recognized as a Gigya host at uri: {uri}") :
                                    new Exception($"The remote service returned a response but is not recognized as a Gigya host at uri: {uri}");

                    nodeAndLoadBalancer.LoadBalancer.ReportUnreachable(nodeAndLoadBalancer.Node, exception);
                    _hostFailureCounter.Increment("NotGigyaHost");

                    if (response.StatusCode == HttpStatusCode.ServiceUnavailable)
                    {
                        Log.Error("The remote service is unavailable (503) and is not recognized as a Gigya host. Continuing to next host.", unencryptedTags: new { uri });
                    }
                    else
                    {
                        Log.Error("The remote service returned a response but is not recognized as a Gigya host. Continuing to next host.", unencryptedTags: new { uri, statusCode = response.StatusCode }, encryptedTags: new { responseContent });
                    }

                    clientCallEvent.ErrCode = 500001;           //(int)GSErrors.General_Server_Error;
                    EventPublisher.TryPublish(clientCallEvent); // fire and forget!
                }
            }
        }
예제 #26
0
        void ThreadProc()
        {
            Data             me;
            Mutex            globalLock;
            MemoryMappedFile sharedData;
            long             dataOffset;

            int SIZE         = Marshal.SizeOf(typeof(Data));
            int knownEntries = 0;

            try {
                Initialize(_identifier, out globalLock, out sharedData, out dataOffset, out me);
            } catch (Exception ex) {
                _pending = ExceptionDispatchInfo.Capture(ex);
                return;
            } finally {
                _workerStarted.Set();
            }

            Dictionary <string, AnalysisProgress> response = null;
            Request request;
            bool    abort = false;

            while (!abort)
            {
                while (!_requests.TryDequeue(out request))
                {
                    try {
                        if (_identifier == null && _period.TotalDays < 1)
                        {
                            if (!_requestAdded.WaitOne(_period))
                            {
                                request = Request.Send;
                                break;
                            }
                        }
                        else
                        {
                            _requestAdded.WaitOne();
                        }
                    } catch (ObjectDisposedException) {
                        request = Request.Abort;
                        break;
                    }
                }
                if (request == null)
                {
                    continue;
                }
                else if (request == Request.Abort)
                {
                    break;
                }

                try {
                    if (!globalLock.WaitOne(LOCK_TIMEOUT))
                    {
                        continue;
                    }
                } catch (ObjectDisposedException) {
                    break;
                } catch (AbandonedMutexException) {
                    break;
                }

                try {
                    if (request == Request.Send)
                    {
                        Debug.Assert(_identifier == null);
                        response = ReadAllStatuses(sharedData, ref knownEntries);
                    }
                    else
                    {
                        Debug.Assert(_identifier != null);
                        using (var accessor = sharedData.CreateViewAccessor(dataOffset, SIZE)) {
                            me.ItemsInQueue = request.Update.Progress;
                            me.MaximumItems = request.Update.Maximum;
                            me.Seconds      = request.Update.Seconds;
                            me.Message      = request.Update.Message;
                            accessor.Write(0, ref me);
                        }
                    }
                } finally {
                    try {
                        globalLock.ReleaseMutex();
                    } catch (ObjectDisposedException) {
                        abort    = true;
                        response = null;
                    }
                }

                // Send the response outside the lock.
                if (response != null && _callback != null)
                {
                    _callback(response);
                    response = null;
                }
            }

            try {
                Uninitialize(_identifier, globalLock, sharedData, dataOffset);
            } catch (Exception ex) {
                _pending = ExceptionDispatchInfo.Capture(ex);
            }
        }
        private static async Task <T> ExecuteWithRetriesHelper <T>(
            Func <int, Task <T> > function,
            int callCounter,
            int maxNumSuccessTries,
            int maxNumErrorTries,
            TimeSpan maxExecutionTime,
            DateTime startExecutionTime,
            Func <T, int, bool> retryValueFilter             = null,
            Func <Exception, int, bool> retryExceptionFilter = null,
            IBackoffProvider onSuccessBackOff = null,
            IBackoffProvider onErrorBackOff   = null)
        {
            T result = default(T);
            ExceptionDispatchInfo lastExceptionInfo = null;
            bool retry;

            do
            {
                retry = false;

                if (maxExecutionTime != Constants.INFINITE_TIMESPAN && maxExecutionTime != default(TimeSpan))
                {
                    DateTime now = DateTime.UtcNow;
                    if (now - startExecutionTime > maxExecutionTime)
                    {
                        if (lastExceptionInfo == null)
                        {
                            throw new TimeoutException(
                                      $"ExecuteWithRetries has exceeded its max execution time of {maxExecutionTime}. Now is {LogFormatter.PrintDate(now)}, started at {LogFormatter.PrintDate(startExecutionTime)}, passed {now - startExecutionTime}");
                        }

                        lastExceptionInfo.Throw();
                    }
                }

                int counter = callCounter;

                try
                {
                    callCounter++;
                    result = await function(counter);

                    lastExceptionInfo = null;

                    if (callCounter < maxNumSuccessTries || maxNumSuccessTries == INFINITE_RETRIES) // -1 for infinite retries
                    {
                        if (retryValueFilter != null)
                        {
                            retry = retryValueFilter(result, counter);
                        }
                    }

                    if (retry)
                    {
                        TimeSpan?delay = onSuccessBackOff?.Next(counter);

                        if (delay.HasValue)
                        {
                            await Task.Delay(delay.Value);
                        }
                    }
                }
                catch (Exception exc)
                {
                    retry = false;

                    if (callCounter < maxNumErrorTries || maxNumErrorTries == INFINITE_RETRIES)
                    {
                        if (retryExceptionFilter != null)
                        {
                            retry = retryExceptionFilter(exc, counter);
                        }
                    }

                    if (!retry)
                    {
                        throw;
                    }

                    lastExceptionInfo = ExceptionDispatchInfo.Capture(exc);

                    TimeSpan?delay = onErrorBackOff?.Next(counter);

                    if (delay.HasValue)
                    {
                        await Task.Delay(delay.Value);
                    }
                }
            } while (retry);

            return(result);
        }
예제 #28
0
        /// <inheritdoc />
        public override async Task <InputFormatterResult> ReadRequestBodyAsync(
            InputFormatterContext context,
            Encoding encoding)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (encoding == null)
            {
                throw new ArgumentNullException(nameof(encoding));
            }

            var request = context.HttpContext.Request;

            var suppressInputFormatterBuffering = _options?.SuppressInputFormatterBuffering ?? _suppressInputFormatterBuffering;

            if (!request.Body.CanSeek && !suppressInputFormatterBuffering)
            {
                // JSON.Net does synchronous reads. In order to avoid blocking on the stream, we asynchronously
                // read everything into a buffer, and then seek back to the beginning.
                request.EnableBuffering();
                Debug.Assert(request.Body.CanSeek);

                await request.Body.DrainAsync(CancellationToken.None);

                request.Body.Seek(0L, SeekOrigin.Begin);
            }

            using (var streamReader = context.ReaderFactory(request.Body, encoding))
            {
                using (var jsonReader = new JsonTextReader(streamReader))
                {
                    jsonReader.ArrayPool  = _charPool;
                    jsonReader.CloseInput = false;

                    var       successful = true;
                    Exception exception  = null;
                    void ErrorHandler(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs eventArgs)
                    {
                        successful = false;

                        // Handle path combinations such as "" + "Property", "Parent" + "Property", or "Parent" + "[12]".
                        var key = eventArgs.ErrorContext.Path;

                        if (!string.IsNullOrEmpty(context.ModelName))
                        {
                            if (string.IsNullOrEmpty(eventArgs.ErrorContext.Path))
                            {
                                key = context.ModelName;
                            }
                            else if (eventArgs.ErrorContext.Path[0] == '[')
                            {
                                key = context.ModelName + eventArgs.ErrorContext.Path;
                            }
                            else
                            {
                                key = context.ModelName + "." + eventArgs.ErrorContext.Path;
                            }
                        }

                        var metadata            = GetPathMetadata(context.Metadata, eventArgs.ErrorContext.Path);
                        var modelStateException = WrapExceptionForModelState(eventArgs.ErrorContext.Error);

                        context.ModelState.TryAddModelError(key, modelStateException, metadata);

                        _logger.JsonInputException(eventArgs.ErrorContext.Error);

                        exception = eventArgs.ErrorContext.Error;

                        // Error must always be marked as handled
                        // Failure to do so can cause the exception to be rethrown at every recursive level and
                        // overflow the stack for x64 CLR processes
                        eventArgs.ErrorContext.Handled = true;
                    }

                    var type           = context.ModelType;
                    var jsonSerializer = CreateJsonSerializer();
                    jsonSerializer.Error += ErrorHandler;
                    object model;
                    try
                    {
                        model = jsonSerializer.Deserialize(jsonReader, type);
                    }
                    finally
                    {
                        // Clean up the error handler since CreateJsonSerializer() pools instances.
                        jsonSerializer.Error -= ErrorHandler;
                        ReleaseJsonSerializer(jsonSerializer);
                    }

                    if (successful)
                    {
                        if (model == null && !context.TreatEmptyInputAsDefaultValue)
                        {
                            // Some nonempty inputs might deserialize as null, for example whitespace,
                            // or the JSON-encoded value "null". The upstream BodyModelBinder needs to
                            // be notified that we don't regard this as a real input so it can register
                            // a model binding error.
                            return(InputFormatterResult.NoValue());
                        }
                        else
                        {
                            return(InputFormatterResult.Success(model));
                        }
                    }

                    if (!(exception is JsonException || exception is OverflowException))
                    {
                        var exceptionDispatchInfo = ExceptionDispatchInfo.Capture(exception);
                        exceptionDispatchInfo.Throw();
                    }

                    return(InputFormatterResult.Failure());
                }
            }
        }
        private async Task <RegistrationOperationStatus> ProvisionOverTcpUsingX509CertificateAsync(
            ProvisioningTransportRegisterMessage message,
            CancellationToken cancellationToken)
        {
            Debug.Assert(message.Security is SecurityProviderX509);
            cancellationToken.ThrowIfCancellationRequested();

            X509Certificate2 clientCertificate =
                ((SecurityProviderX509)message.Security).GetAuthenticationCertificate();

            var tlsSettings = new ClientTlsSettings(
                message.GlobalDeviceEndpoint,
                new List <X509Certificate> {
                clientCertificate
            });

            var tcs = new TaskCompletionSource <RegistrationOperationStatus>();

            Bootstrap bootstrap = new Bootstrap()
                                  .Group(s_eventLoopGroup)
                                  .Channel <TcpSocketChannel>()
                                  .Option(ChannelOption.TcpNodelay, true)
                                  .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default)
                                  .Handler(new ActionChannelInitializer <ISocketChannel>(ch =>
            {
                ch.Pipeline.AddLast(
                    new ReadTimeoutHandler(ReadTimeoutSeconds),
                    new TlsHandler(tlsSettings),     //TODO: Ensure SystemDefault is used.
                    MqttEncoder.Instance,
                    new MqttDecoder(isServer: false, maxMessageSize: MaxMessageSize),
                    new ProvisioningChannelHandlerAdapter(message, tcs, cancellationToken));
            }));

            if (Logging.IsEnabled)
            {
                Logging.Associate(bootstrap, this);
            }

            IPAddress[] addresses = await Dns.GetHostAddressesAsync(message.GlobalDeviceEndpoint).ConfigureAwait(false);

            if (Logging.IsEnabled)
            {
                Logging.Info(this, $"DNS resolved {addresses.Length} addresses.");
            }

            IChannel  channel       = null;
            Exception lastException = null;

            foreach (IPAddress address in addresses)
            {
                cancellationToken.ThrowIfCancellationRequested();

                try
                {
                    if (Logging.IsEnabled)
                    {
                        Logging.Info(this, $"Connecting to {address.ToString()}.");
                    }
                    channel = await bootstrap.ConnectAsync(address, Port).ConfigureAwait(false);

                    break;
                }
                catch (AggregateException ae)
                {
                    ae.Handle((ex) =>
                    {
                        if (ex is ConnectException)     // We will handle DotNetty.Transport.Channels.ConnectException
                        {
                            lastException = ex;
                            if (Logging.IsEnabled)
                            {
                                Logging.Info(
                                    this,
                                    $"ConnectException trying to connect to {address.ToString()}: {ex.ToString()}");
                            }
                            return(true);
                        }

                        return(false); // Let anything else stop the application.
                    });
                }
            }

            if (channel == null)
            {
                string errorMessage = "Cannot connect to Provisioning Service.";
                if (Logging.IsEnabled)
                {
                    Logging.Error(this, errorMessage);
                }
                ExceptionDispatchInfo.Capture(lastException).Throw();
            }

            return(await tcs.Task.ConfigureAwait(false));
        }
        /// <inheritdoc />
        public override async Task <InputFormatterResult> ReadRequestBodyAsync(
            InputFormatterContext context,
            Encoding encoding)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (encoding == null)
            {
                throw new ArgumentNullException(nameof(encoding));
            }

            var request = context.HttpContext.Request;

            var suppressInputFormatterBuffering = _options.SuppressInputFormatterBuffering;

            var readStream        = request.Body;
            var disposeReadStream = false;

            if (!request.Body.CanSeek && !suppressInputFormatterBuffering)
            {
                // JSON.Net does synchronous reads. In order to avoid blocking on the stream, we asynchronously
                // read everything into a buffer, and then seek back to the beginning.
                var memoryThreshold = DefaultMemoryThreshold;
                var contentLength   = request.ContentLength.GetValueOrDefault();
                if (contentLength > 0 && contentLength < memoryThreshold)
                {
                    // If the Content-Length is known and is smaller than the default buffer size, use it.
                    memoryThreshold = (int)contentLength;
                }

                readStream = new FileBufferingReadStream(request.Body, memoryThreshold);

                await readStream.DrainAsync(CancellationToken.None);

                readStream.Seek(0L, SeekOrigin.Begin);

                disposeReadStream = true;
            }

            var       successful = true;
            Exception exception  = null;
            object    model;

            using (var streamReader = context.ReaderFactory(readStream, encoding))
            {
                using var jsonReader  = new JsonTextReader(streamReader);
                jsonReader.ArrayPool  = _charPool;
                jsonReader.CloseInput = false;

                var type           = context.ModelType;
                var jsonSerializer = CreateJsonSerializer(context);
                jsonSerializer.Error += ErrorHandler;
                try
                {
                    model = jsonSerializer.Deserialize(jsonReader, type);
                }
                finally
                {
                    // Clean up the error handler since CreateJsonSerializer() pools instances.
                    jsonSerializer.Error -= ErrorHandler;
                    ReleaseJsonSerializer(jsonSerializer);

                    if (disposeReadStream)
                    {
                        await readStream.DisposeAsync();
                    }
                }
            }

            if (successful)
            {
                if (model == null && !context.TreatEmptyInputAsDefaultValue)
                {
                    // Some nonempty inputs might deserialize as null, for example whitespace,
                    // or the JSON-encoded value "null". The upstream BodyModelBinder needs to
                    // be notified that we don't regard this as a real input so it can register
                    // a model binding error.
                    return(InputFormatterResult.NoValue());
                }
                else
                {
                    return(InputFormatterResult.Success(model));
                }
            }

            if (!(exception is JsonException || exception is OverflowException || exception is FormatException))
            {
                // At this point we've already recorded all exceptions as an entry in the ModelStateDictionary.
                // We only need to rethrow an exception if we believe it needs to be handled by something further up
                // the stack.
                // JsonException, OverflowException, and FormatException are assumed to be only encountered when
                // parsing the JSON and are consequently "safe" to be exposed as part of ModelState. Everything else
                // needs to be rethrown.

                var exceptionDispatchInfo = ExceptionDispatchInfo.Capture(exception);
                exceptionDispatchInfo.Throw();
            }

            return(InputFormatterResult.Failure());

            void ErrorHandler(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs eventArgs)
            {
                successful = false;

                // When ErrorContext.Path does not include ErrorContext.Member, add Member to form full path.
                var path      = eventArgs.ErrorContext.Path;
                var member    = eventArgs.ErrorContext.Member?.ToString();
                var addMember = !string.IsNullOrEmpty(member);

                if (addMember)
                {
                    // Path.Member case (path.Length < member.Length) needs no further checks.
                    if (path.Length == member.Length)
                    {
                        // Add Member in Path.Memb case but not for Path.Path.
                        addMember = !string.Equals(path, member, StringComparison.Ordinal);
                    }
                    else if (path.Length > member.Length)
                    {
                        // Finally, check whether Path already ends with Member.
                        if (member[0] == '[')
                        {
                            addMember = !path.EndsWith(member, StringComparison.Ordinal);
                        }
                        else
                        {
                            addMember = !path.EndsWith("." + member, StringComparison.Ordinal) &&
                                        !path.EndsWith("['" + member + "']", StringComparison.Ordinal) &&
                                        !path.EndsWith("[" + member + "]", StringComparison.Ordinal);
                        }
                    }
                }

                if (addMember)
                {
                    path = ModelNames.CreatePropertyModelName(path, member);
                }

                // Handle path combinations such as ""+"Property", "Parent"+"Property", or "Parent"+"[12]".
                var key = ModelNames.CreatePropertyModelName(context.ModelName, path);

                exception = eventArgs.ErrorContext.Error;

                var metadata            = GetPathMetadata(context.Metadata, path);
                var modelStateException = WrapExceptionForModelState(exception);

                context.ModelState.TryAddModelError(key, modelStateException, metadata);

                _logger.JsonInputException(exception);

                // Error must always be marked as handled
                // Failure to do so can cause the exception to be rethrown at every recursive level and
                // overflow the stack for x64 CLR processes
                eventArgs.ErrorContext.Handled = true;
            }
        }