コード例 #1
0
ファイル: MsgEchoPeerHandler.java プロジェクト: Pigwen/netty
 @Override
 public void channelActive(final ChannelHandlerContext ctx) throws Exception {
   log.info("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions());
   final MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
   out.add(message);
   ctx.flush();
 }
コード例 #2
0
ファイル: MsgEchoPeerHandler.java プロジェクト: Pigwen/netty
 @Override
 protected void messageReceived(final ChannelHandlerContext ctx, final UdtMessage message)
     throws Exception {
   final ByteBuf byteBuf = message.data();
   meter.mark(byteBuf.readableBytes());
   final MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
   out.add(message);
   ctx.flush();
 }
コード例 #3
0
ファイル: AbstractChannel.java プロジェクト: robbinfan/netty
    @Override
    public final void flushNow() {
      if (inFlushNow || flushTaskInProgress != null) {
        return;
      }

      inFlushNow = true;
      ChannelHandlerContext ctx = directOutboundContext();
      Throwable cause = null;
      try {
        if (ctx.hasOutboundByteBuffer()) {
          ByteBuf out = ctx.outboundByteBuffer();
          int oldSize = out.readableBytes();
          try {
            doFlushByteBuffer(out);
          } catch (Throwable t) {
            cause = t;
          } finally {
            final int newSize = out.readableBytes();
            final int writtenBytes = oldSize - newSize;
            if (writtenBytes > 0) {
              flushFutureNotifier.increaseWriteCounter(writtenBytes);
              if (newSize == 0) {
                out.discardReadBytes();
              }
            }
          }
        } else {
          MessageBuf<Object> out = ctx.outboundMessageBuffer();
          int oldSize = out.size();
          try {
            doFlushMessageBuffer(out);
          } catch (Throwable t) {
            cause = t;
          } finally {
            flushFutureNotifier.increaseWriteCounter(oldSize - out.size());
          }
        }

        if (cause == null) {
          flushFutureNotifier.notifyFlushFutures();
        } else {
          flushFutureNotifier.notifyFlushFutures(cause);
          if (cause instanceof IOException) {
            close(voidFuture());
          }
        }
      } finally {
        inFlushNow = false;
      }
    }
コード例 #4
0
 @Before
 public void initialize() {
   MockitoAnnotations.initMocks(this);
   when(context.nextInboundMessageBuffer()).thenReturn(buf);
   when(buf.add(anyObject())).thenReturn(true);
   when(context.nextOutboundMessageBuffer()).thenReturn(outboundBuf);
 }
コード例 #5
0
  @Override
  public void flush(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
    ByteBuf in = ctx.outboundByteBuffer();

    try {
      MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
      ByteBuf payload = Unpooled.buffer(in.readableBytes());
      payload.writeBytes(in);
      out.add(new SctpMessage(streamIdentifier, protocolIdentifier, payload));
      in.discardReadBytes();
    } catch (Throwable t) {
      ctx.fireExceptionCaught(new EncoderException(t));
    }

    ctx.flush(promise);
  }
コード例 #6
0
ファイル: NioDatagramChannel.java プロジェクト: JiniKim/netty
  @Override
  protected int doReadMessages(MessageBuf<Object> buf) throws Exception {
    DatagramChannel ch = javaChannel();
    ByteBuf buffer = alloc().directBuffer(config().getReceivePacketSize());
    boolean free = true;
    try {
      ByteBuffer data = buffer.nioBuffer(buffer.writerIndex(), buffer.writableBytes());

      InetSocketAddress remoteAddress = (InetSocketAddress) ch.receive(data);
      if (remoteAddress == null) {
        return 0;
      }
      buf.add(
          new DatagramPacket(
              buffer.writerIndex(buffer.writerIndex() + data.remaining()), remoteAddress));
      free = false;
      return 1;
    } catch (Throwable cause) {
      if (cause instanceof Error) {
        throw (Error) cause;
      }
      if (cause instanceof RuntimeException) {
        throw (RuntimeException) cause;
      }
      if (cause instanceof Exception) {
        throw (Exception) cause;
      }
      throw new ChannelException(cause);
    } finally {
      if (free) {
        buffer.free();
      }
    }
  }
コード例 #7
0
ファイル: NioDatagramChannel.java プロジェクト: JiniKim/netty
  @Override
  protected int doWriteMessages(MessageBuf<Object> buf, boolean lastSpin) throws Exception {
    DatagramPacket packet = (DatagramPacket) buf.peek();
    ByteBuf data = packet.data();
    int dataLen = data.readableBytes();
    ByteBuffer nioData;
    if (data.nioBufferCount() == 1) {
      nioData = data.nioBuffer();
    } else {
      nioData = ByteBuffer.allocate(dataLen);
      data.getBytes(data.readerIndex(), nioData);
      nioData.flip();
    }

    final int writtenBytes = javaChannel().send(nioData, packet.remoteAddress());

    final SelectionKey key = selectionKey();
    final int interestOps = key.interestOps();
    if (writtenBytes <= 0 && dataLen > 0) {
      // Did not write a packet.
      // 1) If 'lastSpin' is false, the caller will call this method again real soon.
      //    - Do not update OP_WRITE.
      // 2) If 'lastSpin' is true, the caller will not retry.
      //    - Set OP_WRITE so that the event loop calls flushForcibly() later.
      if (lastSpin) {
        if ((interestOps & SelectionKey.OP_WRITE) == 0) {
          key.interestOps(interestOps | SelectionKey.OP_WRITE);
        }
      }
      return 0;
    }

    // Wrote a packet.
    buf.remove();

    // packet was written free up buffer
    packet.free();

    if (buf.isEmpty()) {
      // Wrote the outbound buffer completely - clear OP_WRITE.
      if ((interestOps & SelectionKey.OP_WRITE) != 0) {
        key.interestOps(interestOps & ~SelectionKey.OP_WRITE);
      }
    }
    return 1;
  }
コード例 #8
0
ファイル: NioSctpServerChannel.java プロジェクト: nxbdi/netty
 @Override
 protected int doReadMessages(MessageBuf<Object> buf) throws Exception {
   SctpChannel ch = javaChannel().accept();
   if (ch == null) {
     return 0;
   }
   buf.add(new NioSctpChannel(this, null, ch));
   return 1;
 }
コード例 #9
0
  @Override
  protected void doWriteMessages(MessageBuf<Object> buf) throws Exception {
    DatagramPacket p = (DatagramPacket) buf.poll();
    ByteBuf data = p.data();
    int length = data.readableBytes();
    InetSocketAddress remote = p.remoteAddress();
    if (remote != null) {
      tmpPacket.setSocketAddress(remote);
    }
    if (data.hasArray()) {
      tmpPacket.setData(data.array(), data.arrayOffset() + data.readerIndex(), length);
    } else {
      byte[] tmp = new byte[length];
      data.getBytes(data.readerIndex(), tmp);
      tmpPacket.setData(tmp);
    }

    socket.send(tmpPacket);
  }
コード例 #10
0
  @Override
  protected int doReadMessages(MessageBuf<Object> buf) throws Exception {
    if (readSuspended) {
      try {
        Thread.sleep(SO_TIMEOUT);
      } catch (InterruptedException e) {
        // ignore;
      }
      return 0;
    }

    int packetSize = config().getReceivePacketSize();
    byte[] data = new byte[packetSize];
    tmpPacket.setData(data);
    try {
      socket.receive(tmpPacket);
      InetSocketAddress remoteAddr = (InetSocketAddress) tmpPacket.getSocketAddress();
      if (remoteAddr == null) {
        remoteAddr = remoteAddress();
      }
      buf.add(
          new DatagramPacket(
              Unpooled.wrappedBuffer(data, tmpPacket.getOffset(), tmpPacket.getLength()),
              remoteAddr));

      if (readSuspended) {
        return 0;
      } else {
        return 1;
      }
    } catch (SocketTimeoutException e) {
      // Expected
      return 0;
    } catch (SocketException e) {
      if (!e.getMessage().toLowerCase(Locale.US).contains("socket closed")) {
        throw e;
      }
      return -1;
    }
  }
コード例 #11
0
  @Override
  protected void decode(
      ChannelHandlerContext ctx, SpdyDataOrControlFrame msg, MessageBuf<Object> out)
      throws Exception {
    if (msg instanceof SpdySynStreamFrame) {

      // HTTP requests/responses are mapped one-to-one to SPDY streams.
      SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg;
      int streamId = spdySynStreamFrame.getStreamId();

      if (SpdyCodecUtil.isServerId(streamId)) {
        // SYN_STREAM frames initiated by the server are pushed resources
        int associatedToStreamId = spdySynStreamFrame.getAssociatedToStreamId();

        // If a client receives a SYN_STREAM with an Associated-To-Stream-ID of 0
        // it must reply with a RST_STREAM with error code INVALID_STREAM
        if (associatedToStreamId == 0) {
          SpdyRstStreamFrame spdyRstStreamFrame =
              new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.INVALID_STREAM);
          ctx.write(spdyRstStreamFrame);
        }

        String URL = SpdyHeaders.getUrl(spdyVersion, spdySynStreamFrame);

        // If a client receives a SYN_STREAM without a 'url' header
        // it must reply with a RST_STREAM with error code PROTOCOL_ERROR
        if (URL == null) {
          SpdyRstStreamFrame spdyRstStreamFrame =
              new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.PROTOCOL_ERROR);
          ctx.write(spdyRstStreamFrame);
        }

        try {
          FullHttpResponse httpResponseWithEntity =
              createHttpResponse(spdyVersion, spdySynStreamFrame);

          // Set the Stream-ID, Associated-To-Stream-ID, Priority, and URL as headers
          SpdyHttpHeaders.setStreamId(httpResponseWithEntity, streamId);
          SpdyHttpHeaders.setAssociatedToStreamId(httpResponseWithEntity, associatedToStreamId);
          SpdyHttpHeaders.setPriority(httpResponseWithEntity, spdySynStreamFrame.getPriority());
          SpdyHttpHeaders.setUrl(httpResponseWithEntity, URL);

          if (spdySynStreamFrame.isLast()) {
            HttpHeaders.setContentLength(httpResponseWithEntity, 0);
            out.add(httpResponseWithEntity);
          } else {
            // Response body will follow in a series of Data Frames
            putMessage(streamId, httpResponseWithEntity);
          }
        } catch (Exception e) {
          SpdyRstStreamFrame spdyRstStreamFrame =
              new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.PROTOCOL_ERROR);
          ctx.write(spdyRstStreamFrame);
        }
      } else {
        // SYN_STREAM frames initiated by the client are HTTP requests
        try {
          FullHttpRequest httpRequestWithEntity =
              createHttpRequest(spdyVersion, spdySynStreamFrame);

          // Set the Stream-ID as a header
          SpdyHttpHeaders.setStreamId(httpRequestWithEntity, streamId);

          if (spdySynStreamFrame.isLast()) {
            out.add(httpRequestWithEntity);
          } else {
            // Request body will follow in a series of Data Frames
            putMessage(streamId, httpRequestWithEntity);
          }
        } catch (Exception e) {
          // If a client sends a SYN_STREAM without all of the getMethod, url (host and path),
          // scheme, and version headers the server must reply with a HTTP 400 BAD REQUEST reply.
          // Also sends HTTP 400 BAD REQUEST reply if header name/value pairs are invalid
          SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamId);
          spdySynReplyFrame.setLast(true);
          SpdyHeaders.setStatus(spdyVersion, spdySynReplyFrame, HttpResponseStatus.BAD_REQUEST);
          SpdyHeaders.setVersion(spdyVersion, spdySynReplyFrame, HttpVersion.HTTP_1_0);
          ctx.write(spdySynReplyFrame);
        }
      }

    } else if (msg instanceof SpdySynReplyFrame) {

      SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg;
      int streamId = spdySynReplyFrame.getStreamId();

      try {
        FullHttpResponse httpResponseWithEntity =
            createHttpResponse(spdyVersion, spdySynReplyFrame);

        // Set the Stream-ID as a header
        SpdyHttpHeaders.setStreamId(httpResponseWithEntity, streamId);

        if (spdySynReplyFrame.isLast()) {
          HttpHeaders.setContentLength(httpResponseWithEntity, 0);
          out.add(httpResponseWithEntity);
        } else {
          // Response body will follow in a series of Data Frames
          putMessage(streamId, httpResponseWithEntity);
        }
      } catch (Exception e) {
        // If a client receives a SYN_REPLY without valid getStatus and version headers
        // the client must reply with a RST_STREAM frame indicating a PROTOCOL_ERROR
        SpdyRstStreamFrame spdyRstStreamFrame =
            new DefaultSpdyRstStreamFrame(streamId, SpdyStreamStatus.PROTOCOL_ERROR);
        ctx.write(spdyRstStreamFrame);
      }

    } else if (msg instanceof SpdyHeadersFrame) {

      SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg;
      int streamId = spdyHeadersFrame.getStreamId();
      FullHttpMessage fullHttpMessage = getMessage(streamId);

      // If message is not in map discard HEADERS frame.
      if (fullHttpMessage == null) {
        return;
      }

      for (Map.Entry<String, String> e : spdyHeadersFrame.headers().entries()) {
        fullHttpMessage.headers().add(e.getKey(), e.getValue());
      }

      if (spdyHeadersFrame.isLast()) {
        HttpHeaders.setContentLength(fullHttpMessage, fullHttpMessage.content().readableBytes());
        removeMessage(streamId);
        out.add(fullHttpMessage);
      }

    } else if (msg instanceof SpdyDataFrame) {

      SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg;
      int streamId = spdyDataFrame.getStreamId();
      FullHttpMessage fullHttpMessage = getMessage(streamId);

      // If message is not in map discard Data Frame.
      if (fullHttpMessage == null) {
        return;
      }

      ByteBuf content = fullHttpMessage.content();
      if (content.readableBytes() > maxContentLength - spdyDataFrame.content().readableBytes()) {
        removeMessage(streamId);
        throw new TooLongFrameException(
            "HTTP content length exceeded " + maxContentLength + " bytes.");
      }

      ByteBuf spdyDataFrameData = spdyDataFrame.content();
      int spdyDataFrameDataLen = spdyDataFrameData.readableBytes();
      content.writeBytes(spdyDataFrameData, spdyDataFrameData.readerIndex(), spdyDataFrameDataLen);

      if (spdyDataFrame.isLast()) {
        HttpHeaders.setContentLength(fullHttpMessage, content.readableBytes());
        removeMessage(streamId);
        out.add(fullHttpMessage);
      }

    } else if (msg instanceof SpdyRstStreamFrame) {

      SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg;
      int streamId = spdyRstStreamFrame.getStreamId();
      removeMessage(streamId);
    }
  }
