mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 12:37:09 +08:00
确保rtp/rtcp端口号为偶奇数
This commit is contained in:
parent
f303ab3222
commit
8c46688886
@ -365,5 +365,43 @@ bool RtspUrl::setup(bool isSSL, const string &strUrl, const string &strUser, con
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}//namespace mediakit
|
std::pair<Socket::Ptr, Socket::Ptr> makeSockPair_l(const EventPoller::Ptr &poller, const string &local_ip){
|
||||||
|
auto pSockRtp = std::make_shared<Socket>(poller);
|
||||||
|
if (!pSockRtp->bindUdpSock(0, local_ip.data())) {
|
||||||
|
//分配端口失败
|
||||||
|
throw runtime_error("open udp socket failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
//是否是偶数
|
||||||
|
bool even_numbers = pSockRtp->get_local_port() % 2 != 0;
|
||||||
|
auto pSockRtcp = std::make_shared<Socket>(poller);
|
||||||
|
if (!pSockRtcp->bindUdpSock(pSockRtp->get_local_port() + (even_numbers ? 1 : -1), local_ip.data())) {
|
||||||
|
//分配端口失败
|
||||||
|
throw runtime_error("open udp socket failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!even_numbers) {
|
||||||
|
//如果rtp端口不是偶数,那么与rtcp端口互换,目的是兼容一些要求严格的播放器或服务器
|
||||||
|
Socket::Ptr tmp = pSockRtp;
|
||||||
|
pSockRtp = pSockRtcp;
|
||||||
|
pSockRtcp = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair(pSockRtp, pSockRtcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<Socket::Ptr, Socket::Ptr> makeSockPair(const EventPoller::Ptr &poller, const string &local_ip){
|
||||||
|
int try_count = 0;
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
return makeSockPair_l(poller, local_ip);
|
||||||
|
} catch (...) {
|
||||||
|
if (++try_count == 3) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
WarnL << "open udp socket failed, retry: " << try_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}//namespace mediakit
|
@ -271,5 +271,7 @@ private:
|
|||||||
_StrPrinter _printer;
|
_StrPrinter _printer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::pair<Socket::Ptr, Socket::Ptr> makeSockPair(const EventPoller::Ptr &poller, const string &local_ip);
|
||||||
|
|
||||||
} //namespace mediakit
|
} //namespace mediakit
|
||||||
#endif //RTSP_RTSP_H_
|
#endif //RTSP_RTSP_H_
|
||||||
|
@ -214,29 +214,10 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
|
|||||||
void RtspPlayer::createUdpSockIfNecessary(int track_idx){
|
void RtspPlayer::createUdpSockIfNecessary(int track_idx){
|
||||||
auto &rtpSockRef = _apRtpSock[track_idx];
|
auto &rtpSockRef = _apRtpSock[track_idx];
|
||||||
auto &rtcpSockRef = _apRtcpSock[track_idx];
|
auto &rtcpSockRef = _apRtcpSock[track_idx];
|
||||||
if(!rtpSockRef){
|
if (!rtpSockRef || !rtcpSockRef) {
|
||||||
rtpSockRef.reset(new Socket(getPoller()));
|
auto pr = makeSockPair(getPoller(), get_local_ip());
|
||||||
//rtp随机端口
|
rtpSockRef = pr.first;
|
||||||
if (!rtpSockRef->bindUdpSock(0, get_local_ip().data())) {
|
rtcpSockRef = pr.second;
|
||||||
rtpSockRef.reset();
|
|
||||||
throw std::runtime_error("open rtp sock failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!rtcpSockRef){
|
|
||||||
rtcpSockRef.reset(new Socket(getPoller()));
|
|
||||||
//rtcp端口为rtp端口+1,目的是为了兼容某些服务器,其实更推荐随机端口
|
|
||||||
if (!rtcpSockRef->bindUdpSock(rtpSockRef->get_local_port() + 1, get_local_ip().data())) {
|
|
||||||
rtcpSockRef.reset();
|
|
||||||
throw std::runtime_error("open rtcp sock failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(rtpSockRef->get_local_port() % 2 != 0){
|
|
||||||
//如果rtp端口不是偶数,那么与rtcp端口互换,目的是兼容一些要求严格的服务器
|
|
||||||
Socket::Ptr tmp = rtpSockRef;
|
|
||||||
rtpSockRef = rtcpSockRef;
|
|
||||||
rtcpSockRef = tmp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,29 +627,18 @@ void RtspSession::handleReq_Setup(const Parser &parser) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Rtsp::RTP_UDP: {
|
case Rtsp::RTP_UDP: {
|
||||||
//我们用trackIdx区分rtp和rtcp包
|
std::pair<Socket::Ptr, Socket::Ptr> pr;
|
||||||
auto pSockRtp = std::make_shared<Socket>(_sock->getPoller());
|
try{
|
||||||
if (!pSockRtp->bindUdpSock(0,get_local_ip().data())) {
|
pr = makeSockPair(_sock->getPoller(), get_local_ip());
|
||||||
|
}catch(std::exception &ex) {
|
||||||
//分配端口失败
|
//分配端口失败
|
||||||
send_NotAcceptable();
|
send_NotAcceptable();
|
||||||
throw SockException(Err_shutdown, "open rtp socket failed");
|
throw SockException(Err_shutdown, ex.what());
|
||||||
}
|
|
||||||
auto pSockRtcp = std::make_shared<Socket>(_sock->getPoller());
|
|
||||||
if (!pSockRtcp->bindUdpSock(pSockRtp->get_local_port() + 1,get_local_ip().data())) {
|
|
||||||
//分配端口失败
|
|
||||||
send_NotAcceptable();
|
|
||||||
throw SockException(Err_shutdown, "open rtcp socket failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pSockRtp->get_local_port() % 2 != 0){
|
_apRtpSock[trackIdx] = pr.first;
|
||||||
//如果rtp端口不是偶数,那么与rtcp端口互换,目的是兼容一些要求严格的播放器
|
_apRtcpSock[trackIdx] = pr.second;
|
||||||
Socket::Ptr tmp = pSockRtp;
|
|
||||||
pSockRtp = pSockRtcp;
|
|
||||||
pSockRtcp = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
_apRtpSock[trackIdx] = pSockRtp;
|
|
||||||
_apRtcpSock[trackIdx] = pSockRtcp;
|
|
||||||
//设置客户端内网端口信息
|
//设置客户端内网端口信息
|
||||||
string strClientPort = FindField(parser["Transport"].data(), "client_port=", NULL);
|
string strClientPort = FindField(parser["Transport"].data(), "client_port=", NULL);
|
||||||
uint16_t ui16RtpPort = atoi( FindField(strClientPort.data(), NULL, "-").data());
|
uint16_t ui16RtpPort = atoi( FindField(strClientPort.data(), NULL, "-").data());
|
||||||
@ -661,14 +650,14 @@ void RtspSession::handleReq_Setup(const Parser &parser) {
|
|||||||
peerAddr.sin_port = htons(ui16RtpPort);
|
peerAddr.sin_port = htons(ui16RtpPort);
|
||||||
peerAddr.sin_addr.s_addr = inet_addr(get_peer_ip().data());
|
peerAddr.sin_addr.s_addr = inet_addr(get_peer_ip().data());
|
||||||
bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
|
bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
|
||||||
pSockRtp->setSendPeerAddr((struct sockaddr *)(&peerAddr));
|
pr.first->setSendPeerAddr((struct sockaddr *)(&peerAddr));
|
||||||
|
|
||||||
//设置rtcp发送目标地址
|
//设置rtcp发送目标地址
|
||||||
peerAddr.sin_family = AF_INET;
|
peerAddr.sin_family = AF_INET;
|
||||||
peerAddr.sin_port = htons(ui16RtcpPort);
|
peerAddr.sin_port = htons(ui16RtcpPort);
|
||||||
peerAddr.sin_addr.s_addr = inet_addr(get_peer_ip().data());
|
peerAddr.sin_addr.s_addr = inet_addr(get_peer_ip().data());
|
||||||
bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
|
bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
|
||||||
pSockRtcp->setSendPeerAddr((struct sockaddr *)(&peerAddr));
|
pr.second->setSendPeerAddr((struct sockaddr *)(&peerAddr));
|
||||||
|
|
||||||
//尝试获取客户端nat映射地址
|
//尝试获取客户端nat映射地址
|
||||||
startListenPeerUdpData(trackIdx);
|
startListenPeerUdpData(trackIdx);
|
||||||
@ -677,7 +666,7 @@ void RtspSession::handleReq_Setup(const Parser &parser) {
|
|||||||
sendRtspResponse("200 OK",
|
sendRtspResponse("200 OK",
|
||||||
{"Transport", StrPrinter << "RTP/AVP/UDP;unicast;"
|
{"Transport", StrPrinter << "RTP/AVP/UDP;unicast;"
|
||||||
<< "client_port=" << strClientPort << ";"
|
<< "client_port=" << strClientPort << ";"
|
||||||
<< "server_port=" << pSockRtp->get_local_port() << "-" << pSockRtcp->get_local_port() << ";"
|
<< "server_port=" << pr.first->get_local_port() << "-" << pr.second->get_local_port() << ";"
|
||||||
<< "ssrc=" << printSSRC(trackRef->_ssrc)
|
<< "ssrc=" << printSSRC(trackRef->_ssrc)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user