// // Summary: // Writes encoded bytes to the underlying stream from the specified byte // array. // // Parameters: // array: // The array used to store encoded bytes. // // offset: // The location in the array to begin reading. // // count: // The number of bytes encoded. // // Exceptions: // System.ArgumentNullException: // array is null. // // System.InvalidOperationException: // The Q3Cypher.CypherMode value was Decode when the object // was created. - or - The underlying stream does not support writing. // // System.ArgumentOutOfRangeException: // offset or count is less than zero. -or- array length minus the index starting // point is less than count. // // System.ObjectDisposedException: // The stream is closed. public override void Write(byte [] array, int offset, int count) { #region Exception checks if (array == null) { throw new ArgumentNullException("array"); } if (baseStream == null) { throw new ObjectDisposedException("baseStream"); } if (mode == CypherMode.Decode) { throw new InvalidOperationException("Stream cannot be written while its mode set to Q3Cypher.CypherMode.Decode"); } if (!baseStream.CanWrite) { throw new InvalidOperationException("Underlying stream cannot be written"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0) { throw new ArgumentOutOfRangeException("count"); } if (array.Length < offset) { throw new ArgumentOutOfRangeException("offset"); } if (array.Length < offset + count) { throw new ArgumentOutOfRangeException("count"); } #endregion Exception checks (baseStream as Q3DatagramStream).BeginWritePacket(PacketKind.ConnectionOriented); Q3HuffmanStream huff = connection.Q3HuffDStream; int bloc = 0; int serverId = huff.DecompressBufferToInt32(array, 0, ref bloc); int messageAcknowledge = huff.DecompressBufferToInt32(array, 0, ref bloc); int reliableAcknowledge = huff.DecompressBufferToInt32(array, 0, ref bloc); byte [] buffer = new byte [count]; Array.Copy(array, buffer, CL_ENCODE_START < count ? CL_ENCODE_START : count); string pattern = connection.IncomingReliableCommands [reliableAcknowledge & (Q3Connection.MAX_RELIABLE_COMMANDS - 1)]; int index = 0; byte key = ( byte )(connection.Challenge ^ serverId ^ messageAcknowledge); for (int i = CL_ENCODE_START; i < count; i++) { // modify the key with the last received now acknowledged server command if (pattern == null || index >= pattern.Length) { index = 0; } if (pattern != null && (pattern [index] > 127 || pattern [index] == '%')) { key ^= ( byte )('.' << (i & 1)); } else { key ^= ( byte )((pattern != null ? pattern [index] : 0) << (i & 1)); } index++; // encode the data with this key buffer [i] = ( byte )(array [i + offset] ^ key); } baseStream.Write(buffer, 0, count); }
// // Summary: // Reads a number of decoded bytes into the specified byte array. // // Parameters: // array: // The array used to store decoded bytes. // // offset: // The byte offset in array at which to begin writing data read from the stream. // // count: // The number of bytes to decode. // // Returns: // The number of bytes that were decoded into the byte array. If the end // of the stream has been reached, zero or the number of bytes read is returned. // // Exceptions: // System.ArgumentNullException: // array is null. // // System.InvalidOperationException: // The Q3Cypher.CypherMode value was Encode when the object // was created. - or - The underlying stream does not support reading. // // System.ArgumentOutOfRangeException: // offset or count is less than zero. -or- array length minus the index starting // point is less than count. // // System.ObjectDisposedException: // The stream is closed. public override int Read(byte [] array, int offset, int count) { #region Exception checks if (array == null) { throw new ArgumentNullException("array"); } if (baseStream == null) { throw new ObjectDisposedException("baseStream"); } if (mode == CypherMode.Encode) { throw new InvalidOperationException("Stream cannot be read while its mode set to CypherMode.Encode"); } if (!baseStream.CanRead) { throw new InvalidOperationException("Underlying stream cannot be read"); } if (offset < 0) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0) { throw new ArgumentOutOfRangeException("count"); } if (array.Length < offset) { throw new ArgumentOutOfRangeException("offset"); } if (array.Length < offset + count) { throw new ArgumentOutOfRangeException("count"); } #endregion Exception checks if (this.readPosition == 0) { (( Q3DatagramStream )baseStream).BeginReadPacket(); } int bytesRead = baseStream.Read(array, offset, count); int encStart = 0, encEnd = 0; if (this.readPosition < CL_DECODE_START) { Array.Copy(array, offset, this.readBuffer, this.readPosition, bytesRead + this.readPosition > CL_DECODE_START ? CL_DECODE_START - this.readPosition : bytesRead); if (this.readPosition + bytesRead >= CL_DECODE_START) { Q3HuffmanStream huff = connection.Q3HuffDStream; int bloc = 0; this.readReliableAcknowledge = huff.DecompressBufferToInt32(this.readBuffer, 0, ref bloc); encStart = CL_DECODE_START - this.readPosition + offset; encEnd = bytesRead + offset; this.readPattern = connection.OutgoingReliableCommands [this.readReliableAcknowledge & (Q3Connection.MAX_RELIABLE_COMMANDS - 1)]; this.readKey = ( byte )(connection.Challenge ^ connection.IncomingSequence); this.readPatternIndex = 0; } } else { encStart = offset; encEnd = bytesRead; } for (int i = encStart; i < encEnd; i++) { // modify the key with the last received now acknowledged server command if (this.readPattern == null || this.readPatternIndex >= this.readPattern.Length) { this.readPatternIndex = 0; } if (this.readPattern != null && (this.readPattern [this.readPatternIndex] > 127 || this.readPattern [this.readPatternIndex] == '%')) { this.readKey ^= ( byte )('.' << (i & 1)); } else { this.readKey ^= ( byte )((this.readPattern != null ? this.readPattern [this.readPatternIndex] : 0) << (i & 1)); } this.readPatternIndex++; array [i] = ( byte )(array [i] ^ this.readKey); } this.readPosition += bytesRead; //string dump = BufferInfo.DumpBuffer ( "Decrypted buffer", array, offset, bytesRead, true, true, true ); //Console.Write ( dump ); return(bytesRead); }