Darwin Streaming Server 支持UDP打洞

阅读: 评论:0

Darwin Streaming Server 支持UDP打洞

Darwin Streaming Server 支持UDP打洞

RTSP客户端点播Darwin 视频时,SDP协商后的客户端端口可能是在NAT后面,所以需要Darwin支持NAT打洞的功能,从Darwin的源码看,官方的源码是不支持这个能力的。


通过抓取VLC客户端的包发现,VLC在播放RTSP流时,两次SETUP(音频流和视频分别协商端口)之后,会发送4个UDP打洞的包,但Darwin没有接收这些包,并且根据这些包来源的端口修改远端RTP和RTCP的端口。


文章Darwin Streaming Server 支持UDP穿透中给出了修改方法,尝试之后,发现有两个问题:

1、两次SETUP协商后,Darwin给返回的服务器的RTP和RTCP端口两次都一样

2、客户端发送的打洞的RTP和RTCP打洞的包,并没有接收完全。


针对问题1的修改就是将两次SETUP协商后,Darwin返回的端口不同并且唯一

问题2的修改方法是,在接收到SETUP协商后,开启一个线程接收发送到服务器的RTP和RTCP端口的包,并根据接收到的包的源端口更新远端的RTP和RTCP端口,即使没有收到打洞的包,不做任何处理,还是使用之前协商的端口往外发包。


第一个问题是将RTPStream::Setup方法中的:

fSockets = QTSServerInterface::GetServer()->GetSocketPool()->GetUDPSocketPair(sourceAddr, 0, fRemoteAddr, 
                                                                                        fRemoteRTCPPort);

修改为:

fSockets = QTSServerInterface::GetServer()->GetSocketPool()->CreateUDPSocketPair(sourceAddr, 0);


并将UDPSocketPool::CreateUDPSocketPair方法中两个变量的初值修改为如下:


    UInt16 curPort = kLowestUDPPort + usedNum++;
    UInt16 stopPort = kHighestUDPPort -1; // prevent roll over when iterating over port nums
    UInt16 socketBPort = curPort + 1;



第二个问题修改,头文件增加下面的方法和变量:

        void start_thread_for_nat();void setRemoteRTPPort(int value){fRemoteRTPPort = value; }void setRemoteRTCPPort(int value){fRemoteRTCPPort = value;}UInt16    getRemoteRTPPort(){return  fRemoteRTPPort;}UInt32    getRemoteRTPAddr(){return  fRemoteAddr;}Bool16    getQuitValue(){return  bQuit;}Bool16    getRunningValue(){return  bRunning;}void    setRunningValue(Bool16 value){ bRunning = value;}UInt16    getRemoteRTCPPort(){return  fRemoteRTCPPort;}UDPSocketPair*  getUDPSocketPair(){ return fSockets;}Bool16      bQuit;Bool16      bRunning;


在setup方法最后启动一个监听线程: 

    this->start_thread_for_nat();//errors should only be returned if there is a routing problem, there should be noneAssert(err == QTSS_NoErr);return QTSS_NoErr;
}

实现:

