648540858
2022-08-15 c041aaccb43baf73d1a9f5b50fb5a1f410b88523
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
 
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.SipLayer;
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
import gov.nist.javax.sip.ResponseEventExt;
import gov.nist.javax.sip.message.SIPResponse;
import gov.nist.javax.sip.stack.SIPDialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import javax.sdp.SdpFactory;
import javax.sdp.SdpParseException;
import javax.sdp.SessionDescription;
import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.UserAgentHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
 
 
/**
 * @description: 处理INVITE响应
 * @author: panlinlin
 * @date: 2021年11月5日 16:40
 */
@Component
public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
 
    private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
    private final String method = "INVITE";
 
    @Autowired
    private VideoStreamSessionManager streamSession;
 
    @Autowired
    private SIPProcessorObserver sipProcessorObserver;
 
    @Autowired
    private SipConfig sipConfig;
 
    @Autowired
    private SipFactory sipFactory;
 
    @Override
    public void afterPropertiesSet() throws Exception {
        // 添加消息处理的订阅
        sipProcessorObserver.addResponseProcessor(method, this);
    }
 
 
 
    /**
     * 处理invite响应
     * 
     * @param evt 响应消息
     * @throws ParseException
     */
    @Override
    public void process(ResponseEvent evt ){
        try {
            Response response = evt.getResponse();
            int statusCode = response.getStatusCode();
            // trying不会回复
            if (statusCode == Response.TRYING) {
            }
            // 成功响应
            // 下发ack
            if (statusCode == Response.OK) {
                ResponseEventExt event = (ResponseEventExt)evt;
                SIPDialog dialog = (SIPDialog)evt.getDialog();
                CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
                Request reqAck = dialog.createAck(cseq.getSeqNumber());
                SipURI requestURI = (SipURI) reqAck.getRequestURI();
                String contentString = new String(response.getRawContent());
                // jainSip不支持y=字段, 移除以解析。
                int ssrcIndex = contentString.indexOf("y=");
                // 检查是否有y字段
                SessionDescription sdp;
                if (ssrcIndex >= 0) {
                    //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段
                    String substring = contentString.substring(0, contentString.indexOf("y="));
                    sdp = SdpFactory.getInstance().createSessionDescription(substring);
                } else {
                    sdp = SdpFactory.getInstance().createSessionDescription(contentString);
                }
                requestURI.setUser(sdp.getOrigin().getUsername());
                try {
                    requestURI.setHost(event.getRemoteIpAddress());
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                requestURI.setPort(event.getRemotePort());
                reqAck.setRequestURI(requestURI);
                List<String> agentParam = new ArrayList<>();
                agentParam.add("wvp-pro");
                // TODO 添加版本信息以及日期
                UserAgentHeader userAgentHeader = null;
                try {
                    userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
                reqAck.addHeader(userAgentHeader);
                Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
                reqAck.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
                logger.info("[回复ack] {}-> {}:{} ",requestURI, event.getRemoteIpAddress(), event.getRemotePort());
 
                dialog.sendAck(reqAck);
 
            }
        } catch (InvalidArgumentException | SipException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            throw new RuntimeException(e);
        } catch (SdpParseException e) {
            throw new RuntimeException(e);
        }
    }
 
}