Example #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
}
Example #2
0
File: tcp.c Project: yfqian/libsvc
void
tcp_close(tcp_stream_t *ts)
{
  if(ts->ts_ssl != NULL) {
    SSL_shutdown(ts->ts_ssl);
    SSL_free(ts->ts_ssl);
  }

  htsbuf_queue_flush(&ts->ts_spill);
  htsbuf_queue_flush(&ts->ts_sendq);
  if(ts->ts_fd != -1) {
    int r = close(ts->ts_fd);
    if(r)
      printf("Close failed!\n");
  }
  free(ts);
}
Example #3
0
void
hts_settings_save(htsmsg_t *record, const char *pathfmt, ...)
{
  char path[PATH_MAX];
  char tmppath[PATH_MAX];
  int fd;
  va_list ap;
  htsbuf_queue_t hq;
  htsbuf_data_t *hd;
  int ok, r, pack;

  if(settingspath == NULL)
    return;

  /* Clean the path */
  va_start(ap, pathfmt);
  _hts_settings_buildpath(path, sizeof(path), pathfmt, ap, settingspath);
  va_end(ap);

  /* Create directories */
  if (hts_settings_makedirs(path)) return;

  tvhdebug("settings", "saving to %s", path);

  /* Create tmp file */
  snprintf(tmppath, sizeof(tmppath), "%s.tmp", path);
  if((fd = tvh_open(tmppath, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR)) < 0) {
    tvhlog(LOG_ALERT, "settings", "Unable to create \"%s\" - %s",
	    tmppath, strerror(errno));
    return;
  }

  /* Store data */
#if ENABLE_ZLIB
  pack = strstr(path, "/muxes/") != NULL && /* ugly, redesign API */
         strstr(path, "/networks/") != NULL &&
         strstr(path, "/input/") != NULL;
#else
  pack = 0;
#endif
  ok = 1;

  if (!pack) {
    htsbuf_queue_init(&hq, 0);
    htsmsg_json_serialize(record, &hq, 1);
    TAILQ_FOREACH(hd, &hq.hq_q, hd_link)
      if(tvh_write(fd, hd->hd_data + hd->hd_data_off, hd->hd_data_len)) {
        tvhlog(LOG_ALERT, "settings", "Failed to write file \"%s\" - %s",
                tmppath, strerror(errno));
        ok = 0;
        break;
      }
    htsbuf_queue_flush(&hq);
  } else {
Example #4
0
void
hts_settings_save(htsmsg_t *record, const char *pathfmt, ...)
{
  char path[256];
  char tmppath[256];
  int fd;
  va_list ap;
  htsbuf_queue_t hq;
  htsbuf_data_t *hd;
  int ok;

  if(settingspath == NULL)
    return;

  /* Clean the path */
  va_start(ap, pathfmt);
  _hts_settings_buildpath(path, sizeof(path), pathfmt, ap, settingspath);
  va_end(ap);

  /* Create directories */
  if (hts_settings_makedirs(path)) return;

  tvhdebug("settings", "saving to %s", path);

  /* Create tmp file */
  snprintf(tmppath, sizeof(tmppath), "%s.tmp", path);
  if((fd = tvh_open(tmppath, O_CREAT | O_TRUNC | O_RDWR, 0700)) < 0) {
    tvhlog(LOG_ALERT, "settings", "Unable to create \"%s\" - %s",
	    tmppath, strerror(errno));
    return;
  }

  /* Store data */
  ok = 1;
  htsbuf_queue_init(&hq, 0);
  htsmsg_json_serialize(record, &hq, 1);
  TAILQ_FOREACH(hd, &hq.hq_q, hd_link)
    if(tvh_write(fd, hd->hd_data + hd->hd_data_off, hd->hd_data_len)) {
      tvhlog(LOG_ALERT, "settings", "Failed to write file \"%s\" - %s",
	      tmppath, strerror(errno));
      ok = 0;
      break;
    }
  close(fd);
  htsbuf_queue_flush(&hq);

  /* Move */
  if(ok) {
    rename(tmppath, path);
  
  /* Delete tmp */
  } else
    unlink(tmppath);
}
Example #5
0
void
tcp_close(tcpcon_t *tc)
{
#if ENABLE_POLARSSL
  if(tc->ssl != NULL) {
    ssl_close_notify(tc->ssl);
    ssl_free(tc->ssl);

    free(tc->ssl);
    free(tc->ssn);
    free(tc->hs);
  }
#endif
  htsbuf_queue_flush(&tc->spill);
  netClose(tc->fd);
  free(tc);
}
Example #6
0
void
upnp_server_done(void)
{
  upnp_data_t *data;
  upnp_service_t *us;

  atomic_set(&upnp_running, 0);
  tvh_thread_kill(upnp_tid, SIGTERM);
  pthread_join(upnp_tid, NULL);
  while ((us = TAILQ_FIRST(&upnp_services)) != NULL)
    upnp_service_destroy(us);
  while ((data = TAILQ_FIRST(&upnp_data_write)) != NULL) {
    TAILQ_REMOVE(&upnp_data_write, data, data_link);
    htsbuf_queue_flush(&data->queue);
    free(data);
  }
}
Example #7
0
static const void *description_get(wizard_page_t *page, const char **doc)
{
  htsbuf_queue_t q;

  if (!page->desc) {
    htsbuf_queue_init(&q, 0);
    for (; *doc; doc++) {
      if (*doc[0] == '\xff') {
        htsbuf_append_str(&q, tvh_gettext_lang(config.language_ui, *doc + 1));
      } else {
        htsbuf_append_str(&q, *doc);
      }
    }
    page->desc = htsbuf_to_string(&q);
    htsbuf_queue_flush(&q);
  }
  return &page->desc;
}
Example #8
0
void
tcp_close(tcpcon_t *tc)
{
#if ENABLE_OPENSSL
  if(tc->ssl != NULL) {
    SSL_shutdown(tc->ssl);
    SSL_free(tc->ssl);
  }
#endif
#if ENABLE_POLARSSL
  if(tc->ssl != NULL) {
    ssl_close_notify(tc->ssl);
    ssl_free(tc->ssl);

    free(tc->ssl);
    free(tc->ssn);
    free(tc->hs);
  }
#endif
  close(tc->fd);
  htsbuf_queue_flush(&tc->spill);
  free(tc);
}
Example #9
0
static void *
lirc_thread(void *aux)
{
  char buf[200];
  uint64_t ircode;
  uint32_t repeat;
  char keyname[100];
  int i, r, fd, len, n;
  htsbuf_queue_t q;
  struct pollfd fds;
  event_t *e;

  fd = lirc_fd;

  htsbuf_queue_init(&q, 0);
  fds.fd = fd;
  fds.events = POLLIN;

  while(1) {

    r = poll(&fds, 1, -1);
    if(r > 0) {
      if((r = read(fd, buf, sizeof(buf))) < 1) {
	TRACE(TRACE_ERROR, "lircd", "Read error: %s", strerror(errno));
	break;
      }
      htsbuf_append(&q, buf, r);
    }

    while((len = htsbuf_find(&q, 0xa)) != -1) {
      
      if(len >= sizeof(buf) - 1) {
	TRACE(TRACE_ERROR, "lircd", "Command buffer size exceeded");
	goto out;
      }

      htsbuf_read(&q, buf, len);
      buf[len] = 0;
      
      while(len > 0 && buf[len - 1] < 32)
	buf[--len] = 0;
      htsbuf_drop(&q, 1); /* Drop the \n */
      
      n = sscanf(buf, "%"PRIx64" %x %s", &ircode, &repeat, keyname);
      if(n != 3) {
	TRACE(TRACE_INFO, "lircd", "Invalid LIRC input: \"%s\"", buf);
	continue;
      }
      
      if(keyname[0] && keyname[1] == 0) {
	/* ASCII input */
	e = event_create_int(EVENT_UNICODE, keyname[0]);
      } else {
	e = NULL;
	for(i = 0; i < sizeof(lircmap) / sizeof(lircmap[0]); i++) {
	  if(!strcasecmp(keyname, lircmap[i].name)) {
	    action_type_t av[3] = {
	      lircmap[i].action1,
	      lircmap[i].action2,
	    };
	    if(av[1] != ACTION_NONE)
	      e = event_create_action_multi(av, 2);
	    else
	      e = event_create_action_multi(av, 1);
	    break;
	  }
	}
      }
      if(e == NULL) {
	snprintf(buf, sizeof(buf), "IR+%s", keyname);
	e = event_create_str(EVENT_KEYDESC, buf);
      }
      event_to_ui(e);
    }
  }
 out:
  close(fd);
  htsbuf_queue_flush(&q);
  return NULL;
}
Example #10
0
/*
 *  Discovery thread
 */
static void *
upnp_thread( void *aux )
{
  char *bindaddr = aux;
  tvhpoll_t *poll = tvhpoll_create(2);
  tvhpoll_event_t ev[2];
  upnp_data_t *data;
  udp_connection_t *multicast = NULL, *unicast = NULL;
  udp_connection_t *conn;
  unsigned char buf[16384];
  upnp_service_t *us;
  struct sockaddr_storage ip;
  socklen_t iplen;
  size_t size;
  int r, delay_ms;

  multicast = udp_bind(LS_UPNP, "upnp_thread_multicast",
                       "239.255.255.250", 1900, NULL,
                       NULL, 32*1024, 32*1024);
  if (multicast == NULL || multicast == UDP_FATAL_ERROR)
    goto error;
  unicast = udp_bind(LS_UPNP, "upnp_thread_unicast", bindaddr, 0, NULL,
                     NULL, 32*1024, 32*1024);
  if (unicast == NULL || unicast == UDP_FATAL_ERROR)
    goto error;

  memset(&ev, 0, sizeof(ev));
  ev[0].fd     = multicast->fd;
  ev[0].events = TVHPOLL_IN;
  ev[0].ptr    = multicast;
  ev[1].fd     = unicast->fd;
  ev[1].events = TVHPOLL_IN;
  ev[1].ptr    = unicast;
  tvhpoll_add(poll, ev, 2);

  delay_ms = 0;

  while (atomic_get(&upnp_running) && multicast->fd >= 0) {
    r = tvhpoll_wait(poll, ev, 2, delay_ms ?: 1000);
    if (r == 0) /* timeout */
      delay_ms = 0;

    while (r-- > 0) {
      if ((ev[r].events & TVHPOLL_IN) != 0) {
        conn = ev[r].ptr;
        iplen = sizeof(ip);
        size = recvfrom(conn->fd, buf, sizeof(buf), 0,
                                           (struct sockaddr *)&ip, &iplen);
        if (size > 0 && tvhtrace_enabled()) {
          char tbuf[256];
          inet_ntop(ip.ss_family, IP_IN_ADDR(ip), tbuf, sizeof(tbuf));
          tvhtrace(LS_UPNP, "%s - received data from %s:%hu [size=%zi]",
                   conn == multicast ? "multicast" : "unicast",
                   tbuf, (unsigned short) ntohs(IP_PORT(ip)), size);
          tvhlog_hexdump(LS_UPNP, buf, size);
        }
        /* TODO: a filter */
        TAILQ_FOREACH(us, &upnp_services, us_link)
          us->us_received(buf, size, conn, &ip);
      }
    }

    while (delay_ms == 0) {
      tvh_mutex_lock(&upnp_lock);
      data = TAILQ_FIRST(&upnp_data_write);
      if (data) {
        delay_ms = data->delay_ms;
        data->delay_ms = 0;
        if (!delay_ms) {
          TAILQ_REMOVE(&upnp_data_write, data, data_link);
        } else {
          data = NULL;
        }
      }
      tvh_mutex_unlock(&upnp_lock);
      if (data == NULL)
        break;
      upnp_dump_data(data);
      udp_write_queue(data->from_multicast ? multicast : unicast,
                      &data->queue, &data->storage);
      htsbuf_queue_flush(&data->queue);
      free(data);
      delay_ms = 0;
    }
  }

  /* flush the write queue (byebye messages) */
  while (1) {
    tvh_mutex_lock(&upnp_lock);
    data = TAILQ_FIRST(&upnp_data_write);
    if (data)
      TAILQ_REMOVE(&upnp_data_write, data, data_link);
    tvh_mutex_unlock(&upnp_lock);
    if (data == NULL)
      break;
    tvh_safe_usleep((long)data->delay_ms * 1000);
    upnp_dump_data(data);
    udp_write_queue(unicast, &data->queue, &data->storage);
    htsbuf_queue_flush(&data->queue);
    free(data);
  }

error:
  atomic_set(&upnp_running, 0);
  tvhpoll_destroy(poll);
  udp_close(unicast);
  udp_close(multicast);
  return NULL;
}
Example #11
0
int
soap_exec(const char *uri, const char *service, int version, const char *method,
	  htsmsg_t *in, htsmsg_t **outp, char *errbuf, size_t errlen)
{
  int r;
  htsmsg_t *out;
  htsbuf_queue_t post;
  buf_t *result;
  struct http_header_list hdrs = {0};
  char tmp[100];

  htsbuf_queue_init(&post, 0);

  htsbuf_qprintf(&post,
		 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
		 "<s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">"
		 "<s:Body><ns0:%s xmlns:ns0=\"urn:schemas-upnp-org:service:%s:%d\">", method, service, version);

  soap_encode_args(&post, in);
  htsbuf_qprintf(&post, "</ns0:%s></s:Body></s:Envelope>", method);

  snprintf(tmp, sizeof(tmp),"\"urn:schemas-upnp-org:service:%s:%d#%s\"",
	   service, version, method);

  http_header_add(&hdrs, "SOAPACTION", tmp, 0);

  r = http_request(uri, NULL, &result, errbuf, errlen,
		   &post, "text/xml; charset=\"utf-8\"",
		   0, NULL, &hdrs, NULL, NULL, NULL);

  http_headers_free(&hdrs);

  htsbuf_queue_flush(&post);

  if(r)
    return -1;

  out = htsmsg_xml_deserialize_buf2(result, errbuf, errlen);
  if(out == NULL)
    return -1;

  snprintf(tmp, sizeof(tmp), "urn:schemas-upnp-org:service:%s:%d%sResponse",
	   service, version, method);

  htsmsg_t *outargs = 
    htsmsg_get_map_multi(out,
			 "tags",
			 "http://schemas.xmlsoap.org/soap/envelope/Envelope",
			 "tags",
			 "http://schemas.xmlsoap.org/soap/envelope/Body",
			 "tags",
			 tmp,
			 "tags",
			 NULL);

  if(outargs != NULL) {
    htsmsg_field_t *f;
    htsmsg_t *out = htsmsg_create_map();
    // Convert args from XML style to more compact style
    HTSMSG_FOREACH(f, outargs) {
      htsmsg_t *a;
      const char *s;

      if((a = htsmsg_get_map_by_field(f)) == NULL)
	continue;
      if((s = htsmsg_get_str(a, "cdata")) != NULL)
	htsmsg_add_str(out, f->hmf_name, s);
    }
Example #12
0
/*
 *  Discovery thread
 */
static void *
upnp_thread( void *aux )
{
  char *bindaddr = aux;
  tvhpoll_t *poll = tvhpoll_create(2);
  tvhpoll_event_t ev[2];
  upnp_data_t *data;
  udp_connection_t *multicast = NULL, *unicast = NULL;
  udp_connection_t *conn;
  unsigned char buf[16384];
  upnp_service_t *us;
  struct sockaddr_storage ip;
  socklen_t iplen;
  size_t size;
  int r;

  multicast = udp_bind("upnp", "upnp_thread_multicast",
                       "239.255.255.250", 1900,
                       NULL, 32*1024);
  if (multicast == NULL || multicast == UDP_FATAL_ERROR)
    goto error;
  unicast = udp_bind("upnp", "upnp_thread_unicast", bindaddr, 0,
                     NULL, 32*1024);
  if (unicast == NULL || unicast == UDP_FATAL_ERROR)
    goto error;

  memset(&ev, 0, sizeof(ev));
  ev[0].fd       = multicast->fd;
  ev[0].events   = TVHPOLL_IN;
  ev[0].data.ptr = multicast;
  ev[1].fd       = unicast->fd;
  ev[1].events   = TVHPOLL_IN;
  ev[1].data.ptr = unicast;
  tvhpoll_add(poll, ev, 2);

  while (upnp_running && multicast->fd >= 0) {
    r = tvhpoll_wait(poll, ev, 2, 1000);

    while (r-- > 0) {
      if ((ev[r].events & TVHPOLL_IN) != 0) {
        conn = ev[r].data.ptr;
        iplen = sizeof(ip);
        size = recvfrom(conn->fd, buf, sizeof(buf), 0,
                                           (struct sockaddr *)&ip, &iplen);
#if ENABLE_TRACE
        if (size > 0) {
          char tbuf[256];
          inet_ntop(ip.ss_family, IP_IN_ADDR(ip), tbuf, sizeof(tbuf));
          tvhtrace("upnp", "%s - received data from %s:%hu [size=%zi]",
                   conn == multicast ? "multicast" : "unicast",
                   tbuf, (unsigned short) IP_PORT(ip), size);
          tvhlog_hexdump("upnp", buf, size);
        }
#endif
        /* TODO: a filter */
        TAILQ_FOREACH(us, &upnp_services, us_link)
          us->us_received(buf, size, conn, &ip);
      }
    }

    while (1) {
      pthread_mutex_lock(&upnp_lock);
      data = TAILQ_FIRST(&upnp_data_write);
      if (data)
        TAILQ_REMOVE(&upnp_data_write, data, data_link);
      pthread_mutex_unlock(&upnp_lock);
      if (data == NULL)
        break;
      udp_write_queue(unicast, &data->queue, &data->storage);
      htsbuf_queue_flush(&data->queue);
      free(data);
    }
  }

error:
  upnp_running = 0;
  tvhpoll_destroy(poll);
  udp_close(unicast);
  udp_close(multicast);
  return NULL;
}