hxb
2022-03-21 0188dee359636723190f0f67a6b674b7b08f7bef
HDLSDK/hdl-connect/src/main/java/com/hdl/sdk/connect/protocol/LinkMessageDecoder.java
@@ -1,6 +1,13 @@
package com.hdl.sdk.connect.protocol;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.google.gson.internal.bind.DateTypeAdapter;
import com.hdl.sdk.common.utils.LogUtils;
import com.hdl.sdk.connect.config.HDLLinkConfig;
import com.hdl.sdk.common.event.EventDispatcher;
@@ -11,6 +18,7 @@
import com.hdl.sdk.socket.codec.ByteToMessageDecoder;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
/**
@@ -22,77 +30,228 @@
    private final List<Byte> bytes;
    private final byte[] head = "Topic:".getBytes();
    private final byte[] body = "\r\n\r\n".getBytes();
//    private final byte[] body = "\r\n\r\n".getBytes();
    public LinkMessageDecoder() {
        this.bytes = new ArrayList<>();
    }
    @Override
    protected LinkResponse decoder(Object msg) throws Exception {
        LinkResponse response = new LinkResponse();
        if (msg instanceof byte[]) {
            //解析流
            byte[] data = (byte[]) msg;
            bytes.addAll(ByteUtils.toByteList(data));
            byte[] byteArray = ByteUtils.toByteArray(bytes);
            int headIndex = ByteUtils.getByteIndexOf(byteArray, head);
            if (headIndex > 0) {
                //移动到head 开始位置
                bytes.subList(0, headIndex).clear();
                byteArray = ByteUtils.toByteArray(bytes);
    /// <summary>
    /// 获取内容长度
    /// </summary>
    /// <param name="topMsgs"></param>
    /// <returns></returns>
    int getLenght(String[] topMsgs) {
        for (int i = 0; i < topMsgs.length; i++) {
            String topMsg = topMsgs[i].trim();
            if (topMsg.startsWith("Length:")) {
                return Integer.parseInt(topMsg.replace("Length:", ""));
            }
        }
        //找不到长度
        return -1;
    }
            int bodyIndex = ByteUtils.getByteIndexOf(byteArray, body);
            if (bodyIndex < 0) {
                //头部未获取完成
                return null;
    /// <summary>
    /// 获取主题
    /// </summary>
    /// <param name="topMsgs"></param>
    /// <returns></returns>
    private String getTopic(String[] topMsgs) {
        for (int i = 0; i < topMsgs.length; i++) {
            String topMsg = topMsgs[i].trim();
            if (topMsg.startsWith("Topic:")) {
                return topMsg.replace("Topic:", "");
            }
            int bodyStartIndex = bodyIndex + body.length;
        }
        //找不到主题
        return null;
    }
            //解析头部
            ProtocolParse parse = new ProtocolParse(byteArray);
            response.setTopic(parse.getTopic());
    /**
     * 获取数据的开始位置
     *
     * @param arrayList 接收到的所有数据
     * @return 数据位的开始索引
     */
    int getDataIndex(List<Byte> arrayList) {
        byte r = (byte) '\r';
        byte n = (byte) '\n';
        for (int i = 0; i < arrayList.size(); i++) {
            //找出数据内容前面的两个换行
            if (3 <= i && arrayList.get(i - 3) == r && arrayList.get(i - 2) == n && arrayList.get(i - 1) == r && arrayList.get(i) == n) {
                //剩余的数据
                return i + 1;
            }
        }
        return -1;
    }
            int bodyLength = parse.getLength();
            if (bodyLength > 0) {
                if (byteArray.length >= bodyLength + bodyStartIndex) {
                    byte[] body = ByteUtils.getRangeBytes(bytes, bodyStartIndex, bodyStartIndex + bodyLength);
    void initReceiveData(List<Byte> list) {
                    if (HDLLinkConfig.getInstance().ifNeedEncrypt(response.getTopic())) {
                        //需要解密
                        byte[] bodyBytes = AesUtil.aesDecrypt(body, HDLLinkConfig.getInstance().getLocalSecret());
//                        byte[] bodyBytes = AESUtils.decryptAES(body,AuthenticateConfig.getInstance().getLocalSecret());
                        if (bodyBytes != null) {
                            response.setData(new String(bodyBytes, "utf-8"));
//                            LogUtils.i("TAG", "解密 主题:"+response.getTopic()+ " body: "+response.getData());
                        } else {
                            //解密失败,返回原数据
                            response.setData(new String(body, "utf-8"));
                            LogUtils.e( "解密失败");
                        }
                    } else {
                        response.setData(new String(body, "utf-8"));
                    }
                    if (byteArray.length >= bodyLength + bodyStartIndex) {
                        //保存余留
                        byte[] remaining = ByteUtils.getRangeBytes(bytes, bodyStartIndex + bodyLength, byteArray.length);
                        bytes.clear();
                        for (byte b : remaining) {
                            bytes.add(b);
                        }
                    }
                    //解析完成,topic发送一次
                    EventDispatcher.getInstance().post(response.getTopic(), response);
                    return response;
        int index = 0;
        boolean isMatch = false;
        for (; index < list.size() - head.length; index++) {
            isMatch = true;
            for (int j = 0, k = 0; j < head.length; j++, k++) {
                if (head[j] != list.get(index + k)) {
                    isMatch = false;
                    break;
                }
            } else if (bodyLength == 0) {
                //body为空
                return response;
            }
            if (isMatch) {
                break;
            }
        }
        if (0 < index && isMatch) {
            List<Byte> tempList = new ArrayList<Byte>();
            for (int i = index; i < list.size(); i++) {
                tempList.add(list.get(i));
            }
            list.clear();
            for(int i=0;i<tempList.size();i++){
                list.add(tempList.get(i));
            }
        }
    }
    @Override
    protected synchronized LinkResponse decoder(Object msg,String ipaddress) throws Exception {
        if (msg instanceof byte[]) {
            bytes.addAll(ByteUtils.toByteList((byte[]) msg));
            //如果多条命令打包在一条数据中,都需要处理完
            while (true) {
                initReceiveData(bytes);
                byte[] recevieBytes = ByteUtils.toByteArray(bytes);
                String data = new String(recevieBytes);
                String[] topMsgs = data.split("\r\n");
                String topic = getTopic(topMsgs);
                if (topic == null) {
                    break;
                }
                int lenght = getLenght(topMsgs);
                if (lenght <= 0) {
                    //头部数据还没有接收完成
                    break;
                }
                //是否已经获取完整所有的数据
                byte[] body = new byte[lenght];
                int index = getDataIndex(bytes);
                if (bytes.size() < index + lenght) {
                    //当前数据还没有接收完成
                    break;
                }
                //复制出body数据
                System.arraycopy(recevieBytes, index, body, 0, body.length);
                //保留剩余的数据,以次用
                bytes.clear();
                for (int i = index + lenght; i < recevieBytes.length; i++) {
                    bytes.add(recevieBytes[i]);
                }
                LinkResponse response = new LinkResponse();
                response.setSource_ipAddress(ipaddress);
                response.setTopic(topic);
                if (HDLLinkConfig.getInstance().ifNeedEncrypt(response.getTopic())) {
                    //需要解密
                    byte[] bodyBytes = AesUtil.aesDecrypt(body, HDLLinkConfig.getInstance().getLocalSecret());
                    if (bodyBytes != null) {
                        body = bodyBytes;
                    } else {
                        try {
                            //之前的版本这块是明文的
                            if (!topic.contains("heartbeat_reply")) {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                                    LogUtils.e("解密失败,数据内容是:\r\n" + Base64.getEncoder().encodeToString(body));
                                else {
                                    LogUtils.e("解密失败,数据内容是:\r\n" + new String(body, "utf-8"));
                                }
                            }
                        } catch (Exception e) {
                        }
                    }
                }
                String bodyString = new String(body, "utf-8");
                response.setData(bodyString);
                LogUtils.i( "接收到数据:" + response.getTopic() + "\r\n" + response.getData());
                //非正常数据,返回
                if (!((bodyString.startsWith("{") &&bodyString.endsWith("}"))
                        || (bodyString.startsWith("[")&&bodyString.endsWith("]")))) {
                    continue;
                }
                //解析完成,topic发送一次
                EventDispatcher.getInstance().post(response.getTopic(), response);
            }
            return null;
//            //解析流
//            byte[] data = (byte[]) msg;
//            bytes.addAll(ByteUtils.toByteList(data));
//
//            byte[] byteArray = ByteUtils.toByteArray(bytes);
//            int headIndex = ByteUtils.getByteIndexOf(byteArray, head);
//            if (headIndex > 0) {
//                //移动到head 开始位置
//                bytes.subList(0, headIndex).clear();
//                byteArray = ByteUtils.toByteArray(bytes);
//            }
//
//            int bodyIndex = ByteUtils.getByteIndexOf(byteArray, body);
//            if (bodyIndex < 0) {
//                //头部未获取完成
//                return null;
//            }
//            int bodyStartIndex = bodyIndex + body.length;
//
//            //解析头部
//            ProtocolParse parse = new ProtocolParse(byteArray);
//            response.setTopic(parse.getTopic());
//
//            int bodyLength = parse.getLength();
//            if (bodyLength > 0) {
//                if (byteArray.length >= bodyLength + bodyStartIndex) {
//                    byte[] body = ByteUtils.getRangeBytes(bytes, bodyStartIndex, bodyStartIndex + bodyLength);
//
//                    if (HDLLinkConfig.getInstance().ifNeedEncrypt(response.getTopic())) {
//                        //需要解密
//                        byte[] bodyBytes = AesUtil.aesDecrypt(body, HDLLinkConfig.getInstance().getLocalSecret());
////                        byte[] bodyBytes = AESUtils.decryptAES(body,AuthenticateConfig.getInstance().getLocalSecret());
//                        if (bodyBytes != null) {
//                            response.setData(new String(bodyBytes, "utf-8"));
////                            LogUtils.i("TAG", "解密 主题:"+response.getTopic()+ " body: "+response.getData());
//                        } else {
//                            //解密失败,返回原数据
//                            response.setData(new String(body, "utf-8"));
//                        }
//
//                    } else {
//                        response.setData(new String(body, "utf-8"));
//                    }
//
//                    if (byteArray.length >= bodyLength + bodyStartIndex) {
//                        //保存余留
//                        byte[] remaining = ByteUtils.getRangeBytes(bytes, bodyStartIndex + bodyLength, byteArray.length);
//                        bytes.clear();
//                        for (byte b : remaining) {
//                            bytes.add(b);
//                        }
//                    }
//                    //解析完成,topic发送一次
//                    EventDispatcher.getInstance().post(response.getTopic(), response);
//                    return response;
//                }
//            } else if (bodyLength == 0) {
//                //body为空
//                return response;
//            }
        }
        return null;