示例#1
0
        //
        // 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);
        }
示例#2
0
        //
        // 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);
        }