Exemple #1
0
tcp_stream_t *
tcp_stream_create_from_fd(int fd)
{
  tcp_stream_t *ts = calloc(1, sizeof(tcp_stream_t));

  ts->ts_fd = fd;
  htsbuf_queue_init(&ts->ts_spill, INT32_MAX);
  htsbuf_queue_init(&ts->ts_sendq, INT32_MAX);

  ts->ts_write = os_write;
  ts->ts_read  = os_read;

  return ts;
}
Exemple #2
0
static void
screenshot_response_task(void *task)
{
  response_t *r = task;
  hts_mutex_lock(&screenshot_mutex);
  if(screenshot_connection == NULL) {
    hts_mutex_unlock(&screenshot_mutex);
  } else {
    http_connection_t *hc = screenshot_connection;
    screenshot_connection = NULL;
    hts_mutex_unlock(&screenshot_mutex);

    if(r->url != NULL) {
      http_redirect(hc, r->url);
    } else {
      const char *msg = r->errmsg;
      if(msg == NULL)
        msg = "Error not specified";
      htsbuf_queue_t out;
      htsbuf_queue_init(&out, 0);
      htsbuf_append(&out, msg, strlen(msg));
      htsbuf_append_byte(&out, '\n');
      http_send_reply(hc, 500, "text/plain", NULL, NULL, 0, &out);
    }
  }
  free(r->url);
  free(r->errmsg);
  free(r);
}
Exemple #3
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
}
Exemple #4
0
JSBool 
js_json_encode(JSContext *cx, JSObject *obj,
	       uintN argc, jsval *argv, jsval *rval)
{
  JSObject *o;
  htsbuf_queue_t out;
  char *r;
  size_t len;

  if(!JS_ConvertArguments(cx, argc, argv, "o", &o))
    return JS_FALSE;

  if(o == NULL) {
    JS_ReportError(cx, "Not an object");
    return JS_FALSE;
  }

  htsbuf_queue_init(&out, 0);

  json_encode_from_object(cx, o, &out);

  len = out.hq_size;
  r = malloc(out.hq_size+1);
  r[len] = 0;
  htsbuf_read(&out, r, len);

  *rval = STRING_TO_JSVAL(JS_NewString(cx, r, len));
  return JS_TRUE;
}
Exemple #5
0
static int
hc_prop(http_connection_t *hc, const char *remain, void *opaque,
        http_cmd_t method)
{
    htsbuf_queue_t out;
    rstr_t *r;
    int rval, i;
    prop_t *p;
    const char *action = http_arg_get_req(hc, "action");

    if(remain == NULL)
        return 404;

    p = prop_from_path(remain);

    if(p == NULL)
        return 404;

    htsbuf_queue_init(&out, 0);

    switch(method) {
    case HTTP_CMD_GET:

        if(action != NULL) {
            event_t *e = event_create_action_str(action);
            prop_send_ext_event(p, e);
            event_release(e);
            rval = HTTP_STATUS_OK;
            break;
        }

        r = prop_get_string(p, NULL);

        if(r == NULL) {

            char **childs = prop_get_name_of_childs(p);
            if(childs == NULL) {
                rval = HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE;
                break;
            }
            for(i = 0; childs[i] != NULL; i++) {
                htsbuf_qprintf(&out, "\t%s\n", childs[i]);
            }
        } else {
            htsbuf_append(&out, rstr_get(r), strlen(rstr_get(r)));
            htsbuf_append(&out, "\n", 1);
            rstr_release(r);
        }
        rval = http_send_reply(hc, 0, "text/ascii", NULL, NULL, 0, &out);
        break;

    default:
        rval = HTTP_STATUS_METHOD_NOT_ALLOWED;
        break;
    }

    prop_ref_dec(p);

    return rval;
}
Exemple #6
0
tcpcon_t *
tcp_from_fd(int fd)
{
  tcpcon_t *tc = calloc(1, sizeof(tcpcon_t));
  tc->fd = fd;
  htsbuf_queue_init(&tc->spill, 0);
  tc->read = tcp_read;
  tc->write = tcp_write;
  return tc;
}
Exemple #7
0
static int
hc_done(http_connection_t *hc, const char *remain, void *opaque,
        http_cmd_t method)
{
  htsbuf_queue_t out;

  htsbuf_queue_init(&out, 0);
  htsbuf_qprintf(&out, "OK");
  return http_send_reply(hc, 0, "text/ascii", NULL, NULL, 0, &out);
}
Exemple #8
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 {
Exemple #9
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);
}
Exemple #10
0
static int
airplay_scrub(http_connection_t *hc, const char *remain, void *opaque,
		   http_cmd_t method)
{
  htsbuf_queue_t out;
  htsbuf_queue_init(&out, 0);
  htsbuf_qprintf(&out, 
		 "position: 0.123456\r\n"
		 "duration: 50.123456");

  return http_send_reply(hc, 0, NULL, NULL, NULL, 0, &out);
}
Exemple #11
0
tcpcon_t *
tcp_connect_arch(const net_addr_t *na,
                 char *errbuf, size_t errlen,
                 int timeout, cancellable_t *c, int dbg)
{
  PP_Resource sock = ppb_tcpsocket->Create(g_Instance);
  PP_Resource addr;

  struct PP_NetAddress_IPv4 ipv4_addr = {};
  struct PP_NetAddress_IPv6 ipv6_addr = {};

  switch(na->na_family) {
  case 4:
    memcpy(ipv4_addr.addr, na->na_addr, 4);
    wr16_be((uint8_t *)&ipv4_addr.port, na->na_port);
    addr = ppb_netaddress->CreateFromIPv4Address(g_Instance, &ipv4_addr);
    break;
  case 6:
    memcpy(ipv6_addr.addr, na->na_addr, 16);
    wr16_be((uint8_t *)&ipv6_addr.port, na->na_port);
    addr = ppb_netaddress->CreateFromIPv6Address(g_Instance, &ipv6_addr);
    break;
  default:
    abort();
  }

  if(dbg) { // debug
    struct PP_Var remote = ppb_netaddress->DescribeAsString(addr, 1);
    uint32_t len;
    const char *s = ppb_var->VarToUtf8(remote, &len);
    TRACE(TRACE_DEBUG, "TCP", "Connecting to %d %.*s", len, len, s);
    ppb_var->Release(remote);
  }

  int r = ppb_tcpsocket->Connect(sock, addr, PP_BlockUntilComplete());
  ppb_core->ReleaseResource(addr);
  if(r) {
    snprintf(errbuf, errlen, "Unable to connect -- %s", pepper_errmsg(r));
    ppb_core->ReleaseResource(sock);
    return NULL;
  }

  tcpcon_t *tc = calloc(1, sizeof(tcpcon_t));
  tc->fd = sock;

  htsbuf_queue_init(&tc->spill, 0);
  tc->read = tcp_read;
  tc->write = tcp_write;
  return tc;
}
Exemple #12
0
static int
hc_image(http_connection_t *hc, const char *remain, void *opaque,
         http_cmd_t method)
{
    htsbuf_queue_t out;
    pixmap_t *pm;
    char errbuf[200];
    const char *content;
    image_meta_t im = {0};
    im.im_no_decoding = 1;

    rstr_t *url = rstr_alloc(remain);

    pm = backend_imageloader(url, &im, NULL, errbuf, sizeof(errbuf), NULL,
                             NULL, NULL);
    rstr_release(url);
    if(pm == NULL)
        return http_error(hc, 404, "Unable to load image %s : %s",
                          remain, errbuf);

    if(!pixmap_is_coded(pm)) {
        pixmap_release(pm);
        return http_error(hc, 404,
                          "Unable to load image %s : Original data not available",
                          remain);
    }

    htsbuf_queue_init(&out, 0);
    htsbuf_append(&out, pm->pm_data, pm->pm_size);

    switch(pm->pm_type) {
    case PIXMAP_JPEG:
        content = "image/jpeg";
        break;
    case PIXMAP_PNG:
        content = "image/png";
        break;
    case PIXMAP_GIF:
        content = "image/gif";
        break;
    default:
        content = "image";
        break;
    }

    pixmap_release(pm);

    return http_send_reply(hc, 0, content, NULL, NULL, 0, &out);
}
Exemple #13
0
static int
hc_open(http_connection_t *hc, const char *remain, void *opaque,
	http_cmd_t method)
{
  htsbuf_queue_t out;

  const char *url = http_arg_get_req(hc, "url");

  if(url != NULL) {
    event_dispatch(event_create_openurl(url, NULL, NULL, NULL, NULL, NULL));
    return http_redirect(hc, "/showtime/open");
  }

  htsbuf_queue_init(&out, 0);
  htsbuf_append(&out, openpage, strlen(openpage));
  return http_send_reply(hc, 0, "text/html", NULL, NULL, 0, &out);
}
Exemple #14
0
void
upnp_send( htsbuf_queue_t *q, struct sockaddr_storage *storage )
{
  upnp_data_t *data;

  if (!upnp_running)
    return;
  data = calloc(1, sizeof(upnp_data_t));
  htsbuf_queue_init(&data->queue, 0);
  htsbuf_appendq(&data->queue, q);
  if (storage == NULL)
    data->storage = upnp_ipv4_multicast;
  else
    data->storage = *storage;
  pthread_mutex_lock(&upnp_lock);
  TAILQ_INSERT_TAIL(&upnp_data_write, data, data_link);
  pthread_mutex_unlock(&upnp_lock);
}
Exemple #15
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;
}
Exemple #16
0
static void *
send_report(void *aux)
{
  htsmsg_t *m = aux;
  htsbuf_queue_t hq;

  htsbuf_queue_init(&hq, 0);

  htsmsg_add_msg(m, "plugins", plugins_get_installed_list());

  htsmsg_json_serialize(m, &hq, 0);

  http_req("https://movian.tv/movian/status/v1/usage",
           HTTP_POSTDATA(&hq, "application/json"),
           NULL);

  htsmsg_release(m);
  return NULL;
}
Exemple #17
0
void
upnp_send( htsbuf_queue_t *q, struct sockaddr_storage *storage,
           int delay_ms, int from_multicast )
{
  upnp_data_t *data;

  if (!atomic_get(&upnp_running))
    return;
  data = calloc(1, sizeof(upnp_data_t));
  htsbuf_queue_init(&data->queue, 0);
  htsbuf_appendq(&data->queue, q);
  if (storage == NULL)
    data->storage = upnp_ipv4_multicast;
  else
    data->storage = *storage;
  data->delay_ms = delay_ms;
  data->from_multicast = from_multicast;
  tvh_mutex_lock(&upnp_lock);
  TAILQ_INSERT_TAIL(&upnp_data_write, data, data_link);
  tvh_mutex_unlock(&upnp_lock);
}
Exemple #18
0
static int
dumpstats(http_connection_t *hc, const char *remain, void *opaque,
          http_cmd_t method)
{
  int i;

  htsbuf_queue_t out;
  htsbuf_queue_init(&out, 0);

  np_context_t **vec = np_get_all_contexts();

  for(i = 0; vec[i] != NULL; i++)
    dump_context(&out, vec[i]);

  np_context_vec_free(vec);

  htsbuf_qprintf(&out, "\n");

  return http_send_reply(hc, 0,
                         "text/plain; charset=utf-8", NULL, NULL, 0, &out);
}
Exemple #19
0
static int
memstats(http_connection_t *hc, const char *remain, void *opaque,
	 http_cmd_t method)
{
  htsbuf_queue_t out;
  allsegs_t as = {};

  hts_lwmutex_lock(&mutex);
  tlsf_walk_heap(gpool, list_all_segs_walk, &as);
  int size = as.count * sizeof(seginfo_t);
  as.ptr = halloc(size);
  as.count = 0;
  tlsf_walk_heap(gpool, list_all_segs_walk, &as);
  hts_lwmutex_unlock(&mutex);

  qsort(as.ptr, as.count, sizeof(seginfo_t), seginfo_cmp);

  htsbuf_queue_init(&out, 0);

  htsbuf_qprintf(&out, "%d segments ptr=%p\n\n", as.count, as.ptr);
  int lastsize = -1;
  int dup = 0;
  for(int i = 0; i < as.count; i++) {
    if(as.ptr[i].size == lastsize && i != as.count - 1) {
      dup++;
    } else {
      htsbuf_qprintf(&out, "%s %10d * %d\n",
		     as.ptr[i].used ? "Used" : "Free", as.ptr[i].size,
		     dup + 1);
      dup = 0;
    }
    lastsize = as.ptr[i].size;
  }

  hfree(as.ptr, size);
  

  return http_send_reply(hc, 0, "text/plain", NULL, NULL, 0, &out);
}
Exemple #20
0
JSBool
js_cache_put(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
  char stash[256];
  const char *key,*lstash;
  char *value;
  uint32_t len, maxage;
  JSObject *o;
  htsbuf_queue_t out;
  js_plugin_t *jsp = JS_GetPrivate(cx, obj);

  if (!JS_ConvertArguments(cx, argc, argv, "ssou",
			   &lstash, &key, &o, &maxage))
    return JS_FALSE;

  if (o == NULL) {
    JS_ReportError(cx, "Not an object");
    return JS_FALSE;
  }

  // json encode object
  htsbuf_queue_init(&out, 0);
  if (json_encode_from_object(cx, o, &out) != 0) {
    JS_ReportError(cx, "Not an JSON object");
    return JS_FALSE;
  }

  len = out.hq_size;
  value = JS_malloc(cx,len + 1);
  value[len] = '\0';
  htsbuf_read(&out, value, len);

  // put json encoded object onto cache
  snprintf(stash, sizeof(stash), "plugin/%s/%s", jsp->jsp_id, lstash);
  blobcache_put(key, stash, value, len, maxage, NULL, 0);

  return JS_TRUE;
}
Exemple #21
0
static send_event_t *
upnp_event_generate_one(upnp_local_service_t *uls,
			upnp_subscription_t *us)
{
  send_event_t *set;
  char str[32];
    
  set = malloc(sizeof(send_event_t));

  htsbuf_queue_init(&set->out, 0);
  htsbuf_qprintf(&set->out,
		 "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
		 "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">");
    
  if(uls->uls_generate_props != NULL) {
    htsmsg_t *p = uls->uls_generate_props(uls, us->us_myhost, us->us_myport);
    htsmsg_field_t *f;
    
    HTSMSG_FOREACH(f, p) {
      htsbuf_qprintf(&set->out, "<e:property>");
      soap_encode_arg(&set->out, f);
      htsbuf_qprintf(&set->out, "</e:property>");
    }
Exemple #22
0
static int
hc_root_old(http_connection_t *hc)
{
  htsbuf_queue_t out;

  const char *url = http_arg_get_req(hc, "url");

  if(url != NULL) {
    event_dispatch(event_create_openurl(url, NULL, NULL, NULL, NULL, NULL));
    return http_redirect(hc, "/");
  }

  htsbuf_queue_init(&out, 0);

  htsbuf_qprintf(&out, 
		 "<html><body>"
		 "<h2>%s</h2><p>Version %s"
		 , gconf.system_name,
		 htsversion_full);

  htsbuf_qprintf(&out, 
		 "<form name=\"input\" method=\"get\">"
		 "Open URL in Showtime: "
		 "<input type=\"text\" name=\"url\" style=\"width:500px\"/>"
		 "<input type=\"submit\" value=\"Open\" />"
		 "</form>");
  
  htsbuf_qprintf(&out, "<h3>Diagnostics</h3>"); 

  diag_html(hc, &out);

  htsbuf_qprintf(&out, "<p><a href=\"/showtime/translation\">Upload and test new translation (.lang) file</a></p>");

  htsbuf_qprintf(&out, "</body></html>");
		 
  return http_send_reply(hc, 0, "text/html", NULL, NULL, 0, &out);
}
Exemple #23
0
tcpcon_t *
tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
	    int timeout, int ssl)
{
  struct hostent *hp;
  char *tmphstbuf;
  int fd, val, r, err, herr;
  const char *errtxt;
#if !defined(__APPLE__)
  struct hostent hostbuf;
  size_t hstbuflen;
  int res;
#endif
  struct sockaddr_in6 in6;
  struct sockaddr_in in;
  socklen_t errlen = sizeof(int);


  if(!strcmp(hostname, "localhost")) {
    if((fd = getstreamsocket(AF_INET, errbuf, errbufsize)) == -1)
      return NULL;

    memset(&in, 0, sizeof(in));
    in.sin_family = AF_INET;
    in.sin_port = htons(port);
    in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
  } else {

#if defined(__APPLE__)
    herr = 0;
    tmphstbuf = NULL; /* free NULL is a nop */
    /* TODO: AF_INET6 */
    hp = gethostbyname(hostname);
    if(hp == NULL)
      herr = h_errno;
#else
    hstbuflen = 1024;
    tmphstbuf = malloc(hstbuflen);

    while((res = gethostbyname_r(hostname, &hostbuf, tmphstbuf, hstbuflen,
				 &hp, &herr)) == ERANGE) {
      hstbuflen *= 2;
      tmphstbuf = realloc(tmphstbuf, hstbuflen);
    }
#endif
    if(herr != 0) {
      switch(herr) {
      case HOST_NOT_FOUND:
	errtxt = "Unknown host";
	break;

      case NO_ADDRESS:
	errtxt = "The requested name is valid but does not have an IP address";
	break;
      
      case NO_RECOVERY:
	errtxt = "A non-recoverable name server error occurred";
	break;
      
      case TRY_AGAIN:
	errtxt = "A temporary error occurred on an authoritative name server";
	break;
      
      default:
	errtxt = "Unknown error";
	break;
      }

      snprintf(errbuf, errbufsize, "%s", errtxt);
      free(tmphstbuf);
      return NULL;
    } else if(hp == NULL) {
      snprintf(errbuf, errbufsize, "Resolver internal error");
      free(tmphstbuf);
      return NULL;
    }

    if((fd = getstreamsocket(hp->h_addrtype, errbuf, errbufsize)) == -1) {
      free(tmphstbuf);
      return NULL;
    }

    switch(hp->h_addrtype) {
    case AF_INET:
      memset(&in, 0, sizeof(in));
      in.sin_family = AF_INET;
      in.sin_port = htons(port);
      memcpy(&in.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
      r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
      break;

    case AF_INET6:
      memset(&in6, 0, sizeof(in6));
      in6.sin6_family = AF_INET6;
      in6.sin6_port = htons(port);
      memcpy(&in6.sin6_addr, hp->h_addr_list[0], sizeof(struct in6_addr));
      r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in6));
      break;

    default:
      snprintf(errbuf, errbufsize, "Invalid protocol family");
      free(tmphstbuf);
      return NULL;
    }

    free(tmphstbuf);
  }
  if(r == -1) {
    if(errno == EINPROGRESS) {
      struct pollfd pfd;

      pfd.fd = fd;
      pfd.events = POLLOUT;
      pfd.revents = 0;

      r = poll(&pfd, 1, timeout);
      if(r == 0) {
	/* Timeout */
	snprintf(errbuf, errbufsize, "Connection attempt timed out");
	close(fd);
	return NULL;
      }
      
      if(r == -1) {
	snprintf(errbuf, errbufsize, "poll() error: %s", strerror(errno));
	close(fd);
	return NULL;
      }

      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 NULL;
  }
  
  fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);

  val = 1;
  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));

  tcpcon_t *tc = calloc(1, sizeof(tcpcon_t));
  tc->fd = fd;
  htsbuf_queue_init(&tc->spill, 0);
  

  if(ssl) {
#if ENABLE_OPENSSL
    if(showtime_ssl_ctx != NULL) {
      char errmsg[120];

      if((tc->ssl = SSL_new(showtime_ssl_ctx)) == NULL) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }
      if(SSL_set_fd(tc->ssl, tc->fd) == 0) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL fd: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }

      if(SSL_connect(tc->ssl) <= 0) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL connect: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }

      SSL_set_mode(tc->ssl, SSL_MODE_AUTO_RETRY);
      tc->read = ssl_read;
      tc->write = ssl_write;
    } else
