blob: eea7c086a27a4fd2abd58cfaf837ce343c40cf8f [file] [log] [blame] [raw]
// NVNC - .NET VNC Server Library
// Copyright (C) 2014 T!T@N
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Diagnostics;
using System.IO;
using ComponentAce.Compression.Libs.zlib;
namespace NVNC.Writers
{
/// <summary>
/// A BinaryWriter that uses the Zlib algorithm to write compressed data to a Stream.
/// I have overrided only the necessary methods used by the ZRLE and Zlib encoding.
/// </summary>
public sealed class ZlibCompressedWriter : BinaryWriter
{
/// <summary>
/// A temporary MemoryStream to hold the compressed data.
/// </summary>
private MemoryStream zMemoryStream;
private ZOutputStream zCompressStream;
/// <summary>
/// CompressedWriter is used to write the compressed bytes from zMemoryStream to uncompressedStream.
/// </summary>
private BinaryWriter compressedWriter;
/// <summary>
/// BigWriter is used to write the number of bytes in a BigEndian format.
/// </summary>
private BigEndianBinaryWriter bigWriter;
public int Level { get; private set; }
/// <summary>
/// Writes compressed data to the given stream.
/// </summary>
/// <param name="uncompressedStream">A stream where the compressed data should be written.</param>
/// <param name="level">The Zlib compression level that should be used. Default is Z_BEST_COMPRESSION = 9.</param>
public ZlibCompressedWriter(Stream uncompressedStream, int level = 9)
: base(uncompressedStream)
{
/* Since we need to write the number of compressed bytes that we are going to send first,
* We cannot directly write to the uncompressedStream.
* We first write the compressed data to zMemoryStream, and after that we write the data from it to the uncompressedStream
* using CompressedWriter.
*/
zMemoryStream = new MemoryStream();
zCompressStream = new ZOutputStream(zMemoryStream, level)
{
//The VNC Protocol uses Z_SYNC_FLUSH as a Flush Mode
FlushMode = zlibConst.Z_SYNC_FLUSH
};
Level = level;
compressedWriter = new BinaryWriter(uncompressedStream);
bigWriter = new BigEndianBinaryWriter(uncompressedStream);
}
public override void Write(byte[] buffer, int index, int count)
{
//Seek to the beginning of the MemoryStream before writing
//So stream capacity won't increase, and eventually throw an OutOfMemory exception
zMemoryStream.Seek(0, SeekOrigin.Begin);
zCompressStream.Write(buffer, index, count);
long cPos = zMemoryStream.Position;
int len = Convert.ToInt32(cPos - 0);
bigWriter.Write(len);
zMemoryStream.Position = 0;
byte[] buff = new byte[len];
zMemoryStream.Read(buff, 0, len);
compressedWriter.Write(buff);
Trace.WriteLine("Compressed data length: " + len);
}
public override void Write(byte[] buffer)
{
Write(buffer, 0, buffer.Length);
}
public override void Write(byte value)
{
byte[] b = new byte[1];
b[0] = value;
Write(b, 0, 1);
}
}
}