|
|
|
@ -1,6 +1,6 @@ |
|
|
|
package com.inspect.tcpserver.sip.service; |
|
|
|
|
|
|
|
import com.inspect.tcpserver.sip.items.SipEventRegistry; |
|
|
|
import com.inspect.tcpserver.sip.registry.SipEventRegistry; |
|
|
|
import com.inspect.tcpserver.sip.utils.DigestUtil; |
|
|
|
import com.inspect.tcpserver.sip.utils.SipXmlEnvelope; |
|
|
|
import com.inspect.tcpserver.sip.utils.SipXmlParser; |
|
|
|
@ -23,6 +23,7 @@ import java.io.UnsupportedEncodingException; |
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
import java.security.MessageDigest; |
|
|
|
import java.util.*; |
|
|
|
import java.util.concurrent.ConcurrentHashMap; |
|
|
|
import java.util.concurrent.atomic.AtomicInteger; |
|
|
|
|
|
|
|
@Slf4j |
|
|
|
@ -80,7 +81,20 @@ public class SipClientService implements SipListener { |
|
|
|
|
|
|
|
private AtomicInteger cSeqCounter = new AtomicInteger(1); |
|
|
|
|
|
|
|
String testXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + |
|
|
|
private static class SubscriptionInfo { |
|
|
|
String callId; |
|
|
|
FromHeader from; |
|
|
|
ToHeader to; |
|
|
|
int expires; |
|
|
|
String event; |
|
|
|
} |
|
|
|
|
|
|
|
private final Map<String, SubscriptionInfo> subscriptions = new ConcurrentHashMap<>(); |
|
|
|
|
|
|
|
/* |
|
|
|
* B.2 资源上报 |
|
|
|
*/ |
|
|
|
String resourcesReportTestXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + |
|
|
|
"<SIP_XML EventType=\"Push_Resource\">\n" + |
|
|
|
" <Code>1234567890</Code>\n" + |
|
|
|
" <SubList SubNum=\"50\">\n" + |
|
|
|
@ -137,6 +151,25 @@ public class SipClientService implements SipListener { |
|
|
|
" </SubList>\n" + |
|
|
|
"</SIP_XML>\n"; |
|
|
|
|
|
|
|
/* |
|
|
|
* B.9.2.4.1 告警事件通知 |
|
|
|
*/ |
|
|
|
String alarmEventTestXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + |
|
|
|
"<SIP_XML EventType=\"Notify_Alarm\">\n" + |
|
|
|
"<Item Code=\"ALARM-ADDR-1234567890 \" Name=\"避雷器 \" Type=\"1\" StartTime=\"202501010101\"/>\n" + |
|
|
|
"</SIP_XML>\n"; |
|
|
|
/* |
|
|
|
* B.9.2.4.2 状态事件通知 |
|
|
|
*/ |
|
|
|
String statusEventTestXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + |
|
|
|
"<SIP_XML EventType=\"Notify_Alarm\">\n" + |
|
|
|
"<Item Code=\"STATUS-ADDR-1234567890 \" Name=\"避雷器 \" Type=\"1\" StartTime=\"202501010101\"/>\n" + |
|
|
|
"</SIP_XML>\n"; |
|
|
|
|
|
|
|
String notifyTestXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + |
|
|
|
"<SIP_XML EventType=\"Notify_Test\">\n" + |
|
|
|
"<Type>0</Type>\n" + |
|
|
|
"</SIP_XML>\n"; |
|
|
|
|
|
|
|
@PostConstruct |
|
|
|
public void init() throws Exception { |
|
|
|
@ -216,6 +249,108 @@ public class SipClientService implements SipListener { |
|
|
|
lastRegisterTransaction.sendRequest(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 发送 SUBSCRIBE 请求 |
|
|
|
* |
|
|
|
* @param deviceCode SIP 用户名/设备编号 |
|
|
|
* @param serverIp FreeSWITCH 服务器 IP |
|
|
|
* @param serverPort FreeSWITCH 端口 |
|
|
|
* @param event 订阅事件类型,例如 "presence", "message-summary" |
|
|
|
* @throws Exception |
|
|
|
*/ |
|
|
|
public void sendSubscribe(String deviceCode, String serverIp, int serverPort, String event) throws Exception { |
|
|
|
SipURI requestUri = addressFactory.createSipURI(deviceCode, serverIp); |
|
|
|
requestUri.setPort(serverPort); |
|
|
|
requestUri.setTransportParam(transport.toUpperCase()); |
|
|
|
|
|
|
|
Address fromAddress = addressFactory.createAddress("sip:" + username + "@" + localIp); |
|
|
|
FromHeader fromHeader = headerFactory.createFromHeader(fromAddress, UUID.randomUUID().toString().substring(0, 8)); |
|
|
|
|
|
|
|
Address toAddress = addressFactory.createAddress("sip:" + deviceCode + "@" + serverIp); |
|
|
|
ToHeader toHeader = headerFactory.createToHeader(toAddress, null); |
|
|
|
|
|
|
|
CallIdHeader callId = sipProvider.getNewCallId(); |
|
|
|
CSeqHeader cSeq = headerFactory.createCSeqHeader(cSeqCounter.getAndIncrement(), Request.SUBSCRIBE); |
|
|
|
MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70); |
|
|
|
|
|
|
|
List<ViaHeader> viaHeaders = new ArrayList<>(); |
|
|
|
ViaHeader viaHeader = headerFactory.createViaHeader(localIp, localPort, transport, null); |
|
|
|
viaHeaders.add(viaHeader); |
|
|
|
|
|
|
|
Address contactAddr = addressFactory.createAddress("sip:" + username + "@" + localIp + ":" + localPort); |
|
|
|
ContactHeader contactHeader = headerFactory.createContactHeader(contactAddr); |
|
|
|
|
|
|
|
EventHeader eventHeader = headerFactory.createEventHeader(event); |
|
|
|
|
|
|
|
ExpiresHeader expiresHeader = headerFactory.createExpiresHeader(expires); |
|
|
|
|
|
|
|
Request request = messageFactory.createRequest( |
|
|
|
requestUri, |
|
|
|
Request.SUBSCRIBE, |
|
|
|
callId, |
|
|
|
cSeq, |
|
|
|
fromHeader, |
|
|
|
toHeader, |
|
|
|
viaHeaders, |
|
|
|
maxForwards |
|
|
|
); |
|
|
|
|
|
|
|
request.addHeader(contactHeader); |
|
|
|
request.addHeader(eventHeader); |
|
|
|
request.addHeader(expiresHeader); |
|
|
|
|
|
|
|
ClientTransaction transaction = sipProvider.getNewClientTransaction(request); |
|
|
|
transaction.sendRequest(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 发送带认证头的 SUBSCRIBE |
|
|
|
*/ |
|
|
|
private void sendSubscribeWithAuth(String deviceCode, String serverIp, int serverPort, String event, AuthorizationHeader authHeader) throws Exception { |
|
|
|
SipURI requestUri = addressFactory.createSipURI(deviceCode, serverIp); |
|
|
|
requestUri.setPort(serverPort); |
|
|
|
requestUri.setTransportParam(transport.toUpperCase()); |
|
|
|
|
|
|
|
Address fromAddress = addressFactory.createAddress("sip:" + username + "@" + localIp); |
|
|
|
FromHeader fromHeader = headerFactory.createFromHeader(fromAddress, UUID.randomUUID().toString().substring(0, 8)); |
|
|
|
|
|
|
|
Address toAddress = addressFactory.createAddress("sip:" + deviceCode + "@" + serverIp); |
|
|
|
ToHeader toHeader = headerFactory.createToHeader(toAddress, null); |
|
|
|
|
|
|
|
CallIdHeader callId = sipProvider.getNewCallId(); |
|
|
|
CSeqHeader cSeq = headerFactory.createCSeqHeader(cSeqCounter.getAndIncrement(), Request.SUBSCRIBE); |
|
|
|
MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70); |
|
|
|
|
|
|
|
List<ViaHeader> viaHeaders = new ArrayList<>(); |
|
|
|
ViaHeader viaHeader = headerFactory.createViaHeader(localIp, localPort, transport, null); |
|
|
|
viaHeaders.add(viaHeader); |
|
|
|
|
|
|
|
Address contactAddr = addressFactory.createAddress("sip:" + username + "@" + localIp + ":" + localPort); |
|
|
|
ContactHeader contactHeader = headerFactory.createContactHeader(contactAddr); |
|
|
|
|
|
|
|
EventHeader eventHeader = headerFactory.createEventHeader(event); |
|
|
|
ExpiresHeader expiresHeader = headerFactory.createExpiresHeader(expires); |
|
|
|
|
|
|
|
Request request = messageFactory.createRequest( |
|
|
|
requestUri, |
|
|
|
Request.SUBSCRIBE, |
|
|
|
callId, |
|
|
|
cSeq, |
|
|
|
fromHeader, |
|
|
|
toHeader, |
|
|
|
viaHeaders, |
|
|
|
maxForwards |
|
|
|
); |
|
|
|
|
|
|
|
request.addHeader(contactHeader); |
|
|
|
request.addHeader(eventHeader); |
|
|
|
request.addHeader(expiresHeader); |
|
|
|
request.addHeader(authHeader); |
|
|
|
|
|
|
|
ClientTransaction transaction = sipProvider.getNewClientTransaction(request); |
|
|
|
transaction.sendRequest(); |
|
|
|
} |
|
|
|
|
|
|
|
public void sendXmlResource(String targetSipUri, String xml) throws Exception { |
|
|
|
log.info("Sending XML resource to {}", targetSipUri); |
|
|
|
|
|
|
|
@ -257,10 +392,10 @@ public class SipClientService implements SipListener { |
|
|
|
public void processResponse(ResponseEvent responseEvent) { |
|
|
|
Response response = responseEvent.getResponse(); |
|
|
|
int status = response.getStatusCode(); |
|
|
|
log.info("Received response: {}", status); |
|
|
|
CSeqHeader cSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME); |
|
|
|
if (cSeqHeader == null) return; |
|
|
|
String method = cSeqHeader.getMethod(); |
|
|
|
log.info("Received response: {}, method: {}", status, method); |
|
|
|
|
|
|
|
try { |
|
|
|
if (Request.REGISTER.equalsIgnoreCase(method)) { |
|
|
|
@ -323,10 +458,92 @@ public class SipClientService implements SipListener { |
|
|
|
} |
|
|
|
}, delay * 1000L); |
|
|
|
|
|
|
|
sendNotify(username, domain, port, testXml); |
|
|
|
//sendNotify(username, domain, port, testXml); |
|
|
|
sendSubscribe(username, domain, port, "Push_Resource"); |
|
|
|
} else { |
|
|
|
log.warn("REGISTER response: {}", status); |
|
|
|
} |
|
|
|
} else if (Request.SUBSCRIBE.equalsIgnoreCase(method)) { |
|
|
|
if (status == 401 || status == 407) { |
|
|
|
// TODO: 处理认证,参考 REGISTER 的认证逻辑 |
|
|
|
log.info("SUBSCRIBE 需要认证,返回码 {}", status); |
|
|
|
|
|
|
|
WWWAuthenticateHeader wwwAuth = null; |
|
|
|
ProxyAuthenticateHeader proxyAuth = null; |
|
|
|
|
|
|
|
if (status == 401) { |
|
|
|
wwwAuth = (WWWAuthenticateHeader) response.getHeader(WWWAuthenticateHeader.NAME); |
|
|
|
} else if (status == 407) { |
|
|
|
proxyAuth = (ProxyAuthenticateHeader) response.getHeader(ProxyAuthenticateHeader.NAME); |
|
|
|
} |
|
|
|
|
|
|
|
String realm = null; |
|
|
|
String nonce = null; |
|
|
|
String qop = null; |
|
|
|
if (wwwAuth != null) { |
|
|
|
realm = wwwAuth.getRealm(); |
|
|
|
nonce = wwwAuth.getNonce(); |
|
|
|
qop = wwwAuth.getQop(); |
|
|
|
} else if (proxyAuth != null) { |
|
|
|
realm = proxyAuth.getRealm(); |
|
|
|
nonce = proxyAuth.getNonce(); |
|
|
|
qop = proxyAuth.getQop(); |
|
|
|
} else { |
|
|
|
log.error("No Authenticate header found for SUBSCRIBE"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 保存上次 SUBSCRIBE 请求参数,供重发使用 |
|
|
|
ClientTransaction origTransaction = responseEvent.getClientTransaction(); |
|
|
|
Request origRequest = origTransaction.getRequest(); |
|
|
|
FromHeader fromHeader = (FromHeader) origRequest.getHeader(FromHeader.NAME); |
|
|
|
ToHeader toHeader = (ToHeader) origRequest.getHeader(ToHeader.NAME); |
|
|
|
String deviceCode = ((SipURI) toHeader.getAddress().getURI()).getUser(); |
|
|
|
String serverIp = ((SipURI) toHeader.getAddress().getURI()).getHost(); |
|
|
|
int serverPort = ((SipURI) toHeader.getAddress().getURI()).getPort(); |
|
|
|
serverPort = serverPort < 0 ? 5060 : serverPort; |
|
|
|
log.info("deviceCode: {}, serverIp: {}, serverPort: {}", deviceCode, serverIp, serverPort); |
|
|
|
EventHeader eventHeader = (EventHeader) origRequest.getHeader(EventHeader.NAME); |
|
|
|
String event = eventHeader.getEventType(); |
|
|
|
|
|
|
|
String uri = "sip:" + serverIp + ":" + serverPort; |
|
|
|
String nc = "00000001"; |
|
|
|
String cNonce = generateCNonce(); |
|
|
|
|
|
|
|
String responseDigest = DigestUtil.computeResponse( |
|
|
|
username, |
|
|
|
password, |
|
|
|
realm, |
|
|
|
nonce, |
|
|
|
Request.SUBSCRIBE, |
|
|
|
uri, |
|
|
|
nc, |
|
|
|
cNonce, |
|
|
|
qop |
|
|
|
); |
|
|
|
|
|
|
|
AuthorizationHeader authHeader = headerFactory.createAuthorizationHeader("Digest"); |
|
|
|
authHeader.setUsername(username); |
|
|
|
authHeader.setRealm(realm); |
|
|
|
authHeader.setNonce(nonce); |
|
|
|
authHeader.setURI(addressFactory.createURI(uri)); |
|
|
|
authHeader.setResponse(responseDigest); |
|
|
|
if (qop != null) { |
|
|
|
authHeader.setQop(qop); |
|
|
|
authHeader.setCNonce(cNonce); |
|
|
|
authHeader.setNonceCount(Integer.parseInt(nc, 16)); |
|
|
|
} |
|
|
|
|
|
|
|
// 重发带认证的 SUBSCRIBE |
|
|
|
sendSubscribeWithAuth(deviceCode, serverIp, serverPort, event, authHeader); |
|
|
|
} else if (status >= 200 && status < 300) { |
|
|
|
log.info("SUBSCRIBE 成功: {}", status); |
|
|
|
// 成功订阅后,向服务器上报资源 NOTIFY |
|
|
|
// sendNotify(username, domain, port, resourcesReportTestXml); |
|
|
|
sendNotify(username, domain, port, notifyTestXml); |
|
|
|
} else { |
|
|
|
log.warn("SUBSCRIBE 响应: {}", status); |
|
|
|
} |
|
|
|
} else if (Request.MESSAGE.equalsIgnoreCase(method)) { |
|
|
|
log.info("MESSAGE response: {}", status); |
|
|
|
} else if (Request.NOTIFY.equalsIgnoreCase(method)) { |
|
|
|
@ -413,7 +630,8 @@ public class SipClientService implements SipListener { |
|
|
|
Address contactAddr = addressFactory.createAddress("sip:" + username + "@" + localHost + ":" + localPort); |
|
|
|
ContactHeader contactHeader = headerFactory.createContactHeader(contactAddr); |
|
|
|
|
|
|
|
EventHeader eventHeader = headerFactory.createEventHeader("Push_Resource"); |
|
|
|
// EventHeader eventHeader = headerFactory.createEventHeader("Push_Resource"); |
|
|
|
EventHeader eventHeader = headerFactory.createEventHeader("Notify_Test"); |
|
|
|
|
|
|
|
SubscriptionStateHeader subscriptionStateHeader = headerFactory.createSubscriptionStateHeader(SubscriptionStateHeader.TERMINATED); |
|
|
|
|
|
|
|
@ -477,11 +695,46 @@ public class SipClientService implements SipListener { |
|
|
|
SipXmlEnvelope<?> envelope = SipXmlParser.parse(xml, itemClass); |
|
|
|
//handleSipEvent(envelope); |
|
|
|
} |
|
|
|
} else if (Request.NOTIFY.equalsIgnoreCase(method)) { |
|
|
|
ContentTypeHeader ct = (ContentTypeHeader) request.getHeader(ContentTypeHeader.NAME); |
|
|
|
if (ct != null && "application".equalsIgnoreCase(ct.getContentType()) && "xml".equalsIgnoreCase(ct.getContentSubType())) { |
|
|
|
String xml = new String(request.getRawContent(), StandardCharsets.UTF_8); |
|
|
|
log.info("Received NOTIFY XML:\n{}", xml); |
|
|
|
|
|
|
|
// 可以解析 SUBSCRIBE 通知内容 |
|
|
|
String eventType = SipXmlParser.peekEventType(xml); |
|
|
|
log.info("NOTIFY EventType: {}", eventType); |
|
|
|
|
|
|
|
// 回复 200 OK |
|
|
|
ServerTransaction st = requestEvent.getServerTransaction(); |
|
|
|
if (st == null) { |
|
|
|
st = sipProvider.getNewServerTransaction(request); |
|
|
|
} |
|
|
|
Response ok = messageFactory.createResponse(Response.OK, request); |
|
|
|
st.sendResponse(ok); |
|
|
|
} |
|
|
|
} else if (Request.SUBSCRIBE.equals(request.getMethod())) { |
|
|
|
String xml = new String(request.getRawContent(), StandardCharsets.UTF_8); |
|
|
|
|
|
|
|
ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(ExpiresHeader.NAME); |
|
|
|
int expires = (expiresHeader != null) ? expiresHeader.getExpires() : 0; |
|
|
|
log.info("Received SUBSCRIBE expires: {}, XML:\n{}", expires, xml); |
|
|
|
ServerTransaction transaction = sipProvider.getNewServerTransaction(request); |
|
|
|
Response response = messageFactory.createResponse(Response.OK, request); |
|
|
|
transaction.sendResponse(response); |
|
|
|
|
|
|
|
if (expires > 0) { |
|
|
|
saveSubscription(request, expires); |
|
|
|
sendInitialNotify(request, transaction, "initial"); |
|
|
|
} else { |
|
|
|
removeSubscription(request); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
|
|
|
|
} else { |
|
|
|
Response notImpl = messageFactory.createResponse(Response.NOT_IMPLEMENTED, request); |
|
|
|
requestEvent.getServerTransaction().sendResponse(notImpl); |
|
|
|
log.warn("Method {} not implemented, replied 501", method); |
|
|
|
log.info("Method {} not implemented, replied 501", method); |
|
|
|
} |
|
|
|
} catch (Exception ex) { |
|
|
|
log.error("Error processing request: {}", ex.getMessage(), ex); |
|
|
|
@ -580,4 +833,92 @@ public class SipClientService implements SipListener { |
|
|
|
} |
|
|
|
return sb.toString(); |
|
|
|
} |
|
|
|
|
|
|
|
private void saveSubscription(Request request, int expires) { |
|
|
|
CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); |
|
|
|
ToHeader toHeader = (ToHeader) request.getHeader(ToHeader.NAME); |
|
|
|
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); |
|
|
|
|
|
|
|
String key = callIdHeader.getCallId() + "|" + fromHeader.getTag() + "|" + toHeader.getTag(); |
|
|
|
|
|
|
|
SubscriptionInfo info = new SubscriptionInfo(); |
|
|
|
info.callId = callIdHeader.getCallId(); |
|
|
|
info.from = fromHeader; |
|
|
|
info.to = toHeader; |
|
|
|
info.expires = expires; |
|
|
|
info.event = ((EventHeader) request.getHeader(EventHeader.NAME)).getEventType(); |
|
|
|
|
|
|
|
subscriptions.put(key, info); |
|
|
|
|
|
|
|
System.out.println("保存订阅: " + key + " 有效期 " + expires + " 秒"); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void sendInitialNotify(Request subscribeRequest, ServerTransaction st, String bodyText) { |
|
|
|
try { |
|
|
|
// 获取必要头字段 |
|
|
|
CallIdHeader callIdHeader = (CallIdHeader) subscribeRequest.getHeader(CallIdHeader.NAME); |
|
|
|
CSeqHeader cseqHeader = (CSeqHeader) subscribeRequest.getHeader(CSeqHeader.NAME); |
|
|
|
FromHeader fromHeader = (FromHeader) subscribeRequest.getHeader(FromHeader.NAME); |
|
|
|
ToHeader toHeader = (ToHeader) subscribeRequest.getHeader(ToHeader.NAME); |
|
|
|
EventHeader eventHeader = (EventHeader) subscribeRequest.getHeader(EventHeader.NAME); |
|
|
|
ContactHeader contactHeader = (ContactHeader) subscribeRequest.getHeader(ContactHeader.NAME); |
|
|
|
|
|
|
|
List<ViaHeader> viaHeaders = new ArrayList<>(); |
|
|
|
ViaHeader viaHeader = headerFactory.createViaHeader(localIp, localPort, transport.toUpperCase(), null); |
|
|
|
viaHeaders.add(viaHeader); |
|
|
|
// 创建 NOTIFY 请求 |
|
|
|
Request notifyRequest = messageFactory.createRequest( |
|
|
|
subscribeRequest.getRequestURI(), |
|
|
|
Request.NOTIFY, |
|
|
|
callIdHeader, |
|
|
|
headerFactory.createCSeqHeader(cseqHeader.getSeqNumber() + 1, Request.NOTIFY), |
|
|
|
fromHeader, |
|
|
|
toHeader, |
|
|
|
viaHeaders, |
|
|
|
headerFactory.createMaxForwardsHeader(70) |
|
|
|
); |
|
|
|
|
|
|
|
// 加入 Contact |
|
|
|
notifyRequest.addHeader(contactHeader); |
|
|
|
|
|
|
|
// 必须的事件头 |
|
|
|
notifyRequest.addHeader(eventHeader); |
|
|
|
|
|
|
|
// Subscription-State 头 |
|
|
|
SubscriptionStateHeader ssHeader = headerFactory.createSubscriptionStateHeader("active"); |
|
|
|
ssHeader.setExpires(3600); |
|
|
|
notifyRequest.addHeader(ssHeader); |
|
|
|
|
|
|
|
// 消息体 |
|
|
|
String xmlBody = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + |
|
|
|
"<SIP_XML>\n" + |
|
|
|
" <Type>" + bodyText + "</Type>\n" + |
|
|
|
"</SIP_XML>"; |
|
|
|
ContentTypeHeader contentTypeHeader = headerFactory.createContentTypeHeader("application", "xml"); |
|
|
|
notifyRequest.setContent(xmlBody, contentTypeHeader); |
|
|
|
|
|
|
|
// 发送 |
|
|
|
ClientTransaction ct = sipProvider.getNewClientTransaction(notifyRequest); |
|
|
|
ct.sendRequest(); |
|
|
|
|
|
|
|
System.out.println("发送初始 NOTIFY: " + callIdHeader.getCallId()); |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
e.printStackTrace(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void removeSubscription(Request request) { |
|
|
|
CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); |
|
|
|
ToHeader toHeader = (ToHeader) request.getHeader(ToHeader.NAME); |
|
|
|
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); |
|
|
|
|
|
|
|
String key = callIdHeader.getCallId() + "|" + fromHeader.getTag() + "|" + toHeader.getTag(); |
|
|
|
subscriptions.remove(key); |
|
|
|
|
|
|
|
System.out.println("删除订阅: " + key); |
|
|
|
} |
|
|
|
|
|
|
|
} |