Exemple #1
0
static void
satip_device_block( const char *addr, int block )
{
  extern const idclass_t satip_device_class;
  tvh_hardware_t *th;
  satip_device_t *sd;
  satip_frontend_t *lfe;
  int val = block < 0 ? 0 : block;

  pthread_mutex_lock(&global_lock);
  TVH_HARDWARE_FOREACH(th) {
    if (!idnode_is_instance(&th->th_id, &satip_device_class))
      continue;
    sd = (satip_device_t *)th;
    if (strcmp(sd->sd_info.addr, addr) == 0 && val != sd->sd_dbus_allow) {
      sd->sd_dbus_allow = val;
      if (block < 0) {
        TAILQ_FOREACH(lfe, &sd->sd_frontends, sf_link)
          mpegts_input_stop_all((mpegts_input_t *)lfe);
      }
      tvhinfo("satip", "address %s is %s", addr,
              block < 0 ? "stopped" : (block > 0 ? "allowed" : "disabled"));
    }
  }
  pthread_mutex_unlock(&global_lock);
}
Exemple #2
0
void
tvhdhomerun_device_destroy( tvhdhomerun_device_t *hd )
{
  tvhdhomerun_frontend_t *lfe;

  lock_assert(&global_lock);

  mtimer_disarm(&hd->hd_destroy_timer);

  idnode_save_check(&hd->th_id, 0);

  tvhinfo(LS_TVHDHOMERUN, "Releasing locks for devices");
  while ((lfe = TAILQ_FIRST(&hd->hd_frontends)) != NULL) {
    tvhdhomerun_frontend_delete(lfe);
  }

#define FREEM(x) free(hd->hd_info.x)
  FREEM(friendlyname);
  FREEM(uuid);
  FREEM(deviceModel);
#undef FREEM

  tvh_hardware_delete((tvh_hardware_t*)hd);

#define FREEM(x) free(hd->x)
  FREEM(hd_override_type);
#undef FREEM

  free(hd);
}
Exemple #3
0
static int
linuxdvb_ca_ai_callback(void *arg, uint8_t slot_id, uint16_t session_num,
                     uint8_t app_type, uint16_t app_manufacturer,
                     uint16_t manufacturer_code, uint8_t menu_string_len,
                     uint8_t *menu_string)
{
    linuxdvb_ca_t * lca = arg;

    tvhinfo("en50221", "CAM slot %u: Application type: %02x, manufacturer: %04x,"
            " Manufacturer code: %04x", slot_id, app_type, app_manufacturer,
            manufacturer_code);

    tvhinfo("en50221", "CAM slot %u: Menu string: %.*s", slot_id,
            menu_string_len, menu_string);

    snprintf(lca->lca_cam_menu_string, sizeof(lca->lca_cam_menu_string),
             "%.*s", menu_string_len, menu_string);

    idnode_notify_title_changed(&lca->lca_id, NULL);

    return 0;
}
Exemple #4
0
static int
ciplus13_app_ai_data_rate_info(linuxdvb_ca_t *lca, ciplus13_data_rate_t rate)
{
  uint8_t data[] = {0x9f, 0x80, 0x24, 0x01, (uint8_t) rate};

  /* only version 3 (CI+ 1.3) supports data_rate_info */
  if (lca->lca_ai_version != 3)
    return 0;

  tvhinfo("en50221", "setting CI+ CAM data rate to %s Mbps", rate ? "96":"72");

  return en50221_sl_send_data(lca->lca_sl, lca->lca_ai_session_number, data, sizeof(data));
}
Exemple #5
0
static int
tvhdhomerun_device_class_override_set( void *obj, const void * p )
{
  tvhdhomerun_device_t *hd = obj;
  const char *s = p;
  if ( s != NULL && strlen(s) > 0 ) {
    if ( hd->hd_override_type != NULL && strcmp(hd->hd_override_type,s) != 0 ) {
      free(hd->hd_override_type);
      hd->hd_override_type = strdup(p);
      tvhinfo(LS_TVHDHOMERUN, "Setting override_type : %s", hd->hd_override_type);
      return 1;
    }
  }
  return 0;
}
Exemple #6
0
static int
api_input_satip_discover
  ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
  int err = 0;

  if (op == NULL || strcmp(op, "all"))
    return -EINVAL;

  tvhinfo(LS_SATIP, "Triggered new server discovery");

  pthread_mutex_lock(&global_lock);
  satip_device_discovery_start();
  pthread_mutex_unlock(&global_lock);

  return err;
}
Exemple #7
0
static int
linuxdvb_ca_ca_pmt_reply_cb(void *arg, uint8_t slot_id, uint16_t session_num,
                            struct en50221_app_pmt_reply *reply,
                            uint32_t reply_size)
{
    const char *str;

    switch (reply->CA_enable) {
      case 0x01: str = "possible"; break;
      case 0x02: str = "possible under conditions (purchase dialogue)"; break;
      case 0x03: str = "possible under conditions (technical dialogue)"; break;
      case 0x71: str = "not possible (because no entitlement)"; break;
      case 0x73: str = "not possible (for technical reasons)"; break;
      default:   str = "state unknown (unknown value received)";
    }

    tvhinfo("en50221", "CAM slot %u: descrambling %s", slot_id, str);

    return 0;
}
Exemple #8
0
static int
linuxdvb_ca_ca_info_callback(void *arg, uint8_t slot_id, uint16_t session_num,
                             uint32_t ca_id_count, uint16_t *ca_ids)
{
    linuxdvb_ca_t * lca = arg;
    uint32_t i;
    char buf[256];
    size_t c = 0;

    dvbcam_unregister_cam(lca, 0);
    dvbcam_register_cam(lca, 0, ca_ids, ca_id_count);


    for(i=0; i< ca_id_count; i++) {
        tvh_strlcatf(buf, sizeof(buf), c, " %04X", ca_ids[i]);
        tvh_strlcatf(buf, sizeof(buf), c, " (%s)",
                     caid2name(ca_ids[i]));
    }

    tvhinfo("en50221", "CAM slot %u supported CAIDs: %s", slot_id, buf);
    return 0;
}
Exemple #9
0
int
main(int argc, char **argv)
{
  int i;
  sigset_t set;
#if ENABLE_MPEGTS
  uint32_t adapter_mask = 0;
#endif
  int  log_level   = LOG_INFO;
  int  log_options = TVHLOG_OPT_MILLIS | TVHLOG_OPT_STDERR | TVHLOG_OPT_SYSLOG;
  const char *log_debug = NULL, *log_trace = NULL;
  gid_t gid = -1;
  uid_t uid = -1;
  char buf[512];
  FILE *pidfile = NULL;
  extern int dvb_bouquets_parse;

  main_tid = pthread_self();

  /* Setup global mutexes */
  pthread_mutex_init(&fork_lock, NULL);
  pthread_mutex_init(&global_lock, NULL);
  pthread_mutex_init(&tasklet_lock, NULL);
  pthread_mutex_init(&atomic_lock, NULL);
  pthread_cond_init(&gtimer_cond, NULL);
  pthread_cond_init(&tasklet_cond, NULL);
  TAILQ_INIT(&tasklets);

  /* Defaults */
  tvheadend_webui_port      = 9981;
  tvheadend_webroot         = NULL;
  tvheadend_htsp_port       = 9982;
  tvheadend_htsp_port_extra = 0;
  time(&dispatch_clock);

  /* Command line options */
  int         opt_help         = 0,
              opt_version      = 0,
              opt_fork         = 0,
              opt_firstrun     = 0,
              opt_stderr       = 0,
              opt_syslog       = 0,
              opt_nosyslog     = 0,
              opt_uidebug      = 0,
              opt_abort        = 0,
              opt_noacl        = 0,
              opt_fileline     = 0,
              opt_threadid     = 0,
              opt_libav        = 0,
              opt_ipv6         = 0,
              opt_satip_rtsp   = 0,
#if ENABLE_TSFILE
              opt_tsfile_tuner = 0,
#endif
              opt_dump         = 0,
              opt_xspf         = 0,
              opt_dbus         = 0,
              opt_dbus_session = 0,
              opt_nobackup     = 0,
              opt_nobat        = 0;
  const char *opt_config       = NULL,
             *opt_user         = NULL,
             *opt_group        = NULL,
             *opt_logpath      = NULL,
             *opt_log_debug    = NULL,
             *opt_log_trace    = NULL,
             *opt_pidpath      = "/var/run/tvheadend.pid",
#if ENABLE_LINUXDVB
             *opt_dvb_adapters = NULL,
#endif
             *opt_bindaddr     = NULL,
             *opt_subscribe    = NULL,
             *opt_user_agent   = NULL;
  str_list_t  opt_satip_xml    = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
  str_list_t  opt_tsfile       = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
  cmdline_opt_t cmdline_opts[] = {
    {   0, NULL,        N_("Generic Options"),         OPT_BOOL, NULL         },
    { 'h', "help",      N_("Show this page"),          OPT_BOOL, &opt_help    },
    { 'v', "version",   N_("Show version information"),OPT_BOOL, &opt_version },

    {   0, NULL,        N_("Service Configuration"),   OPT_BOOL, NULL         },
    { 'c', "config",    N_("Alternate config path"),   OPT_STR,  &opt_config  },
    { 'B', "nobackup",  N_("Don't backup config tree at upgrade"), OPT_BOOL, &opt_nobackup },
    { 'f', "fork",      N_("Fork and run as daemon"),  OPT_BOOL, &opt_fork    },
    { 'u', "user",      N_("Run as user"),             OPT_STR,  &opt_user    },
    { 'g', "group",     N_("Run as group"),            OPT_STR,  &opt_group   },
    { 'p', "pid",       N_("Alternate pid path"),      OPT_STR,  &opt_pidpath },
    { 'C', "firstrun",  N_("If no user account exists then create one with\n"
	                   "no username and no password. Use with care as\n"
	                   "it will allow world-wide administrative access\n"
	                   "to your Tvheadend installation until you edit/create\n"
	                   "access-control from within the Tvheadend UI"),
      OPT_BOOL, &opt_firstrun },
#if ENABLE_DBUS_1
    { 'U', "dbus",      N_("Enable DBus"),
      OPT_BOOL, &opt_dbus },
    { 'e', "dbus_session", N_("DBus - use the session message bus instead system one"),
      OPT_BOOL, &opt_dbus_session },
#endif
#if ENABLE_LINUXDVB
    { 'a', "adapters",  N_("Only use specified DVB adapters (comma separated)"),
      OPT_STR, &opt_dvb_adapters },
#endif
#if ENABLE_SATIP_SERVER
    {   0, "satip_rtsp", N_("SAT>IP RTSP port number for server\n"
                            "(default: -1 = disable, 0 = webconfig, standard port is 554)"),
      OPT_INT, &opt_satip_rtsp },
#endif
#if ENABLE_SATIP_CLIENT
    {   0, "satip_xml", N_("URL with the SAT>IP server XML location"),
      OPT_STR_LIST, &opt_satip_xml },
#endif
    {   0, NULL,         N_("Server Connectivity"),    OPT_BOOL, NULL         },
    { '6', "ipv6",       N_("Listen on IPv6"),         OPT_BOOL, &opt_ipv6    },
    { 'b', "bindaddr",   N_("Specify bind address"),   OPT_STR,  &opt_bindaddr},
    {   0, "http_port",  N_("Specify alternative http port"),
      OPT_INT, &tvheadend_webui_port },
    {   0, "http_root",  N_("Specify alternative http webroot"),
      OPT_STR, &tvheadend_webroot },
    {   0, "htsp_port",  N_("Specify alternative htsp port"),
      OPT_INT, &tvheadend_htsp_port },
    {   0, "htsp_port2", N_("Specify extra htsp port"),
      OPT_INT, &tvheadend_htsp_port_extra },
    {   0, "useragent",  N_("Specify User-Agent header for the http client"),
      OPT_STR, &opt_user_agent },
    {   0, "xspf",       N_("Use XSPF playlist instead of M3U"),
      OPT_BOOL, &opt_xspf },

    {   0, NULL,        N_("Debug Options"),           OPT_BOOL, NULL         },
    { 'd', "stderr",    N_("Enable debug on stderr"),  OPT_BOOL, &opt_stderr  },
    { 's', "syslog",    N_("Enable debug to syslog"),  OPT_BOOL, &opt_syslog  },
    { 'S', "nosyslog",  N_("Disable syslog (all msgs)"), OPT_BOOL, &opt_nosyslog },
    { 'l', "logfile",   N_("Enable debug to file"),    OPT_STR,  &opt_logpath },
    {   0, "debug",     N_("Enable debug subsystems"),  OPT_STR,  &opt_log_debug },
#if ENABLE_TRACE
    {   0, "trace",     N_("Enable trace subsystems"), OPT_STR,  &opt_log_trace },
#endif
    {   0, "fileline",  N_("Add file and line numbers to debug"), OPT_BOOL, &opt_fileline },
    {   0, "threadid",  N_("Add the thread ID to debug"), OPT_BOOL, &opt_threadid },
#if ENABLE_LIBAV
    {   0, "libav",     N_("More verbose libav log"),  OPT_BOOL, &opt_libav },
#endif
    {   0, "uidebug",   N_("Enable webUI debug (non-minified JS)"), OPT_BOOL, &opt_uidebug },
    { 'A', "abort",     N_("Immediately abort"),       OPT_BOOL, &opt_abort   },
    { 'D', "dump",      N_("Enable coredumps for daemon"), OPT_BOOL, &opt_dump },
    {   0, "noacl",     N_("Disable all access control checks"),
      OPT_BOOL, &opt_noacl },
    {   0, "nobat",     N_("Disable DVB bouquets"),
      OPT_BOOL, &opt_nobat },
    { 'j', "join",      N_("Subscribe to a service permanently"),
      OPT_STR, &opt_subscribe },


#if ENABLE_TSFILE || ENABLE_TSDEBUG
    { 0, NULL, N_("Testing options"), OPT_BOOL, NULL },
    { 0, "tsfile_tuners", N_("Number of tsfile tuners"), OPT_INT, &opt_tsfile_tuner },
    { 0, "tsfile", N_("tsfile input (mux file)"), OPT_STR_LIST, &opt_tsfile },
#endif
#if ENABLE_TSDEBUG
    { 0, "tsdebug", N_("Output directory for tsdebug"), OPT_STR, &tvheadend_tsdebug },
#endif

  };

  /* Get current directory */
  tvheadend_cwd0 = dirname(tvh_strdupa(argv[0]));
  tvheadend_cwd = dirname(tvh_strdupa(tvheadend_cwd0));

  /* Set locale */
  setlocale(LC_ALL, "");
  setlocale(LC_NUMERIC, "C");

  /* make sure the timezone is set */
  tzset();

  /* Process command line */
  for (i = 1; i < argc; i++) {

    /* Find option */
    cmdline_opt_t *opt
      = cmdline_opt_find(cmdline_opts, ARRAY_SIZE(cmdline_opts), argv[i]);
    if (!opt)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts),
                 _("invalid option specified [%s]"), argv[i]);

    /* Process */
    if (opt->type == OPT_BOOL)
      *((int*)opt->param) = 1;
    else if (++i == argc)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts),
                 _("option %s requires a value"), opt->lopt);
    else if (opt->type == OPT_INT)
      *((int*)opt->param) = atoi(argv[i]);
    else if (opt->type == OPT_STR_LIST) {
      str_list_t *strl = opt->param;
      if (strl->num < strl->max)
        strl->str[strl->num++] = argv[i];
    }
    else
      *((char**)opt->param) = argv[i];

    /* Stop processing */
    if (opt_help)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), NULL);
    if (opt_version)
      show_version(argv[0]);
  }

  /* Additional cmdline processing */
  if (opt_nobat)
    dvb_bouquets_parse = 0;
