protected override async Task OnSendAsync(Message message, TimeSpan timeout)
        {
            this.ThrowIfDisposedOrNotOpen();

            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);

            // If timeout == TimeSpan.MaxValue, then we want to pass Timeout.Infinite as
            // SemaphoreSlim doesn't accept timeouts > Int32.MaxValue.
            // Using TimeoutHelper.RemainingTime() would yield a value less than TimeSpan.MaxValue
            // and would result in the value Int32.MaxValue so we must use the original timeout specified.
            if (!await _sendLock.WaitAsync(TimeoutHelper.ToMilliseconds(timeout)))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException(
                                                                              SR.Format(SR.SendToViaTimedOut, Via, timeout),
                                                                              TimeoutHelper.CreateEnterTimedOutException(timeout)));
            }

            byte[] buffer = null;

            try
            {
                // check again in case the previous send faulted while we were waiting for the lock
                this.ThrowIfDisposedOrNotOpen();
                this.ThrowIfOutputSessionClosed();

                bool success = false;
                try
                {
                    this.ApplyChannelBinding(message);

                    var tcs = new TaskCompletionSource <bool>(this);

                    AsyncCompletionResult completionResult;
                    if (this.IsStreamedOutput)
                    {
                        completionResult = this.StartWritingStreamedMessage(message, timeoutHelper.RemainingTime(), s_onWriteComplete, this);
                    }
                    else
                    {
                        bool allowOutputBatching;
                        ArraySegment <byte> messageData;
                        allowOutputBatching = message.Properties.AllowOutputBatching;
                        messageData         = this.EncodeMessage(message);

                        buffer           = messageData.Array;
                        completionResult = this.StartWritingBufferedMessage(
                            message,
                            messageData,
                            allowOutputBatching,
                            timeoutHelper.RemainingTime(),
                            s_onWriteComplete,
                            tcs);
                    }

                    if (completionResult == AsyncCompletionResult.Completed)
                    {
                        tcs.TrySetResult(true);
                    }

                    await tcs.Task;

                    this.FinishWritingMessage();

                    success = true;
                    if (TD.MessageSentByTransportIsEnabled())
                    {
                        EventTraceActivity eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
                        TD.MessageSentByTransport(eventTraceActivity, this.RemoteAddress.Uri.AbsoluteUri);
                    }
                }
                finally
                {
                    if (!success)
                    {
                        this.Fault();
                    }
                }
            }
            finally
            {
                _sendLock.Release();
            }
            if (buffer != null)
            {
                _bufferManager.ReturnBuffer(buffer);
            }
        }
