void CDplusProtocol::HandleKeepalives(void) { // send keepalives CBuffer keepalive; EncodeKeepAlivePacket(&keepalive); // iterate on clients CClients *clients = g_Reflector.GetClients(); int index = -1; CClient *client = NULL; while ( (client = clients->FindNextClient(PROTOCOL_DPLUS, &index)) != NULL ) { // send keepalive //std::cout << "Sending DPlus packet @ " << client->GetIp() << std::endl; m_Socket.Send(keepalive, client->GetIp()); // is this client busy ? if ( client->IsAMaster() ) { // yes, just tickle it client->Alive(); } // check it's still with us else if ( !client->IsAlive() ) { // no, disconnect CBuffer disconnect; EncodeDisconnectPacket(&disconnect); m_Socket.Send(disconnect, client->GetIp()); // and remove it std::cout << "DPlus client " << client->GetCallsign() << " keepalive timeout" << std::endl; clients->RemoveClient(client); } } g_Reflector.ReleaseClients(); }
void CDplusProtocol::HandleQueue(void) { m_Queue.Lock(); while ( !m_Queue.empty() ) { // get the packet CPacket *packet = m_Queue.front(); m_Queue.pop(); // get our sender's id int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); // check if it's header and update cache if ( packet->IsDvHeader() ) { // this relies on queue feeder setting valid module id m_DvHeadersCache[iModId] = CDvHeaderPacket((const CDvHeaderPacket &)*packet); m_iSeqCounters[iModId] = 0; } // encode it CBuffer buffer; if ( EncodeDvPacket(*packet, &buffer) ) { // and push it to all our clients who are not streaming in // note that for dplus protocol, all stream of all modules are push to all clients // it's client who decide which stream he's interrrested in CClients *clients = g_Reflector.GetClients(); int index = -1; CClient *client = NULL; while ( (client = clients->FindNextClient(PROTOCOL_DPLUS, &index)) != NULL ) { // is this client busy ? if ( !client->IsAMaster() ) { // check if client is a dextra dongle // then replace RPT2 with XRF instead of REF // if the client type is not yet known, send bothheaders if ( packet->IsDvHeader() ) { // sending header in Dplus is client specific SendDvHeader((CDvHeaderPacket *)packet, (CDplusClient *)client); } else if ( packet->IsDvFrame() ) { // and send the DV frame m_Socket.Send(buffer, client->GetIp()); // is it time to insert a DVheader copy ? if ( (m_iSeqCounters[iModId]++ % 21) == 20 ) { // yes, clone it CDvHeaderPacket packet2(m_DvHeadersCache[iModId]); // and send it SendDvHeader(&packet2, (CDplusClient *)client); } } else { // otherwise, send the original packet m_Socket.Send(buffer, client->GetIp()); } } } g_Reflector.ReleaseClients(); } // done delete packet; } m_Queue.Unlock(); }