@Override
  protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
    if (log.isDebugEnabled()) log.debug("encode");
    if (msg instanceof SipMessage) {
      SipMessage m = (SipMessage) msg;

      ChannelBuffer header = dynamicBuffer(channel.getConfig().getBufferFactory());
      encodeInitialLine(header, m);
      encodeHeaders(header, m);

      // always add a single white line between headers and content
      header.writeByte(CR);
      header.writeByte(LF);

      ChannelBuffer content = m.getContent();
      if (content != null && !content.readable()) {
        if (log.isDebugEnabled()) log.debug("no content available");
        // no content available
        return header;
      } else {
        if (log.isDebugEnabled()) log.debug("content available");

        // TODO write content depending on content type
        return wrappedBuffer(header, content);
      }
    }

    // Unknown message type.
    return msg;
  }
  @Test
  public void testNettyConfigBuilder() {
    NettyConfigBuilder configBuilder = new NettyConfigBuilder();

    configBuilder.getServerSocketChannelConfig().setReceiveBufferSize(10000);
    configBuilder.getServerSocketChannelConfig().setBacklog(1000);
    configBuilder.getServerSocketChannelConfig().setReuseAddress(true);

    ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory());
    bootstrap.setOptions(configBuilder.getOptions());
    bootstrap.setPipelineFactory(Channels.pipelineFactory(Channels.pipeline()));
    Channel serverChannel = bootstrap.bind(new InetSocketAddress(port));

    Assert.assertEquals(
        ((ServerSocketChannelConfig) serverChannel.getConfig()).getReceiveBufferSize(), 10000);
    Assert.assertEquals(((ServerSocketChannelConfig) serverChannel.getConfig()).getBacklog(), 1000);
    Assert.assertTrue(((ServerSocketChannelConfig) serverChannel.getConfig()).isReuseAddress());
  }
Пример #3
0
  @Override
  protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
    if (!(msg instanceof ChannelBuffer)) {
      return msg;
    }

    ChannelBuffer body = (ChannelBuffer) msg;
    ChannelBuffer header =
        channel.getConfig().getBufferFactory().getBuffer(body.order(), lengthFieldLength);

    int length =
        lengthIncludesLengthFieldLength
            ? body.readableBytes() + lengthFieldLength
            : body.readableBytes();
    switch (lengthFieldLength) {
      case 1:
        if (length >= 256) {
          throw new IllegalArgumentException("length does not fit into a byte: " + length);
        }
        header.writeByte((byte) length);
        break;
      case 2:
        if (length >= 65536) {
          throw new IllegalArgumentException("length does not fit into a short integer: " + length);
        }
        header.writeShort((short) length);
        break;
      case 3:
        if (length >= 16777216) {
          throw new IllegalArgumentException(
              "length does not fit into a medium integer: " + length);
        }
        header.writeMedium(length);
        break;
      case 4:
        header.writeInt(length);
        break;
      case 8:
        header.writeLong(length);
        break;
      default:
        throw new Error("should not reach here");
    }
    return wrappedBuffer(header, body);
  }
Пример #4
0
 /** Set the max size for the write queue, see {@link WriteStream#setWriteQueueMaxSize} */
 public void setWriteQueueMaxSize(int size) {
   NioSocketChannelConfig conf = (NioSocketChannelConfig) channel.getConfig();
   conf.setWriteBufferLowWaterMark(size / 2);
   conf.setWriteBufferHighWaterMark(size);
 }
