package com.sunyard.sge.database; import com.sun.jna.ptr.IntByReference; import com.sunyard.SydApiException; import com.sunyard.proto.Util; import com.sunyard.sge.bytes.BytesUtil; import com.sunyard.sge.plus.ConnectHandlerManager; import com.sunyard.sge.plus.SydLibrary; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import static com.sunyard.sge.database.SydApiBaseFunction.toBoolArray; import static com.sunyard.sge.database.SydApiBaseFunction.toIntArray; import static com.sunyard.sge.database.SydApiConfig.BATCH_SIZE; /** * 长连接的真正执行过程转发到长连接线程池中执行。 */ public class SydApiLongLinkWrap implements SydApi { private SydApiBuilder builder; public SydApiLongLinkWrap(SydApiBuilder builder) { this.builder = builder; } @Override public SydApi SYD_Short_Connect_Ex(String[] pcIpList, int[] iPortList, int iConnectTimeOut, int iDealTimeOut) { throw new UnsupportedOperationException("此对象为长连接专用"); } @Override public void SYD_Disconnect_Ex() { // pass } @Override public String SYD_SM3_Hash_ShortData(byte[] pcData) { FutureTask task = builder.getLongLinkWorks().fTask(new Callable() { @Override public String call() throws Exception { return builder.get().SYD_SM3_Hash_ShortData(pcData); } }); try { return task.get(); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public LongDataReturn SYD_SM3_Hash_LongData(byte[] pcData, int iPkgNum, String pcProcData) { FutureTask> task = builder.getLongLinkWorks().fTask(new Callable>() { @Override public LongDataReturn call() throws Exception { return builder.get().SYD_SM3_Hash_LongData(pcData, iPkgNum, pcProcData); } }); try { return task.get(); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public byte[] SYD_SM4_ShortData(int iKeyIndex, byte[] pcData, int iFlag) { FutureTask task = builder.getLongLinkWorks().fTask(new Callable() { @Override public byte[] call() throws Exception { return builder.get().SYD_SM4_ShortData(iKeyIndex, pcData, iFlag); } }); try { return task.get(); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public byte[] SYD_SM4_LongData(int iKeyIndex, byte[] pcData, int iPkgNum, int iFlag) { FutureTask task = builder.getLongLinkWorks().fTask(new Callable() { @Override public byte[] call() throws Exception { return builder.get().SYD_SM4_LongData(iKeyIndex, pcData, iPkgNum, iFlag); } }); try { return task.get(); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public LongDataReturn SYD_SM4Mac_LongData(int iKeyIndex, byte[] pcData, int iPkgNum, String pcProcData) { FutureTask> task = builder.getLongLinkWorks().fTask(new Callable>() { @Override public LongDataReturn call() throws Exception { return builder.get().SYD_SM4Mac_LongData(iKeyIndex, pcData, iPkgNum, pcProcData); } }); try { return task.get(); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public LongDataReturn SYD_SM4Mac_LongData(int iKeyIndex, byte[] pcData, int iPkgNum, String pcProcData, String pcMac) { FutureTask> task = builder.getLongLinkWorks().fTask(new Callable>() { @Override public LongDataReturn call() throws Exception { return builder.get().SYD_SM4Mac_LongData(iKeyIndex, pcData, iPkgNum, pcProcData, pcMac); } }); try { return task.get(); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public byte[] SYD_SM4Mac_ShortData(int iKeyIndex, byte[] pcData) { FutureTask task = builder.getLongLinkWorks().fTask(new Callable() { @Override public byte[] call() throws Exception { return builder.get().SYD_SM4Mac_ShortData(iKeyIndex, pcData); } }); try { return task.get(); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public boolean SYD_SM4Mac_ShortData(int iKeyIndex, byte[] pcData, byte[] pcMac) { FutureTask task = builder.getLongLinkWorks().fTask(new Callable() { @Override public Boolean call() throws Exception { return builder.get().SYD_SM4Mac_ShortData(iKeyIndex, pcData, pcMac); } }); try { return task.get(); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } private DataAndMac SYD_SM4_AllInOne(int iEncKeyIndex, int iMacKeyIndex, byte[] pcData){ try { FutureTask taskEnc = builder.getLongLinkWorks().fTask(new Callable() { @Override public byte[] call() throws Exception { return builder.get().SYD_SM4_ShortData(iEncKeyIndex, pcData, Consts.ECB_ENC); } }); byte[] enData = taskEnc.get(); FutureTask taskMac = builder.getLongLinkWorks().fTask(new Callable() { @Override public byte[] call() throws Exception { return builder.get().SYD_SM4Mac_ShortData(iMacKeyIndex, enData); } }); byte[] mac = taskMac.get(); return new DataAndMac(enData, mac); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public DataAndMac SYD_SM4_EncryptAndMac_ShortData(int iEncKeyIndex, int iMacKeyIndex, byte[] pcData) { try { if ( ! ConnectHandlerManager.isInited() ) { throw new SydApiException(-1); } int enLen = BytesUtil.calculatePaddedLength(pcData.length); byte[] encData = new byte[enLen]; byte[] mac = new byte[16]; IntByReference encDataLen = new IntByReference(encData.length); int i = SydLibrary.INSTANCE.SYD_SM4_Encrypt_Mac_ShortData( ConnectHandlerManager.getHandler(), iEncKeyIndex, iMacKeyIndex, pcData, pcData.length, encData, encDataLen, mac ); if ( 0 == i ){ byte[] data = new byte[encDataLen.getValue()]; if( data.length == encData.length ) { data = encData; } else { System.arraycopy(encData, 0, data, 0, data.length); } return new DataAndMac(data, mac); } else { throw new SydApiException(i); } // return SYD_SM4_AllInOne(iEncKeyIndex, iMacKeyIndex, pcData); // // 线程池忙, 使用单线程计算 // if( builder.getLongLinkWorks().threadPoolIsBusy() ) { // return SYD_SM4_AllInOne(iEncKeyIndex, iMacKeyIndex, pcData); // } // // // 线程池不忙,使用并发计算 // // // 将pcData拆分为两半,第一半16字节对齐 // int halfLength = pcData.length / 2; // int alignedLength = (halfLength + 15) & ~15; // 向上取整到16的倍数 // alignedLength = Math.min(alignedLength, pcData.length); // 不超过原始数据长度 // if (alignedLength < 16) { // throw new IllegalArgumentException("数据长度不足16字节,无法对齐"); // } // // // byte[] firstHalf = Arrays.copyOfRange(pcData, 0, alignedLength); // byte[] secondHalf = Arrays.copyOfRange(pcData, alignedLength, pcData.length); // // // FutureTask taskEnc1 = builder.getLongLinkWorks().fTask(new Callable() { // @Override // public byte[] call() throws Exception { // return builder.get().SYD_SM4_LongData( iEncKeyIndex, firstHalf, 1, Consts.ECB_ENC); // } // }); // FutureTask taskEnc2 = builder.getLongLinkWorks().fTask(new Callable() { // @Override // public byte[] call() throws Exception { // return builder.get().SYD_SM4_LongData( iEncKeyIndex, secondHalf, 3, Consts.ECB_ENC); // } // }); // // byte[] enData1 = taskEnc1.get(); // FutureTask> taskMac = builder.getLongLinkWorks().fTask(new Callable< LongDataReturn>() { // @Override // public LongDataReturn call() throws Exception { // return builder.get().SYD_SM4Mac_LongData(iMacKeyIndex, enData1, 1, null); // } // }); // // byte[] enData2 = taskEnc2.get(); // LongDataReturn macProc = taskMac.get(); // FutureTask> taskMac2 = builder.getLongLinkWorks().fTask(new Callable>() { // @Override // public LongDataReturn call() throws Exception { // return builder.get().SYD_SM4Mac_LongData(iMacKeyIndex, enData2, 3, macProc.getProcData()); // } // }); // LongDataReturn mac = taskMac.get(); // // // 合并密文 // byte[] enData = new byte[enData1.length + enData2.length]; // System.arraycopy(enData1, 0, enData, 0, enData1.length); // System.arraycopy(enData2, 0, enData, enData1.length, enData2.length); // // // return new DataAndMac(enData, mac.getData()); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public DataAndMacCheck SYD_SM4_CheckMacAndDecrypt_ShortData(int iEncKeyIndex, int iMacKeyIndex, byte[] pcData, byte[] macs) { try { if ( ! ConnectHandlerManager.isInited() ) { throw new SydApiException(-1); } byte[] decryptedData = new byte[pcData.length]; IntByReference decryptedDataLen = new IntByReference(decryptedData.length); int i = SydLibrary.INSTANCE.SYD_SM4_Decrypt_Mac_ShortData( ConnectHandlerManager.getHandler(), iEncKeyIndex, iMacKeyIndex, pcData, pcData.length, macs, decryptedData, decryptedDataLen ); byte[] data = new byte[decryptedDataLen.getValue()]; System.arraycopy(decryptedData, 0, data, 0, data.length); System.out.println("outlen=" + data.length); if ( 0 == i ){ return new DataAndMacCheck(data, true); } if (0x01000010 == i) { return new DataAndMacCheck(data, false); } else { throw new SydApiException(i); } } catch (Exception e) { if ( e instanceof SydApiException) { throw e; } throw new SydApiException("并行任务执行失败", 0xC101, e); } // FutureTask task = builder.getLongLinkWorks().fTask(new Callable() { // @Override // public DataAndMacCheck call() throws Exception { // return builder.get().SYD_SM4_CheckMacAndDecrypt_ShortData(iEncKeyIndex, iMacKeyIndex, pcData, mac); // } // }); // try { // return task.get(); // } catch (Exception e) { // throw new SydApiException("并行任务执行失败", 0xC101, e); // } } @Override public List SYD_SM4_EncryptAndMac_BatchData(int[] iEncKeyIndex, int[] iMacKeyIndex, List pcData) { if ( ! ConnectHandlerManager.isInited() ) { throw new SydApiException(-1); } try { int size = pcData.size(); // 准备输入参数 - 直接使用 byte[][] byte[][] pcDataArray = pcData.toArray(new byte[0][]); int[] iDataLen = pcData.stream() .mapToInt(bytes -> bytes.length) .toArray(); // 准备输出缓冲区 byte[][] pcEncData = new byte[size][]; int[] iEncDataLen = new int[size]; for (int i = 0; i < size; i++) { int maxEncLen = ((pcData.get(i).length + 15) / 16 * 16); pcEncData[i] = new byte[maxEncLen]; iEncDataLen[i] = maxEncLen; } byte[] pcMac = new byte[16]; // 调用加密函数 int result = SydLibrary.INSTANCE.SYD_SM4_Encrypt_Mac_BatchData( ConnectHandlerManager.getHandler(), iEncKeyIndex, iMacKeyIndex, pcDataArray, iDataLen, size, pcEncData, iEncDataLen, pcMac); if (0 == result) { // 转换结果为Java风格的对象列表 List results = new ArrayList<>(); for (int i = 0; i < size; i++) { results.add(new DataAndMac(pcEncData[i], pcMac)); } return results; } else { throw new SydApiException(result); } } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } // FutureTask> task = builder.getLongLinkWorks().fTask(new Callable>() { // @Override // public List call() throws Exception { // return builder.get().SYD_SM4_EncryptAndMac_BatchData(iEncKeyIndex, iMacKeyIndex, pcData); // } // }); // try { // return task.get(); // } catch (Exception e) { // throw new SydApiException("并行任务执行失败", 0xC101, e); // } } @Override public List SYD_SM4_CheckMacAndDecrypt_BatchData(int[] iEncKeyIndex, int[] iMacKeyIndex, List pcData) { int size = pcData.size(); // 准备输入参数 byte[][] pcEncData = pcData.stream() .map(DataAndMac::getData) .toArray(byte[][]::new); int[] iEncDataLen = pcData.stream() .mapToInt(d -> d.getData().length) .toArray(); byte[][] pcMac = pcData.stream() .map(d -> d.getMac()) .toArray(byte[][]::new); // 准备输出缓冲区 byte[][] pcOutData = new byte[size][]; int[] iOutDataLen = new int[size]; for (int i = 0; i < size; i++) { int maxOutLen = pcData.get(i).getData().length; pcOutData[i] = new byte[maxOutLen]; iOutDataLen[i] = maxOutLen; } int[] iCheckRet = new int[size]; // 调用解密函数 int result = SydLibrary.INSTANCE.SYD_SM4_Decrypt_Mac_BatchData( ConnectHandlerManager.getHandler(), iEncKeyIndex, iMacKeyIndex, pcEncData, iEncDataLen, pcMac, size, pcOutData, iOutDataLen, iCheckRet); if (0 == result) { // 转换结果为Java风格的对象列表 List results = new ArrayList<>(); for (int i = 0; i < size; i++) { results.add(new DataAndMacCheck(pcOutData[i], iCheckRet[i] == 0)); } return results; } else { throw new SydApiException(result); } // FutureTask> task = builder.getLongLinkWorks().fTask(new Callable>() { // @Override // public List call() throws Exception { // return builder.get().SYD_SM4_CheckMacAndDecrypt_BatchData(iEncKeyIndex, iMacKeyIndex, pcData); // } // }); // try { // return task.get(); // } catch (Exception e) { // throw new SydApiException("并行任务执行失败", 0xC101, e); // } } @Override public ISM4 initSM4(int iKeyIndex, int ende) { return new SydSM4(this, iKeyIndex, ende); } @Override public ISM3 initSM3() { return new SydSM3(this); } @Override public ISM4Mac initSM4Mac(int iKeyIndex) { return new SydSM4Mac(this, iKeyIndex); } @Override public List SYD_SM4_BatchData(int[] iKeyIndex, List pcData, int iFlag) { if ( null == iKeyIndex || null == pcData ) { throw new IllegalArgumentException("批量输入数据为 null"); } if ( iKeyIndex.length != pcData.size() ) { throw new IllegalArgumentException("批量输入数据密钥和数据数量不等"); } if ( 0 == iKeyIndex.length ) { return new ArrayList<>(); } // 将数据进行分组,防止超长。 List> dataGroups = new ArrayList<>(); List> keyGroups = new ArrayList<>(); int totalLen = 0; List curDataGroup = new ArrayList<>(); List curKeyGroup = new ArrayList<>(); for (int i = 0; i < pcData.size(); i++) { byte[] data = pcData.get(i); if (null == data) { data = new byte[0]; } if ( curDataGroup.size() > 9 // 分组小于等于 9 个 || (totalLen + data.length > BATCH_SIZE) // 总大小小于 BATCH_SIZE ) { // 扩展包 dataGroups.add(curDataGroup); keyGroups.add(curKeyGroup); curDataGroup = new ArrayList<>(); curKeyGroup = new ArrayList<>(); totalLen = 0; } curDataGroup.add(data); curKeyGroup.add(iKeyIndex[i]); totalLen += data.length; } dataGroups.add(curDataGroup); keyGroups.add(curKeyGroup); // 并发处理 List>> tasks = new ArrayList<>(); for (int i = 0; i < dataGroups.size(); i++) { int finalI = i; FutureTask> task = builder.getLongLinkWorks().fTask(new Callable>() { @Override public List call() throws Exception { SydApi api = builder.get(); return api.SYD_SM4_BatchData(toIntArray(keyGroups.get(finalI)), dataGroups.get(finalI), iFlag); } }); tasks.add(task); } try { List ret = new ArrayList<>(); for (FutureTask> t : tasks) { ret.addAll(t.get()); } return ret; } catch (ExecutionException e) { Throwable cause = e.getCause(); if (cause instanceof SydApiException) { throw (SydApiException) cause; } throw new SydApiException("并行任务执行失败", 0xC101); } catch (Exception e) { throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public List SYD_SM4Mac_BatchData(int[] iKeyIndex, List pcData) { if ( null == iKeyIndex || null == pcData ) { throw new IllegalArgumentException("批量输入数据为 null"); } if ( iKeyIndex.length != pcData.size() ) { throw new IllegalArgumentException("批量输入数据密钥和数据数量不等"); } if ( 0 == iKeyIndex.length ) { return new ArrayList<>(); } // 将数据进行分组,防止超长。 List> dataGroups = new ArrayList<>(); List> keyGroups = new ArrayList<>(); int totalLen = 0; List curDataGroup = new ArrayList<>(); List curKeyGroup = new ArrayList<>(); for (int i = 0; i < pcData.size(); i++) { byte[] data = pcData.get(i); if (null == data) { data = new byte[0]; } if ( curDataGroup.size() > 9 // 分组小于等于 9 个 || (totalLen + data.length > BATCH_SIZE) // 总大小小于 BATCH_SIZE ) {// 扩展包 dataGroups.add(curDataGroup); keyGroups.add(curKeyGroup); curDataGroup = new ArrayList<>(); curKeyGroup = new ArrayList<>(); totalLen = 0; } curDataGroup.add(data); curKeyGroup.add(iKeyIndex[i]); totalLen += data.length; } dataGroups.add(curDataGroup); keyGroups.add(curKeyGroup); // 并发处理 List>> tasks = new ArrayList<>(); for (int i = 0; i < dataGroups.size(); i++) { int finalI = i; FutureTask> task = builder.getLongLinkWorks().fTask(new Callable>() { @Override public List call() throws Exception { SydApi api = builder.get(); return api.SYD_SM4Mac_BatchData(toIntArray(keyGroups.get(finalI)), dataGroups.get(finalI)); } }); tasks.add(task); } try { List ret = new ArrayList<>(); for (FutureTask> t : tasks) { List macs = t.get(); ret.addAll(macs); } return ret; } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } @Override public boolean[] SYD_SM4Mac_BatchData(int[] iKeyIndex, List pcData, List pcMac) { if ( null == iKeyIndex || null == pcData ) { throw new IllegalArgumentException("批量输入数据为 null"); } if ( iKeyIndex.length != pcData.size() ) { throw new IllegalArgumentException("批量输入数据密钥和数据数量不等"); } if ( 0 == iKeyIndex.length ) { return new boolean[0]; } // 将数据进行分组,防止超长。 List> dataGroups = new ArrayList<>(); List> keyGroups = new ArrayList<>(); List> macGroups = new ArrayList<>(); int totalLen = 0; List curDataGroup = new ArrayList<>(); List curKeyGroup = new ArrayList<>(); List curMacGroup = new ArrayList<>(); for (int i = 0; i < pcData.size(); i++) { byte[] data = pcData.get(i); if (null == data) { data = new byte[0]; } if ( curDataGroup.size() > 9 // 分组小于等于 9 个 || (totalLen + data.length > BATCH_SIZE) // 总大小小于 BATCH_SIZE ) { // 扩展包 dataGroups.add(curDataGroup); keyGroups.add(curKeyGroup); macGroups.add(curMacGroup); curDataGroup = new ArrayList<>(); curKeyGroup = new ArrayList<>(); curMacGroup = new ArrayList<>(); totalLen = 0; } curDataGroup.add(data); curKeyGroup.add(iKeyIndex[i]); curMacGroup.add(pcMac.get(i)); totalLen += data.length; } dataGroups.add(curDataGroup); keyGroups.add(curKeyGroup); macGroups.add(curMacGroup); // 并发处理 List> tasks = new ArrayList<>(); for (int i = 0; i < dataGroups.size(); i++) { int finalI = i; FutureTask task = builder.getLongLinkWorks().fTask(new Callable() { @Override public boolean[] call() throws Exception { SydApi api = builder.get(); return api.SYD_SM4Mac_BatchData( toIntArray(keyGroups.get(finalI)), dataGroups.get(finalI), macGroups.get(finalI) ); } }); tasks.add(task); } try { List ret = new ArrayList<>(); for (FutureTask t : tasks) { boolean[] rets = t.get(); for (boolean r : rets) { ret.add(r); } } return toBoolArray(ret); } catch (Exception e) { if ( e.getCause() instanceof SydApiException) { throw (SydApiException) e.getCause(); } throw new SydApiException("并行任务执行失败", 0xC101, e); } } }