Project

General

Profile

Feature #4461 » 0001-Add-HDHomeRun-server-support-for-LiveTV-only-4461.patch

Em Smith, 2020-06-10 21:30

View differences:

src/config.c
2507 2507
      .opts   = PO_HIDDEN | PO_EXPERT,
2508 2508
      .group  = 6
2509 2509
    },
2510
    {
2511
      .type   = PT_STR,
2512
      .id     = "hdhomerun_server_username",
2513
      .name   = N_("Local username for HDHomeRun Server"),
2514
      .desc   = N_("When TVheadend is acting as an HDHomeRun Server, "
2515
                   "we use this user for determining permissions such "
2516
                   "as channels.  This user must have persistent "
2517
                   "authentication enabled in the user password settings."),
2518
      .off    = offsetof(config_t, hdhomerun_server_username),
2519
      .opts   = PO_EXPERT,
2520
      .group  = 6,
2521
    },
2510 2522
    {
2511 2523
      .type   = PT_STR,
2512 2524
      .id     = "http_user_agent",
src/config.h
74 74
  char *hdhomerun_ip;
75 75
  char *local_ip;
76 76
  int local_port;
77
  char *hdhomerun_server_username;
77 78
} config_t;
78 79

  
79 80
extern const idclass_t config_class;
src/webui/webui.c
1597 1597
  return page_play_(hc, remain, opaque, URLAUTH_CODE);
1598 1598
}
1599 1599

  
1600

  
1601
/**
1602
 * Return the discovery information for HDHomeRun to give clients
1603
 * details of how to access the lineup.
1604
 *
1605
 * Our HDHomeRun server implementation uses a server configured
1606
 * username to determine access rather than passing it through the
1607
 * request.  This is because HDHomeRun clients are usually configured
1608
 * with only an IP address and port number and do not offer any input
1609
 * for credentials.
1610
 */
1611
static int
1612
hdhomerun_server_discover(http_connection_t *hc, const char *remain, void *opaque)
1613
{
1614
  const char *hdhr_user = config.hdhomerun_server_username ?: "";
1615
  access_t *perm = access_get_by_username(hdhr_user);
1616
  char http_ip[128];
1617
  htsbuf_queue_t *hq;
1618

  
1619
  if (access_verify2(perm, ACCESS_STREAMING))
1620
       return http_noaccess_code(hc);
1621

  
1622
  hq = &hc->hc_reply;
1623
  tcp_get_str_from_ip(hc->hc_self, http_ip, sizeof(http_ip));
1624

  
1625
  /* The contents below for the discovery message are based on tvhProxy */
1626
  htsbuf_qprintf(hq, "{ "                                               \
1627
                 "\"BaseURL\" : \"http://%s:%u\", "                     \
1628
                 "\"DeviceAuth\": \"none\", "                           \
1629
                 "\"DeviceID\": \"12345678\", "                         \
1630
                 "\"FirmwareName\": \"hdhomerun_atsc\", "               \
1631
                 "\"FirmwareVersion\": \"20200101\", "                  \
1632
                 "\"FriendlyName\": \"tvheadend\", "                    \
1633
                 "\"LineupURL\": \"http://%s:%u/lineup.json\", "        \
1634
                 "\"Manufacturer\": \"Silicondust\", "                  \
1635
                 "\"ModelNumber\": \"HDTC-2US\", "                      \
1636
                 "\"TunerCount\": 6 "                                   \
1637
                 "}",
1638
                 http_ip, tvheadend_webui_port, http_ip, tvheadend_webui_port);
1639
  http_output_content(hc, "application/json");
1640
  return 0;
1641
}
1642

  
1643
/**
1644
 * Dummy password verify callback for HDHomeRun.  We need this to
1645
 * ensure we can get the aa_auth information for the user in to the
1646
 * access_t since it is not populated by an access_get_by_username.
1647
 * Since the user is configured solely on the server, the "passwd" is
1648
 * always valid.
1649
 */
1650
static int
1651
hdhomerun_server_verify_callback(void *aux, const char *passwd)
1652
{
1653
  return 1;
1654
}
1655

  
1656
/**
1657
 * Return the channel lineup for HDHomeRun
1658
 */
