HANTE vor 1 Tag
Ursprung
Commit
a3cf8e5009

+ 23 - 4
src/main/java/com/tsi/comm/server/process/packet/TsiChannelSession.java

@@ -1,5 +1,7 @@
 package com.tsi.comm.server.process.packet;
 
+import com.tsi.app.common.utils.SysUtils;
+import com.tsi.comm.server.protocol.TsiCpuPacket;
 import com.tsi.comm.server.vo.TsiNodeVo;
 import lombok.extern.slf4j.Slf4j;
 import org.slf4j.MDC;
@@ -17,7 +19,6 @@ public class TsiChannelSession {
                 final String logKey = nodeVo.getKey();
                 MDC.put("id", logKey);
                 log.info("Node: {}, ---Connect, Connects: {}, {}", nodeVo.getNodeId(), nodeVo.getConnectCount().get(), remoteIpAddress);
-                MDC.remove(logKey);
                 MDC.clear();
             }
         }
@@ -32,7 +33,6 @@ public class TsiChannelSession {
                 final String logKey = nodeVo.getKey();
                 MDC.put("id", logKey);
                 log.info("Node: {}, Disconnect, Connects: {}, {}", nodeVo.getNodeId(), nodeVo.getConnectCount().get(), remoteIpAddress);
-                MDC.remove(logKey);
                 MDC.clear();
             }
         }
@@ -47,7 +47,6 @@ public class TsiChannelSession {
                 final String logKey = nodeVo.getKey();
                 MDC.put("id", logKey);
                 log.info("Node: {}, Registered, Connects: {}, {}", nodeVo.getNodeId(), nodeVo.getConnectCount().get(), remoteIpAddress);
-                MDC.remove(logKey);
                 MDC.clear();
             }
         }
@@ -62,7 +61,27 @@ public class TsiChannelSession {
                 final String logKey = nodeVo.getKey();
                 MDC.put("id", logKey);
                 log.info("Node: {}, RcvTimeout, Connects: {}, {}", nodeVo.getNodeId(), nodeVo.getConnectCount().get(), remoteIpAddress);
-                MDC.remove(logKey);
+                MDC.clear();
+            }
+        }
+        catch (Exception e) {
+            // Log the exception with a meaningful message
+        }
+    }
+
+    public static void recvPacketDump(TsiNodeVo nodeVo, TsiCpuPacket packet) {
+        try {
+            if (nodeVo != null) {
+                final String logKey = nodeVo.getKey();
+                MDC.put("id", logKey);
+                byte[] buf = packet.getBuf();
+                if (buf == null || buf.length == 0) {
+                    log.info("RECV: {}, null bytes.", nodeVo.getNodeId());
+                }
+                else {
+//                    log.info("RECV: {}, {} bytes, {}", nodeVo.getNodeId(), buf.length, HexString.fromBytes(buf));
+                    log.info("RECV: {}, {} bytes, {}", nodeVo.getNodeId(), buf.length, SysUtils.byteArrayToHex(packet.getBuf()));
+                }
                 MDC.clear();
             }
         }

+ 20 - 11
src/main/java/com/tsi/comm/server/process/packet/TsiCvimPacketWorker.java

@@ -120,13 +120,11 @@ public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnab
                         this.idx, packet.getNodeId(),
                         this.DATA_QUEUE.size(), this.qSize, this.DATA_QUEUE.remainingCapacity(),
                         TimeUtils.elapsedTime(packet.getRcv()), Thread.currentThread().getName());
-                MDC.remove(Long.toString(packet.getNodeId()));
                 MDC.clear();
             }
         } catch (Exception e) {
             MDC.put("id", Long.toString(packet.getNodeId()));
             log.error("PacketWorker({}): Queue.offer: Exception: {}, {}, {}", this.idx, packet.getNodeId(), Thread.currentThread().getName(), e.getMessage());
-            MDC.remove(Long.toString(packet.getNodeId()));
             MDC.clear();
         }
         return offer;
@@ -182,37 +180,49 @@ public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnab
                 return;
             }
 
