public static byte[] CompressStream(byte[] inputStream)
{
#region Consts
// Size of Version field in RPC_HEADER_EXT
const int RpcHeaderExtVersionByteSize = 2;
// Size of Flags field in RPC_HEADER_EXT
const int RpcHeaderExtFlagsByteSize = 2;
// Size of Size field in RPC_HEADER_EXT
const int RpcHeaderExtSizeByteSize = 2;
// The length of RPC_HEADER_EXT.
const int RPCHeaderExtLength = 8;
#endregion
if (inputStream == null)
{
throw new ArgumentNullException("inputStream");
}
if (inputStream.Length < RPCHeaderExtLength)
{
throw new ArgumentException("Input must contain valid RPC_HEADER_EXT.", "inputStream");
}
// The third and fourth byte represents Flags field in RPC_HEADER_EXT
RpcHeaderExtFlags flag = (RpcHeaderExtFlags)BitConverter.ToInt16(inputStream, RpcHeaderExtVersionByteSize);
if ((flag & RpcHeaderExtFlags.Compressed) == RpcHeaderExtFlags.Compressed)
{
// Data stream is already compressed.
return inputStream;
}
ushort originalPayloadSize = BitConverter.ToUInt16(inputStream, RpcHeaderExtVersionByteSize + RpcHeaderExtFlagsByteSize);
// Compress payload
byte[] originalPayload = new byte[originalPayloadSize];
Array.Copy(inputStream, RPCHeaderExtLength, originalPayload, 0, originalPayloadSize);
byte[] compressedPayload = LZ77Compress(originalPayload);
// Output the original stream if compressed payload is bigger.
if (originalPayloadSize <= compressedPayload.Length)
{
return inputStream;
}
byte[] outStream = new byte[RPCHeaderExtLength + compressedPayload.Length];
Array.Copy(inputStream, 0, outStream, 0, RPCHeaderExtLength);
// Update Compressed flag.
flag |= RpcHeaderExtFlags.Compressed;
Array.Copy(BitConverter.GetBytes((short)flag), 0, outStream, RpcHeaderExtVersionByteSize, RpcHeaderExtFlagsByteSize);
// Update Size field.
Array.Copy(BitConverter.GetBytes((ushort)compressedPayload.Length), 0, outStream, RpcHeaderExtVersionByteSize + RpcHeaderExtFlagsByteSize, RpcHeaderExtSizeByteSize);
// Fill compressed payload.
Array.Copy(compressedPayload, 0, outStream, RPCHeaderExtLength, compressedPayload.Length);
return outStream;
}