Exemple #2
0
        IAsyncResult BeginGetContext(bool startListening)
        {
            EventTraceActivity eventTraceActivity = null;

            if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled)
            {
                eventTraceActivity = EventTraceActivity.GetFromThreadOrCreate(true);
                if (TD.HttpGetContextStartIsEnabled())
                {
                    TD.HttpGetContextStart(eventTraceActivity);
                }
            }

            while (true)
            {
                Exception unexpectedException = null;
                try
                {
                    try
                    {
                        if (ExecutionContext.IsFlowSuppressed())
                        {
                            return(this.BeginGetContextCore(eventTraceActivity));
                        }
                        else
                        {
                            using (ExecutionContext.SuppressFlow())
                            {
                                return(this.BeginGetContextCore(eventTraceActivity));
                            }
                        }
                    }
                    catch (HttpListenerException e)
                    {
                        if (!this.HandleHttpException(e))
                        {
                            throw;
                        }
                    }
                }
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    }
                    if (startListening)
                    {
                        // Since we're under a call to StartListening(), just throw the exception up the stack.
                        throw;
                    }
                    unexpectedException = e;
                }

                if (unexpectedException != null)
                {
                    this.Fault(unexpectedException);
                    return(null);
                }
            }
        }
        public void Connect(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);

            addNeighbor.Set();              // We are trying to add a neighbor

            List <IAsyncResult> results = new List <IAsyncResult>();
            List <WaitHandle>   handles = new List <WaitHandle>();

            // While we have more to endpoints try and we have connections pending and we are not connected upto ideal yet, and the maintainer is still open
            while (results.Count != 0 ||
                   (((nodeAddresses.Count != 0 || pendingConnectedNeighbor.Count != 0) && maintainer.IsOpen) &&
                    maintainer.ConnectedNeighborCount < wantedConnectionCount))
            {
                try
                {
                    handles.Clear();
                    foreach (IAsyncResult iar in results)
                    {
                        handles.Add(iar.AsyncWaitHandle);
                    }
                    handles.Add(welcomeReceived);                               // One of our connect requests resulted in a welcome or neighborManager was shutting down
                    handles.Add(maintainerClosed);                              // One of our connect requests resulted in a welcome or neighborManager was shutting down
                    handles.Add(addNeighbor);                                   // Make the last waithandle the add a neighbor signal

                    int index = WaitHandle.WaitAny(handles.ToArray(), config.ConnectTimeout, false);
                    if (index == results.Count)                                 // welcomeReceived was signalled
                    {
                        welcomeReceived.Reset();
                    }
                    else if (index == results.Count + 1)                        // maintainerClosed was signalled
                    {
                        maintainerClosed.Reset();
                        lock (ThisLock)
                        {
                            nodeAddresses.Clear();
                        }
                    }
                    else if (index == results.Count + 2)                        // addNeighbor was signalled
                    {
                        // We need to open a new neighbor
                        if (nodeAddresses.Count > 0)
                        {
                            if (pendingConnectedNeighbor.Count + maintainer.ConnectedNeighborCount < wantedConnectionCount)
                            {
                                PeerNodeAddress epr = null;
                                lock (ThisLock)
                                {
                                    if (nodeAddresses.Count == 0 || !maintainer.IsOpen)   // nodeAddresses or maintainer is closed got updated better cycle
                                    {
                                        addNeighbor.Reset();
                                        continue;
                                    }
                                    int index2             = random.Next() % nodeAddresses.Count;
                                    ICollection <Uri> keys = nodeAddresses.Keys;
                                    int i   = 0;
                                    Uri key = null;
                                    foreach (Uri uri in keys)
                                    {
                                        if (i++ == index2)
                                        {
                                            key = uri;
                                            break;
                                        }
                                    }
                                    Fx.Assert(key != null, "key cannot be null here");
                                    epr = nodeAddresses[key];
                                    Fx.Assert(epr != null, "epr cannot be null here");
                                    nodeAddresses.Remove(key);
                                }
                                if (maintainer.FindDuplicateNeighbor(epr) == null &&
                                    pendingConnectedNeighbor.ContainsKey(GetEndpointUri(epr)) == false)
                                {
                                    lock (ThisLock)
                                    {
                                        pendingConnectedNeighbor.Add(GetEndpointUri(epr), epr);
                                    }

                                    // If the neighborManager is not open this call is going to throw.
                                    // It throws ObjectDisposed exception.
                                    // This check merely eliminates the perf hit, this check is not strictly necessary
                                    // but cuts down the window for the ---- that will result in a throw to a miniscule level
                                    // We ---- the throw because we are closing down
                                    try
                                    {
                                        if (maintainer.IsOpen)
                                        {
                                            if (DiagnosticUtility.ShouldTraceInformation)
                                            {
                                                PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord(SR.GetString(SR.PeerMaintainerConnect, epr, this.config.MeshId));
                                                TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                                                        record, this, null);
                                            }
                                            IAsyncResult iar = maintainer.BeginOpenNeighbor(epr, timeoutHelper.RemainingTime(), null, epr);
                                            results.Add(iar);
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        if (Fx.IsFatal(e))
                                        {
                                            throw;
                                        }
                                        if (DiagnosticUtility.ShouldTraceInformation)
                                        {
                                            PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord(SR.GetString(SR.PeerMaintainerConnectFailure, epr, this.config.MeshId, e.Message));
                                            TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                                                    record, this, null);
                                        }

                                        // I need to remove the epr just began because the BeginOpen threw.
                                        // However Object Disposed can arise as a result of a ---- between PeerNode.Close()
                                        // and Connect trying to reconnect nodes.
                                        pendingConnectedNeighbor.Remove(GetEndpointUri(epr));
                                        if (!(e is ObjectDisposedException))
                                        {
                                            throw;
                                        }

                                        DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
                                    }
                                }
                            }
                        }

                        if (nodeAddresses.Count == 0 || pendingConnectedNeighbor.Count + maintainer.ConnectedNeighborCount == wantedConnectionCount)
                        {
                            addNeighbor.Reset();
                        }
                    }
                    else if (index != WaitHandle.WaitTimeout)
                    {
                        // We have completed this thing remove it from results
                        IAsyncResult iar = results[index];
                        results.RemoveAt(index);
                        IPeerNeighbor neighbor = null;
                        try
                        {
                            // Get opened neighbor and fire NeighborOpened notification
                            neighbor = maintainer.EndOpenNeighbor(iar);
                        }
                        catch (Exception e)
                        {
                            if (Fx.IsFatal(e))
                            {
                                throw;
                            }
                            pendingConnectedNeighbor.Remove(GetEndpointUri((PeerNodeAddress)iar.AsyncState));
                            throw;
                        }
                    }
                    else
                    {
                        //A timeout occured no connections progressed, try some more connections
                        //This may result in more than wantedConnectionCount connections if the timeout connections were
                        // merely being slow
                        pendingConnectedNeighbor.Clear();
                        results.Clear();
                        addNeighbor.Set();
                    }
                }
                catch (CommunicationException e)
                {
                    // mostly likely the endpoint could not be reached, but any channel exception means we should try another node
                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
                    addNeighbor.Set();
                }
                catch (TimeoutException e)
                {
                    if (TD.OpenTimeoutIsEnabled())
                    {
                        TD.OpenTimeout(e.Message);
                    }
                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
                    addNeighbor.Set();
                }
            }
        }
        void HandleCompletedAccept(IAsyncResult result)
        {
            IConnection connection = null;

            lock (ThisLock)
            {
                bool      success             = false;
                Exception unexpectedException = null;
                try
                {
                    if (!isDisposed)
                    {
                        connection = listener.EndAccept(result);
                        if (connection != null)
                        {
                            if (connections + 1 >= maxPendingConnections)
                            {
                                if (TD.MaxPendingConnectionsExceededIsEnabled())
                                {
                                    TD.MaxPendingConnectionsExceeded(SR.GetString(SR.TraceCodeMaxPendingConnectionsReached));
                                }
                                if (DiagnosticUtility.ShouldTraceWarning)
                                {
                                    TraceUtility.TraceEvent(TraceEventType.Warning,
                                                            TraceCode.MaxPendingConnectionsReached, SR.GetString(SR.TraceCodeMaxPendingConnectionsReached),
                                                            new StringTraceRecord("MaxPendingConnections", maxPendingConnections.ToString(System.Globalization.CultureInfo.InvariantCulture)),
                                                            this,
                                                            null);
                                }
                            }
                            else if (TD.PendingConnectionsRatioIsEnabled())
                            {
                                TD.PendingConnectionsRatio(connections + 1, maxPendingConnections);
                            }

                            // This is incremented after the Trace just in case the Trace throws.
                            connections++;
                        }
                    }
                    success = true;
                }
                catch (CommunicationException exception)
                {
                    DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
                }
                catch (Exception exception)
                {
                    if (Fx.IsFatal(exception))
                    {
                        throw;
                    }
                    if ((errorCallback == null) && !ExceptionHandler.HandleTransportExceptionHelper(exception))
                    {
                        throw;
                    }
                    unexpectedException = exception;
                }
                finally
                {
                    if (!success)
                    {
                        connection = null;
                    }
                    pendingAccepts--;
                    if (pendingAccepts == 0 && TD.PendingAcceptsAtZeroIsEnabled())
                    {
                        TD.PendingAcceptsAtZero();
                    }
                }

                if ((unexpectedException != null) && (errorCallback != null))
                {
                    errorCallback(unexpectedException);
                }
            }

            AcceptIfNecessary(false);

            if (connection != null)
            {
                callback(connection, onConnectionDequeued);
            }
        }
