Exemple #1
0
 public TransactionSignalScope(AsyncResult result, Transaction transaction)
 {
     Fx.Assert(transaction != null, "Null Transaction provided to AsyncResult.TransactionSignalScope.");
     _parent           = result;
     _transactionScope = Fx.CreateTransactionScope(transaction);
 }
 public void DebugVerifyEmpty()
 {
     Fx.Assert(this.gate == 0, "Finalized with unfinished slot.");
     Fx.Assert(this.heldCallback == null, "Finalized with leaked callback.");
     Fx.Assert(this.heldState == null, "Finalized with leaked state.");
 }
Exemple #3
0
        protected bool TryComplete(bool didCompleteSynchronously, Exception exception)
        {
            lock (ThisLock)
            {
                if (IsCompleted)
                {
                    return(false);
                }

                _exception  = exception;
                IsCompleted = true;
            }

#if DEBUG
            _marker.AsyncResult = null;
            _marker             = null;
#endif

            CompletedSynchronously = didCompleteSynchronously;
            if (OnCompleting != null)
            {
                // Allow exception replacement, like a catch/throw pattern.
                try
                {
                    OnCompleting(this, _exception);
                }
                catch (Exception e) when(!Fx.IsFatal(e))
                {
                    _exception = e;
                }
            }

            if (didCompleteSynchronously)
            {
                // If we completedSynchronously, then there's no chance that the manualResetEvent was created so
                // we don't need to worry about a race
                Fx.Assert(_manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult.");
            }
            else
            {
                lock (ThisLock)
                {
                    if (_manualResetEvent != null)
                    {
                        _manualResetEvent.Set();
                    }
                }
            }

            if (_callback != null)
            {
                try
                {
                    if (VirtualCallback != null)
                    {
                        VirtualCallback(_callback, this);
                    }
                    else
                    {
                        _callback(this);
                    }
                }
#pragma warning disable 1634
#pragma warning suppress 56500 // transferring exception to another thread
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    }

                    throw Fx.Exception.AsError(new InvalidOperationException(CommonResources.AsyncCallbackThrewException, e));
                }
#pragma warning restore 1634
            }

            return(true);
        }
Exemple #4
0
 public static void End(IAsyncResult result)
 {
     Fx.AssertAndThrowFatal(result.IsCompleted, "CompletedAsyncResult was not completed!");
     AsyncResult.End <CompletedAsyncResult>(result);
 }
        void CompletionCallback(out Action <object> callback, out object state)
        {
            int slot = this.headTail;
            int slotLowPri;

            while (true)
            {
                Fx.Assert(Bits.Count(slot) != -1, "CompletionCallback called on idle IOTS!");

                bool wasEmpty = Bits.Count(slot) == 0;
                if (wasEmpty)
                {
                    // We're about to set this to idle.  First check the low-priority queue.  This alone doesn't
                    // guarantee we service all the low-pri items - there hasn't even been an Interlocked yet.  But
                    // we take care of that later.
                    slotLowPri = this.headTailLowPri;
                    while (Bits.CountNoIdle(slotLowPri) != 0)
                    {
                        if (slotLowPri == (slotLowPri = Interlocked.CompareExchange(ref this.headTailLowPri,
                                                                                    Bits.IncrementLo(slotLowPri), slotLowPri)))
                        {
                            this.overlapped.Post(this);
                            this.slotsLowPri[slotLowPri & SlotMaskLowPri].DequeueWorkItem(out callback, out state);
                            return;
                        }
                    }
                }

                if (slot == (slot = Interlocked.CompareExchange(ref this.headTail, Bits.IncrementLo(slot), slot)))
                {
                    if (!wasEmpty)
                    {
                        this.overlapped.Post(this);
                        this.slots[slot & SlotMask].DequeueWorkItem(out callback, out state);
                        return;
                    }

                    // We just set the IOThreadScheduler to idle.  Check if a low-priority item got added in the
                    // interim.
                    // Interlocked calls create a thread barrier, so this read will give us the value of
                    // headTailLowPri at the time of the interlocked that set us to idle, or later.  The invariant
                    // here is that either the low-priority queue was empty at some point after we set the IOTS to
                    // idle (so that the next enqueue will notice, and issue a Post), or that the IOTS was unidle at
                    // some point after we set it to idle (so that the next attempt to go idle will verify that the
                    // low-priority queue is empty).
                    slotLowPri = this.headTailLowPri;

                    if (Bits.CountNoIdle(slotLowPri) != 0)
                    {
                        // Whoops, go back from being idle (unless someone else already did).  If we go back, start
                        // over.  (We still owe a Post.)
                        slot = Bits.IncrementLo(slot);
                        if (slot == Interlocked.CompareExchange(ref this.headTail, slot + Bits.HiOne, slot))
                        {
                            slot += Bits.HiOne;
                            continue;
                        }

                        // We know that there's a low-priority work item.  But we also know that the IOThreadScheduler
                        // wasn't idle.  It's best to let it take care of itself, since according to this method, we
                        // just set the IOThreadScheduler to idle so shouldn't take on any tasks.
                    }

                    break;
                }
            }

            callback = null;
            state    = null;
            return;
        }
