mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-25 20:27:34 +08:00
支持rtcp心跳包
This commit is contained in:
parent
8242ad674d
commit
101261c299
@ -107,10 +107,10 @@ void RtspSession::shutdown(){
|
||||
|
||||
void RtspSession::onError(const SockException& err) {
|
||||
TraceL << err.getErrCode() << " " << err.what();
|
||||
if (m_bListenPeerUdpPort) {
|
||||
//取消UDP断口监听
|
||||
if (m_bListenPeerUdpData) {
|
||||
//取消UDP端口监听
|
||||
UDPServer::Instance().stopListenPeer(getPeerIp().data(), this);
|
||||
m_bListenPeerUdpPort = false;
|
||||
m_bListenPeerUdpData = false;
|
||||
}
|
||||
if (!m_bBase64need && m_strSessionCookie.size() != 0) {
|
||||
//quickTime http getter
|
||||
@ -135,10 +135,6 @@ void RtspSession::onManager() {
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
if (m_bListenPeerUdpPort) {
|
||||
UDPServer::Instance().stopListenPeer(getPeerIp().data(), this);
|
||||
m_bListenPeerUdpPort = false;
|
||||
}
|
||||
}
|
||||
if (m_rtpType != PlayerBase::RTP_TCP && m_ticker.elapsedTime() > 15 * 1000) {
|
||||
WarnL << "RTSP会话超时:" << getPeerIp();
|
||||
@ -330,15 +326,23 @@ bool RtspSession::handleReq_Setup() {
|
||||
}
|
||||
break;
|
||||
case PlayerBase::RTP_UDP: {
|
||||
auto pSock = UDPServer::Instance().getSock(getLocalIp().data(),trackIdx);
|
||||
if (!pSock) {
|
||||
//我们用trackIdx区分rtp和rtcp包
|
||||
auto pSockRtp = UDPServer::Instance().getSock(getLocalIp().data(),2*trackIdx);
|
||||
if (!pSockRtp) {
|
||||
//分配端口失败
|
||||
WarnL << "分配端口失败";
|
||||
WarnL << "分配rtp端口失败";
|
||||
send_NotAcceptable();
|
||||
return false;
|
||||
}
|
||||
m_apUdpSock[trackIdx] = pSock;
|
||||
int iSrvPort = pSock->get_local_port();
|
||||
auto pSockRtcp = UDPServer::Instance().getSock(getLocalIp().data(),2*trackIdx + 1 ,pSockRtp->get_local_port() + 1);
|
||||
if (!pSockRtcp) {
|
||||
//分配端口失败
|
||||
WarnL << "分配rtcp端口失败";
|
||||
send_NotAcceptable();
|
||||
return false;
|
||||
}
|
||||
m_apUdpSock[trackIdx] = pSockRtp;
|
||||
//设置客户端内网端口信息
|
||||
string strClientPort = FindField(m_parser["Transport"].data(), "client_port=", NULL);
|
||||
uint16_t ui16PeerPort = atoi( FindField(strClientPort.data(), NULL, "-").data());
|
||||
struct sockaddr_in peerAddr;
|
||||
@ -347,7 +351,8 @@ bool RtspSession::handleReq_Setup() {
|
||||
peerAddr.sin_addr.s_addr = inet_addr(getPeerIp().data());
|
||||
bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
|
||||
m_apPeerUdpAddr[trackIdx].reset((struct sockaddr *) (new struct sockaddr_in(peerAddr)));
|
||||
tryGetPeerUdpPort();
|
||||
//尝试获取客户端nat映射地址
|
||||
startListenPeerUdpData();
|
||||
//InfoL << "分配端口:" << srv_port;
|
||||
int n = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
|
||||
"CSeq: %d\r\n"
|
||||
@ -359,7 +364,7 @@ bool RtspSession::handleReq_Setup() {
|
||||
m_iCseq, g_serverName.data(),
|
||||
RTSP_VERSION, RTSP_BUILDTIME,
|
||||
dateHeader().data(), strClientPort.data(),
|
||||
iSrvPort, iSrvPort + 1,
|
||||
pSockRtp->get_local_port(), pSockRtcp->get_local_port(),
|
||||
printSSRC(trackRef.ssrc).data(),
|
||||
m_strSession.data());
|
||||
send(m_pcBuf, n);
|
||||
@ -382,6 +387,15 @@ bool RtspSession::handleReq_Setup() {
|
||||
});
|
||||
}
|
||||
int iSrvPort = m_pBrdcaster->getPort(trackid);
|
||||
//我们用trackIdx区分rtp和rtcp包
|
||||
auto pSockRtcp = UDPServer::Instance().getSock(getLocalIp().data(),2*trackIdx + 1,iSrvPort + 1);
|
||||
if (!pSockRtcp) {
|
||||
//分配端口失败
|
||||
WarnL << "分配rtcp端口失败";
|
||||
send_NotAcceptable();
|
||||
return false;
|
||||
}
|
||||
startListenPeerUdpData();
|
||||
static uint32_t udpTTL = mINI::Instance()[MultiCast::kUdpTTL].as<uint32_t>();
|
||||
int n = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
|
||||
"CSeq: %d\r\n"
|
||||
@ -393,7 +407,7 @@ bool RtspSession::handleReq_Setup() {
|
||||
m_iCseq, g_serverName.data(),
|
||||
RTSP_VERSION, RTSP_BUILDTIME,
|
||||
dateHeader().data(), m_pBrdcaster->getIP().data(),
|
||||
getLocalIp().data(), iSrvPort, iSrvPort + 1,
|
||||
getLocalIp().data(), iSrvPort, pSockRtcp->get_local_port(),
|
||||
udpTTL,printSSRC(trackRef.ssrc).data(),
|
||||
m_strSession.data());
|
||||
send(m_pcBuf, n);
|
||||
@ -581,11 +595,11 @@ inline void RtspSession::send_NotAcceptable() {
|
||||
}
|
||||
|
||||
inline bool RtspSession::findStream() {
|
||||
|
||||
|
||||
string strHost = FindField(m_strUrl.data(), "://", "/");
|
||||
m_strApp = FindField(m_strUrl.data(), (strHost + "/").data(), "/");
|
||||
m_strStream = FindField(m_strUrl.data(), (strHost + "/" + m_strApp + "/").data(), NULL);
|
||||
|
||||
|
||||
auto iPos = m_strStream.find('?');
|
||||
if(iPos != string::npos ){
|
||||
m_strStream.erase(iPos);
|
||||
@ -655,30 +669,37 @@ inline void RtspSession::sendRtpPacket(const RtpPacket& pkt) {
|
||||
}
|
||||
|
||||
inline void RtspSession::onRcvPeerUdpData(int iTrackIdx, const Socket::Buffer::Ptr &pBuf, const struct sockaddr& addr) {
|
||||
m_apPeerUdpAddr[iTrackIdx].reset(new struct sockaddr(addr));
|
||||
m_abGotPeerUdp[iTrackIdx] = true;
|
||||
bool bGotAllPeerUdp = true;
|
||||
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
|
||||
if (!m_abGotPeerUdp[i]) {
|
||||
bGotAllPeerUdp = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bGotAllPeerUdp) {
|
||||
if (m_bListenPeerUdpPort) {
|
||||
UDPServer::Instance().stopListenPeer(getPeerIp().data(), this);
|
||||
m_bListenPeerUdpPort = false;
|
||||
InfoL << "获取到客户端端口";
|
||||
if(iTrackIdx % 2 == 0){
|
||||
//这是rtp探测包
|
||||
if(!m_bGotAllPeerUdp){
|
||||
//还没有获取完整的rtp探测包
|
||||
if(SockUtil::in_same_lan(getLocalIp().data(),getPeerIp().data())){
|
||||
//在内网中,客户端上报的端口号是真实的,所以我们忽略udp打洞包
|
||||
m_bGotAllPeerUdp = true;
|
||||
return;
|
||||
}
|
||||
//设置真实的客户端nat映射端口号
|
||||
m_apPeerUdpAddr[iTrackIdx / 2].reset(new struct sockaddr(addr));
|
||||
m_abGotPeerUdp[iTrackIdx / 2] = true;
|
||||
m_bGotAllPeerUdp = true;//先假设获取到完整的rtp探测包
|
||||
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
|
||||
if (!m_abGotPeerUdp[i]) {
|
||||
//还有track没获取到rtp探测包
|
||||
m_bGotAllPeerUdp = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//这是rtcp心跳包,说明播放器还存活
|
||||
m_ticker.resetTime();
|
||||
TraceL << "rtcp:" << (iTrackIdx-1)/2 ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void RtspSession::tryGetPeerUdpPort() {
|
||||
if(SockUtil::in_same_lan(getLocalIp().data(),getPeerIp().data())){
|
||||
return;
|
||||
}
|
||||
m_bListenPeerUdpPort = true;
|
||||
inline void RtspSession::startListenPeerUdpData() {
|
||||
m_bListenPeerUdpData = true;
|
||||
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
|
||||
UDPServer::Instance().listenPeer(getPeerIp().data(), this,
|
||||
[weakSelf](int iTrackIdx,const Socket::Buffer::Ptr &pBuf,struct sockaddr *pPeerAddr)->bool {
|
||||
|
@ -102,7 +102,7 @@ private:
|
||||
return -1;
|
||||
}
|
||||
inline void onRcvPeerUdpData(int iTrackIdx, const Socket::Buffer::Ptr &pBuf, const struct sockaddr &addr);
|
||||
inline void tryGetPeerUdpPort();
|
||||
inline void startListenPeerUdpData();
|
||||
|
||||
char *m_pcBuf = nullptr;
|
||||
Ticker m_ticker;
|
||||
@ -125,6 +125,7 @@ private:
|
||||
int m_iCseq = 0;
|
||||
unsigned int m_uiTrackCnt = 0; //媒体track个数
|
||||
RtspTrack m_aTrackInfo[2]; //媒体track信息,trackid idx 为数组下标
|
||||
bool m_bGotAllPeerUdp = false;
|
||||
|
||||
#ifdef RTSP_SEND_RTCP
|
||||
RtcpCounter m_aRtcpCnt[2]; //rtcp统计,trackid idx 为数组下标
|
||||
@ -136,7 +137,7 @@ private:
|
||||
bool m_abGotPeerUdp[2] = { false, false }; //获取客户端udp端口计数
|
||||
weak_ptr<Socket> m_apUdpSock[2]; //发送RTP的UDP端口,trackid idx 为数组下标
|
||||
std::shared_ptr<struct sockaddr> m_apPeerUdpAddr[2]; //播放器接收RTP的地址,trackid idx 为数组下标
|
||||
bool m_bListenPeerUdpPort = false;
|
||||
bool m_bListenPeerUdpData = false;
|
||||
RtpBroadCaster::Ptr m_pBrdcaster;
|
||||
|
||||
//RTSP over HTTP
|
||||
|
@ -39,15 +39,15 @@ UDPServer::~UDPServer() {
|
||||
InfoL;
|
||||
}
|
||||
|
||||
Socket::Ptr UDPServer::getSock(const char* strLocalIp, int iTrackIndex) {
|
||||
Socket::Ptr UDPServer::getSock(const char* strLocalIp, int iTrackIndex,uint16_t iLocalPort) {
|
||||
lock_guard<mutex> lck(m_mtxUpdSock);
|
||||
string strKey = StrPrinter << strLocalIp << ":" << iTrackIndex << endl;
|
||||
auto it = m_mapUpdSock.find(strKey);
|
||||
if (it == m_mapUpdSock.end()) {
|
||||
Socket::Ptr pSock(new Socket());
|
||||
//InfoL<<localIp;
|
||||
if (!pSock->bindUdpSock(0, strLocalIp)) {
|
||||
//系统随机分配端口
|
||||
if (!pSock->bindUdpSock(iLocalPort, strLocalIp)) {
|
||||
//分配失败
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
static void Destory() {
|
||||
delete &UDPServer::Instance();
|
||||
}
|
||||
Socket::Ptr getSock(const char *strLocalIp, int iTrackIndex);
|
||||
Socket::Ptr getSock(const char *strLocalIp, int iTrackIndex,uint16_t iLocalPort = 0);
|
||||
void listenPeer(const char *strPeerIp, void *pSelf, const onRecvData &cb);
|
||||
void stopListenPeer(const char *strPeerIp, void *pSelf);
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user