blob: 9d42d99748528557c72772dd772a1a55c0760df9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import debug from 'debug';
import Hessian from 'hessian.js';
import {fromBytes8} from '../common/byte';
import {DubboDecodeError} from '../common/err';
import {IDubboResponse} from '../types';
import {
DEFAULT_DUBBO_PROTOCOL_VERSION,
DUBBO_RESPONSE_BODY_FLAG,
DUBBO_RESPONSE_STATUS,
DUBBO_FLAG_REQUEST,
DUBBO_FLAG_TWOWAY,
DUBBO_HEADER_LENGTH,
HESSIAN2_SERIALIZATION_CONTENT_ID,
DUBBO_FLAG_EVENT,
} from './constants';
import Request from './request';
const log = debug('dubbo:hessian:DecoderV2');
export function decodeDubboRequest(buff: Buffer): Request {
const flag = buff[2];
// get requestId
const requestId = fromBytes8(buff.slice(4, 12));
log('decode requestId -> ', requestId);
const req = new Request(requestId);
// decode request
if ((flag & DUBBO_FLAG_REQUEST) !== 0) {
req.version = DEFAULT_DUBBO_PROTOCOL_VERSION;
req.twoWay = (flag & DUBBO_FLAG_TWOWAY) !== 0;
if ((flag & DUBBO_FLAG_EVENT) !== 0) {
req.event = true;
}
const decoder = new Hessian.DecoderV2(buff.slice(DUBBO_HEADER_LENGTH));
if (req.event) {
// decode event
} else {
// decode request
const dubboVersion = decoder.read();
req.version = dubboVersion;
const attachments = new Map();
const path = decoder.read();
const version = decoder.read();
const methodName = decoder.read();
const desc = decoder.read();
}
// const dubboInterface = body.read();
// const version = body.read();
// const methodName = body.read();
// const parameterTypes: string = body.read();
// const len: number = parameterTypes.split(';').filter(Boolean).length;
// const args: Array<any> = [];
// for (let i = 0; i < len; i++) {
// args.push(body.read());
// }
// const attachments = body.read();
// req = {
// requestId,
// twoWay,
// dubboVersion,
// dubboInterface,
// version,
// methodName,
// parameterTypes,
// args,
// attachments,
// };
}
return req;
}
//com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.encodeResponse/decode
export function decodeDubboResponse<T>(bytes: Buffer): IDubboResponse<T> {
let res = null;
let err = null;
let attachments = {};
// set request and serialization flag.
//字节位置[4-11] 8 bytes
const requestIdBuff = bytes.slice(4, 12);
const requestId = fromBytes8(requestIdBuff);
log(`decode parse requestId: ${requestId}`);
const typeId = bytes[2];
if (typeId !== HESSIAN2_SERIALIZATION_CONTENT_ID) {
return {
err: new DubboDecodeError(`only support hessian serialization`),
res: null,
attachments,
requestId,
};
}
// get response status.
const status = bytes[3];
log(
`parse response status: ${status}, DUBBO_RESPONSE_STATUS: ${
DUBBO_RESPONSE_STATUS[DUBBO_RESPONSE_STATUS.OK]
}`,
);
if (status != DUBBO_RESPONSE_STATUS.OK) {
return {
err: new DubboDecodeError(bytes.slice(DUBBO_HEADER_LENGTH).toString()),
res: null,
attachments,
requestId,
};
}
//com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcResult
const body = new Hessian.DecoderV2(bytes.slice(DUBBO_HEADER_LENGTH));
const flag = body.readInt();
log(
`parse dubbo response body flag: ${flag}, DUBBO_RESPONSE_BODY_FLAG: ${
DUBBO_RESPONSE_BODY_FLAG[flag]
}`,
);
switch (flag) {
case DUBBO_RESPONSE_BODY_FLAG.RESPONSE_VALUE:
err = null;
res = body.read();
attachments = {};
break;
case DUBBO_RESPONSE_BODY_FLAG.RESPONSE_NULL_VALUE:
err = null;
res = null;
attachments = {};
break;
case DUBBO_RESPONSE_BODY_FLAG.RESPONSE_WITH_EXCEPTION:
const exception = body.read();
err =
exception instanceof Error
? exception
: new DubboDecodeError(exception);
res = null;
attachments = {};
break;
case DUBBO_RESPONSE_BODY_FLAG.RESPONSE_NULL_VALUE_WITH_ATTACHMENTS:
err = null;
res = null;
attachments = body.read();
break;
case DUBBO_RESPONSE_BODY_FLAG.RESPONSE_VALUE_WITH_ATTACHMENTS:
err = null;
res = body.read();
attachments = body.read();
break;
case DUBBO_RESPONSE_BODY_FLAG.RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS:
const exp = body.read();
err = exp instanceof Error ? exp : new DubboDecodeError(exp);
res = null;
attachments = body.read();
break;
default:
err = new DubboDecodeError(
`Unknown result flag, expect '0/1/2/3/4/5', get ${flag})`,
);
res = null;
}
return {
requestId,
err,
res,
attachments,
};
}