Example #1
0
        protected override void ExecuteOperation()
        {
            Debug.Assert(ItemCompletionRegister[Index] == false);

            PayloadItem item           = PayloadItems[Index];
            Guid        itemIdentifier = item.Identifier;

            bool skip = ItemSkipRegister != null && ItemSkipRegister.Contains(itemIdentifier);

            MuxItemResourceContainer itemContainer;
            bool activeResource = _activeItemResources.ContainsKey(itemIdentifier);

            if (activeResource)
            {
                itemContainer = _activeItemResources[itemIdentifier];
            }
            else
            {
                if (skip == false)
                {
                    itemContainer = CreateEtMSchemeResources(item);
                    if (Writing)
                    {
                        EmitHeader(itemContainer.Authenticator);
                    }
                    else
                    {
                        ConsumeHeader(itemContainer.Authenticator);
                    }
                }
                else
                {
                    itemContainer = new MuxItemResourceContainer(null, null, null);
                }
                _activeItemResources.Add(itemIdentifier, itemContainer);
            }

            int opLength = NextOperationLength();

            if (skip == false)
            {
                CipherStream itemEncryptor     = itemContainer.Encryptor;
                MacStream    itemAuthenticator = itemContainer.Authenticator;

                if (Writing)
                {
                    // Writing/multiplexing
                    if (itemEncryptor.BytesIn + opLength < item.ExternalLength)
                    {
                        // Normal operation
                        itemEncryptor.WriteExactly(item.StreamBinding, opLength);
                    }
                    else
                    {
                        // Final operation, or just prior to
                        if (itemContainer.Buffer.IsValueCreated == false)
                        {
                            // Redirect final ciphertext to buffer to account for possible expansion
                            itemAuthenticator.ReassignBinding(itemContainer.Buffer.Value, false, finish: false);
                        }
                        var remaining = (int)(item.ExternalLength - itemEncryptor.BytesIn);
                        if (remaining > 0)
                        {
                            while (remaining > 0)
                            {
                                int toRead = Math.Min(remaining, BufferSize);
                                int iterIn = item.StreamBinding.Read(Buffer, 0, toRead);
                                if (iterIn < toRead)
                                {
                                    throw new EndOfStreamException();
                                }
                                itemEncryptor.Write(Buffer, 0, iterIn); // Writing into recently-lazy-inited buffer
                                remaining -= iterIn;
                            }
                            itemEncryptor.Close();
                        }
                        var toWrite = (int)Math.Min(opLength, itemContainer.Buffer.Value.Length);
                        Debug.Print(DebugUtility.CreateReportString("FabricPayloadMux", "ExecuteOperation",
                                                                    "Multiplexing item: final stripe length", toWrite));

                        itemContainer.Buffer.Value.ReadTo(PayloadStream, toWrite);
                    }
                }
                else
                {
                    // Reading/demultiplexing
                    long readRemaining = item.InternalLength - itemEncryptor.BytesIn;
                    bool finalOp       = false;
                    if (readRemaining <= opLength)
                    {
                        // Final operation
                        opLength = (int)readRemaining;
                        finalOp  = true;
                        Debug.Print(DebugUtility.CreateReportString("FabricPayloadMux", "ExecuteOperation",
                                                                    "Demultiplexing item: final stripe length", opLength));
                    }
                    itemEncryptor.ReadExactly(item.StreamBinding, opLength, finalOp);
                }

                if ((Writing && itemEncryptor.BytesIn >= item.ExternalLength && itemContainer.Buffer.Value.Length == 0) ||
                    (Writing == false && itemEncryptor.BytesIn >= item.InternalLength))
                {
                    // Now that we're finished we need to do some extra things, then clean up
                    FinishItem(item, itemEncryptor, itemAuthenticator);
                }
            }
            else
            {
                // Skipping
                Debug.Assert(Writing == false, "Should not be skipping when writing!");

                if (itemContainer.SkippedLength == 0)
                {
                    // Start of item
                    PayloadStream.Seek(opLength, SeekOrigin.Current);
                    itemContainer.SkippedLength += opLength;
                }
                else if (itemContainer.SkippedLength + opLength >= item.InternalLength)
                {
                    int remainingToSkip = (int)(item.InternalLength - itemContainer.SkippedLength);
                    itemContainer.SkippedLength += remainingToSkip;
                    PayloadStream.Seek(remainingToSkip + GetTrailerLength(), SeekOrigin.Current);
                    // "Finish" item
                    _activeItemResources.Remove(item.Identifier);
                    // Mark the item as completed in the register
                    ItemCompletionRegister[Index] = true;
                    ItemsCompleted++;
                    Debug.Print(DebugUtility.CreateReportString("FabricPayloadMux", "ExecuteOperation", "[*** SKIPPED ITEM",
                                                                Index + " ***]"));
                }
                else
                {
                    PayloadStream.Seek(opLength, SeekOrigin.Current);
                    itemContainer.SkippedLength += opLength;
                }
            }
        }