Пример #5
0
  @Override
  protected Object decode(
      ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, State state)
      throws Exception {
    switch (state) {
      case SKIP_CONTROL_CHARS:
        {
          try {
            skipControlCharacters(buffer);
            checkpoint(State.READ_INITIAL);
          } finally {
            checkpoint();
          }
        }
      case READ_INITIAL:
        {
          final String[] initialLine = splitInitialLine(readLine(buffer, maxInitialLineLength));
          if (initialLine.length < 3) {
            // Invalid initial line - ignore.
            checkpoint(State.SKIP_CONTROL_CHARS);
            return null;
          }
          message = createMessage(initialLine);
          checkpoint(State.READ_HEADER);
        }
      case READ_HEADER:
        {
          State nextState = readHeaders(buffer);
          checkpoint(nextState);
          if (nextState == State.SKIP_CONTROL_CHARS) {
            return message;
          } else {
            long contentLength = getContentLength(message, -1);
            if (contentLength == 0 || contentLength == -1 && isDecodingRequest()) {
              content = ChannelBuffers.EMPTY_BUFFER;
              return reset();
            }

            switch (nextState) {
              case READ_FIXED_LENGTH_CONTENT:
                if (contentLength > maxChunkSize || HttpHeaders.is100ContinueExpected(message)) {
                  // Generate HttpMessage first. HttpChunks will follow.
                  checkpoint(State.READ_FIXED_LENGTH_CONTENT_AS_CHUNKS);
                  message.setChunked(true);
                  // chunkSize will be decreased as the READ_FIXED_LENGTH_CONTENT_AS_CHUNKS
                  // state reads data chunk by chunk.
                  chunkSize = getContentLength(message, -1);
                  return message;
                }
                break;
              case READ_VARIABLE_LENGTH_CONTENT:
                if (buffer.readableBytes() > maxChunkSize
                    || HttpHeaders.is100ContinueExpected(message)) {
                  // Generate HttpMessage first. HttpChunks will follow.
                  checkpoint(State.READ_VARIABLE_LENGTH_CONTENT_AS_CHUNKS);
                  message.setChunked(true);
                  return message;
                }
                break;
              default:
                throw new IllegalStateException("Unexpected state: " + nextState);
            }
          }
          // We return null here, this forces decode to be called again where we will decode the
          // content
          return null;
        }
      case READ_VARIABLE_LENGTH_CONTENT:
        {
          if (content == null) {
            content = ChannelBuffers.dynamicBuffer(channel.getConfig().getBufferFactory());
          }
          // this will cause a replay error until the channel is closed where this will read what's
          // left in the buffer
          content.writeBytes(buffer.readBytes(buffer.readableBytes()));
          return reset();
        }
      case READ_VARIABLE_LENGTH_CONTENT_AS_CHUNKS:
        {
          // Keep reading data as a chunk until the end of connection is reached.
          int chunkSize = Math.min(maxChunkSize, buffer.readableBytes());
          HttpChunk chunk = new DefaultHttpChunk(buffer.readBytes(chunkSize));

          if (!buffer.readable()) {
            // Reached to the end of the connection.
            reset();
            if (!chunk.isLast()) {
              // Append the last chunk.
              return new Object[] {chunk, HttpChunk.LAST_CHUNK};
            }
          }
          return chunk;
        }
      case READ_FIXED_LENGTH_CONTENT:
        {
          // we have a content-length so we just read the correct number of bytes
          readFixedLengthContent(buffer);
          return reset();
        }
      case READ_FIXED_LENGTH_CONTENT_AS_CHUNKS:
        {
          long chunkSize = this.chunkSize;
          HttpChunk chunk;
          if (chunkSize > maxChunkSize) {
            chunk = new DefaultHttpChunk(buffer.readBytes(maxChunkSize));
            chunkSize -= maxChunkSize;
          } else {
            assert chunkSize <= Integer.MAX_VALUE;
            chunk = new DefaultHttpChunk(buffer.readBytes((int) chunkSize));
            chunkSize = 0;
          }
          this.chunkSize = chunkSize;

          if (chunkSize == 0) {
            // Read all content.
            reset();
            if (!chunk.isLast()) {
              // Append the last chunk.
              return new Object[] {chunk, HttpChunk.LAST_CHUNK};
            }
          }
          return chunk;
        }
        /**
         * everything else after this point takes care of reading chunked content. basically, read
         * chunk size, read chunk, read and ignore the CRLF and repeat until 0
         */
      case READ_CHUNK_SIZE:
        {
          String line = readLine(buffer, maxInitialLineLength);
          int chunkSize = getChunkSize(line);
          this.chunkSize = chunkSize;
          if (chunkSize == 0) {
            checkpoint(State.READ_CHUNK_FOOTER);
            return null;
          } else if (chunkSize > maxChunkSize) {
            // A chunk is too large. Split them into multiple chunks again.
            checkpoint(State.READ_CHUNKED_CONTENT_AS_CHUNKS);
          } else {
            checkpoint(State.READ_CHUNKED_CONTENT);
          }
        }
      case READ_CHUNKED_CONTENT:
        {
          assert chunkSize <= Integer.MAX_VALUE;
          HttpChunk chunk = new DefaultHttpChunk(buffer.readBytes((int) chunkSize));
          checkpoint(State.READ_CHUNK_DELIMITER);
          return chunk;
        }
      case READ_CHUNKED_CONTENT_AS_CHUNKS:
        {
          long chunkSize = this.chunkSize;
          HttpChunk chunk;
          if (chunkSize > maxChunkSize) {
            chunk = new DefaultHttpChunk(buffer.readBytes(maxChunkSize));
            chunkSize -= maxChunkSize;
          } else {
            assert chunkSize <= Integer.MAX_VALUE;
            chunk = new DefaultHttpChunk(buffer.readBytes((int) chunkSize));
            chunkSize = 0;
          }
          this.chunkSize = chunkSize;

          if (chunkSize == 0) {
            // Read all content.
            checkpoint(State.READ_CHUNK_DELIMITER);
          }

          if (!chunk.isLast()) {
            return chunk;
          }
        }
      case READ_CHUNK_DELIMITER:
        {
          for (; ; ) {
            byte next = buffer.readByte();
            if (next == HttpCodecUtil.CR) {
              if (buffer.readByte() == HttpCodecUtil.LF) {
                checkpoint(State.READ_CHUNK_SIZE);
                return null;
              }
            } else if (next == HttpCodecUtil.LF) {
              checkpoint(State.READ_CHUNK_SIZE);
              return null;
            }
          }
        }
      case READ_CHUNK_FOOTER:
        {
          HttpChunkTrailer trailer = readTrailingHeaders(buffer);
          if (maxChunkSize == 0) {
            // Chunked encoding disabled.
            return reset();
          } else {
            reset();
            // The last chunk, which is empty
            return trailer;
          }
        }
      default:
        {
          throw new Error("Shouldn't reach here.");
        }
    }
  }