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::Task(void) { CBuffer Buffer; CIp Ip; CCallsign Callsign; CDvHeaderPacket *Header; CDvFramePacket *Frame; CDvLastFramePacket *LastFrame; // handle incoming packets if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) { // crack the packet if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL ) { //std::cout << "DPlus DV frame" << std::endl; // handle it OnDvFramePacketIn(Frame); } else if ( (Header = IsValidDvHeaderPacket(Buffer)) != NULL ) { //std::cout << "DPlus DV header:" << std::endl << *Header << std::endl; // callsign muted? if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DPLUS, Header->GetRpt2Module()) ) { // handle it OnDvHeaderPacketIn(Header, Ip); } else { delete Header; } } else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != NULL ) { //std::cout << "DPlus DV last frame" << std::endl; // handle it OnDvLastFramePacketIn(LastFrame); } else if ( IsValidConnectPacket(Buffer) ) { std::cout << "DPlus connect request packet from " << Ip << std::endl; // acknowledge the request m_Socket.Send(Buffer, Ip); } else if ( IsValidLoginPacket(Buffer, &Callsign) ) { std::cout << "DPlus login packet from " << Callsign << " at " << Ip << std::endl; // callsign authorized? if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DPLUS) ) { // acknowledge the request EncodeLoginAckPacket(&Buffer); m_Socket.Send(Buffer, Ip); // create the client CDplusClient *client = new CDplusClient(Callsign, Ip); // and append g_Reflector.GetClients()->AddClient(client); g_Reflector.ReleaseClients(); } else { // deny the request EncodeLoginNackPacket(&Buffer); m_Socket.Send(Buffer, Ip); } } else if ( IsValidDisconnectPacket(Buffer) ) { std::cout << "DPlus disconnect packet from " << Ip << std::endl; // find client CClients *clients = g_Reflector.GetClients(); CClient *client = clients->FindClient(Ip, PROTOCOL_DPLUS); if ( client != NULL ) { // remove it clients->RemoveClient(client); // and acknowledge the disconnect EncodeDisconnectPacket(&Buffer); m_Socket.Send(Buffer, Ip); } g_Reflector.ReleaseClients(); } else if ( IsValidKeepAlivePacket(Buffer) ) { //std::cout << "DPlus keepalive packet from " << Ip << std::endl; // find all clients with that callsign & ip and keep them alive CClients *clients = g_Reflector.GetClients(); int index = -1; CClient *client = NULL; while ( (client = clients->FindNextClient(Ip, PROTOCOL_DPLUS, &index)) != NULL ) { client->Alive(); } g_Reflector.ReleaseClients(); } else { std::cout << "DPlus packet (" << Buffer.size() << ")" << std::endl; } } // handle end of streaming timeout CheckStreamsTimeout(); // handle queue from reflector HandleQueue(); // keep client alive if ( m_LastKeepaliveTime.DurationSinceNow() > DPLUS_KEEPALIVE_PERIOD ) { // HandleKeepalives(); // update time m_LastKeepaliveTime.Now(); } }