diff --git a/src/main/java/com/sunyard/SydApi.java b/src/main/java/com/sunyard/SydApi.java index a513cb2..2c9d48e 100644 --- a/src/main/java/com/sunyard/SydApi.java +++ b/src/main/java/com/sunyard/SydApi.java @@ -71,6 +71,18 @@ public interface SydApi extends */ SydApi connect(String ip, int port, String pwd, int connectTimeout, int readTimeout); + /** + * 建立到指定地址和端口号的加密设备的TCP/IP 连接,返回 TCP/IP 连接句柄。 + * @param ip + * @param port + * @param pwd + * @param connectTimeout + * @param readTimeout + * @param retryWhenNetError 网络失败时重试 + * @return + */ + SydApi connect(String ip, int port, String pwd, int connectTimeout, int readTimeout , int retryWhenNetError); + void init(SydApiBuilder builder); /** diff --git a/src/main/java/com/sunyard/util/DnUtil.java b/src/main/java/com/sunyard/util/DnUtil.java new file mode 100644 index 0000000..6d30ffd --- /dev/null +++ b/src/main/java/com/sunyard/util/DnUtil.java @@ -0,0 +1,36 @@ +package com.sunyard.util; + +import java.util.LinkedHashMap; + +public class DnUtil { + + + public static LinkedHashMap dnToMap(String dn) { + LinkedHashMapmap = new LinkedHashMap(); + String[] kvs = dn.split(","); + for ( String kv : kvs ) { + String[] ps = kv.split("="); + map.put( ps[0].trim() , ps[1].trim() ); + } + return map; + } + + public static String verifyDn( String dn ) { + if ( dn.startsWith("C=") || dn.startsWith("c=")) { + return dn; + } + // 反转顺序 + LinkedHashMap map = dnToMap( dn ); + StringBuilder sb = new StringBuilder(); + + for ( String key : map.keySet() ) { + if ( sb.length() > 0 ) { + sb.insert(0, ","); + } + sb.insert(0, key + "=" + map.get( key )); + } + + return sb.toString(); + } + +} diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index 21cba09..e1a6533 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -15,10 +15,7 @@ import com.sunyard.trans.Alg; import com.sunyard.trans.FullMode; import com.sunyard.trans.PacketSN; import com.sunyard.trans.RoundMode; -import com.sunyard.util.CoderUtil; -import com.sunyard.util.FileUtil; -import com.sunyard.util.MyUtil; -import com.sunyard.util.SYMUtil; +import com.sunyard.util.*; import org.bouncycastle.asn1.*; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.cms.SydCmsUtil; @@ -56,10 +53,18 @@ public class SydApi4j implements SydApi { private static long sTime = System.currentTimeMillis(); - private static String ip1; - private static String ip2; - private static int port; - private static int timeout; + private static String ha_ip1; + private static String ha_ip2; + private static int ha_port; + private static int ha_timeout; + + // 网络失败时重试次数 + private String ip; + private int port; + private String pwd; + private int connectTimeout; + private int readTimeout; + private int retryWhenNetError = 0; //初始化变量 static { @@ -94,10 +99,10 @@ public class SydApi4j implements SydApi { int timeout ) { - SydApi4j.ip1 = ip1; - SydApi4j.ip2 = ip2; - SydApi4j.port = port; - SydApi4j.timeout = timeout; + SydApi4j.ha_ip1 = ip1; + SydApi4j.ha_ip2 = ip2; + SydApi4j.ha_port = port; + SydApi4j.ha_timeout = timeout; return 0; } @@ -1124,22 +1129,22 @@ public class SydApi4j implements SydApi { if (null == socket) { // 全局热备模式(old shool) - if (null != ip2) { + if (null != ha_ip2) { Socket s1 = new Socket(); - SocketAddress address = new InetSocketAddress(ip1, port); + SocketAddress address = new InetSocketAddress(ha_ip1, ha_port); try { - s1.connect(address, timeout); + s1.connect(address, ha_timeout); socket = s1; - socket.setSoTimeout(timeout); + socket.setSoTimeout(ha_timeout); } catch (Exception e) { Socket s2 = new Socket(); - SocketAddress add2 = new InetSocketAddress(ip2, port); + SocketAddress add2 = new InetSocketAddress(ha_ip2, ha_port); try { - s2.connect(add2, timeout); + s2.connect(add2, ha_timeout); socket = s2; - socket.setSoTimeout(timeout); + socket.setSoTimeout(ha_timeout); } catch (Exception e2) { throw new SydApiException(-2); } @@ -1181,8 +1186,27 @@ public class SydApi4j implements SydApi { try { socket.getOutputStream().write(buff); + socket.getOutputStream().flush(); } catch (IOException e) { - e.printStackTrace(); + + // 发送失败 + if ( null != ha_ip2 ) { + // HA 模式直接失败 + e.printStackTrace(); + throw new SydApiException("Socket write error", -2); + } else { + // 非 HA 模式检查重试 + socket = reConnect( new SydApiException("Socket write error", -2) ); + if ( null != socket ) { + // 补发数据 + try { + socket.getOutputStream().write(buff); + socket.getOutputStream().flush(); + }catch ( IOException e2 ) { + socket = reConnect( new SydApiException("Socket re write error", -2) ); + } + } + } } return buff; @@ -1311,7 +1335,7 @@ public class SydApi4j implements SydApi { @Override synchronized public SydApi connect(String ip, int port, String pwd, int timeout) { - if (null != ip2) { + if (null != ha_ip2) { throw new SydApiException("双机热备模式不用调用此方法", -1); } Socket socket = new Socket(); @@ -1325,7 +1349,7 @@ public class SydApi4j implements SydApi { } socket.setSoTimeout(timeout); } catch (Exception e) { - throw new SydApiException(-2); + socket = reConnect( new SydApiException(-2) ); } @@ -1341,7 +1365,7 @@ public class SydApi4j implements SydApi { @Override synchronized public SydApi connect(String ip, int port, String pwd, int connectTimeout, int readTimeout) { - if (null != ip2) { + if (null != ha_ip2) { throw new SydApiException("双机热备模式不用调用此方法", -1); } Socket socket = new Socket(); @@ -1351,7 +1375,7 @@ public class SydApi4j implements SydApi { socket.connect(address, connectTimeout); socket.setSoTimeout(readTimeout); } catch (Exception e) { - throw new SydApiException(-2); + socket = reConnect(new SydApiException(-2)); } @@ -1359,6 +1383,67 @@ public class SydApi4j implements SydApi { return this; } + + @Override + synchronized public SydApi connect(String ip, int port, String pwd, int connectTimeout, int readTimeout, int retryWhenNetError) { + + if (null != ha_ip2) { + throw new SydApiException("双机热备模式不用调用此方法", -1); + } + + // 重试模式必须保留链接参数 + this.retryWhenNetError = retryWhenNetError; + this.ip = ip; + this.port = port; + this.pwd = pwd; + this.connectTimeout = connectTimeout; + this.readTimeout = readTimeout; + + Socket socket = new Socket(); + SocketAddress address = new InetSocketAddress(ip, port); + + try { + socket.connect(address, connectTimeout); + socket.setSoTimeout(readTimeout); + } catch (Exception e) { + socket = reConnect(new SydApiException(-2)); + } + + + this.socket = socket; + return this; + } + + /** + * + * @param e 原始错误 + * @throws SydApiException + */ + private Socket reConnect(SydApiException e) { + while ( this.retryWhenNetError > 0 ) { + try { + println("Net error retry on " + this.retryWhenNetError ); + Socket socket = new Socket(); + SocketAddress address = new InetSocketAddress(ip, port); + + try { + socket.connect(address, connectTimeout); + socket.setSoTimeout(readTimeout); + } catch (Exception e1) { + throw new SydApiException(-2); + } + +// this.socket = socket; + return socket; + } catch ( Exception e1 ){ + println("Exception when net error retry on " + this.retryWhenNetError ); + } finally { + this.retryWhenNetError --; + } + } + throw e; + } + @Override synchronized public int disconnect() { @@ -1421,7 +1506,7 @@ public class SydApi4j implements SydApi { final ByteBuffer bbs = ByteBuffer.allocate(v + 1024); - int packSize = 2048; // 2048/3072/4096 + int packSize = 4080; // 2048/3072/4080 int packSizeDe = packSize + 16; // int fm = (int) data.get("fullMode$option"); int fm = (Integer) data.get("fullMode$option"); @@ -2226,6 +2311,9 @@ public class SydApi4j implements SydApi { } public RetWrap generateDEByDnHsm(String certSerial, String oData) { + + certSerial = DnUtil.verifyDn( certSerial ); + byte[] dnBytes = null; try { dnBytes = certSerial.getBytes("gbk"); @@ -2348,6 +2436,9 @@ public class SydApi4j implements SydApi { public RetWrap decryptDEByDNHsm(String certSerial, String pCipherKey) { + + certSerial = DnUtil.verifyDn( certSerial ); + byte[] dnBytes = null; try { dnBytes = certSerial.getBytes("gbk"); @@ -2438,6 +2529,9 @@ public class SydApi4j implements SydApi { } public RetWrap generateDEByDnSoft(String certSerial, String oData) { + + certSerial = DnUtil.verifyDn( certSerial ); + RetWrap ret = new RetWrap(); byte[] dnBytes = null; try { @@ -2573,6 +2667,9 @@ public class SydApi4j implements SydApi { } public RetWrap decryptDEByDNSoft(String certSerial, String pCipherKey) { + + certSerial = DnUtil.verifyDn( certSerial ); + byte[] dnBytes = null; try { dnBytes = certSerial.getBytes("gbk"); @@ -10316,6 +10413,8 @@ public class SydApi4j implements SydApi { */ @Override public String attachedSign(byte[] orgData, String sCertDN) { + sCertDN = DnUtil.verifyDn( sCertDN ); + Proto8018 proto = new Proto8018(); byte[] dn = new byte[256]; byte[] s = null; diff --git a/src/test/java/com/sunyard/sydapi/test/TestE0.java b/src/test/java/com/sunyard/sydapi/test/TestE0.java index 2b38060..73b164c 100644 --- a/src/test/java/com/sunyard/sydapi/test/TestE0.java +++ b/src/test/java/com/sunyard/sydapi/test/TestE0.java @@ -18,7 +18,7 @@ public class TestE0 { public void before() { // 通过设置debug的属性开启debug,如果不设置则默认不打开 System.setProperty("com.sunyard.sydapi4j.debug", "true"); - api = (SydApi4j) new SydApi4j().connect("172.16.18.59", 8889, null, 1000); + api = (SydApi4j) new SydApi4j().connect("192.168.1.111", 8889, null, 1000, 1000, 2); Arrays.fill( iv, (byte) 0x38 ); }