| package com.genersoft.iot.vmp.gb28181.event; | 
|   | 
| import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent; | 
| import gov.nist.javax.sip.message.SIPRequest; | 
| import org.slf4j.Logger; | 
| import org.slf4j.LoggerFactory; | 
| import org.springframework.scheduling.annotation.Scheduled; | 
| import org.springframework.stereotype.Component; | 
|   | 
| import javax.sip.DialogTerminatedEvent; | 
| import javax.sip.ResponseEvent; | 
| import javax.sip.TimeoutEvent; | 
| import javax.sip.TransactionTerminatedEvent; | 
| import javax.sip.header.CallIdHeader; | 
| import javax.sip.message.Response; | 
| import java.time.Instant; | 
| import java.util.Map; | 
| import java.util.concurrent.ConcurrentHashMap; | 
| import java.util.concurrent.TimeUnit; | 
|   | 
| /** | 
|  * @author lin | 
|  */ | 
| @Component | 
| public class SipSubscribe { | 
|   | 
|     private final Logger logger = LoggerFactory.getLogger(SipSubscribe.class); | 
|   | 
|     private Map<String, SipSubscribe.Event> errorSubscribes = new ConcurrentHashMap<>(); | 
|   | 
|     private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>(); | 
|   | 
|     private Map<String, Instant> okTimeSubscribes = new ConcurrentHashMap<>(); | 
|   | 
|     private Map<String, Instant> errorTimeSubscribes = new ConcurrentHashMap<>(); | 
|   | 
|     //    @Scheduled(cron="*/5 * * * * ?")   //每五秒执行一次 | 
|     //    @Scheduled(fixedRate= 100 * 60 * 60 ) | 
|     @Scheduled(cron="0 0/5 * * * ?")   //每5分钟执行一次 | 
|     public void execute(){ | 
|         logger.info("[定时任务] 清理过期的SIP订阅信息"); | 
|   | 
|         Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5)); | 
|   | 
|         for (String key : okTimeSubscribes.keySet()) { | 
|             if (okTimeSubscribes.get(key).isBefore(instant)){ | 
|                 okSubscribes.remove(key); | 
|                 okTimeSubscribes.remove(key); | 
|             } | 
|         } | 
|         for (String key : errorTimeSubscribes.keySet()) { | 
|             if (errorTimeSubscribes.get(key).isBefore(instant)){ | 
|                 errorSubscribes.remove(key); | 
|                 errorTimeSubscribes.remove(key); | 
|             } | 
|         } | 
|         logger.debug("okTimeSubscribes.size:{}",okTimeSubscribes.size()); | 
|         logger.debug("okSubscribes.size:{}",okSubscribes.size()); | 
|         logger.debug("errorTimeSubscribes.size:{}",errorTimeSubscribes.size()); | 
|         logger.debug("errorSubscribes.size:{}",errorSubscribes.size()); | 
|     } | 
|   | 
|     public interface Event { void response(EventResult eventResult) ; | 
|     } | 
|   | 
|     /** | 
|      * | 
|      */ | 
|     public enum EventResultType{ | 
|         // 超时 | 
|         timeout, | 
|         // 回复 | 
|         response, | 
|         // 事务已结束 | 
|         transactionTerminated, | 
|         // 会话已结束 | 
|         dialogTerminated, | 
|         // 设备未找到 | 
|         deviceNotFoundEvent | 
|     } | 
|   | 
|     public static class EventResult<EventObject>{ | 
|         public int statusCode; | 
|         public EventResultType type; | 
|         public String msg; | 
|         public String callId; | 
|         public EventObject event; | 
|   | 
|         public EventResult(EventObject event) { | 
|             this.event = event; | 
|             if (event instanceof ResponseEvent) { | 
|                 ResponseEvent responseEvent = (ResponseEvent)event; | 
|                 Response response = responseEvent.getResponse(); | 
|                 this.type = EventResultType.response; | 
|                 if (response != null) { | 
|                     this.msg = response.getReasonPhrase(); | 
|                     this.statusCode = response.getStatusCode(); | 
|                 } | 
|                 this.callId = ((CallIdHeader)response.getHeader(CallIdHeader.NAME)).getCallId(); | 
|   | 
|             }else if (event instanceof TimeoutEvent) { | 
|                 TimeoutEvent timeoutEvent = (TimeoutEvent)event; | 
|                 this.type = EventResultType.timeout; | 
|                 this.msg = "消息超时未回复"; | 
|                 this.statusCode = -1024; | 
|                 if (timeoutEvent.isServerTransaction()) { | 
|                     this.callId = ((SIPRequest)timeoutEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId(); | 
|                 }else { | 
|                     this.callId = ((SIPRequest)timeoutEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId(); | 
|                 } | 
|             }else if (event instanceof TransactionTerminatedEvent) { | 
|                 TransactionTerminatedEvent transactionTerminatedEvent = (TransactionTerminatedEvent)event; | 
|                 this.type = EventResultType.transactionTerminated; | 
|                 this.msg = "事务已结束"; | 
|                 this.statusCode = -1024; | 
|                 if (transactionTerminatedEvent.isServerTransaction()) { | 
|                     this.callId = ((SIPRequest)transactionTerminatedEvent.getServerTransaction().getRequest()).getCallIdHeader().getCallId(); | 
|                 }else { | 
|                     this.callId = ((SIPRequest)transactionTerminatedEvent.getClientTransaction().getRequest()).getCallIdHeader().getCallId(); | 
|                 } | 
|             }else if (event instanceof DialogTerminatedEvent) { | 
|                 DialogTerminatedEvent dialogTerminatedEvent = (DialogTerminatedEvent)event; | 
|                 this.type = EventResultType.dialogTerminated; | 
|                 this.msg = "会话已结束"; | 
|                 this.statusCode = -1024; | 
|                 this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId(); | 
|             }else if (event instanceof DeviceNotFoundEvent) { | 
|                 this.type = EventResultType.deviceNotFoundEvent; | 
|                 this.msg = "设备未找到"; | 
|                 this.statusCode = -1024; | 
|                 this.callId = ((DeviceNotFoundEvent) event).getCallId(); | 
|             } | 
|         } | 
|     } | 
|   | 
|     public void addErrorSubscribe(String key, SipSubscribe.Event event) { | 
|         errorSubscribes.put(key, event); | 
|         errorTimeSubscribes.put(key, Instant.now()); | 
|     } | 
|   | 
|     public void addOkSubscribe(String key, SipSubscribe.Event event) { | 
|         okSubscribes.put(key, event); | 
|         okTimeSubscribes.put(key, Instant.now()); | 
|     } | 
|   | 
|     public SipSubscribe.Event getErrorSubscribe(String key) { | 
|         return errorSubscribes.get(key); | 
|     } | 
|   | 
|     public void removeErrorSubscribe(String key) { | 
|         if(key == null){ | 
|             return; | 
|         } | 
|         errorSubscribes.remove(key); | 
|         errorTimeSubscribes.remove(key); | 
|     } | 
|   | 
|     public SipSubscribe.Event getOkSubscribe(String key) { | 
|         return okSubscribes.get(key); | 
|     } | 
|   | 
|     public void removeOkSubscribe(String key) { | 
|         if(key == null){ | 
|             return; | 
|         } | 
|         okSubscribes.remove(key); | 
|         okTimeSubscribes.remove(key); | 
|     } | 
|     public int getErrorSubscribesSize(){ | 
|         return errorSubscribes.size(); | 
|     } | 
|     public int getOkSubscribesSize(){ | 
|         return okSubscribes.size(); | 
|     } | 
| } |