@Override
    protected void encode(ChannelHandlerContext ctx, Object msg, List<Object> out)
        throws Exception {
      com.alibaba.dubbo.remoting.buffer.ChannelBuffer buffer =
          com.alibaba.dubbo.remoting.buffer.ChannelBuffers.dynamicBuffer(1024);
      NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
      try {
        codec.encode(channel, buffer, msg);
      } finally {
        NettyChannel.removeChannelIfDisconnected(ctx.channel());
      }

      out.add(Unpooled.wrappedBuffer(buffer.toByteBuffer()));
    }
Пример #2
0
  protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byte[] header)
      throws IOException {
    // check magic number.
    if (readable > 0 && header[0] != MAGIC_HIGH || readable > 1 && header[1] != MAGIC_LOW) {
      int length = header.length;
      if (header.length < readable) {
        header = Bytes.copyOf(header, readable);
        buffer.readBytes(header, length, readable - length);
      }
      for (int i = 1; i < header.length - 1; i++) {
        if (header[i] == MAGIC_HIGH && header[i + 1] == MAGIC_LOW) {
          buffer.readerIndex(buffer.readerIndex() - header.length + i);
          header = Bytes.copyOf(header, i);
          break;
        }
      }
      return super.decode(channel, buffer, readable, header);
    }
    // check length.
    if (readable < HEADER_LENGTH) {
      return DecodeResult.NEED_MORE_INPUT;
    }

    // get data length.
    int len = Bytes.bytes2int(header, 12);
    checkPayload(channel, len);

    int tt = len + HEADER_LENGTH;
    if (readable < tt) {
      return DecodeResult.NEED_MORE_INPUT;
    }

    // limit input stream.
    ChannelBufferInputStream is = new ChannelBufferInputStream(buffer, len);

    try {
      return decodeBody(channel, is, header);
    } finally {
      if (is.available() > 0) {
        try {
          if (logger.isWarnEnabled()) {
            logger.warn("Skip input stream " + is.available());
          }
          StreamUtils.skipUnusedStream(is);
        } catch (IOException e) {
          logger.warn(e.getMessage(), e);
        }
      }
    }
  }
Пример #3
0
  protected void encodeRequest(Channel channel, ChannelBuffer buffer, Request req)
      throws IOException {
    Serialization serialization = getSerialization(channel);
    // header.
    byte[] header = new byte[HEADER_LENGTH];
    // set magic number.
    Bytes.short2bytes(MAGIC, header);

    // set request and serialization flag.
    header[2] = (byte) (FLAG_REQUEST | serialization.getContentTypeId());

    if (req.isTwoWay()) header[2] |= FLAG_TWOWAY;
    if (req.isEvent()) header[2] |= FLAG_EVENT;

    // set request id.
    Bytes.long2bytes(req.getId(), header, 4);

    // encode request data.
    int savedWriteIndex = buffer.writerIndex();
    buffer.writerIndex(savedWriteIndex + HEADER_LENGTH);
    ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer);
    ObjectOutput out = serialization.serialize(channel.getUrl(), bos);
    try {
      if (req.isEvent()) {
        encodeEventData(channel, out, req.getData());
      } else {
        encodeRequestData(channel, out, req.getData());
      }
      out.flushBuffer();
    } finally {
      // modified by lishen
      if (out instanceof Cleanable) {
        ((Cleanable) out).cleanup();
      }
    }

    bos.flush();
    bos.close();
    int len = bos.writtenBytes();
    checkPayload(channel, len);
    Bytes.int2bytes(len, header, 12);

    // write
    buffer.writerIndex(savedWriteIndex);
    buffer.writeBytes(header); // write header.
    buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len);
  }
