示例#1
0
/*
 * Read thread
 */
static void *
iptv_file_thread ( void *aux )
{
  iptv_mux_t *im = aux;
  file_priv_t *fp = im->im_data;
  ssize_t r;
  int fd = fp->fd, pause = 0;
  char buf[32*1024];
  off_t off = 0;
  int64_t mono;
  int e;

#if defined(PLATFORM_DARWIN)
  fcntl(fd, F_NOCACHE, 1);
#endif
  pthread_mutex_lock(&iptv_lock);
  while (!fp->shutdown && fd > 0) {
    while (!fp->shutdown && pause) {
      mono = mclk() + sec2mono(1);
      do {
        e = tvh_cond_timedwait(&fp->cond, &iptv_lock, mono);
        if (e == ETIMEDOUT)
          break;
      } while (ERRNO_AGAIN(e));
    }
    if (fp->shutdown)
      break;
    pause = 0;
    pthread_mutex_unlock(&iptv_lock);
    r = read(fd, buf, sizeof(buf));
    pthread_mutex_lock(&iptv_lock);
    if (r == 0)
      break;
    if (r < 0) {
      if (ERRNO_AGAIN(errno))
        continue;
      break;
    }
    sbuf_append(&im->mm_iptv_buffer, buf, r);
    if (iptv_input_recv_packets(im, r) == 1)
      pause = 1;
#ifndef PLATFORM_DARWIN
#if !ENABLE_ANDROID
    posix_fadvise(fd, off, r, POSIX_FADV_DONTNEED);
#endif
#endif
    off += r;
  }
  pthread_mutex_unlock(&iptv_lock);
  return NULL;
}
示例#2
0
文件: tcp.c 项目: zman0900/tvheadend
int
tcp_read_timeout(int fd, void *buf, size_t len, int timeout)
{
  int x, tot = 0;
  struct pollfd fds;

  assert(timeout > 0);

  fds.fd = fd;
  fds.events = POLLIN;
  fds.revents = 0;

  while(tot != len) {

    x = poll(&fds, 1, timeout);
    if(x == 0)
      return ETIMEDOUT;
    if(x == -1) {
      if (!tvheadend_running)
        return ECONNRESET;
      if (ERRNO_AGAIN(errno))
        continue;
      return errno;
    }

    x = recv(fd, buf + tot, len - tot, MSG_DONTWAIT);
    if(x == -1) {
      if(ERRNO_AGAIN(errno))
        continue;
      return errno;
    }

    if(x == 0)
      return ECONNRESET;

    tot += x;
  }

  return 0;

}
示例#3
0
void
tvh_safe_usleep(int64_t us)
{
  int64_t r;
  if (us <= 0)
    return;
  do {
    r = tvh_usleep(us);
    if (r < 0) {
      if (ERRNO_AGAIN(-r))
        continue;
      break;
    }
    us = r;
  } while (r > 0);
}
示例#4
0
static int
download_file(download_t *dn, const char *filename)
{
  int fd, res;
  struct stat st;
  char *data, *last_url;
  ssize_t r;
  off_t off;

  fd = tvh_open(filename, O_RDONLY, 0);
  if (fd < 0) {
    tvherror(dn->log, "unable to open file '%s': %s",
             filename, strerror(errno));
    return -1;
  }
  if (fstat(fd, &st) || st.st_size == 0) {
    tvherror(dn->log, "unable to stat file '%s': %s",
             filename, strerror(errno));
    close(fd);
    return -1;
  }
  data = malloc(st.st_size+1);
  off = 0;
  do {
    r = read(fd, data + off, st.st_size - off);
    if (r < 0) {
      if (ERRNO_AGAIN(errno))
        continue;
      break;
    }
    off += r;
  } while (off != st.st_size);
  close(fd);

  if (off == st.st_size) {
    data[off] = '\0';
    last_url = strrchr(filename, '/');
    if (last_url)
      last_url++;
    res = dn->process(dn->aux, last_url, NULL, data, off);
  } else {
    res = -1;
  }
  free(data);
  return res;
}
示例#5
0
/*
 * Write data (retry on EAGAIN)
 */
static ssize_t _write
  ( int fd, const void *buf, size_t count )
{
  ssize_t r;
  size_t  n = 0;
  while ( n < count ) {
    r = write(fd, buf+n, count-n);
    if (r == -1) {
      if (ERRNO_AGAIN(errno))
        continue;
      else
        return -1;
    }
    n += r;
  }
  return count == n ? n : -1;
}
示例#6
0
/*
 * Read data
 */