Exemple #6
0
 void IdleTimerCallback()
 {
     Fx.Assert(this.referenceCount == 0, "Cached IotHubConnection's ref count should be zero when idle timeout occurs!");
     this.cache.RemoveHubScopeConnectionPool(this.ConnectionString);
     this.Connection.CloseAsync().Fork();
 }
        /// <summary>
        /// Copies the properties from the amqp message to the Message instance.
        /// </summary>
        public static void UpdateMessageHeaderAndProperties(AmqpMessage amqpMessage, Message data)
        {
            Fx.AssertAndThrow(amqpMessage.DeliveryTag != null, "AmqpMessage should always contain delivery tag.");
            data.DeliveryTag = amqpMessage.DeliveryTag;

            SectionFlag sections = amqpMessage.Sections;

            if ((sections & SectionFlag.Properties) != 0)
            {
                // Extract only the Properties that we support
                data.MessageId = amqpMessage.Properties.MessageId != null?amqpMessage.Properties.MessageId.ToString() : null;

                data.To = amqpMessage.Properties.To != null?amqpMessage.Properties.To.ToString() : null;

                if (amqpMessage.Properties.AbsoluteExpiryTime.HasValue)
                {
                    data.ExpiryTimeUtc = amqpMessage.Properties.AbsoluteExpiryTime.Value;
                }

                data.CorrelationId = amqpMessage.Properties.CorrelationId != null?amqpMessage.Properties.CorrelationId.ToString() : null;

                data.UserId = amqpMessage.Properties.UserId.Array != null?Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array, 0 /*index*/, amqpMessage.Properties.UserId.Array.Length) : null;

                if (!string.IsNullOrWhiteSpace(amqpMessage.Properties.ContentType.Value))
                {
                    data.ContentType = amqpMessage.Properties.ContentType.Value;
                }

                if (!string.IsNullOrWhiteSpace(amqpMessage.Properties.ContentEncoding.Value))
                {
                    data.ContentEncoding = amqpMessage.Properties.ContentEncoding.Value;
                }
            }

            if ((sections & SectionFlag.MessageAnnotations) != 0)
            {
                string lockToken;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(LockTokenName, out lockToken))
                {
                    data.LockToken = lockToken;
                }

                ulong sequenceNumber;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(SequenceNumberName, out sequenceNumber))
                {
                    data.SequenceNumber = sequenceNumber;
                }

                DateTime enqueuedTime;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.EnqueuedTime, out enqueuedTime))
                {
                    data.EnqueuedTimeUtc = enqueuedTime;
                }

                byte deliveryCount;
                if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.DeliveryCount, out deliveryCount))
                {
                    data.DeliveryCount = deliveryCount;
                }
            }

            if ((sections & SectionFlag.ApplicationProperties) != 0)
            {
                foreach (KeyValuePair <MapKey, object> pair in amqpMessage.ApplicationProperties.Map)
                {
                    object netObject = null;
                    if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out netObject))
                    {
                        var stringObject = netObject as string;

                        if (stringObject != null)
                        {
                            switch (pair.Key.ToString())
                            {
                            case MessageSystemPropertyNames.Operation:
                                data.SystemProperties[pair.Key.ToString()] = stringObject;
                                break;

                            case MessageSystemPropertyNames.MessageSchema:
                                data.MessageSchema = stringObject;
                                break;

                            case MessageSystemPropertyNames.CreationTimeUtc:
                                data.CreationTimeUtc = DateTime.Parse(stringObject);
                                break;

                            default:
                                data.Properties[pair.Key.ToString()] = stringObject;
                                break;
                            }
                        }
                        else
                        {
                            // TODO: RDBug 4093369 Handling of non-string property values in Amqp messages
                            // Drop non-string properties and log an error
                            Fx.Exception.TraceHandled(new InvalidDataException("IotHub does not accept non-string Amqp properties"), "MessageConverter.UpdateMessageHeaderAndProperties");
                        }
                    }
                }
            }
        }