Exemple #5
0
            static void OnProcessConnection(IAsyncResult result)
            {
                if (result.CompletedSynchronously)
                {
                    return;
                }

                EstablishConnectionAsyncResult thisPtr = (EstablishConnectionAsyncResult)result.AsyncState;

                Exception completionException = null;
                bool      completeSelf;

                try
                {
                    bool snapshotCollection = false;
                    try
                    {
                        completeSelf = thisPtr.HandleProcessConnection(result);
                        if (completeSelf)
                        {
                            snapshotCollection = true;
                        }
                    }
                    catch (CommunicationException communicationException)
                    {
                        if (!thisPtr.newConnection) // CommunicationException is ok from our cache
                        {
                            DiagnosticUtility.TraceHandledException(communicationException, TraceEventType.Information);
                            thisPtr.Cleanup();
                            completeSelf = thisPtr.Begin();
                        }
                        else
                        {
                            completeSelf        = true;
                            completionException = communicationException;
                        }
                    }
                    catch (TimeoutException timeoutException)
                    {
                        if (!thisPtr.newConnection) // TimeoutException is ok from our cache
                        {
                            if (TD.OpenTimeoutIsEnabled())
                            {
                                TD.OpenTimeout(timeoutException.Message);
                            }
                            DiagnosticUtility.TraceHandledException(timeoutException, TraceEventType.Information);
                            thisPtr.Cleanup();
                            completeSelf = thisPtr.Begin();
                        }
                        else
                        {
                            completeSelf        = true;
                            completionException = timeoutException;
                        }
                    }

                    if (snapshotCollection)
                    {
                        thisPtr.SnapshotConnection();
                    }
                }
#pragma warning suppress 56500 // Microsoft, transferring exception to another thread
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    }

                    completeSelf        = true;
                    completionException = e;
                }

                if (completeSelf)
                {
                    thisPtr.Cleanup();
                    thisPtr.Complete(false, completionException);
                }
            }