#if ENABLE_LINUXDVB
  if (!opt_dvb_adapters) {
    adapter_mask = ~0;
  } else {
    char *p, *e;
    char *r = NULL;
    char *dvb_adapters = strdup(opt_dvb_adapters);
    adapter_mask = 0x0;
    p = strtok_r(dvb_adapters, ",", &r);
    while (p) {
      int a = strtol(p, &e, 10);
      if (*e != 0 || a < 0 || a > 31) {
        fprintf(stderr, _("Invalid adapter number '%s'\n"), p);
        free(dvb_adapters);
        return 1;
      }
      adapter_mask |= (1 << a);
      p = strtok_r(NULL, ",", &r);
    }
    free(dvb_adapters);
    if (!adapter_mask) {
      fprintf(stderr, "%s", _("No adapters specified!\n"));
      return 1;
    }
  }
#endif
  if (tvheadend_webroot) {
    char *tmp;
    if (*tvheadend_webroot == '/')
      tmp = strdup(tvheadend_webroot);
    else {
      tmp = malloc(strlen(tvheadend_webroot)+2);
      *tmp = '/';
      strcpy(tmp+1, tvheadend_webroot);
    }
    if (tmp[strlen(tmp)-1] == '/')
      tmp[strlen(tmp)-1] = '\0';
    tvheadend_webroot = tmp;
  }
  tvheadend_webui_debug = opt_uidebug;

  /* Setup logging */
  if (isatty(2))
    log_options |= TVHLOG_OPT_DECORATE;
  if (opt_stderr || opt_syslog || opt_logpath) {
    if (!opt_log_trace && !opt_log_debug)
      log_debug      = "all";
    log_level      = LOG_DEBUG;
    if (opt_stderr)
      log_options   |= TVHLOG_OPT_DBG_STDERR;
    if (opt_syslog)
      log_options   |= TVHLOG_OPT_DBG_SYSLOG;
    if (opt_logpath)
      log_options   |= TVHLOG_OPT_DBG_FILE;
  }
  if (opt_nosyslog)
    log_options &= ~(TVHLOG_OPT_SYSLOG|TVHLOG_OPT_DBG_SYSLOG);
  if (opt_fileline)
    log_options |= TVHLOG_OPT_FILELINE;
  if (opt_threadid)
    log_options |= TVHLOG_OPT_THREAD;
  if (opt_libav)
    log_options |= TVHLOG_OPT_LIBAV;
  if (opt_log_trace) {
    log_level  = LOG_TRACE;
    log_trace  = opt_log_trace;
  }
  if (opt_log_debug)
    log_debug  = opt_log_debug;
    
  tvhlog_init(log_level, log_options, opt_logpath);
  tvhlog_set_debug(log_debug);
  tvhlog_set_trace(log_trace);
  tvhinfo("main", "Log started");
 
  signal(SIGPIPE, handle_sigpipe); // will be redundant later
  signal(SIGILL, handle_sigill);   // see handler..

  /* Set priviledges */
  if(opt_fork || opt_group || opt_user) {
    const char *homedir;
    struct group  *grp = getgrnam(opt_group ?: "video");
    struct passwd *pw  = opt_user ? getpwnam(opt_user) : NULL;

    if(grp != NULL) {
      gid = grp->gr_gid;
    } else {
      gid = 1;
    }

    if (pw != NULL) {
      if (getuid() != pw->pw_uid) {
        gid_t glist[16];
        int gnum;
        gnum = get_user_groups(pw, glist, ARRAY_SIZE(glist));
        if (gnum > 0 && setgroups(gnum, glist)) {
          char buf[256] = "";
          int i;
          for (i = 0; i < gnum; i++)
            snprintf(buf + strlen(buf), sizeof(buf) - 1 - strlen(buf),
                     ",%d", glist[i]);
          tvhlog(LOG_ALERT, "START",
                 "setgroups(%s) failed, do you have permission?", buf+1);
          return 1;
        }
      }
      uid     = pw->pw_uid;
      homedir = pw->pw_dir;
      setenv("HOME", homedir, 1);
    } else {
      uid = 1;
    }
  }

  uuid_init();
  config_boot(opt_config, gid, uid);
  tcp_server_preinit(opt_ipv6);
  http_server_init(opt_bindaddr);    // bind to ports only
  htsp_init(opt_bindaddr);	     // bind to ports only
  satip_server_init(opt_satip_rtsp); // bind to ports only

  if (opt_fork)
    pidfile = tvh_fopen(opt_pidpath, "w+");

  if (gid != -1 && (getgid() != gid) && setgid(gid)) {
    tvhlog(LOG_ALERT, "START",
           "setgid(%d) failed, do you have permission?", gid);
    return 1;
  }
  if (uid != -1 && (getuid() != uid) && setuid(uid)) {
    tvhlog(LOG_ALERT, "START",
           "setuid(%d) failed, do you have permission?", uid);
    return 1;
  }

  /* Daemonise */
  if(opt_fork) {
    if(daemon(0, 0)) {
      exit(2);
    }
    if(pidfile != NULL) {
      fprintf(pidfile, "%d\n", getpid());
      fclose(pidfile);
    }

    /* Make dumpable */
    if (opt_dump) {
#ifdef PLATFORM_LINUX
      if (chdir("/tmp"))
        tvhwarn("START", "failed to change cwd to /tmp");
      prctl(PR_SET_DUMPABLE, 1);
#else
      tvhwarn("START", "Coredumps not implemented on your platform");
#endif
    }

    umask(0);
  }

  tvheadend_running = 1;

  /* Start log thread (must be done post fork) */
  tvhlog_start();

  /* Alter logging */
  if (opt_fork)
    tvhlog_options &= ~TVHLOG_OPT_STDERR;
  if (!isatty(2))
    tvhlog_options &= ~TVHLOG_OPT_DECORATE;
  
  /* Initialise clock */
  pthread_mutex_lock(&global_lock);
  time(&dispatch_clock);

  /* Signal handling */
  sigfillset(&set);
  sigprocmask(SIG_BLOCK, &set, NULL);
  trap_init(argv[0]);

  /* SSL library init */
  OPENSSL_config(NULL);
  SSL_load_error_strings();
  SSL_library_init();

  /* Initialise configuration */
  notify_init();
  idnode_init();
  spawn_init();
  config_init(opt_nobackup == 0);

  /**
   * Initialize subsystems
   */

  epg_in_load = 1;

  tvhthread_create(&tasklet_tid, NULL, tasklet_thread, NULL);

  dbus_server_init(opt_dbus, opt_dbus_session);

  intlconv_init();
  
  api_init();

  fsmonitor_init();

  libav_init();

  tvhtime_init();

  profile_init();

  imagecache_init();

  http_client_init(opt_user_agent);
  esfilter_init();

  bouquet_init();

  service_init();

  dvb_init();

