コード例 #1
0
ファイル: Compression.cs プロジェクト: alex606/cis300
        /// <summary>
        /// Method to rebuild the Huffman tree
        /// </summary>
        /// <param name="BIS"></param>
        /// <param name="numNodes"></param>
        /// <returns></returns>
        private BinaryTreeNode <byte> ReadHuffManTree(BitInputStream BIS, int numNodes)
        {
            BinaryTreeNode <byte>[] nodeArray = new BinaryTreeNode <byte> [numNodes];
            int numBits = numNodes * 14 - 5;
            int counter = 0;

            while (counter != numNodes)
            {
                long k = ReadGivenBits(1, BIS);
                if (k == 0)
                {
                    long byteValue = ReadGivenBits(8, BIS);
                    BinaryTreeNode <byte> newLeafNode = new BinaryTreeNode <byte>((byte)byteValue, null, null);
                    nodeArray[counter] = newLeafNode;
                }
                else
                {
                    long leftChildIndex              = ReadGivenBits(9, BIS);
                    long rightChildIndex             = ReadGivenBits(9, BIS);
                    BinaryTreeNode <byte> newBinNode = new BinaryTreeNode <byte>(0, nodeArray[leftChildIndex], nodeArray[rightChildIndex]);
                    nodeArray[counter] = newBinNode;
                }
                counter++;
            }
            return(nodeArray[numNodes - 1]);
        }
コード例 #2
0
    public HZIPReader(Stream bin)
    {
        codeTree = new HuffmanTree( );
        codeTree.ReadEncodingTable(bin);

        bitstream = new BitInputStream(bin);
    }
コード例 #3
0
        public void BitStream_IntDelta_Random()
        {
            var buffer = new byte[1024 * 64];
            var output = new BitOutputStream(buffer);

            var  values   = new int[1024];
            var  random   = new Random(1032);
            long previous = 0;

            for (int i = 0; i < 1024; ++i)
            {
                values[i] = random.Next(int.MinValue, int.MaxValue);
                output.WriteIntDelta(values[i], previous);
                previous = values[i];
            }
            output.Flush();

            var input = new BitInputStream(buffer);

            previous = 0;
            for (int i = 0; i < 1024; ++i)
            {
                var value = input.ReadIntDelta(previous);
                Assert.AreEqual(values[i], value);
                previous = value;
            }
        }
コード例 #4
0
        public (string, HuffmanTree) CondenseToTree(string w)
        {
            var tree = HuffmanTree.AssembleTree(CharCountDeterminer.GetAllFromString(w));

            var b         = new BitInputStream();
            var charArray = w.ToCharArray();

            var first = charArray[0];

            b.AddFromStringSource(tree[first]);

            for (var i = 1; i < charArray.Length; i++)
            {
                var current = charArray[i];

                var relPath = tree[current];
                b.AddFromStringSource(relPath);
            }

            var output = new StringBuilder();

            b.Flush();
            output.Append(b.ToChars());

            return(output.ToString(), tree);
        }
コード例 #5
0
        public (string, HuffmanChain) Condense(string w)
        {
            var chain = new HuffmanChain(w);

            if (w.Length == 0)
            {
                return("", chain);
            }


            var b         = new BitInputStream();
            var charArray = w.ToCharArray();

            char first = charArray[0], pre = first;

            b.AddFromStringSource(chain[first]);

            for (var i = 1; i < charArray.Length; i++)
            {
                var current = charArray[i];

                var relPath = chain[current, pre];
                b.AddFromStringSource(relPath);

                pre = current;
            }

            var output = new StringBuilder();

            b.Flush();
            output.Append(b.ToChars());

            return(output.ToString(), chain);
        }
コード例 #6
0
ファイル: Compression.cs プロジェクト: alex606/cis300
        // Decompression part------------------------------------------------------------------

        /// <summary>
        /// Read the given number of bits
        /// </summary>
        /// <param name="numBits"></param>
        /// <param name="BIS"></param>
        /// <returns></returns>
        private long ReadGivenBits(int numBits, BitInputStream BIS)
        {
            int  bitsRead = 0;
            long check    = BIS.ReadBits(numBits, out bitsRead);

            if (numBits != bitsRead)
            {
                throw new IOException();
            }
            return(check);
        }