Exemple #8
0
 public static void Fork(this Task thisTask, string tracingInfo)
 {
     Fx.Assert(thisTask != null, "task is required!");
     thisTask.ContinueWith(t => Fx.Exception.TraceHandled(t.Exception, tracingInfo), TaskContinuationOptions.OnlyOnFaulted);
 }
Exemple #9
0
        public async Task <int> ReceiveAsync(byte[] buffer, int offset, int size, TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, timeout, $"{nameof(IotHubClientWebSocket)}.{nameof(ReceiveAsync)}");
            }

            byte[] header = new byte[2];

            Fx.AssertAndThrow(this.State == WebSocketState.Open, ClientWebSocketNotInOpenStateDuringReceive);
            this.TcpClient.ReceiveTimeout = TimeoutHelper.ToMilliseconds(timeout);

            bool succeeded = false;

            try
            {
                byte payloadLength;
                bool pongFrame;

                // TODO: rewrite this section to handle all control frames (including ping)
                int totalBytesRead;
                int bytesRead;
                do
                {
                    // Ignore pong frame and start over
                    totalBytesRead = 0;
                    do
                    {
                        bytesRead = await this.WebSocketStream.ReadAsync(header, totalBytesRead, header.Length - totalBytesRead).ConfigureAwait(false);

                        if (bytesRead == 0)
                        {
                            throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes"));
                        }

                        totalBytesRead += bytesRead;
                    }while (totalBytesRead < header.Length);

                    if (!ParseWebSocketFrameHeader(header, out payloadLength, out pongFrame))
                    {
                        // Encountered a close frame or error in parsing frame from server. Close connection
                        var closeHeader = PrepareWebSocketHeader(0, WebSocketMessageType.Close);

                        await this.WebSocketStream.WriteAsync(closeHeader, 0, closeHeader.Length).ConfigureAwait(false);

                        this.State = WebSocketState.Closed;
#if !NETSTANDARD1_3
                        this.WebSocketStream?.Close();
                        this.TcpClient?.Close();
#else
                        this.WebSocketStream?.Dispose();
                        this.TcpClient?.Dispose();
#endif
                        return(0);  // TODO: throw exception?
                    }

                    if (pongFrame && payloadLength > 0)
                    {
                        totalBytesRead = 0;
                        var tempBuffer = new byte[payloadLength];
                        while (totalBytesRead < payloadLength)
                        {
                            bytesRead = await this.WebSocketStream.ReadAsync(tempBuffer, totalBytesRead, payloadLength - totalBytesRead).ConfigureAwait(false);

                            if (bytesRead == 0)
                            {
                                throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes"));
                            }

                            totalBytesRead += bytesRead;
                        }
                    }
                }while (pongFrame);

                totalBytesRead = 0;

                if (buffer.Length < payloadLength)
                {
                    throw Fx.Exception.AsError(new InvalidOperationException(Resources.SizeExceedsRemainingBufferSpace));
                }

                if (payloadLength < MediumSizeFrame)
                {
                    while (totalBytesRead < payloadLength)
                    {
                        bytesRead = await this.WebSocketStream.ReadAsync(buffer, offset + totalBytesRead, payloadLength - totalBytesRead).ConfigureAwait(false);

                        if (bytesRead == 0)
                        {
                            throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes"));
                        }

                        totalBytesRead += bytesRead;
                    }
                }
                else
                {
                    switch (payloadLength)
                    {
                    case MediumSizeFrame:
                        // read payload length (< 64K)
                        do
                        {
                            bytesRead = await this.WebSocketStream.ReadAsync(header, totalBytesRead, header.Length - totalBytesRead).ConfigureAwait(false);

                            if (bytesRead == 0)
                            {
                                throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes"));
                            }

                            totalBytesRead += bytesRead;
                        }while (totalBytesRead < header.Length);

                        totalBytesRead = 0;
                        ushort extendedPayloadLength = (ushort)((header[0] << 8) | header[1]);

                        // read payload
                        if (buffer.Length >= extendedPayloadLength)
                        {
                            while (totalBytesRead < extendedPayloadLength)
                            {
                                bytesRead = await this.WebSocketStream.ReadAsync(buffer, offset + totalBytesRead, extendedPayloadLength - totalBytesRead).ConfigureAwait(false);

                                if (bytesRead == 0)
                                {
                                    throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes"));
                                }

                                totalBytesRead += bytesRead;
                            }
                        }
                        else
                        {
                            throw Fx.Exception.AsError(new InvalidOperationException(Resources.SizeExceedsRemainingBufferSpace));
                        }

                        break;

                    case LargeSizeFrame:
                        // read payload length (>= 64K)
                        var payloadLengthBuffer = new byte[8];
                        do
                        {
                            bytesRead = await this.WebSocketStream.ReadAsync(payloadLengthBuffer, totalBytesRead, payloadLengthBuffer.Length - totalBytesRead).ConfigureAwait(false);

                            if (bytesRead == 0)
                            {
                                throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes"));
                            }

                            totalBytesRead += bytesRead;
                        }while (totalBytesRead < payloadLengthBuffer.Length);

                        totalBytesRead = 0;

                        // ignore bytes 0-3 - length cannot be larger than a 32-bit number
                        uint superExtendedPayloadLength = (uint)((payloadLengthBuffer[4] << 24) | (payloadLengthBuffer[5] << 16) | (payloadLengthBuffer[6] << 8) | payloadLengthBuffer[7]);

                        // read payload
                        if (buffer.Length >= superExtendedPayloadLength)
                        {
                            while (totalBytesRead < superExtendedPayloadLength)
                            {
                                bytesRead = await this.WebSocketStream.ReadAsync(buffer, offset + totalBytesRead, (int)(superExtendedPayloadLength - totalBytesRead)).ConfigureAwait(false);

                                if (bytesRead == 0)
                                {
                                    throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes"));
                                }

                                totalBytesRead += bytesRead;
                            }
                        }
                        else
                        {
                            throw Fx.Exception.AsError(new InvalidOperationException(Resources.SizeExceedsRemainingBufferSpace));
                        }

                        break;
                    }
                }

                succeeded = true;
                return(totalBytesRead);
            }
            finally
            {
                if (!succeeded)
                {
                    this.Fault();
                }
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, timeout, $"{nameof(IotHubClientWebSocket)}.{nameof(ReceiveAsync)}");
                }
            }
        }
Exemple #10
0
 void SetDeadline()
 {
     Fx.Assert(!deadlineSet, "TimeoutHelper deadline set twice.");
     this.deadline    = DateTime.UtcNow + this.originalTimeout;
     this.deadlineSet = true;
 }
Exemple #11
0
 public static Exception AssertAndThrowFatal(string description)
 {
     Fx.Assert(description);
     throw Fx.Exception.AsError(new FatalException(description));
 }
Exemple #12
0
 public static Exception AssertAndThrow(string description)
 {
     Fx.Assert(description);
     throw Fx.Exception.AsError(new AssertionFailedException(description));
 }