static ssize_t
iptv_rtsp_read ( iptv_mux_t *im )
{
  rtsp_priv_t *rp = im->im_data;
  udp_multirecv_t *um = &rp->um;
  ssize_t r;
  uint8_t buf[1500];

  /* RTCP - ignore all incoming packets for now */
  do {
    r = recv(im->mm_iptv_fd2, buf, sizeof(buf), MSG_DONTWAIT);
  } while (r > 0);

  r = iptv_rtp_read(im, um, iptv_rtp_header_callback);
  if (r < 0 && ERRNO_AGAIN(errno))
    r = 0;
  return r;
}
示例#7
0
static void
spawn_pipe_read( th_pipe_t *p, char **_buf, int level )
{
  char *buf = *_buf, *s;
  size_t len;
  int r;

  if (buf == NULL) {
    buf = malloc(SPAWN_PIPE_READ_SIZE);
    buf[0] = '\0';
    buf[SPAWN_PIPE_READ_SIZE - 1] = 0;
    *_buf = buf;
  }
  while (1) {
    len = strlen(buf);
    r = read(p->rd, buf + len, SPAWN_PIPE_READ_SIZE - 1 - len);
    if (r < 1) {
      if (errno == EAGAIN)
        break;
      if (ERRNO_AGAIN(errno))
        continue;
      break;
    }
    buf[len + r] = '\0';
    tvhlog_hexdump("spawn", buf + len, r);
    while (1) {
      s = buf;
      while (*s && *s != '\n' && *s != '\r')
        s++;
      if (*s == '\0')
        break;
      *s++ = '\0';
      if (buf[0])
        tvhlog(level, "spawn", "%s", buf);
      memmove(buf, s, strlen(s) + 1);
    }
    if (strlen(buf) == SPAWN_PIPE_READ_SIZE - 1) {
      tvherror("spawn", "pipe buffer full");
      buf[0] = '\0';
    }
  }
}
示例#8
0
int64_t
tvh_usleep(int64_t us)
{
#if defined(PLATFORM_DARWIN)
  return usleep(us);
#else
  struct timespec ts;
  int64_t val;
  int r;
  if (us <= 0)
    return 0;
  ts.tv_sec = us / 1000000LL;
  ts.tv_nsec = (us % 1000000LL) * 1000LL;
  r = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts);
  val = (ts.tv_sec * 1000000LL) + ((ts.tv_nsec + 500LL) / 1000LL);
  if (ERRNO_AGAIN(r))
    return val;
  return r ? -r : 0;
#endif
}
示例#9
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);
}
示例#10
0
static void
spawn_pipe_write( th_pipe_t *p, const char *fmt, va_list ap )
{
  char buf[512], *s = buf;
  int r;

  vsnprintf(buf, sizeof(buf), fmt, ap);
  while (*s) {
    r = write(p->wr, s, strlen(s));
    if (r < 0) {
      if (errno == EAGAIN)
        break;
      if (ERRNO_AGAIN(errno))
        continue;
      break;
    }
    if (!r)
      break;
    s += r;
  }
}
示例#11
0
int64_t
tvh_usleep_abs(int64_t us)
{
#if defined(PLATFORM_DARWIN)
  /* Convert to relative wait */
  int64_t now = getmonoclock();
  int64_t relative = us - now;
  return tvh_usleep(relative);
#else
  struct timespec ts;
  int64_t val;
  int r;
  if (us <= 0)
    return 0;
  ts.tv_sec = us / 1000000LL;
  ts.tv_nsec = (us % 1000000LL) * 1000LL;
  r = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, &ts);
  val = (ts.tv_sec * 1000000LL) + ((ts.tv_nsec + 500LL) / 1000LL);
  if (ERRNO_AGAIN(r))
    return val;
  return r ? -r : 0;
#endif
}
示例#12
0
int
tvh_write(int fd, const void *buf, size_t len)
{
  time_t next = dispatch_clock + 25;
  ssize_t c;

  while (len) {
    c = write(fd, buf, len);
    if (c < 0) {
      if (ERRNO_AGAIN(errno)) {
        if (dispatch_clock > next)
          break;
        usleep(100);
        continue;
      }
      break;
    }
    len -= c;
    buf += c;
  }

  return len ? 1 : 0;
}
示例#13
0
int
tvh_write(int fd, const void *buf, size_t len)
{
  int64_t limit = mclk() + sec2mono(25);
  ssize_t c;

  while (len) {
    c = write(fd, buf, len);
    if (c < 0) {
      if (ERRNO_AGAIN(errno)) {
        if (mclk() > limit)
          break;
        tvh_safe_usleep(100);
        continue;
      }
      break;
    }
    len -= c;
    buf += c;
  }

  return len ? 1 : 0;
}
示例#14
0
int
udp_write( udp_connection_t *uc, const void *buf, size_t len,
           struct sockaddr_storage *storage )
{
  int r;

