public Packet DequeueTransformedPacket ()
		{
			var output = new Packet ();
			if (TransformedOutgoingPacketQueue.TryDequeue (out output))
				return output;
			return null;
		}
		public void EnqueuePacket(Packet packet)
		{
			CheckIfDisposed ();
			if (packet.Length > ushort.MaxValue)
				throw new PacketTooBigException (string.Format ("Packet must not exceed {0} bytes long.", ushort.MaxValue));
			OutgoingQueue.Enqueue (packet);
		}
		public Packet DequeuePacket()
		{
			CheckIfDisposed ();
			var result = new Packet();
			if (IncomingQueue.TryDequeue (out result))
				return result;
			return null;
		}
		private async Task ProcessOutgoingPackets()
		{
			var outgoingPacket = new Packet ();
			var netStream = connector.GetStream ();
			while (OutgoingQueue.TryDequeue (out outgoingPacket)) {
				var lengthBuffer = DataUtility.GetBytes ((ushort)outgoingPacket.RawContent.Length);
				await netStream.WriteAsync (lengthBuffer, 0, lengthBuffer.Length);
				await netStream.WriteAsync (outgoingPacket.RawContent, 0, outgoingPacket.RawContent.Length);
			}
		}
		private async Task ProcessIncomingPackets()
		{
			var netStream = connector.GetStream ();
			var length = 0;
			var buffer = new byte[ushort.MaxValue];
			while (netStream.DataAvailable) {
				length = await netStream.ReadAsync (buffer, 0, buffer.Length);
				if (length <= 0)
					break;
				RawIncomingStream.Write (buffer, 0, length);
			}

			while (RawIncomingStream.Length >= LengthVariableSize) {

				RawIncomingStream.Seek (0, SeekOrigin.Begin);
				var packetLength = DataUtility.ReadUInt16FromStream (RawIncomingStream);

				if (packetLength == 0 || RawIncomingStream.Length - LengthVariableSize < packetLength)
					continue;
				// If Packet Size exceed 65535 bytes, ignore it.
				if (packetLength <= ushort.MaxValue) {
					var newPacketBuffer = new byte[packetLength];
					RawIncomingStream.Read (newPacketBuffer, 0, newPacketBuffer.Length);
					var packet = new Packet (newPacketBuffer);
					IncomingQueue.Enqueue (packet);
				}
				DataUtility.ClearAndCopyMemoryStream (ref RawIncomingStream, (int)packetLength + LengthVariableSize);
			}
		}
		public Packet DequeueUntransformedPacket ()
		{
			var output = new Packet ();
			if (UntransformedIncomingPacketQueue.TryDequeue (out output))
				return output;
			return null;
		}
		public void EnqueueTransformedPacket (Packet packet)
		{
			TransformedIncomingPacketQueue.Enqueue (packet);
		}
		public void EnqueueUntransformedPacket (Packet packet)
		{
			UntransformedOutgoingPacketQueue.Enqueue (packet);
		}
		void EncryptWithNewKey(ref Packet input)
		{
			using (var output = new MemoryStream ()) {
				Rij.GenerateIV ();
				Rij.Key = NewKey;
				DataUtility.WriteOnlyBytesToStream (Rij.IV, output);
				DataUtility.WriteOnlyBytesToStream (Rij.CreateEncryptor ().TransformFinalBlock
					(input.RawContent, 0, input.RawContent.Length), output);
				Rij.Key = CurrentKey;
				input.RawContent = output.ToArray ();
			}
		}