文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

java 对接国标摄像头流程、代码整合 springboot SIP -GB2818

2023-08-18 16:50

关注

java 对接设备的代码资料较少,这里介绍GB2818的基本对接流程,有用自取👇

  • java负责SIP信令的注册交互,推流、拉流鉴权
  • 摄像头负责推流、流媒体负责拉流、转码

wvp-GB28181-pro项目 ,如果java对接各种摄像头,这个项目很👍,比较完善,可参考。进去star 支持一波

做到需要播放摄像头视频需要:

  • 摄像头:视频摄像数据的输出端,协议输出端。
  • SIP服务端:java开发sip信令注册交互,流媒体(推流、播放)鉴权
  • 流媒体服务器:负责注册rtp流媒体,摄像头推流输出端

概念:

国标协议2818 组成:

  • SIP:会话初始协议(Session Initiation Protocol),是一个应用层的 点对点协议,用于初始、管理和终止网络中的语音和视频会话,是 GB28181 的核心之一
    1
  • 流媒体:音视频流的传输与转换

sip服务端:

  • java实现一般采用 JAIN-SIP
  • 项目启动时,初始化tpc、udp端口监听,当有接收sip信令时,会触发相关请求事件

流媒体:

配置摄像头接入:
1

sip注册交互流程:

  • 在这里插入图片描述
    在这里插入图片描述

拉流交互过程:

在这里插入图片描述

摄像头返回推流端口:

在这里插入图片描述

invite 抓包:
1

部分代码示例:

  <dependency>       <groupId>javax.sipgroupId>       <artifactId>jain-sip-riartifactId>       <version>1.3.0-91version>   dependency>

初始监听端口:

  • 参考 panll / wvp-GB28181-pro 项目,👆上面有地址
