Пример #1
0
static void
satip_discovery_send_msearch(void *aux)
{
#define MSG "\
M-SEARCH * HTTP/1.1\r\n\
HOST: 239.255.255.250:1900\r\n\
MAN: \"ssdp:discover\"\r\n\
MX: 2\r\n\
ST: urn:ses-com:device:SatIPServer:1\r\n"
  int attempt = ((intptr_t)aux) % 10;
  htsbuf_queue_t q;

  /* UDP is not reliable - send this message three times */
  if (attempt < 1 || attempt > 3)
    return;
  if (satip_discovery_service == NULL)
    return;

  htsbuf_queue_init(&q, 0);
  htsbuf_append(&q, MSG, sizeof(MSG)-1);
  htsbuf_qprintf(&q, "USER-AGENT: unix/1.0 UPnP/1.1 TVHeadend/%s\r\n", tvheadend_version);
  htsbuf_append(&q, "\r\n", 2);
  upnp_send(&q, NULL, 0);
  htsbuf_queue_flush(&q);

  gtimer_arm_ms(&satip_discovery_msearch_timer, satip_discovery_send_msearch,
                (void *)(intptr_t)(attempt + 1), attempt * 11);
#undef MSG
}
Пример #2
0
void
linuxdvb_ca_enqueue_capmt(linuxdvb_ca_t *lca, uint8_t slot, const uint8_t *ptr,
                          int len, uint8_t list_mgmt, uint8_t cmd_id)
{
  linuxdvb_ca_capmt_t *lcc;
  int c = 1;

  if (!lca)
    return;

  if (lca->lca_capmt_query && cmd_id == CA_PMT_CMD_ID_OK_DESCRAMBLING)
    c = 2;

  while (c--) {
    lcc = calloc(1, sizeof(*lcc));

    if (!lcc)
      return;

    lcc->data = malloc(len);
    lcc->len = len;
    lcc->slot = slot;
    lcc->list_mgmt = list_mgmt;
    lcc->cmd_id = (c ? CA_PMT_CMD_ID_QUERY : cmd_id);
    memcpy(lcc->data, ptr, len);

    TAILQ_INSERT_TAIL(&lca->lca_capmt_queue, lcc, lcc_link);

    tvhtrace("en50221", "%s CAPMT enqueued (%s)", ca_pmt_cmd_id2str(lcc->cmd_id),
             ca_pmt_list_mgmt2str(lcc->list_mgmt));
  }

  gtimer_arm_ms(&lca->lca_capmt_queue_timer,
                linuxdvb_ca_process_capmt_queue, lca, 50);
}
Пример #3
0
static int
download_pipe(download_t *dn, const char *args)
{
  char **argv = NULL;
  int r;

  download_pipe_close(dn);
  gtimer_disarm(&dn->pipe_read_timer);

  /* Arguments */
  if (spawn_parse_args(&argv, 64, args, NULL)) {
    tvherror(dn->log, "pipe: unable to parse arguments (%s)", args);
    return -1;
  }

  /* Grab */
  r = spawn_and_give_stdout(argv[0], argv, NULL, &dn->pipe_fd, &dn->pipe_pid, 1);

  spawn_free_args(argv);

  if (r < 0) {
    dn->pipe_fd = -1;
    dn->pipe_pid = 0;
    tvherror(dn->log, "pipe: cannot start (%s)", args);
    return -1;
  }

  fcntl(dn->pipe_fd, F_SETFL, fcntl(dn->pipe_fd, F_GETFL) | O_NONBLOCK);

  gtimer_arm_ms(&dn->pipe_read_timer, download_pipe_read, dn, 250);
  return 0;
}
Пример #4
0
static void
tvhdhomerun_discovery_timer_cb(void *aux)
{
  struct hdhomerun_discover_device_t result_list[MAX_HDHOMERUN_DEVICES];

  if (!tvheadend_running)
    return;

  int 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 ) {
        if ( !tvhdhomerun_device_find(cDev->device_id) ) {
          tvhlog(LOG_INFO, "tvhdhomerun","Found HDHomerun device %08x with %d tuners", cDev->device_id, cDev->tuner_count);
          tvhdhomerun_device_create(cDev);
        }
      }
    }  
  }

  // Do rediscovery every 30 seconds..
  gtimer_arm_ms(&tvhdhomerun_discovery_timer, tvhdhomerun_discovery_timer_cb, NULL, 15*1000); 
}
Пример #5
0
static void
linuxdvb_ca_monitor ( void *aux )
{
  linuxdvb_ca_t *lca = aux;
  ca_slot_info_t csi;
  int state;

  csi.num = 0;

  if (lca->lca_ca_fd >= 0) {
    if ((ioctl(lca->lca_ca_fd, CA_GET_SLOT_INFO, &csi)) != 0) {
      tvherror("linuxdvb", "failed to get CAM slot %u info [e=%s]",
               csi.num, strerror(errno));
    }
    if (csi.flags & CA_CI_MODULE_READY)
      state = CA_SLOT_STATE_MODULE_READY;
    else if (csi.flags & CA_CI_MODULE_PRESENT)
      state = CA_SLOT_STATE_MODULE_PRESENT;
    else
      state = CA_SLOT_STATE_EMPTY;

    lca->lca_state_str = ca_slot_state2str(state);

    if (lca->lca_state != state) {
      tvhlog(LOG_INFO, "linuxdvb", "CAM slot %u status changed to %s",
             csi.num, lca->lca_state_str);
      idnode_notify_title_changed(&lca->lca_id, NULL);
      lca->lca_state = state;
    }

    if ((!lca->lca_en50221_thread_running) &&
        (state == CA_SLOT_STATE_MODULE_READY)) 
    {
      lca->lca_en50221_thread_running = 1;
      tvhthread_create(&lca->lca_en50221_thread, NULL,
                       linuxdvb_ca_en50221_thread, lca);
    } else if (lca->lca_en50221_thread_running &&
               (state != CA_SLOT_STATE_MODULE_READY))
    {
      lca->lca_en50221_thread_running = 0;
      pthread_join(lca->lca_en50221_thread, NULL);
    }

  }

  gtimer_arm_ms(&lca->lca_monitor_timer, linuxdvb_ca_monitor, lca, 250);
}
Пример #6
0
linuxdvb_ca_t *
linuxdvb_ca_create
  ( htsmsg_t *conf, linuxdvb_adapter_t *la, int number, const char *ca_path)
{
  linuxdvb_ca_t *lca;
  char id[6];
  const char *uuid = NULL;

  lca = calloc(1, sizeof(linuxdvb_ca_t));
  memset(lca, 0, sizeof(linuxdvb_ca_t));
  lca->lca_number = number;
  lca->lca_ca_path  = strdup(ca_path);
  lca->lca_ca_fd = -1;
  lca->lca_capmt_interval = 100;
  lca->lca_capmt_query_interval = 1200;

  /* Internal config ID */
  snprintf(id, sizeof(id), "ca%u", number);

  if (conf)
    conf = htsmsg_get_map(conf, id);
  if (conf)
    uuid = htsmsg_get_str(conf, "uuid");

  if (idnode_insert(&lca->lca_id, uuid, &linuxdvb_ca_class, 0)) {
    free(lca);
    return NULL;
  }

  if (conf)
    idnode_load(&lca->lca_id, conf);

  /* Adapter link */
  lca->lca_adapter = la;
  LIST_INSERT_HEAD(&la->la_ca_devices, lca, lca_link);

  TAILQ_INIT(&lca->lca_capmt_queue);

  gtimer_arm_ms(&lca->lca_monitor_timer, linuxdvb_ca_monitor, lca, 250);

  return lca;
}
Пример #7
0
static void
download_pipe_read(void *aux)
{
  download_t *dn = aux;
  ssize_t len;
  char *s, *p;

  if (dn->pipe_fd < 0 || dn->pipe_pid == 0)
    return;

  while (1) {
    if (dn->pipe_sbuf.sb_ptr > 50*1024*1024) {
      errno = EMSGSIZE;
      goto failed;
    }
    sbuf_alloc(&dn->pipe_sbuf, 2048);
    len = sbuf_read(&dn->pipe_sbuf, dn->pipe_fd);
    if (len == 0) {
      s = dn->url ? strdupa(dn->url) : strdupa("");
      p = strchr(s, ' ');
      if (p)
        *p = '\0';
      p = strrchr(s, '/');
      if (p)
        p++;
      sbuf_append(&dn->pipe_sbuf, "", 1);
      dn->process(dn->aux, p, NULL, (char *)dn->pipe_sbuf.sb_data, (size_t)dn->pipe_sbuf.sb_ptr);
      download_pipe_close(dn);
      return;
    } else if (len < 0) {
      if (ERRNO_AGAIN(errno))
        break;
failed:
      tvherror(dn->log, "pipe: read failed: %d", errno);
      download_pipe_close(dn);
      return;
    }
  }

  gtimer_arm_ms(&dn->pipe_read_timer, download_pipe_read, dn, 250);
}
Пример #8
0
static void
satip_discovery_service_received
  (uint8_t *data, size_t len, udp_connection_t *conn,
   struct sockaddr_storage *storage)
{
  char *buf, *ptr, *saveptr;
  char *argv[10];
  char *st = NULL;
  char *location = NULL;
  char *server = NULL;
  char *uuid = NULL;
  char *bootid = NULL;
  char *configid = NULL;
  char *deviceid = NULL;
  char sockbuf[128];
  satip_discovery_t *d;
  int n, i;

