shjung 1 anno fa
parent
commit
f2b7f7deaa
36 ha cambiato i file con 1724 aggiunte e 270 eliminazioni
  1. 11 0
      src/main/java/com/its/app/common/utils/SysUtils.java
  2. 1 1
      src/main/java/com/its/rota/client/ItsRotaClientApplication.java
  3. 58 0
      src/main/java/com/its/rota/client/dao/mapper/batch/ItsRotaClientDao.java
  4. 42 2
      src/main/java/com/its/rota/client/dto/CenterDto.java
  5. 2 3
      src/main/java/com/its/rota/client/dto/NET.java
  6. 29 11
      src/main/java/com/its/rota/client/dto/NetState.java
  7. 21 0
      src/main/java/com/its/rota/client/dto/RecvPacketDto.java
  8. 5 1
      src/main/java/com/its/rota/client/entity/TbCenter.java
  9. 0 214
      src/main/java/com/its/rota/client/process/work/DataPacketWorker.java
  10. 53 1
      src/main/java/com/its/rota/client/repository/ApplicationRepository.java
  11. 1 1
      src/main/java/com/its/rota/client/xnet/client/ItsAsnClient.java
  12. 3 3
      src/main/java/com/its/rota/client/xnet/client/ItsAsnClientCommService.java
  13. 1 1
      src/main/java/com/its/rota/client/xnet/client/handler/ItsAsnClientInboundHandler.java
  14. 97 0
      src/main/java/com/its/rota/client/xnet/client/process/request/AiAccept.java
  15. 56 0
      src/main/java/com/its/rota/client/xnet/client/process/request/AiInitialize.java
  16. 97 0
      src/main/java/com/its/rota/client/xnet/client/process/request/AiLogin.java
  17. 75 0
      src/main/java/com/its/rota/client/xnet/client/process/request/AiPublicationIncidentCondition.java
  18. 75 0
      src/main/java/com/its/rota/client/xnet/client/process/request/AiPublicationTraffic.java
  19. 59 0
      src/main/java/com/its/rota/client/xnet/client/process/request/AiReject.java
  20. 97 0
      src/main/java/com/its/rota/client/xnet/client/process/request/AiSubscription.java
  21. 52 0
      src/main/java/com/its/rota/client/xnet/client/process/request/AiTerminate.java
  22. 55 0
      src/main/java/com/its/rota/client/xnet/client/process/response/AcceptResponse.java
  23. 62 0
      src/main/java/com/its/rota/client/xnet/client/process/response/FredResponse.java
  24. 41 0
      src/main/java/com/its/rota/client/xnet/client/process/response/InitiateResponse.java
  25. 5 0
      src/main/java/com/its/rota/client/xnet/client/process/response/ItsAsnResponse.java
  26. 133 0
      src/main/java/com/its/rota/client/xnet/client/process/response/LoginResponse.java
  27. 36 0
      src/main/java/com/its/rota/client/xnet/client/process/response/LogoutResponse.java
  28. 28 0
      src/main/java/com/its/rota/client/xnet/client/process/response/NullResponse.java
  29. 111 0
      src/main/java/com/its/rota/client/xnet/client/process/response/PublicationResponse.java
  30. 75 0
      src/main/java/com/its/rota/client/xnet/client/process/response/RejectResponse.java
  31. 107 0
      src/main/java/com/its/rota/client/xnet/client/process/response/SubscriptionResponse.java
  32. 31 0
      src/main/java/com/its/rota/client/xnet/client/process/response/TerminateResponse.java
  33. 28 0
      src/main/java/com/its/rota/client/xnet/client/process/response/TransferDoneResponse.java
  34. 9 19
      src/main/java/com/its/rota/client/xnet/client/process/work/DataPacketProcess.java
  35. 155 0
      src/main/java/com/its/rota/client/xnet/client/process/work/DataPacketWorker.java
  36. 13 13
      src/main/resources/mybatis/mapper/IncidentMapper.xml

+ 11 - 0
src/main/java/com/its/app/common/utils/SysUtils.java

@@ -168,4 +168,15 @@ public class SysUtils {
 
         return sb.toString();
     }
+
+    public static String subString(String str, int start, int end) {
+        if (str == null || "".equals(str)) {
+            return "";
+        }
+        if (start >= end) {
+            return "";
+        }
+        return str.substring(start, Math.min(end, str.length()));
+    }
+
 }

+ 1 - 1
src/main/java/com/its/rota/client/ItsRotaClientApplication.java

@@ -2,10 +2,10 @@ package com.its.rota.client;
 
 import com.its.rota.client.common.SpringUtils;
 import com.its.rota.client.process.dbms.DbmsDataProcess;
-import com.its.rota.client.process.work.DataPacketProcess;
 import com.its.rota.client.repository.ApplicationRepository;
 import com.its.rota.client.service.UnitSystService;
 import com.its.rota.client.xnet.client.ItsAsnClientCommService;
+import com.its.rota.client.xnet.client.process.work.DataPacketProcess;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.factory.InitializingBean;

+ 58 - 0
src/main/java/com/its/rota/client/dao/mapper/batch/ItsRotaClientDao.java

@@ -1,7 +1,9 @@
 package com.its.rota.client.dao.mapper.batch;
 
 import com.beanit.its.CurrentLinkState;
+import com.beanit.its.IncidentConditions;
 import com.its.app.common.utils.Elapsed;
+import com.its.app.common.utils.SysUtils;
 import com.its.rota.client.dao.mapper.BatchDaoService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.ibatis.session.SqlSessionFactory;
@@ -69,4 +71,60 @@ public class ItsRotaClientDao extends BatchDaoService {
         return total;
     }
 
+    public List<HashMap<String, Object>> getRcvIncident(String fromCenterId, String toCenterId, List<IncidentConditions> req) {
+        List<HashMap<String, Object>> lists = new ArrayList<>();
+        for (IncidentConditions obj : req) {
+            HashMap<String, Object> param = new HashMap<>();
+
+            String linkIdNumber = obj.getLinkLinkIdNumber().toString();
+            if (linkIdNumber == null || linkIdNumber.isEmpty()) {
+                continue;
+            }
+            String nodeIdNumber = obj.getNodeNodeIdNumber().toString();
+            if (nodeIdNumber == null || nodeIdNumber.isEmpty()) {
+                continue;
+            }
+
+            String orgnContactOrganizationNameText = new String(obj.getOrgnContactOrganizationNameText().value);
+
+            int descriptionTypeIncidentCode = obj.getEvntDescriptionTypeIncidentCode().intValue();
+            String descriptionTypeIncidentOther = new String(obj.getEvntDescriptionTypeIncidentOther().value);
+
+            byte incidentVehiclesInvolvedCodeByte = obj.getEvntIncidentVehiclesInvolvedCode().value[0];
+            int incidentVehiclesInvolvedCode = (incidentVehiclesInvolvedCodeByte & 0xFF) == 0xFE ? 255 : incidentVehiclesInvolvedCodeByte;
+            String incidentVehiclesInvolvedOther = new String(obj.getEvntIncidentVehiclesInvolvedOther().value);
+
+            int incidentStatusCode = obj.getEvntIncidentStatusCode().intValue();
+            String incidentStatusCodeOther = new String(obj.getEvntIncidentStatusOther().value);
+
+            int updateTypeCode = obj.getEvntUpdateTypeCode().intValue();
+            String updateTypeOther = new String(obj.getEvntUpdateTypeOther().value);
+
+            param.put("TOCENTERID",                    toCenterId);
+            param.put("LINK_LINKIDNUMBER",             SysUtils.subString(linkIdNumber, 0, 10));
+            param.put("FROMCENTERID",                  fromCenterId);
+            param.put("NODE_NODEIDNUMBER",             SysUtils.subString(nodeIdNumber, 0, 20));
+            param.put("CONTACTORGANIZATIONNAMETEXT",   SysUtils.subString(orgnContactOrganizationNameText, 0, 128));
+            param.put("DESCRIPTIONTYPEINCIDENTCODE",   descriptionTypeIncidentCode);
+            param.put("DESCRIPTIONTYPEINCIDENTOTHER",  SysUtils.subString(descriptionTypeIncidentOther,0, 256));
+            param.put("INCIDENTVEHICLESINVOLVEDCODE",  incidentVehiclesInvolvedCode);
+            param.put("INCIDENTVEHICLESINVOLVEDOTHER", SysUtils.subString(incidentVehiclesInvolvedOther,0, 256));
+            param.put("INCIDENTSTATUSCODE",            incidentStatusCode);
+            param.put("INCIDENTSTATUSOTHER",           SysUtils.subString(incidentStatusCodeOther, 0, 256));
+            param.put("UPDATETYPECODE",                updateTypeCode);
+            param.put("UPDATETYPEOTHER",               SysUtils.subString(updateTypeOther, 0, 256));
+
+            lists.add(param);
+        }
+        return lists;
+    }
+
+    public int insRcvIncident(String fromCenterId, String toCenterId, List<IncidentConditions> req) {
+        log.info("{}.insRcvIncident: START. {} EA", this.serviceName, req.size());
+        Elapsed elapsed = new Elapsed();
+        int total = insertBatch("insRcvIncident", getRcvIncident(fromCenterId, toCenterId, req));
+        log.info("{}.insRcvIncident: ..END. {} EA. {} ms.", this.serviceName, total, elapsed.milliSeconds());
+        return total;
+    }
+
 }

+ 42 - 2
src/main/java/com/its/rota/client/dto/CenterDto.java

@@ -1,13 +1,17 @@
 package com.its.rota.client.dto;
 
-import io.netty.channel.Channel;
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.beanit.utils.ItsAsnSequence;
+import io.netty.channel.ChannelFuture;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 
 import java.io.Serializable;
 
+@Slf4j
 @Data
 @Builder
 @NoArgsConstructor