Exemple #6
0
        public IConnection EstablishConnection(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper             = new TimeoutHelper(timeout);
            IConnection   localRawConnection        = null;
            IConnection   localUpgradedConnection   = null;
            bool          localIsConnectionFromPool = true;

            EventTraceActivity localEventTraceActivity = this.EventTraceActivity;

            if (TD.EstablishConnectionStartIsEnabled())
            {
                TD.EstablishConnectionStart(localEventTraceActivity,
                                            this.via != null ? this.via.AbsoluteUri : string.Empty);
            }

            // first try and use a connection from our pool (and use it if we successfully receive an ACK)
            while (localIsConnectionFromPool)
            {
                localRawConnection = this.TakeConnection(timeoutHelper.RemainingTime());
                if (localRawConnection == null)
                {
                    localIsConnectionFromPool = false;
                }
                else
                {
                    bool preambleSuccess = false;
                    try
                    {
                        localUpgradedConnection = AcceptPooledConnection(localRawConnection, ref timeoutHelper);
                        preambleSuccess         = true;
                        break;
                    }
                    catch (CommunicationException e)
                    {
                        DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
                        // CommmunicationException is ok since it was a cached connection of unknown state
                    }
                    catch (TimeoutException e)
                    {
                        if (TD.OpenTimeoutIsEnabled())
                        {
                            TD.OpenTimeout(e.Message);
                        }
                        DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
                        // ditto for TimeoutException
                    }
                    finally
                    {
                        if (!preambleSuccess)
                        {
                            if (TD.ConnectionPoolPreambleFailedIsEnabled())
                            {
                                TD.ConnectionPoolPreambleFailed(localEventTraceActivity);
                            }

                            if (DiagnosticUtility.ShouldTraceInformation)
                            {
                                TraceUtility.TraceEvent(
                                    TraceEventType.Information,
                                    TraceCode.FailedAcceptFromPool,
                                    SR.GetString(
                                        SR.TraceCodeFailedAcceptFromPool,
                                        timeoutHelper.RemainingTime()));
                            }

                            // This cannot throw TimeoutException since isConnectionStillGood is false (doesn't attempt a Close).
                            this.connectionPool.ReturnConnection(connectionKey, localRawConnection, false, TimeSpan.Zero);
                        }
                    }
                }
            }

            // if there isn't anything in the pool, we need to use a new connection
            if (!localIsConnectionFromPool)
            {
                bool     success        = false;
                TimeSpan connectTimeout = timeoutHelper.RemainingTime();
                try
                {
                    try
                    {
                        localRawConnection = this.connectionInitiator.Connect(this.via, connectTimeout);
                    }
                    catch (TimeoutException e)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateNewConnectionTimeoutException(
                                                                                      connectTimeout, e));
                    }

                    this.connectionInitiator = null;
                    localUpgradedConnection  = AcceptPooledConnection(localRawConnection, ref timeoutHelper);
                    success = true;
                }
                finally
                {
                    if (!success)
                    {
                        connectionKey = null;
                        if (localRawConnection != null)
                        {
                            localRawConnection.Abort();
                        }
                    }
                }
            }

            SnapshotConnection(localUpgradedConnection, localRawConnection, localIsConnectionFromPool);

            if (TD.EstablishConnectionStopIsEnabled())
            {
                TD.EstablishConnectionStop(localEventTraceActivity);
            }

            return(localUpgradedConnection);
        }
        private async Task <WebSocket> CreateWebSocketWithFactoryAsync(X509Certificate2 certificate, TimeoutHelper timeoutHelper)
        {
            Contract.Assert(_connectionFactory != null, "Invalid call: CreateWebSocketWithFactory.");

            if (TD.WebSocketCreateClientWebSocketWithFactoryIsEnabled())
            {
                TD.WebSocketCreateClientWebSocketWithFactory(EventTraceActivity, _connectionFactory.GetType().FullName);
            }

            // Create the client WebSocket with the factory.
            WebSocket ws;

            try
            {
                if (certificate != null)
                {
                    throw ExceptionHelper.PlatformNotSupported("client certificates not supported yet");
                }
                var headers = new WebHeaderCollection();
                headers[WebSocketTransportSettings.SoapContentTypeHeader] = _channelFactory.WebSocketSoapContentType;
                if (_channelFactory.MessageEncoderFactory is BinaryMessageEncoderFactory)
                {
                    headers[WebSocketTransportSettings.BinaryEncoderTransferModeHeader] = _channelFactory.TransferMode.ToString();
                }

                var credentials = _channelFactory.GetCredentials();
                ws = await _connectionFactory.CreateWebSocketAsync(Via, headers, credentials, WebSocketSettings.Clone(), timeoutHelper);
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }

                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Format(SR.ClientWebSocketFactory_CreateWebSocketFailed, _connectionFactory.GetType().Name), e));
            }

            // The returned WebSocket should be valid (non-null), in an opened state and with the same SubProtocol that we requested.
            if (ws == null)
            {
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Format(SR.ClientWebSocketFactory_InvalidWebSocket, _connectionFactory.GetType().Name)));
            }

            if (ws.State != WebSocketState.Open)
            {
                ws.Dispose();
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Format(SR.ClientWebSocketFactory_InvalidWebSocket, _connectionFactory.GetType().Name)));
            }

            string requested = WebSocketSettings.SubProtocol;
            string obtained  = ws.SubProtocol;

            if (!(requested == null ? string.IsNullOrWhiteSpace(obtained) : requested.Equals(obtained, StringComparison.OrdinalIgnoreCase)))
            {
                ws.Dispose();
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Format(SR.ClientWebSocketFactory_InvalidSubProtocol, _connectionFactory.GetType().Name, obtained, requested)));
            }

            return(ws);
        }
        protected internal override async Task OnOpenAsync(TimeSpan timeout)
        {
            TimeoutHelper helper = new TimeoutHelper(timeout);

            bool success = false;

            try
            {
                if (TD.WebSocketConnectionRequestSendStartIsEnabled())
                {
                    TD.WebSocketConnectionRequestSendStart(
                        EventTraceActivity,
                        RemoteAddress != null ? RemoteAddress.ToString() : string.Empty);
                }

                ChannelParameterCollection channelParameterCollection = new ChannelParameterCollection();

                if (HttpChannelFactory <IDuplexSessionChannel> .MapIdentity(this.RemoteAddress, _channelFactory.AuthenticationScheme))
                {
                    lock (ThisLock)
                    {
                        _cleanupIdentity = HttpTransportSecurityHelpers.AddIdentityMapping(Via, RemoteAddress);
                    }
                }

                X509Certificate2 clientCertificate = null;
                HttpsChannelFactory <IDuplexSessionChannel> httpsChannelFactory = _channelFactory as HttpsChannelFactory <IDuplexSessionChannel>;
                if (httpsChannelFactory != null && httpsChannelFactory.RequireClientCertificate)
                {
                    var certificateProvider    = httpsChannelFactory.CreateAndOpenCertificateTokenProvider(RemoteAddress, Via, channelParameterCollection, helper.RemainingTime());
                    var clientCertificateToken = httpsChannelFactory.GetCertificateSecurityToken(certificateProvider, RemoteAddress, Via, channelParameterCollection, ref helper);
                    var x509Token = (X509SecurityToken)clientCertificateToken.Token;
                    clientCertificate = x509Token.Certificate;
                }

                try
                {
                    WebSocket = await CreateWebSocketWithFactoryAsync(clientCertificate, helper);
                }
                finally
                {
                    if (WebSocket != null && _cleanupStarted)
                    {
                        WebSocket.Abort();
                        CommunicationObjectAbortedException communicationObjectAbortedException = new CommunicationObjectAbortedException(
                            new WebSocketException(WebSocketError.ConnectionClosedPrematurely).Message);
                        FxTrace.Exception.AsWarning(communicationObjectAbortedException);
                        throw communicationObjectAbortedException;
                    }
                }

                bool inputUseStreaming = TransferModeHelper.IsResponseStreamed(TransferMode);

                SetMessageSource(new WebSocketMessageSource(
                                     this,
                                     WebSocket,
                                     inputUseStreaming,
                                     this));

                success = true;

                if (TD.WebSocketConnectionRequestSendStopIsEnabled())
                {
                    TD.WebSocketConnectionRequestSendStop(
                        EventTraceActivity,
                        WebSocket != null ? WebSocket.GetHashCode() : -1);
                }
            }
            catch (WebSocketException ex)
            {
                if (TD.WebSocketConnectionFailedIsEnabled())
                {
                    TD.WebSocketConnectionFailed(EventTraceActivity, ex.Message);
                }

                TryConvertAndThrow(ex);
            }
            finally
            {
                CleanupTokenProviders();
                if (!success)
                {
                    CleanupOnError();
                }
            }
        }