  if (len > 8191 || satip_discoveries_count > 100)
    return;
  buf = alloca(len+1);
  memcpy(buf, data, len);
  buf[len] = '\0';
  ptr = strtok_r(buf, "\r\n", &saveptr);
  /* Request decoder */
  if (ptr) {
    if (http_tokenize(ptr, argv, 3, -1) != 3)
      return;
    if (conn->multicast) {
      if (strcmp(argv[0], "NOTIFY"))
        return;
      if (strcmp(argv[1], "*"))
        return;
      if (strcmp(argv[2], "HTTP/1.1"))
        return;
    } else {
      if (strcmp(argv[0], "HTTP/1.1"))
        return;
      if (strcmp(argv[1], "200"))
        return;
    }
    ptr = strtok_r(NULL, "\r\n", &saveptr);
  }
  /* Header decoder */
  while (1) {
    if (ptr == NULL)
      break;
    if (http_tokenize(ptr, argv, 2, ':') == 2) {
      if (strcmp(argv[0], "ST") == 0)
        st = argv[1];
      else if (strcmp(argv[0], "LOCATION") == 0)
        location = argv[1];
      else if (strcmp(argv[0], "SERVER") == 0)
        server = argv[1];
      else if (strcmp(argv[0], "BOOTID.UPNP.ORG") == 0)
        bootid = argv[1];
      else if (strcmp(argv[0], "CONFIGID.UPNP.ORG") == 0)
        configid = argv[1];
      else if (strcmp(argv[0], "DEVICEID.SES.COM") == 0)
        deviceid = argv[1];
      else if (strcmp(argv[0], "USN") == 0) {
        n = http_tokenize(argv[1], argv, ARRAY_SIZE(argv), ':');
        for (i = 0; i < n-1; i++)
          if (argv[i] && strcmp(argv[i], "uuid") == 0) {
            uuid = argv[++i];
            break;
          }
      }
    }
    ptr = strtok_r(NULL, "\r\n", &saveptr);
  }
  /* Sanity checks */
  if (st == NULL || strcmp(st, "urn:ses-com:device:SatIPServer:1"))
    goto add_uuid;
  if (uuid == NULL || strlen(uuid) < 16 || satip_server_match_uuid(uuid))
    goto add_uuid;
  if (location == NULL || strncmp(location, "http://", 7))
    goto add_uuid;
  if (bootid == NULL || configid == NULL || server == NULL)
    goto add_uuid;