#elif ENABLE_POLARSSL
    if(1) {
      tc->ssl = malloc(sizeof(ssl_context));
      if(ssl_init(tc->ssl)) {
	snprintf(errbuf, errlen, "SSL failed to initialize");
	close(fd);
	free(tc->ssl);
	free(tc);
	return NULL;
      }

      tc->ssn = malloc(sizeof(ssl_session));
      tc->hs = malloc(sizeof(havege_state));

      havege_init(tc->hs);
      memset(tc->ssn, 0, sizeof(ssl_session));


      ssl_set_endpoint(tc->ssl, SSL_IS_CLIENT );
      ssl_set_authmode(tc->ssl, SSL_VERIFY_NONE );

      ssl_set_rng(tc->ssl, havege_rand, tc->hs );
      ssl_set_bio(tc->ssl, net_recv, &tc->fd, net_send, &tc->fd);
      ssl_set_ciphers(tc->ssl, ssl_default_ciphers );
      ssl_set_session(tc->ssl, 1, 600, tc->ssn );
      
      tc->read = polarssl_read;
      tc->write = polarssl_write;
      
    } else
#endif
    {

      snprintf(errbuf, errlen, "SSL not supported");
      tcp_close(tc);
      return NULL;
    }
  } else {
    tc->read = tcp_read;
    tc->write = tcp_write;
  }

  return tc;
}
Exemple #24
0
static int
hc_image(http_connection_t *hc, const char *remain, void *opaque,
	http_cmd_t method)
{
  htsbuf_queue_t out;
  image_t *img;
  char errbuf[200];
  const char *content;
  image_meta_t im = {0};
  im.im_no_decoding = 1;
  rstr_t *url;
  const char *u = http_arg_get_req(hc, "url");
  
  if(u != NULL) {
    url = rstr_alloc(u);
    url_deescape(rstr_data(url));
  } else {
    if(remain == NULL) {
      return 404;
    }
    url = rstr_alloc(remain);
  }

  img = backend_imageloader(url, &im, NULL, errbuf, sizeof(errbuf), NULL,
                            NULL);
  rstr_release(url);
  if(img == NULL)
    return http_error(hc, 404, "Unable to load image %s : %s",
		      remain, errbuf);

  const image_component_t *ic = image_find_component(img, IMAGE_CODED);
  if(ic == NULL) {
    image_release(img);
    return http_error(hc, 404,
		      "Unable to load image %s : Original data not available",
		      remain);
  }
  const image_component_coded_t *icc = &ic->coded;

  htsbuf_queue_init(&out, 0);
  htsbuf_append(&out, buf_cstr(icc->icc_buf), buf_len(icc->icc_buf));

  switch(icc->icc_type) {
  case IMAGE_JPEG:
    content = "image/jpeg";
    break;
  case IMAGE_PNG:
    content = "image/png";
    break;
  case IMAGE_GIF:
    content = "image/gif";
    break;
  default:
    content = "image";
    break;
  }

  image_release(img);

  return http_send_reply(hc, 0, content, NULL, NULL, 0, &out);
}
Exemple #25
0
static void
screenshot_process(void *task)
{
  pixmap_t *pm = task;

  if(pm == NULL) {
    screenshot_response(NULL, "Screenshot not supported on this platform");
    return;
  }

  TRACE(TRACE_DEBUG, "Screenshot", "Processing image %d x %d",
        pm->pm_width, pm->pm_height);

  int codecid = AV_CODEC_ID_PNG;
  if(screenshot_connection)
    codecid = AV_CODEC_ID_MJPEG;

  buf_t *b = screenshot_compress(pm, codecid);
  pixmap_release(pm);
  if(b == NULL) {
    screenshot_response(NULL, "Unable to compress image");
    return;
  }

  if(!screenshot_connection) {
    char path[512];
    char errbuf[512];
    snprintf(path, sizeof(path), "%s/screenshot.png",
             gconf.cache_path);
    fa_handle_t *fa = fa_open_ex(path, errbuf, sizeof(errbuf),
                                 FA_WRITE, NULL);
    if(fa == NULL) {
      TRACE(TRACE_ERROR, "SCREENSHOT", "Unable to open %s -- %s",
            path, errbuf);
      buf_release(b);
      return;
    }
    fa_write(fa, buf_data(b), buf_len(b));
    fa_close(fa);
    TRACE(TRACE_INFO, "SCREENSHOT", "Written to %s", path);
    buf_release(b);
    return;
  }

  buf_t *result = NULL;
  htsbuf_queue_t hq;
  htsbuf_queue_init(&hq, 0);

  htsbuf_append(&hq, "image=", 6);
  htsbuf_append_and_escape_url_len(&hq, buf_cstr(b), buf_len(b));

  char errbuf[256];

  int ret = http_req("https://api.imgur.com/3/upload",
                     HTTP_FLAGS(FA_CONTENT_ON_ERROR),
                     HTTP_REQUEST_HEADER("Authorization",
                                         "Client-ID 7c79b311d4797ed"),
                     HTTP_RESULT_PTR(&result),
                     HTTP_POSTDATA(&hq, "application/x-www-form-urlencoded"),
                     HTTP_ERRBUF(errbuf, sizeof(errbuf)),
                     NULL);


  if(ret) {
    screenshot_response(NULL, errbuf);
  } else {

    htsmsg_t *response = htsmsg_json_deserialize(buf_cstr(result));
    if(response == NULL) {
      screenshot_response(NULL, "Unable to parse imgur response");
    } else {

      if(htsmsg_get_u32_or_default(response, "success", 0)) {
        const char *url = htsmsg_get_str_multi(response, "data", "link", NULL);
        screenshot_response(url, "No link in imgur response");
      } else {
        const char *msg = htsmsg_get_str_multi(response, "data", "error", NULL);
        if(msg == NULL) {
          screenshot_response(NULL, "Unkown imgur error");
        } else {
          snprintf(errbuf, sizeof(errbuf), "Imgur error: %s", msg);
          screenshot_response(NULL, errbuf);
        }
      }
      htsmsg_release(response);
    }
    buf_release(result);
  }
  buf_release(b);
}
Exemple #26
0
tcpcon_t *
tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
	    int timeout, int ssl)
{
  struct net_hostent *hp;
  char *tmphstbuf;
  int fd, r, err, herr, optval;
  const char *errtxt;
  struct sockaddr_in in;
  socklen_t errlen = sizeof(int);


  if(!strcmp(hostname, "localhost")) {
    if((fd = getstreamsocket(AF_INET, errbuf, errbufsize)) == -1)
      return NULL;

    memset(&in, 0, sizeof(in));
    in.sin_family = AF_INET;
    in.sin_port = htons(port);
    in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    r = netConnect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
  } else {

    herr = 0;
    tmphstbuf = NULL; /* free NULL is a nop */
    hp = netGetHostByName(hostname);
    if(hp == NULL)
      herr = h_errno;

    if(herr != 0) {
      switch(herr) {
      case HOST_NOT_FOUND:
	errtxt = "Unknown host";
	break;

      case NO_ADDRESS:
	errtxt = "The requested name is valid but does not have an IP address";
	break;
      
      case NO_RECOVERY:
	errtxt = "A non-recoverable name server error occurred";
	break;
      
      case TRY_AGAIN:
	errtxt = "A temporary error occurred on an authoritative name server";
	break;
      
      default:
	errtxt = "Unknown error";
	break;
      }

      snprintf(errbuf, errbufsize, "%s", errtxt);
      free(tmphstbuf);
      return NULL;
    } else if(hp == NULL) {
      snprintf(errbuf, errbufsize, "Resolver internal error");
      free(tmphstbuf);
      return NULL;
    }

    if((fd = getstreamsocket(hp->h_addrtype, errbuf, errbufsize)) == -1) {
      free(tmphstbuf);
      return NULL;
    }

    switch(hp->h_addrtype) {
    case AF_INET:
      memset(&in, 0, sizeof(in));
      in.sin_family = AF_INET;
      in.sin_port = htons(port);
      lv2_void* netaddrlist = (lv2_void*)(u64)hp->h_addr_list;
      memcpy(&in.sin_addr, (char*)(u64)netaddrlist[0], sizeof(struct in_addr));
      r = netConnect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
      break;

    default:
      snprintf(errbuf, errbufsize, "Invalid protocol family");
      free(tmphstbuf);
      return NULL;
    }

    free(tmphstbuf);
  }

  if(r < 0) {
    if(net_errno == NET_EINPROGRESS) {

      struct pollfd pfd;
      pfd.fd = fd;
      pfd.events = POLLOUT;
      pfd.revents = 0;

      r = netPoll(&pfd, 1, timeout);
      if(r == 0) {
	/* Timeout */
	snprintf(errbuf, errbufsize, "Connection attempt timed out");
	netClose(fd);
	return NULL;
      }
      
      if(r == -1) {
	snprintf(errbuf, errbufsize, "poll() error: %s", 
		 strerror(net_errno));
	netClose(fd);
	return NULL;
      }

      netGetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen);
    } else {
      err = net_errno;
    }
  } else {
    err = 0;
  }

  if(err != 0) {
    snprintf(errbuf, errbufsize, "%s", strerror(err));
    netClose(fd);
    return NULL;
  }
  
  optval = 0;
  r = netSetSockOpt(fd, SOL_SOCKET, SO_NBIO, &optval, sizeof(optval));
  if(r < 0) {
    snprintf(errbuf, errbufsize, "Unable to go blocking: %s",
	     strerror(net_errno));
    netClose(fd);
    return NULL;
  }

  tcpcon_t *tc = calloc(1, sizeof(tcpcon_t));
  tc->fd = fd;
  htsbuf_queue_init(&tc->spill, 0);


  if(ssl) {
#if ENABLE_POLARSSL
    if(1) {
      tc->ssl = malloc(sizeof(ssl_context));
      if(ssl_init(tc->ssl)) {
	snprintf(errbuf, errlen, "SSL failed to initialize");
	close(fd);
	free(tc->ssl);
	free(tc);
	return NULL;
      }

      tc->ssn = malloc(sizeof(ssl_session));
      tc->hs = malloc(sizeof(havege_state));

      havege_init(tc->hs);
      memset(tc->ssn, 0, sizeof(ssl_session));


      ssl_set_endpoint(tc->ssl, SSL_IS_CLIENT );
      ssl_set_authmode(tc->ssl, SSL_VERIFY_NONE );

      ssl_set_rng(tc->ssl, havege_rand, tc->hs );
      ssl_set_bio(tc->ssl, net_recv, &tc->fd, net_send, &tc->fd);
      ssl_set_ciphers(tc->ssl, ssl_default_ciphers );
      ssl_set_session(tc->ssl, 1, 600, tc->ssn );
      
      tc->read = polarssl_read;
      tc->write = polarssl_write;
      
    } else
#endif
    {

      snprintf(errbuf, errlen, "SSL not supported");
      tcp_close(tc);
      return NULL;
    }
  } else {
    tc->read = tcp_read;
    tc->write = tcp_write;
  }

  return tc;
}
Exemple #27
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);
    }