コード例 #7
0
ファイル: Compression.cs プロジェクト: alex606/cis300
 /// <summary>
 /// Method to Decompress the file
 /// </summary>
 /// <param name="BIS"></param>
 /// <param name="fn"></param>
 /// <param name="numbytes"></param>
 /// <param name="HuffTree"></param>
 private void DecompressFile(BitInputStream BIS, string fn, long numbytes, BinaryTreeNode <byte> HuffTree)
 {
     using (FileStream fs = new FileStream(fn, FileMode.Create, FileAccess.Write))
     {
         int counter = 0;
         while (counter != numbytes)
         {
             byte DataToWrite = ReadCompressedByte(BIS, HuffTree);
             fs.WriteByte(DataToWrite);
             counter++;
         }
     }
 }
コード例 #8
0
    public void CopyByteArray(ref BitInputStream input)
    {
        var count = (int)input.ReadUIntPacked();

        WriteUIntPacked((uint)count);
        if (count > 0)
        {
            Align();
            input.Align();
            input.ReadBytes(m_Buffer, m_CurrentByteIdx, count);
            m_CurrentByteIdx += count;
        }
    }
コード例 #9
0
ファイル: Compression.cs プロジェクト: alex606/cis300
 /// <summary>
 /// Read to get the values for each huffman leave
 /// </summary>
 /// <param name="BIS"></param>
 /// <param name="huffTree"></param>
 /// <returns></returns>
 private byte ReadCompressedByte(BitInputStream BIS, BinaryTreeNode <byte> huffTree)
 {
     while (true)
     {
         if (huffTree.LeftChild == null && huffTree.RightChild == null)
         {
             return(huffTree.Data);
         }
         if (ReadGivenBits(1, BIS) == 0)
         {
             huffTree = huffTree.LeftChild;
         }
         else
         {
             huffTree = huffTree.RightChild;
         }
     }
 }
コード例 #10
0
        public ArithmeticDecoder(BitInputStream inputStream)
        {
            const long fullRange = 1L << 32;

            _halfRange    = fullRange >> 1;
            _quarterRange = _halfRange >> 1;
            _stateMask    = fullRange - 1;

            _low  = 0;
            _high = _stateMask;

            Input = inputStream;
            _code = 0;
            for (var i = 0; i < 32; i++)
            {
                _code = _code << 1 | ReadCodeBit();
            }
        }
コード例 #11
0
        public void BitStream_AlignAndByteArray()
        {
            var random = new Random(1293);

            var numbers = new int[1024];

            var payload        = new byte[32];
            var payloadCompare = new byte[32];

            random.NextBytes(payload);

            var buffer = new byte[1024 * 1024];

            for (int runs = 0; runs < 1; ++runs)
            {
                for (int i = 0; i < 1024; ++i)
                {
                    numbers[i] = random.Next(1, 33);
                }

                var output = new BitOutputStream(buffer);
                for (int i = 0; i < 1024; ++i)
                {
                    output.WriteBits((uint)numbers[i], numbers[i]);
                    if (i % 3 == 0)
                    {
                        output.WriteBytes(payload, 0, numbers[i]);
                    }
                }

                var input = new BitInputStream(buffer);
                for (int i = 0; i < 1024; ++i)
                {
                    var value = input.ReadBits(numbers[i]);
                    Assert.AreEqual((uint)numbers[i], value);
                    if (i % 3 == 0)
                    {
                        input.ReadBytes(payloadCompare, 0, numbers[i]);
                        Assert.AreEqual(0, NetworkUtils.MemCmp(payload, 0, payloadCompare, 0, numbers[i]));
                    }
                }
            }
        }
コード例 #12
0
        public static float[] getCompressedFloatsArray(byte[] data, float precision)
        {
            if (data == null || data.Length == 0)
            {
                return(new float[0]);
            }

            BitInputStream bitInputStream = new BitInputStream(data);
            int            min            = bitInputStream.ReadBits(24) - MIDDLE_VALUE;
            int            bitsSize       = bitInputStream.ReadBits(8);
            int            size           = bitInputStream.ReadBits(24);

            float[] values = new float[size];
            for (int i = 0; i < values.Length; i++)
            {
                int read = bitInputStream.ReadBits(bitsSize);
                values[i] = (min + read) * precision;
            }

            return(values);
        }