#if ENABLE_MPEGTS
  mpegts_init(adapter_mask, &opt_satip_xml, &opt_tsfile, opt_tsfile_tuner);
#endif

  channel_init();

  bouquet_service_resolve();

  subscription_init();

  dvr_config_init();

  access_init(opt_firstrun, opt_noacl);

#if ENABLE_TIMESHIFT
  timeshift_init();
#endif

  tcp_server_init();
  webui_init(opt_xspf);
#if ENABLE_UPNP
  upnp_server_init(opt_bindaddr);
#endif

  service_mapper_init();

  descrambler_init();

  epggrab_init();
  epg_init();

  dvr_init();

  dbus_server_start();

  http_server_register();
  satip_server_register();
  htsp_register();

  if(opt_subscribe != NULL)
    subscription_dummy_join(opt_subscribe, 1);

  avahi_init();
  bonjour_init();

  epg_updated(); // cleanup now all prev ref's should have been created
  epg_in_load = 0;

  pthread_mutex_unlock(&global_lock);

  /**
   * Wait for SIGTERM / SIGINT, but only in this thread
   */

  sigemptyset(&set);
  sigaddset(&set, SIGTERM);
  sigaddset(&set, SIGINT);

  signal(SIGTERM, doexit);
  signal(SIGINT, doexit);

  pthread_sigmask(SIG_UNBLOCK, &set, NULL);

  tvhlog(LOG_NOTICE, "START", "HTS Tvheadend version %s started, "
         "running as PID:%d UID:%d GID:%d, CWD:%s CNF:%s",
         tvheadend_version,
         getpid(), getuid(), getgid(), getcwd(buf, sizeof(buf)),
         hts_settings_get_root());

  if(opt_abort)
    abort();

  mainloop();

