caclient: improve webui, rewrite status notifications
This commit is contained in:
parent
7f89149674
commit
ff104c4c18
10 changed files with 132 additions and 71 deletions
|
@ -36,8 +36,9 @@ api_caclient_list
|
|||
l = htsmsg_create_list();
|
||||
TAILQ_FOREACH(cac, &caclients, cac_link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "key", idnode_uuid_as_str(&cac->cac_id));
|
||||
htsmsg_add_str(e, "val", idnode_get_title(&cac->cac_id));
|
||||
htsmsg_add_str(e, "uuid", idnode_uuid_as_str(&cac->cac_id));
|
||||
htsmsg_add_str(e, "title", idnode_get_title(&cac->cac_id));
|
||||
htsmsg_add_str(e, "status", caclient_get_status(cac));
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
}
|
||||
*resp = htsmsg_create_map();
|
||||
|
|
|
@ -211,6 +211,15 @@ caclient_class_class_set(void *o, const void *v)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const void *
|
||||
caclient_class_status_get(void *o)
|
||||
{
|
||||
caclient_t *cac = o;
|
||||
static const char *ret;
|
||||
ret = caclient_get_status(cac);
|
||||
return &ret;
|
||||
}
|
||||
|
||||
const idclass_t caclient_class =
|
||||
{
|
||||
.ic_class = "caclient",
|
||||
|
@ -256,6 +265,13 @@ const idclass_t caclient_class =
|
|||
.name = "Comment",
|
||||
.off = offsetof(caclient_t, cac_comment),
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.id = "status",
|
||||
.name = "Status",
|
||||
.get = caclient_class_status_get,
|
||||
.opts = PO_RDONLY | PO_HIDDEN | PO_NOSAVE,
|
||||
},
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
@ -286,6 +302,27 @@ caclient_caid_update(struct mpegts_mux *mux, uint16_t caid, uint16_t pid, int va
|
|||
pthread_mutex_unlock(&caclients_mutex);
|
||||
}
|
||||
|
||||
void
|
||||
caclient_set_status(caclient_t *cac, caclient_status_t status)
|
||||
{
|
||||
if (cac->cac_status != status) {
|
||||
cac->cac_status = status;
|
||||
idnode_notify_simple(&cac->cac_id);
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
caclient_get_status(caclient_t *cac)
|
||||
{
|
||||
switch (cac->cac_status) {
|
||||
case CACLIENT_STATUS_NONE: return "caclientNone";
|
||||
case CACLIENT_STATUS_READY: return "caclientReady";
|
||||
case CACLIENT_STATUS_CONNECTED: return "caclientConnected";
|
||||
case CACLIENT_STATUS_DISCONNECTED: return "caclientDisconnected";
|
||||
default: return "caclientUnknown";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,13 @@ extern struct caclient_entry_queue caclients;
|
|||
|
||||
extern const idclass_t *caclient_classes[];
|
||||
|
||||
typedef enum caclient_status {
|
||||
CACLIENT_STATUS_NONE,
|
||||
CACLIENT_STATUS_READY,
|
||||
CACLIENT_STATUS_CONNECTED,
|
||||
CACLIENT_STATUS_DISCONNECTED
|
||||
} caclient_status_t;
|
||||
|
||||
typedef struct caclient {
|
||||
idnode_t cac_id;
|
||||
TAILQ_ENTRY(caclient) cac_link;
|
||||
|
@ -43,6 +50,7 @@ typedef struct caclient {
|
|||
int cac_enabled;
|
||||
char *cac_name;
|
||||
char *cac_comment;
|
||||
int cac_status;
|
||||
|
||||
void (*cac_free)(struct caclient *cac);
|
||||
void (*cac_start)(struct caclient *cac, struct service *t);
|
||||
|
@ -59,6 +67,9 @@ void caclient_start( struct service *t );
|
|||
void caclient_caid_update(struct mpegts_mux *mux,
|
||||
uint16_t caid, uint16_t pid, int valid);
|
||||
|
||||
void caclient_set_status(caclient_t *cac, caclient_status_t status);
|
||||
const char *caclient_get_status(caclient_t *cac);
|
||||
|
||||
void caclient_init(void);
|
||||
void caclient_done(void);
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "tcp.h"
|
||||
#include "tvhpoll.h"
|
||||
|
||||
#include "notify.h"
|
||||
#include "subscriptions.h"
|
||||
#include "tvhcsa.h"
|
||||
#if ENABLE_LINUXDVB
|
||||
|
@ -262,7 +261,6 @@ typedef struct capmt {
|
|||
|
||||
/* thread flags */
|
||||
int capmt_connected;
|
||||
int capmt_enabled;
|
||||
int capmt_running;
|
||||
int capmt_reconfigure;
|
||||
|
||||
|
@ -424,22 +422,6 @@ capmt_pid_flush(capmt_t *capmt)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
capmt_set_connected(capmt_t *capmt, int c)
|
||||
{
|
||||
htsmsg_t *m;
|
||||
if (c == capmt->capmt_connected)
|
||||
return;
|
||||
m = htsmsg_create_map();
|
||||
capmt->capmt_connected = c;
|
||||
htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&capmt->cac_id));
|
||||
htsmsg_add_u32(m, "connected", capmt->capmt_connected);
|
||||
notify_by_msg("caclient_status", m);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
@ -585,7 +567,9 @@ capmt_write_msg(capmt_t *capmt, int adapter, int sid, const uint8_t *buf, size_t
|
|||
// opening socket and sending
|
||||
if (capmt->capmt_sock[i] < 0) {
|
||||
fd = capmt_connect(capmt, i);
|
||||
capmt_set_connected(capmt, fd >= 0 ? 2 : 0);
|
||||
caclient_set_status((caclient_t *)capmt,
|
||||
fd >= 0 ? CACLIENT_STATUS_CONNECTED :
|
||||
CACLIENT_STATUS_READY);
|
||||
if (fd >= 0)
|
||||
capmt_notify_server(capmt, NULL, 1);
|
||||
}
|
||||
|
@ -1401,14 +1385,15 @@ capmt_thread(void *aux)
|
|||
memset(&capmt->capmt_demuxes, 0, sizeof(capmt->capmt_demuxes));
|
||||
|
||||
/* Accessible */
|
||||
if (capmt->capmt_sockfile && !access(capmt->capmt_sockfile, R_OK | W_OK))
|
||||
capmt_set_connected(capmt, 1);
|
||||
if (capmt->capmt_sockfile && capmt->capmt_oscam != CAPMT_OSCAM_TCP &&
|
||||
!access(capmt->capmt_sockfile, R_OK | W_OK))
|
||||
caclient_set_status((caclient_t *)capmt, CACLIENT_STATUS_NONE);
|
||||
else
|
||||
capmt_set_connected(capmt, 0);
|
||||
caclient_set_status((caclient_t *)capmt, CACLIENT_STATUS_READY);
|
||||
|
||||
pthread_mutex_lock(&capmt->capmt_mutex);
|
||||
|
||||
while(capmt->capmt_running && capmt->capmt_enabled == 0)
|
||||
while(capmt->capmt_running && capmt->cac_enabled == 0)
|
||||
pthread_cond_wait(&capmt->capmt_cond, &capmt->capmt_mutex);
|
||||
|
||||
pthread_mutex_unlock(&capmt->capmt_mutex);
|
||||
|
@ -1419,7 +1404,7 @@ capmt_thread(void *aux)
|
|||
capmt_connect(capmt, 0);
|
||||
|
||||
if (capmt->capmt_sock[0] >= 0) {
|
||||
capmt_set_connected(capmt, 2);
|
||||
caclient_set_status((caclient_t *)capmt, CACLIENT_STATUS_CONNECTED);
|
||||
#if CONFIG_LINUXDVB
|
||||
if (capmt_oscam_new(capmt)) {
|
||||
handle_single(capmt);
|
||||
|
@ -1465,7 +1450,7 @@ capmt_thread(void *aux)
|
|||
#endif
|
||||
}
|
||||
|
||||
capmt_set_connected(capmt, 0);
|
||||
caclient_set_status((caclient_t *)capmt, CACLIENT_STATUS_DISCONNECTED);
|
||||
|
||||
/* close opened sockets */
|
||||
for (i = 0; i < MAX_SOCKETS; i++)
|
||||
|
@ -1741,7 +1726,7 @@ capmt_enumerate_services(capmt_t *capmt, int force)
|
|||
// closing socket (oscam handle this as event and stop decrypting)
|
||||
tvhlog(LOG_DEBUG, "capmt", "%s: no subscribed services, closing socket, fd=%d", __FUNCTION__, capmt->capmt_sock[0]);
|
||||
if (capmt->capmt_sock[0] >= 0)
|
||||
capmt_set_connected(capmt, 1);
|
||||
caclient_set_status((caclient_t *)capmt, CACLIENT_STATUS_READY);
|
||||
capmt_socket_close(capmt, 0);
|
||||
}
|
||||
else if (force || (res_srv_count != all_srv_count)) {
|
||||
|
@ -1917,8 +1902,10 @@ capmt_conf_changed(caclient_t *cac)
|
|||
pthread_t tid;
|
||||
|
||||
if (capmt->cac_enabled) {
|
||||
if (capmt->capmt_sockfile == NULL || capmt->capmt_sockfile[0] == '\0')
|
||||
if (capmt->capmt_sockfile == NULL || capmt->capmt_sockfile[0] == '\0') {
|
||||
caclient_set_status(cac, CACLIENT_STATUS_NONE);
|
||||
return;
|
||||
}
|
||||
if (!capmt->capmt_running) {
|
||||
capmt->capmt_running = 1;
|
||||
tvhthread_create(&capmt->capmt_tid, NULL, capmt_thread, capmt);
|
||||
|
@ -1938,6 +1925,7 @@ capmt_conf_changed(caclient_t *cac)
|
|||
pthread_mutex_unlock(&capmt->capmt_mutex);
|
||||
tvh_write(capmt->capmt_pipe.wr, "", 1);
|
||||
pthread_join(tid, NULL);
|
||||
caclient_set_status(cac, CACLIENT_STATUS_NONE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "tvheadend.h"
|
||||
#include "tcp.h"
|
||||
#include "caclient.h"
|
||||
#include "notify.h"
|
||||
#include "atomic.h"
|
||||
#include "subscriptions.h"
|
||||
#include "service.h"
|
||||
|
@ -206,7 +205,6 @@ typedef struct cwc {
|
|||
caclient_t;
|
||||
|
||||
int cwc_fd;
|
||||
int cwc_connected;
|
||||
|
||||
int cwc_retry_delay;
|
||||
|
||||
|
@ -269,7 +267,6 @@ typedef struct cwc {
|
|||
|
||||
const char *cwc_errtxt;
|
||||
|
||||
int cwc_enabled;
|
||||
int cwc_running;
|
||||
int cwc_reconfigure;
|
||||
} cwc_t;
|
||||
|
@ -545,19 +542,6 @@ cwc_send_ka(cwc_t *cwc)
|
|||
cwc_send_msg(cwc, buf, 3, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
cwc_comet_status_update(cwc_t *cwc)
|
||||
{
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
|
||||
htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&cwc->cac_id));
|
||||
htsmsg_add_u32(m, "connected", !!cwc->cwc_connected);
|
||||
notify_by_msg("caclient_status", m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle reply to card data request
|
||||
*/
|
||||
|
@ -590,8 +574,7 @@ cwc_decode_card_data_reply(cwc_t *cwc, uint8_t *msg, int len)
|
|||
return -1;
|
||||
}
|
||||
|
||||
cwc->cwc_connected = 1;
|
||||
cwc_comet_status_update(cwc);
|
||||
caclient_set_status((caclient_t *)cwc, CACLIENT_STATUS_CONNECTED);
|
||||
struct cs_card_data *pcard;
|
||||
pcard = calloc(1, sizeof(struct cs_card_data));
|
||||
pcard->cwc_caid = (msg[4] << 8) | msg[5];
|
||||
|
@ -938,8 +921,7 @@ cwc_running_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len)
|
|||
tvhlog(LOG_INFO, "cwc", "Invalid card data reply (provider list)");
|
||||
return -1;
|
||||
}
|
||||
cwc->cwc_connected = 1;
|
||||
cwc_comet_status_update(cwc);
|
||||
caclient_set_status((caclient_t *)cwc, CACLIENT_STATUS_CONNECTED);
|
||||
struct cs_card_data *pcard;
|
||||
pcard = calloc(1, sizeof(struct cs_card_data));
|
||||
pcard->cwc_caid = caid;
|
||||
|
@ -974,7 +956,7 @@ cwc_running_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len)
|
|||
static int
|
||||
cwc_must_break(cwc_t *cwc)
|
||||
{
|
||||
return !cwc->cwc_running || !cwc->cwc_enabled || cwc->cwc_reconfigure;
|
||||
return !cwc->cwc_running || !cwc->cac_enabled || cwc->cwc_reconfigure;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1192,6 +1174,8 @@ cwc_thread(void *aux)
|
|||
pthread_mutex_lock(&cwc->cwc_mutex);
|
||||
|
||||
while(cwc->cwc_running) {
|
||||
|
||||
caclient_set_status((caclient_t *)cwc, CACLIENT_STATUS_READY);
|
||||
|
||||
snprintf(hostname, sizeof(hostname), "%s", cwc->cwc_hostname);
|
||||
port = cwc->cwc_port;
|
||||
|
@ -1226,16 +1210,16 @@ cwc_thread(void *aux)
|
|||
|
||||
cwc->cwc_fd = -1;
|
||||
close(fd);
|
||||
cwc->cwc_connected = 0;
|
||||
cwc_comet_status_update(cwc);
|
||||
tvhlog(LOG_INFO, "cwc", "Disconnected from %s:%i",
|
||||
cwc->cwc_hostname, cwc->cwc_port);
|
||||
}
|
||||
|
||||
if(cwc->cwc_running == 0) continue;
|
||||
if(attempts == 1) continue; // Retry immediately
|
||||
d = 3;
|
||||
|
||||
caclient_set_status((caclient_t *)cwc, CACLIENT_STATUS_DISCONNECTED);
|
||||
|
||||
d = 3;
|
||||
ts.tv_sec = time(NULL) + d;
|
||||
ts.tv_nsec = 0;
|
||||
|
||||
|
@ -2199,8 +2183,10 @@ cwc_conf_changed(caclient_t *cac)
|
|||
cwc->cwc_password ? crypt_md5(cwc->cwc_password, "$1$abcdefgh$") : NULL;
|
||||
|
||||
if (cac->cac_enabled) {
|
||||
if (cwc->cwc_hostname == NULL || cwc->cwc_hostname[0] == '\0')
|
||||
if (cwc->cwc_hostname == NULL || cwc->cwc_hostname[0] == '\0') {
|
||||
caclient_set_status(cac, CACLIENT_STATUS_NONE);
|
||||
return;
|
||||
}
|
||||
if (!cwc->cwc_running) {
|
||||
cwc->cwc_running = 1;
|
||||
tvhthread_create(&cwc->cwc_tid, NULL, cwc_thread, cwc);
|
||||
|
@ -2222,6 +2208,7 @@ cwc_conf_changed(caclient_t *cac)
|
|||
pthread_mutex_unlock(&cwc->cwc_mutex);
|
||||
pthread_kill(tid, SIGTERM);
|
||||
pthread_join(tid, NULL);
|
||||
caclient_set_status(cac, CACLIENT_STATUS_NONE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,14 @@ tvheadend.caclient_builders = new Ext.data.JsonStore({
|
|||
});
|
||||
|
||||
tvheadend.caclient = function(panel, index) {
|
||||
var actions = new Ext.ux.grid.RowActions({
|
||||
id: 'status',
|
||||
header: '',
|
||||
width: 45,
|
||||
actions: [ { iconIndex: 'status' } ],
|
||||
destroy: function() { }
|
||||
});
|
||||
|
||||
var list = 'enabled,name,username,password,hostname,mode,camdfilename,' +
|
||||
'port,deskey,emm,emmex,comment';
|
||||
|
||||
|
@ -22,6 +30,9 @@ tvheadend.caclient = function(panel, index) {
|
|||
titleP: 'CAs',
|
||||
titleC: 'Client Name',
|
||||
iconCls: 'key',
|
||||
key: 'uuid',
|
||||
val: 'title',
|
||||
fields: ['uuid', 'title', 'status'],
|
||||
tabIndex: index,
|
||||
list: { url: 'api/caclient/list', params: { } },
|
||||
edit: { params: { list: list } },
|
||||
|
@ -40,6 +51,8 @@ tvheadend.caclient = function(panel, index) {
|
|||
},
|
||||
del: true,
|
||||
move: true,
|
||||
lcol: [actions],
|
||||
plugins: [actions],
|
||||
help: function() {
|
||||
new tvheadend.help('Conditional Access Client', 'config_caclient.html');
|
||||
},
|
||||
|
|
|
@ -322,6 +322,22 @@
|
|||
background-image: url(../icons/film_edit.png) !important;
|
||||
}
|
||||
|
||||
.caclientNone {
|
||||
background-image: url(../icons/stop.png) !important;
|
||||
}
|
||||
|
||||
.caclientReady {
|
||||
background-image: url(../icons/accept.png) !important;
|
||||
}
|
||||
|
||||
.caclientConnected {
|
||||
background-image: url(../icons/tick.png) !important;
|
||||
}
|
||||
|
||||
.caclientDisconnected {
|
||||
background-image: url(../icons/exclamation.png) !important;
|
||||
}
|
||||
|
||||
.x-linked {
|
||||
display: inline-block;
|
||||
background-image: url(../icons/linked.gif) !important;
|
||||
|
|
|
@ -1447,6 +1447,7 @@ tvheadend.idnode_form_grid = function(panel, conf)
|
|||
if (conf.builder)
|
||||
conf.builder(conf);
|
||||
|
||||
var columns = [];
|
||||
var buttons = [];
|
||||
var abuttons = {};
|
||||
var plugins = conf.plugins || [];
|
||||
|
@ -1464,12 +1465,13 @@ tvheadend.idnode_form_grid = function(panel, conf)
|
|||
'class': conf.clazz
|
||||
},
|
||||
autoLoad: true,
|
||||
id: 'key',
|
||||
id: conf.key || 'key',
|
||||
totalProperty: 'total',
|
||||
fields: ['key','val'],
|
||||
fields: conf.fields || ['key','val'],
|
||||
remoteSort: false,
|
||||
pruneModifiedRecords: true,
|
||||
sortInfo: conf.move ? null : { field: 'val', direction: 'ASC' }
|
||||
sortInfo: conf.move ? conf.sort :
|
||||
(conf.sort || { field: conf.val || 'val', direction: 'ASC' })
|
||||
});
|
||||
|
||||
store.on('load', function(records) {
|
||||
|
@ -1486,16 +1488,23 @@ tvheadend.idnode_form_grid = function(panel, conf)
|
|||
select.selectFirstRow();
|
||||
});
|
||||
|
||||
/* Left-hand columns (do copy, no reference!) */
|
||||
if (conf.lcol)
|
||||
for (i = 0; i < conf.lcol.length; i++)
|
||||
columns.push(conf.lcol[i]);
|
||||
|
||||
columns.push({
|
||||
width: 300,
|
||||
id: conf.val || 'val',
|
||||
header: conf.titleC,
|
||||
sortable: conf.move ? false : true,
|
||||
dataIndex: conf.val || 'val'
|
||||
});
|
||||
|
||||
/* Model */
|
||||
var model = new Ext.grid.ColumnModel({
|
||||
defaultSortable: conf.move ? false : true,
|
||||
columns: [{
|
||||
width: 300,
|
||||
id: 'val',
|
||||
header: conf.titleC,
|
||||
sortable: conf.move ? false : true,
|
||||
dataIndex: 'val'
|
||||
}]
|
||||
columns: columns,
|
||||
});
|
||||
|
||||
/* Selection */
|
||||
|
@ -1587,13 +1596,11 @@ tvheadend.idnode_form_grid = function(panel, conf)
|
|||
text: 'Move Up',
|
||||
disabled: true,
|
||||
handler: function() {
|
||||
var r = select.getSelections();
|
||||
if (r && r.length > 0) {
|
||||
var uuid = r[0].id;
|
||||
if (current) {
|
||||
tvheadend.Ajax({
|
||||
url: 'api/idnode/moveup',
|
||||
params: {
|
||||
uuid: uuid
|
||||
uuid: current.uuid
|
||||
},
|
||||
success: function(d)
|
||||
{
|
||||
|
@ -1610,13 +1617,12 @@ tvheadend.idnode_form_grid = function(panel, conf)
|
|||
text: 'Move Down',
|
||||
disabled: true,
|
||||
handler: function() {
|
||||
var r = select.getSelections();
|
||||
if (r && r.length > 0) {
|
||||
if (current) {
|
||||
var uuid = r[0].id;
|
||||
tvheadend.Ajax({
|
||||
url: 'api/idnode/movedown',
|
||||
params: {
|
||||
uuid: uuid
|
||||
uuid: current.uuid
|
||||
},
|
||||
success: function(d)
|
||||
{
|
||||
|
|
1
src/webui/static/icons/accept.png
Symbolic link
1
src/webui/static/icons/accept.png
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../../../vendor/famfamsilk/accept.png
|
1
src/webui/static/icons/stop.png
Symbolic link
1
src/webui/static/icons/stop.png
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../../../vendor/famfamsilk/stop.png
|
Loading…
Add table
Reference in a new issue