import com.config.SipConfig;import com.sip.uitl.SipUtil;import gov.nist.javax.sip.SipProviderImpl;import gov.nist.javax.sip.SipStackImpl;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.CommandLineRunner;import org.springframework.stereotype.Component;import org.springframework.util.ObjectUtils;import javax.annotation.Resource;import javax.sip.*;import java.util.*;import java.util.concurrent.ConcurrentHashMap;@Slf4j@Componentpublic class SipInitListen implements CommandLineRunner {    @Resource    private SipConfig sipConfig;        @Resource    private SipProcessListener sipProcessListener;    private SipFactory sipFactory;        private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();        private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();    @Override    public void run(String... args) {        List<String> monitorIps = new ArrayList<>();        // 使用逗号分割多个ip        String separator = ",";        if (sipConfig.getIp().indexOf(separator) > 0) {            String[] split = sipConfig.getIp().split(separator);            monitorIps.addAll(Arrays.asList(split));        }else {            monitorIps.add(sipConfig.getIp());        }        sipFactory = SipFactory.getInstance();        sipFactory.setPathName("gov.nist");        if (monitorIps.size() > 0) {            for (String monitorIp : monitorIps) {                addListeningPoint(monitorIp, sipConfig.getPort());            }            if (udpSipProviderMap.size() + tcpSipProviderMap.size() == 0) {                System.exit(1);            }        }    }        private void addListeningPoint(String monitorIp, int port){        //sip协议栈        SipStackImpl sipStack;        try {            sipStack = (SipStackImpl)sipFactory.createSipStack(SipUtil.defaultProperties(monitorIp, Boolean.FALSE));        } catch (PeerUnavailableException e) {            e.printStackTrace();            log.error("[Sip Server] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp);            return;        }        try {            //创建 TCP传输监听            ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "TCP");            //tcp 消息处理实现            SipProviderImpl tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);            tcpSipProvider.setDialogErrorsAutomaticallyHandled();            tcpSipProvider.addSipListener(sipProcessListener);            tcpSipProviderMap.put(monitorIp, tcpSipProvider);            log.info("[Sip Server] tcp://{}:{} 启动成功", monitorIp, port);        } catch (TransportNotSupportedException                 | TooManyListenersException                 | ObjectInUseException                 | InvalidArgumentException e) {            log.error("[Sip Server] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"                    , monitorIp, port);        }        try {            //创建 UDP传输监听            ListeningPoint udpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "UDP");            //udp 消息处理实现            SipProviderImpl udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);            udpSipProvider.addSipListener(sipProcessListener);            udpSipProviderMap.put(monitorIp, udpSipProvider);            log.info("[Sip Server] udp://{}:{} 启动成功", monitorIp, port);        } catch (TransportNotSupportedException                 | TooManyListenersException                 | ObjectInUseException                 | InvalidArgumentException e) {            log.error("[Sip Server] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确"                    , monitorIp, port);        }    }    public SipFactory getSipFactory() {        return sipFactory;    }    public SipProviderImpl getUdpSipProvider(String ip) {        if (ObjectUtils.isEmpty(ip)) {            return null;        }        return udpSipProviderMap.get(ip);    }    public SipProviderImpl getUdpSipProvider() {        if (udpSipProviderMap.size() != 1) {            return null;        }        return udpSipProviderMap.values().stream().findFirst().get();    }    public SipProviderImpl getTcpSipProvider() {        if (tcpSipProviderMap.size() != 1) {            return null;        }        return tcpSipProviderMap.values().stream().findFirst().get();    }    public SipProviderImpl getTcpSipProvider(String ip) {        if (ObjectUtils.isEmpty(ip)) {            return null;        }        return tcpSipProviderMap.get(ip);    }    public String getLocalIp(String deviceLocalIp) {        if (!ObjectUtils.isEmpty(deviceLocalIp)) {            return deviceLocalIp;        }        return getUdpSipProvider().getListeningPoint().getIPAddress();    }}

摄像头消息监听

import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Component;import javax.annotation.Resource;import javax.sip.*;import javax.sip.header.CSeqHeader;import javax.sip.message.Response;@Component@Slf4jpublic class SipProcessListener implements SipListener {    @Resource    private SipEventService sipEventService;        @Override    public void processRequest(RequestEvent requestEvent) {        log.info("收到摄像机服务请求");        String method = requestEvent.getRequest().getMethod();        log.info("method:"+method);        if (method.equals("REGISTER")){            sipEventService.requestRegister(requestEvent);        }        if (method.equals("MESSAGE")){            sipEventService.requestMessage(requestEvent);        }        if (method.equals("BYE")){            sipEventService.requestBye(requestEvent);        }    }        @Override    public void processResponse(ResponseEvent responseEvent) {        log.info("收到摄像机服务响应");        Response response = responseEvent.getResponse();        int status = response.getStatusCode();        // Success        if (((status >= Response.OK) && (status < Response.MULTIPLE_CHOICES)) || status == Response.UNAUTHORIZED) {            CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);            String method = cseqHeader.getMethod();            log.info("method:"+method);            sipEventService.responseInvite(responseEvent);        } else if ((status >= Response.TRYING) && (status < Response.OK)) {            // 增加其它无需回复的响应,如101、180等        } else {            log.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase());            if (responseEvent.getDialog() != null) {                responseEvent.getDialog().delete();            }        }    }        @Override    public void processTimeout(TimeoutEvent timeoutEvent) {        log.info("收到摄像机 超时回调");    }        @Override    public void processIOException(IOExceptionEvent exceptionEvent) {        log.info("收到摄像机 IO异常的回调");    }        @Override    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {        log.info("收到摄像机 事务中断回调");    }        @Override    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {        log.info("收到摄像机 对话框关闭事件");    }}

业务处理 service

import com.sip.bean.Device;import com.sip.bean.SSRCInfo;import javax.sip.RequestEvent;import javax.sip.ResponseEvent;public interface SipEventService {        void requestRegister(RequestEvent requestEvent);        void requestMessage(RequestEvent requestEvent);        void responseInvite(ResponseEvent responseEvent);        void requestBye(RequestEvent requestEvent);        void sendInvite(Device device, SSRCInfo ssrcInfo);        void getDeviceInfo(Device device);}
@Slf4j@Servicepublic class SipEventServiceImpl implements SipEventService {    @Resource    private RedisTemplate<String,Object> redisTemplate;    @Resource    private SipConfig sipConfig;    @Resource    private SIPSender sipSender;    @Resource    private SipInitListen sipInitListen;    @Resource    private SipProcessResponse sipProcessResponse;    @Resource    private SIPRequestHeaderProvider requestHeaderProvider;    @SneakyThrows    @Override    public void requestRegister(RequestEvent evt) {        RequestEventExt evtExt = (RequestEventExt) evt;        String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort();        log.info("[注册请求] 开始处理: {}", requestAddress);        SIPRequest sipRequest = (SIPRequest) evt.getRequest();        Response response = null;        //密码是否正确        boolean passwordCorrect = false;        // 注册标志        boolean registerFlag;        FromHeader fromHeader = (FromHeader) sipRequest.getHeader(FromHeader.NAME);        AddressImpl address = (AddressImpl) fromHeader.getAddress();        SipUri uri = (SipUri) address.getURI();        //设备ID(保留)        String deviceId = uri.getUser();        //是否携带认证信息        AuthorizationHeader authHead = (AuthorizationHeader) sipRequest.getHeader(AuthorizationHeader.NAME);        String password = sipConfig.getPassword();        if (authHead == null) {            log.info("[注册请求] 摄像头未携带认证信息");            log.info("[注册请求] 回复401: {}", requestAddress);            response = sipProcessResponse.getMessageFactory().createResponse(Response.UNAUTHORIZED, sipRequest);            new DigestServerAuthenticationHelper().generateChallenge(sipProcessResponse.getHeaderFactory(), response, sipConfig.getDomain());            sipSender.send(sipRequest.getLocalAddress().getHostAddress(), response);            return;        }        passwordCorrect = new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(sipRequest, password);        //密码验证失败        if (!passwordCorrect) {            // 注册失败            log.info("[注册请求] 携带认证信息,但是密码验证错误");            response = sipProcessResponse.getMessageFactory().createResponse(Response.FORBIDDEN, sipRequest);            response.setReasonPhrase("wrong password");            log.info("[注册请求] 密码/SIP服务器ID错误, 回复403: {}", requestAddress);            sipSender.send(sipRequest.getLocalAddress().getHostAddress(), response);            return;        }        // 携带授权头并且密码正确        response = sipProcessResponse.getMessageFactory().createResponse(Response.OK, sipRequest);        // 添加date头        SIPDateHeader dateHeader = new SIPDateHeader();        // 使用自己修改的        WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis());        dateHeader.setDate(wvpSipDate);        response.addHeader(dateHeader);        if (sipRequest.getExpires() == null) {            response = sipProcessResponse.getMessageFactory().createResponse(Response.BAD_REQUEST, sipRequest);            sipSender.send(sipRequest.getLocalAddress().getHostAddress(), response);            return;        }        // 添加Contact头        response.addHeader(sipRequest.getHeader(ContactHeader.NAME));        // 添加Expires头        response.addHeader(sipRequest.getExpires());        RemoteAddressInfo remoteAddressInfo = SipUtil.getRemoteAddressFromRequest(sipRequest,false);        String key = "camera-device:"+deviceId;        Device device = (Device)redisTemplate.opsForValue().get(key);        if (device == null) {            device = new Device();            device.setStreamMode("UDP");            device.setCharset("GB2312");            device.setGeoCoordSys("WGS84");            device.setTreeType("CivilCode");            device.setDeviceId(deviceId);            device.setOnline(0);        }        device.setIp(remoteAddressInfo.getIp());        device.setPort(remoteAddressInfo.getPort());        device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));        device.setLocalIp(sipRequest.getLocalAddress().getHostAddress());        if (sipRequest.getExpires().getExpires() == 0) {            // 注销成功            registerFlag = false;        } else {            // 注册成功            device.setExpires(sipRequest.getExpires().getExpires());            registerFlag = true;            // 判断TCP还是UDP            ViaHeader reqViaHeader = (ViaHeader) sipRequest.getHeader(ViaHeader.NAME);            String transport = reqViaHeader.getTransport();            device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");        }        sipSender.send(sipRequest.getLocalAddress().getHostAddress(), response);        // 注册成功        // 保存到redis        if (registerFlag) {            log.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress);            device.setRegisterTime(DateUtil.getNow());            device.setOnline(1);        } else {            log.info("[注销成功] deviceId: {}->{}", deviceId, requestAddress);            device.setOnline(0);        }        redisTemplate.opsForValue().set(key,device);    }    @Override    public void requestMessage(RequestEvent evt) {        SIPRequest sipRequest = (SIPRequest)evt.getRequest();        log.info("接收到消息:" + evt.getRequest());        String deviceId = SipUtil.getUserIdFromFromHeader(evt.getRequest());        CallIdHeader callIdHeader = sipRequest.getCallIdHeader();        SIPRequest request = (SIPRequest) evt.getRequest();        // 查询设备是否存在        String key = "camera-device:"+deviceId;        Device device = (Device)redisTemplate.opsForValue().get(key);        // 查询上级平台是否存在        try {            if (device == null) {                // 不存在则回复404                sipProcessResponse.responseAck(request, Response.NOT_FOUND, "device "+ deviceId +" not found");                log.warn("[设备未找到 ]deviceId: {}, callId: {}", deviceId, callIdHeader.getCallId());            }else {                Element rootElement = null;                try {                    rootElement = sipProcessResponse.getRootElement(evt);                    if (rootElement == null) {                        log.error("处理MESSAGE请求  未获取到消息体{}", evt.getRequest());                        sipProcessResponse.responseAck(request, Response.BAD_REQUEST, "content is null");                        return;                    }                    //message 命令类型                    String cmdType = XmlUtil.getText(rootElement, "CmdType");                    switch (cmdType){                        case "DeviceInfo"://厂家String manufacturer = XmlUtil.getText(rootElement, "Manufacturer");String Channel = XmlUtil.getText(rootElement, "DeviceID");sipProcessResponse.responseAck(sipRequest, Response.OK);return;                        case "Keepalive":sipProcessResponse.responseAck(sipRequest, Response.OK,"注册成功");return;                        default:sipProcessResponse.responseAck(sipRequest, Response.OK);                    }                } catch (DocumentException e) {                    log.warn("解析XML消息内容异常", e);                    // 不存在则回复404                    sipProcessResponse.responseAck(request, Response.BAD_REQUEST, e.getMessage());                }            }        } catch (SipException e) {            log.warn("SIP 回复错误", e);        } catch (InvalidArgumentException e) {            log.warn("参数无效", e);        } catch (ParseException e) {            log.warn("SIP回复时解析异常", e);        }    }    @Override    public void responseInvite(ResponseEvent evt) {        log.debug("响应invite:" + evt.getResponse());        try {            SIPResponse response = (SIPResponse)evt.getResponse();            int statusCode = response.getStatusCode();            // trying不会回复            if (statusCode == Response.TRYING) {            }            // 成功响应            // 下发ack            if (statusCode == Response.OK) {                log.info("回复ACK,准备推流");                ResponseEventExt event = (ResponseEventExt)evt;                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);                }                SipURI requestUri = sipInitListen.getSipFactory().createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), event.getRemoteIpAddress() + ":" + event.getRemotePort());                Request reqAck = requestHeaderProvider.createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response);                log.info("[回复ack] {}-> {}:{} ", sdp.getOrigin().getUsername(), event.getRemoteIpAddress(), event.getRemotePort());                sipSender.send( response.getLocalAddress().getHostAddress(), reqAck);            }        } catch (InvalidArgumentException | ParseException | SipException | SdpParseException e) {            log.info("[点播回复ACK],异常:", e );        }    }    @Override    public void requestBye(RequestEvent evt) {        log.info("处理BYE请求");        try {            sipProcessResponse.responseAck((SIPRequest) evt.getRequest(), Response.OK);        } catch (SipException | InvalidArgumentException | ParseException e) {            log.error("[回复BYE信息失败],{}", e.getMessage());        }    }    @Override    public void sendInvite(Device device,SSRCInfo ssrcInfo) {        try {            String channelId="34020000001320000001";            String sdpIp;            if (!ObjectUtils.isEmpty(device.getSdpIp())) {                sdpIp = device.getSdpIp();            }else {                sdpIp = "192.168.1.250";            }            //封装 sdp协议信息,告诉摄像头 推流配置            StringBuffer content = new StringBuffer(200);            content.append("v=0\r\n");            content.append("o=" + channelId + " 0 0 IN IP4 " + sdpIp + "\r\n");            content.append("s=Play\r\n");            content.append("c=IN IP4 " + sdpIp + "\r\n");            content.append("t=0 0\r\n");            //is -SDP            if (Boolean.FALSE) {                if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {                    content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");                } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) {                    content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");                } else if ("UDP".equalsIgnoreCase(device.getStreamMode())) {                    content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n");                }                content.append("a=recvonly\r\n");                content.append("a=rtpmap:96 PS/90000\r\n");                content.append("a=fmtp:126 profile-level-id=42e01e\r\n");                content.append("a=rtpmap:126 H264/90000\r\n");                content.append("a=rtpmap:125 H264S/90000\r\n");                content.append("a=fmtp:125 profile-level-id=42e01e\r\n");                content.append("a=rtpmap:99 H265/90000\r\n");                content.append("a=rtpmap:98 H264/90000\r\n");                content.append("a=rtpmap:97 MPEG4/90000\r\n");                if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式                    content.append("a=setup:passive\r\n");                    content.append("a=connection:new\r\n");                } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式                    content.append("a=setup:active\r\n");                    content.append("a=connection:new\r\n");                }            } else {                if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {                    content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");                } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) {                    content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");                } else if ("UDP".equalsIgnoreCase(device.getStreamMode())) {                    content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n");                }                content.append("a=recvonly\r\n");                content.append("a=rtpmap:96 PS/90000\r\n");                content.append("a=rtpmap:98 H264/90000\r\n");                content.append("a=rtpmap:97 MPEG4/90000\r\n");                content.append("a=rtpmap:99 H265/90000\r\n");                if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式                    content.append("a=setup:passive\r\n");                    content.append("a=connection:new\r\n");                } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式                    content.append("a=setup:active\r\n");                    content.append("a=connection:new\r\n");                }            }            content.append("y=" + ssrcInfo + "\r\n");//ssrc            System.out.println(content);            CallIdHeader newCallIdHeader=sipSender.getNewCallIdHeader(sipInitListen.getLocalIp(device.getLocalIp()),device.getTransport());            Request request = requestHeaderProvider.createInviteRequest(device, channelId,                    content.toString(), SipUtil.getNewViaTag(), SipUtil.getNewFromTag(), null, ssrcInfo.getSsrc(), newCallIdHeader);            sipSender.send(sipConfig.getIp(),request);        } catch (ParseException | InvalidArgumentException | PeerUnavailableException e) {            throw new RuntimeException(e);        }    }    @Override    public void getDeviceInfo(Device device) {        try {            sipSender.deviceInfoQuery(device);        } catch (InvalidArgumentException | SipException | ParseException e) {            throw new RuntimeException(e);        }    }}

消息发送:

@Slf4j@Componentpublic class SIPSender {    @Autowired    private SipInitListen sipInitListen;    @Autowired    private SIPRequestHeaderProvider headerProvider;        @SneakyThrows    public void send(String ip, Message message) {        ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME);        String transport = "UDP";        if (viaHeader == null) {            log.warn("[消息头缺失]: ViaHeader, 使用默认的UDP方式处理数据");        }else {            transport = viaHeader.getTransport();        }        if (message.getHeader(UserAgentHeader.NAME) == null) {            message.addHeader(SipUtil.createUserAgentHeader(sipInitListen.getSipFactory()));        }        switch (transport){            case "TCP":                sendTCP(ip,message);                return;            case "UDP":                sendUDP(ip,message);                return;            default:                sendTCP(ip,message);        }    }    private boolean sendUDP(String ip, Message message) throws SipException {        SipProviderImpl sipProvider = sipInitListen.getUdpSipProvider(ip);        if (sipProvider == null) {            log.error("[发送信息失败] 未找到udp://{}的监听信息", ip);            return true;        }        if (message instanceof Request) {            sipProvider.sendRequest((Request) message);        }else if (message instanceof Response) {            sipProvider.sendResponse((Response) message);        }        return false;    }    private boolean sendTCP(String ip, Message message) throws SipException {        SipProviderImpl tcpSipProvider = sipInitListen.getTcpSipProvider(ip);        if (tcpSipProvider == null) {            log.error("[发送信息失败] 未找到tcp://{}的监听信息", ip);            return true;        }        if (message instanceof Request) {            tcpSipProvider.sendRequest((Request) message);        }else if (message instanceof Response) {            tcpSipProvider.sendResponse((Response) message);        }        return false;    }    public CallIdHeader getNewCallIdHeader(String ip, String transport){        if (ObjectUtils.isEmpty(transport)) {            return sipInitListen.getUdpSipProvider().getNewCallId();        }        SipProviderImpl sipProvider;        if (ObjectUtils.isEmpty(ip)) {            sipProvider = transport.equalsIgnoreCase("TCP") ? sipInitListen.getTcpSipProvider()                    : sipInitListen.getUdpSipProvider();        }else {            sipProvider = transport.equalsIgnoreCase("TCP") ? sipInitListen.getTcpSipProvider(ip)                    : sipInitListen.getUdpSipProvider(ip);        }        if (sipProvider == null) {            sipProvider = sipInitListen.getUdpSipProvider();        }        if (sipProvider != null) {            return sipProvider.getNewCallId();        }else {            log.warn("[新建CallIdHeader失败], ip={}, transport={}", ip, transport);            return null;        }    }        public void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException {        StringBuffer catalogXml = new StringBuffer(200);        String charset = device.getCharset();        catalogXml.append(" + charset + "\"?>\r\n");        catalogXml.append("\r\n");        catalogXml.append("DeviceInfo\r\n");        catalogXml.append("" + (int) ((Math.random() * 9 + 1) * 100000) + "\r\n");        catalogXml.append("" + device.getDeviceId() + "\r\n");        catalogXml.append("\r\n");        Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtil.getNewViaTag(), SipUtil.getNewFromTag(), null,getNewCallIdHeader(sipInitListen.getLocalIp(device.getLocalIp()),device.getTransport()));        send(sipInitListen.getLocalIp(device.getLocalIp()), request);    }}

来源地址:https://blog.csdn.net/hesqlplus730/article/details/130791859

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