apache / dubbo

The java implementation of Apache Dubbo. An RPC and microservice framework.
https://dubbo.apache.org/
Apache License 2.0
40.48k stars 26.43k forks source link

Hessian lite 3.2.5 cannot readInputStream from Hessian2Input #4051

Closed haiyang1985 closed 3 years ago

haiyang1985 commented 5 years ago

Environment

Steps to reproduce this issue

We are going to support Google PB serialization with Hessian2 as delegate to write buffer to channel. But, the readInputStream cannot parse the tag from the BytesOutputStream.

  1. write stream direct to Hessian2Output BytesOutputStream.
    
    protected AbstractProtobufObjectOutput(OutputStream os) {
    this.delegate = new Hessian2ObjectOutput(os);
    }

private void writeStream(Object obj) throws IOException { Hessian2ObjectOutput hessian2ObjectOutput = (Hessian2ObjectOutput) delegate; OutputStream outputStream = hessian2ObjectOutput.getOutput().getBytesOutputStream(); protobufUtil.serializeWithProtobuf(obj, outputStream); }

2. read the stream from the Hessian2Input readInputStream.

protected AbstractProtobufObjectInput(InputStream is) {
  this.delegate = new Hessian2ObjectInput(is);
}

<T> T deserializeWithStream(Class<T> clazz)
        throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
  Hessian2ObjectInput input = (Hessian2ObjectInput) delegate;
  InputStream inputStream = input.getOutput().readInputStream();
  return deserializeWithProtobuf(inputStream, clazz);
}

Pls. provide [GitHub address] to reproduce this issue.

### Expected Result
Google Protobuf should be able to read inputStream from Hessian2Input readInputStream.

### Actual Result
The tag value should be 'B' or 'b', actually it's not.

@Override public InputStream readInputStream() throws IOException { int tag = read();

switch (tag) {
   case 'B':
   case 'b':
        _isLastChunk = tag == 'B';
        _chunkLength = (read() << 8) + read();
        break;

    default:
        throw expect("binary", tag);

}

return new ReadInputStream();

}

From the Hessian2Output's BytesOutputStream, we are able to see write 'A' for continue, but 'B' for close.

@Override public void write(byte[] buffer, int offset, int length) throws IOException { while (length > 0) { int sublen = SIZE - _offset;

    if (length < sublen)
        sublen = length;

    if (sublen > 0) {
        System.arraycopy(buffer, offset, _buffer, _offset, sublen);
        _offset += sublen;
    }

    length -= sublen;
    offset += sublen;

    if (SIZE <= _offset) {
        int chunkLength = (_offset - _startOffset) - 3;

        _buffer[_startOffset] = (byte) BC_BINARY_CHUNK;
        _buffer[_startOffset + 1] = (byte) (chunkLength >> 8);
        _buffer[_startOffset + 2] = (byte) (chunkLength);

        Hessian2Output.this.flush();

        _startOffset = _offset;
        _offset += 3;
    }
}

}

@Override public void close() throws IOException { int startOffset = _startOffset; _startOffset = -1;

if (startOffset < 0)
    return;

int length = (_offset - startOffset) - 3;

_buffer[startOffset] = (byte) 'B';
_buffer[startOffset + 1] = (byte) (length >> 8);
_buffer[startOffset + 2] = (byte) (length);

Hessian2Output.this.flush();

}


If there is an exception, please attach the exception trace:

Just put your stack trace here!

chickenlj commented 4 years ago

How do protobufUtil.serializeWithProtobuf(obj, outputStream); and protobufUtil.deserializeWithProtobuf(inputStream, clazz); work?

chickenlj commented 4 years ago

If we write and read bytes in or out Hessian's OutputStream and InputStream directly, is there any rule we should follow? for example, write some flags to indicate Hessian how to work properly?

chickenlj commented 4 years ago

Try to call outstream.close () everytime.

CrazyHZM commented 3 years ago

No feedback for a long time, please close the issue temporarily. If there is still a problem, you can reopen it.