#if ENABLE_DBUS_1
  tvhftrace("main", dbus_server_done);
#endif
#if ENABLE_UPNP
  tvhftrace("main", upnp_server_done);
#endif
  tvhftrace("main", satip_server_done);
  tvhftrace("main", htsp_done);
  tvhftrace("main", http_server_done);
  tvhftrace("main", webui_done);
  tvhftrace("main", fsmonitor_done);
  tvhftrace("main", http_client_done);
  tvhftrace("main", tcp_server_done);

  // Note: the locking is obviously a bit redundant, but without
  //       we need to disable the gtimer_arm call in epg_save()
  pthread_mutex_lock(&global_lock);
  tvhftrace("main", epg_save);

#if ENABLE_TIMESHIFT
  tvhftrace("main", timeshift_term);
#endif
  pthread_mutex_unlock(&global_lock);

  tvhftrace("main", epggrab_done);
#if ENABLE_MPEGTS
  tvhftrace("main", mpegts_done);
#endif
  tvhftrace("main", descrambler_done);
  tvhftrace("main", service_mapper_done);
  tvhftrace("main", service_done);
  tvhftrace("main", channel_done);
  tvhftrace("main", bouquet_done);
  tvhftrace("main", dvr_done);
  tvhftrace("main", subscription_done);
  tvhftrace("main", access_done);
  tvhftrace("main", epg_done);
  tvhftrace("main", avahi_done);
  tvhftrace("main", bonjour_done);
  tvhftrace("main", imagecache_done);
  tvhftrace("main", lang_code_done);
  tvhftrace("main", api_done);

  tvhtrace("main", "tasklet enter");
  pthread_cond_signal(&tasklet_cond);
  pthread_join(tasklet_tid, NULL);
  tvhtrace("main", "tasklet thread end");
  tasklet_flush();
  tvhtrace("main", "tasklet leave");

  tvhftrace("main", hts_settings_done);
  tvhftrace("main", dvb_done);
  tvhftrace("main", lang_str_done);
  tvhftrace("main", esfilter_done);
  tvhftrace("main", profile_done);
  tvhftrace("main", intlconv_done);
  tvhftrace("main", urlparse_done);
  tvhftrace("main", idnode_done);
  tvhftrace("main", notify_done);
  tvhftrace("main", spawn_done);

  tvhlog(LOG_NOTICE, "STOP", "Exiting HTS Tvheadend");
  tvhlog_end();

  tvhftrace("main", config_done);

  if(opt_fork)
    unlink(opt_pidpath);
    