-            // 메모리에서 객체를 찾은 후 패킷 파싱
             // 20250425: packet parsing 의 로그를 노드별 로그파일에 저장되도록 MDC 위치 변경
             // 20250425: parsing 함수에 packet-check 여부를 같이 넘겨줘서 CRC 체크여부 확인
             try {
                 int result = cpuPacket.parsing(nodeVo, this.cvimServerConfig.isCheckPacket());
                 if (0 != result) {
+                    if (-4 == result) {
+                        return; // 패킷 버퍼가 null 이거나 너무 짧은 경우
+                    }
+                    if (!nodeVo.isConnect()) {
+                        return; // 연결이 끊어진 경우
+                    }
+
                     byte[] buf = cpuPacket.getBuf();
-                    int reqLength = TsiCpuPacket.SIZE_PACKET_DATA + (TsiCpuPacket.SIZE_STATUS_DATA * cpuPacket.getCount());
                     log.error("Node: {}, CPU Packet parsing failed. error: {}.", nodeId, result);
                     log.error("{}", HexString.fromBytes(buf));
+                    byte stx1 = 0x00, stx2 = 0x00, version = 0x00;
+                    if (buf.length > TsiCpuPacket.INDEX_VERSION) {
+                        stx1 = buf[TsiCpuPacket.INDEX_STX1];
+                        stx2 = buf[TsiCpuPacket.INDEX_STX2];
+                        version = buf[TsiCpuPacket.INDEX_VERSION];
+                    }
+
+                    int reqLength = TsiCpuPacket.SIZE_PACKET_DATA + (TsiCpuPacket.SIZE_STATUS_DATA * cpuPacket.getCount());
                     switch (result) {
                         case -1:
-                            log.info("Node: {}, STX Error: {}, {}", nodeId, buf[TsiCpuPacket.INDEX_STX1], buf[TsiCpuPacket.INDEX_STX2]);
+                            log.error("Node: {}, STX Error: {}, {}", nodeId, stx1, stx2);
                             break;
                         case -2:
-                            log.info("Node: {}, Length Error: {}, Version: {}, status count: {}, {}", nodeId, cpuPacket.getLength(), buf[TsiCpuPacket.INDEX_VERSION],
+                            log.error("Node: {}, Length Error: {}, Version: {}, status count: {}, {}", nodeId, cpuPacket.getLength(), version,
                                     cpuPacket.getCount(), reqLength);
                             break;
                         case -3:
-                            log.error("Node: {}, Check Sum Error: Version: {}, recv: {}, calc: {}", nodeId, buf[TsiCpuPacket.INDEX_VERSION], cpuPacket.getCheckSum(),
+                            log.error("Node: {}, Check Sum Error: Version: {}, recv: {}, calc: {}", nodeId, version, cpuPacket.getCheckSum(),
                                     cpuPacket.getCalcCheckSum());
                             break;
                         default:
                             log.error("Node: {}, Packet parsing error: {}", nodeId, result);
                             break;
                     }
+                    return;
                 }
             } catch (Exception e) {
-                if (nodeVo.isConnect()) {
-                    log.warn("Node: {}, CPU Packet parsing error: {}, connect: {}", nodeId, Thread.currentThread().getName(), nodeVo.isConnect());
-                }
+                log.warn("Node: {}, CPU Packet parsing error: {}, connect: {}", nodeId, Thread.currentThread().getName(), nodeVo.isConnect());
             }
 
             packet.setPar(System.nanoTime());
@@ -263,7 +273,6 @@ public class TsiCvimPacketWorker extends AbstractTsiCvimWorker implements Runnab
                 }
             }
         } finally {
-            MDC.remove(logKey);
             MDC.clear();
         }
 

+ 4 - 0
src/main/java/com/tsi/comm/server/protocol/TsiCpuPacket.java