Пример #4
0
  public void encode(Channel channel, ChannelBuffer buffer, Object msg) throws IOException {
    if (msg instanceof Request) {
      encodeRequest(channel, buffer, (Request) msg);
    } else if (msg instanceof Response) {
      encodeResponse(channel, buffer, (Response) msg);
    } else {
      super.encode(channel, buffer, msg);
    }

    // TODO modified by lishen
    //        System.out.println(">>>>>>>>>>>>>>>>>>>>>> the resulting byte size of encoding is " +
    // buffer.readableBytes());
    if (logger.isTraceEnabled()) {
      logger.trace("the resulting byte size of encoding is " + buffer.readableBytes());
    }
  }
    @Override
    public void channelRead0(ChannelHandlerContext ctx, ByteBuf input) throws Exception {

      int readable = input.readableBytes();
      if (readable <= 0) {
        return;
      }

      com.alibaba.dubbo.remoting.buffer.ChannelBuffer message;
      if (buffer.readable()) {
        if (buffer instanceof DynamicChannelBuffer) {
          buffer.writeBytes(input.nioBuffer());
          message = buffer;
        } else {
          int size = buffer.readableBytes() + input.readableBytes();
          message =
              com.alibaba.dubbo.remoting.buffer.ChannelBuffers.dynamicBuffer(
                  size > bufferSize ? size : bufferSize);
          message.writeBytes(buffer, buffer.readableBytes());
          message.writeBytes(input.nioBuffer());
        }
      } else {
        message = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.wrappedBuffer(input.nioBuffer());
      }

      NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
      Object msg;
      int saveReaderIndex;

      try {
        // decode object.
        do {
          saveReaderIndex = message.readerIndex();
          try {
            msg = codec.decode(channel, message);
          } catch (IOException e) {
            buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
            throw e;
          }
          if (msg == Codec2.DecodeResult.NEED_MORE_INPUT) {
            message.readerIndex(saveReaderIndex);
            break;
          } else {
            if (saveReaderIndex == message.readerIndex()) {
              buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
              throw new IOException("Decode without read data.");
            }
            if (msg != null) {
              ctx.fireChannelRead(msg);
            }
          }
        } while (message.readable());
      } finally {
        if (message.readable()) {
          message.discardReadBytes();
          buffer = message;
        } else {
          buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
        }
        NettyChannel.removeChannelIfDisconnected(ctx.channel());
      }
    }
Пример #6
0
 public Object decode(Channel channel, ChannelBuffer buffer) throws IOException {
   int readable = buffer.readableBytes();
   byte[] header = new byte[Math.min(readable, HEADER_LENGTH)];
   buffer.readBytes(header);
   return decode(channel, buffer, readable, header);
 }
Пример #7
0
  protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response res)
      throws IOException {
    try {
      Serialization serialization = getSerialization(channel);
      // header.
      byte[] header = new byte[HEADER_LENGTH];
      // set magic number.
      Bytes.short2bytes(MAGIC, header);
      // set request and serialization flag.
      header[2] = serialization.getContentTypeId();
      if (res.isHeartbeat()) header[2] |= FLAG_EVENT;
      // set response status.
      byte status = res.getStatus();
      header[3] = status;
      // set request id.
      Bytes.long2bytes(res.getId(), header, 4);

      int savedWriteIndex = buffer.writerIndex();
      buffer.writerIndex(savedWriteIndex + HEADER_LENGTH);
      ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer);
      ObjectOutput out = serialization.serialize(channel.getUrl(), bos);
      try {
        // encode response data or error message.
        if (status == Response.OK) {
          if (res.isHeartbeat()) {
            encodeHeartbeatData(channel, out, res.getResult());
          } else {
            encodeResponseData(channel, out, res.getResult());
          }
        } else out.writeUTF(res.getErrorMessage());
        out.flushBuffer();
      } finally {
        // modified by lishen
        if (out instanceof Cleanable) {
          ((Cleanable) out).cleanup();
        }
      }

      bos.flush();
      bos.close();

      int len = bos.writtenBytes();
      checkPayload(channel, len);
      Bytes.int2bytes(len, header, 12);
      // write
      buffer.writerIndex(savedWriteIndex);
      buffer.writeBytes(header); // write header.
      buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len);
    } catch (Throwable t) {
      // 发送失败信息给Consumer,否则Consumer只能等超时了
      if (!res.isEvent() && res.getStatus() != Response.BAD_RESPONSE) {
        try {
          // FIXME 在Codec中打印出错日志?在IoHanndler的caught中统一处理?
          logger.warn(
              "Fail to encode response: "
                  + res
                  + ", send bad_response info instead, cause: "
                  + t.getMessage(),
              t);

          Response r = new Response(res.getId(), res.getVersion());
          r.setStatus(Response.BAD_RESPONSE);
          r.setErrorMessage(
              "Failed to send response: " + res + ", cause: " + StringUtils.toString(t));
          channel.send(r);

          return;
        } catch (RemotingException e) {
          logger.warn(
              "Failed to send bad_response info back: " + res + ", cause: " + e.getMessage(), e);
        }
      }

      // 重新抛出收到的异常
      if (t instanceof IOException) {
        throw (IOException) t;
      } else if (t instanceof RuntimeException) {
        throw (RuntimeException) t;
      } else if (t instanceof Error) {
        throw (Error) t;
      } else {
        throw new RuntimeException(t.getMessage(), t);
      }
    }
  }