/** * 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 srpc; import com.google.protobuf.ByteString; import com.google.protobuf.CodedInputStream; import com.google.protobuf.GeneratedMessage; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.List; import java.util.regex.Pattern; /** * Created by Administrator on 2016/5/6. */ public class WholePackage { private long sequence; private String methodNameBeCalled; private byte[] bodyBytes; public long getSequence() { return sequence; } public void setSequence(long sequence) { this.sequence = sequence; } public String getMethodNameBeCalled() { return methodNameBeCalled; } public void setMethodNameBeCalled(String methodNameBeCalled) { this.methodNameBeCalled = methodNameBeCalled; } public byte[] getBodyBytes() { return bodyBytes; } public void setBodyBytes(byte[] bodyBytes) { this.bodyBytes = bodyBytes; } //����ת��Ϊ������ֽ����� static private byte[] int2Bytes(int i) { byte[] b = new byte[4]; int v = 256 * 256 * 256; for (int j = 0; j < 3; j++) { b[j] = (byte)(i / v); i = i % v; v = v / 256; } b[3] = (byte)i; return b; } //������ֽ�bufת��Ϊ����int static private int bytes2int(byte[] buf) { int v = 0; int b0 = buf[0]; if (b0 < 0) { b0 += 256;} int b1 = buf[1]; if (b1 < 0) { b1 += 256;} int b2 = buf[2]; if (b2 < 0) { b2 += 256;} int b3 = buf[3]; if (b3 < 0) { b3 += 256;} v = b0 * (256*256*256) + b1 * (256*256) + b2*256 + b3; return v; } private Head.CRpcHead buildHead() { Head.CRpcHead.Builder b = Head.CRpcHead.newBuilder(); b.setSequence( sequence); b.setMethodName(ByteString.copyFrom(methodNameBeCalled.getBytes())); return b.build(); } public byte[] pack() throws Exception { //���ĸ�ʽ "(head_len body_len head body)" Head.CRpcHead head = buildHead(); int sz = 2 + 4 + 4 + head.getSerializedSize()+bodyBytes.length; byte[] result = new byte[sz]; byte[] head_len = int2Bytes(head.getSerializedSize()); byte[] body_len = int2Bytes(bodyBytes.length); byte[] head_bytes = head.toByteArray(); int offset = 0; result[offset++] = 0x28; // ( for (int i = 0; i < 4; ++i, offset++) // head_len { result[offset] = head_len[i]; } for (int i = 0; i < 4; ++i, offset++) // body_len { result[offset] = body_len[i]; } for (int i = 0; i < head_bytes.length; ++i, ++offset) // head { result[offset] = head_bytes[i]; } for (int i = 0; i < bodyBytes.length; ++i, ++offset) // body { result[offset] = bodyBytes[i]; } result[offset++] = 0x29; // ) if (offset != sz) { throw new Exception("length mismatch!"); } return result; } public void unpack(final byte[] raw) throws Exception { if (raw.length < 10 || raw[0] != 0x28 ) { throw new Exception("raw data is invalid response."); } byte[] lenBytes = new byte[4]; for (int i = 0; i < 4; i++) { lenBytes[i] = raw[1+i]; } int headLen = bytes2int(lenBytes); for (int i = 0; i < 4; i++) { lenBytes[i] = raw[5+i]; } int bodyLen = bytes2int(lenBytes); if (raw[10+headLen+bodyLen-1] != 0x29) { throw new Exception("raw data is invalid response."); } if ( (10 + headLen + bodyLen ) > raw.length) { throw new Exception("raw data length is invalid."); } byte[] headBytes = new byte[headLen]; bodyBytes = new byte[bodyLen]; for (int i = 0; i < headLen; i++) { headBytes[i] = raw[9+i]; } for (int i = 0; i < bodyLen; i++) { bodyBytes[i] = raw[9+headLen+i]; } Head.CRpcHead head = Head.CRpcHead.parseFrom(headBytes); sequence = head.getSequence(); methodNameBeCalled = new String(head.getMethodName().toByteArray()); return; } //用于流式传输(例如tcp)情况下,判断buf里是否获得了一个完整的package // 返回值:小于0表示格式非法 等于0表示没有收完整还需要继续接收 大于0表示收到了完整的报文,报文长度作为返回值 static public int isWholePackage(byte[] buf, int offset, int len) { if (buf[offset] != 0x28) { return -1; } if (len < 10) { return -1; } byte[] lenBytes = new byte[4]; for (int i = 0; i < 4; i++) { lenBytes[i] = buf[offset+1+i]; } int headLen = bytes2int(lenBytes); if (headLen < 0) { return -1;} for (int i = 0; i < 4; i++) { lenBytes[i] = buf[offset+5+i]; } int bodyLen = bytes2int(lenBytes); if (bodyLen < 0) { return -1;} if ( ( 2+4+4+headLen+bodyLen) <= len) { return ( 2+4+4+headLen+bodyLen); } else { return 0; } } }