ProxyDemuxerTask* ProxyClientInfo::AddStream(QTSS_RTPStreamObject inStream) { // // Allocate some UDP sockets out of our pool to receive the UDP data from // the server. Demuxing is based on the origin server's (host's) IP addr, so // pass that to the socket pool so it can properly allocate a pair of UDP sockets. // We don't know what the remote port is yet (we only find out when we get the // SETUP response from the origin), so just pass in 0. UInt32 theHostAddr = fClient.GetSocket()->GetHostAddr(); UInt32 theLocalAddr = fClient.GetSocket()->GetLocalAddr(); UDPSocketPair* thePair = sSocketPool->GetUDPSocketPair(theLocalAddr, 0, theHostAddr, 0); fLastDemuxerTask = NEW ProxyDemuxerTask(inStream, thePair); fDemuxerTaskQueue.EnQueue(fLastDemuxerTask->GetQueueElem()); // // Tell the demuxers for these sockets to send any packets from this IP addr // to the ProxyDemuxerTask for this stream. This is how incoming UDP packets // will be routed to the proper QTSS_RTPStreamObject thePair->GetSocketA()->GetDemuxer()->RegisterTask(theHostAddr, 0, fLastDemuxerTask); thePair->GetSocketB()->GetDemuxer()->RegisterTask(theHostAddr, 0, fLastDemuxerTask); // // return the newly created ProxyDemuxerTask return fLastDemuxerTask; }
SInt64 ProxyTask::Run() { const UInt32 kMaxRTCPPacketSize = 2048; char thePacketBuffer[kMaxRTCPPacketSize]; QTSS_PacketStruct thePacketStruct; thePacketStruct.packetTransmitTime = QTSS_Milliseconds(); thePacketStruct.packetData = thePacketBuffer; (void)this->GetEvents(); OSMutexLocker locker(sSocketPool->GetMutex()); for (OSQueueIter iter(sSocketPool->GetSocketQueue()); !iter.IsDone(); iter.Next()) { UInt32 theRemoteAddr = 0; UInt16 theRemotePort = 0; UDPSocketPair* thePair = (UDPSocketPair*)iter.GetCurrent()->GetEnclosingObject(); Assert(thePair != NULL); for (UInt32 x = 0; x < 2; x++) { QTSS_WriteFlags theFlags = qtssWriteFlagsNoFlags; UDPSocket* theSocket = NULL; if (x == 0) { theFlags = qtssWriteFlagsIsRTP; theSocket = thePair->GetSocketA(); } else { theFlags = qtssWriteFlagsIsRTCP; theSocket = thePair->GetSocketB(); } Assert(theSocket->GetDemuxer() != NULL); OSMutexLocker locker(theSocket->GetDemuxer()->GetMutex()); //get all the outstanding packets for this socket while (true) { UInt32 thePacketLen = 0; theSocket->RecvFrom(&theRemoteAddr, &theRemotePort, thePacketStruct.packetData, kMaxRTCPPacketSize, &thePacketLen); if (thePacketLen == 0) break;//no more packets on this socket! ProxyDemuxerTask* theDemuxerTask = (ProxyDemuxerTask*)theSocket->GetDemuxer()->GetTask(theRemoteAddr, 0); if (theDemuxerTask != NULL) { QTSS_RTPStreamObject theStream = theDemuxerTask->GetStream(); (void)QTSS_Write(theStream, &thePacketStruct, thePacketLen, NULL, theFlags); } } } } return kProxyTaskPollIntervalMsec; }
ProxyClientInfo::~ProxyClientInfo() { UInt32 theHostAddr = fClient.GetSocket()->GetHostAddr(); for (OSQueueIter iter(&fDemuxerTaskQueue); !iter.IsDone(); ) { OSQueueElem* theElem = iter.GetCurrent(); ProxyDemuxerTask* theTask = (ProxyDemuxerTask*)theElem->GetEnclosingObject(); // // Move onto the next element becase we are going to be deleting this one iter.Next(); theElem->Remove(); // Get off the queue before deleting // // Clean up UDPSocketPair* thePair = theTask->GetSockets(); thePair->GetSocketA()->GetDemuxer()->UnregisterTask(theHostAddr, 0, theTask); thePair->GetSocketB()->GetDemuxer()->UnregisterTask(theHostAddr, 0, theTask); delete theTask; sSocketPool->ReleaseUDPSocketPair(thePair); } }
SInt64 RTCPTask::Run() { const UInt32 kMaxRTCPPacketSize = 2048; char thePacketBuffer[kMaxRTCPPacketSize]; StrPtrLen thePacket(thePacketBuffer, 0); QTSServerInterface* theServer = QTSServerInterface::GetServer(); //This task goes through all the UDPSockets in the RTPSocketPool, checking to see //if they have data. If they do, it demuxes the packets and sends the packet onto //the proper RTP session. EventFlags events = this->GetEvents(); // get and clear events if ( (events & Task::kReadEvent) || (events & Task::kIdleEvent) ) { //Must be done atomically wrt the socket pool. OSMutexLocker locker(theServer->GetSocketPool()->GetMutex()); for (OSQueueIter iter(theServer->GetSocketPool()->GetSocketQueue()); !iter.IsDone(); iter.Next()) { UInt32 theRemoteAddr = 0; UInt16 theRemotePort = 0; UDPSocketPair* thePair = (UDPSocketPair*)iter.GetCurrent()->GetEnclosingObject(); Assert(thePair != NULL); for (UInt32 x = 0; x < 2; x++) { UDPSocket* theSocket = NULL; if (x == 0) theSocket = thePair->GetSocketA(); else theSocket = thePair->GetSocketB(); UDPDemuxer* theDemuxer = theSocket->GetDemuxer(); if (theDemuxer == NULL) continue; else { theDemuxer->GetMutex()->Lock(); while (true) //get all the outstanding packets for this socket { thePacket.Len = 0; theSocket->RecvFrom(&theRemoteAddr, &theRemotePort, thePacket.Ptr, kMaxRTCPPacketSize, &thePacket.Len); if (thePacket.Len == 0) { theSocket->RequestEvent(EV_RE); break;//no more packets on this socket! } //if this socket has a demuxer, find the target RTPStream if (theDemuxer != NULL) { RTPStream* theStream = (RTPStream*)theDemuxer->GetTask(theRemoteAddr, theRemotePort); if (theStream != NULL) theStream->ProcessIncomingRTCPPacket(&thePacket); } } theDemuxer->GetMutex()->Unlock(); } } } } return 0; /* Fix for 4004432 */ /* SInt64 result = 0; if (theServer->GetNumRTPSessions() > 0) result = theServer->GetPrefs()->GetRTCPPollIntervalInMsec(); return result; */ }