@@ -296,6 +296,10 @@ public class TsiCpuPacket extends AbstractTsiPacket {
 
     public int parsing(TsiNodeVo obj, boolean isCheckPacket) {
 
+        if (this.buf == null || this.buf.length < INDEX_STATUS_HDR+3) {
+            return -4;
+        }
+
         this.opCode = this.buf[INDEX_OPCODE];
         this.dataVer = this.buf[INDEX_VERSION];
         this.length = ByteUtils.getUnsignedShort(this.buf, INDEX_LENGTH);

+ 2 - 4
src/main/java/com/tsi/comm/server/repository/TsiAlarmManager.java

@@ -45,13 +45,12 @@ public class TsiAlarmManager {
         this.UNKNOWN_NODE_SET.add(remoteIpAddress);
 
         final String fileName = "unknown_node";
-        MDC.put("report", fileName);
+        MDC.put("filename", fileName);
         if (nodeId > 0) {
             log.info("Node: {}, {}, unknown node id registered.", nodeId, remoteIpAddress);
         } else {
             log.info("Node: {}, {}", nodeId, remoteIpAddress);
         }
-        MDC.remove(fileName);
         MDC.clear();
     }
     public void loggingUnknownNodePacket(long nodeId, Channel channel, byte[] buf) {
@@ -62,9 +61,8 @@ public class TsiAlarmManager {
         this.UNKNOWN_NODE_BUF_SET.add(remoteIpAddress);
 
         final String fileName = "unknown_node_packet";
-        MDC.put("report", fileName);
+        MDC.put("filename", fileName);
         log.info("Node: {}, {}, [{}]", nodeId, remoteIpAddress, HexString.fromBytes(buf));
-        MDC.remove(fileName);
         MDC.clear();
     }
 

+ 18 - 50
src/main/java/com/tsi/comm/server/repository/TsiReportManager.java

@@ -37,7 +37,7 @@ public class TsiReportManager {
 
     public void reportNodeSessions() {
         final String fileName = "report";
-        MDC.put("report", fileName);
+        MDC.put("filename", fileName);
 
         int nodeCount = this.nodeManager.getTsiNodeVoMap().size();
         log.info("================================================================================================================");
@@ -52,44 +52,6 @@ public class TsiReportManager {
         log.info("{}", String.format("%10s %4s %7s %19s %19s %9s %6s %19s  Remote-Address", "ID", "INTC", "Connect", "Connect Time", "Disconnect Time", "Connected", "Closed", "Last-Recv-Time"));
         log.info("----------------------------------------------------------------------------------------------------------------");
 
-//        this.tsiNodeVoMap.entrySet().stream()
-//                .sorted(Map.Entry.comparingByKey()) // 키값 기준 오름차순 정렬
-//                .forEach(entry -> {
-//                    TsiNodeVo node = entry.getValue();
-//                    String check = (node.isInstalled() ? "Y" : "N")
-//                            + (node.isSendNode() ? "Y" : "N")
-//                            + (node.isSendTest() ? "Y" : "N")
-//                            + (node.isSendCvim() ? "Y" : "N");
-//
-//                    if (node.isRegistered()) {
-//                        registered.getAndIncrement();
-//                    } else {
-//                        unknown++;
-//                    }
-//
-//                    String connect;
-//                    String info;
-//                    if (node.isConnect()) {
-//                        connected++;
-//                        connect = "Y";
-//                        info = NettyUtils.getRemoteAddress(node.getChannel());
-//                    } else {
-//                        connect = "N";
-//                        info = "---";
-//                    }
-//
-//                    String connectTm = sdf.format(new Date(node.getConnectTm()));
-//                    String disconnectTm = sdf.format(new Date(node.getDisconnectTm()));
-//                    String lastCommTm = sdf.format(new Date(node.getLastCommTm()));
-//
-//                    log.info("{}", String.format(
-//                            "%10s %4s %7s %19s %19s %9d %6d %19s  %s",
-//                            node.getKey(), check, connect, connectTm,
-//                            disconnectTm, node.getConnectCount().get(),
-//                            node.getDisconnectCount().get(), lastCommTm, info
-//                    ));
-//                });
-//
         for (Map.Entry<Long, TsiNodeVo> obj : this.nodeManager.getTsiNodeVoMap().entrySet()) {
             TsiNodeVo node = obj.getValue();
             String check = (node.isInstalled() ? "Y" : "N");
@@ -125,13 +87,11 @@ public class TsiReportManager {
         log.info("Total Nodes: {} EA, Registered: {} EA, Unknown: {} EA, Connected: {} EA", nodeCount, registered, unknown, connected);
         log.info("==============================================");
 
-        MDC.remove(fileName);
         MDC.clear();
     }
 
     public void checkSessionTimeout(long timeout) {
         final String fileName = "timeout";
-        MDC.put("report", fileName);
 
         String connectTm;
         String lastCommTm;
@@ -143,21 +103,33 @@ public class TsiReportManager {
             if (node.isConnect()) {
                 if ((currTm - node.getLastCommTm()) > timeout) {
                     try {
+                        String ipAddress = node.getIpAddr();
+                        if (node.getChannel() != null) {
+                            ipAddress = NettyUtils.getRemoteIpAddress(node.getChannel());
+                        }
+
                         AlarmOccrVo alarm = new AlarmOccrVo(AbstractDbmsVo.DBMS_ALARM_OCCR_HS);
                         alarm.setAlarmCode(TsiAlarmConfigVo.COMM_02);
                         alarm.setAlarmTarget(node.getKey());
-                        alarm.setAlarmValue(NettyUtils.getRemoteIpAddress(node.getChannel()));
+                        alarm.setAlarmValue(ipAddress);
                         this.dbmsProcess.add(alarm, (int) Thread.currentThread().getId());
 
                         connectTm = sdf.format(new Date(node.getConnectTm()));
                         lastCommTm = sdf.format(new Date(node.getLastCommTm()));
-                        log.info("Recv Timeout: Node: {}, Connect: {}, LastCommTime: {}, timeout: {}",
+
+                        MDC.put("filename", fileName);
+
+                        log.info("Node: {}, Recv Timeout: Connect: {}, LastCommTime: {}, timeout: {}",
                                 node.getKey(), connectTm, lastCommTm, timeout);
 
+                        MDC.clear();
+
                         TsiChannelSession.sessionTimeout(node, NettyUtils.getRemoteIpAddress(node.getChannel()));
 
-                        node.getChannel().disconnect();
-                        node.getChannel().close();
+                        if (node.getChannel() != null) {
+                            node.getChannel().disconnect();
+                            node.getChannel().close();
+                        }
                     }
                     catch (Exception e) {
                         log.error("checkSessionTimeout: {}", e.getMessage());
@@ -165,14 +137,11 @@ public class TsiReportManager {
                 }
             }
         }
-
-        MDC.remove(fileName);
-        MDC.clear();
     }
 
     public void reportQueueInfo(boolean isAlert) {
         final String fileName = "queue";
-        MDC.put("report", fileName);
+        MDC.put("filename", fileName);
 
         boolean isTail = false;
         int remainingCapacity = 0;
@@ -240,7 +209,6 @@ public class TsiReportManager {
         if (isTail) {
             log.info("================================================================================================================");
         }
-        MDC.remove(fileName);
         MDC.clear();
     }
 

+ 1 - 2
src/main/java/com/tsi/comm/server/tcp/codec/CvimServerByteBufMessageDecoder.java

@@ -1,6 +1,5 @@
 package com.tsi.comm.server.tcp.codec;
 
-import com.tsi.app.common.utils.SysUtils;
 import com.tsi.app.common.utils.TimeUtils;
 import com.tsi.app.common.xnet.NettyUtils;
 import com.tsi.comm.server.config.TsiCvimServerConfig;
@@ -124,7 +123,7 @@ public class CvimServerByteBufMessageDecoder extends MessageToMessageDecoder<Byt
             // 패킷 통계정보 생성
             this.tpmsManager.readPacket(packet);
             if (nodeVo.isDump()) {
-                log.info("RECV: {}, {}", nodeVo.getNodeId(), SysUtils.byteArrayToHex(packet.getBuf()));
+                TsiChannelSession.recvPacketDump(nodeVo, packet);
             }
         }
         catch (Exception e) {

+ 11 - 18
src/main/java/com/tsi/comm/server/tcp/handler/CvimServerInboundMessageHandler.java

@@ -66,40 +66,33 @@ public class CvimServerInboundMessageHandler extends ChannelInboundHandlerAdapte
     @Override
     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
         final String remoteIpAddr = NettyUtils.getRemoteIpAddress(ctx.channel());
+        int sessions = this.sessionManager.remove();
         TsiNodeVo nodeVo = this.sessionManager.getNodeVo(ctx.channel());
         if (nodeVo != null) {
-            nodeVo.setConnect(null);
-            this.sessionManager.removeChannel(ctx.channel());
-
-            // TODO: session disconnect. to be continue
             NodeStatusVo status = new NodeStatusVo(AbstractDbmsVo.DBMS_NODE_STATUS);
             status.setServerId(this.config.getServerId());
             status.setNodeId(nodeVo.getNodeId());
             status.setStatus(0);
-            status.setIpAddr(NettyUtils.getRemoteIpAddress(ctx.channel()));
+            status.setIpAddr(remoteIpAddr);
+            this.dbmsProcess.add(status, (int)Thread.currentThread().getId());
+
             if (this.sessionManager.isServerRun()) {
                 TsiCpuDisconnected packet = new TsiCpuDisconnected(nodeVo.getNodeId(), ctx.channel());
                 packet.setBuf(null);
                 packet.setObj(nodeVo);
                 this.packetProcess.add(packet, nodeVo.getIdx());
-
-                this.dbmsProcess.add(status, (int)Thread.currentThread().getId());
             }
-            else {
-                log.error("{}.channelInactive: Node {}, Logout but server not running: {}", this.getClass().getSimpleName(), nodeVo.getNodeId(), status.toString());
-            }
-            log.error("{}.channelInactive: Node {}, Channel close: {}", this.getClass().getSimpleName(), nodeVo.getNodeId(), ctx.channel());
+            log.info("channelInactive: Node {}, Channel close: {}", nodeVo.getNodeId(), remoteIpAddr);
+            TsiChannelSession.sessionInactive(nodeVo, remoteIpAddr);
 
+            nodeVo.setConnect(null);
+            this.sessionManager.removeChannel(ctx.channel());
             ctx.channel().attr(TsiSessionManager.TSI_NODE_ATTRIBUTE_KEY).set(null);
         }
-
-        // session count decrement
-        int sessions = this.sessionManager.remove();
-        log.info("channelInactive: {}, {} Sessions.", remoteIpAddr, sessions);
-        TsiNodeVo ipNodeVo = this.nodeManager.getIpAddr(remoteIpAddr);
-        if (ipNodeVo != null) {
-            TsiChannelSession.sessionInactive(ipNodeVo, remoteIpAddr);
+        else {
+            log.info("channelInactive: {}, {} Sessions.", remoteIpAddr, sessions);
         }
+
         ctx.fireChannelInactive();
     }
 

+ 8 - 7
src/main/resources/logback-spring.xml

@@ -24,7 +24,7 @@
 
     <property name="MAX_FILESIZE" value="20MB"/>
     <property name="MAX_HISTORY"  value="15"/>
-    <property name="MAX_PROCESS_FILESIZE" value="10MB"/>
+    <property name="MAX_PROCESS_FILESIZE" value="20MB"/>
 
     <property name="LOG_PATTERN_FILE"        value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
     <property name="LOG_PATTERN_ERROR"       value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %msg%n"/>
@@ -95,12 +95,12 @@
 
     <logger name="com.tsi.comm.server.process.packet" level="INFO" additivity="false">
         <appender-ref ref="FILE_PROCESS"/>
-        <appender-ref ref="FILE_LOG"/>
+<!--        <appender-ref ref="FILE_LOG"/>-->
         <appender-ref ref="FILE_ERROR"/>
     </logger>
     <logger name="com.tsi.comm.server.process.logging" level="INFO" additivity="false">
         <appender-ref ref="FILE_PROCESS"/>
-        <appender-ref ref="FILE_LOG"/>
+<!--        <appender-ref ref="FILE_LOG"/>-->
         <appender-ref ref="FILE_ERROR"/>
     </logger>
 
@@ -198,21 +198,22 @@
 <!--            <maxHistory>${MAX_HISTORY}</maxHistory>-->
 <!--        </rollingPolicy>-->
 <!--    </appender>-->
+
     <appender name="FILE_REPORT" class="ch.qos.logback.classic.sift.SiftingAppender">
         <discriminator>
-            <key>report</key>
+            <key>filename</key>
             <defaultValue>${LOG_FILE_NAME_REPORT}</defaultValue>
         </discriminator>
         <sift>
-            <appender name="FILE-${report}" class="ch.qos.logback.core.rolling.RollingFileAppender">
-                <file>${LOG_PATH}/${report}.log</file>
+            <appender name="FILE-${filename}" class="ch.qos.logback.core.rolling.RollingFileAppender">
+                <file>${LOG_PATH}/${filename}.log</file>
                 <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                     <charset>${LOG_CHARSET}</charset>
                     <Pattern>${LOG_PATTERN_PROCESS}</Pattern>
                 </encoder>
 
                 <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-                    <FileNamePattern>${LOG_BACKUP_PATH}/${report}.${LOG_FILE_NAME_PATTERN}</FileNamePattern>
+                    <FileNamePattern>${LOG_BACKUP_PATH}/${filename}.${LOG_FILE_NAME_PATTERN}</FileNamePattern>
                     <maxFileSize>${MAX_FILESIZE}</maxFileSize>
                     <maxHistory>${MAX_HISTORY}</maxHistory>
                 </rollingPolicy>