public int PeekRead(IByteBuffer buffer) { buffer.Clear(); ArraySegment <byte> segment = buffer.ToSegment(true); return(buffer.End = _socket.Peek(segment.Array, segment.Offset, segment.Count) + buffer.Start); }
/* * Resets the state of this transport so it can be used to write more messages */ public void ResetOutputBuffer() { int shrunkenSize = ShrinkBufferSize(); if (_outputBuffer.WriterIndex < shrunkenSize) { // Less than the shrunken size of the buffer was actually used, so increment // the under-use counter ++_bufferUnderUsedCounter; } else { // More than the shrunken size of the buffer was actually used, reset // the counter so we won't shrink the buffer soon _bufferUnderUsedCounter = 0; } if (ShouldShrinkBuffer()) { if ((_outputBuffer?.ReferenceCount ?? 0) > 0) { _outputBuffer?.Release(); } _outputBuffer = Unpooled.Buffer(shrunkenSize); _bufferUnderUsedCounter = 0; } else { _outputBuffer.Clear(); } }
/// <inheritdoc/> public void Clear(int position, int count) { EnsureValidPositionAndCount(position, count); ThrowIfDisposed(); _buffer.Clear(position + _offset, count); }
public void RegisterSocketRead(IEvent e, BufferedSocket socket, IEventHandler protocol, ReadFunction callback) { e.RegisterSocketRead(socket, () => { EndPoint ep = new IPEndPoint(IPAddress.Any, 0); try { protocol.Read(socket, _msg, ref ep); } catch (SocketException ex) { Console.WriteLine("SocketException occured: " + ex.Message); _msg.Clear(); } callback(_msg, ep); }); }
private void PrepareToWrite(int count) { _buffer.EnsureCapacity(_position + count); _buffer.Length = _buffer.Capacity; if (_length < _position) { _buffer.Clear(_length, _position - _length); } }
public int ReceiveFrom(IByteBuffer message, ref IPEndPoint to) { message.Clear(); EndPoint ep = to; int length = ReceiveFrom(message, ref ep); to = (IPEndPoint)ep; return(length); }
public int ReceiveFrom(IByteBuffer message, ref EndPoint to) { message.Clear(); ArraySegment <byte> segment = message.ToSegment(true); int length = _socket.ReceiveFrom(segment.Array, segment.Offset, segment.Count, ref to); message.End = length; return(length); }
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List <object> output) { byte[] array = new byte[input.ReadableBytes]; input.GetBytes(input.ReaderIndex, array, 0, input.ReadableBytes); input.Clear(); var msg = new Message(); output.Add(msg.Prase(array)); }
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List <object> output) { var request = new PacketRequest <IMessage>(); request.Checkbit = input.ReadInt(); request.Length = input.ReadInt(); request.CommandId = input.ReadInt(); IByteBuffer result = Unpooled.Buffer(request.Length - 4 * 3); input.ReadBytes(result, request.Length - 4 * 3); request.Deserialize(result.Array); output.Add(request); result.Clear(); }
private void PrepareToWrite(int count) { var minimumCapacity = (long)_position + (long)count; if (minimumCapacity > int.MaxValue) { throw new IOException("Stream was too long."); } _buffer.EnsureCapacity((int)minimumCapacity); _buffer.Length = _buffer.Capacity; if (_length < _position) { _buffer.Clear(_length, _position - _length); } }
public static void MakeSpace(this IByteBuffer output, int length, string reason = null) { if (output.WritableBytes < length) { if (output.ReaderIndex == output.WriterIndex) { output.Clear(); } else { output.DiscardReadBytes(); } if (output.WritableBytes < length) { output.EnsureWritable(length, true); } } }
public void TestDecodeLargerThanMaxHeaderListSizeUpdatesDynamicTable() { IByteBuffer input = Unpooled.Buffer(300); try { hpackDecoder.SetMaxHeaderListSize(200); HpackEncoder hpackEncoder = new HpackEncoder(true); // encode headers that are slightly larger than maxHeaderListSize IHttp2Headers toEncode = new DefaultHttp2Headers(); toEncode.Add((AsciiString)"test_1", (AsciiString)"1"); toEncode.Add((AsciiString)"test_2", (AsciiString)"2"); toEncode.Add((AsciiString)"long", (AsciiString)"A".PadRight(100, 'A')); //string.Format("{0,0100:d}", 0).Replace('0', 'A') toEncode.Add((AsciiString)"test_3", (AsciiString)"3"); hpackEncoder.EncodeHeaders(1, input, toEncode, NeverSensitiveDetector.Instance); // decode the headers, we should get an exception IHttp2Headers decoded = new DefaultHttp2Headers(); Assert.Throws <HeaderListSizeException>(() => hpackDecoder.Decode(1, input, decoded, true)); // but the dynamic table should have been updated, so that later blocks // can refer to earlier headers input.Clear(); // 0x80, "indexed header field representation" // index 62, the first (most recent) dynamic table entry input.WriteByte(0x80 | 62); IHttp2Headers decoded2 = new DefaultHttp2Headers(); hpackDecoder.Decode(1, input, decoded2, true); IHttp2Headers golden = new DefaultHttp2Headers(); golden.Add((AsciiString)"test_3", (AsciiString)"3"); Assert.Equal(golden, decoded2); } finally { input.Release(); } }
public void EncodeHeaders(int streamId, IHttp2Headers headers, IByteBuffer buffer) { try { // If there was a change in the table size, serialize the output from the hpackEncoder // resulting from that change. if (_tableSizeChangeOutput.IsReadable()) { _ = buffer.WriteBytes(_tableSizeChangeOutput); _ = _tableSizeChangeOutput.Clear(); } _hpackEncoder.EncodeHeaders(streamId, buffer, headers, _sensitivityDetector); } catch (Http2Exception) { throw; } catch (Exception t) { ThrowHelper.ThrowConnectionError_FailedEncodingHeadersBlock(t); } }
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List <object> output) { //0 if (!input.HasArray) return; var request = new PacketRequest <string>(); request.Checkbit = input.ReadInt(); //0-4 request.Length = input.ReadInt(); //4-8 request.CommandId = input.ReadInt(); //8-12 IByteBuffer result = Unpooled.Buffer(request.Length - 4 * 3); input.ReadBytes(result, request.Length - 4 * 3);//12 - (20 - 4 * 3) 从第12个字节位置开始往后读8个字节 request.Deserialize(result.Array); output.Add(request); result.Clear(); //1 显式丢弃消息 //ReferenceCountUtil.Release(msg); //2增加引用计数防止释放 //ReferenceCountUtil.retain(message) //3 IByteBuffer.Read 读字节 IByteBuffer.Write 写字节 /* * 4 移除可丢弃字节 * 所谓可丢弃字节就是调用read方法之后,readindex已经移动过了的区域,这段区域的字节称为可丢弃字节。 * 只有在内存十分宝贵需要清理的时候再调用这个方法,随便调用有可能会造成内存的复制,降低效率。 */ //message.DiscardReadBytes(); //5 读取所有可读字节(移动读索引) //while (message.IsReadable()) //{ // Console.WriteLine(message.ReadByte()); //} }
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List <object> output) { if (!_suppressRead && !_handshakeFailed) { Exception error = null; try { int readerIndex = input.ReaderIndex; int readableBytes = input.ReadableBytes; int handshakeLength = -1; // Check if we have enough data to determine the record type and length. while (readableBytes >= TlsUtils.SSL_RECORD_HEADER_LENGTH) { int contentType = input.GetByte(readerIndex); // tls, but not handshake command switch (contentType) { case TlsUtils.SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC: // fall-through case TlsUtils.SSL_CONTENT_TYPE_ALERT: int len = TlsUtils.GetEncryptedPacketLength(input, readerIndex); // Not an SSL/TLS packet if (len == TlsUtils.NOT_ENCRYPTED) { _handshakeFailed = true; var e = new NotSslRecordException( "not an SSL/TLS record: " + ByteBufferUtil.HexDump(input)); _ = input.SkipBytes(input.ReadableBytes); _ = context.FireUserEventTriggered(new SniCompletionEvent(e)); TlsUtils.NotifyHandshakeFailure(context, e, true); throw e; } if (len == TlsUtils.NOT_ENOUGH_DATA) { // Not enough data return; } // SNI can't be present in an ALERT or CHANGE_CIPHER_SPEC record, so we'll fall back and // assume no SNI is present. Let's let the actual TLS implementation sort this out. // Just select the default SslContext goto SelectDefault; case TlsUtils.SSL_CONTENT_TYPE_HANDSHAKE: int majorVersion = input.GetByte(readerIndex + 1); // SSLv3 or TLS if (majorVersion == 3) { int packetLength = input.GetUnsignedShort(readerIndex + 3) + TlsUtils.SSL_RECORD_HEADER_LENGTH; if (readableBytes < packetLength) { // client hello incomplete; try again to decode once more data is ready. return; } else if (packetLength == TlsUtils.SSL_RECORD_HEADER_LENGTH) { goto SelectDefault; } int endOffset = readerIndex + packetLength; // Let's check if we already parsed the handshake length or not. if (handshakeLength == -1) { if (readerIndex + 4 > endOffset) { // Need more data to read HandshakeType and handshakeLength (4 bytes) return; } int handshakeType = input.GetByte(readerIndex + TlsUtils.SSL_RECORD_HEADER_LENGTH); // Check if this is a clientHello(1) // See https://tools.ietf.org/html/rfc5246#section-7.4 if (handshakeType != 1) { goto SelectDefault; } // Read the length of the handshake as it may arrive in fragments // See https://tools.ietf.org/html/rfc5246#section-7.4 handshakeLength = input.GetUnsignedMedium(readerIndex + TlsUtils.SSL_RECORD_HEADER_LENGTH + 1); // Consume handshakeType and handshakeLength (this sums up as 4 bytes) readerIndex += 4; packetLength -= 4; if (handshakeLength + 4 + TlsUtils.SSL_RECORD_HEADER_LENGTH <= packetLength) { // We have everything we need in one packet. // Skip the record header readerIndex += TlsUtils.SSL_RECORD_HEADER_LENGTH; Select(context, ExtractSniHostname(input, readerIndex, readerIndex + handshakeLength)); return; } else { if (_handshakeBuffer is null) { _handshakeBuffer = context.Allocator.Buffer(handshakeLength); } else { // Clear the buffer so we can aggregate into it again. _ = _handshakeBuffer.Clear(); } } } // Combine the encapsulated data in one buffer but not include the SSL_RECORD_HEADER _ = _handshakeBuffer.WriteBytes(input, readerIndex + TlsUtils.SSL_RECORD_HEADER_LENGTH, packetLength - TlsUtils.SSL_RECORD_HEADER_LENGTH); readerIndex += packetLength; readableBytes -= packetLength; if (handshakeLength <= _handshakeBuffer.ReadableBytes) { Select(context, ExtractSniHostname(_handshakeBuffer, 0, handshakeLength)); return; } } break; default: //not tls, ssl or application data, do not try sni break; } } } catch (Exception e) { error = e; // unexpected encoding, ignore sni and use default if (Logger.WarnEnabled) { Logger.UnexpectedClientHelloPacket(input, e); } } SelectDefault: if (_serverTlsSniSettings.DefaultServerHostName is object) { // Just select the default server TLS setting Select(context, _serverTlsSniSettings.DefaultServerHostName); } else { ReleaseHandshakeBuffer(); _handshakeFailed = true; var e = new DecoderException($"failed to get the server TLS setting {error}"); TlsUtils.NotifyHandshakeFailure(context, e, true); throw e; } } }
//패킷 완성후, 다음 데이터가 없는지 체크하는 함수. //패킷 완성후, 다시 자기자신을 호출하여 다음 데이터가 없을때까지 계속 자기자신을 호출한다. bool isCompleteSizePacket(int packet_size, IChannelHandlerContext ctx, IByteBuffer msg) { //아직 버퍼에 데이터가 충분하지 않다면 다시 되돌려서 패킷을 이어서 더 받아오게끔 하는 부분! if (msg.ReadableBytes < packet_size + 8) { //정상적으로 데이터를 다 읽은것이 아니므로 아까 MarkReaderIndex로 저장했던 0값으로 readerIndex 4 -> 0로 초기화함. msg.ResetReaderIndex(); return(false); //다시 되돌려서 패킷을 이어서 더 받아오게끔 하는 부분! } //패킷이 뭉쳐서 데이터를 더 받아왔을 경우! 원래 받아야 할 부분만 받고, 나머지는 다시 되돌려서 뒤이어 오는 패킷과 합쳐서 받을 것! else if (msg.ReadableBytes > packet_size + 8) { //받아온 데이터. byte[] packet_data = new byte[msg.ReadableBytes]; msg.ReadBytes(packet_data, 0, msg.ReadableBytes); //버퍼의 현재 용량에서 추가로 기록가능한 영역이 10KB 이하라면, //이미 읽은 분량만큼은 필요없으므로 Index 0의 위치로 데이터를 옮겨 추가로 기록가능한 영역을 늘린다. if (msg.Capacity - msg.WriterIndex < 10000) { msg.DiscardReadBytes(); } //받아온 데이터를 메인스레드와 통신하기 위한 목적으로 만들어둔 수신 Queue에 삽입. //멀티스레드에서 공유하는 Queue이므로, Locking 처리. NetworkManager.locking 는 스레드 lock용 모니터 객체이다. lock (NetworkManager.locking) { //받아온 데이터를 수신Queue에 삽입하는 부분. //데이터 삽입. NetworkManager.packet_Queue.Enqueue(new Packet_Data(packet_data)); } //패킷 완성후 남은 데이터가 헤더크기인 12byte보다 작을 경우. if (msg.ReadableBytes < 12) { return(false); } else { msg.MarkReaderIndex(); int amountSize = msg.ReadIntLE(); //비정상적인 데이터가 도달하였다면. if (!isAvailablePacketSize(amountSize)) { //연결 종료 ctx.CloseAsync(); //채널이 닫힌다면 msg는 release 된다. return(false); } return(isCompleteSizePacket(amountSize, ctx, msg)); //재귀함수 처리 //패킷 완성후, 남은데이터가 없을때까지 계속 반복한다. } } else //정확한 데이터일 경우. [msg.ReadableBytes > packet_size + 8] 또는 [msg.readableBytes() + 4 == packet_size + 12] { //받아온 데이터. byte[] packet_data = new byte[msg.ReadableBytes]; msg.ReadBytes(packet_data, 0, msg.ReadableBytes); //버퍼에 읽어와야 할 데이터가 남아있지 않으므로 readerIndex, writerIndex를 각각 0으로 초기화 한다. //내부 버퍼 데이터를 변경하지 않고 index값만 변경하므로 자원을 적게 소모한다. msg.Clear(); //받아온 데이터를 메인스레드와 통신하기 위한 목적으로 만들어둔 수신 Queue에 삽입. //멀티스레드에서 공유하는 Queue이므로, Locking 처리. NetworkManager.locking 는 스레드 lock용 모니터 객체이다. lock (NetworkManager.locking) { //받아온 데이터를 수신Queue에 삽입하는 부분. //데이터 삽입. NetworkManager.packet_Queue.Enqueue(new Packet_Data(packet_data)); } //다시 되돌려서 패킷을 이어서 더 받아오게끔 하는 부분! return(false); } }
/// <summary> /// Clears the data in the buffer. /// </summary> public void Clear() { ThrowIfDisposed(); _byteBuffer.Clear(); }
public int Read(IByteBuffer buffer) { buffer.Clear(); ArraySegment<byte> segment = buffer.ToSegment(true); buffer.End = _socket.Receive(segment.Array, segment.Offset, segment.Count) + buffer.Start; return buffer.End; }
public int ReceiveFrom(IByteBuffer message, ref EndPoint to) { message.Clear(); ArraySegment<byte> segment = message.ToSegment(true); int length = _socket.ReceiveFrom(segment.Array, segment.Offset, segment.Count, ref to); message.End = length; return length; }
public IByteBuffer Clear() { _ = Buf.Clear(); return(this); }
public int ReceiveFrom(IByteBuffer message, ref IPEndPoint to) { message.Clear(); EndPoint ep = to; int length = ReceiveFrom(message, ref ep); to = (IPEndPoint) ep; return length; }
public void Clear() { _bb.Clear(); }