/** * Tencent is pleased to support the open source community by making MSEC available. * * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. * * Licensed under the GNU General Public 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 * * https://opensource.org/licenses/GPL-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. */ package org.msec.rpc; import com.google.protobuf.ByteString; import com.google.protobuf.MessageLite; import org.msec.net.NettyCodecUtils; import srpc.Head; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; public class SrpcProxy { RpcRequest rpcRequest = new RpcRequest(); String caller; int errno; String errmsg; long sequence; public void setMethod(String method) { rpcRequest.setMethodName(method); } public void setSequence(long seq) { rpcRequest.setSeq(seq); } public void setCaller(String caller) { this.caller = caller; } public int getErrno() { return errno; } public String getErrmsg() { return errmsg; } public long getSequence() { return sequence; } public byte[] serialize(MessageLite request) { Head.CRpcHead.Builder builder = Head.CRpcHead.newBuilder(); String serviceMethodName; if (rpcRequest.getServiceName() == null || rpcRequest.getServiceName().isEmpty()) { serviceMethodName = rpcRequest.getMethodName(); } else { serviceMethodName = rpcRequest.getServiceName() + "." + rpcRequest.getMethodName(); } builder.clear(); builder.setSequence(rpcRequest.getSeq()); builder.setColoring(0); builder.setColorId(NettyCodecUtils.generateColorId(rpcRequest.getMethodName())); builder.setFlowId(rpcRequest.getSeq() ^ builder.getColorId()); builder.setErr(0); builder.setResult(0); builder.setErrMsg(ByteString.EMPTY); builder.setCaller(ByteString.copyFromUtf8(caller)); builder.setMethodName(ByteString.copyFrom((serviceMethodName).getBytes())); builder.addCallerStack(ByteString.EMPTY); Head.CRpcHead rpcHead = builder.build(); int rpcHeadLen = rpcHead.getSerializedSize(); int rpcBodyLen = request.getSerializedSize(); int totalLen = 1 + 4 + 4 + rpcHeadLen + rpcBodyLen + 1; byte[] buffer = new byte[totalLen]; buffer[0] = '('; NettyCodecUtils.int32_to_buf(buffer, 1, rpcHeadLen); NettyCodecUtils.int32_to_buf(buffer, 5, rpcBodyLen); System.arraycopy(rpcHead.toByteArray(), 0, buffer, 5 + 4, rpcHeadLen); System.arraycopy(request.toByteArray(), 0, buffer, 5 + 4 + rpcHeadLen, rpcBodyLen); buffer[totalLen - 1] = ')'; return buffer; } //�����Ӧ���ij��� //Return value: //ret > 0: package length //ret == 0: package not complete //ret < 0: wrong package format public static int checkPackage(byte[] data, int length) { if (length < 10) { return 0; } byte stx = data[0]; if (stx != (byte)'(') { return -1; } int headLength = NettyCodecUtils.buf_to_int32(data, 1); int bodyLength = NettyCodecUtils.buf_to_int32(data, 5); int totalLength = 10 + headLength + bodyLength; if (length < totalLength) { return 0; } return totalLength; } public MessageLite deserialize(byte[] data, int length, MessageLite responseInstance) throws Exception { if (checkPackage(data, length) != length) { throw new Exception("Invalid data: maybe not complete or wrong format!"); } int headLength = NettyCodecUtils.buf_to_int32(data, 1); int bodyLength = NettyCodecUtils.buf_to_int32(data, 5); byte[] headBytes = new byte[headLength]; byte[] bodyBytes = new byte[bodyLength]; System.arraycopy(data, 9, headBytes, 0, headLength); System.arraycopy(data, 9 + headLength, bodyBytes, 0, bodyLength); Head.CRpcHead pbHead = Head.CRpcHead.parseFrom(headBytes); errno = pbHead.getErr(); sequence = pbHead.getSequence(); if (pbHead.getErrMsg() != null && !pbHead.getErrMsg().isEmpty()) { errmsg = pbHead.getErrMsg().toStringUtf8(); } else { errmsg = ""; } if (errno == 0) { return responseInstance.getParserForType().parseFrom(bodyBytes); } return null; } }