Exemple #9
0
                protected override void SendHttpPipelineResponse()
                {
                    this.WaitTransportIntegrationHandlerTask(this.defaultSendTimeout);

                    HttpResponseMessage response = this.transportIntegrationHandlerTask.Result;

                    // HttpResponseMessage equals to null means that the pipeline is already cancelled.
                    // We should aborte the connection immediately in this case.
                    if (response == null)
                    {
                        this.cancellationTokenSource.Cancel();
                    }
                    else
                    {
                        if (response.StatusCode == HttpStatusCode.SwitchingProtocols)
                        {
                            string protocol = null;
                            if (response.Headers.Contains(WebSocketHelper.SecWebSocketProtocol))
                            {
                                foreach (string headerValue in response.Headers.GetValues(WebSocketHelper.SecWebSocketProtocol))
                                {
                                    protocol = headerValue;
                                    break;
                                }

                                response.Headers.Remove(WebSocketHelper.SecWebSocketProtocol);
                            }

                            // Remove unnecessary properties from HttpRequestMessage
                            if (response.RequestMessage != null)
                            {
                                HttpPipeline.RemoveHttpPipeline(response.RequestMessage);
                                response.RequestMessage.Properties.Remove(RemoteEndpointMessageProperty.Name);
                            }

                            // CSDMain 255817: There's a race condition that the channel could be dequeued and pipeline could be closed before the
                            // Listener.CreateWebSocketChannelAndEnqueue call finishes. In this case, we are actually calling BeginGetContext twice, thus
                            // cause the memory leak.
                            this.isShortCutResponse = false;
                            bool channelEnqueued;
                            try
                            {
                                channelEnqueued = this.HttpRequestContext.Listener.CreateWebSocketChannelAndEnqueue(this.HttpRequestContext, this, response, protocol, this.dequeuedCallback);
                            }
                            catch (Exception ex)
                            {
                                if (!Fx.IsFatal(ex))
                                {
                                    if (TD.WebSocketConnectionFailedIsEnabled())
                                    {
                                        TD.WebSocketConnectionFailed(this.EventTraceActivity, ex.Message);
                                    }

                                    this.HttpRequestContext.SendResponseAndClose(HttpStatusCode.InternalServerError);
                                }

                                throw;
                            }

                            this.isShortCutResponse = !channelEnqueued;
                            if (!channelEnqueued)
                            {
                                if (TD.WebSocketConnectionDeclinedIsEnabled())
                                {
                                    TD.WebSocketConnectionDeclined(this.EventTraceActivity, HttpStatusCode.ServiceUnavailable.ToString());
                                }

                                this.httpRequestContext.SendResponseAndClose(HttpStatusCode.ServiceUnavailable);
                            }
                        }
                        else
                        {
                            if (TD.WebSocketConnectionDeclinedIsEnabled())
                            {
                                TD.WebSocketConnectionDeclined(this.EventTraceActivity, response.StatusCode.ToString());
                            }

                            this.SendAndClose(response);
                        }
                    }
                }