#if ENABLE_TSFILE
  free(opt_tsfile.str);
#endif
  free(opt_satip_xml.str);

  /* OpenSSL - welcome to the "cleanup" hell */
  ENGINE_cleanup();
  RAND_cleanup();
  CRYPTO_cleanup_all_ex_data();
  EVP_cleanup();
  CONF_modules_free();
#ifndef OPENSSL_NO_COMP
  COMP_zlib_cleanup();
#endif
  ERR_remove_state(0);
  ERR_free_strings();
#ifndef OPENSSL_NO_COMP
  sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
#endif
  /* end of OpenSSL cleanup code */

#if ENABLE_DBUS_1
  extern void dbus_shutdown(void);
  if (opt_dbus) dbus_shutdown();
#endif
  return 0;
}

/**
 *
 */
void
tvh_str_set(char **strp, const char *src)
{
  free(*strp);
  *strp = src ? strdup(src) : NULL;
}


/**
 *
 */
int
tvh_str_update(char **strp, const char *src)
{
  if(src == NULL)
    return 0;
  free(*strp);
  *strp = strdup(src);
  return 1;
}


/**
 *
 */
void
scopedunlock(pthread_mutex_t **mtxp)
{
  pthread_mutex_unlock(*mtxp);
}
Exemple #10
0
static void *
tvhdhomerun_device_discovery_thread( void *aux )
{
  struct hdhomerun_discover_device_t result_list[MAX_HDHOMERUN_DEVICES];
  int numDevices, brk;

  while (tvheadend_is_running()) {

    numDevices =
      hdhomerun_discover_find_devices_custom(0,
                                             HDHOMERUN_DEVICE_TYPE_TUNER,
                                             HDHOMERUN_DEVICE_ID_WILDCARD,
                                             result_list,
                                             MAX_HDHOMERUN_DEVICES);

    if (numDevices > 0) {
      while (numDevices > 0 ) {
        numDevices--;
        struct hdhomerun_discover_device_t* cDev = &result_list[numDevices];
        if ( cDev->device_type == HDHOMERUN_DEVICE_TYPE_TUNER ) {
          pthread_mutex_lock(&global_lock);
          tvhdhomerun_device_t *existing = tvhdhomerun_device_find(cDev->device_id);
          if ( tvheadend_is_running() ) {
            if ( !existing ) {
              tvhinfo(LS_TVHDHOMERUN,"Found HDHomerun device %08x with %d tuners",
                      cDev->device_id, cDev->tuner_count);
              tvhdhomerun_device_create(cDev);
            } else if ( ((struct sockaddr_in *)&existing->hd_info.ip_address)->sin_addr.s_addr !=
                     htonl(cDev->ip_addr) ) {
              struct sockaddr_storage detected_dev_addr;
              memset(&detected_dev_addr, 0, sizeof(detected_dev_addr));
              detected_dev_addr.ss_family = AF_INET;
              ((struct sockaddr_in *)&detected_dev_addr)->sin_addr.s_addr = htonl(cDev->ip_addr);

              char existing_ip[64];
              tcp_get_str_from_ip(&existing->hd_info.ip_address, existing_ip, sizeof(existing_ip));

              char detected_ip[64];
              tcp_get_str_from_ip(&detected_dev_addr, detected_ip, sizeof(detected_ip));

              tvhinfo(LS_TVHDHOMERUN,"HDHomerun device %08x switched IPs from %s to %s, updating",
                     cDev->device_id, existing_ip, detected_ip);
              tvhdhomerun_device_destroy(existing);
              tvhdhomerun_device_create(cDev);
            }
          }
          pthread_mutex_unlock(&global_lock);
        }
      }
    }

    pthread_mutex_lock(&tvhdhomerun_discovery_lock);
    brk = 0;
    if (tvheadend_is_running()) {
      brk = tvh_cond_timedwait(&tvhdhomerun_discovery_cond,
                               &tvhdhomerun_discovery_lock,
                               mclk() + sec2mono(15));
      brk = !ERRNO_AGAIN(brk) && brk != ETIMEDOUT;
    }
    pthread_mutex_unlock(&tvhdhomerun_discovery_lock);
    if (brk)
      break;
  }

  return NULL;
}
Exemple #11
0
static void tvhdhomerun_device_create(struct hdhomerun_discover_device_t *dInfo) {

  tvhdhomerun_device_t *hd = calloc(1, sizeof(tvhdhomerun_device_t));
  htsmsg_t *conf = NULL, *feconf = NULL;
  char uhex[UUID_HEX_SIZE];
  int j, save = 0;
  struct hdhomerun_device_t *hdhomerun_tuner;
  dvb_fe_type_t type = DVB_TYPE_C;

  tvhdhomerun_device_calc_uuid(uhex, dInfo->device_id);

  hdhomerun_tuner = hdhomerun_device_create(dInfo->device_id, dInfo->ip_addr, 0, NULL);
  {
    const char *deviceModel =  hdhomerun_device_get_model_str(hdhomerun_tuner);
    if(deviceModel != NULL) {
      hd->hd_info.deviceModel = strdup(deviceModel);
    }
    hdhomerun_device_destroy(hdhomerun_tuner);
  }

  conf = hts_settings_load("input/tvhdhomerun/adapters/%s", uhex);

  if ( conf != NULL ) {
    const char *override_type = htsmsg_get_str(conf, "fe_override");
    if ( override_type != NULL) {
      if ( !strcmp(override_type, "ATSC" ) )
        override_type = "ATSC-T";
      type = dvb_str2type(override_type);
      if ( ! ( type == DVB_TYPE_C || type == DVB_TYPE_T ||
               type == DVB_TYPE_ATSC_T || type == DVB_TYPE_ATSC_C ) ) {
        type = DVB_TYPE_C;
      }
    }
  } else {
    if (strstr(hd->hd_info.deviceModel, "_atsc"))
      type = DVB_TYPE_ATSC_T;
  }

  hd->hd_override_type = strdup(dvb_type2str(type));
  tvhinfo(LS_TVHDHOMERUN, "Using Network type : %s", hd->hd_override_type);

  /* some sane defaults */
  hd->hd_fullmux_ok  = 1;
  hd->hd_pids_len    = 127;
  hd->hd_pids_max    = 32;
  hd->hd_pids_deladd = 1;

  if (!tvh_hardware_create0((tvh_hardware_t*)hd, &tvhdhomerun_device_class,
                            uhex, conf))
    return;

  TAILQ_INIT(&hd->hd_frontends);

  /* we may check if uuid matches, but the SHA hash should be enough */
  if (hd->hd_info.uuid)
    free(hd->hd_info.uuid);

  char fName[128];
  snprintf(fName, 128, "HDHomeRun(%08X)",dInfo->device_id);

  memset(&hd->hd_info.ip_address, 0, sizeof(hd->hd_info.ip_address));
  hd->hd_info.ip_address.ss_family = AF_INET;
  ((struct sockaddr_in *)&hd->hd_info.ip_address)->sin_addr.s_addr = htonl(dInfo->ip_addr);
  hd->hd_info.uuid = strdup(uhex);
  hd->hd_info.friendlyname = strdup(fName);

  if (conf)
    feconf = htsmsg_get_map(conf, "frontends");
  save = !conf || !feconf;

  for (j = 0; j < dInfo->tuner_count; ++j) {
      if (tvhdhomerun_frontend_create(hd, dInfo, feconf, type, j)) {
        tvhinfo(LS_TVHDHOMERUN, "Created frontend %08X tuner %d", dInfo->device_id, j);
      } else {
        tvherror(LS_TVHDHOMERUN, "Unable to create frontend-device. ( %08x-%d )", dInfo->device_id,j);
      }
  }


  if (save)
    tvhdhomerun_device_changed(hd);

  htsmsg_destroy(conf);
}
Exemple #12
0
void
ffdecsa_init(void)
{
  current = funcs_32int;


#if defined(__i386__) || defined(__x86_64__)

  unsigned int eax, ebx, ecx, edx;
  unsigned int max_std_level, std_caps;
  
#if defined(__i386__)

  x86_reg a, c;
  __asm__ volatile (
		    /* See if CPUID instruction is supported ... */
		    /* ... Get copies of EFLAGS into eax and ecx */
		    "pushfl\n\t"
		    "pop %0\n\t"
		    "mov %0, %1\n\t"

		    /* ... Toggle the ID bit in one copy and store */
		    /*     to the EFLAGS reg */
		    "xor $0x200000, %0\n\t"
		    "push %0\n\t"
		    "popfl\n\t"

		    /* ... Get the (hopefully modified) EFLAGS */
		    "pushfl\n\t"
		    "pop %0\n\t"
		    : "=a" (a), "=c" (c)
		    :
		    : "cc"
		    );

  if (a != c) {
#endif
    eax = ebx = ecx = edx = 0;
    native_cpuid(&eax, &ebx, &ecx, &edx);
    max_std_level = eax;

    if(max_std_level >= 1){
      eax = 1;
      native_cpuid(&eax, &ebx, &ecx, &edx);
      std_caps = edx;

#ifdef CONFIG_SSE2
      if (std_caps & (1<<26)) {
	current = funcs_128sse2;
	tvhinfo(LS_CSA, "Using SSE2 128bit parallel descrambling");
	return;
      }
#endif

#ifdef CONFIG_MMX
      if (std_caps & (1<<23)) {
	current = funcs_64mmx;
	tvhinfo(LS_CSA, "Using MMX 64bit parallel descrambling");
	return;
      }
#endif
    }
#if defined(__i386__)
  }
#endif
#endif

  tvhinfo(LS_CSA, "Using 32bit parallel descrambling");
}