コード例 #13
0
        public void BitStream_UIntPacked_RandomUInt()
        {
            var buffer = new byte[1024 * 64];
            var output = new BitOutputStream(buffer);

            var values = new uint[1024];
            var random = new Random(1032);

            for (int i = 0; i < 1024; ++i)
            {
                values[i] = (uint)random.Next(int.MaxValue);
                output.WriteUIntPacked(values[i]);
            }
            output.Flush();

            var input = new BitInputStream(buffer);

            for (int i = 0; i < 1024; ++i)
            {
                var value = input.ReadUIntPacked();
                Assert.AreEqual(values[i], value);
            }
        }
コード例 #14
0
ファイル: Compression.cs プロジェクト: alex606/cis300
        /// <summary>
        ///  Event Handler for Decompression Button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void uxDecompressButton_Click(object sender, EventArgs e)
        {
            try
            {
                if (uxOpenFileDialog2.ShowDialog() == DialogResult.OK)
                {
                    string OpenFile = uxOpenFileDialog2.FileName;
                    using (BitInputStream BIS = new BitInputStream(OpenFile))
                    {
                        long first63Bits = ReadGivenBits(63, BIS);
                        long next9Bits   = ReadGivenBits(9, BIS);
                        BinaryTreeNode <byte> huffTree;

                        // If file length is 0, use a null HuffMan Tree
                        if (first63Bits == 0)
                        {
                            huffTree = null;
                        }
                        else
                        {
                            huffTree = ReadHuffManTree(BIS, (int)next9Bits);
                        }

                        if (uxSaveFileDialog2.ShowDialog() == DialogResult.OK)
                        {
                            string SaveFile = uxSaveFileDialog2.FileName;
                            DecompressFile(BIS, SaveFile, first63Bits, huffTree);
                            MessageBox.Show("Decompressed File Written");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
コード例 #15
0
        public void BitStream_Align()
        {
            var random = new Random(1293);

            var numbers = new int[1024];
            var buffer  = new byte[1024 * 64];

            for (int runs = 0; runs < 1000; ++runs)
            {
                for (int i = 0; i < 1024; ++i)
                {
                    numbers[i] = random.Next(1, 33);
                }

                var output = new BitOutputStream(buffer);
                for (int i = 0; i < 1024; ++i)
                {
                    output.WriteBits((uint)numbers[i], numbers[i]);
                    if (i % 3 == 0)
                    {
                        output.Align();
                    }
                }

                var input = new BitInputStream(buffer);
                for (int i = 0; i < 1024; ++i)
                {
                    var value = input.ReadBits(numbers[i]);
                    Assert.AreEqual((uint)numbers[i], value);
                    if (i % 3 == 0)
                    {
                        input.Align();
                    }
                }
            }
        }
コード例 #16
0
    public int ProcessPackageHeader(byte[] packageData, out NetworkMessage content, out int headerSize)
    {
        counters.packagesIn++;

        var input = new BitInputStream(packageData);

        headerSize = 0;
        int headerStartInBits = input.GetBitPosition();

        content = (NetworkMessage)input.ReadBits(8);

        var inSequenceNew         = Sequence.FromUInt16((ushort)input.ReadBits(16), inSequence);
        var outSequenceAckNew     = Sequence.FromUInt16((ushort)input.ReadBits(16), outSequenceAck);
        var outSequenceAckMaskNew = (ushort)input.ReadBits(16);

        if (inSequenceNew > inSequence)
        {
            // If we have a hole in the package sequence that will fall off the ack mask that
            // means the package (inSequenceNew-15 and before) will be considered lost (either it will never come or we will
            // reject it as being stale if we get it at a later point in time)
            var distance = inSequenceNew - inSequence;
            for (var i = 0; i < Math.Min(distance, 15); ++i)    // TODO : Fix this contant
            {
                if ((inSequenceAckMask & 1 << (15 - i)) == 0)
                {
                    counters.packagesLostIn++;
                }
            }

            // If there is a really big hole then those packages are considered lost as well
            // Update the incoming ack mask.
            if (distance > 15)
            {
                counters.packagesLostIn += distance - 15;
                inSequenceAckMask        = 1; // all is lost except current package
            }
            else
            {
                inSequenceAckMask <<= distance;
                inSequenceAckMask  |= 1;
            }

            inSequence     = inSequenceNew;
            inSequenceTime = NetworkUtils.stopwatch.ElapsedMilliseconds;
        }
        else if (inSequenceNew < inSequence)
        {
            // Package is out of order

            // Check if the package is stale
            var distance = inSequence - inSequenceNew;
            if (distance > 15) // TODO : Fix this constant
            {
                counters.packagesStaleIn++;
                return(0);
            }

            // Check if the package is a duplicate
            var ackBit = 1 << distance;
            if ((ackBit & inSequenceAckMask) != 0)
            {
                // Duplicate package
                counters.packagesDuplicateIn++;
                return(0);
            }

            // Accept the package out of order
            //counters.packagesOutOfOrderIn++;
            inSequenceAckMask |= (ushort)ackBit;
        }
        else
        {
            // Duplicate package
            counters.packagesDuplicateIn++;
            return(0);
        }

        if (inSequenceNew % 3 == 0)
        {
            var          timeOnServer = (ushort)input.ReadBits(8);
            TPackageInfo info;
            if (outstandingPackages.TryGetValue(outSequenceAckNew, out info))
            {
                var now = NetworkUtils.stopwatch.ElapsedMilliseconds;
                rtt = (int)(now - info.SentTime - timeOnServer);
            }
        }

        // If the ack sequence is not higher we have nothing new to do
        if (outSequenceAckNew <= outSequenceAck)
        {
            headerSize = input.Align();
            return(inSequenceNew);
        }

        // Find the sequence numbers that we have to consider lost
        var seqsBeforeThisAlreadyNotifedAsLost = outSequenceAck - 15;
        var seqsBeforeThisAreLost = outSequenceAckNew - 15;

        for (int sequence = seqsBeforeThisAlreadyNotifedAsLost; sequence <= seqsBeforeThisAreLost; ++sequence)
        {
            // Handle conditions before first 15 packets
            if (sequence < 0)
            {
                continue;
            }

            // If seqence covered by old ack mask, we may already have received it (and notified)
            int bitnum      = outSequenceAck - sequence;
            var ackBit      = bitnum >= 0 ? 1 << bitnum : 0;
            var notNotified = (ackBit & outSequenceAckMask) == 0;

            if (outstandingPackages.Exists(sequence) && notNotified)
            {
                var info = outstandingPackages[sequence];
                NotifyDelivered(sequence, info, false);

                counters.packagesLostOut++;

                info.Reset();
                outstandingPackages.Remove(sequence);
            }
        }

        outSequenceAck     = outSequenceAckNew;
        outSequenceAckMask = outSequenceAckMaskNew;

        // Ack packages if they haven't been acked already
        for (var sequence = Math.Max(outSequenceAck - 15, 0); sequence <= outSequenceAck; ++sequence)
        {
            var ackBit = 1 << outSequenceAck - sequence;
            if (outstandingPackages.Exists(sequence) && (ackBit & outSequenceAckMask) != 0)
            {
                var info = outstandingPackages[sequence];
                NotifyDelivered(sequence, info, true);

                info.Reset();
                outstandingPackages.Remove(sequence);
            }
        }

        headerSize = input.Align();
        return(inSequenceNew);
    }
コード例 #17
0
ファイル: UserInterface.cs プロジェクト: jdeloach/CIS300
        /// <summary>
        /// General method which takes an Input and Output file and rebuilds a Huffman trees and takes the compressed data and uses the Huffman tree to decompress it.
        /// </summary>
        /// <param name="inputStream">Compressed file stream to decompress</param>
        /// <param name="outputStream">Uncompressed file stream to write decompressed bytes to</param>
        private void DecompressStream(BitInputStream inputStream, FileStream outputStream)
        {
            long numBytes = ReadBits(inputStream, 63);
            long numNodes = ReadBits(inputStream, 9);

            if (numBytes > 0 && numNodes == 0)
                throw new IOException(_errorMessage);

            BinaryTreeNode<byte> huffTree = RecontstructHuffmanTree(inputStream, numNodes);
            for (int i = 0; i < numBytes; i++)
                WriteDecompressedByte(inputStream, outputStream, huffTree);
        }
コード例 #18
0
ファイル: UserInterface.cs プロジェクト: jdeloach/CIS300
        /// <summary>
        /// Reads Bits from given BitInputStream
        /// </summary>
        /// <param name="inputStream">Stream to read from</param>
        /// <param name="numberToRead">Number of bits to read from the stream.</param>
        /// <returns>A long of the bits in the stream.</returns>
        private long ReadBits(BitInputStream inputStream, int numberToRead)
        {
            int numRead = 0;
            long results = inputStream.ReadBits(numberToRead, out numRead);

            if (numRead == 0)
                throw new IOException(_errorMessage);
            else
                return results;
        }
コード例 #19
0
ファイル: Compression.cs プロジェクト: alex606/cis300
        /// <summary>
        ///  Event Handler for Decompression Button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void uxDecompressButton_Click(object sender, EventArgs e)
        {
            try
            {
                if(uxOpenFileDialog2.ShowDialog() == DialogResult.OK)
                {
                    string OpenFile = uxOpenFileDialog2.FileName;
                    using (BitInputStream BIS = new BitInputStream(OpenFile))
                    {
                        long first63Bits = ReadGivenBits(63, BIS);
                        long next9Bits = ReadGivenBits(9, BIS);
                        BinaryTreeNode<byte> huffTree;

                        // If file length is 0, use a null HuffMan Tree
                        if (first63Bits == 0)
                        {
                            huffTree = null;
                        }
                        else
                        {
                            huffTree = ReadHuffManTree(BIS, (int)next9Bits);
                        }

                        if (uxSaveFileDialog2.ShowDialog() == DialogResult.OK)
                        {
                            string SaveFile = uxSaveFileDialog2.FileName;
                            DecompressFile(BIS, SaveFile, first63Bits, huffTree);
                            MessageBox.Show("Decompressed File Written");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
コード例 #20
0
ファイル: Compression.cs プロジェクト: alex606/cis300
        /// <summary>
        /// Method to rebuild the Huffman tree
        /// </summary>
        /// <param name="BIS"></param>
        /// <param name="numNodes"></param>
        /// <returns></returns>
        private BinaryTreeNode<byte> ReadHuffManTree(BitInputStream BIS, int numNodes)
        {
            BinaryTreeNode<byte>[] nodeArray = new BinaryTreeNode<byte>[numNodes];
            int numBits = numNodes * 14 - 5;
            int counter = 0;

            while(counter != numNodes)
            {
                long k = ReadGivenBits(1, BIS);
                if (k == 0)
                {
                    long byteValue = ReadGivenBits(8, BIS);
                    BinaryTreeNode<byte> newLeafNode = new BinaryTreeNode<byte>((byte)byteValue, null, null);
                    nodeArray[counter] = newLeafNode;
                }
                else
                {
                    long leftChildIndex = ReadGivenBits(9, BIS);
                    long rightChildIndex = ReadGivenBits(9, BIS);
                    BinaryTreeNode<byte> newBinNode = new BinaryTreeNode<byte>(0,nodeArray[leftChildIndex], nodeArray[rightChildIndex]);
                    nodeArray[counter] = newBinNode;
                }
                counter++;
            }
            return nodeArray[numNodes - 1];
        }
コード例 #21
0
ファイル: Compression.cs プロジェクト: alex606/cis300
 // Decompression part------------------------------------------------------------------
 /// <summary>
 /// Read the given number of bits
 /// </summary>
 /// <param name="numBits"></param>
 /// <param name="BIS"></param>
 /// <returns></returns>
 private long ReadGivenBits(int numBits, BitInputStream BIS)
 {
     int bitsRead = 0;
     long check = BIS.ReadBits(numBits, out bitsRead);
     if(numBits != bitsRead)
     {
         throw new IOException();
     }
     return check;
 }
コード例 #22
0
ファイル: Compression.cs プロジェクト: alex606/cis300
 /// <summary>
 /// Read to get the values for each huffman leave
 /// </summary>
 /// <param name="BIS"></param>
 /// <param name="huffTree"></param>
 /// <returns></returns>
 private byte ReadCompressedByte(BitInputStream BIS, BinaryTreeNode<byte> huffTree)
 {
     while(true)
     {
         if (huffTree.LeftChild == null && huffTree.RightChild == null)
         {
             return huffTree.Data;
         }
         if(ReadGivenBits(1,BIS) == 0)
         {
             huffTree = huffTree.LeftChild;
         }
         else
         {
             huffTree = huffTree.RightChild;
         }
     }
 }
コード例 #23
0
ファイル: Compression.cs プロジェクト: alex606/cis300
 /// <summary>
 /// Method to Decompress the file
 /// </summary>
 /// <param name="BIS"></param>
 /// <param name="fn"></param>
 /// <param name="numbytes"></param>
 /// <param name="HuffTree"></param>
 private void DecompressFile(BitInputStream BIS, string fn, long numbytes, BinaryTreeNode<byte> HuffTree)
 {
     using (FileStream fs = new FileStream(fn, FileMode.Create, FileAccess.Write))
     {
         int counter = 0;
         while(counter != numbytes)
         {
             byte DataToWrite = ReadCompressedByte(BIS, HuffTree);
             fs.WriteByte(DataToWrite);
             counter++;
         }
     }
 }
コード例 #24
0
ファイル: UserInterface.cs プロジェクト: jdeloach/CIS300
        /// <summary>
        /// Reconstructs a Huffman tree from BitInputStreams
        /// </summary>
        /// <param name="inputStream">InputStream to read bits from to construct tree from.</param>
        /// <param name="numberOfNodes">Number of nodes to construct in tree.</param>
        /// <returns>A fully generated Huffman Tree</returns>
        private BinaryTreeNode<byte> RecontstructHuffmanTree(BitInputStream inputStream, long numberOfNodes)
        {
            BinaryTreeNode<byte>[] nodes = new BinaryTreeNode<byte>[numberOfNodes];
            int index = 0;

            foreach(BinaryTreeNode<byte> node in nodes)
            {
                if (ReadBits(inputStream, 1) == 1)
                {
                    BinaryTreeNode<byte> tmp = new BinaryTreeNode<byte>();
                    tmp.IsEmpty = false;
                    tmp.RootValue = (byte)ReadBits(inputStream, 8);
                    nodes[index] = tmp;
                    index++;
                }
                else
                {
                    BinaryTreeNode<byte> tmp = new BinaryTreeNode<byte>();
                     tmp.IsEmpty = false;

                    tmp.LeftChild = RetrieveHuffmanTree(inputStream, nodes, index);
                    tmp.RightChild = RetrieveHuffmanTree(inputStream, nodes, index);

                    nodes[index] = tmp;
                    index++;
                }
            }

            return nodes[index - 1];
        }
コード例 #25
0
 public void Initialize(byte[] buffer)
 {
     this = new BitInputStream(buffer);
 }
コード例 #26
0
    // Returns the 'wide' packageSequenceNumber (i.e. 32 bit reconstructed from the 16bits sent over wire)
    protected int ProcessPackageHeader(byte[] packageData, int packageSize, out NetworkMessage content, out byte[] assembledData, out int assembledSize, out int headerSize)
    {
        counters.packagesIn++;
        assembledData = packageData;
        assembledSize = packageSize;
        headerSize    = 0;
        var input = new BitInputStream(packageData);

        int headerStartInBits = input.GetBitPosition();

        content = (NetworkMessage)input.ReadBits(8);

        // TODO: Possible improvement is to ack on individual fragments not just entire message
        if ((content & NetworkMessage.FRAGMENT) != 0)
        {
            // Package fragment
            var fragmentPackageSequence = Sequence.FromUInt16((ushort)input.ReadBits(16), inSequence);
            var numFragments            = (int)input.ReadBits(8);
            var fragmentIndex           = (int)input.ReadBits(8);
            var fragmentSize            = (int)input.ReadBits(16);

            FragmentReassemblyInfo assembly;
            if (!m_FragmentReassembly.TryGetValue(fragmentPackageSequence, out assembly))
            {
                // If we run out of room in the reassembly buffer we will not be able to reassemble this package
                if (!m_FragmentReassembly.Available(fragmentPackageSequence))
                {
                    counters.fragmentedPackagesLostIn++;
                }

                GameDebug.Assert(numFragments <= NetworkConfig.maxFragments);

                assembly = m_FragmentReassembly.Acquire(fragmentPackageSequence);
                assembly.numFragments  = numFragments;
                assembly.receivedMask  = 0;
                assembly.receivedCount = 0;
            }

            GameDebug.Assert(assembly.numFragments == numFragments);
            GameDebug.Assert(fragmentIndex < assembly.numFragments);
            counters.headerBitsIn += input.GetBitPosition() - headerStartInBits;

            if ((assembly.receivedMask & (1U << fragmentIndex)) != 0)
            {
                // Duplicate package fragment
                counters.packagesDuplicateIn++;
                return(0);
            }

            assembly.receivedMask |= 1U << fragmentIndex;
            assembly.receivedCount++;

            input.ReadBytes(assembly.data, fragmentIndex * NetworkConfig.packageFragmentSize, fragmentSize);

            if (assembly.receivedCount < assembly.numFragments)
            {
                return(0);   // Not fully assembled
            }

            // Continue processing package as we have now reassembled the package
            assembledData = assembly.data;
            assembledSize = fragmentIndex * NetworkConfig.packageFragmentSize + fragmentSize;
            input.Initialize(assembledData);
            headerStartInBits = 0;
            content           = (NetworkMessage)input.ReadBits(8);
        }

        var inSequenceNew         = Sequence.FromUInt16((ushort)input.ReadBits(16), inSequence);
        var outSequenceAckNew     = Sequence.FromUInt16((ushort)input.ReadBits(16), outSequenceAck);
        var outSequenceAckMaskNew = (ushort)input.ReadBits(16);

        if (inSequenceNew > inSequence)
        {
            // If we have a hole in the package sequence that will fall off the ack mask that
            // means the package (inSequenceNew-15 and before) will be considered lost (either it will never come or we will
            // reject it as being stale if we get it at a later point in time)
            var distance = inSequenceNew - inSequence;
            for (var i = 0; i < Math.Min(distance, 15); ++i)    // TODO : Fix this contant
            {
                if ((inSequenceAckMask & 1 << (15 - i)) == 0)
                {
                    counters.packagesLostIn++;
                }
            }

            // If there is a really big hole then those packages are considered lost as well

            // Update the incoming ack mask.
            if (distance > 15)
            {
                counters.packagesLostIn += distance - 15;
                inSequenceAckMask        = 1; // all is lost except current package
            }
            else
            {
                inSequenceAckMask <<= distance;
                inSequenceAckMask  |= 1;
            }

            inSequence     = inSequenceNew;
            inSequenceTime = NetworkUtils.stopwatch.ElapsedMilliseconds;
        }
        else if (inSequenceNew < inSequence)
        {
            // Package is out of order

            // Check if the package is stale
            // NOTE : We rely on the fact that we will reject packages that we cannot ack due to the size
            // of the ack mask, so we don't have to worry about resending messages as long as we do that
            // after the original package has fallen off the ack mask.
            var distance = inSequence - inSequenceNew;
            if (distance > 15) // TODO : Fix this constant
            {
                counters.packagesStaleIn++;
                return(0);
            }

            // Check if the package is a duplicate
            var ackBit = 1 << distance;
            if ((ackBit & inSequenceAckMask) != 0)
            {
                // Duplicate package
                counters.packagesDuplicateIn++;
                return(0);
            }

            // Accept the package out of order
            counters.packagesOutOfOrderIn++;
            inSequenceAckMask |= (ushort)ackBit;
        }
        else
        {
            // Duplicate package
            counters.packagesDuplicateIn++;
            return(0);
        }

        if (inSequenceNew % 3 == 0)
        {
            var          timeOnServer = (ushort)input.ReadBits(8);
            TPackageInfo info;
            if (outstandingPackages.TryGetValue(outSequenceAckNew, out info))
            {
                var now = NetworkUtils.stopwatch.ElapsedMilliseconds;
                rtt = (int)(now - info.sentTime - timeOnServer);
            }
        }

        // If the ack sequence is not higher we have nothing new to do
        if (outSequenceAckNew <= outSequenceAck)
        {
            headerSize = input.Align();
            return(inSequenceNew);
        }

        // Find the sequence numbers that we have to consider lost
        var seqsBeforeThisAlreadyNotifedAsLost = outSequenceAck - 15;
        var seqsBeforeThisAreLost = outSequenceAckNew - 15;

        for (int sequence = seqsBeforeThisAlreadyNotifedAsLost; sequence <= seqsBeforeThisAreLost; ++sequence)
        {
            // Handle conditions before first 15 packets
            if (sequence < 0)
            {
                continue;
            }

            // If seqence covered by old ack mask, we may already have received it (and notified)
            int bitnum      = outSequenceAck - sequence;
            var ackBit      = bitnum >= 0 ? 1 << bitnum : 0;
            var notNotified = (ackBit & outSequenceAckMask) == 0;

            if (outstandingPackages.Exists(sequence) && notNotified)
            {
                var info = outstandingPackages[sequence];
                NotifyDelivered(sequence, info, false);

                counters.packagesLostOut++;
                if (info.fragmented)
                {
                    counters.fragmentedPackagesLostOut++;
                }

                info.Reset();
                outstandingPackages.Remove(sequence);
            }
        }

        outSequenceAck     = outSequenceAckNew;
        outSequenceAckMask = outSequenceAckMaskNew;

        // Ack packages if they haven't been acked already
        for (var sequence = Math.Max(outSequenceAck - 15, 0); sequence <= outSequenceAck; ++sequence)
        {
            var ackBit = 1 << outSequenceAck - sequence;
            if (outstandingPackages.Exists(sequence) && (ackBit & outSequenceAckMask) != 0)
            {
                var info = outstandingPackages[sequence];
                NotifyDelivered(sequence, info, true);

                info.Reset();
                outstandingPackages.Remove(sequence);
            }
        }

        counters.headerBitsIn += input.GetBitPosition() - headerStartInBits;

        headerSize = input.Align();
        return(inSequenceNew);
    }
コード例 #27
0
ファイル: UserInterface.cs プロジェクト: jdeloach/CIS300
        /// <summary>
        /// Retrieves a specific Huffman tree from the array of them.
        /// </summary>
        /// <param name="inputStream">Stream to read bits from</param>
        /// <param name="huffTrees">Array of Huffman trees to choose from</param>
        /// <param name="numberOfTrees">Number of filled trees in the array</param>
        /// <returns>Returns the Huffman tree that is needed that is requested in the BitStream.</returns>
        private BinaryTreeNode<byte> RetrieveHuffmanTree(BitInputStream inputStream, BinaryTreeNode<byte>[] huffTrees, int numberOfTrees)
        {
            int bitsRead = 0;
            int spot = (int)inputStream.ReadBits(9, out bitsRead);

            if (bitsRead < 9)
                throw new IOException(_errorMessage);

            return huffTrees[spot];
        }
コード例 #28
0
ファイル: UserInterface.cs プロジェクト: jdeloach/CIS300
 /// <summary>
 /// Handles a decompress button click.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void uxDecompress_Click(object sender, EventArgs e)
 {
     if (uxOpenFileDialog.ShowDialog() == DialogResult.OK)
     {
         if (uxSaveFileDialog.ShowDialog() == DialogResult.OK)
         {
             try
             {
                 using (BitInputStream input = new BitInputStream(uxOpenFileDialog.FileName))
                 {
                     using (FileStream output = File.OpenWrite(uxSaveFileDialog.FileName))
                     {
                         DecompressStream(input, output);
                     }
                 }
             }
             catch (Exception ex)
             {
                 DisplayError(ex);
             }
         }
     }
 }
コード例 #29
0
ファイル: UserInterface.cs プロジェクト: jdeloach/CIS300
 /// <summary>
 /// Decompressses and writes the current byte in the inputStream to the outputstream.
 /// </summary>
 /// <param name="inputStream">File of compressed data to decompress.</param>
 /// <param name="outputStream">File to write uncompressed data to.</param>
 /// <param name="huffTree">Huffman tree used to decode with</param>
 private void WriteDecompressedByte(BitInputStream inputStream, FileStream outputStream, BinaryTreeNode<byte> huffTree)
 {
     while (huffTree.LeftChild != null || huffTree.RightChild != null)
     {
         if (ReadBits(inputStream, 1) == 0)
             huffTree = huffTree.LeftChild;
         else
             huffTree = huffTree.RightChild;
     }
     outputStream.WriteByte(huffTree.RootValue);
 }