Exemple #10
0
 /// <summary>
 /// Check if trace definition is enabled
 /// Event description ID=4801, Level=verbose, Channel=Debug
 /// </summary>
 internal static bool ByteStreamMessageDecodingStartIsEnabled()
 {
     return(FxTrace.ShouldTraceVerbose && TD.IsEtwEventEnabled(1));
 }
Exemple #11
0
 /// <summary>
 /// Check if trace definition is enabled
 /// Event description ID=4800, Level=Warning, Channel=debug
 /// </summary>
 internal static bool MaxPendingMessagesTotalSizeReachedIsEnabled()
 {
     return(FxTrace.ShouldTraceWarning &&
            (FxTrace.ShouldTraceWarningToTraceSource || TD.IsEtwEventEnabled(0)));
 }
Exemple #12
0
        public override ArraySegment <byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
        {
            if (message == null)
            {
                throw FxTrace.Exception.ArgumentNull("message");
            }
            if (bufferManager == null)
            {
                throw FxTrace.Exception.ArgumentNull("bufferManager");
            }
            if (maxMessageSize < 0)
            {
                throw FxTrace.Exception.ArgumentOutOfRange("maxMessageSize", maxMessageSize, SR.ArgumentOutOfMinRange(0));
            }
            if (messageOffset < 0)
            {
                throw FxTrace.Exception.ArgumentOutOfRange("messageOffset", messageOffset, SR.ArgumentOutOfMinRange(0));
            }

            EventTraceActivity eventTraceActivity = null;

            if (TD.ByteStreamMessageEncodingStartIsEnabled())
            {
                eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
                TD.ByteStreamMessageEncodingStart(eventTraceActivity);
            }

            ThrowIfMismatchedMessageVersion(message);
            message.Properties.Encoder = this;

            ArraySegment <byte> messageBuffer;
            int size;

            using (BufferManagerOutputStream stream = new BufferManagerOutputStream(maxSentMessageSizeExceededResourceString, 0, maxMessageSize, bufferManager))
            {
                stream.Skip(messageOffset);
                using (XmlWriter writer = new XmlByteStreamWriter(stream, true))
                {
                    message.WriteMessage(writer);
                    writer.Flush();
                    byte[] bytes = stream.ToArray(out size);
                    messageBuffer = new ArraySegment <byte>(bytes, messageOffset, size - messageOffset);
                }
            }

            if (SMTD.MessageWrittenByEncoderIsEnabled())
            {
                SMTD.MessageWrittenByEncoder(
                    eventTraceActivity ?? EventTraceActivityHelper.TryExtractActivity(message),
                    messageBuffer.Count,
                    this);
            }

            if (MessageLogger.LogMessagesAtTransportLevel)
            {
                // DevDiv#486728
                // Don't pass in a buffer manager to avoid returning 'messageBuffer" to the bufferManager twice.
                ByteStreamBufferedMessageData messageData = new ByteStreamBufferedMessageData(messageBuffer, null);
                using (XmlReader reader = new XmlBufferedByteStreamReader(messageData, this.quotas))
                {
                    MessageLogger.LogMessage(ref message, reader, MessageLoggingSource.TransportSend);
                }
            }

            return(messageBuffer);
        }