1659
static int
1660
hdhomerun_server_lineup(http_connection_t *hc, const char *remain, void *opaque)
1661
{
1662
  const char *hdhr_user = config.hdhomerun_server_username ?: "";
1663
  access_t *perm = access_get(hc->hc_peer, hdhr_user, hdhomerun_server_verify_callback, NULL);
1664
  htsbuf_queue_t *hq;
1665
  channel_t *ch;
1666
  const char *name;
1667
  const char *blank;
1668
  const char *chnum_str;
1669
  const int use_auth = perm && perm->aa_auth && !strempty(perm->aa_auth);
1670
  char buf1[128], chnum[32], ubuf[UUID_HEX_SIZE];
1671
  char url[1024];
1672
  char http_ip[128];
1673
  const int flags =
1674
    (config.chname_num ? CHANNEL_ENAME_NUMBERS : 0) |
1675
    (config.chname_src ? CHANNEL_ENAME_SOURCES : 0);
1676
  int is_first = 1;
1677

  
1678
  if (access_verify2(perm, ACCESS_STREAMING))
1679
    return http_noaccess_code(hc);
1680

  
1681
  tcp_get_str_from_ip(hc->hc_self, http_ip, sizeof(http_ip));
1682
  blank = tvh_gettext_lang(perm->aa_lang_ui, channel_blank_name);
1683
  hq = &hc->hc_reply;
1684
  htsbuf_append_str(hq, "[");
1685
  tvh_mutex_lock(&global_lock);
1686
  CHANNEL_FOREACH(ch) {
1687
    if (!channel_access(ch, perm, 0) || !ch->ch_enabled)
1688
      continue;
1689
    if (!is_first)
1690
      htsbuf_append_str(hq, ", \n");
1691
    name = channel_get_ename(ch, buf1, sizeof(buf1), blank, flags);
1692
    htsbuf_append_str(hq, "{ \"GuideName\" : ");
1693
    htsbuf_append_and_escape_jsonstr(hq, name);
1694
    htsbuf_append_str(hq, ", \"GuideNumber\" : ");
1695
    /* channel_get_number_as_str returns NULL if no channel number! */
1696
    chnum_str = channel_get_number_as_str(ch, chnum, sizeof(chnum));
1697
    htsbuf_append_and_escape_jsonstr(hq, chnum_str ? chnum_str : "0");
1698
    htsbuf_append_str(hq, ", \"URL\" : ");
1699
    sprintf(url, "http://%s:%u/stream/channel/%s?profile=pass%s%s",
1700
            http_ip,
1701
            tvheadend_webui_port,
1702
            channel_get_uuid(ch, ubuf),
1703
            use_auth? "&auth=" : "",
1704
            use_auth ? perm->aa_auth : "");
1705
    htsbuf_append_and_escape_jsonstr(hq, url);
1706
    htsbuf_append_str(hq, "}");
1707
    is_first = 0;
1708
  }
1709
  tvh_mutex_unlock(&global_lock);
1710
  htsbuf_append_str(hq, "]");
1711
  http_output_content(hc, "application/json");
1712
  return 0;
1713
}
1714

  
1600 1715
/**
1601 1716
 *
1602 1717
 */
......
2133 2248
#if CONFIG_SATIP_SERVER
2134 2249
  http_path_add("/satip_server", NULL, satip_server_http_page, ACCESS_ANONYMOUS);
2135 2250
#endif
2251
  /* These names are specified in https://info.hdhomerun.com/info/http_api */
2252
  http_path_add("/discover.json", NULL, hdhomerun_server_discover, ACCESS_ANONYMOUS);
2253
  http_path_add("/lineup.json", NULL, hdhomerun_server_lineup, ACCESS_ANONYMOUS);
2136 2254

  
2137 2255
  http_path_add_modify("/play", NULL, page_play, ACCESS_ANONYMOUS, page_play_path_modify5);
2138 2256
  http_path_add_modify("/play/ticket", NULL, page_play_ticket, ACCESS_ANONYMOUS, page_play_path_modify12);
2139
- 
(1-1/19)