Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}