protected override long GetUnadjustedFrameLength(IByteBuffer buffer, int offset, int length, ByteOrder order) { buffer = buffer.WithOrder(order); var scalarPrefix = buffer.GetByte(offset++); if (buffer.ReadableBytes - (offset - buffer.ReaderIndex) < scalarPrefix) { return(scalarPrefix); } switch (scalarPrefix) { case 1: return(buffer.GetByte(offset) + scalarPrefix); case 2: return(buffer.GetShort(offset) + scalarPrefix); case 4: return(buffer.GetInt(offset) + scalarPrefix); default: throw new ProudException("Invalid scalar prefix " + scalarPrefix); } }
/// <summary> /// Gets the num bits from the buffer. /// </summary> /// <param name="numBits"></param> /// <returns></returns> public int GetBits(int numBits) { if (numBits < 0 || numBits > 32) { throw new Exception("Number of bits must be between 1 and 32 inclusive"); } CheckBitAccess(); int bytePos = bitIndex >> 3; int bitOffset = 8 - (bitIndex & 7); int value = 0; bitIndex += numBits; for (; numBits > bitOffset; bitOffset = 8) { value += (buffer.GetByte(bytePos++) & DataConstants.BIT_MASK[bitOffset]) << numBits - bitOffset; numBits -= bitOffset; } if (numBits == bitOffset) { value += buffer.GetByte(bytePos) & DataConstants.BIT_MASK[bitOffset]; } else { value += buffer.GetByte(bytePos) >> bitOffset - numBits & DataConstants.BIT_MASK[numBits]; } return(value); }
/** * Gets the specified amount of bits from the buffer. * * @param amount The amount of bits. * @return The value. * @throws IllegalStateException If the reader is not in bit access mode. * @throws IllegalArgumentException If the number of bits is not between 1 and 31 inclusive. */ public int GetBits(int amount) { Guard.Argument(amount).InRange(0, 32); CheckBitAccess(); int bytePos = _bitIndex >> 3; int bitOffset = 8 - (_bitIndex & 7); int value = 0; _bitIndex += amount; for (; amount > bitOffset; bitOffset = 8) { value += (_buffer.GetByte(bytePos++) & MessageFrameBuilder.BITMASKS[bitOffset]) << amount - bitOffset; amount -= bitOffset; } if (amount == bitOffset) { value += _buffer.GetByte(bytePos) & MessageFrameBuilder.BITMASKS[bitOffset]; } else { value += _buffer.GetByte(bytePos) >> bitOffset - amount & MessageFrameBuilder.BITMASKS[amount]; } return(value); }
protected override IByteBuffer ExtractFrame(IChannelHandlerContext context, IByteBuffer buffer, int index, int length) { var bytesToSkip = 2; // magic var scalarPrefix = buffer.GetByte(index + bytesToSkip); ++bytesToSkip; switch (scalarPrefix) { case 1: ++bytesToSkip; break; case 2: bytesToSkip += 2; break; case 4: bytesToSkip += 4; break; } var frame = buffer.Slice(index + bytesToSkip, length - bytesToSkip); frame.Retain(); return(frame); }
private static int IndexOf(IByteBuffer haystack, IReadOnlyList <byte> needle) { for (var i = haystack.ReaderIndex; i < haystack.WriterIndex; i++) { var haystackIndex = i; int needleIndex; for (needleIndex = 0; needleIndex < needle.Count; needleIndex++) { if (haystack.GetByte(haystackIndex) != needle[needleIndex]) { break; } haystackIndex++; if (haystackIndex == haystack.WriterIndex && needleIndex != needle.Count - 1) { return(-1); } } if (needleIndex == needle.Count) { return(i - haystack.ReaderIndex); } } return(-1); }
/** * Returns the number of bytes between the readerIndex of the haystack and * the first needle found in the haystack. -1 is returned if no needle is * found in the haystack. */ static int IndexOf(IByteBuffer haystack, IByteBuffer needle) { for (int i = haystack.ReaderIndex; i < haystack.WriterIndex; i++) { int haystackIndex = i; int needleIndex; for (needleIndex = 0; needleIndex < needle.Capacity; needleIndex++) { if (haystack.GetByte(haystackIndex) != needle.GetByte(needleIndex)) { break; } else { haystackIndex++; if (haystackIndex == haystack.WriterIndex && needleIndex != needle.Capacity - 1) { return(-1); } } } if (needleIndex == needle.Capacity) { // Found the needle from the haystack! return(i - haystack.ReaderIndex); } } return(-1); }
void Unmask(IByteBuffer frame) { int i = frame.ReaderIndex; int end = frame.WriterIndex; int intMask = BitConverter.IsLittleEndian ? (this.maskingKey[0]) | (this.maskingKey[1] << 8) | (this.maskingKey[2] << 16) | (this.maskingKey[3] << 24) : (this.maskingKey[0] << 24) | (this.maskingKey[1] << 16) | (this.maskingKey[2] << 8) | this.maskingKey[3]; for (; i + 3 < end; i += 4) { int unmasked = frame.GetInt(i) ^ intMask; frame.SetInt(i, unmasked); } for (; i < end; i++) { frame.SetByte(i, frame.GetByte(i) ^ this.maskingKey[i % 4]); } }
private int FindEndOfLine(IByteBuffer byteBuffer) { var chars = terminator.ToCharArray(); var byteChar = (byte)chars[0]; var index = byteBuffer.ForEachByte(new ByteProcessor(b => b != byteChar)); if (index != -1) { for (int i = 1; i < chars.Length; i++) { var chatByte = (byte)chars[i]; if (index > byteBuffer.ReadableBytes) { index = -1; break; } var byteItem = byteBuffer.GetByte(index + 1); if (chatByte == byteItem) { index += 1; } else { index = -1; break; } } } if (index != -1) { index -= chars.Length - 1; } return(index); }
/// <summary> /// Decodes the specified region of the buffer into an unadjusted frame length. The default implementation is /// capable of decoding the specified region into an unsigned 8/16/24/32/64 bit integer. Override this method to /// decode the length field encoded differently. /// Note that this method must not modify the state of the specified buffer (e.g. /// <see cref="IByteBuffer.ReaderIndex" />, /// <see cref="IByteBuffer.WriterIndex" />, and the content of the buffer.) /// </summary> /// <param name="buffer">The buffer we'll be extracting the frame length from.</param> /// <param name="offset">The offset from the absolute <see cref="IByteBuffer.ReaderIndex" />.</param> /// <param name="length">The length of the framelenght field. Expected: 1, 2, 3, 4, or 8.</param> /// <param name="order">The preferred <see cref="ByteOrder" /> of <see cref="buffer" />.</param> /// <returns>A long integer that represents the unadjusted length of the next frame.</returns> protected long GetUnadjustedFrameLength(IByteBuffer buffer, int offset, int length, ByteOrder order) { buffer = buffer.WithOrder(order); long frameLength; switch (length) { case 1: frameLength = buffer.GetByte(offset); break; case 2: frameLength = buffer.GetShort(offset); break; case 4: frameLength = buffer.GetInt(offset); break; case 8: frameLength = buffer.GetLong(offset); break; default: throw new DecoderException("unsupported lengthFieldLength: " + this.lengthFieldLength + " (expected: 1, 2, 3, 4, or 8)"); } return(frameLength); }
/// <summary> /// Unsigned Little Endian Base 128 Variable-Length Integer Encoding /// <para>Visible for testing only!</para> /// </summary> /// <param name="input"></param> /// <param name="result"></param> /// <returns></returns> internal static long DecodeULE128(IByteBuffer input, long result) { Debug.Assert(result <= 0x7f && result >= 0); bool resultStartedAtZero = 0ul >= (ulong)result; int writerIndex = input.WriterIndex; for (int readerIndex = input.ReaderIndex, shift = 0; readerIndex < writerIndex; ++readerIndex, shift += 7) { byte b = input.GetByte(readerIndex); if (shift == 56 && ((b & 0x80) != 0 || b == 0x7F && !resultStartedAtZero)) { // the maximum value that can be represented by a signed 64 bit number is: // [0x01L, 0x7fL] + 0x7fL + (0x7fL << 7) + (0x7fL << 14) + (0x7fL << 21) + (0x7fL << 28) + (0x7fL << 35) // + (0x7fL << 42) + (0x7fL << 49) + (0x7eL << 56) // OR // 0x0L + 0x7fL + (0x7fL << 7) + (0x7fL << 14) + (0x7fL << 21) + (0x7fL << 28) + (0x7fL << 35) + // (0x7fL << 42) + (0x7fL << 49) + (0x7fL << 56) // this means any more shifts will result in overflow so we should break out and throw an error. ThrowHelper.ThrowHttp2Exception_DecodeULE128ToLongDecompression(); } if (0u >= (uint)(b & 0x80)) { _ = input.SetReaderIndex(readerIndex + 1); return(result + ((b & 0x7FL) << shift)); } result += (b & 0x7FL) << shift; } return(ThrowHelper.FromHttp2Exception_DecodeULE128Decompression()); }
private static int CompareSlow(IByteBuffer bufferA, IByteBuffer bufferB) { int aLen = bufferA.ReadableBytes; int bLen = bufferB.ReadableBytes; int minLength = Math.Min(aLen, bLen); int uintCount = minLength.RightUShift(2); int byteCount = minLength & 3; int aIndex = bufferA.ReaderIndex; int bIndex = bufferB.ReaderIndex; if (uintCount > 0) { int uintCountIncrement = uintCount << 2; int res = CompareUint(bufferA, bufferB, aIndex, bIndex, uintCountIncrement); if (res != 0) { return(res); } aIndex += uintCountIncrement; bIndex += uintCountIncrement; } for (int aEnd = aIndex + byteCount; aIndex < aEnd; ++aIndex, ++bIndex) { int comp = bufferA.GetByte(aIndex) - bufferB.GetByte(bIndex); if (comp != 0) { return(comp); } } return(aLen - bLen); }
long ParseNumber(IByteBuffer byteBuffer) { int readableBytes = byteBuffer.ReadableBytes; bool negative = readableBytes > 0 && byteBuffer.GetByte(byteBuffer.ReaderIndex) == '-'; int extraOneByteForNegative = negative ? 1 : 0; if (readableBytes <= extraOneByteForNegative) { throw new RedisCodecException( $"No number to parse: {byteBuffer.ToString(Encoding.ASCII)}"); } if (readableBytes > RedisConstants.PositiveLongValueMaximumLength + extraOneByteForNegative) { throw new RedisCodecException( $"Too many characters to be a valid RESP Integer: {byteBuffer.ToString(Encoding.ASCII)}"); } if (negative) { return(-this.ParsePositiveNumber(byteBuffer.SkipBytes(extraOneByteForNegative))); } return(this.ParsePositiveNumber(byteBuffer)); }
public static string DoHexDump(IByteBuffer buffer, int fromIndex, int length) { uint uLength = (uint)length; if (uLength > SharedConstants.TooBigOrNegative) { ThrowHelper.ThrowArgumentException_PositiveOrZero(length, ExceptionArgument.length); } if (0u >= uLength) { return(string.Empty); } int endIndex = fromIndex + length; var buf = new char[length << 1]; int srcIdx = fromIndex; int dstIdx = 0; for (; srcIdx < endIndex; srcIdx++, dstIdx += 2) { Array.Copy( HexdumpTable, buffer.GetByte(srcIdx) << 1, buf, dstIdx, 2); } return(new string(buf)); }
/// <inheritdoc/> public byte GetByte(int position) { EnsureValidPosition(position); ThrowIfDisposed(); return(_buffer.GetByte(position + _offset)); }
private static bool EqualsSlow(IByteBuffer a, int aStartIndex, IByteBuffer b, int bStartIndex, int length) { int longCount = unchecked ((int)((uint)length >> 3)); int byteCount = length & 7; for (int i = longCount; i > 0; i--) { if (a.GetLong(aStartIndex) != b.GetLong(bStartIndex)) { return(false); } aStartIndex += 8; bStartIndex += 8; } for (int i = byteCount; i > 0; i--) { if (a.GetByte(aStartIndex) != b.GetByte(bStartIndex)) { return(false); } aStartIndex++; bStartIndex++; } return(true); }
/// <summary> /// Calculates the hash code of the specified buffer. This method is /// useful when implementing a new buffer type. /// </summary> public static int HashCode(IByteBuffer buffer) { int aLen = buffer.ReadableBytes; int intCount = (int)((uint)aLen >> 2); int byteCount = aLen & 3; int hashCode = 1; int arrayIndex = buffer.ReaderIndex; for (int i = intCount; i > 0; i--) { hashCode = 31 * hashCode + buffer.GetInt(arrayIndex); arrayIndex += 4; } for (int i = byteCount; i > 0; i--) { hashCode = 31 * hashCode + buffer.GetByte(arrayIndex++); } if (hashCode == 0) { hashCode = 1; } return(hashCode); }
public override void ChannelRead(IChannelHandlerContext ctx, object msg) { Client client = Engine.Locator.ClientController.GetClient(ctx.Channel); IByteBuffer message = msg as IByteBuffer; if (message.GetByte(0) == 60) { string policy = "<?xml version=\"1.0\"?>\r\n<!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\r\n<cross-domain-policy>\r\n <allow-access-from domain=\"*\" to-ports=\"1-65535\" />\r\n</cross-domain-policy>\0"; ctx.Channel.WriteAndFlushAsync(Unpooled.CopiedBuffer(Encoding.GetEncoding(0).GetBytes(policy))).Wait(); } else { while (message.ReadableBytes >= 5) { int length = Base64Encoding.DecodeInt32(message.ReadBytes(3).ToArray()); if (length > 0) { IByteBuffer packet = message.ReadBytes(length); Engine.Locator.PacketController.Handle(client, packet); } } } base.ChannelRead(ctx, msg); }
/// <summary> /// Decodes the specified region of the buffer into an unadjusted frame length. The default implementation is /// capable of decoding the specified region into an unsigned 8/16/24/32/64 bit integer. Override this method to /// decode the length field encoded differently. /// Note that this method must not modify the state of the specified buffer (e.g. /// <see cref="IByteBuffer.ReaderIndex" />, /// <see cref="IByteBuffer.WriterIndex" />, and the content of the buffer.) /// </summary> /// <param name="buffer">The buffer we'll be extracting the frame length from.</param> /// <param name="offset">The offset from the absolute <see cref="IByteBuffer.ReaderIndex" />.</param> /// <param name="length">The length of the framelenght field. Expected: 1, 2, 3, 4, or 8.</param> /// <param name="order">The preferred <see cref="ByteOrder" /> of buffer.</param> /// <returns>A long integer that represents the unadjusted length of the next frame.</returns> protected virtual long GetUnadjustedFrameLength(IByteBuffer buffer, int offset, int length, ByteOrder order) { long frameLength; switch (length) { case 1: frameLength = buffer.GetByte(offset); break; case 2: frameLength = order == ByteOrder.BigEndian ? buffer.GetUnsignedShort(offset) : buffer.GetUnsignedShortLE(offset); break; case 3: frameLength = order == ByteOrder.BigEndian ? buffer.GetUnsignedMedium(offset) : buffer.GetUnsignedMediumLE(offset); break; case 4: frameLength = order == ByteOrder.BigEndian ? buffer.GetInt(offset) : buffer.GetIntLE(offset); break; case 8: frameLength = order == ByteOrder.BigEndian ? buffer.GetLong(offset) : buffer.GetLongLE(offset); break; default: throw new DecoderException("unsupported lengthFieldLength: " + this.lengthFieldLength + " (expected: 1, 2, 3, 4, or 8)"); } return(frameLength); }
/// <summary> /// Calculates the hash code of the specified buffer. This method is /// useful when implementing a new buffer type. /// </summary> public static int HashCode(IByteBuffer buffer) { int aLen = buffer.ReadableBytes; int intCount = aLen.RightUShift(2); int byteCount = aLen & 3; int hashCode = EmptyByteBuffer.EmptyByteBufferHashCode; int arrayIndex = buffer.ReaderIndex; for (int i = intCount; i > 0; i--) { hashCode = 31 * hashCode + buffer.GetInt(arrayIndex); arrayIndex += 4; } for (int i = byteCount; i > 0; i--) { hashCode = 31 * hashCode + buffer.GetByte(arrayIndex++); } if (0u >= (uint)hashCode) { hashCode = 1; } return(hashCode); }
void DecodeByte(byte c, IByteBuffer input, int idx) { if ((c == '{' || c == '[') && !this.insideString) { this.openBraces++; } else if ((c == '}' || c == ']') && !this.insideString) { this.openBraces--; } else if (c == '"') { // start of a new JSON string. It's necessary to detect strings as they may // also contain braces/brackets and that could lead to incorrect results. if (!this.insideString) { this.insideString = true; // If the double quote wasn't escaped then this is the end of a string. } else if (input.GetByte(idx - 1) != '\\') { this.insideString = false; } } }
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List <object> output) { try { switch (State) { case Socks5PasswordAuthRequestDecoderState.Init: var startOffset = input.ReaderIndex; var version = input.GetByte(startOffset); if (version != 1) { throw new DecoderException("unsupported subnegotiation version: " + version + " (expected: 1)"); } int usernameLength = input.GetByte(startOffset + 1); int passwordLength = input.GetByte(startOffset + 2 + usernameLength); var totalLength = usernameLength + passwordLength + 3; input.SkipBytes(totalLength); output.Add( new DefaultSocks5PasswordAuthRequest( input.ToString(startOffset + 2, usernameLength, Encoding.ASCII), input.ToString(startOffset + 3 + usernameLength, passwordLength, Encoding.ASCII))); Checkpoint(Socks5PasswordAuthRequestDecoderState.Success); break; case Socks5PasswordAuthRequestDecoderState.Success: var readableBytes = ActualReadableBytes; if (readableBytes > 0) { output.Add(input.ReadRetainedSlice(readableBytes)); } break; case Socks5PasswordAuthRequestDecoderState.Failure: input.SkipBytes(ActualReadableBytes); break; } } catch (Exception e) { Fail(output, e); } }
public void Decrypt(ref IByteBuffer data) { for (var k = 0; k < data.ReadableBytes; k++) { var b = data.GetByte(k) ^ Decryptor.Prga(); data.SetByte(k, b); } }
/// <summary>Returns true if the delimiters are "\n" and "\r\n"</summary> static bool IsLineBased(IByteBuffer[] delimiters) { if (delimiters.Length != 2) { return(false); } IByteBuffer a = delimiters[0]; IByteBuffer b = delimiters[1]; if (a.Capacity < b.Capacity) { a = delimiters[1]; b = delimiters[0]; } return(a.Capacity == 2 && b.Capacity == 1 && a.GetByte(0) == '\r' && a.GetByte(1) == '\n' && b.GetByte(0) == '\n'); }
static unsafe int DecodeUsingGetSet(IByteBuffer src, IByteBuffer dest, sbyte *decodabet, int offset, int length) { int charCount = 0; byte *b4 = stackalloc byte[4]; int b4Count = 0; int i = 0; for (i = offset; i < offset + length; ++i) { sbyte value = (sbyte)(src.GetByte(i) & 0x7F); if (decodabet[value] < WHITE_SPACE_ENC) { throw new ArgumentException(string.Format("bad Base64 input character at {0}:{1}", i, value)); } if (decodabet[value] >= EQUALS_SIGN_ENC) { b4[b4Count++] = (byte)value; if (b4Count <= 3) { continue; } if (b4[2] == EQUALS_SIGN) { int output = ((decodabet[b4[0]] & 0xFF) << 18) | ((decodabet[b4[1]] & 0xFF) << 12); dest.SetByte(charCount++, (int)((uint)output >> 16)); } else if (b4[3] == EQUALS_SIGN) { int output = ((decodabet[b4[0]] & 0xFF) << 18) | ((decodabet[b4[1]] & 0xFF) << 12) | ((decodabet[b4[2]] & 0xFF) << 6); dest.SetByte(charCount++, (int)((uint)output >> 16)); dest.SetByte(charCount++, (int)((uint)output >> 8)); } else { int output = ((decodabet[b4[0]] & 0xFF) << 18) | ((decodabet[b4[1]] & 0xFF) << 12) | ((decodabet[b4[2]] & 0xFF) << 6) | ((decodabet[b4[3]] & 0xFF) << 0); dest.SetByte(charCount++, (int)((uint)output >> 16)); dest.SetByte(charCount++, (int)((uint)output >> 8)); dest.SetByte(charCount++, (int)((uint)output >> 0)); } b4Count = 0; if (value == EQUALS_SIGN) { break; } } } return(charCount); }
static unsafe int DecodeUsingGetSet(IByteBuffer src, IByteBuffer dest, sbyte *decodabet, int offset, int length) { int charCount = 0; byte *b4 = stackalloc byte[4]; int b4Count = 0; int i = 0; for (i = offset; i < offset + length; ++i) { var value = src.GetByte(i); var sbiDecode = decodabet[value]; if (sbiDecode < WHITE_SPACE_ENC) { CThrowHelper.ThrowArgumentException_InvalidBase64InputChar(i, value); } if (sbiDecode >= EQUALS_SIGN_ENC) { b4[b4Count++] = value; if (b4Count <= 3) { continue; } if (0u >= (uint)(b4[2] - EQUALS_SIGN)) { int output = ((decodabet[b4[0]] & 0xFF) << 18) | ((decodabet[b4[1]] & 0xFF) << 12); _ = dest.SetByte(charCount++, (int)((uint)output >> 16)); } else if (0u >= (uint)(b4[3] - EQUALS_SIGN)) { int output = ((decodabet[b4[0]] & 0xFF) << 18) | ((decodabet[b4[1]] & 0xFF) << 12) | ((decodabet[b4[2]] & 0xFF) << 6); _ = dest.SetByte(charCount++, (int)((uint)output >> 16)); _ = dest.SetByte(charCount++, (int)((uint)output >> 8)); } else { int output = ((decodabet[b4[0]] & 0xFF) << 18) | ((decodabet[b4[1]] & 0xFF) << 12) | ((decodabet[b4[2]] & 0xFF) << 6) | ((decodabet[b4[3]] & 0xFF) << 0); _ = dest.SetByte(charCount++, (int)((uint)output >> 16)); _ = dest.SetByte(charCount++, (int)((uint)output >> 8)); _ = dest.SetByte(charCount++, (int)((uint)output >> 0)); } b4Count = 0; if (0u >= (uint)(value - EQUALS_SIGN)) { break; } } } return(charCount); }
public static void Xor(IByteBuffer data, int seed) { for (int i = 0; i < data.ReadableBytes; i++) { data.SetByte(i, (byte)(data.GetByte(i) ^ xorKey[(seed & 0xFF) + 4])); seed++; } }
/// <inheritdoc/> public override int ReadByte() { ThrowIfDisposed(); if (_position >= _length) { return(-1); } return(_buffer.GetByte(_position++)); }
public static byte[] Split(IByteBuffer buffer) { var readableSize = buffer.ReadableBytes; if (readableSize == 0) { return(null); } int startIndex = -1; byte[] starter = new byte[2]; for (int i = 0; i < readableSize - 1; i++) { starter[0] = buffer.GetByte(i); starter[1] = buffer.GetByte(i + 1); if (BytesUtil.ByteArrayEquals(starter, LaserDefault.Starter)) { startIndex = i; break; } } //至少得有13个字节 帧头(2) + 长度(2) + 硬件类型(1) + MAC地址(6) + CRC校验(2) if (startIndex == -1 || readableSize < 13) { return(null); } buffer.SetReaderIndex(startIndex); byte[] srcLength = new byte[2]; buffer.GetBytes(2, srcLength); int length = BytesUtil.Bytes2Int16(srcLength); //真正的包长度 = 帧头(2) + 长度(2) + 【长度值 硬件类型(1) + MAC地址(6) + 业务数据(n)】 + CRC校验(2) byte[] frame = null; int frameLength = length + 6; if (readableSize >= frameLength) { frame = new byte[frameLength]; buffer.ReadBytes(frame); } return(frame); }
protected override long GetUnadjustedFrameLength(IByteBuffer buffer, int offset, int length, ByteOrder order) { buffer = buffer.WithOrder(ByteOrder.LittleEndian); var scalarPrefix = buffer.GetByte(offset++); switch (scalarPrefix) { case 1: return(buffer.ReadableBytes < 1 ? 1 : buffer.GetByte(offset) + 1); case 2: return(buffer.ReadableBytes < 2 ? 2 : buffer.GetShort(offset) + 2); case 4: return(buffer.ReadableBytes < 4 ? 4 : buffer.GetInt(offset) + 4); default: throw new ProudException("Invalid scalar prefix " + scalarPrefix); } }
int FindEndOfLine(IByteBuffer buffer) { int i = buffer.ForEachByte(ByteProcessor.FIND_LF); if (i > 0 && buffer.GetByte(i - 1) == '\r') { i--; } return(i); }
/// <summary> /// Returns {@code true} if and only if the two specified buffers are /// identical to each other for {@code length} bytes starting at {@code aStartIndex} /// index for the {@code a} buffer and {@code bStartIndex} index for the {@code b} buffer. /// A more compact way to express this is: /// <p> /// {@code a[aStartIndex : aStartIndex + length] == b[bStartIndex : bStartIndex + length]} /// </summary> public static bool Equals(IByteBuffer a, int aStartIndex, IByteBuffer b, int bStartIndex, int length) { if (aStartIndex < 0 || bStartIndex < 0 || length < 0) { throw new ArgumentException("All indexes and lengths must be non-negative"); } if (a.WriterIndex - length < aStartIndex || b.WriterIndex - length < bStartIndex) { return false; } int longCount = unchecked((int)((uint)length >> 3)); int byteCount = length & 7; if (a.Order == b.Order) { for (int i = longCount; i > 0; i --) { if (a.GetLong(aStartIndex) != b.GetLong(bStartIndex)) { return false; } aStartIndex += 8; bStartIndex += 8; } } else { for (int i = longCount; i > 0; i --) { if (a.GetLong(aStartIndex) != SwapLong(b.GetLong(bStartIndex))) { return false; } aStartIndex += 8; bStartIndex += 8; } } for (int i = byteCount; i > 0; i --) { if (a.GetByte(aStartIndex) != b.GetByte(bStartIndex)) { return false; } aStartIndex ++; bStartIndex ++; } return true; }
const int MAX_PLAINTEXT_LENGTH = 16 * 1024; // 2^14 #endregion Fields #region Methods /// <summary> /// Return how much bytes can be read out of the encrypted data. Be aware that this method will not increase /// the readerIndex of the given <see cref="IByteBuffer"/>. /// </summary> /// <param name="buffer"> /// The <see cref="IByteBuffer"/> to read from. Be aware that it must have at least /// <see cref="SSL_RECORD_HEADER_LENGTH"/> bytes to read, /// otherwise it will throw an <see cref="ArgumentException"/>. /// </param> /// <param name="offset">Offset to record start.</param> /// <returns> /// The length of the encrypted packet that is included in the buffer. This will /// return <c>-1</c> if the given <see cref="IByteBuffer"/> is not encrypted at all. /// </returns> public static int GetEncryptedPacketLength(IByteBuffer buffer, int offset) { int packetLength = 0; // SSLv3 or TLS - Check ContentType switch (buffer.GetByte(offset)) { case SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC: case SSL_CONTENT_TYPE_ALERT: case SSL_CONTENT_TYPE_HANDSHAKE: case SSL_CONTENT_TYPE_APPLICATION_DATA: break; default: // SSLv2 or bad data return -1; } // SSLv3 or TLS - Check ProtocolVersion int majorVersion = buffer.GetByte(offset + 1); if (majorVersion == 3) { // SSLv3 or TLS packetLength = buffer.GetUnsignedShort(offset + 3) + SSL_RECORD_HEADER_LENGTH; if (packetLength <= SSL_RECORD_HEADER_LENGTH) { // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data) return -1; } } else { // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data) return -1; } return packetLength; }
protected internal override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output) { if (this.state == StCorrupted) { input.SkipBytes(input.ReadableBytes); return; } // index of next byte to process. int idx = this.idx; int wrtIdx = input.WriterIndex; if (wrtIdx > this.maxObjectLength) { // buffer size exceeded maxObjectLength; discarding the complete buffer. input.SkipBytes(input.ReadableBytes); this.Reset(); throw new TooLongFrameException($"Object length exceeds {this.maxObjectLength}: {wrtIdx} bytes discarded"); } for ( /* use current idx */; idx < wrtIdx; idx++) { byte c = input.GetByte(idx); if (this.state == StDecodingNormal) { this.DecodeByte(c, input, idx); // All opening braces/brackets have been closed. That's enough to conclude // that the JSON object/array is complete. if (this.openBraces == 0) { IByteBuffer json = this.ExtractObject(context, input, input.ReaderIndex, idx + 1 - input.ReaderIndex); if (json != null) { output.Add(json); } // The JSON object/array was extracted => discard the bytes from // the input buffer. input.SetReaderIndex(idx + 1); // Reset the object state to get ready for the next JSON object/text // coming along the byte stream. this.Reset(); } } else if (this.state == StDecodingArrayStream) { this.DecodeByte(c, input, idx); if (!this.insideString && (this.openBraces == 1 && c == ',' || this.openBraces == 0 && c == ']')) { // skip leading spaces. No range check is needed and the loop will terminate // because the byte at position idx is not a whitespace. for (int i = input.ReaderIndex; char.IsWhiteSpace(Convert.ToChar(input.GetByte(i))); i++) { input.SkipBytes(1); } // skip trailing spaces. int idxNoSpaces = idx - 1; while (idxNoSpaces >= input.ReaderIndex && char.IsWhiteSpace(Convert.ToChar(input.GetByte(idxNoSpaces)))) { idxNoSpaces--; } IByteBuffer json = this.ExtractObject(context, input, input.ReaderIndex, idxNoSpaces + 1 - input.ReaderIndex); if (json != null) { output.Add(json); } input.SetReaderIndex(idx + 1); if (c == ']') { this.Reset(); } } } else if (c == '{' || c == '[') // JSON object/array detected. Accumulate bytes until all braces/brackets are closed { this.InitDecoding(c); if (this.state == StDecodingArrayStream) { //Discard the array bracket input.SkipBytes(1); } } else if (char.IsWhiteSpace(Convert.ToChar(c))) //Discard leading spaces in from of a JSON object/array { input.SkipBytes(1); } else { this.state = StCorrupted; throw new CorruptedFrameException($"Invalid JSON received at byte position {idx}"); } } if (input.ReadableBytes == 0) { this.idx = 0; } else { this.idx = idx; } }
/// <summary> /// Determines whether the buffer contains a data block header. /// </summary> /// <param name="input">The input.</param> /// <returns><c>true</c> if the buffer contains a data block header; otherwise, <c>false</c>.</returns> private static bool IsDataBlockHeader(IByteBuffer input) => ((input.GetByte(input.ReaderIndex) ^ 0xFF) == '/' && (input.GetByte(input.ReaderIndex + 1) ^ 0xFF) == 'P' && (input.GetByte(input.ReaderIndex + 2) ^ 0xFF) == 'F');
/// <summary> /// Determines whether the buffer contains a server list. /// </summary> /// <param name="input">The input.</param> /// <returns><c>true</c> if the buffer contains a server list header; otherwise, <c>false</c>.</returns> private static bool IsServerList(IByteBuffer input) => ((input.GetByte(input.ReaderIndex) ^ 0xFF) == '/' && (input.GetByte(input.ReaderIndex + 1) ^ 0xFF) == 'S' && (input.GetByte(input.ReaderIndex + 2) ^ 0xFF) == 'e');
/// <summary> /// Reads the string from the byte buffer until null terminator. /// </summary> /// <param name="input">The input.</param> /// <returns>System.String.</returns> private static string ReadString(IByteBuffer input) { // Scan buffer for end of string null terminator for (var index = input.ReaderIndex; index < input.WriterIndex; index++) { if (input.GetByte(index) != 0xFF) continue; var bytes = XorArray(input.ReadBytes(index - input.ReaderIndex).ToArray()); return Encoding.ASCII.GetString(bytes); } return string.Empty; }
/// <summary> /// Compares the two specified buffers as described in {@link ByteBuf#compareTo(ByteBuf)}. /// This method is useful when implementing a new buffer type. /// </summary> public static int Compare(IByteBuffer bufferA, IByteBuffer bufferB) { int aLen = bufferA.ReadableBytes; int bLen = bufferB.ReadableBytes; int minLength = Math.Min(aLen, bLen); int uintCount = (int)((uint)minLength >> 2); int byteCount = minLength & 3; int aIndex = bufferA.ReaderIndex; int bIndex = bufferB.ReaderIndex; if (bufferA.Order == bufferB.Order) { for (int i = uintCount; i > 0; i--) { long va = bufferA.GetUnsignedInt(aIndex); long vb = bufferB.GetUnsignedInt(bIndex); if (va > vb) { return 1; } if (va < vb) { return -1; } aIndex += 4; bIndex += 4; } } else { for (int i = uintCount; i > 0; i--) { long va = bufferA.GetUnsignedInt(aIndex); long vb = SwapInt(bufferB.GetInt(bIndex)) & 0xFFFFFFFFL; if (va > vb) { return 1; } if (va < vb) { return -1; } aIndex += 4; bIndex += 4; } } for (int i = byteCount; i > 0; i--) { short va = bufferA.GetByte(aIndex); short vb = bufferB.GetByte(bIndex); if (va > vb) { return 1; } if (va < vb) { return -1; } aIndex++; bIndex++; } return aLen - bLen; }
/// <summary> /// Skips the null bytes. /// </summary> /// <param name="input">The input.</param> /// <returns><c>true</c> if successful, <c>false</c> otherwise.</returns> private static bool SkipNullBytes(IByteBuffer input) { while (input.IsReadable()) { if (input.GetByte(input.ReaderIndex) != 0xFF) return true; input.SkipBytes(1); } return false; }
/** * Returns the number of bytes between the readerIndex of the haystack and * the first needle found in the haystack. -1 is returned if no needle is * found in the haystack. */ static int IndexOf(IByteBuffer haystack, IByteBuffer needle) { for (int i = haystack.ReaderIndex; i < haystack.WriterIndex; i++) { int haystackIndex = i; int needleIndex; for (needleIndex = 0; needleIndex < needle.Capacity; needleIndex++) { if (haystack.GetByte(haystackIndex) != needle.GetByte(needleIndex)) { break; } else { haystackIndex++; if (haystackIndex == haystack.WriterIndex && needleIndex != needle.Capacity - 1) { return -1; } } } if (needleIndex == needle.Capacity) { // Found the needle from the haystack! return i - haystack.ReaderIndex; } } return -1; }
/// <summary> /// Create a frame out of the {@link ByteBuf} and return it. /// </summary> /// <param name="ctx">the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to</param> /// <param name="buffer">the {@link ByteBuf} from which to read data</param> protected internal object Decode(IChannelHandlerContext ctx, IByteBuffer buffer) { int eol = this.FindEndOfLine(buffer); if (!this.discarding) { if (eol >= 0) { IByteBuffer frame; int length = eol - buffer.ReaderIndex; int delimLength = buffer.GetByte(eol) == '\r' ? 2 : 1; if (length > this.maxLength) { buffer.SetReaderIndex(eol + delimLength); this.Fail(ctx, length); return null; } if (this.stripDelimiter) { frame = buffer.ReadSlice(length); buffer.SkipBytes(delimLength); } else { frame = buffer.ReadSlice(length + delimLength); } return frame.Retain(); } else { int length = buffer.ReadableBytes; if (length > this.maxLength) { this.discardedBytes = length; buffer.SetReaderIndex(buffer.WriterIndex); this.discarding = true; if (this.failFast) { this.Fail(ctx, "over " + this.discardedBytes); } } return null; } } else { if (eol >= 0) { int length = this.discardedBytes + eol - buffer.ReaderIndex; int delimLength = buffer.GetByte(eol) == '\r' ? 2 : 1; buffer.SetReaderIndex(eol + delimLength); this.discardedBytes = 0; this.discarding = false; if (!this.failFast) { this.Fail(ctx, length); } } else { this.discardedBytes += buffer.ReadableBytes; buffer.SetReaderIndex(buffer.WriterIndex); } return null; } }
/// <summary> /// Calculates the hash code of the specified buffer. This method is /// useful when implementing a new buffer type. /// </summary> public static int HashCode(IByteBuffer buffer) { int aLen = buffer.ReadableBytes; int intCount = (int)((uint)aLen >> 2); int byteCount = aLen & 3; int hashCode = 1; int arrayIndex = buffer.ReaderIndex; if (buffer.Order == ByteOrder.BigEndian) { for (int i = intCount; i > 0; i--) { hashCode = 31 * hashCode + buffer.GetInt(arrayIndex); arrayIndex += 4; } } else { for (int i = intCount; i > 0; i--) { hashCode = 31 * hashCode + SwapInt(buffer.GetInt(arrayIndex)); arrayIndex += 4; } } for (int i = byteCount; i > 0; i--) { hashCode = 31 * hashCode + buffer.GetByte(arrayIndex++); } if (hashCode == 0) { hashCode = 1; } return hashCode; }
/// <summary> /// Decodes the specified region of the buffer into an unadjusted frame length. The default implementation is /// capable of decoding the specified region into an unsigned 8/16/24/32/64 bit integer. Override this method to /// decode the length field encoded differently. /// Note that this method must not modify the state of the specified buffer (e.g. /// <see cref="IByteBuffer.ReaderIndex" />, /// <see cref="IByteBuffer.WriterIndex" />, and the content of the buffer.) /// </summary> /// <param name="buffer">The buffer we'll be extracting the frame length from.</param> /// <param name="offset">The offset from the absolute <see cref="IByteBuffer.ReaderIndex" />.</param> /// <param name="length">The length of the framelenght field. Expected: 1, 2, 3, 4, or 8.</param> /// <param name="order">The preferred <see cref="ByteOrder" /> of <see cref="buffer" />.</param> /// <returns>A long integer that represents the unadjusted length of the next frame.</returns> protected long GetUnadjustedFrameLength(IByteBuffer buffer, int offset, int length, ByteOrder order) { buffer = buffer.WithOrder(order); long frameLength; switch (length) { case 1: frameLength = buffer.GetByte(offset); break; case 2: frameLength = buffer.GetShort(offset); break; case 4: frameLength = buffer.GetInt(offset); break; case 8: frameLength = buffer.GetLong(offset); break; default: throw new DecoderException("unsupported lengthFieldLength: " + this.lengthFieldLength + " (expected: 1, 2, 3, 4, or 8)"); } return frameLength; }
/// <summary> /// Appends the prettified multi-line hexadecimal dump of the specified {@link ByteBuf} to the specified /// {@link StringBuilder} that is easy to read by humans, starting at the given {@code offset} using /// the given {@code length}. /// </summary> public static void AppendPrettyHexDump(StringBuilder dump, IByteBuffer buf, int offset, int length) { if (offset < 0 || length > buf.Capacity - offset) { throw new IndexOutOfRangeException( "expected: " + "0 <= offset(" + offset + ") <= offset + length(" + length + ") <= " + "buf.capacity(" + buf.Capacity + ')'); } if (length == 0) { return; } dump.Append( " +-------------------------------------------------+" + Newline + " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |" + Newline + "+--------+-------------------------------------------------+----------------+"); int startIndex = offset; int fullRows = (int)((uint)length >> 4); int remainder = length & 0xF; // Dump the rows which have 16 bytes. for (int row = 0; row < fullRows; row++) { int rowStartIndex = (row << 4) + startIndex; // Per-row prefix. AppendHexDumpRowPrefix(dump, row, rowStartIndex); // Hex dump int rowEndIndex = rowStartIndex + 16; for (int j = rowStartIndex; j < rowEndIndex; j++) { dump.Append(Byte2Hex[buf.GetByte(j)]); } dump.Append(" |"); // ASCII dump for (int j = rowStartIndex; j < rowEndIndex; j++) { dump.Append(Byte2Char[buf.GetByte(j)]); } dump.Append('|'); } // Dump the last row which has less than 16 bytes. if (remainder != 0) { int rowStartIndex = (fullRows << 4) + startIndex; AppendHexDumpRowPrefix(dump, fullRows, rowStartIndex); // Hex dump int rowEndIndex = rowStartIndex + remainder; for (int j = rowStartIndex; j < rowEndIndex; j++) { dump.Append(Byte2Hex[buf.GetByte(j)]); } dump.Append(HexPadding[remainder]); dump.Append(" |"); // Ascii dump for (int j = rowStartIndex; j < rowEndIndex; j++) { dump.Append(Byte2Char[buf.GetByte(j)]); } dump.Append(BytePadding[remainder]); dump.Append('|'); } dump.Append(Newline + "+--------+-------------------------------------------------+----------------+"); }
/// <summary> /// Returns a <a href="http://en.wikipedia.org/wiki/Hex_dump">hex dump</a> /// of the specified buffer's sub-region. /// </summary> public static string HexDump(IByteBuffer buffer, int fromIndex, int length) { Contract.Requires(length >= 0); if (length == 0) { return ""; } int endIndex = fromIndex + length; char[] buf = new char[length << 1]; int srcIdx = fromIndex; int dstIdx = 0; for (; srcIdx < endIndex; srcIdx++, dstIdx += 2) { Array.Copy( HexdumpTable, buffer.GetByte(srcIdx) << 1, buf, dstIdx, 2); } return new string(buf); }
int FindEndOfLine(IByteBuffer buffer) { int i = buffer.ForEachByte(ByteProcessor.FIND_LF); if (i > 0 && buffer.GetByte(i - 1) == '\r') { i--; } return i; }