コード例 #12
0
  @Override
  protected void decode(ChannelHandlerContext ctx, HttpObject msg, MessageBuf<Object> out)
      throws Exception {
    FullHttpMessage currentMessage = this.currentMessage;

    if (msg instanceof HttpMessage) {
      assert currentMessage == null;

      HttpMessage m = (HttpMessage) msg;

      // Handle the 'Expect: 100-continue' header if necessary.
      // TODO: Respond with 413 Request Entity Too Large
      //   and discard the traffic or close the connection.
      //       No need to notify the upstream handlers - just log.
      //       If decoding a response, just throw an exception.
      if (is100ContinueExpected(m)) {
        ctx.write(CONTINUE.duplicate());
      }

      if (!m.getDecoderResult().isSuccess()) {
        removeTransferEncodingChunked(m);
        this.currentMessage = null;
        out.add(BufUtil.retain(m));
        return;
      }
      if (msg instanceof HttpRequest) {
        HttpRequest header = (HttpRequest) msg;
        this.currentMessage =
            currentMessage =
                new DefaultFullHttpRequest(
                    header.getProtocolVersion(),
                    header.getMethod(),
                    header.getUri(),
                    Unpooled.compositeBuffer(maxCumulationBufferComponents));
      } else if (msg instanceof HttpResponse) {
        HttpResponse header = (HttpResponse) msg;
        this.currentMessage =
            currentMessage =
                new DefaultFullHttpResponse(
                    header.getProtocolVersion(),
                    header.getStatus(),
                    Unpooled.compositeBuffer(maxCumulationBufferComponents));
      } else {
        throw new Error();
      }

      currentMessage.headers().set(m.headers());

      // A streamed message - initialize the cumulative buffer, and wait for incoming chunks.
      removeTransferEncodingChunked(currentMessage);
    } else if (msg instanceof HttpContent) {
      assert currentMessage != null;

      // Merge the received chunk into the content of the current message.
      HttpContent chunk = (HttpContent) msg;
      CompositeByteBuf content = (CompositeByteBuf) currentMessage.content();

      if (content.readableBytes() > maxContentLength - chunk.content().readableBytes()) {
        // TODO: Respond with 413 Request Entity Too Large
        //   and discard the traffic or close the connection.
        //       No need to notify the upstream handlers - just log.
        //       If decoding a response, just throw an exception.
        throw new TooLongFrameException(
            "HTTP content length exceeded " + maxContentLength + " bytes.");
      }

      // Append the content of the chunk
      if (chunk.content().isReadable()) {
        chunk.retain();
        content.addComponent(chunk.content());
        content.writerIndex(content.writerIndex() + chunk.content().readableBytes());
      }

      final boolean last;
      if (!chunk.getDecoderResult().isSuccess()) {
        currentMessage.setDecoderResult(DecoderResult.failure(chunk.getDecoderResult().cause()));
        last = true;
      } else {
        last = chunk instanceof LastHttpContent;
      }

      if (last) {
        this.currentMessage = null;

        // Merge trailing headers into the message.
        if (chunk instanceof LastHttpContent) {
          LastHttpContent trailer = (LastHttpContent) chunk;
          currentMessage.headers().add(trailer.trailingHeaders());
        }

        // Set the 'Content-Length' header.
        currentMessage
            .headers()
            .set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(content.readableBytes()));

        // All done
        out.add(currentMessage);
      }
    } else {
      throw new Error();
    }
  }