  /* Forward information to next layer */

  d = calloc(1, sizeof(satip_discovery_t));
  if (inet_ntop(conn->ip.ss_family, IP_IN_ADDR(conn->ip),
                sockbuf, sizeof(sockbuf)) == NULL) {
    satip_discovery_destroy(d, 0);
    return;
  }
  d->myaddr   = strdup(sockbuf);
  d->location = strdup(location);
  d->server   = strdup(server);
  d->uuid     = strdup(uuid);
  d->bootid   = strdup(bootid);
  d->configid = strdup(configid);
  d->deviceid = strdup(deviceid ? deviceid : "");
  if (urlparse(d->location, &d->url)) {
    satip_discovery_destroy(d, 0);
    return;
  }

  pthread_mutex_lock(&global_lock);  
  i = 1;
  if (!satip_discovery_find(d) && !satip_device_find(d->uuid)) {
    TAILQ_INSERT_TAIL(&satip_discoveries, d, disc_link);
    satip_discoveries_count++;
    gtimer_arm_ms(&satip_discovery_timerq, satip_discovery_timerq_cb, NULL, 250);
    i = 0;
  }
  pthread_mutex_unlock(&global_lock);
  if (i) /* duplicate */
    satip_discovery_destroy(d, 0);
  return;

add_uuid:
  if (deviceid == NULL || uuid == NULL)
    return;
  /* if new uuid was discovered, retrigger MSEARCH */
  pthread_mutex_lock(&global_lock);
  if (!satip_device_find(uuid))
    gtimer_arm(&satip_discovery_timer, satip_discovery_timer_cb, NULL, 5);
  pthread_mutex_unlock(&global_lock);
}
Пример #9
0
void
satip_device_destroy_later( satip_device_t *sd, int after )
{
  gtimer_arm_ms(&sd->sd_destroy_timer, satip_device_destroy_cb, sd, after);
}
Пример #10
0
static void
linuxdvb_ca_process_capmt_queue ( void *aux )
{
  linuxdvb_ca_t *lca = aux;
  linuxdvb_ca_capmt_t *lcc;
  struct section *section;
  struct section_ext *result;
  struct mpeg_pmt_section *pmt;
  uint8_t capmt[4096];
  int size, i;

  lcc = TAILQ_FIRST(&lca->lca_capmt_queue);

  if (!lcc)
    return;

  if (!(section = section_codec(lcc->data, lcc->len))){
    tvherror("en50221", "failed to decode PMT section");
    goto done;
  }

  if (!(result = section_ext_decode(section, 0))){
    tvherror("en50221", "failed to decode PMT ext_section");
    goto done;
  }

  if (!(pmt = mpeg_pmt_section_codec(result))){
    tvherror("en50221", "failed to decode PMT");
    goto done;
  }

  size = en50221_ca_format_pmt(pmt, capmt, sizeof(capmt), 0,
                               lcc->list_mgmt, lcc->cmd_id);

  if (size < 0) {
    tvherror("en50221", "Failed to format CAPMT");
  }

  if (en50221_app_ca_pmt(lca->lca_ca_resource, lca->lca_ca_session_number,
                         capmt, size)) {
        tvherror("en50221", "Failed to send CAPMT");
  }

  tvhtrace("en50221", "%s CAPMT sent (%s)", ca_pmt_cmd_id2str(lcc->cmd_id),
           ca_pmt_list_mgmt2str(lcc->list_mgmt));
  tvhlog_hexdump("en50221", capmt, size);

done:
  i = (lcc->cmd_id == CA_PMT_CMD_ID_QUERY) ?
    lca->lca_capmt_query_interval : lca->lca_capmt_interval;

  TAILQ_REMOVE(&lca->lca_capmt_queue, lcc, lcc_link);

  free(lcc->data);
  free(lcc);

  if (!TAILQ_EMPTY(&lca->lca_capmt_queue)) {
    gtimer_arm_ms(&lca->lca_capmt_queue_timer,
                  linuxdvb_ca_process_capmt_queue, lca, i);
  }
}