channel enhancements (enabled), fixed min/max chnum handling (access)

This commit is contained in:
Jaroslav Kysela 2014-11-21 18:02:27 +01:00
parent 00f3cc0e8a
commit da3d9ecb48
14 changed files with 87 additions and 45 deletions

View file

@ -348,7 +348,7 @@ access_dump_a(access_t *a)
int first; int first;
snprintf(buf, sizeof(buf), snprintf(buf, sizeof(buf),
"%s:%s [%s%s%s%s%s], conn=%u, chmin=%u, chmax=%u%s", "%s:%s [%s%s%s%s%s], conn=%u, chmin=%llu, chmax=%llu%s",
a->aa_representative ?: "<no-id>", a->aa_representative ?: "<no-id>",
a->aa_username ?: "<no-user>", a->aa_username ?: "<no-user>",
a->aa_rights & ACCESS_STREAMING ? "S" : "", a->aa_rights & ACCESS_STREAMING ? "S" : "",
@ -357,7 +357,7 @@ access_dump_a(access_t *a)
a->aa_rights & ACCESS_RECORDER ? "R" : "", a->aa_rights & ACCESS_RECORDER ? "R" : "",
a->aa_rights & ACCESS_ADMIN ? "*" : "", a->aa_rights & ACCESS_ADMIN ? "*" : "",
a->aa_conn_limit, a->aa_conn_limit,
a->aa_chmin, a->aa_chmax, (long long)a->aa_chmin, (long long)a->aa_chmax,
a->aa_match ? ", matched" : ""); a->aa_match ? ", matched" : "");
if (a->aa_profiles) { if (a->aa_profiles) {
@ -1295,13 +1295,15 @@ const idclass_t access_entry_class = {
.off = offsetof(access_entry_t, ae_conn_limit), .off = offsetof(access_entry_t, ae_conn_limit),
}, },
{ {
.type = PT_U32, .type = PT_S64,
.intsplit = CHANNEL_SPLIT,
.id = "channel_min", .id = "channel_min",
.name = "Min Channel Num", .name = "Min Channel Num",
.off = offsetof(access_entry_t, ae_chmin), .off = offsetof(access_entry_t, ae_chmin),
}, },
{ {
.type = PT_U32, .type = PT_S64,
.intsplit = CHANNEL_SPLIT,
.id = "channel_max", .id = "channel_max",
.name = "Max Channel Num", .name = "Max Channel Num",
.off = offsetof(access_entry_t, ae_chmax), .off = offsetof(access_entry_t, ae_chmax),

View file

@ -70,8 +70,8 @@ typedef struct access_entry {
int ae_webui; int ae_webui;
int ae_admin; int ae_admin;
uint32_t ae_chmin; uint64_t ae_chmin;
uint32_t ae_chmax; uint64_t ae_chmax;
struct channel_tag *ae_chtag; struct channel_tag *ae_chtag;
LIST_ENTRY(access_entry) ae_channel_tag_link; LIST_ENTRY(access_entry) ae_channel_tag_link;
@ -89,8 +89,8 @@ typedef struct access {
uint32_t aa_rights; uint32_t aa_rights;
htsmsg_t *aa_profiles; htsmsg_t *aa_profiles;
htsmsg_t *aa_dvrcfgs; htsmsg_t *aa_dvrcfgs;
uint32_t aa_chmin; uint64_t aa_chmin;
uint32_t aa_chmax; uint64_t aa_chmax;
htsmsg_t *aa_chtags; htsmsg_t *aa_chtags;
int aa_match; int aa_match;
uint32_t aa_conn_limit; uint32_t aa_conn_limit;

View file

@ -25,21 +25,28 @@
#include "access.h" #include "access.h"
#include "api.h" #include "api.h"
static void
api_channel_key_val(htsmsg_t *dst, const char *key, const char *val)
{
htsmsg_t *e = htsmsg_create_map();
htsmsg_add_str(e, "key", key);
htsmsg_add_str(e, "val", val ?: "");
htsmsg_add_msg(dst, NULL, e);
}
// TODO: this will need converting to an idnode system // TODO: this will need converting to an idnode system
static int static int
api_channel_list api_channel_list
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp ) ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{ {
channel_t *ch; channel_t *ch;
htsmsg_t *l, *e; htsmsg_t *l;
l = htsmsg_create_list(); l = htsmsg_create_list();
pthread_mutex_lock(&global_lock); pthread_mutex_lock(&global_lock);
CHANNEL_FOREACH(ch) { CHANNEL_FOREACH(ch) {
e = htsmsg_create_map(); if (!channel_access(ch, perm, 0)) continue;
htsmsg_add_str(e, "key", idnode_uuid_as_str(&ch->ch_id)); api_channel_key_val(l, idnode_uuid_as_str(&ch->ch_id), channel_get_name(ch));
htsmsg_add_str(e, "val", channel_get_name(ch));
htsmsg_add_msg(l, NULL, e);
} }
pthread_mutex_unlock(&global_lock); pthread_mutex_unlock(&global_lock);
*resp = htsmsg_create_map(); *resp = htsmsg_create_map();
@ -55,7 +62,8 @@ api_channel_grid
channel_t *ch; channel_t *ch;
CHANNEL_FOREACH(ch) CHANNEL_FOREACH(ch)
idnode_set_add(ins, (idnode_t*)ch, &conf->filter); if (channel_access(ch, perm, 1))
idnode_set_add(ins, (idnode_t*)ch, &conf->filter);
} }
static int static int
@ -82,14 +90,19 @@ api_channel_tag_list
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp ) ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{ {
channel_tag_t *ct; channel_tag_t *ct;
htsmsg_t *l, *e; htsmsg_t *l;
l = htsmsg_create_list(); l = htsmsg_create_list();
TAILQ_FOREACH(ct, &channel_tags, ct_link) { if (perm->aa_chtags) {
e = htsmsg_create_map(); htsmsg_field_t *f;
htsmsg_add_str(e, "key", idnode_uuid_as_str(&ct->ct_id)); HTSMSG_FOREACH(f, perm->aa_chtags) {
htsmsg_add_str(e, "val", ct->ct_name); ct = channel_tag_find_by_uuid(htsmsg_field_get_str(f) ?: "");
htsmsg_add_msg(l, NULL, e); if (ct)
api_channel_key_val(l, idnode_uuid_as_str(&ct->ct_id), ct->ct_name);
}
} else {
TAILQ_FOREACH(ct, &channel_tags, ct_link)
api_channel_key_val(l, idnode_uuid_as_str(&ct->ct_id), ct->ct_name);
} }
*resp = htsmsg_create_map(); *resp = htsmsg_create_map();
htsmsg_add_msg(*resp, "entries", l); htsmsg_add_msg(*resp, "entries", l);
@ -102,8 +115,17 @@ api_channel_tag_grid
{ {
channel_tag_t *ct; channel_tag_t *ct;
TAILQ_FOREACH(ct, &channel_tags, ct_link) if (perm->aa_chtags) {
idnode_set_add(ins, (idnode_t*)ct, &conf->filter); htsmsg_field_t *f;
HTSMSG_FOREACH(f, perm->aa_chtags) {
ct = channel_tag_find_by_uuid(htsmsg_field_get_str(f) ?: "");
if (ct)
idnode_set_add(ins, (idnode_t*)ct, &conf->filter);
}
} else {
TAILQ_FOREACH(ct, &channel_tags, ct_link)
idnode_set_add(ins, (idnode_t*)ct, &conf->filter);
}
} }
static int static int

View file

@ -422,7 +422,7 @@ api_epg_grid
/* Query the EPG */ /* Query the EPG */
pthread_mutex_lock(&global_lock); pthread_mutex_lock(&global_lock);
epg_query(&eq); epg_query(&eq, perm);
/* Build response */ /* Build response */
start = MIN(eq.entries, start); start = MIN(eq.entries, start);

View file

@ -309,14 +309,12 @@ const idclass_t channel_class = {
.ic_get_title = channel_class_get_title, .ic_get_title = channel_class_get_title,
.ic_delete = channel_class_delete, .ic_delete = channel_class_delete,
.ic_properties = (const property_t[]){ .ic_properties = (const property_t[]){
#if 0
{ {
.type = PT_BOOL, .type = PT_BOOL,
.id = "enabled", .id = "enabled",
.name = "Enabled", .name = "Enabled",
.off = offsetof(channel_t, ch_enabled), .off = offsetof(channel_t, ch_enabled),
}, },
#endif
{ {
.type = PT_STR, .type = PT_STR,
.id = "name", .id = "name",
@ -417,7 +415,7 @@ channel_find_by_name ( const char *name )
if (name == NULL) if (name == NULL)
return NULL; return NULL;
CHANNEL_FOREACH(ch) CHANNEL_FOREACH(ch)
if (!strcmp(channel_get_name(ch), name)) if (ch->ch_enabled && !strcmp(channel_get_name(ch), name))
break; break;
return ch; return ch;
} }
@ -457,17 +455,23 @@ channel_find_by_number ( const char *no )
* Check if user can access the channel * Check if user can access the channel
*/ */
int int
channel_access(channel_t *ch, access_t *a, const char *username) channel_access(channel_t *ch, access_t *a, int disabled)
{ {
if (!ch)
return 0;
if (!disabled && !ch->ch_enabled)
return 0;
/* Channel number check */ /* Channel number check */
if (ch && (a->aa_chmin || a->aa_chmax)) { if (a->aa_chmin || a->aa_chmax) {
int chnum = channel_get_number(ch); int64_t chnum = channel_get_number(ch);
if (chnum < a->aa_chmin || chnum > a->aa_chmax) if (chnum < a->aa_chmin || chnum > a->aa_chmax)
return 0; return 0;
} }
/* Channel tag check */ /* Channel tag check */
if (ch && a->aa_chtags) { if (a->aa_chtags) {
channel_tag_mapping_t *ctm; channel_tag_mapping_t *ctm;
htsmsg_field_t *f; htsmsg_field_t *f;
HTSMSG_FOREACH(f, a->aa_chtags) { HTSMSG_FOREACH(f, a->aa_chtags) {
@ -722,6 +726,9 @@ channel_create0
abort(); abort();
} }
/* Defaults */
ch->ch_enabled = 1;
if (conf) { if (conf) {
ch->ch_load = 1; ch->ch_load = 1;
idnode_load(&ch->ch_id, conf); idnode_load(&ch->ch_id, conf);

View file

@ -43,12 +43,13 @@ typedef struct channel
idnode_t ch_id; idnode_t ch_id;
RB_ENTRY(channel) ch_link; RB_ENTRY(channel) ch_link;
int ch_refcount; int ch_refcount;
int ch_zombie; int ch_zombie;
int ch_load; int ch_load;
/* Channel info */ /* Channel info */
int ch_enabled;
char *ch_name; // Note: do not access directly! char *ch_name; // Note: do not access directly!
int64_t ch_number; int64_t ch_number;
char *ch_icon; char *ch_icon;
@ -176,7 +177,7 @@ htsmsg_t * channel_tag_class_get_list(void *o);
const char * channel_tag_get_icon(channel_tag_t *ct); const char * channel_tag_get_icon(channel_tag_t *ct);
int channel_access(channel_t *ch, struct access *a, const char *username); int channel_access(channel_t *ch, struct access *a, int disabled);
int channel_tag_map(channel_t *ch, channel_tag_t *ct); int channel_tag_map(channel_t *ch, channel_tag_t *ct);
void channel_tag_unmap(channel_t *ch, channel_tag_t *ct); void channel_tag_unmap(channel_t *ch, channel_tag_t *ct);

View file

@ -1047,6 +1047,7 @@ dvr_autorec_changed(dvr_autorec_entry_t *dae, int purge)
dvr_autorec_purge_spawns(dae, 1); dvr_autorec_purge_spawns(dae, 1);
CHANNEL_FOREACH(ch) { CHANNEL_FOREACH(ch) {
if (!ch->ch_enabled) continue;
RB_FOREACH(e, &ch->ch_epg_schedule, sched_link) { RB_FOREACH(e, &ch->ch_epg_schedule, sched_link) {
if(autorec_cmp(dae, e)) if(autorec_cmp(dae, e))
dvr_entry_create_by_autorec(e, dae); dvr_entry_create_by_autorec(e, dae);

View file

@ -2517,7 +2517,7 @@ static int _epg_sort_genre_descending ( const void *a, const void *b, void *eq )
} }
epg_broadcast_t ** epg_broadcast_t **
epg_query ( epg_query_t *eq ) epg_query ( epg_query_t *eq, access_t *perm )
{ {
channel_t *channel; channel_t *channel;
channel_tag_t *tag; channel_tag_t *tag;
@ -2542,20 +2542,25 @@ epg_query ( epg_query_t *eq )
/* Single channel */ /* Single channel */
if (channel && tag == NULL) { if (channel && tag == NULL) {
_eq_add_channel(eq, channel); if (channel_access(channel, perm, 0))
_eq_add_channel(eq, channel);
/* Tag based */ /* Tag based */
} else if (tag) { } else if (tag) {
channel_tag_mapping_t *ctm; channel_tag_mapping_t *ctm;
channel_t *ch2;
LIST_FOREACH(ctm, &tag->ct_ctms, ctm_tag_link) { LIST_FOREACH(ctm, &tag->ct_ctms, ctm_tag_link) {
if(channel == NULL || ctm->ctm_channel == channel) ch2 = ctm->ctm_channel;
_eq_add_channel(eq, ctm->ctm_channel); if(ch2 == channel || channel == NULL)
if (channel_access(channel, perm, 0))
_eq_add_channel(eq, ch2);
} }
/* All channels */ /* All channels */
} else { } else {
CHANNEL_FOREACH(channel) CHANNEL_FOREACH(channel)
_eq_add_channel(eq, channel); if (channel_access(channel, perm, 0))
_eq_add_channel(eq, channel);
} }
switch (eq->sort_dir) { switch (eq->sort_dir) {

View file

@ -22,6 +22,7 @@
#include <regex.h> #include <regex.h>
#include "settings.h" #include "settings.h"
#include "lang_str.h" #include "lang_str.h"
#include "access.h"
/* /*
* External forward decls * External forward decls
@ -609,7 +610,7 @@ typedef struct epg_query {
uint32_t allocated; uint32_t allocated;
} epg_query_t; } epg_query_t;
epg_broadcast_t **epg_query(epg_query_t *eq); epg_broadcast_t **epg_query(epg_query_t *eq, access_t *perm);
void epg_query_free(epg_query_t *eq); void epg_query_free(epg_query_t *eq);
/* ************************************************************************ /* ************************************************************************

View file

@ -435,7 +435,7 @@ htsp_generate_challenge(htsp_connection_t *htsp)
static inline int static inline int
htsp_user_access_channel(htsp_connection_t *htsp, channel_t *ch) htsp_user_access_channel(htsp_connection_t *htsp, channel_t *ch)
{ {
return channel_access(ch, htsp->htsp_granted_access, htsp->htsp_username); return channel_access(ch, htsp->htsp_granted_access, 0);
} }
#define HTSP_CHECK_CHANNEL_ACCESS(htsp, ch)\ #define HTSP_CHECK_CHANNEL_ACCESS(htsp, ch)\
@ -1189,7 +1189,7 @@ htsp_method_epgQuery(htsp_connection_t *htsp, htsmsg_t *in)
return htsp_error("User does not have access"); return htsp_error("User does not have access");
/* Query */ /* Query */
epg_query(&eq); epg_query(&eq, htsp->htsp_granted_access);
/* Create Reply */ /* Create Reply */
out = htsmsg_create_map(); out = htsmsg_create_map();

View file

@ -467,7 +467,7 @@ http_access_verify_channel(http_connection_t *hc, int mask,
if (access_verify2(hc->hc_access, mask)) if (access_verify2(hc->hc_access, mask))
return -1; return -1;
if (channel_access(ch, hc->hc_access, hc->hc_username)) if (channel_access(ch, hc->hc_access, 0))
res = 0; res = 0;
return res; return res;
} }

View file

@ -189,7 +189,7 @@ page_simple(http_connection_t *hc,
eq.lang = strdup(lang); eq.lang = strdup(lang);
//Note: force min/max durations for this interface to 0 and INT_MAX seconds respectively //Note: force min/max durations for this interface to 0 and INT_MAX seconds respectively
epg_query(&eq); epg_query(&eq, hc->hc_access);
c = eq.entries; c = eq.entries;

View file

@ -59,7 +59,8 @@ dumpchannels(htsbuf_queue_t *hq)
CHANNEL_FOREACH(ch) { CHANNEL_FOREACH(ch) {
htsbuf_qprintf(hq, "%s (%d)\n", channel_get_name(ch), channel_get_id(ch)); htsbuf_qprintf(hq, "%s%s (%d)\n", !ch->ch_enabled ? "[DISABLED] " : "",
channel_get_name(ch), channel_get_id(ch));
chnum = channel_get_number(ch); chnum = channel_get_number(ch);
if (channel_get_minor(chnum)) if (channel_get_minor(chnum))
snprintf(chbuf, sizeof(chbuf), "%u.%u", snprintf(chbuf, sizeof(chbuf), "%u.%u",

View file

@ -512,12 +512,14 @@ http_channel_list_playlist(http_connection_t *hc)
profile = profile_validate_name(http_arg_get(&hc->hc_req_args, "profile")); profile = profile_validate_name(http_arg_get(&hc->hc_req_args, "profile"));
CHANNEL_FOREACH(ch) CHANNEL_FOREACH(ch)
count++; if (ch->ch_enabled)
count++;
chlist = malloc(count * sizeof(channel_t *)); chlist = malloc(count * sizeof(channel_t *));
CHANNEL_FOREACH(ch) CHANNEL_FOREACH(ch)
chlist[idx++] = ch; if (ch->ch_enabled)
chlist[idx++] = ch;
assert(idx == count); assert(idx == count);