#include <pthread.h>
void* thread_for_nat(void *parms){Bool16      fUpdateRtpPort = false;Bool16      fUpdateRtcpPort = false;SInt64                  currentTime = OS::Milliseconds();RTPStream *pRTPStream = (RTPStream *)parms;if (pRTPStream == NULL){return NULL;}if (pRTPStream->getUDPSocketPair() == NULL){return NULL;}if (pRTPStream->getUDPSocketPair()->GetSocketA() == NULL ||pRTPStream->getUDPSocketPair()->GetSocketB() == NULL){return NULL;}qtss_printf("thread_for_nat enter, pRTPStream:%08x, rtp_port:%dn", pRTPStream, pRTPStream->getRemoteRTPPort());pRTPStream->setRunningValue(true);while(1){UInt32 iRemoteAddr = 0;UInt16 iRemotePort = 0;char szBuff[64];UInt32 iBufLen = sizeof(szBuff);UInt32 iRecvLen = 0;if (pRTPStream->getQuitValue()){break;}if (!fUpdateRtpPort){OS_Error iRet = pRTPStream->getUDPSocketPair()->GetSocketA()->RecvFrom(&iRemoteAddr, &iRemotePort, szBuff, iBufLen, &iRecvLen);if (OS_NoErr == iRet){if (iRemoteAddr == pRTPStream->getRemoteRTPAddr()&& iRemotePort != pRTPStream->getRemoteRTPPort()&& iRecvLen > 0){qtss_printf("thread_for_nat update GetSocketA iRet:%d, fRemoteRTPPort:%d, fRemoteRTCPPort:%d, iRemotePort:%dn", iRet, pRTPStream->getRemoteRTPPort(), pRTPStream->getRemoteRTCPPort(), iRemotePort);pRTPStream->setRemoteRTPPort(iRemotePort);fUpdateRtpPort = true;}else{qtss_printf("thread_for_nat update GetSocketA received the same port value, fRemoteRTPPort:%d, fRemoteRTCPPort:%dn", pRTPStream->getRemoteRTPPort(), pRTPStream->getRemoteRTCPPort());fUpdateRtpPort = true;}}else{//qtss_printf("Setup update GetSocketA iRet:%d, fRemoteRTPPort:%d, fRemoteRTCPPort:%dn", iRet, fRemoteRTPPort, fRemoteRTCPPort);}}if (!fUpdateRtcpPort){OS_Error iRet = pRTPStream->getUDPSocketPair()->GetSocketB()->RecvFrom(&iRemoteAddr, &iRemotePort, szBuff, iBufLen, &iRecvLen);if (OS_NoErr == iRet){if (iRemoteAddr == pRTPStream->getRemoteRTPAddr()&& iRemotePort != pRTPStream->getRemoteRTCPPort()&& iRecvLen > 0){qtss_printf("thread_for_nat update GetSocketB iRet:%d, fRemoteRTPPort:%d, fRemoteRTCPPort:%d, iRemotePort:%dn", iRet, pRTPStream->getRemoteRTPPort(), pRTPStream->getRemoteRTCPPort(), iRemotePort);pRTPStream->setRemoteRTCPPort(iRemotePort);fUpdateRtcpPort = true;} else{qtss_printf("thread_for_nat update GetSocketB received the same port value, fRemoteRTPPort:%d, fRemoteRTCPPort:%dn", pRTPStream->getRemoteRTPPort(), pRTPStream->getRemoteRTCPPort());fUpdateRtcpPort = true;}}else{//wait.//qtss_printf("Setup update GetSocketB iRet:%d, fRemoteRTPPort:%d, fRemoteRTCPPort:%dn", iRet, fRemoteRTPPort, fRemoteRTCPPort);}}if (fUpdateRtcpPort && fUpdateRtpPort){qtss_printf("thread_for_nat exit for update end, break, pRTPStream:%08x, rtp_port:%dn", pRTPStream, pRTPStream->getRemoteRTPPort());break;}if ( (OS::Milliseconds() - currentTime ) > 2000){qtss_printf("thread_for_nat exaust 2000 ms, break, pRTPStream:%08x, rtp_port:%dn", pRTPStream, pRTPStream->getRemoteRTPPort());break;}}pRTPStream->setRunningValue(false);gid_thread = -1;return NULL;
}void RTPStream::start_thread_for_nat(){int ret=pthread_create(&gid_thread, NULL, thread_for_nat, (void*)this);if (ret != 0){qtss_printf("err:%dn", ret);}else{qtss_printf("start_thread_for_nat create OKn");}
}


本文发布于:2024-02-04 08:06:22,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170702681053789.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:打洞   Streaming   Darwin   UDP   Server
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23