@@ -15,6 +19,7 @@ import java.io.Serializable;
 public class CenterDto implements Serializable {
     private static final long serialVersionUID = 1L;
 
+    private int idx;
     private String centerId;        /* 센터 ID                       */
     private String centerInfo;      /* 센터 NAME                     */
     private String ipAddress;       /* 통신 IP                       */
@@ -26,10 +31,45 @@ public class CenterDto implements Serializable {
     private int datagramSize;       /* 데이터그램 크기               */
 
     private boolean commLogging;
-    private Channel channel;
+    private ItsAsnSequence seq;
+    private NetState netState;
 
+    public void setCenter(CenterDto dto) {
+        this.idx = dto.getIdx();
+        this.centerId = dto.getCenterId();
+        this.centerInfo = dto.getCenterInfo();
+        this.ipAddress = dto.getIpAddress();
+        this.commPort = dto.getCommPort();
+        this.datexUser = dto.getDatexUser();
+        this.datexPasswd = dto.getDatexPasswd();
+        this.heartBeat = dto.getHeartBeat();
+        this.resTime = dto.getResTime();
+        this.datagramSize = dto.getDatagramSize();
+        this.commLogging = dto.isCommLogging();
+        this.seq = new ItsAsnSequence();
+        this.netState = new NetState();
+    }
     public String getLogKey() {
         return this.centerId;
     }
 
+    public boolean sendData(C2CAuthenticatedMessage c2c, String msg) {
+        if (this.netState.getChannel() == null) {
+            log.warn("SEND: [{}, {}]. Channel closed. {}.", this.centerId, this.ipAddress, msg);
+            return false;
+        }
+        ChannelFuture f = this.netState.getChannel().writeAndFlush(c2c);
+        f.awaitUninterruptibly();
+        if (f.isDone() || f.isSuccess()) {
+            log.info("SEND: [{}, {}]. Packet send Ok. {}.", this.centerId, this.ipAddress, msg);
+            return true;
+        }
+        log.error("SEND: [{}, {}]. Packet send Failed. {}. will be closed.", this.centerId, this.ipAddress, msg);
+        return false;
+    }
+
+    public boolean channelOpened() {
+        return this.netState.getChannel() != null && this.netState.getState() == NET.DATA_TRANS;
+    }
+
 }

+ 2 - 3
src/main/java/com/its/rota/client/dto/NET.java

@@ -4,8 +4,7 @@ public class NET {
 
     public final static int CLOSED = 0; /* 종료된 상태 */
     public final static int LOGIN_WAIT = 1;      /* 최초 연결후 로그인 기다림 */
-    public final static int CONNECTED= 2;      /* 로그인 성공 */
-    public final static int DBASE_TRANS = 3;     /* database trans state */
-    public final static int DATA_TRANS = 4;      /* data trans state */
+    public final static int DATA_TRANS = 2;      /* data trans state */
+    public final static int TERMINATE = 2;
 
 }

+ 29 - 11
src/main/java/com/its/rota/client/dto/NetState.java

@@ -10,10 +10,12 @@ import java.util.Date;
 @Data
 public class NetState {
 
-    private int netState;
+    private int state;
     private Channel channel;
     private long connectCount;
-    private long lastCommTime;
+    private long lastRecvTime;
+    private long lastSendTime;
+    private int retryCount;
     private Date connectTime;
     private Date disconnectTime;
 
@@ -21,32 +23,48 @@ public class NetState {
         init();
     }
     public void init() {
-        this.netState = NET.CLOSED;
+        this.state = NET.CLOSED;
         this.channel = null;
         this.connectCount = 0;
-        this.lastCommTime = 0;
+        this.lastRecvTime = 0;
+        this.lastSendTime = 0;
+        this.retryCount = 0;
         this.connectTime = null;
         this.disconnectTime = null;
     }
 
-    public void setLastCommTime() {
-        this.lastCommTime = System.currentTimeMillis();
+    public void setLastRecvTime() {
+        this.lastRecvTime = System.currentTimeMillis();
     }
+    public void setLastSendTime() {
+        this.lastSendTime = System.currentTimeMillis();
+    }
+    public void retry() {
+        this.retryCount++;
+    }
+    public void request() {
+        this.retryCount = 0;
+    }
+
     public void connect(Channel channel) {
-        this.netState = NET.LOGIN_WAIT;
+        this.state = NET.LOGIN_WAIT;
         this.channel = channel;
         this.connectCount++;
         this.connectTime = new Date();
-        setLastCommTime();
+        this.retryCount = 0;
+        setLastRecvTime();
     }
     public void loginOk() {
-        //this.netState = NET.CONNECTED;
-        this.netState = NET.DATA_TRANS;
+        this.state = NET.DATA_TRANS;
     }
     public void disConnect() {
-        this.netState = NET.CLOSED;
+        this.state = NET.CLOSED;
         this.channel = null;
         this.disconnectTime = new Date();
+        this.retryCount = 0;
+    }
+    public void terminate() {
+        this.state = NET.TERMINATE;
     }
     public boolean isActive() {
         return this.channel != null && this.channel.isActive();

+ 21 - 0
src/main/java/com/its/rota/client/dto/RecvPacketDto.java

@@ -0,0 +1,21 @@
+package com.its.rota.client.dto;
+
+import com.beanit.its.C2CAuthenticatedMessage;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RecvPacketDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private long recvTime;
+    private CenterDto center;
+    private C2CAuthenticatedMessage c2c;
+}

+ 5 - 1
src/main/java/com/its/rota/client/entity/TbCenter.java

@@ -1,6 +1,8 @@
 package com.its.rota.client.entity;
 
+import com.beanit.utils.ItsAsnSequence;
 import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.dto.NetState;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
@@ -24,6 +26,7 @@ public class TbCenter {
 
     public CenterDto toDto() {
         return CenterDto.builder()
+                .idx(0)
                 .centerId(this.centerId)
                 .centerInfo(this.centerInfo)
                 .ipAddress(this.ipAddress)
@@ -34,7 +37,8 @@ public class TbCenter {
                 .resTime(this.resTime)
                 .datagramSize(this.datagramSize)
                 .commLogging(false)
-                .channel(null)
+                .seq(new ItsAsnSequence())
+                .netState(new NetState())
                 .build();
     }
 }

+ 0 - 214
src/main/java/com/its/rota/client/process/work/DataPacketWorker.java

@@ -1,214 +0,0 @@
-package com.its.rota.client.process.work;
-
-import com.its.app.common.utils.Elapsed;
-import com.its.rota.client.dto.SigGgitsTsinfoDto;
-import com.its.rota.client.process.AbstractAppWorker;
-import com.its.rota.client.process.dbms.DbmsDataProcess;
-import com.its.rota.client.repository.ApplicationRepository;
-import lombok.extern.slf4j.Slf4j;
-import org.slf4j.MDC;
-
-import java.util.concurrent.LinkedBlockingQueue;
-
-@Slf4j
-public class DataPacketWorker extends AbstractAppWorker implements Runnable {
-
-    private final ApplicationRepository repo;
-    private final DbmsDataProcess dbmsDataProcess;
-
-    private final LinkedBlockingQueue<SigGgitsTsinfoDto> DATA_QUEUE;
-
-    public DataPacketWorker(int idx, int qSize, ApplicationRepository repo, DbmsDataProcess dbmsDataProcess) {
-        this.idx = idx;
-        this.qSize = qSize;
-        this.repo = repo;
-        this.dbmsDataProcess = dbmsDataProcess;
-        this.DATA_QUEUE = new LinkedBlockingQueue<>(qSize);
-    }
-
-    @Override
-    public void run() {
-        log.info("{} Start. QSIZE: {}", Thread.currentThread().getName(), this.qSize);
-        while (true) {
-            try {
-                Object packet = this.DATA_QUEUE.take();
-                process(packet);
-            }
-            catch (Exception e) {
-                log.error("Exception: {}", e.getMessage());
-            }
-        }
-    }
-
-    /*
-     *  작업큐에 데이터 추가
-     */
-    public boolean add(Object object) {
-        boolean offer = false;
-        SigGgitsTsinfoDto packet = (SigGgitsTsinfoDto)object;
-        try {
-            //offer => full -> return
-            //add   => full -> wait
-            offer = this.DATA_QUEUE.offer(packet);
-            if (!offer) {
-                MDC.put("id", Long.toString(packet.getLocalPort()));
-                log.error("Packet Queue.offer: [{}]({})/{}, Queue Full: {} EA.",
-                        packet.getLocalPort(), this.idx, this.DATA_QUEUE.size(), this.qSize);
-                MDC.clear();
-            }
-        } catch (Exception e) {
-            MDC.put("id", Long.toString(packet.getLocalPort()));
-            log.error("Packet Queue.offer: Exception: {}, {}, {}", packet.getLocalPort(), Thread.currentThread().getName(), e.getMessage());
-            MDC.clear();
-        }
-        return offer;
-    }
-
-    public void process(Object object) {
-//        SigGgitsTsinfoDto data = (SigGgitsTsinfoDto)object;
-//        long popTimestamp = System.currentTimeMillis();
-//        int idx = 0;
-//        try {
-////            RegionCenter center = data.getCenter();//this.repo.getCenterMap().get(data.getLocalPort());
-////            if (center == null) {
-////                log.warn("WorkDataProcess.process: [{}],Not Found Region Center By RegionId: {}", data.getLocalPort(), data.getLocalPort());
-////                return;
-////            }
-//            List<IntStatusDto> statusLists = new ArrayList<>();
-//
-//            byte stx = data.buffer[idx++];
-//            byte opCode = data.buffer[idx++];
-//            short year  = (short)(data.buffer[idx++] & 0xFF);
-//            short month = (short)(data.buffer[idx++] & 0xFF);
-//            short day   = (short)(data.buffer[idx++] & 0xFF);
-//            short hour  = (short)(data.buffer[idx++] & 0xFF);
-//            short min   = (short)(data.buffer[idx++] & 0xFF);
-//            short sec   = (short)(data.buffer[idx++] & 0xFF);
-//            String COLLCT_DTIME = String.format("%4d%02d%02d%02d%02d%02d", year+2000, month, day, hour, min, sec);
-//
-//            int sequence   = ((data.buffer[idx++] & 0xFF) << 8) | (data.buffer[idx++] & 0xFF);
-//            int regionId   = ((data.buffer[idx++] & 0xFF) << 8) | (data.buffer[idx++] & 0xFF);
-//            int dataLength = ((data.buffer[idx++] & 0xFF) << 8) | (data.buffer[idx++] & 0xFF);
-//            int count      = ((data.buffer[idx++] & 0xFF) << 8) | (data.buffer[idx++] & 0xFF);
-//
-////            log.info("WorkDataProcess.process: [{}], Sequence {}, RegionId {}, DataLength {}, Count {}, {} Bytes. {} ms.",
-////                    data.getLocalPort(), sequence, regionId, dataLength, count, data.getBuffer().length, timestamp - data.getTimestamp());
-//
-//            if (opCode != SigProtocolConst.SIG_PHASE_CHANGE) {
-//                log.warn("WorkDataProcess.process: [{}], Unknown OpCode: {}, {}", data.getLocalPort(), stx, opCode);
-//                return;
-//            }
-//            if (dataLength != (count * 10)) {
-//                log.warn("WorkDataProcess.process: [{}], Data Length & Data count Error(length/count): {}, {}", data.getLocalPort(), dataLength, count);
-//                return;
-//            }
-//
-//            if (sequence < center.getRecvSeqNo()) {
-////                log.warn("WorkDataProcess.process: [{}], Receive Sequence Error(curr/old): {}, {}", data.getLocalPort(), sequence, center.getRecvSeqNo());
-//            }
-//            if (regionId != data.getLocalPort()) {
-//                log.warn("WorkDataProcess.process: [{}], Receive Region Id Error(packet/port): {}, {}", data.getLocalPort(), regionId, data.getLocalPort());
-//            }
-//            center.setRecvSeqNo(sequence);
-//
-//            int intLcNo;
-//            int ringAP;
-//            //int ringAS;
-//            int ringBP;
-//            //int ringBS;
-//            int comm;
-//            int mapNo;
-//            //int crs;
-//            int mode;
-////            int pnlManCont;
-////            int pnlMan;
-////            int pnlBlink;
-////            int pnlOut;
-////            int pnlAS;
-//            int turnOff;
-//            int blink;
-////            int pnlDb;
-////            byte ppc;
-////            byte omit;
-//            byte flags1;
-//            byte flags2;
-//            byte flags3;
-//            byte flags4;
-//
-//            for (int ii = 0; ii < count; ii++) {
-//                intLcNo = ((data.buffer[idx++] & 0xFF) << 24) |
-//                        ((data.buffer[idx++] & 0xFF) << 16) |
-//                        ((data.buffer[idx++] & 0xFF) << 8)  |
-//                        (data.buffer[idx++] & 0xFF);
-//
-//                flags1 = data.buffer[idx++];
-//                flags2 = data.buffer[idx++];
-//                flags3 = data.buffer[idx++];
-//                flags4 = data.buffer[idx++];
-////                ppc    = data.buffer[idx++];
-////                omit   = data.buffer[idx++];
-//                idx++;
-//                idx++;
-//                IntDto intDto = this.repo.getIntMap().get(intLcNo);
-//                if (intDto == null) {
-//                    UnknownIntDto unknownDto = this.repo.getUnknownIntMap().get(intLcNo);
-//                    if (unknownDto == null) {
-//                        unknownDto = new UnknownIntDto(intLcNo, center.getRegionCd());
-//                        this.repo.getUnknownIntMap().put(intLcNo, unknownDto);
-//                        log.warn("WorkDataProcess.process: [{}], Not Found IntLcNo: {}, {}, {}", data.getLocalPort(), intLcNo, intLcNo % 10000, intLcNo / 10000);
-//                    }
-//                    continue;
-//                }
-//
-//                ringAP = (flags1 >> 5) & 0x07;
-//                //ringAS = flags1 & 0x1F;
-//
-//                ringBP = (flags2 >> 5) & 0x07;
-//                //ringBS = flags2 & 0x1F;
-//
-//                comm = (flags3 >> 7 & 0x01);
-//                mapNo = (flags3 >> 4) & 0x07;
-//                //crs = (flags3 & 0x08);
-//                mode = (flags3) & 0x07;
-//
-////                pnlManCont = (flags4 >> 7 & 0x01);
-////                pnlMan     = (flags4 >> 6 & 0x01);
-////                pnlBlink   = (flags4 >> 5 & 0x01);
-////                pnlOut     = (flags4 >> 4 & 0x01);
-////                pnlAS      = (flags4 >> 3 & 0x01);
-//                turnOff    = (flags4 >> 2 & 0x01);
-//                blink      = (flags4 >> 1 & 0x01);
-////                pnlDb      = (flags4 >> 0 & 0x01);
-//
-//
-//                IntStatusDto status = intDto.getStatus();
-//                status.COLLCT_DTIME          = COLLCT_DTIME;
-//                status.A_RING_PHASE_VAL      = ringAP;
-//                status.B_RING_PHASE_VAL      = ringBP;
-//                status.COMM_ON_OFF_FLAG      = String.valueOf(comm);
-//                status.MAP_NO                = mapNo;
-//                status.CONTRLR_OPER_MODE_CD  = String.valueOf(mode);
-//                status.SIGLIGHT_TURNOFF_FLAG = String.valueOf(turnOff);
-//                status.SIGLIGHT_BLINK_FLAG   = String.valueOf(blink);
-//
-//                statusLists.add(status);
-//            }
-//            if (statusLists.isEmpty()) {
-//                log.warn("WorkDataProcess.process: [{}], Int Status Data Empty: {}, {} ms.", data.getLocalPort(), COLLCT_DTIME, System.currentTimeMillis() - popTimestamp);
-//                return;
-//            }
-////            log.info("WorkDataProcess.process: [{}], {} EA. {} Bytes. Parse {} ms.", data.getLocalPort(), count, data.getBuffer().length, System.currentTimeMillis() - parsetime);
-//            this.dbmsDataProcess.add(new DbmsData(data.getCenter(), this.idx, data.getTimestamp(), popTimestamp, System.currentTimeMillis(),
-//                    center.getRegionCd(), center.getRegionId(), DbmsDataType.DBMS_DATA_INT_STATUS_UPDATE, false, statusLists));
-////            log.info("WorkDataProcess.process: [{}], {} EA. {} Bytes. {} ms.[Q Added]", data.getLocalPort(), count, data.getBuffer().length, System.currentTimeMillis() - timestamp);
-//        }
-//        catch (Exception e) {
-//            log.error("WorkDataProcess.process: Exception: [{}] {}", data.getLocalPort(), e.toString());
-//        }
-    }
-
-    public void report() {
-        long avgTime = 0;
-        log.info("Packet: Remain Q: {}, Average: {}, {}", this.DATA_QUEUE.size(), Elapsed.elapsedTimeStr(avgTime), Thread.currentThread().getName());
-    }
-}

+ 53 - 1
src/main/java/com/its/rota/client/repository/ApplicationRepository.java

@@ -1,9 +1,16 @@
 package com.its.rota.client.repository;
 
+import com.beanit.asn1bean.ber.types.string.BerUTF8String;
+import com.beanit.its.HeaderOptions;
+import com.beanit.utils.ItsAsnUtils;
 import com.its.app.common.utils.Elapsed;
+import com.its.app.common.utils.NettyUtils;
 import com.its.rota.client.dao.mapper.CenterMapper;
 import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.dto.NET;
 import com.its.rota.client.entity.TbCenter;
+import com.its.rota.client.xnet.client.process.request.AiTerminate;
+import io.netty.channel.Channel;
 import io.netty.util.AttributeKey;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
@@ -23,12 +30,57 @@ import java.util.List;
 @Transactional(rollbackFor = {Exception.class})
 public class ApplicationRepository {
 
-    public static final AttributeKey<CenterDto> SIG_REGION_ATTRIBUTE_KEY = AttributeKey.valueOf("centerInfo");
+    public static final AttributeKey<CenterDto> CENTER_ATTRIBUTE_KEY = AttributeKey.valueOf("centerInfo");
 
     public static final CenterDto center = new CenterDto();
     private final HashMap<String, CenterDto> regionCenterMap = new HashMap<>();
     private final CenterMapper mapper;
 
+
+    public static void closeChannel(CenterDto center, Channel channel) {
+        try {
+            if (center != null && center.getNetState().getState() > NET.LOGIN_WAIT) {
+                AiTerminate.run(center);
+            }
+            if (channel != null) {
+                channel.flush();
+                channel.disconnect();
+                channel.close();
+            }
+        }
+        catch (Exception e) {
+            log.error("ApplicationRepository.closeChannel Exception: {}", e.getMessage());
+        }
+    }
+    public static void setCenterObject(Channel channel, CenterDto center) {
+        channel.attr(ApplicationRepository.CENTER_ATTRIBUTE_KEY).set(center);
+    }
+    public static CenterDto getCenterObject(Channel channel) {
+        CenterDto center = channel.attr(ApplicationRepository.CENTER_ATTRIBUTE_KEY).get();
+        if (center == null) {
+            log.warn("ApplicationRepository.getCenterObject: {}, Not Found Channel Object. Will be closed.", NettyUtils.getAddress(channel));
+            closeChannel(null, channel);
+            return null;
+        }
+        return center;
+    }
+
+    public static HeaderOptions getHeaderOptions(CenterDto regionCenter) {
+        HeaderOptions hdrOpts = new HeaderOptions();
+
+        hdrOpts.setDatexOriginText(new BerUTF8String(center.getCenterId()));
+        hdrOpts.setDatexOriginAddressLocation(new BerUTF8String(center.getCenterId()));
+        hdrOpts.setDatexSenderText(new BerUTF8String(center.getCenterId()));
+        hdrOpts.setDatexSenderAddressLocation(new BerUTF8String(center.getCenterId()));
+
+        hdrOpts.setDatexDestinationText(new BerUTF8String(regionCenter.getCenterId()));
+        hdrOpts.setDatexDestinationAddressLocation(new BerUTF8String(regionCenter.getCenterId()));
+
+        hdrOpts.setDatexDataPacketTime(ItsAsnUtils.getTime());
+
+        return hdrOpts;
+    }
+
     @PostConstruct
     private void init() {
         log.info("AppRepositoryService.init: Start.");

+ 1 - 1
src/main/java/com/its/rota/client/xnet/client/ItsAsnClient.java

@@ -2,11 +2,11 @@ package com.its.rota.client.xnet.client;
 
 import com.its.rota.client.config.ApplicationConfig;
 import com.its.rota.client.dto.CenterDto;
-import com.its.rota.client.process.work.DataPacketProcess;
 import com.its.rota.client.xnet.client.codec.ItsAsnClientDecoder;
 import com.its.rota.client.xnet.client.codec.ItsAsnClientEncoder;
 import com.its.rota.client.xnet.client.handler.ItsAsnClientIdleHandler;
 import com.its.rota.client.xnet.client.handler.ItsAsnClientInboundHandler;
+import com.its.rota.client.xnet.client.process.work.DataPacketProcess;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.*;
 import io.netty.channel.socket.SocketChannel;

+ 3 - 3
src/main/java/com/its/rota/client/xnet/client/ItsAsnClientCommService.java

@@ -2,8 +2,8 @@ package com.its.rota.client.xnet.client;
 
 import com.its.rota.client.config.ApplicationConfig;
 import com.its.rota.client.dto.CenterDto;
-import com.its.rota.client.process.work.DataPacketProcess;
 import com.its.rota.client.repository.ApplicationRepository;
+import com.its.rota.client.xnet.client.process.work.DataPacketProcess;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -64,8 +64,8 @@ public class ItsAsnClientCommService {
     public void shutdown() {
         for (Map.Entry<String, CenterDto> entry : this.repo.getRegionCenterMap().entrySet()) {
             CenterDto obj = entry.getValue();
-            if (obj.getChannel() != null) {
-                obj.getChannel().close();
+            if (obj.getNetState().getChannel() != null) {
+                obj.getNetState().getChannel().close();
             }
         }
         this.bootstrapFactory.getEventLoopGroup().shutdownGracefully();

+ 1 - 1
src/main/java/com/its/rota/client/xnet/client/handler/ItsAsnClientInboundHandler.java

@@ -1,7 +1,7 @@
 package com.its.rota.client.xnet.client.handler;
 
 import com.its.app.common.utils.NettyUtils;
-import com.its.rota.client.process.work.DataPacketProcess;
+import com.its.rota.client.xnet.client.process.work.DataPacketProcess;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;

+ 97 - 0
src/main/java/com/its/rota/client/xnet/client/process/request/AiAccept.java

@@ -0,0 +1,97 @@
+package com.its.rota.client.xnet.client.process.request;
+
+import com.beanit.asn1bean.ber.types.BerEnum;
+import com.beanit.asn1bean.ber.types.BerInteger;
+import com.beanit.asn1bean.ber.types.BerNull;
+import com.beanit.asn1bean.ber.types.BerOctetString;
+import com.beanit.enums.eAuthInfo;
+import com.beanit.enums.ePdusPr;
+import com.beanit.its.*;
+import com.beanit.utils.ItsAsnUtils;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+
+public class AiAccept {
+
+    public static C2CAuthenticatedMessage makeMessage(CenterDto center, C2CAuthenticatedMessage c2c) {
+        C2CAuthenticatedMessage resC2c = null;
+        PDUs pdus = c2c.getPdu();
+        ePdusPr pdu = ItsAsnUtils.getPduChoice(pdus);
+
+        byte[] accept = { eAuthInfo.AI_Accept.getValue() };
+        PDUs resPdus = new PDUs();
+        Accept acpt = new Accept();
+        Accept.DatexAcceptType acptType = new Accept.DatexAcceptType();
+
+        switch(pdu) {
+            case PDUs_PR_login:
+                resC2c = new C2CAuthenticatedMessage();
+                Login login = pdus.getLogin();
+                acptType.setLogIn(login.getDatexLoginEncodingRulesId().getBerObjectIdentifier().get(0));
+                break;
+            case PDUs_PR_subscripiton:
+                resC2c = new C2CAuthenticatedMessage();
+                Subscription subscription = c2c.getPdu().getSubscription();
+                SubscriptionType subscriptionType = subscription.getDatexSubscribeType();
+                BerEnum cancelReasonCd = subscriptionType.getDatexSubscribeCancelReasonCd();
+                if (subscriptionType != null) {
+                    // Subscription
+                    SubscriptionData subscriptionData = subscriptionType.getSubscription();
+                    SubscriptionMode subscriptionMode = subscriptionData.getDatexSubscribeMode();
+                    BerNull single = subscriptionMode.getSingle();
+                    Registered eventDriven = subscriptionMode.getEventDriven();
+                    Registered periodic = subscriptionMode.getPeriodic();
+
+                    if (single != null) {
+                        acptType.setSingleSubscription(new BerNull());
+                    }
+                    else if (eventDriven != null) {
+                        Registered.Continuous cont = eventDriven.getContinuous();
+                        if (cont != null) {
+                            acptType.setRegisteredSubscription(cont.getDatexRegisteredUpdateDelayQty());
+                        }
+                        else {
+                            acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
+                        }
+                    }
+                    else if (periodic != null) {
+                        Registered.Continuous cont = periodic.getContinuous();
+                        if (cont != null) {
+                            acptType.setRegisteredSubscription(cont.getDatexRegisteredUpdateDelayQty());
+                        }
+                        else {
+                            acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
+                        }
+                    }
+                    else {
+                        return null;
+                    }
+                }
+                else if (cancelReasonCd != null) {
+                    // Cancel
+                    acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
+                }
+                break;
+            case PDUs_PR_publication:
+                resC2c = new C2CAuthenticatedMessage();
+                BerNull berNull = new BerNull();
+                acptType.setPublication(berNull);
+                break;
+            default:
+                break;
+        }
+
+        if (resC2c != null) {
+            acpt.setDatexAcceptPacketNbr(c2c.getDatexDataPacketNumber());
+            acpt.setDatexAcceptType(acptType);
+            resPdus.setAccept(acpt);
+
+            resC2c.setDatexAuthenticationInfoText(new BerOctetString(accept));
+            resC2c.setDatexDataPacketNumber(new BerInteger(center.getSeq().nextValue()));
+            resC2c.setDatexDataPacketPriorityNumber(new BerInteger(0));
+            resC2c.setOptions(ApplicationRepository.getHeaderOptions(center));
+            resC2c.setPdu(resPdus);
+        }
+        return resC2c;
+    }
+}

+ 56 - 0
src/main/java/com/its/rota/client/xnet/client/process/request/AiInitialize.java

@@ -0,0 +1,56 @@
+package com.its.rota.client.xnet.client.process.request;
+
+import com.beanit.asn1bean.ber.types.BerInteger;
+import com.beanit.asn1bean.ber.types.BerOctetString;
+import com.beanit.asn1bean.ber.types.string.BerUTF8String;
+import com.beanit.enums.eAuthInfo;
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.beanit.its.HeaderOptions;
+import com.beanit.its.Initiate;
+import com.beanit.its.PDUs;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+@Slf4j
+public class AiInitialize {
+
+    public static boolean run(CenterDto center) {
+        boolean result;
+        try {
+            MDC.put("id", center.getLogKey());
+            log.info("AiInitialize.run: [{}, {}].", center.getLogKey(), center.getIpAddress());
+
+            PDUs pdUs = new PDUs();
+            byte[] auth = {eAuthInfo.AI_Initiate.getValue() };
+            Initiate initiate = new Initiate();
+            initiate.setDatexSenderTxt(new BerUTF8String(ApplicationRepository.center.getCenterId()));
+            initiate.setDatexDestinationTxt(new BerUTF8String(center.getCenterId()));
+            pdUs.setDatexInitiateNull(initiate);
+
+            HeaderOptions hdrOpts = ApplicationRepository.getHeaderOptions(center);
+
+            C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+            c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+            c2c.setDatexDataPacketNumber(new BerInteger(center.getSeq().nextValue()));
+            c2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
+            c2c.setOptions(hdrOpts);
+            c2c.setPdu(pdUs);
+
+            result = center.sendData(c2c, "AI_Initiate");
+        }
+        catch (Exception e) {
+            log.error("AiInitialize.run: [{}, {}]. Packet send Exception. will be closed. {}", center.getLogKey(), center.getIpAddress(), e.getMessage());
+            result = false;
+        }
+        finally {
+            MDC.clear();
+        }
+
+        if (!result) {
+            ApplicationRepository.closeChannel(center, center.getNetState().getChannel());
+        }
+        return result;
+    }
+}

+ 97 - 0
src/main/java/com/its/rota/client/xnet/client/process/request/AiLogin.java

@@ -0,0 +1,97 @@
+package com.its.rota.client.xnet.client.process.request;
+
+import com.beanit.asn1bean.ber.types.BerEnum;
+import com.beanit.asn1bean.ber.types.BerInteger;
+import com.beanit.asn1bean.ber.types.BerNull;
+import com.beanit.asn1bean.ber.types.BerOctetString;
+import com.beanit.enums.eAuthInfo;
+import com.beanit.enums.ePdusPr;
+import com.beanit.its.*;
+import com.beanit.utils.ItsAsnUtils;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+
+public class AiLogin {
+
+    public static C2CAuthenticatedMessage makeMessage(CenterDto center, C2CAuthenticatedMessage c2c) {
+        C2CAuthenticatedMessage resC2c = null;
+        PDUs pdus = c2c.getPdu();
+        ePdusPr pdu = ItsAsnUtils.getPduChoice(pdus);
+
+        byte[] accept = { eAuthInfo.AI_Accept.getValue() };
+        PDUs resPdus = new PDUs();
+        Accept acpt = new Accept();
+        Accept.DatexAcceptType acptType = new Accept.DatexAcceptType();
+
+        switch(pdu) {
+            case PDUs_PR_login:
+                resC2c = new C2CAuthenticatedMessage();
+                Login login = pdus.getLogin();
+                acptType.setLogIn(login.getDatexLoginEncodingRulesId().getBerObjectIdentifier().get(0));
+                break;
+            case PDUs_PR_subscripiton:
+                resC2c = new C2CAuthenticatedMessage();
+                Subscription subscription = c2c.getPdu().getSubscription();
+                SubscriptionType subscriptionType = subscription.getDatexSubscribeType();
+                BerEnum cancelReasonCd = subscriptionType.getDatexSubscribeCancelReasonCd();
+                if (subscriptionType != null) {
+                    // Subscription
+                    SubscriptionData subscriptionData = subscriptionType.getSubscription();
+                    SubscriptionMode subscriptionMode = subscriptionData.getDatexSubscribeMode();
+                    BerNull single = subscriptionMode.getSingle();
+                    Registered eventDriven = subscriptionMode.getEventDriven();
+                    Registered periodic = subscriptionMode.getPeriodic();
+
+                    if (single != null) {
+                        acptType.setSingleSubscription(new BerNull());
+                    }
+                    else if (eventDriven != null) {
+                        Registered.Continuous cont = eventDriven.getContinuous();
+                        if (cont != null) {
+                            acptType.setRegisteredSubscription(cont.getDatexRegisteredUpdateDelayQty());
+                        }
+                        else {
+                            acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
+                        }
+                    }
+                    else if (periodic != null) {
+                        Registered.Continuous cont = periodic.getContinuous();
+                        if (cont != null) {
+                            acptType.setRegisteredSubscription(cont.getDatexRegisteredUpdateDelayQty());
+                        }
+                        else {
+                            acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
+                        }
+                    }
+                    else {
+                        return null;
+                    }
+                }
+                else if (cancelReasonCd != null) {
+                    // Cancel
+                    acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
+                }
+                break;
+            case PDUs_PR_publication:
+                resC2c = new C2CAuthenticatedMessage();
+                BerNull berNull = new BerNull();
+                acptType.setPublication(berNull);
+                break;
+            default:
+                break;
+        }
+
+        if (resC2c != null) {
+            acpt.setDatexAcceptPacketNbr(c2c.getDatexDataPacketNumber());
+            acpt.setDatexAcceptType(acptType);
+            resPdus.setAccept(acpt);
+
+            resC2c.setDatexAuthenticationInfoText(new BerOctetString(accept));
+            resC2c.setDatexDataPacketNumber(new BerInteger(center.getSeq().nextValue()));
+            resC2c.setDatexDataPacketPriorityNumber(new BerInteger(0));
+            resC2c.setOptions(ApplicationRepository.getHeaderOptions(center));
+            resC2c.setPdu(resPdus);
+        }
+        return resC2c;
+    }
+}

+ 75 - 0
src/main/java/com/its/rota/client/xnet/client/process/request/AiPublicationIncidentCondition.java

@@ -0,0 +1,75 @@
+package com.its.rota.client.xnet.client.process.request;
+
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+@Slf4j
+public class AiPublicationIncidentCondition {
+
+    public static boolean run(CenterDto center) {
+        boolean result = true;
+        try {
+            MDC.put("id", center.getLogKey());
+            log.info("AiPublicationIncidentCondition.run: [{}, {}].", center.getLogKey(), center.getIpAddress());
+
+//            IncidentConditionsList lists = center.getIncidentConditionsList();
+//            if (lists.getIncidentConditions().isEmpty()) {
+//                return true;
+//            }
+//
+//            EndApplicationMessage endMsg =  new EndApplicationMessage();
+//            int[] messageId = {1, 0, 14827, 1, 1, 4};
+//            ReverseByteArrayOutputStream msgBuff = new ReverseByteArrayOutputStream(ItsAsn.ITS_ASN_PACKET_MAX_SIZE);
+//            lists.encode(msgBuff);
+//            endMsg.setEndApplicationMessageId(new BerObjectIdentifier(messageId));
+//            endMsg.setEndApplicationMessageMsg(new BerAny(msgBuff.getArray()));
+//
+//            byte[] auth = { eAuthInfo.AI_IncidentConditions.getValue() };
+//            int packetNmbr = ItsAsn.ITS_ASN_DATEX_INCIDENT_SEQUENCE;
+//
+//            PublicationType publicationType = new PublicationType();
+//            publicationType.setDatexPublishData(endMsg);
+//
+//            PublicationData publicationData = new PublicationData();
+//            publicationData.setDatexPublishSubscribeSerialNbr(new BerInteger(packetNmbr));  // 요청 serial nmbr
+//            publicationData.setDatexPublishSerialNbr(new BerInteger(packetNmbr));           // 생성 serial nmbr
+//            publicationData.setDatexPublishLatePublicationFlag(new BerBoolean(true));
+//            publicationData.setDatexPublishType(publicationType);
+//
+//            PublishFormat.DatexPublishData publishData = new PublishFormat.DatexPublishData();
+//            publishData.getPublicationData().add(publicationData);
+//
+//            PublishFormat publishFormat = new PublishFormat();
+//            publishFormat.setDatexPublishData(publishData);
+//
+//            Publication publication = new Publication();
+//            publication.setDatexPublishFormat(publishFormat);
+//            publication.setDatexPublishGuaranteedBool(new BerBoolean(true));
+//
+//            C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+//            PDUs pdus = new PDUs();
+//            pdus.setPublication(publication);
+//            c2c.setDatexDataPacketNumber(new BerInteger(packetNmbr));
+//            c2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
+//            c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+//            c2c.setOptions(ApplicationRepository.getHeaderOptions(center));
+//            c2c.setPdu(pdus);
+
+//            result = center.sendData(c2c, "AI_Publication-IncidentConditions");
+        }
+        catch (Exception e) {
+            log.error("AiPublicationIncidentCondition.run: [{}, {}]. Packet send Exception. will be closed. {}", center.getLogKey(), center.getIpAddress(), e.getMessage());
+            result = false;
+        }
+        finally {
+            MDC.clear();
+        }
+
+        if (!result) {
+            ApplicationRepository.closeChannel(center, center.getNetState().getChannel());
+        }
+        return result;
+    }
+}

+ 75 - 0
src/main/java/com/its/rota/client/xnet/client/process/request/AiPublicationTraffic.java

@@ -0,0 +1,75 @@
+package com.its.rota.client.xnet.client.process.request;
+
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+@Slf4j
+public class AiPublicationTraffic {
+
+    public static boolean run(CenterDto center) {
+        boolean result = true;
+        try {
+            MDC.put("id", center.getLogKey());
+            log.info("AiPublicationTraffic.run: [{}, {}].", center.getLogKey(), center.getIpAddress());
+
+//            CurrentLinkStateList lists = center.getCurrentLinkStateList();
+//            if (lists.getCurrentLinkState().isEmpty()) {
+//                return true;
+//            }
+//
+//            EndApplicationMessage endMsg =  new EndApplicationMessage();
+//            int[] messageId = {1, 0, 14827, 1, 1, 1};
+//            ReverseByteArrayOutputStream msgBuff = new ReverseByteArrayOutputStream(ItsAsn.ITS_ASN_PACKET_MAX_SIZE);
+//            lists.encode(msgBuff);
+//            endMsg.setEndApplicationMessageId(new BerObjectIdentifier(messageId));
+//            endMsg.setEndApplicationMessageMsg(new BerAny(msgBuff.getArray()));
+//
+//            byte[] auth = { eAuthInfo.AI_CurrentLinkState.getValue() };
+//            int packetNmbr = ItsAsn.ITS_ASN_DATEX_TRAFFIC_SEQUENCE;
+//
+//            PublicationType publicationType = new PublicationType();
+//            publicationType.setDatexPublishData(endMsg);
+//
+//            PublicationData publicationData = new PublicationData();
+//            publicationData.setDatexPublishSubscribeSerialNbr(new BerInteger(packetNmbr));  // 요청 serial nmbr
+//            publicationData.setDatexPublishSerialNbr(new BerInteger(packetNmbr));           // 생성 serial nmbr
+//            publicationData.setDatexPublishLatePublicationFlag(new BerBoolean(true));
+//            publicationData.setDatexPublishType(publicationType);
+//
+//            PublishFormat.DatexPublishData publishData = new PublishFormat.DatexPublishData();
+//            publishData.getPublicationData().add(publicationData);
+//
+//            PublishFormat publishFormat = new PublishFormat();
+//            publishFormat.setDatexPublishData(publishData);
+//
+//            Publication publication = new Publication();
+//            publication.setDatexPublishFormat(publishFormat);
+//            publication.setDatexPublishGuaranteedBool(new BerBoolean(true));
+//
+//            C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+//            PDUs pdus = new PDUs();
+//            pdus.setPublication(publication);
+//            c2c.setDatexDataPacketNumber(new BerInteger(packetNmbr));
+//            c2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
+//            c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+//            c2c.setOptions(ApplicationRepository.getHeaderOptions(center));
+//            c2c.setPdu(pdus);
+//
+//            result = center.sendData(c2c, "AI_Publication-CurrentLinkState");
+        }
+        catch (Exception e) {
+            log.error("AiPublicationTraffic.run: [{}, {}]. Packet send Exception. will be closed. {}", center.getLogKey(), center.getIpAddress(), e.getMessage());
+            result = false;
+        }
+        finally {
+            MDC.clear();
+        }
+
+        if (!result) {
+            ApplicationRepository.closeChannel(center, center.getNetState().getChannel());
+        }
+        return result;
+    }
+}

+ 59 - 0
src/main/java/com/its/rota/client/xnet/client/process/request/AiReject.java

@@ -0,0 +1,59 @@
+package com.its.rota.client.xnet.client.process.request;
+
+import com.beanit.asn1bean.ber.types.BerEnum;
+import com.beanit.asn1bean.ber.types.BerInteger;
+import com.beanit.asn1bean.ber.types.BerOctetString;
+import com.beanit.enums.eAuthInfo;
+import com.beanit.enums.ePdusPr;
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.beanit.its.PDUs;
+import com.beanit.its.Reject;
+import com.beanit.its.RejectType;
+import com.beanit.utils.ItsAsnUtils;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AiReject {
+
+    public static C2CAuthenticatedMessage makeMessage(CenterDto center, C2CAuthenticatedMessage c2c, int rejectType) {
+        C2CAuthenticatedMessage resC2c = null;
+        ePdusPr pdu = ItsAsnUtils.getPduChoice(c2c.getPdu());
+
+        byte[] reject = { eAuthInfo.AI_Reject.getValue() };
+        PDUs resPdus = new PDUs();
+        Reject rjt = new Reject();
+        RejectType rjtType = new RejectType();
+
+        switch(pdu) {
+            case PDUs_PR_login:
+                resC2c = new C2CAuthenticatedMessage();
+                rjtType.setDatexRejectLoginCd(new BerEnum(rejectType));
+                break;
+            case PDUs_PR_subscripiton:
+                resC2c = new C2CAuthenticatedMessage();
+                rjtType.setDatexRejectSubscriptionCd(new BerEnum(rejectType));
+                break;
+            case PDUs_PR_publication:
+                resC2c = new C2CAuthenticatedMessage();
+                rjtType.setDatexRejectPublicationCd(new BerEnum(rejectType));
+                break;
+            default:
+                break;
+        }
+
+        if (resC2c != null) {
+            rjt.setDatexRejectPacketNbr(c2c.getDatexDataPacketNumber());
+            rjt.setDatexRejectType(rjtType);
+            resPdus.setReject(rjt);
+
+            resC2c.setDatexAuthenticationInfoText(new BerOctetString(reject));
+            resC2c.setDatexDataPacketNumber(new BerInteger(center.getSeq().nextValue()));
+            resC2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
+            resC2c.setOptions(ApplicationRepository.getHeaderOptions(center));
+            resC2c.setPdu(resPdus);
+        }
+        return resC2c;
+    }
+}

+ 97 - 0
src/main/java/com/its/rota/client/xnet/client/process/request/AiSubscription.java

@@ -0,0 +1,97 @@
+package com.its.rota.client.xnet.client.process.request;
+
+import com.beanit.asn1bean.ber.types.BerEnum;
+import com.beanit.asn1bean.ber.types.BerInteger;
+import com.beanit.asn1bean.ber.types.BerNull;
+import com.beanit.asn1bean.ber.types.BerOctetString;
+import com.beanit.enums.eAuthInfo;
+import com.beanit.enums.ePdusPr;
+import com.beanit.its.*;
+import com.beanit.utils.ItsAsnUtils;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+
+public class AiSubscription {
+
+    public static C2CAuthenticatedMessage makeMessage(CenterDto center, C2CAuthenticatedMessage c2c) {
+        C2CAuthenticatedMessage resC2c = null;
+        PDUs pdus = c2c.getPdu();
+        ePdusPr pdu = ItsAsnUtils.getPduChoice(pdus);
+
+        byte[] accept = { eAuthInfo.AI_Accept.getValue() };
+        PDUs resPdus = new PDUs();
+        Accept acpt = new Accept();
+        Accept.DatexAcceptType acptType = new Accept.DatexAcceptType();
+
+        switch(pdu) {
+            case PDUs_PR_login:
+                resC2c = new C2CAuthenticatedMessage();
+                Login login = pdus.getLogin();
+                acptType.setLogIn(login.getDatexLoginEncodingRulesId().getBerObjectIdentifier().get(0));
+                break;
+            case PDUs_PR_subscripiton:
+                resC2c = new C2CAuthenticatedMessage();
+                Subscription subscription = c2c.getPdu().getSubscription();
+                SubscriptionType subscriptionType = subscription.getDatexSubscribeType();
+                BerEnum cancelReasonCd = subscriptionType.getDatexSubscribeCancelReasonCd();
+                if (subscriptionType != null) {
+                    // Subscription
+                    SubscriptionData subscriptionData = subscriptionType.getSubscription();
+                    SubscriptionMode subscriptionMode = subscriptionData.getDatexSubscribeMode();
+                    BerNull single = subscriptionMode.getSingle();
+                    Registered eventDriven = subscriptionMode.getEventDriven();
+                    Registered periodic = subscriptionMode.getPeriodic();
+
+                    if (single != null) {
+                        acptType.setSingleSubscription(new BerNull());
+                    }
+                    else if (eventDriven != null) {
+                        Registered.Continuous cont = eventDriven.getContinuous();
+                        if (cont != null) {
+                            acptType.setRegisteredSubscription(cont.getDatexRegisteredUpdateDelayQty());
+                        }
+                        else {
+                            acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
+                        }
+                    }
+                    else if (periodic != null) {
+                        Registered.Continuous cont = periodic.getContinuous();
+                        if (cont != null) {
+                            acptType.setRegisteredSubscription(cont.getDatexRegisteredUpdateDelayQty());
+                        }
+                        else {
+                            acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
+                        }
+                    }
+                    else {
+                        return null;
+                    }
+                }
+                else if (cancelReasonCd != null) {
+                    // Cancel
+                    acptType.setRegisteredSubscription(subscription.getDatexSubscribeSerialNbr());
+                }
+                break;
+            case PDUs_PR_publication:
+                resC2c = new C2CAuthenticatedMessage();
+                BerNull berNull = new BerNull();
+                acptType.setPublication(berNull);
+                break;
+            default:
+                break;
+        }
+
+        if (resC2c != null) {
+            acpt.setDatexAcceptPacketNbr(c2c.getDatexDataPacketNumber());
+            acpt.setDatexAcceptType(acptType);
+            resPdus.setAccept(acpt);
+
+            resC2c.setDatexAuthenticationInfoText(new BerOctetString(accept));
+            resC2c.setDatexDataPacketNumber(new BerInteger(center.getSeq().nextValue()));
+            resC2c.setDatexDataPacketPriorityNumber(new BerInteger(0));
+            resC2c.setOptions(ApplicationRepository.getHeaderOptions(center));
+            resC2c.setPdu(resPdus);
+        }
+        return resC2c;
+    }
+}

+ 52 - 0
src/main/java/com/its/rota/client/xnet/client/process/request/AiTerminate.java

@@ -0,0 +1,52 @@
+package com.its.rota.client.xnet.client.process.request;
+
+import com.beanit.asn1bean.ber.types.BerInteger;
+import com.beanit.asn1bean.ber.types.BerOctetString;
+import com.beanit.enums.eAuthInfo;
+import com.beanit.enums.eTerminate;
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.beanit.its.HeaderOptions;
+import com.beanit.its.PDUs;
+import com.beanit.its.Terminate;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+@Slf4j
+public class AiTerminate {
+
+    public static boolean run(CenterDto center) {
+        boolean result;
+        center.getNetState().terminate();
+        try {
+            MDC.put("id", center.getLogKey());
+            log.info("AiTerminate.run: [{}, {}].", center.getLogKey(), center.getIpAddress());
+
+            PDUs pdUs = new PDUs();
+            byte[] auth = {eAuthInfo.AI_Terminate.getValue() };
+            Terminate terminate = new Terminate(eTerminate.Terminate_Other.getValue());
+            pdUs.setTerminate(terminate);
+
+            HeaderOptions hdrOpts = ApplicationRepository.getHeaderOptions(center);
+
+            C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+            c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+            c2c.setDatexDataPacketNumber(new BerInteger(center.getSeq().nextValue()));
+            c2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
+            c2c.setOptions(hdrOpts);
+            c2c.setPdu(pdUs);
+
+            result = center.sendData(c2c, "AI_Terminate");
+        }
+        catch (Exception e) {
+            log.error("AiTerminate.run: [{}, {}]. Packet send Exception. will be closed. {}", center.getLogKey(), center.getIpAddress(), e.getMessage());
+            result = false;
+        }
+        finally {
+            MDC.clear();
+        }
+        // 연결을 종료할 때 전송하는 메시지 이기 때문에 여기서 Channel 의 연결을 종료하면 안된다.
+        return result;
+    }
+}

+ 55 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/AcceptResponse.java

@@ -0,0 +1,55 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.its.Accept;
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.beanit.its.PDUs;
+import com.beanit.utils.ItsAsn;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.xnet.client.process.request.AiPublicationIncidentCondition;
+import com.its.rota.client.xnet.client.process.request.AiPublicationTraffic;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+@Slf4j
+public class AcceptResponse implements ItsAsnResponse {
+    private final CenterDto center;
+    private final C2CAuthenticatedMessage c2c;
+
+    public AcceptResponse(CenterDto center, C2CAuthenticatedMessage c2c) {
+        this.center = center;
+        this.c2c = c2c;
+    }
+
+    @Override
+    public boolean response() {
+        boolean result = true;
+        try {
+            MDC.put("id", this.center.getLogKey());
+            log.info("AcceptResponse.response: [{}, {}].", this.center.getLogKey(), this.center.getIpAddress());
+
+            PDUs pdus = this.c2c.getPdu();
+            Accept accept = pdus.getAccept();
+            if (accept == null) {
+                log.info("AcceptResponse.response: [{}, {}]. accept data null. will be closed.", this.center.getLogKey(), this.center.getIpAddress());
+                return false;
+            }
+            Long acceptPacketNmbr = accept.getDatexAcceptPacketNbr().value.longValue();
+            log.info("AcceptResponse.response: [{}, {}]. Accept packet number {}.", this.center.getLogKey(), this.center.getIpAddress(), acceptPacketNmbr);
+            if (acceptPacketNmbr == ItsAsn.ITS_ASN_DATEX_INCIDENT_SEQUENCE) {
+                AiPublicationIncidentCondition.run(this.center);
+            }
+            else if (acceptPacketNmbr == ItsAsn.ITS_ASN_DATEX_TRAFFIC_SEQUENCE) {
+                AiPublicationTraffic.run(this.center);
+            }
+        }
+        catch (Exception e) {
+            log.error("AcceptResponse.response: [{}, {}]. Packet send Exception. will be closed. {}", this.center.getLogKey(), this.center.getIpAddress(), e.getMessage());
+            result = false;
+        }
+        finally {
+            MDC.clear();
+        }
+        return result;
+    }
+
+}

+ 62 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/FredResponse.java

@@ -0,0 +1,62 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.asn1bean.ber.types.BerInteger;
+import com.beanit.asn1bean.ber.types.BerOctetString;
+import com.beanit.enums.eAuthInfo;
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.beanit.its.FrED;
+import com.beanit.its.HeaderOptions;
+import com.beanit.its.PDUs;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+import java.math.BigInteger;
+
+@Slf4j
+public class FredResponse implements ItsAsnResponse {
+    private CenterDto center;
+    private C2CAuthenticatedMessage c2c;
+
+    public FredResponse(CenterDto center, C2CAuthenticatedMessage c2c) {
+        this.center = center;
+        this.c2c = c2c;
+    }
+
+    @Override
+    public boolean response() {
+        boolean result = true;
+        try {
+            MDC.put("id", this.center.getLogKey());
+            log.info("FredResponse.response: [{}, {}].", this.center.getLogKey(), this.center.getIpAddress());
+
+            // 세션 연결 유지를 위해 Fred 메시지 전송
+            PDUs pdUs = new PDUs();
+            FrED fred = new FrED(new BigInteger(String.valueOf(9871)));
+            pdUs.setFred(fred);
+
+            byte[] auth = { eAuthInfo.AI_FrED.getValue() };
+
+            HeaderOptions hdrOpts = ApplicationRepository.getHeaderOptions(this.center);
+
+            C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
+            c2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+            c2c.setDatexDataPacketNumber(new BerInteger(this.center.getSeq().nextValue()));
+            c2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
+            c2c.setOptions(hdrOpts);
+            c2c.setPdu(pdUs);
+
+            result = this.center.sendData(c2c, "AI_FrED");
+        }
+        catch (Exception e) {
+            log.error("FredResponse.response: [{}, {}]. Packet send Exception. will be closed. {}", this.center.getLogKey(), this.center.getIpAddress(), e.getMessage());
+            result = false;
+        }
+        finally {
+            MDC.clear();
+        }
+        return result;
+    }
+
+}

+ 41 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/InitiateResponse.java

@@ -0,0 +1,41 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.beanit.its.Initiate;
+import com.beanit.its.PDUs;
+import com.its.app.common.utils.NettyUtils;
+import com.its.rota.client.dto.CenterDto;
+import io.netty.channel.ChannelHandlerContext;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class InitiateResponse implements ItsAsnResponse {
+    private CenterDto obj;
+    private ChannelHandlerContext ctx;
+    private C2CAuthenticatedMessage c2c;
+
+    public InitiateResponse(CenterDto obj, ChannelHandlerContext ctx, C2CAuthenticatedMessage c2c) {
+        this.obj = obj;
+        this.ctx = ctx;
+        this.c2c = c2c;
+    }
+
+    @Override
+    public boolean response() {
+        // 처리내용 없음
+        String ipAddress = NettyUtils.getRemoteIpAddress(this.ctx.channel());
+        log.info("InitiateResponse.response: {}", ipAddress);
+
+        PDUs pdus = this.c2c.getPdu();
+        Initiate initiate = pdus.getDatexInitiateNull();
+        if (initiate != null) {
+            /**
+             * Login 요청에 대한 응답을 처리함
+             */
+//            return LoginDeviceService.getInstance().requestLogin(obj, this.ctx.channel(), config);
+        }
+
+        return true;
+    }
+
+}

+ 5 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/ItsAsnResponse.java

@@ -0,0 +1,5 @@
+package com.its.rota.client.xnet.client.process.response;
+
+public interface ItsAsnResponse {
+    boolean response();
+}

+ 133 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/LoginResponse.java

@@ -0,0 +1,133 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.asn1bean.ber.types.BerEnum;
+import com.beanit.asn1bean.ber.types.BerInteger;
+import com.beanit.asn1bean.ber.types.BerOctetString;
+import com.beanit.enums.eAuthInfo;
+import com.beanit.enums.ePdusPr;
+import com.beanit.enums.eRejectLogin;
+import com.beanit.its.*;
+import com.beanit.utils.ItsAsnUtils;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+import java.math.BigInteger;
+
+@Slf4j
+public class LoginResponse implements ItsAsnResponse {
+    private final CenterDto center;
+    private final C2CAuthenticatedMessage c2c;
+
+    public LoginResponse(CenterDto center, C2CAuthenticatedMessage c2c) {
+        this.center = center;
+        this.c2c = c2c;
+    }
+
+    @Override
+    public boolean response() {
+        boolean result;
+        try {
+            MDC.put("id", this.center.getLogKey());
+            log.info("LoginResponse.response: [{}, {}].", this.center.getLogKey(), this.center.getIpAddress());
+            PDUs loginPdUs = this.c2c.getPdu();
+            eAuthInfo cmd = eAuthInfo.getByValue(this.c2c.getDatexAuthenticationInfoText().value[0]);
+            ePdusPr pdu = ItsAsnUtils.getPduChoice(loginPdUs);
+            if (cmd == null || pdu == null) {
+                log.error("LoginResponse.response: [{}, {}]. AuthInfo Error, Auth {}, PDUs {}", this.center.getLogKey(), this.center.getIpAddress(), cmd, pdu);
+                return false;
+            }
+            if (cmd != eAuthInfo.AI_Login || pdu != ePdusPr.PDUs_PR_login) {
+                log.error("LoginResponse.response: [{}, {}]. Miss Matched Login Message, Auth {}, PDUs {}. will be closed.", this.center.getLogKey(), this.center.getIpAddress(), cmd, pdu);
+                return false;
+            }
+
+            Login login = loginPdUs.getLogin();
+//            String datexSenderTxt      = new String(login.getDatexSenderTxt().value);
+//            String datexDestinationTxt  = new String(login.getDatexDestinationTxt().value);
+            String datexLoginUserNameTxt       = new String(login.getDatexLoginUserNameTxt().value);
+            String datexLoginPasswordTxt       = new String(login.getDatexLoginPasswordTxt().value);
+            BigInteger datexLoginHeartbeatDurationMaxQty  = login.getDatexLoginHeartbeatDurationMaxQty().value;
+            BigInteger datexLoginResponseTimeOutQty = login.getDatexLoginResponseTimeOutQty().value;
+//            BigInteger datexLoginInitiatorCd     = login.getDatexLoginInitiatorCd().value;
+//            BigInteger datexLoginDatagramSizeQty    = login.getDatexLoginDatagramSizeQty().value;
+
+//            log.info("LoginResponse.response: [{}, {}]. {}, {}, {}, {}, Login {}.", this.center.getLogKey(), this.center.getIpAddress(), datexSenderTxt, datexDestinationTxt, datexLoginUserNameTxt, datexLoginPasswordTxt, login);
+
+            eRejectLogin rejectLogin = eRejectLogin.Reject_Login_cd_other;
+            if (!this.center.getDatexUser().equals(datexLoginUserNameTxt) || !this.center.getDatexPasswd().equals(datexLoginPasswordTxt)) {
+                log.error("LoginResponse.response: [{}, {}]. Login Invalid Name or Password {}, {}. will be closed.", this.center.getLogKey(), this.center.getIpAddress(), datexLoginUserNameTxt, datexLoginPasswordTxt);
+                rejectLogin = eRejectLogin.Reject_Login_cd_invalidNamePassword;
+            }
+            if (datexLoginHeartbeatDurationMaxQty.intValue() < 10) {
+                rejectLogin = eRejectLogin.Reject_Login_cd_heartbeatTooSmall;
+                log.error("LoginResponse.response: [{}, {}]. Login Heartbeat too small {}. will be closed.", this.center.getLogKey(), this.center.getIpAddress(), datexLoginHeartbeatDurationMaxQty);
+            }
+            if (datexLoginHeartbeatDurationMaxQty.intValue() > 1000) {
+                rejectLogin = eRejectLogin.Reject_Login_cd_heartbeatTooLarge;
+                log.error("LoginResponse.response: [{}, {}]. Login Heartbeat too large {}. will be closed.", this.center.getLogKey(), this.center.getIpAddress(), datexLoginHeartbeatDurationMaxQty);
+            }
+
+            if (datexLoginResponseTimeOutQty.intValue() < 3) {
+                rejectLogin = eRejectLogin.Reject_Login_cd_timeoutTooSmall;
+                log.error("LoginResponse.response: [{}, {}]. Login Timeout too small {}. will be closed.", this.center.getLogKey(), this.center.getIpAddress(), datexLoginResponseTimeOutQty);
+            }
+            if (datexLoginResponseTimeOutQty.intValue() > 120) {
+                rejectLogin = eRejectLogin.Reject_Login_cd_timeoutTooSmall;
+                log.error("LoginResponse.response: [{}, {}]. Login Timeout too large {}. will be closed.", this.center.getLogKey(), this.center.getIpAddress(), datexLoginResponseTimeOutQty);
+            }
+
+            byte[] auth = new byte[1];
+            PDUs pdUs = new PDUs();
+
+            if (rejectLogin != eRejectLogin.Reject_Login_cd_other) {
+                auth[0] = eAuthInfo.AI_Reject.getValue();
+
+                RejectType rjtType = new RejectType();
+                rjtType.setDatexRejectLoginCd(new BerEnum(rejectLogin.getValue()));
+
+                Reject reject = new Reject();
+                reject.setDatexRejectPacketNbr(c2c.getDatexDataPacketNumber());
+                reject.setDatexRejectType(rjtType);
+
+                pdUs.setReject(reject);
+            }
+            else {
+                auth[0] = eAuthInfo.AI_Accept.getValue();
+
+                Accept.DatexAcceptType acptType = new Accept.DatexAcceptType();
+                acptType.setLogIn(login.getDatexLoginEncodingRulesId().getBerObjectIdentifier().get(0));
+
+                Accept accept = new Accept();
+                accept.setDatexAcceptPacketNbr(c2c.getDatexDataPacketNumber());
+                accept.setDatexAcceptType(acptType);
+
+                pdUs.setAccept(accept);
+            }
+
+            HeaderOptions hdrOpts = ApplicationRepository.getHeaderOptions(this.center);
+
+            C2CAuthenticatedMessage resC2c = new C2CAuthenticatedMessage();
+            resC2c.setDatexAuthenticationInfoText(new BerOctetString(auth));
+            resC2c.setDatexDataPacketNumber(new BerInteger(this.center.getSeq().nextValue()));
+            resC2c.setDatexDataPacketPriorityNumber(new BerInteger(1));
+            resC2c.setOptions(hdrOpts);
+            resC2c.setPdu(pdUs);
+
+            result = this.center.sendData(resC2c, "AI_Login-Response");
+            if (result) {
+                this.center.getNetState().loginOk();
+            }
+        }
+        catch (Exception e) {
+            log.error("LoginResponse.response: [{}, {}]. Packet send Exception. will be closed. {}", this.center.getLogKey(), this.center.getIpAddress(), e.getMessage());
+            result = false;
+        }
+        finally {
+            MDC.clear();
+        }
+        return result;
+    }
+
+}

+ 36 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/LogoutResponse.java

@@ -0,0 +1,36 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+@Slf4j
+public class LogoutResponse implements ItsAsnResponse {
+    private final CenterDto center;
+    private final C2CAuthenticatedMessage c2c;
+
+    public LogoutResponse(CenterDto center, C2CAuthenticatedMessage c2c) {
+        this.center = center;
+        this.c2c = c2c;
+    }
+
+    @Override
+    public boolean response() {
+        boolean result = true;
+        try {
+            MDC.put("id", this.center.getLogKey());
+            log.info("LogoutResponse.response: [{}, {}].", this.center.getLogKey(), this.center.getIpAddress());
+            ApplicationRepository.closeChannel(this.center, this.center.getNetState().getChannel());
+        }
+        catch (Exception e) {
+            log.error("LogoutResponse.response: [{}, {}]. Packet send Exception. will be closed. {}", this.center.getLogKey(), this.center.getIpAddress(), e.getMessage());
+            result = false;
+        }
+        finally {
+            MDC.clear();
+        }
+        return result;
+    }
+}

+ 28 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/NullResponse.java

@@ -0,0 +1,28 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.its.app.common.utils.NettyUtils;
+import com.its.rota.client.dto.CenterDto;
+import io.netty.channel.ChannelHandlerContext;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class NullResponse implements ItsAsnResponse {
+    private CenterDto obj;
+    private ChannelHandlerContext ctx;
+    private C2CAuthenticatedMessage c2c;
+
+    public NullResponse(CenterDto obj, ChannelHandlerContext ctx, C2CAuthenticatedMessage c2c) {
+        this.obj = obj;
+        this.ctx = ctx;
+        this.c2c = c2c;
+    }
+
+    @Override
+    public boolean response() {
+        // 처리내용 없음. 여기들어오면 패킷이 잘못된 것임
+        String ipAddress = NettyUtils.getRemoteIpAddress(this.ctx.channel());
+        log.info("NullResponse.response: {}", ipAddress);
+        return true;
+    }
+}

+ 111 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/PublicationResponse.java

@@ -0,0 +1,111 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.its.*;
+import com.its.app.common.utils.NettyUtils;
+import com.its.rota.client.dto.CenterDto;
+import io.netty.channel.ChannelHandlerContext;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.util.List;
+
+@Slf4j
+public class PublicationResponse implements ItsAsnResponse {
+    private CenterDto obj;
+    private ChannelHandlerContext ctx;
+    private C2CAuthenticatedMessage c2c;
+
+    public PublicationResponse(CenterDto obj, ChannelHandlerContext ctx, C2CAuthenticatedMessage c2c) {
+        this.obj = obj;
+        this.ctx = ctx;
+        this.c2c = c2c;
+    }
+
+    @Override
+    public boolean response() {
+        String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
+        log.debug("PublicationResponse.response: {}", ipAddress);
+
+        PDUs pdus = this.c2c.getPdu();
+        Publication publication = pdus.getPublication();
+        if (publication == null) {
+           log.error("PublicationResponse.response: {}, Publication data null", ipAddress);
+           return false;
+        }
+
+        boolean guaranteed = publication.getDatexPublishGuaranteedBool().value;
+        PublishFormat publishFormat = publication.getDatexPublishFormat();
+        if (publishFormat.getDatexPublishData() != null) {
+            List<PublicationData> list = publishFormat.getDatexPublishData().getPublicationData();
+            //log.info("PublicationResponse.response: {}. Publication PublishData. size: {} EA", ipAddress, list.size());
+            for (PublicationData data : list) {
+                if (data.getDatexPublishType().getDatexPublishData() != null) {
+                    try {
+                        responsePublicationData(data.getDatexPublishType().getDatexPublishData());
+                    } catch (IOException e) {
+                        log.error("PublicationResponse.response: Exception: {}", e.toString());
+                    }
+                }
+            }
+        }
+        else if (publishFormat.getDatexPublishFileNameTxt() != null) {
+            log.warn("PublicationResponse.response: {}. Publication PublishFileName.", ipAddress);
+        }
+
+        if (guaranteed) {
+            //log.info("PublicationResponse.response: {}. guaranteed: true", ipAddress);
+//            C2CAuthenticatedMessage resC2c = DsrcAsn1Accept.makeC2CAuthenticatedMessage(this.obj, this.ctx.channel(), this.c2c);
+//            if (resC2c != null) {
+//                ChannelFuture f = this.ctx.channel().writeAndFlush(resC2c);
+//                f.awaitUninterruptibly();
+//                if (!f.isDone() || !f.isSuccess()) {
+//                    log.info("PublicationResponse.response: {}. guaranteed: response send failed.", ipAddress);
+//                }
+//            }
+        }
+        return true;
+    }
+
+    private void responsePublicationData(EndApplicationMessage msg) throws IOException {
+//        int objectId = DsrcAsn1Utils.getObjectId(msg.getEndApplicationMessageId().value);
+//        if (objectId == eObjectId.OBJ_ControlDevice.getValue()) {
+//            // RSE Status
+//            ByteArrayInputStream berInputStream = new ByteArrayInputStream(msg.getEndApplicationMessageMsg().value);
+//            ControlDeviceList devices = new ControlDeviceList();
+//            devices.decode(berInputStream);
+//            List<ControlDevice> list = devices.getControlDevice();
+//            log.info("PublicationResponse.responsePublicationData: DSRC Status, objectId: {}, {} EA.", objectId, list.size());
+//            for (ControlDevice controlDevice : list) {
+//                if (controlDevice.getVpbdControlDeviceData() != null) {
+//                    eControlDevice e = eControlDevice.getByValue(controlDevice.getVpbdControlID().value[0]);
+//                    if (e == eControlDevice.Control_StatusRequest) {
+//                        //TODO: DSRC Device Status
+//                        log.info("PublicationResponse.responsePublicationData: {}, OBU Status {}", this.obj.getMcuID(), controlDevice);
+//                        //ControlDeviceService.getInstance().decoding_ControlDevice_Status_AirPoint(this.obj, controlDevice);
+//                        ControlDeviceService.getInstance().decoding_ControlDevice_Status_ITTelecom(this.obj, controlDevice);
+//                    }
+//                    else {
+//                        log.error("PublicationResponse.responsePublicationData: Unknown: {}", e.toString());
+//                    }
+//                }
+//                else {
+//                    log.error("PublicationResponse.responsePublicationData: VpbdControlDeviceData Data Null");
+//                }
+//            }
+//        }
+//        else if (objectId == eObjectId.OBJ_OBUGatherInfo.getValue()) {
+//            // OBE Traffic
+//            //log.info("PublicationResponse.responsePublicationData: DSRC OBU Traffic");
+//            ByteArrayInputStream berInputStream = new ByteArrayInputStream(msg.getEndApplicationMessageMsg().value);
+//            OBUGatherInfoList obuInfos = new OBUGatherInfoList();
+//            obuInfos.decode(berInputStream);
+//            List<OBUGatherInfo> list = obuInfos.getOBUGatherInfo();
+//            //TODO: OBU Gather Info
+//            log.info("PublicationResponse.responsePublicationData: {}, OBU Traffic {} EA", this.obj.getMcuID(), list.size());
+//            OBUGatherInfoService.getInstance().decoding_OBUGatherInfo(this.obj, list);
+//        }
+//        else {
+//            log.error("responsePublicationData.responsePublicationData: Unknown ObjectId: {}", objectId);
+//        }
+    }
+}

+ 75 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/RejectResponse.java

@@ -0,0 +1,75 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.beanit.its.PDUs;
+import com.beanit.its.Reject;
+import com.beanit.its.RejectType;
+import com.its.app.common.utils.NettyUtils;
+import com.its.rota.client.common.SpringUtils;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.process.dbms.DbmsDataProcess;
+import io.netty.channel.ChannelHandlerContext;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class RejectResponse implements ItsAsnResponse {
+    private CenterDto obj;
+    private ChannelHandlerContext ctx;
+    private C2CAuthenticatedMessage c2c;
+    private DbmsDataProcess dbmsDataProcess;
+
+    public RejectResponse(CenterDto obj, ChannelHandlerContext ctx, C2CAuthenticatedMessage c2c) {
+        this.obj = obj;
+        this.ctx = ctx;
+        this.c2c = c2c;
+        this.dbmsDataProcess = SpringUtils.getBean(DbmsDataProcess.class);
+    }
+
+    @Override
+    public boolean response() {
+        String ipAddress = NettyUtils.getRemoteIpAddress(this.ctx.channel());
+        log.info("RejectResponse.response: {}", ipAddress);
+
+        PDUs pdus = this.c2c.getPdu();
+        Reject reject = pdus.getReject();
+        if (reject == null) {
+            log.error("RejectResponse.response: {}, reject data null", ipAddress);
+            return false;
+        }
+
+        long dataPacketNmbr = c2c.getDatexDataPacketNumber().value.longValue();
+        Long  rejectPacketNmbr = reject.getDatexRejectPacketNbr().value.longValue();
+        RejectType rejectType = reject.getDatexRejectType();
+
+//        TbRseCtrlHs command = null;
+        int rejectCode = 0;
+        if (rejectType.getDatexRejectLoginCd() != null) {
+            rejectCode = rejectType.getDatexRejectLoginCd().value.intValue();
+            log.error("RejectResponse.response: {}. RejectLoginCd: dataPacketNmbr: {}, rejectPacketNmbr: {}, rejectCode: {}", ipAddress, dataPacketNmbr, rejectPacketNmbr, rejectCode);
+            // TODO: 클라이언트와의 연결을 종료한다.
+            //ItsAsnServerIdleStatePacketHandler.disconnectChannel(this.obj, this.ctx.channel());
+        }
+        else if (rejectType.getDatexRejectSubscriptionCd() != null) {
+            rejectCode = rejectType.getDatexRejectSubscriptionCd().value.intValue();
+            log.error("RejectResponse.response: {}. RejectSubscription: dataPacketNmbr: {}, rejectPacketNmbr: {}, rejectCode: {}", ipAddress, dataPacketNmbr, rejectPacketNmbr, rejectCode);
+//            this.obj.removeRegisteredCommands(rejectPacketNmbr, true);
+//            command = this.obj.getUserCommands(rejectPacketNmbr);
+        }
+        else if (rejectType.getDatexRejectPublicationCd() != null) {
+            rejectCode = rejectType.getDatexRejectPublicationCd().value.intValue();
+            log.error("RejectResponse.response: {}. RejectPublication: dataPacketNmbr: {}, rejectPacketNmbr: {}, rejectCode: {}", ipAddress, dataPacketNmbr, rejectPacketNmbr, rejectCode);
+//            this.obj.removeRegisteredCommands(rejectPacketNmbr, true);
+//            command = this.obj.getUserCommands(rejectPacketNmbr);
+        }
+
+//        if (command != null) {
+//            log.error("RejectResponse.response: {}. Reject User Command: dataPacketNmbr: {}, rejectPacketNmbr: {}, rejectCode: {}", ipAddress, dataPacketNmbr, rejectPacketNmbr, rejectCode);
+////            this.obj.removeUserCommands(rejectPacketNmbr);
+////            // TODO: 제어명령 전송정보 전송(실패)
+////            command.setRspsType("4");  // 명령 실패(REJECT)로 설정
+////            RseCtlrMapper mapper = (RseCtlrMapper) AppUtils.getBean(RseCtlrMapper.class);
+////            mapper.updateRseCtrlHs(command);
+//        }
+        return true;
+    }
+}

+ 107 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/SubscriptionResponse.java

@@ -0,0 +1,107 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.asn1bean.ber.types.BerEnum;
+import com.beanit.enums.eObjectId;
+import com.beanit.enums.eRejectSubscription;
+import com.beanit.its.*;
+import com.beanit.utils.ItsAsnUtils;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.xnet.client.process.request.AiAccept;
+import com.its.rota.client.xnet.client.process.request.AiReject;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+@Slf4j
+public class SubscriptionResponse implements ItsAsnResponse {
+    private final CenterDto center;
+    private final C2CAuthenticatedMessage c2c;
+
+    public SubscriptionResponse(CenterDto center, C2CAuthenticatedMessage c2c) {
+        this.center = center;
+        this.c2c = c2c;
+    }
+
+    @Override
+    public boolean response() {
+        // AI_Accept or AI_Reject 로 응답
+        boolean result = true;
+        boolean accepted = true;
+        try {
+            MDC.put("id", this.center.getLogKey());
+            log.info("SubscriptionResponse.response: [{}, {}].", this.center.getLogKey(), this.center.getIpAddress());
+
+            int dataPacketNmbr = this.c2c.getDatexDataPacketNumber().intValue();
+            int objectId = 0;
+            C2CAuthenticatedMessage c2c = null;
+            PDUs pdUs = this.c2c.getPdu();
+            Subscription subscription = pdUs.getSubscription();
+            if (subscription != null) {
+                int subscribeSerialNbr = subscription.getDatexSubscribeSerialNbr().intValue();
+                SubscriptionType subscriptionType = subscription.getDatexSubscribeType();
+                BerEnum cancelReasonCd = subscriptionType.getDatexSubscribeCancelReasonCd();
+                if (subscriptionType != null) {
+                    SubscriptionData subscriptionData = subscriptionType.getSubscription();
+                    if (subscriptionData != null) {
+//                        boolean persistentBool = subscriptionData.getDatexSubscribePersistentBool().value;
+//                        int statusCd           = subscriptionData.getDatexSubscribeStatusCd().value.intValue();   // new, update
+//                        int publishFormatCd    = subscriptionData.getDatexSubscribePublishFormatCd().value.intValue();
+//                        int priorityNbr        = subscriptionData.getDatexSubscriptionPriorityNbr().value.intValue();
+                        boolean guaranteeBool  = subscriptionData.getDatexSubscribeGuaranteeBool().value;
+
+                        objectId = ItsAsnUtils.getObjectId(subscriptionData.getDatexSubscribePdu().getEndApplicationMessageId().value);
+                        log.info("SubscriptionResponse.response: [{}, {}]. objectId: {}", this.center.getLogKey(), this.center.getIpAddress(), objectId);
+
+                        if (objectId < eObjectId.OBJ_CurrentLinkState.getValue() && objectId  > eObjectId.OBJ_DetectorCollection.getValue()) {
+                            // Reject
+                            accepted = false;
+                            c2c = AiReject.makeMessage(this.center, this.c2c, eRejectSubscription.Reject_Subscription_cd_invalidSubscriptionMsgId.getValue());
+                            log.info("SubscriptionResponse.response: [{}, {}]. objectId: {}, Reject.", this.center.getLogKey(), this.center.getIpAddress(), objectId);
+                        }
+                        else {
+                            SubscriptionMode subscriptionMode = subscriptionData.getDatexSubscribeMode();
+                            if (subscriptionMode != null) {
+                                // subscriptionMode = single, event-driven, periodic
+                                if (subscriptionMode.getSingle() != null) {
+                                    log.info("SubscriptionResponse.response: [{}, {}]. subscriptionMode-Single.", this.center.getLogKey(), this.center.getIpAddress());
+                                    //subscriptionService = SubscriptionSingleService.getInstance();
+                                } else if (subscriptionMode.getEventDriven() != null) {
+                                    log.info("SubscriptionResponse.response: [{}, {}]. subscriptionMode-EventDriven.", this.center.getLogKey(), this.center.getIpAddress());
+                                    //subscriptionService = SubscriptionRegisterService.getInstance();
+                                } else if (subscriptionMode.getPeriodic() != null) {
+                                    log.info("SubscriptionResponse.response: [{}, {}]. subscriptionMode-Periodic.", this.center.getLogKey(), this.center.getIpAddress());
+                                    //subscriptionService = SubscriptionRegisterService.getInstance();
+                                }
+                                if (guaranteeBool) {
+                                    c2c = AiAccept.makeMessage(this.center, this.c2c);
+                                }
+                            }
+                            else {
+                                log.warn("SubscriptionResponse.response: [{}, {}]. subscriptionMode is null.", this.center.getLogKey(), this.center.getIpAddress());
+                            }
+                        }
+                    }
+                }
+                else if (cancelReasonCd != null) {
+                    // Cancel
+                    int cancelReasonId = cancelReasonCd.value.intValue();
+                    c2c = AiAccept.makeMessage(this.center, this.c2c);
+                    log.info("SubscriptionResponse.response: [{}, {}]. Accept, cancelReasonCd: {}.", this.center.getLogKey(), this.center.getIpAddress(), cancelReasonId);
+                }
+            }
+
+            if (c2c != null) {
+                String sendMsg = accepted ? "AI_Subscription-AI_Accept" : "AI_Subscription-AI_Reject";
+                result = this.center.sendData(c2c, sendMsg);
+            }
+        }
+        catch (Exception e) {
+            log.error("SubscriptionResponse.response: [{}, {}]. Packet send Exception. will be closed. {}", this.center.getLogKey(), this.center.getIpAddress(), e.getMessage());
+            result = false;
+        }
+        finally {
+            MDC.clear();
+        }
+        return result;
+    }
+
+}

+ 31 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/TerminateResponse.java

@@ -0,0 +1,31 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.repository.ApplicationRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+@Slf4j
+public class TerminateResponse implements ItsAsnResponse {
+    private final CenterDto center;
+    private final C2CAuthenticatedMessage c2c;
+
+    public TerminateResponse(CenterDto center, C2CAuthenticatedMessage c2c) {
+        this.center = center;
+        this.c2c = c2c;
+    }
+
+    @Override
+    public boolean response() {
+        try {
+            MDC.put("id", this.center.getLogKey());
+            log.info("TerminateResponse.response: [{}, {}].", this.center.getLogKey(), this.center.getIpAddress());
+            ApplicationRepository.closeChannel(this.center, this.center.getNetState().getChannel());
+        }
+        finally {
+            MDC.clear();
+        }
+        return true;
+    }
+}

+ 28 - 0
src/main/java/com/its/rota/client/xnet/client/process/response/TransferDoneResponse.java

@@ -0,0 +1,28 @@
+package com.its.rota.client.xnet.client.process.response;
+
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.its.app.common.utils.NettyUtils;
+import com.its.rota.client.dto.CenterDto;
+import io.netty.channel.ChannelHandlerContext;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class TransferDoneResponse implements ItsAsnResponse {
+    private CenterDto obj;
+    private ChannelHandlerContext ctx;
+    private C2CAuthenticatedMessage c2c;
+
+    public TransferDoneResponse(CenterDto obj, ChannelHandlerContext ctx, C2CAuthenticatedMessage c2c) {
+        this.obj = obj;
+        this.ctx = ctx;
+        this.c2c = c2c;
+    }
+
+    @Override
+    public boolean response() {
+        // 처리내용 없음.
+        String ipAddress = NettyUtils.getRemoteIpAddress(this.ctx.channel());
+        log.info("TransferDoneResponse.response: {}", ipAddress);
+        return true;
+    }
+}

+ 9 - 19
src/main/java/com/its/rota/client/process/work/DataPacketProcess.java → src/main/java/com/its/rota/client/xnet/client/process/work/DataPacketProcess.java

@@ -1,7 +1,6 @@
-package com.its.rota.client.process.work;
+package com.its.rota.client.xnet.client.process.work;
 
 import com.its.rota.client.config.ApplicationConfig;
-import com.its.rota.client.dto.SigGgitsTsinfoDto;
 import com.its.rota.client.process.AbstractAppProcess;
 import com.its.rota.client.process.AbstractAppWorker;
 import com.its.rota.client.process.dbms.DbmsDataProcess;
@@ -9,7 +8,6 @@ import com.its.rota.client.repository.ApplicationRepository;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
-import org.slf4j.MDC;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.PostConstruct;
@@ -29,35 +27,28 @@ public class DataPacketProcess extends AbstractAppProcess {
         this.workerGroup = new ThreadGroup("PacketProcess");
     }
 
-    public boolean add(Object object, int idx) {
+    public boolean add(Object data, int idx) {
         boolean offer = false;
-        SigGgitsTsinfoDto packet = (SigGgitsTsinfoDto)object;
         try {
             if (idx >= this.workers) {
                 idx = idx % this.workers;
             }
-            offer = this.workerList.get(idx).add(packet);
+            offer = this.workerList.get(idx).add(data);
         }
         catch (Exception e) {
-            MDC.put("id", Long.toString(packet.getLocalPort()));
-            log.error("QUEUE_DATA.add: Exception: {}, {}", packet.getLocalPort(), e.getMessage());
-            MDC.clear();
+            log.error("QUEUE_DATA.add: Exception: {}, {}", data, e.getMessage());
         }
         return offer;
     }
 
     public void run() {
-        this.workers = 0;//this.repo.getCenterMap().size();
-        if (this.workers <= 0) this.workers = 1;
+        this.workers = this.config.getPacketWorkers();
+//        if (!this.repo.getCenterMap().isEmpty() && this.workers > this.repo.getCenterMap().size()) {
+//            this.workers = this.repo.getIpAddressMap().size();
+//        }
         int qSize = this.config.getPacketQueueSize();
-        if (qSize <= 0) {
-            qSize = 1000;
-        }
-
-        qSize *= 4;
-        qSize /= this.workers;
         for (int ii = 0; ii < this.workers; ii++) {
-            DataPacketWorker packetWorker = new DataPacketWorker(ii, qSize, this.repo, this.dbmsDataProcess);
+            DataPacketWorker packetWorker = new DataPacketWorker(this.repo, ii, qSize, this.dbmsDataProcess);
             this.workerList.add(packetWorker);
             Thread worker = new Thread(workerGroup, packetWorker);
             worker.setName(String.format("PacketWorker-%03d.%03d", this.workers, ii+1));
@@ -67,7 +58,6 @@ public class DataPacketProcess extends AbstractAppProcess {
         for (Thread worker : this.threadList) {
             worker.start();
         }
-
     }
 
     public void stop() {

+ 155 - 0
src/main/java/com/its/rota/client/xnet/client/process/work/DataPacketWorker.java

@@ -0,0 +1,155 @@
+package com.its.rota.client.xnet.client.process.work;
+
+import com.beanit.enums.eAuthInfo;
+import com.beanit.its.C2CAuthenticatedMessage;
+import com.its.app.common.utils.Elapsed;
+import com.its.rota.client.dto.CenterDto;
+import com.its.rota.client.dto.RecvPacketDto;
+import com.its.rota.client.process.AbstractAppWorker;
+import com.its.rota.client.process.dbms.DbmsDataProcess;
+import com.its.rota.client.repository.ApplicationRepository;
+import com.its.rota.client.xnet.client.process.response.*;
+import io.netty.channel.Channel;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+
+import java.util.concurrent.LinkedBlockingQueue;
+
+@Slf4j
+public class DataPacketWorker extends AbstractAppWorker implements Runnable {
+
+    private final ApplicationRepository repo;
+    private final DbmsDataProcess dbmsDataProcess;
+
+    private final LinkedBlockingQueue<RecvPacketDto> dataQueue;
+
+    public DataPacketWorker(ApplicationRepository repo, int idx, int qSize, DbmsDataProcess dbmsDataProcess) {
+        this.repo = repo;
+        this.idx = idx;
+        this.qSize = qSize;
+        this.dbmsDataProcess = dbmsDataProcess;
+        this.dataQueue = new LinkedBlockingQueue<>(qSize);
+    }
+
+    @Override
+    public void run() {
+        log.info("{} Start. QSIZE: {}", Thread.currentThread().getName(), this.qSize);
+        while (true) {
+            try {
+                Object packet = this.dataQueue.take();
+                process(packet);
+            }
+            catch (Exception e) {
+                log.error("Exception: {}", e.getMessage());
+            }
+        }
+    }
+
+    /*
+     *  작업큐에 데이터 추가
+     */
+    public boolean add(Object object) {
+        boolean offer = false;
+        RecvPacketDto packet = (RecvPacketDto)object;
+        try {
+            //offer => full -> return
+            //add   => full -> wait
+            offer = this.dataQueue.offer(packet);
+            if (!offer) {
+                MDC.put("id", packet.getCenter().getLogKey());
+                log.error("Packet Queue.offer: [{}]({})/{}, Queue Full: {} EA.",
+                        packet.getCenter().getLogKey(), this.idx, this.dataQueue.size(), this.qSize);
+                MDC.clear();
+            }
+        } catch (Exception e) {
+            MDC.put("id", packet.getCenter().getLogKey());
+            log.error("Packet Queue.offer: Exception: {}, {}, {}", packet.getCenter().getLogKey(), Thread.currentThread().getName(), e.getMessage());
+            MDC.clear();
+        }
+        return offer;
+    }
+
+    public void process(Object object) {
+        boolean isError = false;
+        RecvPacketDto packet = (RecvPacketDto)object;
+        Channel channel = packet.getCenter().getNetState().getChannel();
+        CenterDto center = packet.getCenter();;
+        C2CAuthenticatedMessage c2c = packet.getC2c();
+        try {
+            MDC.put("id", center.getLogKey());
+
+            eAuthInfo cmd = eAuthInfo.getByValue(c2c.getDatexAuthenticationInfoText().value[0]);
+
+            log.info("DataPacketWorker.process: [{}, {}]. cmd {}, ThreadId: {}", center.getLogKey(), center.getIpAddress(), cmd.toString(), Thread.currentThread().getId());
+
+            ItsAsnResponse response = null;
+            switch (cmd) {
+                case AI_Initiate:
+                    break;
+                case AI_Login:
+                    response = new LoginResponse(center, c2c);
+                    break;
+                case AI_FrED:
+                    response = new FredResponse(center, c2c);
+                    break;
+                case AI_Terminate: // 연결을 종료하고자 할 때, 서버에서 클라이언트에 요청하는 데이터 패킷
+                    response = new TerminateResponse(center, c2c);
+                    break;
+                case AI_Logout: // 접속을 종료하기 위한 클라이언트의 로그아웃 데이터 패킷
+                    response = new LogoutResponse(center, c2c);
+                    break;
+                case AI_Subscription: // 클라이언트가 서버에 정보를 요청할 경우 송신하는 데이터 패킷
+                    response = new SubscriptionResponse(center, c2c);
+                    break;
+//                case AI_Publication :   //(0x07, "AI_Publication"),        /* 클라이언트가 요청한 정보를 제공하기 위한 데이터 패킷 - 요청에 대한 정보공개*/
+//                    response = new PublicationResponse(obj, ctx, c2c);
+//                    break;
+                case AI_Accept      :   //(0x09, "AI_Accept"),             /* 클라이언트의 요청에 대한 수용 */
+                    response = new AcceptResponse(center, c2c);
+                    break;
+//                case AI_Reject      :   //(0x0A, "AI_Reject");             /* 클라이언트의 요청에 대한 거부 */
+//                    // 운영단말 명령에 대한 거부도 발생할 수 있으므로 운영단말로 결과를 전송한다.
+//                    response = new RejectResponse(obj, ctx, c2c);
+//                    break;
+//                case AI_TransferDone:   //(0x08, "AI_TransferDone"),       /* 클라이언트가 요청한 정보를 파일형태로 제공하기 위한 데이터 패킷 */
+//                    // 처리내용 없음
+//                    response = new TransferDoneResponse(obj, ctx, c2c);
+//                    break;
+//                case AI_Null        :   //(0x00, "AI_Null"),               /* NULL */
+//                    // 처리내용 없음
+//                    response = new NullResponse(obj, ctx, c2c);
+//                    break;
+                default:
+                    break;
+            }
+
+            if (response != null) {
+                if (!response.response()) {
+                    log.error("TcpServerDataProcess.process: [{}, {}]. response error. will be closed.", center.getLogKey(), center.getIpAddress());
+                    isError = true;
+                }
+            }
+            else {
+                log.error("DataPacketWorker.process: [{}, {}]. Unknown packet cmd: {}. will be closed.", center.getLogKey(), center.getIpAddress(), cmd.toString());
+                isError = true;
+            }
+        }
+        catch (Exception e) {
+            log.error("DataPacketWorker.process: [{}, {}]. Exception, will be closed. {}", center.getLogKey(), center.getIpAddress(), e.getMessage());
+            isError = true;
+        }
+        finally {
+            MDC.remove(center.getLogKey());
+            MDC.clear();
+        }
+
+        if (isError) {
+            ApplicationRepository.closeChannel(center, channel);
+        }
+    }
+
+    public void report() {
+        long avgTime = 0;
+        log.info("Packet: Remain Q: {}, Average: {}, {}", this.dataQueue.size(), Elapsed.elapsedTimeStr(avgTime), Thread.currentThread().getName());
+    }
+}

+ 13 - 13
src/main/resources/mybatis/mapper/IncidentMapper.xml

@@ -27,20 +27,20 @@
                                  UPDATETYPECODE,
                                  UPDATETYPEOTHER,
                                  SENDYN)
-        VALUES(:rec.szToCenterId,
-               :rec.szLinkNumber,
+        VALUES(#{TOCENTERID},
+               #{LINK_LINKIDNUMBER},
                SYSDATE,
-               :rec.szFromCenterId,
-               :rec.szNodeNumber,
-               :rec.szContactOrganizationNameText,
-               :rec.nDescriptionTypeIncidentCode,
-               :rec.szDescriptionTypeIncidentOther,
-               :rec.nIncidentVehiclesInvolvedCode,
-               :rec.szIncidentVehiclesInvolvedOther,
-               :rec.nIncidentStatusCode,
-               :rec.szIncidentStatusOther,
-               :rec.nUpdateTypeCode,
-               :rec.szUpdateTypeOther,
+               #{FROMCENTERID},
+               #{NODE_NODEIDNUMBER},
+               #{CONTACTORGANIZATIONNAMETEXT},
+               #{DESCRIPTIONTYPEINCIDENTCODE},
+               #{DESCRIPTIONTYPEINCIDENTOTHER},
+               #{INCIDENTVEHICLESINVOLVEDCODE},
+               #{INCIDENTVEHICLESINVOLVEDOTHER},
+               #{INCIDENTSTATUSCODE},
+               #{INCIDENTSTATUSOTHER},
+               #{UPDATETYPECODE},
+               #{UPDATETYPEOTHER},
                'N')
         ]]>
     </insert>