Exemple #28
0
static htsmsg_t *
avt_generate_props(upnp_local_service_t *uls, const char *myhost, int myport)
{
  char *event;
  htsbuf_queue_t xml;
  char str[256];
  const char *s;
  
  htsbuf_queue_init(&xml, 0);

  htsbuf_qprintf(&xml,
		 "<Event xmlns=\"urn:schemas-upnp-org:metadata-1-0/RCS/\">"
		 "<InstanceID val=\"0\">");


  upnp_event_encode_str(&xml, "TransportState", current_playstate());

  upnp_event_encode_str(&xml, "CurrentMediaCategory", current_mediaCategory());

  // PlaybackStorageMedium

  if(upnp_current_playstatus == NULL)
    s = "NONE";
  else
    s = "NETWORK";
  upnp_event_encode_str(&xml, "PlaybackStorageMedium", s);

  upnp_event_encode_str(&xml, "CurrentPlayMode", current_playMode());

  current_transportActions(str, sizeof(str));
  upnp_event_encode_str(&xml, "CurrentTransportActions", str);

  upnp_event_encode_int(&xml, "NumberOfTracks", upnp_current_total_tracks);
  upnp_event_encode_int(&xml, "CurrentTrack", upnp_current_track);
  upnp_event_encode_str(&xml, "AVTransportURI", upnp_current_url ?: "");
  upnp_event_encode_int(&xml, "TransportPlaySpeed", 1);

  // Metadata

  char *meta = build_didl(myhost, myport);
  upnp_event_encode_str(&xml, "AVTransportURIMetaData", meta);
  upnp_event_encode_str(&xml, "CurrentTrackMetaData", meta);
  free(meta);

  fmttime(str, sizeof(str), upnp_current_track_duration);
  upnp_event_encode_str(&xml, "CurrentTrackDuration", str);
  upnp_event_encode_str(&xml, "CurrentMediaDuration", str);

  upnp_event_encode_str(&xml, "PossibleRecordQualityModes", NULL);
  upnp_event_encode_str(&xml, "TransportStatus", "OK");
  upnp_event_encode_str(&xml, "DRMState", "UNKNOWN");
  upnp_event_encode_str(&xml, "RecordMediumWriteStatus", NULL);
  upnp_event_encode_str(&xml, "RecordStorageMedium", NULL);
  upnp_event_encode_str(&xml, "PossibleRecordStorageMedia", NULL);
  upnp_event_encode_str(&xml, "NextAVTransportURI", "");
  upnp_event_encode_str(&xml, "NextAVTransportURIMetaData", NULL);
  upnp_event_encode_str(&xml, "CurrentRecordQualityMode", NULL);
  upnp_event_encode_str(&xml, "PossiblePlaybackStorageMedia", "NETWORK");



  htsbuf_qprintf(&xml, "</InstanceID></Event>");

  event = htsbuf_to_string(&xml);

  htsmsg_t *r = htsmsg_create_map();
  htsmsg_add_str(r, "LastChange", event);
  free(event);
  return r;
}
Exemple #29
0
static char *
build_didl(const char *myhost, int myport)
{
  htsbuf_queue_t hq;

  htsbuf_queue_init(&hq, 0);

  htsbuf_qprintf(&hq,
		 "<DIDL-Lite xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\" "
		 "xmlns:dc=\"http://purl.org/dc/elements/1.1/\" "
		 "xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0\" "
		 "xmlns:pv=\"http://www.pv.com/pvns/\" "
		 "xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\">"
		 "<item id=\"101\" parentID=\"100\" restricted=\"0\">"
		 "<upnp:class xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\">object.item.audioItem.musicTrack</upnp:class>");

  if(upnp_current_title) {
    htsbuf_qprintf(&hq,
		   "<dc:title xmlns:dc=\"http://purl.org/dc/elements/1.1/\">");
    htsbuf_append_and_escape_xml(&hq, upnp_current_title);
    htsbuf_qprintf(&hq, "</dc:title>");
  }


  if(upnp_current_artist) {
    htsbuf_qprintf(&hq,
		   "<upnp:artist xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\">");
    htsbuf_append_and_escape_xml(&hq, upnp_current_artist);
    htsbuf_qprintf(&hq, "</upnp:artist>");
  }
  


  if(upnp_current_album) {
    htsbuf_qprintf(&hq,
		   "<upnp:album xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\">");
    htsbuf_append_and_escape_xml(&hq, upnp_current_album);
    htsbuf_qprintf(&hq, "</upnp:album>");
  }

  if(upnp_current_album_art) {

    char url[URL_MAX];
    const char *arturl;

    if(strncmp(upnp_current_album_art, "http://", strlen("http://"))) {
      snprintf(url, sizeof(url), "http://%s:%d/api/image/%s",
	       myhost, myport, upnp_current_album_art);
      arturl = url;
    } else {
      arturl = upnp_current_album_art;
    }

    htsbuf_qprintf(&hq,
		   "<upnp:albumArtURI xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\">");
    htsbuf_append_and_escape_xml(&hq, arturl);
    htsbuf_qprintf(&hq, "</upnp:albumArtURI>");
  }
  
  htsbuf_qprintf(&hq, "</item></DIDL-Lite>");

  return htsbuf_to_string(&hq);
}
Exemple #30
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;
}