  if (storage == NULL)
    storage = &uc->ip;
  while (len) {
    r = sendto(uc->fd, buf, len, 0, (struct sockaddr*)storage,
               storage->ss_family == AF_INET6 ?
                 sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
    if (r < 0) {
      if (ERRNO_AGAIN(errno)) {
        tvh_safe_usleep(100);
        continue;
      }
      break;
    }
    len -= r;
    buf += r;
  }
  return len;
}
示例#15
0
static ssize_t _read_buf ( timeshift_file_t *tsf, int fd, void *buf, size_t size )
{
  ssize_t r;
  size_t ret;

  if (tsf && tsf->ram) {
    if (tsf->roff == tsf->woff) return 0;
    if (tsf->roff + size > tsf->woff) return -1;
    pthread_mutex_lock(&tsf->ram_lock);
    memcpy(buf, tsf->ram + tsf->roff, size);
    tsf->roff += size;
    pthread_mutex_unlock(&tsf->ram_lock);
    return size;
  } else {
    ret = 0;
    while (size > 0) {
      r = read(tsf ? tsf->rfd : fd, buf, size);
      if (r < 0) {
        if (ERRNO_AGAIN(errno))
          continue;
        tvhtrace(LS_TIMESHIFT, "read errno %d", errno);
        return -1;
      }
      if (r > 0) {
        size -= r;
        ret += r;
        buf += r;
      }
      if (r == 0)
        return 0;
    }
    if (ret > 0 && tsf)
      tsf->roff += ret;
    return ret;
  }
}
示例#16
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;
}
示例#17
0
文件: tcp.c 项目: zman0900/tvheadend
int
tcp_connect(const char *hostname, int port, const char *bindaddr,
            char *errbuf, size_t errbufsize, int timeout)
{
  int fd, r, res, err;
  struct addrinfo *ai;
  char portstr[6];
  socklen_t errlen = sizeof(err);

  snprintf(portstr, 6, "%u", port);
  res = getaddrinfo(hostname, portstr, NULL, &ai);
  
  if (res != 0) {
    snprintf(errbuf, errbufsize, "%s", gai_strerror(res));
    return -1;
  }

  fd = tvh_socket(ai->ai_family, SOCK_STREAM, 0);
  if(fd == -1) {
    snprintf(errbuf, errbufsize, "Unable to create socket: %s",
	     strerror(errno));
    freeaddrinfo(ai);
    return -1;
  }

  /**
   * Switch to nonblocking
   */
  fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);

  if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
    if (bindaddr && bindaddr[0] != '\0') {
      struct sockaddr_storage ip;
      memset(&ip, 0, sizeof(ip));
      ip.ss_family = ai->ai_family;
      if (inet_pton(AF_INET, bindaddr, IP_IN_ADDR(ip)) <= 0 ||
          bind(fd, (struct sockaddr *)&ip, IP_IN_ADDRLEN(ip)) < 0) {
        snprintf(errbuf, errbufsize, "Cannot bind to IPv%s addr '%s'",
                                     ai->ai_family == AF_INET6 ? "6" : "4",
                                     bindaddr);
        freeaddrinfo(ai);
        return -1;
      }
    }
  } else {
    snprintf(errbuf, errbufsize, "Invalid protocol family");
    freeaddrinfo(ai);
    return -1;
  }

  r = connect(fd, ai->ai_addr, ai->ai_addrlen);
  freeaddrinfo(ai);

  if(r == -1) {
    /* timeout < 0 - do not wait at all */
    if(errno == EINPROGRESS && timeout < 0) {
      err = 0;
    } else if(errno == EINPROGRESS) {
      tvhpoll_event_t ev;
      tvhpoll_t *efd;

      efd = tvhpoll_create(1);
      memset(&ev, 0, sizeof(ev));
      ev.events   = TVHPOLL_OUT;
      ev.fd       = fd;
      ev.data.ptr = &fd;
      tvhpoll_add(efd, &ev, 1);

      /* minimal timeout is one second */
      if (timeout < 1)
        timeout = 0;

      while (1) {
        if (!tvheadend_running) {
          errbuf[0] = '\0';
          tvhpoll_destroy(efd);
          close(fd);
          return -1;
        }

        r = tvhpoll_wait(efd, &ev, 1, timeout * 1000);
        if (r > 0)
          break;
        
        if (r == 0) { /* Timeout */
          snprintf(errbuf, errbufsize, "Connection attempt timed out");
          tvhpoll_destroy(efd);
          close(fd);
          return -1;
        }
      
        if (!ERRNO_AGAIN(errno)) {
          snprintf(errbuf, errbufsize, "poll() error: %s", strerror(errno));
          tvhpoll_destroy(efd);
          close(fd);
          return -1;
        }
      }
      
      tvhpoll_destroy(efd);
      getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen);
    } else {
      err = errno;
    }
  } else {
    err = 0;
  }

  if(err != 0) {
    snprintf(errbuf, errbufsize, "%s", strerror(err));
    close(fd);
    return -1;
  }
  
  fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);


  /* Set the keep-alive active */
  err = 1;
  setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&err, errlen);

  return fd;
}