Commit 8c466888 by xiongziliang

确保rtp/rtcp端口号为偶奇数

parent f303ab32
...@@ -365,5 +365,43 @@ bool RtspUrl::setup(bool isSSL, const string &strUrl, const string &strUser, con ...@@ -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
\ No newline at end of file
...@@ -271,5 +271,7 @@ private: ...@@ -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) { ...@@ -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) { ...@@ -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();
throw SockException(Err_shutdown, "open rtp socket failed");
}
auto pSockRtcp = std::make_shared<Socket>(_sock->getPoller());
if (!pSockRtcp->bindUdpSock(pSockRtp->get_local_port() + 1,get_local_ip().data())) {
//分配端口失败 //分配端口失败
send_NotAcceptable(); send_NotAcceptable();
throw SockException(Err_shutdown, "open rtcp socket failed"); throw SockException(Err_shutdown, ex.what());
} }
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,24 +650,24 @@ void RtspSession::handleReq_Setup(const Parser &parser) { ...@@ -661,24 +650,24 @@ 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);
//InfoP(this) << "分配端口:" << srv_port; //InfoP(this) << "分配端口:" << srv_port;
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)
}); });
} }
break; break;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论