Exemple #13
0
        void OnConnectionModeKnownCore(ConnectionModeReader modeReader, bool isCached)
        {
            lock (ThisLock)
            {
                if (isDisposed)
                {
                    return;
                }

                this.connectionReaders.Remove(modeReader);
            }

            bool closeReader = true;

            try
            {
                FramingMode framingMode;
                try
                {
                    framingMode = modeReader.GetConnectionMode();
                }
                catch (CommunicationException exception)
                {
                    TraceEventType eventType = modeReader.Connection.ExceptionEventType;
                    DiagnosticUtility.TraceHandledException(exception, eventType);
                    return;
                }
                catch (TimeoutException exception)
                {
                    if (!isCached)
                    {
                        exception = new TimeoutException(SR.GetString(SR.ChannelInitializationTimeout, this.channelInitializationTimeout), exception);
                        System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(exception);
                    }

                    if (TD.ChannelInitializationTimeoutIsEnabled())
                    {
                        TD.ChannelInitializationTimeout(SR.GetString(SR.ChannelInitializationTimeout, this.channelInitializationTimeout));
                    }

                    TraceEventType eventType = modeReader.Connection.ExceptionEventType;
                    DiagnosticUtility.TraceHandledException(exception, eventType);
                    return;
                }

                switch (framingMode)
                {
                case FramingMode.Duplex:
                    OnDuplexConnection(modeReader.Connection, modeReader.ConnectionDequeuedCallback,
                                       modeReader.StreamPosition, modeReader.BufferOffset, modeReader.BufferSize,
                                       modeReader.GetRemainingTimeout());
                    break;

                case FramingMode.Singleton:
                    OnSingletonConnection(modeReader.Connection, modeReader.ConnectionDequeuedCallback,
                                          modeReader.StreamPosition, modeReader.BufferOffset, modeReader.BufferSize,
                                          modeReader.GetRemainingTimeout());
                    break;

                default:
                {
                    Exception inner = new InvalidDataException(SR.GetString(
                                                                   SR.FramingModeNotSupported, framingMode));
                    Exception exception = new ProtocolException(inner.Message, inner);
                    FramingEncodingString.AddFaultString(exception, FramingEncodingString.UnsupportedModeFault);
                    System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(exception);
                    return;
                }
                }

                closeReader = false;
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                if (!ExceptionHandler.HandleTransportExceptionHelper(e))
                {
                    throw;
                }

                // containment -- the reader is aborted, no need for additional containment
            }
            finally
            {
                if (closeReader)
                {
                    modeReader.Dispose();
                }
            }
        }