예제 #1
0
        /// <inheritdoc/>
        public byte ReadByte(long index)
        {
            byte ret;

            if (!cache.TryReadByte(index, out ret))
            {
                ByteCache.FillCache callback = delegate(byte[] buffer, out long cacheStart, out int cacheLength)
                {
                    // the file is more likely to be read from the beginning to the end
                    cacheStart  = Math.Max(0, index - 512);
                    cacheLength = (int)Math.Min(buffer.Length, stream.Length - cacheStart);
                    try
                    {
                        stream.ReadBytesToBuffer(buffer, cacheStart, cacheLength);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    ret = buffer[index - cacheStart];
                };
                cache.Cache(callback);
            }
            return(ret);
        }
예제 #2
0
 public void ReadBytesToBuffer(byte[] buffer, long start = 0, int length = -1, int offset = 0)
 {
     IDataStreamHelpers.ReadBytesToBufferArgsCheck(this, buffer, start, ref length, offset);
     while (length > 0)
     {
         var off = start % fullChunkSize;
         int read;
         if (off < chunkStart.Length)
         {
             read = (int)Math.Min(length, chunkStart.Length - off);
             chunkStart.ReadBytesToBuffer(buffer, off, read, offset);
         }
         else if (off > fullChunkSize - 3)
         {
             read = (int)Math.Min(length, fullChunkSize - off);
             chunkEnd.ReadBytesToBuffer(buffer, off - (fullChunkSize - 2), read, offset);
         }
         else
         {
             var chunk = start / fullChunkSize;
             off -= chunkStart.Length;
             read = (int)Math.Min(length, chunkSize - off);
             innerStream.ReadBytesToBuffer(buffer, chunk * chunkSize + off, read, offset);
         }
         length -= read;
         offset += read;
         start  += read;
     }
 }
예제 #3
0
 /// <inheritdoc/>
 public void ReadBytesToBuffer(byte[] buffer, long start = 0, int length = -1, int offset = 0)
 {
     IDataStreamHelpers.ReadBytesToBufferArgsCheck(this, buffer, start, ref length, offset);
     innerStream.ReadBytesToBuffer(buffer, start, length, offset);
     for (long i = 0; i < length; ++i)
     {
         buffer[offset + i] = (byte)(buffer[offset + i] ^ mask[(start + i) % 4]);
     }
 }
예제 #4
0
        /// <inheritdoc/>
        public override int Read(byte[] buffer, int offset, int count)
        {
            int len = Math.Min(count, (int)(Math.Min(int.MaxValue, stream.Length - (position + offset))));

            if (len > 0)
            {
                stream.ReadBytesToBuffer(buffer, position + offset, len);
                position += len;
            }
            return(len);
        }
예제 #5
0
        /// <summary>
        /// Reads bytes and returns them as a byte array. This method must perform a copy.
        /// </summary>
        /// <param name="s"></param>
        /// <inheritdoc cref="IDataStream.ReadBytesToBuffer" select="param[@name='start']|param[@name='length']|exception"/>
        /// <inheritdoc cref="IDataStreamHelpers.ReadBytesToBufferArgsCheck" select="exception"/>
        public static byte[] ReadBytes(this IDataStream s, long start = 0, int length = -1)
        {
            if (length == -1)
            {
                length = (int)Math.Min(int.MaxValue, s.Length - start);
            }
            var ret = new byte[length];

            s.ReadBytesToBuffer(ret, start, length);
            return(ret);
        }
예제 #6
0
 /// <inheritdoc/>
 public void ReadBytesToBuffer(byte[] buffer, long start = 0, int length = -1, int offset = 0)
 {
     IDataStreamHelpers.ReadBytesToBufferArgsCheck(this, buffer, start, ref length, offset);
     if (length == -1)
     {
         length = (int)Math.Min(int.MaxValue, Length - start);
     }
     if (start + length > count || start < 0 || length < 0)
     {
         throw new ArgumentOutOfRangeException("wrong index or length");
     }
     stream.ReadBytesToBuffer(buffer, this.offset + start, length, offset);
 }
예제 #7
0
 public static void Send(Socket socket, IDataStream stream)
 {
     if (stream.Length < socket.SendBufferSize)
     {
         socket.Send(stream.ReadBytes());
     }
     else
     {
         var  buffer    = new byte[socket.SendBufferSize];
         var  remaining = stream.Length;
         long start     = 0;
         while (remaining > 0)
         {
             var read = (int)Math.Min(remaining, buffer.Length);
             stream.ReadBytesToBuffer(buffer, start, read);
             start     += read;
             remaining -= read;
             socket.Send(buffer, read, SocketFlags.None);
         }
     }
 }
예제 #8
0
 /// <inheritdoc/>
 public void ReadBytesToBuffer(byte[] buffer, long start = 0, int length = -1, int offset = 0)
 {
     MessageData.ReadBytesToBuffer(buffer, start, length, offset);
 }
예제 #9
0
            /// <summary>
            /// Parse the header from data stream
            /// </summary>
            /// <param name="s"></param>
            /// <returns>length of missing payload data (negative if there are more data than neccessary)</returns>
            public long ParseHeader(IDataStream s)
            {
                headerLength = 2;
                var len = s.Length;

                if (len < 2)
                {
                    throw new ArgumentException("Stream too short to contain the header!");
                }
                byte b1, b2;

                b1                = s.ReadByte(0);
                b2                = s.ReadByte(1);
                msg.FIN           = (b1 & 0x80) == 0x80;
                msg.RSV1          = (b1 & 0x40) == 0x40;
                msg.RSV2          = (b1 & 0x20) == 0x20;
                msg.RSV3          = (b1 & 0x10) == 0x10;
                msg.Opcode        = (OpcodeType)(b1 & 0x0F);
                msg.MASK          = (b2 & 0x80) == 0x80;
                msg.PayloadLength = b2 & ~0x80;
                byte[] buffer;
                if (msg.PayloadLength == 126)
                {
                    if (len < 4)
                    {
                        throw new ArgumentException("Stream too short to contain the header!");
                    }
                    buffer = new byte[2];
                    s.ReadBytesToBuffer(buffer, 2, 2);
                    if (BitConverter.IsLittleEndian)
                    {
                        b1        = buffer[0];
                        buffer[0] = buffer[1];
                        buffer[1] = b1;
                    }
                    msg.PayloadLength = BitConverter.ToUInt16(buffer, 0);
                    headerLength     += 2;
                }
                else if (msg.PayloadLength == 127)
                {
                    if (len < 10)
                    {
                        throw new ArgumentException("Stream too short to contain the header!");
                    }
                    buffer = new byte[8];
                    s.ReadBytesToBuffer(buffer, 2, 8);
                    if (BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(buffer);
                    }
                    // lets hope no one will ever send a websocket message that long that this actually matters.
                    msg.PayloadLength = (long)BitConverter.ToUInt64(buffer, 0);
                    headerLength     += 8;
                }
                if (msg.MASK)
                {
                    buffer = new byte[4];
                    s.ReadBytesToBuffer(buffer, headerLength, 4);
                    msg.MaskingKey = buffer;
                    headerLength  += 4;
                }
                return(headerLength + msg.PayloadLength - len);
            }
예제 #10
0
 /// <inheritdoc/>
 public void ReadBytesToBuffer(byte[] buffer, long start = 0, int length = -1, int offset = 0)
 {
     binaryStream.ReadBytesToBuffer(buffer, start, length, offset);
 }
예제 #11
0
        /// <summary>
        /// Append data to file
        /// </summary>
        /// <param name="hint">as returned from FileLog.CreateFile or FileLogReader.GetFileHint</param>
        /// <param name="input">data to append</param>
        /// <remarks>
        /// Note that this function only appends data, eg. be careful not to pass more data into it.
        /// For example if you incrementaly add data to a StreamList don't pass the whole list each time, but only new data.
        /// </remarks>
        public void AppendDataToFile(LoggedFileInfo hint, IDataStream input)
        {
            long remaining = input.Length;

            if (remaining == 0)
            {
                return;
            }

            lock (streamLock)
            {
                var initialPos = stream.Position;
                if (blockBuffer == null)
                {
                    blockBuffer = new byte[BlockSize];
                }
                stream.Position = hint.Hint;
                long size = binReader.ReadInt64();
                // stream position is now the beginning of FBT
                long blockOffset = size % BlockSize;
                long fbt2Offset  = (size / (BlockSize)) % (FilesPerBlock + 1);
                long fbtOffset   = size / (BlockSize * (FilesPerBlock + 1)) + 1;
                // locate correct FBT
                while (fbtOffset > FilesPerBlock)
                {
                    // move to the next table
                    long nextFBT = binReader.ReadInt64();
                    if (nextFBT == 0)
                    {
                        nextFBT = createNewFBT(stream.Position - sizeof(long));
                    }
                    stream.Position = nextFBT;
                    fbtOffset      -= FilesPerBlock;
                }
                long currentFBT = stream.Position;
                while (remaining > 0)
                {
                    while (fbtOffset <= FilesPerBlock)
                    {
                        stream.Position = currentFBT + fbtOffset * sizeof(long);
                        long currentFBT2 = binReader.ReadInt64();
                        if (currentFBT2 == 0)
                        {
                            stream.Position -= sizeof(long);
                            binWriter.Write(stream.Length);
                            currentFBT2     = stream.Length;
                            stream.Position = stream.Length;
                            writeNewTable();
                        }
                        while (fbt2Offset <= FilesPerBlock)
                        {
                            int bytesRead = (int)Math.Min(BlockSize - blockOffset, remaining);
                            input.ReadBytesToBuffer(blockBuffer, input.Length - remaining, bytesRead);
                            stream.Position = currentFBT2 + fbt2Offset * sizeof(long);
                            long currentBlock = binReader.ReadInt64();
                            if (currentBlock == 0)
                            {
                                stream.Position -= sizeof(long);
                                binWriter.Write(stream.Length);
                                stream.Position = stream.Length;
                                // blockBuffer is exactly blockSize bytes long
                                // so don't call writeNewTable() to avoid unnecessary writes
                                // extra data written to the block will be ovewritten later or not used at all
                                binWriter.Write(blockBuffer);
                            }
                            else
                            {
                                stream.Position = currentBlock + blockOffset;
                                binWriter.Write(blockBuffer, 0, bytesRead);
                            }
                            blockOffset = 0;
                            remaining  -= bytesRead;
                            if (remaining == 0)
                            {
                                stream.Position = hint.Hint;
                                binWriter.Write(size + input.Length);
                                stream.Flush();
                                stream.Position = initialPos;
                                return;
                            }
                            // otherwise the current block has been filled completely
                            ++fbt2Offset;
                        }
                        fbt2Offset = 0;
                        fbtOffset++;
                    }
                    fbtOffset  = 1;
                    currentFBT = createNewFBT(currentFBT);
                }
                // unreachable
                throw new InvalidOperationException("There is something terribly wrong - more bytes were written than it was supposed to.");
            }
        }