void cXVDRServer::Action(void) { fd_set fds; struct timeval tv; cTimeMs channelReloadTimer; cTimeMs channelCacheTimer; cTimeMs recordingReloadTimer; bool channelReloadTrigger = false; bool recordingReloadTrigger = false; uint64_t channelsHash = 0; SetPriority(19); // get initial state of the recordings int recState = -1; int recStateOld = -1; Recordings.StateChanged(recState); recStateOld = recState; while (Running()) { FD_ZERO(&fds); FD_SET(m_ServerFD, &fds); tv.tv_sec = 0; tv.tv_usec = 250*1000; int r = select(m_ServerFD + 1, &fds, NULL, NULL, &tv); if (r == -1) { ERRORLOG("failed during select"); continue; } if (r == 0) { // remove disconnected clients bool bChanged = false; for (ClientList::iterator i = m_clients.begin(); i != m_clients.end();) { if (!(*i)->Active()) { INFOLOG("Client with ID %u seems to be disconnected, removing from client list", (*i)->GetID()); delete (*i); i = m_clients.erase(i); bChanged = true; } else { i++; } } // store channel cache if(bChanged) { cChannelCache::SaveChannelCacheData(); } // trigger clients to reload the modified channel list if(m_clients.size() > 0) { uint64_t hash = XVDRChannels.CheckUpdates(); XVDRChannels.Lock(false); if(hash != channelsHash) { channelReloadTrigger = true; channelReloadTimer.Set(0); } if(channelReloadTrigger && channelReloadTimer.Elapsed() >= 10*1000) { INFOLOG("Checking for channel updates ..."); for (ClientList::iterator i = m_clients.begin(); i != m_clients.end(); i++) (*i)->ChannelsChanged(); channelReloadTrigger = false; INFOLOG("Done."); } XVDRChannels.Unlock(); channelsHash = hash; } // reset inactivity timeout as long as there are clients connected if(m_clients.size() > 0) { ShutdownHandler.SetUserInactiveTimeout(); } // store channel cache if(m_clients.size() > 0 && channelCacheTimer.Elapsed() >= 60*1000) { if(!bChanged) { cChannelCache::SaveChannelCacheData(); } channelCacheTimer.Set(0); } // check for recording changes Recordings.StateChanged(recState); if(recState != recStateOld) { recordingReloadTrigger = true; recordingReloadTimer.Set(2000); INFOLOG("Recordings state changed (%i)", recState); recStateOld = recState; } // update recordings if((recordingReloadTrigger && recordingReloadTimer.TimedOut()) || cRecordingsCache::GetInstance().Changed()) { // start gc if reload was triggered if(!cRecordingsCache::GetInstance().Changed()) { INFOLOG("Starting garbage collection in recordings cache"); cRecordingsCache::GetInstance().gc(); } // request clients to reload recordings if(!m_clients.empty()) { INFOLOG("Requesting clients to reload recordings list"); for (ClientList::iterator i = m_clients.begin(); i != m_clients.end(); i++) { (*i)->RecordingsChange(); } } recordingReloadTrigger = false; } // no connect request -> continue waiting continue; } int fd = accept(m_ServerFD, 0, 0); if (fd >= 0) { NewClientConnected(fd); } else { ERRORLOG("accept failed"); } } return; }
void cVNSIServer::Action(void) { fd_set fds; struct timeval tv; // get initial state of the recordings int recState = -1; Recordings.StateChanged(recState); // get initial state of the timers int timerState = -1; Timers.Modified(timerState); // last update of epg time_t epgUpdate = cSchedules::Modified(); while (Running()) { FD_ZERO(&fds); FD_SET(m_ServerFD, &fds); tv.tv_sec = 0; tv.tv_usec = 250*1000; int r = select(m_ServerFD + 1, &fds, NULL, NULL, &tv); if (r == -1) { ERRORLOG("failed during select"); continue; } if (r == 0) { // remove disconnected clients for (ClientList::iterator i = m_clients.begin(); i != m_clients.end();) { if (!(*i)->Active()) { INFOLOG("Client with ID %u seems to be disconnected, removing from client list", (*i)->GetID()); delete (*i); i = m_clients.erase(i); } else { i++; } } // trigger clients to reload the modified channel list if(m_clients.size() > 0) { Channels.Lock(false); if(Channels.Modified() != 0) { INFOLOG("Requesting clients to reload channel list"); for (ClientList::iterator i = m_clients.begin(); i != m_clients.end(); i++) (*i)->ChannelChange(); } Channels.Unlock(); } // reset inactivity timeout as long as there are clients connected if(m_clients.size() > 0) { ShutdownHandler.SetUserInactiveTimeout(); } // update recordings if(Recordings.StateChanged(recState)) { INFOLOG("Recordings state changed (%i)", recState); INFOLOG("Requesting clients to reload recordings list"); for (ClientList::iterator i = m_clients.begin(); i != m_clients.end(); i++) (*i)->RecordingsChange(); } // update timers if(Timers.Modified(timerState)) { INFOLOG("Timers state changed (%i)", timerState); INFOLOG("Requesting clients to reload timers"); for (ClientList::iterator i = m_clients.begin(); i != m_clients.end(); i++) { (*i)->TimerChange(); } } // update epg if((cSchedules::Modified() > epgUpdate + 10) || time(NULL) > epgUpdate + 300) { for (ClientList::iterator i = m_clients.begin(); i != m_clients.end(); i++) { (*i)->EpgChange(); } epgUpdate = cSchedules::Modified(); } continue; } int fd = accept(m_ServerFD, 0, 0); if (fd >= 0) { NewClientConnected(fd); } else { ERRORLOG("accept failed"); } } return; }
void cVNSIServer::Action(void) { fd_set fds; struct timeval tv; if(*VNSIServerConfig.ConfigDirectory) { m_AllowedHostsFile = cString::sprintf("%s/" ALLOWED_HOSTS_FILE, *VNSIServerConfig.ConfigDirectory); } else { ERRORLOG("cVNSIServer: missing ConfigDirectory!"); m_AllowedHostsFile = cString::sprintf("/video/" ALLOWED_HOSTS_FILE); } VNSIChannelFilter.Load(); VNSIChannelFilter.SortChannels(); m_Status.Init(&m_timers); m_timers.Load(); m_timers.Start(); m_ServerFD = socket(AF_INET, SOCK_STREAM, 0); if(m_ServerFD == -1) return; fcntl(m_ServerFD, F_SETFD, fcntl(m_ServerFD, F_GETFD) | FD_CLOEXEC); int one = 1; setsockopt(m_ServerFD, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)); struct sockaddr_in s; memset(&s, 0, sizeof(s)); s.sin_family = AF_INET; s.sin_port = htons(m_ServerPort); int x = bind(m_ServerFD, (struct sockaddr *)&s, sizeof(s)); if (x < 0) { close(m_ServerFD); INFOLOG("Unable to start VNSI Server, port already in use ?"); m_ServerFD = -1; return; } listen(m_ServerFD, 10); while (Running()) { FD_ZERO(&fds); FD_SET(m_ServerFD, &fds); tv.tv_sec = 0; tv.tv_usec = 250*1000; int r = select(m_ServerFD + 1, &fds, NULL, NULL, &tv); if (r == -1) { ERRORLOG("failed during select"); continue; } if (r == 0) { continue; } int fd = accept(m_ServerFD, 0, 0); if (fd >= 0) { NewClientConnected(fd); } else { ERRORLOG("accept failed"); } } return; }