From 60e5a1014c52e926fb7dbb12392f60a473e44d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jernej=20Fija=C4=8Dko?= Date: Fri, 30 Sep 2011 13:23:46 +0200 Subject: [PATCH 01/41] Fix memory leak in queue size protection --- src/htsp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/htsp.c b/src/htsp.c index 8bb803b1..f786a886 100644 --- a/src/htsp.c +++ b/src/htsp.c @@ -1508,6 +1508,9 @@ htsp_stream_deliver(htsp_subscription_t *hs, th_pkt_t *pkt) hs->hs_dropstats[pkt->pkt_frametype]++; + // destroy the already created htsmsg to avoid memory leaks + htsmsg_destroy(m); + /* Queue size protection */ pkt_ref_dec(pkt); return; From 4b28d78701899b955b96043934d87ff232399038 Mon Sep 17 00:00:00 2001 From: Jernej Date: Sun, 29 Jan 2012 17:24:42 +0100 Subject: [PATCH 02/41] Code optimization --- src/htsp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/htsp.c b/src/htsp.c index f786a886..a21e28ee 100644 --- a/src/htsp.c +++ b/src/htsp.c @@ -1496,7 +1496,7 @@ const static char frametypearray[PKT_NTYPES] = { static void htsp_stream_deliver(htsp_subscription_t *hs, th_pkt_t *pkt) { - htsmsg_t *m = htsmsg_create_map(), *n; + htsmsg_t *m, *n; htsp_msg_t *hm; htsp_connection_t *htsp = hs->hs_htsp; int64_t ts; @@ -1508,13 +1508,12 @@ htsp_stream_deliver(htsp_subscription_t *hs, th_pkt_t *pkt) hs->hs_dropstats[pkt->pkt_frametype]++; - // destroy the already created htsmsg to avoid memory leaks - htsmsg_destroy(m); - /* Queue size protection */ pkt_ref_dec(pkt); return; } + + m = htsmsg_create_map(); htsmsg_add_str(m, "method", "muxpkt"); htsmsg_add_u32(m, "subscriptionId", hs->hs_sid); From eecf66f3ca628474eec4151a7136593153a8acd2 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 28 Feb 2012 20:48:55 +0100 Subject: [PATCH 03/41] Improve copy operation for satellite muxes - allow specify the dst LNB config The previous code was creating wrong mux entries with references to a LNB configuration used by the source adapter. Signed-off-by: Jaroslav Kysela --- src/dvb/dvb.h | 6 ++-- src/dvb/dvb_adapter.c | 2 +- src/dvb/dvb_multiplex.c | 19 +++++++---- src/dvb/dvb_preconf.c | 2 +- src/dvb/dvb_tables.c | 4 +-- src/webui/extjs_dvb.c | 18 ++++++++-- src/webui/static/app/dvb.js | 66 ++++++++++++++++++++++++++++++++----- 7 files changed, 92 insertions(+), 25 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 9c14e23f..ad9c30fb 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -265,7 +265,8 @@ th_dvb_mux_instance_t *dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, uint16_t tsid, const char *network, const char *logprefix, int enabled, - int initialscan, const char *identifier); + int initialscan, const char *identifier, + dvb_satconf_t *satconf); void dvb_mux_set_networkname(th_dvb_mux_instance_t *tdmi, const char *name); @@ -295,7 +296,8 @@ const char *dvb_mux_add_by_params(th_dvb_adapter_t *tda, int polarisation, const char *satconf); -int dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src); +int dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src, + dvb_satconf_t *satconf); /** * DVB Transport (aka DVB service) diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index 9f6afd56..433107ae 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -458,7 +458,7 @@ dvb_adapter_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src) dvb_mux_destroy(tdmi_dst); LIST_FOREACH(tdmi_src, &src->tda_muxes, tdmi_adapter_link) - dvb_mux_copy(dst, tdmi_src); + dvb_mux_copy(dst, tdmi_src, NULL); tda_save(dst); } diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 9756fd6e..770e03a2 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -150,7 +150,8 @@ tdmi_compare_conf(int adapter_type, th_dvb_mux_instance_t * dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, uint16_t tsid, const char *network, const char *source, - int enabled, int initialscan, const char *identifier) + int enabled, int initialscan, const char *identifier, + dvb_satconf_t *satconf) { th_dvb_mux_instance_t *tdmi, *c; unsigned int hash; @@ -225,8 +226,9 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, snprintf(buf, sizeof(buf), "%s%d%s%s%s", tda->tda_identifier, dmc->dmc_fe_params.frequency, qpsktxt, - dmc->dmc_satconf ? "_satconf_" : "", - dmc->dmc_satconf ? dmc->dmc_satconf->sc_id : ""); + (satconf || dmc->dmc_satconf) ? "_satconf_" : "", + (satconf ? satconf->sc_id : + (dmc->dmc_satconf ? dmc->dmc_satconf->sc_id : ""))); tdmi->tdmi_identifier = strdup(buf); } else { @@ -259,6 +261,8 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, memcpy(&tdmi->tdmi_conf, dmc, sizeof(struct dvb_mux_conf)); + if(satconf) + tdmi->tdmi_conf.dmc_satconf = satconf; if(tdmi->tdmi_conf.dmc_satconf != NULL) { LIST_INSERT_HEAD(&tdmi->tdmi_conf.dmc_satconf->sc_tdmis, tdmi, tdmi_satconf_link); @@ -708,7 +712,7 @@ tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier) tdmi = dvb_mux_create(tda, &dmc, tsid, htsmsg_get_str(m, "network"), NULL, enabled, 1, - identifier); + identifier, NULL); if(tdmi != NULL) { if((s = htsmsg_get_str(m, "status")) != NULL) @@ -1058,7 +1062,7 @@ dvb_mux_add_by_params(th_dvb_adapter_t *tda, } dmc.dmc_polarisation = polarisation; - tdmi = dvb_mux_create(tda, &dmc, 0xffff, NULL, NULL, 1, 1, NULL); + tdmi = dvb_mux_create(tda, &dmc, 0xffff, NULL, NULL, 1, 1, NULL, NULL); if(tdmi == NULL) return "Mux already exist"; @@ -1071,7 +1075,8 @@ dvb_mux_add_by_params(th_dvb_adapter_t *tda, * */ int -dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src) +dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src, + dvb_satconf_t *satconf) { th_dvb_mux_instance_t *tdmi_dst; service_t *t_src, *t_dst; @@ -1083,7 +1088,7 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src) tdmi_src->tdmi_transport_stream_id, tdmi_src->tdmi_network, "copy operation", tdmi_src->tdmi_enabled, - 1, NULL); + 1, NULL, satconf); if(tdmi_dst == NULL) return -1; // Already exist diff --git a/src/dvb/dvb_preconf.c b/src/dvb/dvb_preconf.c index ee6098ff..07f8c6ab 100644 --- a/src/dvb/dvb_preconf.c +++ b/src/dvb/dvb_preconf.c @@ -102,7 +102,7 @@ dvb_mux_preconf_add(th_dvb_adapter_t *tda, const struct mux *m, int num, dmc.dmc_satconf = dvb_satconf_entry_find(tda, satconf, 0); - dvb_mux_create(tda, &dmc, 0xffff, NULL, source, 1, 1, NULL); + dvb_mux_create(tda, &dmc, 0xffff, NULL, source, 1, 1, NULL, NULL); m++; } } diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 74aa4676..53004aa3 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -938,7 +938,7 @@ dvb_table_cable_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x07]; dvb_mux_create(tdmi->tdmi_adapter, &dmc, tsid, NULL, - "automatic mux discovery", 1, 1, NULL); + "automatic mux discovery", 1, 1, NULL, NULL); return 0; } @@ -1023,7 +1023,7 @@ dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, #endif dvb_mux_create(tdmi->tdmi_adapter, &dmc, tsid, NULL, - "automatic mux discovery", 1, 1, NULL); + "automatic mux discovery", 1, 1, NULL, NULL); return 0; } diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index c0d9c7f0..4080868e 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -454,11 +454,14 @@ extjs_dvbsatconf(http_connection_t *hc, const char *remain, void *opaque) htsbuf_queue_t *hq = &hc->hc_reply; th_dvb_adapter_t *tda; htsmsg_t *out; + const char *adapter = http_arg_get(&hc->hc_req_args, "adapter"); pthread_mutex_lock(&global_lock); - if(remain == NULL || - (tda = dvb_adapter_find_by_identifier(remain)) == NULL) { + if((remain == NULL || + (tda = dvb_adapter_find_by_identifier(remain)) == NULL) && + (adapter == NULL || + (tda = dvb_adapter_find_by_identifier(adapter)) == NULL)) { pthread_mutex_unlock(&global_lock); return 404; } @@ -582,9 +585,11 @@ extjs_dvb_copymux(http_connection_t *hc, const char *remain, void *opaque) th_dvb_adapter_t *tda; htsmsg_t *in; const char *entries = http_arg_get(&hc->hc_req_args, "entries"); + const char *satconf = http_arg_get(&hc->hc_req_args, "satconf"); const char *id; htsmsg_field_t *f; th_dvb_mux_instance_t *tdmi; + dvb_satconf_t *sc = NULL; in = entries != NULL ? htsmsg_json_deserialize(entries) : NULL; @@ -599,13 +604,20 @@ extjs_dvb_copymux(http_connection_t *hc, const char *remain, void *opaque) return 404; } + if (satconf) { + sc = dvb_satconf_entry_find(tda, satconf, 0); + if (sc == NULL) { + pthread_mutex_unlock(&global_lock); + return 404; + } + } TAILQ_FOREACH(f, &in->hm_fields, hmf_link) { if((id = htsmsg_field_get_string(f)) != NULL && (tdmi = dvb_mux_find_by_identifier(id)) != NULL && tda != tdmi->tdmi_adapter) { - if(dvb_mux_copy(tda, tdmi)) { + if(dvb_mux_copy(tda, tdmi, sc)) { char buf[100]; dvb_mux_nicename(buf, sizeof(buf), tdmi); diff --git a/src/webui/static/app/dvb.js b/src/webui/static/app/dvb.js index 7fae890a..1fee1bcc 100644 --- a/src/webui/static/app/dvb.js +++ b/src/webui/static/app/dvb.js @@ -169,14 +169,24 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) { var selectedKeys = grid.selModel.selections.keys; var target = panel.getForm().getValues('targetID').targetID; + if(adapterData.satConf) { + var satconf = panel.getForm().getValues('targetSatConfID').targetSatConfID; + var mparams = { + entries:Ext.encode(selectedKeys), + satconf:satconf + }; + } else { + var mparams = { + entries:Ext.encode(selectedKeys) + }; + } + Ext.Ajax.request({ url: "dvb/copymux/" + target, - params: { - entries:Ext.encode(selectedKeys) - }, - failure:function(response,options) { + params: mparams, + failure:function(response,options) { Ext.MessageBox.alert('Server Error','Unable to copy'); - }, + }, success: function() { win.close(); } @@ -191,13 +201,38 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) { 'name'], baseParams: {sibling: adapterId} }); + if(adapterData.satConf) { + targetSatConfStore = new Ext.data.JsonStore({ + root:'entries', + id: 'identifier', + url:'dvb/satconf', + fields: ['identifier', + 'name'], + baseParams: {adapter: adapterId} + }); + satConf = new Ext.form.ComboBox({ + store: targetSatConfStore, + fieldLabel: 'Target Satellite config', + name: 'targetsatconf', + hiddenName: 'targetSatConfID', + editable: false, + allowBlank: false, + triggerAction: 'all', + mode: 'remote', + displayField:'name', + valueField:'identifier', + emptyText: 'Select target adapter first...' + }); + } else { + satConf = null; + } var panel = new Ext.FormPanel({ frame:true, border:true, bodyStyle:'padding:5px', labelAlign: 'right', - labelWidth: 110, + labelWidth: 150, defaultType: 'textfield', items: [ @@ -212,8 +247,21 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) { mode: 'remote', displayField:'name', valueField:'identifier', - emptyText: 'Select target adapter...' - }) + emptyText: 'Select target adapter...', + listeners: { + 'select': function(combo, value) { + if (satConf) { + satConf.emptyText = 'Select satellite configuration...'; + satConf.clearValue(); + targetSatConfStore.baseParams = {adapter: combo.value}; + targetSatConfStore.load(); + satConf.focus(); + satConf.expand(); + } + } + } + }), + satConf, ], buttons: [{ text: 'Copy', @@ -225,7 +273,7 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) { title: 'Copy multiplex configuration', layout: 'fit', width: 500, - height: 120, + height: 150, modal: true, plain: true, items: panel From d8788062abb92c495588c1005d7df80bc107ef77 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 1 Mar 2012 17:37:07 +0100 Subject: [PATCH 04/41] Allow restriction for one DVR configuration mapped to one user In some use cases, it may be usefull to not allow selection of the DVR configuration for the end-users. Map the DVR configuration by name matching the username for these restricted users (DVR configuration must be identical to the username, otherwise the default configuration is used). Signed-off-by: Jaroslav Kysela --- src/access.c | 4 ++++ src/access.h | 3 ++- src/webui/extjs.c | 28 ++++++++++++++++++++++++++++ src/webui/static/app/acleditor.js | 11 +++++++++-- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/access.c b/src/access.c index 080d6d84..f40c1ab3 100644 --- a/src/access.c +++ b/src/access.c @@ -391,6 +391,7 @@ access_record_build(access_entry_t *ae) htsmsg_add_u32(e, "streaming", ae->ae_rights & ACCESS_STREAMING ? 1 : 0); htsmsg_add_u32(e, "dvr" , ae->ae_rights & ACCESS_RECORDER ? 1 : 0); + htsmsg_add_u32(e, "dvrallcfg", ae->ae_rights & ACCESS_RECORDER_ALL ? 1 : 0); htsmsg_add_u32(e, "webui" , ae->ae_rights & ACCESS_WEB_INTERFACE ? 1 : 0); htsmsg_add_u32(e, "admin" , ae->ae_rights & ACCESS_ADMIN ? 1 : 0); @@ -480,6 +481,9 @@ access_record_update(void *opaque, const char *id, htsmsg_t *values, if(!htsmsg_get_u32(values, "dvr", &u32)) access_update_flag(ae, ACCESS_RECORDER, u32); + if(!htsmsg_get_u32(values, "dvrallcfg", &u32)) + access_update_flag(ae, ACCESS_RECORDER_ALL, u32); + if(!htsmsg_get_u32(values, "admin", &u32)) access_update_flag(ae, ACCESS_ADMIN, u32); diff --git a/src/access.h b/src/access.h index 7af118e2..37f42a08 100644 --- a/src/access.h +++ b/src/access.h @@ -58,7 +58,8 @@ typedef struct access_ticket { #define ACCESS_STREAMING 0x1 #define ACCESS_WEB_INTERFACE 0x2 #define ACCESS_RECORDER 0x4 -#define ACCESS_ADMIN 0x8 +#define ACCESS_RECORDER_ALL 0x8 +#define ACCESS_ADMIN 0x10 #define ACCESS_FULL 0x3f /** diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 3ed9f8b4..b4677e22 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -624,6 +624,9 @@ extjs_confignames(http_connection_t *hc, const char *remain, void *opaque) out = htsmsg_create_map(); array = htsmsg_create_list(); + if (http_access_verify(hc, ACCESS_RECORDER_ALL)) + goto skip; + LIST_FOREACH(cfg, &dvrconfigs, config_link) { e = htsmsg_create_map(); htsmsg_add_str(e, "identifier", cfg->dvr_config_name); @@ -634,6 +637,7 @@ extjs_confignames(http_connection_t *hc, const char *remain, void *opaque) htsmsg_add_msg(array, NULL, e); } +skip: htsmsg_add_msg(out, "entries", array); } else { @@ -787,6 +791,18 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque) return HTTP_STATUS_BAD_REQUEST; } + if (http_access_verify(hc, ACCESS_RECORDER_ALL)) { + config_name = NULL; + LIST_FOREACH(cfg, &dvrconfigs, config_link) { + if (strcmp(cfg->dvr_config_name, hc->hc_username) == 0) { + config_name = cfg->dvr_config_name; + break; + } + } + if (config_name == NULL) + tvhlog(LOG_INFO,"dvr","User '%s' has no dvr config with identical name, using default...", hc->hc_username); + } + dvr_entry_create_by_event(config_name, e, hc->hc_representative, NULL, DVR_PRIO_NORMAL); @@ -857,6 +873,18 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque) if(stop < start) stop += 86400; + if (http_access_verify(hc, ACCESS_RECORDER_ALL)) { + config_name = NULL; + LIST_FOREACH(cfg, &dvrconfigs, config_link) { + if (strcmp(cfg->dvr_config_name, hc->hc_username) == 0) { + config_name = cfg->dvr_config_name; + break; + } + } + if (config_name == NULL) + tvhlog(LOG_INFO,"dvr","User '%s' has no dvr config with identical name, using default...", hc->hc_username); + } + dvr_entry_create(config_name, ch, start, stop, title, NULL, hc->hc_representative, NULL, NULL, 0, dvr_pri2val(pri)); diff --git a/src/webui/static/app/acleditor.js b/src/webui/static/app/acleditor.js index d9864d83..eaeddbf4 100644 --- a/src/webui/static/app/acleditor.js +++ b/src/webui/static/app/acleditor.js @@ -20,6 +20,12 @@ tvheadend.acleditor = function() { width: 100 }); + var dvrallcfgColumn = new Ext.grid.CheckColumn({ + header: "All Configs (VR)", + dataIndex: 'dvrallcfg', + width: 100 + }); + var webuiColumn = new Ext.grid.CheckColumn({ header: "Web Interface", dataIndex: 'webui', @@ -52,6 +58,7 @@ tvheadend.acleditor = function() { }, streamingColumn, dvrColumn, + dvrallcfgColumn, webuiColumn, adminColumn, { @@ -63,14 +70,14 @@ tvheadend.acleditor = function() { ]); var UserRecord = Ext.data.Record.create([ - 'enabled','streaming','dvr','admin','webui','username', + 'enabled','streaming','dvr','dvrallcfg','admin','webui','username', 'prefix','password','comment' ]); return new tvheadend.tableEditor('Access control', 'accesscontrol', cm, UserRecord, [enabledColumn, streamingColumn, - dvrColumn, webuiColumn, + dvrColumn, dvrallcfgColumn, webuiColumn, adminColumn], null, 'config_access.html', 'group'); From 07df79f2ee62ce649d6e1b0c5e472c869ddb3a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Thu, 8 Mar 2012 10:53:07 +0100 Subject: [PATCH 05/41] sanity checks for mkv muxer --- src/dvr/mkmux.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/dvr/mkmux.c b/src/dvr/mkmux.c index 54a350ce..1303d69f 100644 --- a/src/dvr/mkmux.c +++ b/src/dvr/mkmux.c @@ -810,10 +810,13 @@ mk_write_frame_i(mk_mux_t *mkm, mk_track *t, th_pkt_t *pkt) int skippable = pkt->pkt_frametype == PKT_B_FRAME; int vkeyframe = SCT_ISVIDEO(t->type) && keyframe; - uint8_t *data; - size_t len; + uint8_t *data = pktbuf_ptr(pkt->pkt_payload); + size_t len = pktbuf_len(pkt->pkt_payload); const int clusersizemax = 2000000; + if(!data || len <= 0) + return; + if(pts == PTS_UNSET) // This is our best guess, it might be wrong but... oh well pts = t->nextpts; @@ -863,10 +866,6 @@ mk_write_frame_i(mk_mux_t *mkm, mk_track *t, th_pkt_t *pkt) addcue(mkm, pts, t->tracknum); } - - data = pktbuf_ptr(pkt->pkt_payload); - len = pktbuf_len(pkt->pkt_payload); - if(t->type == SCT_AAC || t->type == SCT_MP4A) { // Skip ADTS header if(len < 7) From 72be167545f838eba2411736bcab39ac9b17f0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Thu, 8 Mar 2012 10:54:48 +0100 Subject: [PATCH 06/41] Merge branch 'upstream', remote branch 'upstream/master' into upstream From 5f00b7309a5b3711d2590613a35110bb82d217a0 Mon Sep 17 00:00:00 2001 From: amet Date: Thu, 8 Mar 2012 14:13:48 +0400 Subject: [PATCH 07/41] change CWS_NETMSGSIZE to 362 --- src/cwc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cwc.c b/src/cwc.c index 9e6c24ef..6b38f212 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -47,7 +47,7 @@ #define TVHEADEND_PROTOCOL_ID 0x6502 #define CWC_KEEPALIVE_INTERVAL 30 -#define CWS_NETMSGSIZE 272 +#define CWS_NETMSGSIZE 362 #define CWS_FIRSTCMDNO 0xe0 /** From d204718cf9a9dcfe1d88d14cbc99ff9a734e6e7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Sun, 11 Mar 2012 18:08:45 +0100 Subject: [PATCH 08/41] Log timeouts as warnings --- src/webui/webui.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/webui/webui.c b/src/webui/webui.c index ed69ebdf..1b3d8ca9 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -157,8 +157,9 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t getsockopt(hc->hc_fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); //Abort upon socket error, or after 20 seconds of silence - if(err || timeouts >= 20){ - run = 0; + if(err || timeouts >= 20) { + tvhlog(LOG_WARNING, "webui", "Timeout waiting for packets"); + run = 0; } } pthread_mutex_unlock(&sq->sq_mutex); From 86cd61f21927ec1183ac2efed9fc24f592fc33cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Sun, 11 Mar 2012 18:10:45 +0100 Subject: [PATCH 09/41] unlock mutex earlier --- src/webui/webui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webui/webui.c b/src/webui/webui.c index 1b3d8ca9..bcb75b66 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -168,6 +168,7 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t timeouts = 0; //Reset timeout counter TAILQ_REMOVE(&sq->sq_queue, sm, sm_link); + pthread_mutex_unlock(&sq->sq_mutex); switch(sm->sm_type) { case SMT_PACKET: { @@ -220,7 +221,6 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t break; } streaming_msg_free(sm); - pthread_mutex_unlock(&sq->sq_mutex); } if(mkm) From 47bc9b2d8f02d88ca24e145b208b2b282e7f1abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Sun, 11 Mar 2012 18:13:05 +0100 Subject: [PATCH 10/41] Removed a call to pkt_ref_inc. I am not sure if this is OK or not. other parts of tvheadend don't seem to do it (like file recorder) so I guess it should work. --- src/webui/webui.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/webui/webui.c b/src/webui/webui.c index bcb75b66..2483c2be 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -175,7 +175,6 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t if(!mkm) break; - pkt_ref_inc(sm->sm_data); run = !mk_mux_write_pkt(mkm, sm->sm_data); sm->sm_data = NULL; From 96966d1e123b064aa008111b45884e937520622d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Sun, 11 Mar 2012 18:17:09 +0100 Subject: [PATCH 11/41] added missing free() to epg_event_destroy --- src/epg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/epg.c b/src/epg.c index c43248a6..168133c2 100644 --- a/src/epg.c +++ b/src/epg.c @@ -274,6 +274,9 @@ epg_event_destroy(event_t *e) { free(e->e_title); free(e->e_desc); + free(e->e_ext_desc); + free(e->e_ext_item); + free(e->e_ext_text); free(e->e_episode.ee_onscreen); LIST_REMOVE(e, e_global_link); free(e); From 36af656f2e4fc1d61dd4ab03857ac7ddea6ec7a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Sat, 10 Mar 2012 12:14:26 +0100 Subject: [PATCH 12/41] Fixed crash when subscribing to a channel or service would fail --- src/webui/webui.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/webui/webui.c b/src/webui/webui.c index 2483c2be..71122d00 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -376,11 +376,12 @@ http_stream_service(http_connection_t *hc, service_t *service) pthread_mutex_unlock(&global_lock); - http_stream_run(hc, &sq, s); - - pthread_mutex_lock(&global_lock); - subscription_unsubscribe(s); - pthread_mutex_unlock(&global_lock); + if(s) { + http_stream_run(hc, &sq, s); + pthread_mutex_lock(&global_lock); + subscription_unsubscribe(s); + pthread_mutex_unlock(&global_lock); + } globalheaders_destroy(gh); tsfix_destroy(tsfix); @@ -411,11 +412,12 @@ http_stream_channel(http_connection_t *hc, channel_t *ch) 0); pthread_mutex_unlock(&global_lock); - http_stream_run(hc, &sq, s); - - pthread_mutex_lock(&global_lock); - subscription_unsubscribe(s); - pthread_mutex_unlock(&global_lock); + if(s) { + http_stream_run(hc, &sq, s); + pthread_mutex_lock(&global_lock); + subscription_unsubscribe(s); + pthread_mutex_unlock(&global_lock); + } globalheaders_destroy(gh); tsfix_destroy(tsfix); From cac15666af2f60133c8fd376b9d28b98af0abb6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Sun, 11 Mar 2012 18:29:49 +0100 Subject: [PATCH 13/41] Cosmetics --- src/webui/webui.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/webui/webui.c b/src/webui/webui.c index 71122d00..9aefb0a5 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -155,9 +155,10 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t //Check socket status getsockopt(hc->hc_fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); - - //Abort upon socket error, or after 20 seconds of silence - if(err || timeouts >= 20) { + if(err) { + tvhlog(LOG_DEBUG, "webui", "Client hung up, exit streaming"); + run = 0; + }else if(timeouts >= 20) { tvhlog(LOG_WARNING, "webui", "Timeout waiting for packets"); run = 0; } From be49ddd007337a3a2109c42a0a3f00434b44664c Mon Sep 17 00:00:00 2001 From: Bart Lauret Date: Tue, 13 Mar 2012 08:42:33 +0100 Subject: [PATCH 14/41] Null pointer passed as an argument in line 181 in strcmp(ae->ae_password, password) --- src/access.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/access.c b/src/access.c index 080d6d84..2710ec0f 100644 --- a/src/access.c +++ b/src/access.c @@ -174,7 +174,7 @@ access_verify(const char *username, const char *password, if(ae->ae_username[0] != '*') { /* acl entry requires username to match */ - if(username == NULL) + if(username == NULL || password == NULL) continue; /* Didn't get one */ if(strcmp(ae->ae_username, username) || From afc6029beb92e8b9b392d887242e7eaf24547c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Sun, 18 Mar 2012 23:02:32 +0100 Subject: [PATCH 15/41] fix subtitle issues on comhem. Sometimes the subtitles would get stuck on the screen, sometimes only half of them delivered to the client. --- src/teletext.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/src/teletext.c b/src/teletext.c index ff7a72db..c559cac1 100644 --- a/src/teletext.c +++ b/src/teletext.c @@ -40,7 +40,6 @@ */ typedef struct tt_mag { int ttm_curpage; - int ttm_inactive; int64_t ttm_current_pts; uint8_t ttm_lang; uint8_t ttm_page[23*40 + 1]; @@ -397,8 +396,7 @@ tt_decode_line(service_t *t, elementary_stream_t *st, uint8_t *buf) case 0: if(ttm->ttm_curpage != 0) { - if(ttm->ttm_inactive == 0) - tt_subtitle_deliver(t, st, ttm); + tt_subtitle_deliver(t, st, ttm); if(ttm->ttm_curpage == 192) teletext_rundown_copy(ttp, ttm); @@ -429,11 +427,9 @@ tt_decode_line(service_t *t, elementary_stream_t *st, uint8_t *buf) teletext_rundown_scan(t, ttp); ttm->ttm_current_pts = t->s_current_pts; - ttm->ttm_inactive = 0; break; case 1 ... 23: - ttm->ttm_inactive = 0; for(i = 0; i < 40; i++) { c = buf[i + 2] & 0x7f; ttm->ttm_page[i + 40 * (line - 1)] = c; @@ -446,30 +442,6 @@ tt_decode_line(service_t *t, elementary_stream_t *st, uint8_t *buf) } - - -/** - * - */ -static void -teletext_scan_stream(service_t *t, elementary_stream_t *st) -{ - tt_private_t *ttp = st->es_priv; - tt_mag_t *ttm; - int i; - - if(ttp == NULL) - return; - for(i = 0; i < 8; i++) { - ttm = &ttp->ttp_mags[i]; - ttm->ttm_inactive++; - if(ttm->ttm_inactive == 2) { - tt_subtitle_deliver(t, st, ttm); - } - } -} - - /** * */ @@ -489,7 +461,6 @@ teletext_input(service_t *t, elementary_stream_t *st, const uint8_t *tsb) } x += 46; } - teletext_scan_stream(t, st); } From f5ceace980411cf361f2a2cdcd39a4f749d18237 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 20 Mar 2012 16:09:20 +0100 Subject: [PATCH 16/41] dvb_tables: fix extended event parsing The ext_desc / ext_item strings are just copied without language handling. This patch uses standard dvb_get_string_with_len() function. It's safer and the language conversions are handled correctly. Signed-off-by: Jaroslav Kysela --- src/dvb/dvb_tables.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 74aa4676..00042008 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -411,9 +411,13 @@ dvb_desc_extended_event(uint8_t *ptr, int len, if ((desclen - strlen(desc)) > 2) { /* get description -> append to desc if space left */ - strncat(desc, "\n", 1); - strncat(desc, (char*)(items+1), - items[0] > (desclen - strlen(desc)) ? (desclen - strlen(desc)) : items[0]); + if (desc[0] != '\0') + strncat(desc, "\n", 1); + if((r = dvb_get_string_with_len(desc + strlen(desc), + desclen - strlen(desc), + items, (localptr + count) - items, + dvb_default_charset)) < 0) + return -1; } items += 1 + items[0]; @@ -422,9 +426,13 @@ dvb_desc_extended_event(uint8_t *ptr, int len, if ((itemlen - strlen(item)) > 2) { /* get item -> append to item if space left */ - strncat(item, "\n", 1); - strncat(item, (char*)(items+1), - items[0] > (itemlen - strlen(item)) ? (itemlen - strlen(item)) : items[0]); + if (item[0] != '\0') + strncat(item, "\n", 1); + if((r = dvb_get_string_with_len(item + strlen(item), + itemlen - strlen(item), + items, (localptr + count) - items, + dvb_default_charset)) < 0) + return -1; } /* go to next item */ From e4b88cfc39354043ce7bcaf09a28f0ea44a0983b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 21 Mar 2012 09:29:49 +0100 Subject: [PATCH 17/41] Fix crash when cfg->dvr_config_name is NULL (default config) As suggested by opdenkamp - the cfg->dvr_config_name may be NULL in some cases. Add more restrictive checks in extjs_dvr() . --- src/webui/extjs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/webui/extjs.c b/src/webui/extjs.c index b4677e22..647f28ff 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -794,12 +794,13 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque) if (http_access_verify(hc, ACCESS_RECORDER_ALL)) { config_name = NULL; LIST_FOREACH(cfg, &dvrconfigs, config_link) { - if (strcmp(cfg->dvr_config_name, hc->hc_username) == 0) { + if (cfg->dvr_config_name && hc->hc_username && + strcmp(cfg->dvr_config_name, hc->hc_username) == 0) { config_name = cfg->dvr_config_name; break; } } - if (config_name == NULL) + if (config_name == NULL && hc->hc_username) tvhlog(LOG_INFO,"dvr","User '%s' has no dvr config with identical name, using default...", hc->hc_username); } From 6097dcd6d12e1b37fadc12d7dc14e47125c3b351 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 21 Mar 2012 09:34:23 +0100 Subject: [PATCH 18/41] Fix crash when cfg->dvr_config_name is NULL (default config) As suggested by opdenkamp - the cfg->dvr_config_name may be NULL in some cases. Add more restrictive checks in extjs_dvr() . This patch fixes the second location for the user check. --- src/webui/extjs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 647f28ff..2505232f 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -877,12 +877,13 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque) if (http_access_verify(hc, ACCESS_RECORDER_ALL)) { config_name = NULL; LIST_FOREACH(cfg, &dvrconfigs, config_link) { - if (strcmp(cfg->dvr_config_name, hc->hc_username) == 0) { + if (cfg->dvr_config_name && hc->hc_username && + strcmp(cfg->dvr_config_name, hc->hc_username) == 0) { config_name = cfg->dvr_config_name; break; } } - if (config_name == NULL) + if (config_name == NULL && hc->hc_username) tvhlog(LOG_INFO,"dvr","User '%s' has no dvr config with identical name, using default...", hc->hc_username); } From dc74a18b2874dffa351e2cd8d8c379bc54ba5b14 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 26 Mar 2012 10:50:41 +0200 Subject: [PATCH 19/41] Javascript fix the improved mux-copy operation. The previous version did not work with the DVB-T tuners (without satconf). Signed-off-by: Jaroslav Kysela --- src/webui/static/app/dvb.js | 61 +++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/webui/static/app/dvb.js b/src/webui/static/app/dvb.js index 1fee1bcc..5b7d0576 100644 --- a/src/webui/static/app/dvb.js +++ b/src/webui/static/app/dvb.js @@ -227,6 +227,37 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) { satConf = null; } + var mitems = [ + new Ext.form.ComboBox({ + store: targetStore, + fieldLabel: 'Target adapter', + name: 'targetadapter', + hiddenName: 'targetID', + editable: false, + allowBlank: false, + triggerAction: 'all', + mode: 'remote', + displayField:'name', + valueField:'identifier', + emptyText: 'Select target adapter...', + listeners: { + 'select': function(combo, value) { + if (satConf) { + satConf.emptyText = 'Select satellite configuration...'; + satConf.clearValue(); + targetSatConfStore.baseParams = {adapter: combo.value}; + targetSatConfStore.load(); + satConf.focus(); + satConf.expand(); + } + } + } + }), + ]; + + if (satConf) + mitems.push(satConf); + var panel = new Ext.FormPanel({ frame:true, border:true, @@ -234,35 +265,7 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) { labelAlign: 'right', labelWidth: 150, defaultType: 'textfield', - items: [ - - new Ext.form.ComboBox({ - store: targetStore, - fieldLabel: 'Target adapter', - name: 'targetadapter', - hiddenName: 'targetID', - editable: false, - allowBlank: false, - triggerAction: 'all', - mode: 'remote', - displayField:'name', - valueField:'identifier', - emptyText: 'Select target adapter...', - listeners: { - 'select': function(combo, value) { - if (satConf) { - satConf.emptyText = 'Select satellite configuration...'; - satConf.clearValue(); - targetSatConfStore.baseParams = {adapter: combo.value}; - targetSatConfStore.load(); - satConf.focus(); - satConf.expand(); - } - } - } - }), - satConf, - ], + items: mitems, buttons: [{ text: 'Copy', handler: doCopy From ce1477cfc4dc89a42f536beac69d3b2e052fd928 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 29 Mar 2012 21:20:55 +0300 Subject: [PATCH 20/41] fix ca descr parsing for caid 4aee --- src/psi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/psi.c b/src/psi.c index 130678d5..116e0014 100644 --- a/src/psi.c +++ b/src/psi.c @@ -307,8 +307,10 @@ psi_desc_ca(service_t *t, const uint8_t *buffer, int size) } break; case 0x4a00://DRECrypt - provid = size < 4 ? 0 : buffer[4]; - break; + if (caid != 0x4aee) { // Bulcrypt + provid = size < 4 ? 0 : buffer[4]; + break; + } default: provid = 0; break; From 05fa4d341a6e05dbf3d0c4384795d0ee31f93958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Meerk=C3=B6tter?= Date: Sat, 31 Mar 2012 23:44:40 +0200 Subject: [PATCH 21/41] fix pointless self-assign --- src/tsdemux.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tsdemux.c b/src/tsdemux.c index 897fe1d6..57d6836e 100644 --- a/src/tsdemux.c +++ b/src/tsdemux.c @@ -142,8 +142,6 @@ ts_extract_pcr(service_t *t, elementary_stream_t *st, const uint8_t *tsb, pcr |= (uint64_t)tsb[9] << 1; pcr |= ((uint64_t)tsb[10] >> 7) & 0x01; - pcr = pcr; - if(pcrp != NULL) *pcrp = pcr; From 8d65d26893b9dccc30b6f11c381459d811a5be4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Meerk=C3=B6tter?= Date: Sat, 31 Mar 2012 23:45:40 +0200 Subject: [PATCH 22/41] fix "comparison of unsigned expression < 0 is always false" --- src/cwc.c | 2 +- src/rawtsinput.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cwc.c b/src/cwc.c index 6b38f212..431596a4 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -469,7 +469,7 @@ cwc_send_msg(cwc_t *cwc, const uint8_t *msg, size_t len, int sid, int enq) buf[4] = sid >> 8; buf[5] = sid; - if((len = des_encrypt(buf, len, cwc)) < 0) { + if((len = des_encrypt(buf, len, cwc)) <= 0) { free(buf); free(cm); return -1; diff --git a/src/rawtsinput.c b/src/rawtsinput.c index b1db456f..24a71d34 100644 --- a/src/rawtsinput.c +++ b/src/rawtsinput.c @@ -184,7 +184,7 @@ got_pat(const uint8_t *ptr, size_t len, void *opaque) len -= 8; ptr += 8; - if(len < 0) + if(len <= 0) return; pthread_mutex_lock(&global_lock); From dc3bbe1c23308b0ef543a7f3c433522c16c87110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Meerk=C3=B6tter?= Date: Sun, 1 Apr 2012 00:02:36 +0200 Subject: [PATCH 23/41] fix warning about unused variable --- src/tvheadend.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tvheadend.h b/src/tvheadend.h index c4c1d777..85f8395f 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -400,7 +400,7 @@ extern void scopedunlock(pthread_mutex_t **mtxp); #define scopedlock(mtx) \ pthread_mutex_t *scopedlock ## __LINE__ \ __attribute__((cleanup(scopedunlock))) = mtx; \ - pthread_mutex_lock(mtx); + pthread_mutex_lock(scopedlock ## __LINE__); #define scopedgloballock() scopedlock(&global_lock) From da4c28b9813f3b87a4a93c9c2306f50b3bd65a10 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 10 Apr 2012 10:26:22 +0200 Subject: [PATCH 24/41] cwc: Add EMM support for the Cryptoworks system Add initial EMM support for Cryptoworks. Also add Irdeto CAID numbers for Czech providers to the src/psi.c table. Signed-off-by: Jaroslav Kysela --- src/cwc.c | 35 +++++++++++++++++++++++++++++++++++ src/psi.c | 12 +++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/cwc.c b/src/cwc.c index 431596a4..426c0ddf 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -61,6 +61,7 @@ typedef enum { CARD_VIACCESS, CARD_NAGRA, CARD_NDS, + CARD_CRYPTOWORKS, CARD_UNKNOWN } card_type_t; @@ -280,6 +281,7 @@ void cwc_emm_seca(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_nagra(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_nds(cwc_t *cwc, uint8_t *data, int len); +void cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len); /** @@ -696,6 +698,11 @@ cwc_detect_card_type(cwc_t *cwc) tvhlog(LOG_INFO, "cwc", "%s: nds card", cwc->cwc_hostname); break; + case 0x0d: + cwc->cwc_card_type = CARD_CRYPTOWORKS; + tvhlog(LOG_INFO, "cwc", "%s: cryptoworks card", + cwc->cwc_hostname); + break; default: cwc->cwc_card_type = CARD_UNKNOWN; break; @@ -1210,6 +1217,9 @@ cwc_emm(uint8_t *data, int len) case CARD_NDS: cwc_emm_nds(cwc, data, len); break; + case CARD_CRYPTOWORKS: + cwc_emm_cryptoworks(cwc, data, len); + break; case CARD_UNKNOWN: break; } @@ -1654,6 +1664,31 @@ cwc_emm_nds(cwc_t *cwc, uint8_t *data, int len) cwc_send_msg(cwc, data, len, 0, 1); } +void +cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len) +{ + int match = 0; + + switch (data[0]) { + case 0x82: /* unique */ + match = len >= 10 && memcmp(data + 5, cwc->cwc_ua + 3, 5) == 0; + break; + case 0x84: /* shared */ + match = len >= 9 && memcmp(data + 5, cwc->cwc_ua + 3, 4) == 0; + break; + case 0x86: /* shared header */ + case 0x88: /* global */ + case 0x89: /* global */ + match = 1; + break; + default: + break; + } + + if (match) + cwc_send_msg(cwc, data, len, 0, 1); +} + /** * */ diff --git a/src/psi.c b/src/psi.c index 116e0014..9dee140e 100644 --- a/src/psi.c +++ b/src/psi.c @@ -836,13 +836,23 @@ static struct strtab caidnametab[] = { { "Irdeto", 0x0600 }, { "Irdeto", 0x0602 }, { "Irdeto", 0x0604 }, + { "Irdeto", 0x0624 }, + { "Irdeto", 0x0666 }, { "Jerroldgi", 0x0700 }, { "Matra", 0x0800 }, { "NDS", 0x0900 }, { "Nokia", 0x0A00 }, { "Conax", 0x0B00 }, { "NTL", 0x0C00 }, - { "CryptoWorks", 0x0D00 }, + { "CryptoWorks", 0x0D00 }, + { "CryptoWorks", 0x0D01 }, + { "CryptoWorks", 0x0D02 }, + { "CryptoWorks", 0x0D03 }, + { "CryptoWorks", 0x0D05 }, + { "CryptoWorks", 0x0D0F }, + { "CryptoWorks", 0x0D70 }, + { "CryptoWorks ICE", 0x0D96 }, + { "CryptoWorks ICE", 0x0D97 }, { "PowerVu", 0x0E00 }, { "Sony", 0x0F00 }, { "Tandberg", 0x1000 }, From a9bb7c31066fa800b722c9089020799ce3009c68 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 10 Apr 2012 11:22:47 +0200 Subject: [PATCH 25/41] cwc: improve EMM handling for multiple readers with same CAS system Add CAID filter to identify the correct reader for EMM messages. Previous code sent all EMMs to all readers with different CAIDs but same CAS system. Signed-off-by: Jaroslav Kysela --- src/cwc.c | 5 +++-- src/cwc.h | 2 +- src/dvb/dvb_tables.c | 7 ++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/cwc.c b/src/cwc.c index 431596a4..c18cb445 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -1180,14 +1180,15 @@ cwc_emm_cache_lookup(cwc_t *cwc, uint32_t crc) * */ void -cwc_emm(uint8_t *data, int len) +cwc_emm(uint8_t *data, int len, uint16_t caid) { cwc_t *cwc; pthread_mutex_lock(&cwc_mutex); TAILQ_FOREACH(cwc, &cwcs, cwc_link) { - if(cwc->cwc_forward_emm && cwc->cwc_writer_running) { + if(cwc->cwc_caid == caid && + cwc->cwc_forward_emm && cwc->cwc_writer_running) { switch (cwc->cwc_card_type) { case CARD_CONAX: cwc_emm_conax(cwc, data, len); diff --git a/src/cwc.h b/src/cwc.h index fa3cede9..da2381bf 100644 --- a/src/cwc.h +++ b/src/cwc.h @@ -23,6 +23,6 @@ void cwc_init(void); void cwc_service_start(struct service *t); -void cwc_emm(uint8_t *data, int len); +void cwc_emm(uint8_t *data, int len, uint16_t caid); #endif /* CWC_H_ */ diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 00042008..2225b6cc 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -828,7 +828,7 @@ static int dvb_ca_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, uint8_t tableid, void *opaque) { - cwc_emm(ptr, len); + cwc_emm(ptr, len, (uintptr_t)opaque); return 0; } @@ -841,6 +841,7 @@ dvb_cat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, { int tag, tlen; uint16_t pid; + uintptr_t caid; if((ptr[2] & 1) == 0) { /* current_next_indicator == next, skip this */ @@ -856,13 +857,13 @@ dvb_cat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, len -= 2; switch(tag) { case DVB_DESC_CA: - // caid = ( ptr[0] << 8) | ptr[1]; + caid = ( ptr[0] << 8) | ptr[1]; pid = ((ptr[2] & 0x1f) << 8) | ptr[3]; if(pid == 0) break; - tdt_add(tdmi, NULL, dvb_ca_callback, NULL, "CA", + tdt_add(tdmi, NULL, dvb_ca_callback, (void *)caid, "CA", TDT_INC_TABLE_HDR, pid, NULL); break; From a06ee6d17588625c05ed12f99c938ac7c6f8688d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 10 Apr 2012 14:32:11 +0200 Subject: [PATCH 26/41] cwc: Cryptoworks - re-compose the EMM-S (shared) messages The newcamd server expects composed EMM-S messages from 0x84 (EMM-SH) and 0x84 (EMM-SB). Signed-off-by: Jaroslav Kysela --- src/cwc.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/cwc.c b/src/cwc.c index 426c0ddf..86b3f900 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -244,6 +244,7 @@ typedef struct cwc { int shared_len; uint8_t * shared_emm; } cwc_viaccess_emm; +#define cwc_cryptoworks_emm cwc_viaccess_emm /* Card type */ card_type_t cwc_card_type; @@ -1673,10 +1674,44 @@ cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len) case 0x82: /* unique */ match = len >= 10 && memcmp(data + 5, cwc->cwc_ua + 3, 5) == 0; break; - case 0x84: /* shared */ - match = len >= 9 && memcmp(data + 5, cwc->cwc_ua + 3, 4) == 0; + case 0x84: /* emm-sh */ + if (len >= 9 && memcmp(data + 5, cwc->cwc_ua + 3, 4) == 0) { + if (cwc->cwc_cryptoworks_emm.shared_emm) { + free(cwc->cwc_cryptoworks_emm.shared_emm); + cwc->cwc_cryptoworks_emm.shared_len = 0; + cwc->cwc_cryptoworks_emm.shared_emm = (uint8_t *)malloc(len); + } + cwc->cwc_cryptoworks_emm.shared_emm = malloc(len); + if (cwc->cwc_cryptoworks_emm.shared_emm) { + cwc->cwc_cryptoworks_emm.shared_len = len; + memcpy(cwc->cwc_cryptoworks_emm.shared_emm, data, len); + printf("emm-sh[%04x]: loaded\n", cwc->cwc_caid); + } + } + break; + case 0x86: /* emm-sb */ + if (cwc->cwc_cryptoworks_emm.shared_emm) { + /* python: EMM_SH[0:12] + EMM_SB[5:-1] + EMM_SH[12:-1] */ + uint32_t elen = len - 5 + cwc->cwc_cryptoworks_emm.shared_len - 12; + uint8_t *tmp = malloc(elen); + uint8_t *composed = tmp ? malloc(elen + 12) : NULL; + if (composed) { + printf("emm-sb[%04x]: composed\n", cwc->cwc_caid); + memcpy(tmp, data + 5, len - 5); + memcpy(tmp + len - 5, cwc->cwc_cryptoworks_emm.shared_emm + 12, + cwc->cwc_cryptoworks_emm.shared_len - 12); + memcpy(composed, cwc->cwc_cryptoworks_emm.shared_emm, 12); + sort_nanos(composed + 12, tmp, elen); + composed[1] = ((elen + 9) >> 8) | 0x70; + composed[2] = (elen + 9) & 0xff; + cwc_send_msg(cwc, composed, elen + 12, 0, 1); + free(composed); + free(tmp); + } + cwc->cwc_cryptoworks_emm.shared_emm = NULL; + cwc->cwc_cryptoworks_emm.shared_len = 0; + } break; - case 0x86: /* shared header */ case 0x88: /* global */ case 0x89: /* global */ match = 1; From 30eb130fc1feee3dd4bfa2f3919ad90193eaabd3 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 10 Apr 2012 14:37:52 +0200 Subject: [PATCH 27/41] cwc: Cryptoworks - removed debug lines introduced in last commit --- src/cwc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cwc.c b/src/cwc.c index 86b3f900..44f0c3b0 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -1685,7 +1685,6 @@ cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len) if (cwc->cwc_cryptoworks_emm.shared_emm) { cwc->cwc_cryptoworks_emm.shared_len = len; memcpy(cwc->cwc_cryptoworks_emm.shared_emm, data, len); - printf("emm-sh[%04x]: loaded\n", cwc->cwc_caid); } } break; @@ -1696,7 +1695,6 @@ cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len) uint8_t *tmp = malloc(elen); uint8_t *composed = tmp ? malloc(elen + 12) : NULL; if (composed) { - printf("emm-sb[%04x]: composed\n", cwc->cwc_caid); memcpy(tmp, data + 5, len - 5); memcpy(tmp + len - 5, cwc->cwc_cryptoworks_emm.shared_emm + 12, cwc->cwc_cryptoworks_emm.shared_len - 12); From 0f7689099a4bfc5b60c5045b25fa1f9f6620cf87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 10 Apr 2012 20:14:48 +0200 Subject: [PATCH 28/41] Fix the way we generate version tags inside the binary --- Makefile | 16 ++++++---------- src/dvr/mkmux.c | 5 ++--- src/htsp.c | 3 +-- src/main.c | 6 ++---- src/trap.c | 5 +---- src/tvheadend.h | 3 ++- src/version.c | 9 ++------- src/webui/extjs.c | 11 ++++------- src/webui/statedump.c | 3 +-- support/version.sh | 26 +++++++------------------- 10 files changed, 28 insertions(+), 59 deletions(-) diff --git a/Makefile b/Makefile index 100c71f0..a5136ac0 100644 --- a/Makefile +++ b/Makefile @@ -151,14 +151,11 @@ BUNDLE_OBJS=$(BUNDLE_SRCS:%.c=%.o) OBJDIRS+= $(sort $(dir $(BUNDLE_OBJS))) .PRECIOUS: ${BUNDLE_SRCS} -VERSION=$(shell support/version.sh) -CURVERSION=$(shell cat ${BUILDDIR}/ver || echo "0") # Common CFLAGS for all files CFLAGS_com = -g -funsigned-char -O2 CFLAGS_com += -D_FILE_OFFSET_BITS=64 CFLAGS_com += -I${BUILDDIR} -I${CURDIR}/src -I${CURDIR} -CFLAGS_com += -DHTS_VERSION=\"$(VERSION)\" MKBUNDLE = $(CURDIR)/support/mkbundle @@ -188,18 +185,17 @@ ${BUILDDIR}/%.so: ${SRCS_EXTRA} ${CC} -O -fbuiltin -fomit-frame-pointer -fPIC -shared -o $@ $< -ldl clean: - rm -rf ${BUILDDIR}/src ${BUILDDIR}/bundles ${BUILDDIR}/ver + rm -rf ${BUILDDIR}/src ${BUILDDIR}/bundles find . -name "*~" | xargs rm -f distclean: clean rm -rf build.* -ifneq ($(VERSION), $(CURVERSION)) -.PHONY: src/version.c -$(info Version changed) -src/version.c: - @echo $(VERSION) >${BUILDDIR}/ver -endif +# Create buildversion.h +src/version.c: $(BUILDDIR)/buildversion.h +$(BUILDDIR)/buildversion.h: FORCE + @$(CURDIR)/support/version.sh $(CURDIR) $@ +FORCE: # Include dependency files if they exist. diff --git a/src/dvr/mkmux.c b/src/dvr/mkmux.c index 1303d69f..8a73b517 100644 --- a/src/dvr/mkmux.c +++ b/src/dvr/mkmux.c @@ -143,14 +143,13 @@ static htsbuf_queue_t * mk_build_segment_info(mk_mux_t *mkm) { htsbuf_queue_t *q = htsbuf_queue_alloc(0); - extern char *htsversion_full; char app[128]; - snprintf(app, sizeof(app), "HTS Tvheadend %s", htsversion_full); + snprintf(app, sizeof(app), "Tvheadend %s", tvheadend_version); ebml_append_bin(q, 0x73a4, mkm->uuid, sizeof(mkm->uuid)); ebml_append_string(q, 0x7ba9, mkm->title); - ebml_append_string(q, 0x4d80, "HTS Tvheadend Matroska muxer"); + ebml_append_string(q, 0x4d80, "Tvheadend Matroska muxer"); ebml_append_string(q, 0x5741, app); ebml_append_uint(q, 0x2ad7b1, MATROSKA_TIMESCALE); diff --git a/src/htsp.c b/src/htsp.c index 6c6fcbcb..1a630fa7 100644 --- a/src/htsp.c +++ b/src/htsp.c @@ -50,7 +50,6 @@ static void *htsp_server; #define HTSP_PRIV_MASK (ACCESS_STREAMING) -extern const char *htsversion; extern char *dvr_storage; LIST_HEAD(htsp_connection_list, htsp_connection); @@ -1032,7 +1031,7 @@ htsp_method_hello(htsp_connection_t *htsp, htsmsg_t *in) htsmsg_add_u32(r, "htspversion", HTSP_PROTO_VERSION); htsmsg_add_str(r, "servername", "HTS Tvheadend"); - htsmsg_add_str(r, "serverversion", htsversion); + htsmsg_add_str(r, "serverversion", tvheadend_version); htsmsg_add_bin(r, "challenge", htsp->htsp_challenge, 32); htsp_update_logname(htsp); diff --git a/src/main.c b/src/main.c index 370bb2ae..9474ea8b 100644 --- a/src/main.c +++ b/src/main.c @@ -60,8 +60,6 @@ #include "ffdecsa/FFdecsa.h" int running; -extern const char *htsversion; -extern const char *htsversion_full; time_t dispatch_clock; static LIST_HEAD(, gtimer) gtimers; pthread_mutex_t global_lock; @@ -150,7 +148,7 @@ gtimer_disarm(gtimer_t *gti) static void usage(const char *argv0) { - printf("HTS Tvheadend %s\n", htsversion_full); + printf("HTS Tvheadend %s\n", tvheadend_version); printf("usage: %s [options]\n", argv0); printf("\n"); printf(" -a Use only DVB adapters specified (csv)\n"); @@ -432,7 +430,7 @@ main(int argc, char **argv) tvhlog(LOG_NOTICE, "START", "HTS Tvheadend version %s started, " "running as PID:%d UID:%d GID:%d, settings located in '%s'", - htsversion_full, + tvheadend_version, getpid(), getuid(), getgid(), hts_settings_get_root()); if(crash) diff --git a/src/trap.c b/src/trap.c index 1e92497d..bd761186 100644 --- a/src/trap.c +++ b/src/trap.c @@ -220,9 +220,6 @@ callback(struct dl_phdr_info *info, size_t size, void *data) } -extern const char *htsversion_full; - - void trap_init(const char *ver) { @@ -259,7 +256,7 @@ trap_init(const char *ver) "PRG: %s (%s) " "[%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x] " - "CWD: %s ", ver, htsversion_full, + "CWD: %s ", ver, tvheadend_version, digest[0], digest[1], digest[2], diff --git a/src/tvheadend.h b/src/tvheadend.h index 85f8395f..74b77834 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -15,7 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - #ifndef TVHEADEND_H #define TVHEADEND_H @@ -34,6 +33,8 @@ #include "redblack.h" +extern const char *tvheadend_version; + #define PTS_UNSET INT64_C(0x8000000000000000) extern pthread_mutex_t global_lock; diff --git a/src/version.c b/src/version.c index 118eb0c4..9aebe049 100644 --- a/src/version.c +++ b/src/version.c @@ -1,9 +1,4 @@ +#include "buildversion.h" #include "config.h" -#ifdef HTS_RELEASE_TAG -const char *htsversion=HTS_RELEASE_TAG; -const char *htsversion_full=HTS_RELEASE_TAG " (" HTS_VERSION ")"; -#else -const char *htsversion=HTS_VERSION; -const char *htsversion_full=HTS_VERSION; -#endif +const char *tvheadend_version = BUILD_VERSION; diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 2505232f..c1884d02 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -43,9 +43,6 @@ #include "epg.h" #include "iptv_input.h" -extern const char *htsversion; -extern const char *htsversion_full; - static void extjs_load(htsbuf_queue_t *hq, const char *script) { @@ -166,7 +163,7 @@ extjs_root(http_connection_t *hc, const char *remain, void *opaque) "\n" "
\n" "\n", - htsversion); + tvheadend_version); http_output_html(hc); return 0; } @@ -185,7 +182,7 @@ page_about(http_connection_t *hc, const char *remain, void *opaque) "
" "HTS Tvheadend %s" "

" - "© 2006 - 2010 Andreas \303\226man, et al.

" + "© 2006 - 2012 Andreas \303\226man, et al.

" "
" "" "http://www.lonelycoder.com/hts

" @@ -197,8 +194,8 @@ page_about(http_connection_t *hc, const char *remain, void *opaque) "

" "Build: %s" "", - htsversion, - htsversion_full); + tvheadend_version, + tvheadend_version); http_output_html(hc); return 0; diff --git a/src/webui/statedump.c b/src/webui/statedump.c index 911a31ec..4816c65b 100644 --- a/src/webui/statedump.c +++ b/src/webui/statedump.c @@ -37,7 +37,6 @@ #endif extern char tvh_binshasum[20]; -extern char *htsversion_full; int page_statedump(http_connection_t *hc, const char *remain, void *opaque); @@ -162,7 +161,7 @@ page_statedump(http_connection_t *hc, const char *remain, void *opaque) htsbuf_qprintf(hq, "Tvheadend %s Binary SHA1: " "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", - htsversion_full, + tvheadend_version, tvh_binshasum[0], tvh_binshasum[1], tvh_binshasum[2], diff --git a/support/version.sh b/support/version.sh index 98035c68..cee64950 100755 --- a/support/version.sh +++ b/support/version.sh @@ -1,23 +1,11 @@ #!/bin/sh -# check for SVN revision number -revision=`cd "$1" && LC_ALL=C svn info 2> /dev/null | grep Revision | cut -d' ' -f2` -test $revision || revision=`cd "$1" && grep revision .svn/entries 2>/dev/null | cut -d '"' -f2` -test $revision || revision=`cd "$1" && sed -n -e '/^dir$/{n;p;q}' .svn/entries 2>/dev/null` -test $revision && revision=SVN-r$revision +revision=`$1/support/getver.sh` -# check for git short hash -if ! test $revision; then - revision=`cd "$1" && git log -1 --pretty=format:%h` - test $revision && revision=git-$revision +NEW_REVISION="#define BUILD_VERSION \"$revision\"" +OLD_REVISION=`cat $2 2> /dev/null` + +# Update version.h only on revision changes to avoid spurious rebuilds +if test "$NEW_REVISION" != "$OLD_REVISION"; then + echo "$NEW_REVISION" > "$2" fi - -# check for debian changelog -if ! test $revision; then - revision=`cd "$1" && cat debian/changelog |head -1|cut -f2 -d' '|sed s/\(//|sed s/\)//` -fi - -# no version number found -test $revision || revision=UNKNOWN - -echo $revision From e226ec3ed789bba8f492844b602a6340512d0cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 10 Apr 2012 20:15:48 +0200 Subject: [PATCH 29/41] build: Don't use OBJDIR, instead mkdir in each recipe --- Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index a5136ac0..a0dacf29 100644 --- a/Makefile +++ b/Makefile @@ -142,13 +142,11 @@ SLIBS += $(SLIBS-yes) OBJS= $(SRCS:%.c=$(BUILDDIR)/%.o) OBJS_EXTRA = $(SRCS_EXTRA:%.c=$(BUILDDIR)/%.so) DEPS= ${OBJS:%.o=%.d} -OBJDIRS= $(sort $(dir $(OBJS))) $(sort $(dir $(OBJS_EXTRA))) # File bundles BUNDLE_SRCS=$(BUNDLES:%=$(BUILDDIR)/bundles/%.c) BUNDLE_DEPS=$(BUNDLE_SRCS:%.c=%.d) BUNDLE_OBJS=$(BUNDLE_SRCS:%.c=%.o) -OBJDIRS+= $(sort $(dir $(BUNDLE_OBJS))) .PRECIOUS: ${BUNDLE_SRCS} @@ -172,16 +170,16 @@ all: ${PROG} .PHONY: clean distclean -${PROG}: $(OBJDIRS) $(OBJS) $(BUNDLE_OBJS) ${OBJS_EXTRA} Makefile +${PROG}: $(OBJS) $(BUNDLE_OBJS) ${OBJS_EXTRA} Makefile + @mkdir -p $(dir $@) $(CC) -o $@ $(OBJS) $(BUNDLE_OBJS) $(LDFLAGS) ${LDFLAGS_cfg} -$(OBJDIRS): - @mkdir -p $@ - ${BUILDDIR}/%.o: %.c + @mkdir -p $(dir $@) $(CC) -MD -MP $(CFLAGS_com) $(CFLAGS) $(CFLAGS_cfg) -c -o $@ $(CURDIR)/$< ${BUILDDIR}/%.so: ${SRCS_EXTRA} + @mkdir -p $(dir $@) ${CC} -O -fbuiltin -fomit-frame-pointer -fPIC -shared -o $@ $< -ldl clean: @@ -206,7 +204,9 @@ include support/${OSENV}.mk # Bundle files $(BUILDDIR)/bundles/%.o: $(BUILDDIR)/bundles/%.c + @mkdir -p $(dir $@) $(CC) -I${CURDIR}/src -c -o $@ $< $(BUILDDIR)/bundles/%.c: % + @mkdir -p $(dir $@) $(MKBUNDLE) -o $@ -s $< -d ${BUILDDIR}/bundles/$<.d -p $< -z From 00378579ed350ab1d18be53ccec179acb594da90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 10 Apr 2012 20:43:43 +0200 Subject: [PATCH 30/41] Rework file bundling and make configure take most standard args Now ./configure should be able to be correctly invoked from standard debian helper rules file --- ChangeLog | 1 - Makefile | 19 +++++++-- configure | 87 ++++++++++++++++++++++++-------------- src/main.c | 8 ++-- src/tvheadend.h | 1 + src/webui/webui.c | 5 +-- support/dataroot/bundle.c | 4 ++ support/dataroot/datadir.c | 7 +++ support/dataroot/wd.c | 4 ++ support/getver.sh | 8 ++++ support/posix.mk | 31 ++++++-------- 11 files changed, 117 insertions(+), 58 deletions(-) delete mode 120000 ChangeLog create mode 100644 support/dataroot/bundle.c create mode 100644 support/dataroot/datadir.c create mode 100644 support/dataroot/wd.c create mode 100755 support/getver.sh diff --git a/ChangeLog b/ChangeLog deleted file mode 120000 index d526672c..00000000 --- a/ChangeLog +++ /dev/null @@ -1 +0,0 @@ -debian/changelog \ No newline at end of file diff --git a/Makefile b/Makefile index a0dacf29..52694582 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,8 @@ CFLAGS += -Wall -Werror -Wwrite-strings -Wno-deprecated-declarations CFLAGS += -Wmissing-prototypes LDFLAGS += -lrt -ldl +BUNDLES += docs/html docs/docresources src/webui/static + # # Core # @@ -170,10 +172,21 @@ all: ${PROG} .PHONY: clean distclean -${PROG}: $(OBJS) $(BUNDLE_OBJS) ${OBJS_EXTRA} Makefile - @mkdir -p $(dir $@) - $(CC) -o $@ $(OBJS) $(BUNDLE_OBJS) $(LDFLAGS) ${LDFLAGS_cfg} +# +# +# +${PROG}: $(OBJS) $(ALLDEPS) support/dataroot/wd.c + $(CC) -o $@ $(OBJS) support/dataroot/wd.c $(LDFLAGS) ${LDFLAGS_cfg} +${PROG}.bundle: $(OBJS) $(BUNDLE_OBJS) $(ALLDEPS) support/dataroot/bundle.c + $(CC) -o $@ $(OBJS) support/dataroot/bundle.c $(BUNDLE_OBJS) $(LDFLAGS) ${LDFLAGS_cfg} + +${PROG}.datadir: $(OBJS) $(ALLDEPS) support/dataroot/datadir.c + $(CC) -o $@ $(OBJS) -iquote${BUILDDIR} support/dataroot/datadir.c $(LDFLAGS) ${LDFLAGS_cfg} + +# +# +# ${BUILDDIR}/%.o: %.c @mkdir -p $(dir $@) $(CC) -MD -MP $(CFLAGS_com) $(CFLAGS) $(CFLAGS_cfg) -c -o $@ $(CURDIR)/$< diff --git a/configure b/configure index 7c01c60c..651b9c37 100755 --- a/configure +++ b/configure @@ -11,14 +11,16 @@ # Copyright (c) 2005-2008 Mans Rullgard # -PLATFORM=`uname` - +PLATFORM=linux source support/configure.inc CPU=generic ARCH=`uname -m` OSENV="posix" -PREFIX=/usr/local +prefix=/usr/local +bindir="\${prefix}/bin" +mandir="\${prefix}/share/man" +datadir="\${prefix}/share/tvheadend" show_help(){ echo "Usage: configure [options]" @@ -26,7 +28,11 @@ show_help(){ echo echo "Standard options:" echo " --help print this message" - echo " --prefix=PREFIX install in PREFIX [$PREFIX]" + echo " --prefix=PREFIX Install in PREFIX [$prefix]" + echo " --bindir=DIR Install binaries in DIR [$bindir]" + echo " --mandir=DIR Install man pages in DIR [$mandir]" + echo " --datadir=DIR Install data files in DIR [$datadir]" + echo echo " --arch=arch Build for this architecture [$ARCH]" echo " --cpu=cpu Build and optimize for specific CPU" echo " --cc=CC Build using the given compiler" @@ -42,8 +48,6 @@ enable v4l for opt do optval="${opt#*=}" case "$opt" in - --prefix=*) PREFIX="$optval" - ;; --cpu=*) CPU="$optval" ;; --help) show_help @@ -53,6 +57,33 @@ for opt do ;; --cc=*) CC="$optval" ;; + --prefix=*) + prefix="$optval" + ;; + --bindir=*) + bindir="$optval" + ;; + --mandir=*) + mandir="$optval" + ;; + --datadir=*) + datadir="$optval" + ;; + --includedir=*) + ;; + --infodir=*) + ;; + --sysconfdir=*) + ;; + --localstatedir=*) + ;; + --libexecdir=*) + ;; + --disable-maintainer-mode) + ;; + --disable-dependency-tracking) + ;; + --enable-?*|--disable-?*) eval $(echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g') $action $option @@ -154,38 +185,32 @@ else die fi -# -# Configure paths, etc -# -if [ ${RELEASE} != yes ]; then - echo NOTE: - echo NOTE: Development build. - echo NOTE: The generated binary will contained compild-in paths to - echo NOTE: the current build tree. If you plan to install or move - echo NOTE: the binary, please reconfigure with '--release'. - echo NOTE: - - cat >> ${CONFIG_H} << EOF -#define TVHEADEND_CONTENT_PATH "${TOPDIR}" -EOF - -else - - echo >>${CONFIG_MAK} "BUNDLES += docs/html docs/docresources src/webui/static" - - cat >> ${CONFIG_H} << EOF -#define TVHEADEND_CONTENT_PATH NULL -EOF -fi - # # Finalize # cat >> ${CONFIG_MAK} << EOF ARCH=$ARCH -INSTALLPREFIX=$PREFIX LDFLAGS_cfg += -lpthread EOF +# +# Finalize +# +echo +echo "Installation paths:" +echo " Prefix: ${prefix}" +echo " Binaries: ${bindir}" +echo " Man pages: ${mandir}" +echo " Data files: ${datadir}" +echo +echo >>${CONFIG_MAK} "prefix=$prefix" +echo >>${CONFIG_MAK} "bindir=\${DESTDIR}$bindir" +echo >>${CONFIG_MAK} "mandir=\${DESTDIR}$mandir" +echo >>${CONFIG_MAK} "datadir=\${DESTDIR}$datadir" +echo >>${CONFIG_MAK} LDFLAGS_cfg += -lpthread -lrt -ldl +eval datadirpath=${datadir} +echo >>${CONFIG_H} "#define TVHEADEND_DATADIR \"${datadirpath}\"" + + finalize diff --git a/src/main.c b/src/main.c index 9474ea8b..9569ea0d 100644 --- a/src/main.c +++ b/src/main.c @@ -385,7 +385,7 @@ main(int argc, char **argv) #endif http_server_init(); - webui_init(TVHEADEND_CONTENT_PATH); + webui_init(tvheadend_dataroot()); serviceprobe_init(); @@ -429,9 +429,11 @@ main(int argc, char **argv) pthread_sigmask(SIG_UNBLOCK, &set, NULL); tvhlog(LOG_NOTICE, "START", "HTS Tvheadend version %s started, " - "running as PID:%d UID:%d GID:%d, settings located in '%s'", + "running as PID:%d UID:%d GID:%d, settings located in '%s', " + "dataroot: %s", tvheadend_version, - getpid(), getuid(), getgid(), hts_settings_get_root()); + getpid(), getuid(), getgid(), hts_settings_get_root(), + tvheadend_dataroot() ?: ""); if(crash) abort(); diff --git a/src/tvheadend.h b/src/tvheadend.h index 74b77834..a82feaee 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -34,6 +34,7 @@ #include "redblack.h" extern const char *tvheadend_version; +extern const char *tvheadend_dataroot(); #define PTS_UNSET INT64_C(0x8000000000000000) diff --git a/src/webui/webui.c b/src/webui/webui.c index 9aefb0a5..929341eb 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -657,10 +657,9 @@ webui_static_content(const char *content_path, const char *http_path, } tvhlog(LOG_ERR, "webui", - "No source path providing HTTP content: \"%s\"." + "No source path providing HTTP content: \"%s\". " "Checked in \"%s\" and in the binary's embedded file system. " - "If you need to move or install the binary, " - "reconfigure with --release", http_path, content_path); + , http_path, content_path); } diff --git a/support/dataroot/bundle.c b/support/dataroot/bundle.c new file mode 100644 index 00000000..72abeff0 --- /dev/null +++ b/support/dataroot/bundle.c @@ -0,0 +1,4 @@ +const char *tvheadend_dataroot(void) +{ + return (void *)0; +} diff --git a/support/dataroot/datadir.c b/support/dataroot/datadir.c new file mode 100644 index 00000000..af380ac3 --- /dev/null +++ b/support/dataroot/datadir.c @@ -0,0 +1,7 @@ +#include "config.h" + +const char *tvheadend_dataroot(void) +{ + return TVHEADEND_DATADIR; +} + diff --git a/support/dataroot/wd.c b/support/dataroot/wd.c new file mode 100644 index 00000000..9b653eb2 --- /dev/null +++ b/support/dataroot/wd.c @@ -0,0 +1,4 @@ +const char *tvheadend_dataroot(void) +{ + return "./"; +} diff --git a/support/getver.sh b/support/getver.sh new file mode 100755 index 00000000..938b5a5f --- /dev/null +++ b/support/getver.sh @@ -0,0 +1,8 @@ +#!/bin/sh +revision=`cd "$1" && git describe --dirty --abbrev=5 2>/dev/null | sed -e 's/-/./g'` + +if ! test $revision; then + test $revision || revision=`cd "$1" && git describe --abbrev=5 2>/dev/null | sed -e 's/-/./g'` +fi + +echo $revision diff --git a/support/posix.mk b/support/posix.mk index baad6936..7f7bfc35 100644 --- a/support/posix.mk +++ b/support/posix.mk @@ -1,22 +1,19 @@ +MAN = man/tvheadend.1 +ICON = support/gnome/tvheadend.svg -INSTBIN= ${DESTDIR}${INSTALLPREFIX}/bin -INSTMAN= ${DESTDIR}${INSTALLPREFIX}/share/man/man1 -INSTDBG= ${DESTDIR}${INSTALLPREFIX}/lib/debug/bin -MAN=man/tvheadend.1 +INSTICON= ${DESTDIR}$(prefix)/share/icons/hicolor/scalable/apps -install: ${PROG} ${MAN} - mkdir -p ${INSTBIN} - install -T ${PROG} ${INSTBIN}/tvheadend - mkdir -p ${INSTMAN} - install ${MAN} ${INSTMAN} -install-debug: ${PROG} - mkdir -p ${INSTDBG} - objcopy --only-keep-debug ${INSTBIN}/tvheadend ${INSTDBG}/tvheadend.debug - strip -g ${INSTBIN}/tvheadend - objcopy --add-gnu-debuglink=${INSTDBG}/tvheadend.debug ${INSTBIN}/tvheadend +install: ${PROG}.datadir ${MAN} + install -D ${PROG}.datadir ${bindir}/tvheadend + install -D ${MAN} ${mandir}/tvheadend.1 + + for bundle in ${BUNDLES}; do \ + mkdir -p ${datadir}/$$bundle ;\ + cp -r $$bundle/* ${datadir}/$$bundle ;\ + done + uninstall: - rm -f ${INSTBIN}/tvheadend - rm -f ${INSTDBG}/tvheadend.debug - rm -f ${INSTMAN}/tvheadend.1 + rm -f ${bindir)/tvheadend + rm -f ${mandir)/tvheadend.1 From 98dd35342fb1315ae260bc2c4043825d7d1feb48 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 10 Apr 2012 15:48:07 +0200 Subject: [PATCH 31/41] cwc: Use "per stream" update id for Cryptoworks and Viaccess CA composed emms This fixes possible shared EMM messages composing issues when multiple streams are sending EMMs to the card reader. Just make sure, that both parts of compose messages are from one "stream". Signed-off-by: Jaroslav Kysela --- src/cwc.c | 23 ++++++++++++++--------- src/cwc.h | 2 +- src/dvb/dvb_tables.c | 11 ++++++----- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/cwc.c b/src/cwc.c index a90c1f3a..e2442ea8 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -243,6 +243,7 @@ typedef struct cwc { int shared_toggle; int shared_len; uint8_t * shared_emm; + void *ca_update_id; } cwc_viaccess_emm; #define cwc_cryptoworks_emm cwc_viaccess_emm @@ -279,10 +280,10 @@ void cwc_emm_conax(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_irdeto(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_dre(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_seca(cwc_t *cwc, uint8_t *data, int len); -void cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int len); +void cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int len, void *ca_update_id); void cwc_emm_nagra(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_nds(cwc_t *cwc, uint8_t *data, int len); -void cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len); +void cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len, void *ca_update_id); /** @@ -1188,7 +1189,7 @@ cwc_emm_cache_lookup(cwc_t *cwc, uint32_t crc) * */ void -cwc_emm(uint8_t *data, int len, uint16_t caid) +cwc_emm(uint8_t *data, int len, uint16_t caid, void *ca_update_id) { cwc_t *cwc; @@ -1208,7 +1209,7 @@ cwc_emm(uint8_t *data, int len, uint16_t caid) cwc_emm_seca(cwc, data, len); break; case CARD_VIACCESS: - cwc_emm_viaccess(cwc, data, len); + cwc_emm_viaccess(cwc, data, len, ca_update_id); break; case CARD_DRE: cwc_emm_dre(cwc, data, len); @@ -1220,7 +1221,7 @@ cwc_emm(uint8_t *data, int len, uint16_t caid) cwc_emm_nds(cwc, data, len); break; case CARD_CRYPTOWORKS: - cwc_emm_cryptoworks(cwc, data, len); + cwc_emm_cryptoworks(cwc, data, len, ca_update_id); break; case CARD_UNKNOWN: break; @@ -1382,7 +1383,7 @@ static int via_provider_id(uint8_t * data) void -cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int mlen) +cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int mlen, void *ca_update_id) { /* Get SCT len */ int len = 3 + ((data[1] & 0x0f) << 8) + data[2]; @@ -1414,13 +1415,15 @@ cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int mlen) if (cwc->cwc_viaccess_emm.shared_emm) { cwc->cwc_viaccess_emm.shared_len = len; memcpy(cwc->cwc_viaccess_emm.shared_emm, data, len); + cwc->cwc_viaccess_emm.ca_update_id = ca_update_id; } cwc->cwc_viaccess_emm.shared_toggle = data[0]; } } break; case 0x8e: - if (cwc->cwc_viaccess_emm.shared_emm) { + if (cwc->cwc_viaccess_emm.shared_emm && + cwc->cwc_viaccess_emm.ca_update_id == ca_update_id) { int match = 0; int i; /* Match SA and provider in shared */ @@ -1667,7 +1670,7 @@ cwc_emm_nds(cwc_t *cwc, uint8_t *data, int len) } void -cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len) +cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len, void *ca_update_id) { int match = 0; @@ -1686,11 +1689,13 @@ cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len) if (cwc->cwc_cryptoworks_emm.shared_emm) { cwc->cwc_cryptoworks_emm.shared_len = len; memcpy(cwc->cwc_cryptoworks_emm.shared_emm, data, len); + cwc->cwc_cryptoworks_emm.ca_update_id = ca_update_id; } } break; case 0x86: /* emm-sb */ - if (cwc->cwc_cryptoworks_emm.shared_emm) { + if (cwc->cwc_cryptoworks_emm.shared_emm && + cwc->cwc_cryptoworks_emm.ca_update_id == ca_update_id) { /* python: EMM_SH[0:12] + EMM_SB[5:-1] + EMM_SH[12:-1] */ uint32_t elen = len - 5 + cwc->cwc_cryptoworks_emm.shared_len - 12; uint8_t *tmp = malloc(elen); diff --git a/src/cwc.h b/src/cwc.h index da2381bf..3c28710a 100644 --- a/src/cwc.h +++ b/src/cwc.h @@ -23,6 +23,6 @@ void cwc_init(void); void cwc_service_start(struct service *t); -void cwc_emm(uint8_t *data, int len, uint16_t caid); +void cwc_emm(uint8_t *data, int len, uint16_t caid, void *ca_update_id); #endif /* CWC_H_ */ diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index efcd5024..f2e83653 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -44,7 +44,7 @@ #define TDT_CRC 0x1 #define TDT_QUICKREQ 0x2 -#define TDT_INC_TABLE_HDR 0x4 +#define TDT_CA 0x4 static void dvb_table_add_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid); @@ -214,8 +214,9 @@ dvb_proc_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt, uint8_t *sec, ptr = &sec[3]; if(chkcrc) len -= 4; /* Strip trailing CRC */ - if(tdt->tdt_flags & TDT_INC_TABLE_HDR) - ret = tdt->tdt_callback(tdmi, sec, len + 3, tableid, tdt->tdt_opaque); + if(tdt->tdt_flags & TDT_CA) + ret = tdt->tdt_callback((th_dvb_mux_instance_t *)tdt, + sec, len + 3, tableid, tdt->tdt_opaque); else ret = tdt->tdt_callback(tdmi, ptr, len, tableid, tdt->tdt_opaque); @@ -828,7 +829,7 @@ static int dvb_ca_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, uint8_t tableid, void *opaque) { - cwc_emm(ptr, len, (uintptr_t)opaque); + cwc_emm(ptr, len, (uintptr_t)opaque, (void *)tdmi); return 0; } @@ -864,7 +865,7 @@ dvb_cat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, break; tdt_add(tdmi, NULL, dvb_ca_callback, (void *)caid, "CA", - TDT_INC_TABLE_HDR, pid, NULL); + TDT_CA, pid, NULL); break; default: From 84842c951c4fded196e27d8a614c06b00a211a4d Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 10 Apr 2012 20:51:10 +0200 Subject: [PATCH 32/41] cwc: Allow updating of EMMs only from one channel at a time Signed-off-by: Jaroslav Kysela --- docs/html/config_cwc.html | 3 +++ src/cwc.c | 38 +++++++++++++++++++++++-------- src/webui/static/app/cwceditor.js | 11 +++++++-- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/docs/html/config_cwc.html b/docs/html/config_cwc.html index 3877d541..24a5a251 100644 --- a/docs/html/config_cwc.html +++ b/docs/html/config_cwc.html @@ -51,6 +51,9 @@
Update Card
Forward Entitlement Management Messages (EMMs) to the server. +
Update One +
Forward EMMs only from one channel at a time. +
Comment
Allows the administrator to set a comment only visible in this editor. It does not serve any active purpose. diff --git a/src/cwc.c b/src/cwc.c index e2442ea8..7db23099 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -247,6 +247,10 @@ typedef struct cwc { } cwc_viaccess_emm; #define cwc_cryptoworks_emm cwc_viaccess_emm + /* one update id */ + int64_t cwc_update_time; + void *cwc_update_id; + /* Card type */ card_type_t cwc_card_type; @@ -261,6 +265,7 @@ typedef struct cwc { int cwc_port; char *cwc_id; int cwc_emm; + int cwc_emmex; const char *cwc_errtxt; @@ -280,10 +285,10 @@ void cwc_emm_conax(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_irdeto(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_dre(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_seca(cwc_t *cwc, uint8_t *data, int len); -void cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int len, void *ca_update_id); +void cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_nagra(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_nds(cwc_t *cwc, uint8_t *data, int len); -void cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len, void *ca_update_id); +void cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len); /** @@ -1198,6 +1203,15 @@ cwc_emm(uint8_t *data, int len, uint16_t caid, void *ca_update_id) TAILQ_FOREACH(cwc, &cwcs, cwc_link) { if(cwc->cwc_caid == caid && cwc->cwc_forward_emm && cwc->cwc_writer_running) { + if (cwc->cwc_emmex) { + if (cwc->cwc_update_id != ca_update_id) { + int64_t delta = getmonoclock() - cwc->cwc_update_time; + if (delta < 25000000UL) /* 25 seconds */ + continue; + } + cwc->cwc_update_time = getmonoclock(); + } + cwc->cwc_update_id = ca_update_id; switch (cwc->cwc_card_type) { case CARD_CONAX: cwc_emm_conax(cwc, data, len); @@ -1209,7 +1223,7 @@ cwc_emm(uint8_t *data, int len, uint16_t caid, void *ca_update_id) cwc_emm_seca(cwc, data, len); break; case CARD_VIACCESS: - cwc_emm_viaccess(cwc, data, len, ca_update_id); + cwc_emm_viaccess(cwc, data, len); break; case CARD_DRE: cwc_emm_dre(cwc, data, len); @@ -1221,7 +1235,7 @@ cwc_emm(uint8_t *data, int len, uint16_t caid, void *ca_update_id) cwc_emm_nds(cwc, data, len); break; case CARD_CRYPTOWORKS: - cwc_emm_cryptoworks(cwc, data, len, ca_update_id); + cwc_emm_cryptoworks(cwc, data, len); break; case CARD_UNKNOWN: break; @@ -1383,7 +1397,7 @@ static int via_provider_id(uint8_t * data) void -cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int mlen, void *ca_update_id) +cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int mlen) { /* Get SCT len */ int len = 3 + ((data[1] & 0x0f) << 8) + data[2]; @@ -1415,7 +1429,7 @@ cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int mlen, void *ca_update_id) if (cwc->cwc_viaccess_emm.shared_emm) { cwc->cwc_viaccess_emm.shared_len = len; memcpy(cwc->cwc_viaccess_emm.shared_emm, data, len); - cwc->cwc_viaccess_emm.ca_update_id = ca_update_id; + cwc->cwc_viaccess_emm.ca_update_id = cwc->cwc_update_id; } cwc->cwc_viaccess_emm.shared_toggle = data[0]; } @@ -1423,7 +1437,7 @@ cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int mlen, void *ca_update_id) break; case 0x8e: if (cwc->cwc_viaccess_emm.shared_emm && - cwc->cwc_viaccess_emm.ca_update_id == ca_update_id) { + cwc->cwc_viaccess_emm.ca_update_id == cwc->cwc_update_id) { int match = 0; int i; /* Match SA and provider in shared */ @@ -1670,7 +1684,7 @@ cwc_emm_nds(cwc_t *cwc, uint8_t *data, int len) } void -cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len, void *ca_update_id) +cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len) { int match = 0; @@ -1689,13 +1703,13 @@ cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len, void *ca_update_id) if (cwc->cwc_cryptoworks_emm.shared_emm) { cwc->cwc_cryptoworks_emm.shared_len = len; memcpy(cwc->cwc_cryptoworks_emm.shared_emm, data, len); - cwc->cwc_cryptoworks_emm.ca_update_id = ca_update_id; + cwc->cwc_cryptoworks_emm.ca_update_id = cwc->cwc_update_id; } } break; case 0x86: /* emm-sb */ if (cwc->cwc_cryptoworks_emm.shared_emm && - cwc->cwc_cryptoworks_emm.ca_update_id == ca_update_id) { + cwc->cwc_cryptoworks_emm.ca_update_id == cwc->cwc_update_id) { /* python: EMM_SH[0:12] + EMM_SB[5:-1] + EMM_SH[12:-1] */ uint32_t elen = len - 5 + cwc->cwc_cryptoworks_emm.shared_len - 12; uint8_t *tmp = malloc(elen); @@ -1998,6 +2012,7 @@ cwc_record_build(cwc_t *cwc) htsmsg_add_str(e, "deskey", buf); htsmsg_add_u32(e, "emm", cwc->cwc_emm); + htsmsg_add_u32(e, "emmex", cwc->cwc_emmex); htsmsg_add_str(e, "comment", cwc->cwc_comment ?: ""); return e; @@ -2084,6 +2099,9 @@ cwc_entry_update(void *opaque, const char *id, htsmsg_t *values, int maycreate) if(!htsmsg_get_u32(values, "emm", &u32)) cwc->cwc_emm = u32; + if(!htsmsg_get_u32(values, "emmex", &u32)) + cwc->cwc_emmex = u32; + cwc->cwc_reconfigure = 1; if(cwc->cwc_fd != -1) diff --git a/src/webui/static/app/cwceditor.js b/src/webui/static/app/cwceditor.js index 99daadf1..ac5f610a 100644 --- a/src/webui/static/app/cwceditor.js +++ b/src/webui/static/app/cwceditor.js @@ -14,6 +14,12 @@ tvheadend.cwceditor = function() { width: 100 }); + var emmexColumn = new Ext.grid.CheckColumn({ + header: "Update One", + dataIndex: 'emmex', + width: 100 + }); + function setMetaAttr(meta, record){ var enabled = record.get('enabled'); if(!enabled) return; @@ -72,6 +78,7 @@ tvheadend.cwceditor = function() { editor: new fm.TextField({allowBlank: false}) }, emmColumn, + emmexColumn, { header: "Comment", dataIndex: 'comment', @@ -86,7 +93,7 @@ tvheadend.cwceditor = function() { var rec = Ext.data.Record.create([ 'enabled', 'connected', 'hostname', 'port', 'username', - 'password', 'deskey', 'emm', 'comment' + 'password', 'deskey', 'emm', 'emmex', 'comment' ]); var store = new Ext.data.JsonStore({ @@ -99,7 +106,7 @@ tvheadend.cwceditor = function() { }); var grid = new tvheadend.tableEditor('Code Word Client', 'cwc', cm, rec, - [enabledColumn, emmColumn], store, + [enabledColumn, emmColumn, emmexColumn], store, 'config_cwc.html', 'key'); tvheadend.comet.on('cwcStatus', function(msg) { From da053d7c29054d1de2d0290fef04baf4cb5df644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 10 Apr 2012 21:15:57 +0200 Subject: [PATCH 33/41] Cleanup the debian/ directory and make it use more dh scripts and add entry points for Autobuild system --- Autobuild.sh | 74 +++++ Autobuild/debian.sh | 26 ++ Autobuild/ubuntu-lucid-amd64.sh | 1 + Autobuild/ubuntu-lucid-i386.sh | 1 + debian/changelog | 472 -------------------------------- debian/rules | 30 +- debian/tvheadend.tvheadend.init | 2 +- support/configure.inc | 8 - 8 files changed, 108 insertions(+), 506 deletions(-) create mode 100755 Autobuild.sh create mode 100755 Autobuild/debian.sh create mode 100755 Autobuild/ubuntu-lucid-amd64.sh create mode 100755 Autobuild/ubuntu-lucid-i386.sh delete mode 100644 debian/changelog diff --git a/Autobuild.sh b/Autobuild.sh new file mode 100755 index 00000000..3593a02c --- /dev/null +++ b/Autobuild.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# +# Entry point for the Doozer autobuild system +# +# (c) Andreas Öman 2011. All rights reserved. +# +# + +set -eu + +BUILD_API_VERSION=2 +EXTRA_BUILD_NAME="" +JARGS="" +JOBSARGS="" +TARGET="" +RELEASE="--release" +WORKINGDIR="/var/tmp/showtime-autobuild" +UPLOAD_BUILD_ARTIFACTS=1 +while getopts "vht:e:j:w:R" OPTION +do + case $OPTION in + v) + echo $BUILD_API_VERSION + exit 0 + ;; + R) + UPLOAD_BUILD_ARTIFACTS=0 + ;; + h) + echo "This script is intended to be used by the autobuild system only" + exit 0 + ;; + t) + TARGET="$OPTARG" + ;; + e) + EXTRA_BUILD_NAME="$OPTARG" + ;; + j) + JOBSARGS="--jobs=$OPTARG" + JARGS="-j$OPTARG" + ;; + w) + WORKINGDIR="$OPTARG" + ;; + esac +done + + +if [[ -z $TARGET ]]; then + echo "target (-t) not specified" + exit 1 +fi + +# +# $1 = local file path +# $2 = type +# $3 = content-type +# $4 = filename +# +artifact() { + if [ $UPLOAD_BUILD_ARTIFACTS -eq 1 ]; then + echo "doozer-artifact:$PWD/$1:$2:$3:$4" + else + echo "Ignoring: $1:$2:$3:$4" + fi +} + +if [ -f Autobuild/${TARGET}.sh ]; then + source Autobuild/${TARGET}.sh +else + echo "target $TARGET not supported" + exit 1 +fi diff --git a/Autobuild/debian.sh b/Autobuild/debian.sh new file mode 100755 index 00000000..587eac69 --- /dev/null +++ b/Autobuild/debian.sh @@ -0,0 +1,26 @@ +CHANGELOG=debian/changelog +NOW=`date -R` +VER=`git describe | sed "s/\([0-9]*\)\.\([0-9]*\)-\([0-9]*\)-.*/\1.\2.\3/"` +echo >${CHANGELOG} "tvheadend (${VER}) unstable; urgency=low" +echo >>${CHANGELOG} +echo >>${CHANGELOG} " * The full changelog can be found at " +echo >>${CHANGELOG} " http://www.lonelycoder.com/tvheadend/download" +echo >>${CHANGELOG} +echo >>${CHANGELOG} " -- Andreas Öman ${NOW}" +cat ${CHANGELOG} +export JOBSARGS +export JARGS +dpkg-buildpackage -b -us -uc + +for a in ../tvheadend*${VER}*.deb; do + artifact $a deb application/x-deb `basename $a` + rm -f $a +done + +for a in ../tvheadend*${VER}*.changes; do + artifact $a changes text/plain `basename $a` + rm -f $a +done + +rm -f ${CHANGELOG} +dh_clean diff --git a/Autobuild/ubuntu-lucid-amd64.sh b/Autobuild/ubuntu-lucid-amd64.sh new file mode 100755 index 00000000..606932b3 --- /dev/null +++ b/Autobuild/ubuntu-lucid-amd64.sh @@ -0,0 +1 @@ +source Autobuild/debian.sh diff --git a/Autobuild/ubuntu-lucid-i386.sh b/Autobuild/ubuntu-lucid-i386.sh new file mode 100755 index 00000000..606932b3 --- /dev/null +++ b/Autobuild/ubuntu-lucid-i386.sh @@ -0,0 +1 @@ +source Autobuild/debian.sh diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 86bc0ec1..00000000 --- a/debian/changelog +++ /dev/null @@ -1,472 +0,0 @@ -tvheadend (2.12.99) hts; urgency=low - - * Debian package has been renamed from hts-tvheadend to tvheadend - - * Add functionality to delete recordings - - * Better support for playing in web clients. - Temporary tickets are used instead of username/password authentication - - * Remove lock contention in CWC updates - - * Fix bug in IPTV PAT parser (Ticket #318) - - * Store EPG on disk so it can be reloaded on restart - - * Add support for Viaccess EMM - - * Add support for DRECrypt EMM - - * Depend on OpenSSL for cryptographic features - - * RTSP has been dropped. It was too buggy and noone wanted to maintain it - - * Fix bug in JSON encoder. Ticket #163 - - * Fix crash in HTTP service. Ticket #334 - - * Added http-streaming of services. Tested and working with mplayer. - - * Add support for building RPM packages - - -- Andreas Öman Sat, 19 Feb 2011 12:57:09 +0100 - -hts-tvheadend (2.12) hts; urgency=low - - * Add support for IPTV over IPv6 - - * Use a native matroska mutiplixer to get better support for metadata, etc - - * Add support for multiple DVR configurations (can be set per recording) - - * Add suport for teletext subtitles - - * Add support for E-AC3 - - * Workaround for ITV HD (which has incorrect PMT) - Ticket #215 - - * Keep track of video width and height and send it over HTSP in - subscriptionStart. - Ticket #208 - - * Add support for Logical Channel Number descriptor (0x83) - Ticket #138 - - * Maintain the order of PIDs as they appear in the PMT. - Ticket #218 - - * When there is no video pid (service type is Radio), - start the audio stream right away. - Ticket #59 - - * Add subscriptionChangeWeight HTSP method. - - * psi: Assume that elementary stream type 0x81 is AC3 without - relying on any further descriptors - Ticket #217 - - * Tvheadend no longer depends on FFmpeg so it's not externally updated - in svn, nor linked. - - * Added a native matroska muxer. - Correctly writes global headers. Ticket #61 - Add support for recording AAC audio. Ticket #160 - Improves metadata written to files. - - * Tvheadend no longer tries to fixup lack of PTS/DTS for packets - before sending them over HTSP. Rather, those fields will be left - out in the message. Currently, all HTSP clients known to mankind - handles this. - - * Make error detection in timestamp parsing much more robust. Avoid - extracting persistent data (such as video width*height) from - received data if we suspect that an error has occured (MPEG-TS TEI - or continuity counter errors). - - -- Andreas Öman Mon, 29 Nov 2010 20:06:52 +0100 - -hts-tvheadend (2.11) hts; urgency=low - - * Add support for filtering autorecordings based on weekdays. - - * Add circular 10.75 GHz LNB - - * Add a new DVB adapter option that allows the entire DVB Mux to be - written to disk as Tvheadend tunes to it. This should aid a lot when - it comes to debugging - - * Inject entries in DVR schedule as soon as we know about an EPG - entry that matches an autorecording rule. Previously Tvheadend - would scan the EPG continously and just grab shows as they neared - air time. The drawbacks of this approach was that it's a bit hard - to understand what is happening. It also makes (more) correct - wakeup from suspend hard to do. - - * Add parsing of episode information from XMLTV and display it in the - WebUI EPG - - * A bug caused the 'Automatic Recorder' tab grid not to reload - entries upon external change (Such as when a channel got deleted - or when a new auto recording was created from the EPG view). This - is now fixed. - - * Add support for storing recorded events in a directory named after - the event. Ticket #150 - - * Add support for appending season and episode numbers to filenames - during recording. - - * Prior to this release the color (i.e. connection status) of the - CWC entries were not correctly updated when a connection was established - or lost. This is now fixed. Ticket #144 - - * Add support for prioritized recordings. The user can chose among five - different priorities. - - * Fix various issues realted to the Recording Schedule user interface. - The UI now includes better visual feedback on what's going on and if - there are errors. Also recordings that do not complete successfully - are correctly reported as failed entries. Ticket #131 - - * Add support for Irdeto and Seca EMM - - -- Andreas Öman Sat, 27 Mar 2010 10:03:40 +0100 - -hts-tvheadend (2.10) hts; urgency=high - - * Fix a crash in HTSP server. - - -- Andreas Öman Thu, 04 Feb 2010 22:21:22 +0100 - -hts-tvheadend (2.9) hts; urgency=high - - * A last minute bug slipped in the 2.8 release, causing Tvheadend to read - settings and configuration from incorrect path when also switching user - during startup. This has now been fixed. - - -- Andreas Öman Mon, 25 Jan 2010 21:23:47 +0100 - -hts-tvheadend (2.8) hts; urgency=low - - * Added support for AAC audio - - * Added support for manual creation of DVR entries. Prior to this it - was only possible to schedule a recording based on EPG entries. - - * It's now possible to enable/disable the signal quality monitor per - adapter. This is now default off as it seem to mostly cause problems - for people and it's only useful if you have complex setups with - multiple adapters, etc. - - * Improve logging when subscriptions fail to start - - * More intelligent arbitration amongst all sources when a subscription - is about to start for a channel. If we cannot descramble or if no - input is detected, skip to next source. - Fixes ticket #89 - - * Add option for editing channel icon URL in the channel config tab. - - * Fix support for Irdeto ECM - - * Automatically detect if a connected USB DVB adapter is only Full speed - (ie 12Mbit/s), and if so, limit so Tvheadend only can stream one service - at the time from the tuned frequency. - - * Add support for extracting provider in the PMT for SECA/Mediaguard - - * Add support for NIT-other tables. - In particular useful for Ziggo DVB-C networks in the Netherlands. - - * Fix various bugs related to RTP encapsulated IPTV - - * Tvheadend now support placement of configurations and settings at any path. - Use the '-c' command line option for this. By default Tvheadend puts - configuration at $HOME/.hts/tvheadend - - * Make it possible to enable debug level log in the web interface. - Press the small top-right gear icon in the log console to enable/disable - debug log. - - -- Andreas Öman Mon, 25 Jan 2010 21:23:47 +0100 - -hts-tvheadend (2.7) hts; urgency=low - - * Added support for DVB subtitles. Currently only forwarded over HTSP - - * Add support for reception of RTP encapsulated IPTV - - * Fixed a crash caused by a race condition when starting a subscription - - * Increase maximum packet size for IPTV to 65536 bytes - - -- Andreas Öman Sun, 06 Dec 2009 20:40:41 +0100 - -hts-tvheadend (2.6) hts; urgency=low - - * Tvheadend's DVB service probe will now make the channel join tags based - on the service type and DVB provider name. - - * Add support for tuning on ATSC adapters - - * Add support for sattelite beams with circular polarisation - - * If a user changed the XMLTV source for a channel to 'None', tvheadend - would crash. This is now fixed. - - * Add support for copying a selection of muxes from one DVB adapter to - another in the web UI. - - * Support for DVB-S2 has been added - - * Default character encoding in DVB is ISO6937, not Latin-1. Ticket #96 - - * Add support for DiSEqC 1.1 / 2.1, configured on per-adapter basis. - Ticket #99 - - * Increase logging and include various stats to XMLTV grab - - * Add support for configuring a per-channel pre/post extra time for - scheduled recordings. Ticket #104 - - * Autodetect CPU capabilities and choose best mode for CSA descrambler. - Ticket #122 - - -- Andreas Öman Sun, 29 Nov 2009 14:02:36 +0100 - -hts-tvheadend (2.5) hts; urgency=low - - * If a previosly detected DVB adapter was not present during startup, - Tvheadend would crash. This is now fixed. - - * If XMLTV grabbing was disabled tvheadend would spin in a 100% CPU loop. - This is now fixed. - - * The HTSP service is now announced via AVAHI (mDNS service discovery) - - * Support for IPTV has been added. Only RAW TS in UDP is supported - at the moment. - - * Add support for setting default extra times to add before and after - a recording. Useful if your TV shows never start on time. - - * Use FFmpeg's av_interleaved_write_frame() or some players can't - play the recorded content (vlc is one) - - -- Andreas Öman Wed, 19 Aug 2009 22:28:02 +0200 - -hts-tvheadend (2.4) hts; urgency=low - - * Due to a bug, the polarisation of DVB-S muxes was not correctly - stored internally. This has now been fixed. - - * Fix compilation on 64bit systems - - * Make sure channel <> service mappings are saved when edited from - DVB service grid - - * Add support for merging one channel into another. - Useful if you have multiple providers offering the same DVB service - but with different names. - - * The embedded HTTP server now logs failed requests - - * Use absolute paths when serving static content (the web app itself) - This was only a problem when fork()ing a development build - - * Rework the CWC reconnection strategy. - If there are active subscription, Tvheadend will attempt to reconnect - immediately and then retry every three seconds. - If no subscription is active a reconnection attempt is performed - every minute. - Also, if any CWC configuration changes are made from the UI, Tvheadend - will try to reconnect directly. - - * If the EPG receives an updated description for an even that is shorter - than the current description it will be ignored. - This typically happens if the XMLTV and DVB EIT (Event Information Table) - differs. In other words, we assume that a longer description of an - event is better than a short. - - -- Andreas Öman Sun, 26 Jul 2009 13:27:32 +0200 - -hts-tvheadend (2.3) hts; urgency=low - - * A simple web interface has been added. To access it, visit - - http://host:9981/simple.html - - This web interface is designed to be really tiny with only - a simple search field and options to record found shows. - Preferably used from handheld devices. - - * All sensitive information (passwords, etc) are hidden from display - in the web ui. The text will still be displayed in cleartext when - editing. - - * Redesigned the DVB configuration tab in the web userinterface: - - Each adapter have three (or four) tabs - o General setup and information - o Grid of multiplexes - o Grid of services - o For sattelite adapters, a sattelite configuration tab. - - * Add support for disabling / enabling an entire DVB multiplex - - * Add support for multiple DiSEqC switchports on a single adapter - - * Add support for different sattelite LNBs - - * Graceful handling of DVB adapters that does not support many - table filters in hardware. Tvheadend will rotate among the available - ones. - - * Add support for enabling / disabling transports from the DVB configuration - - * Make it possible to remove DVB multiplexes from the web ui - - * Add 'Revert changes' button to all editable grids in the web ui - - * Make it possible to disable the idle scan on per-DVB adapter basis. - The idle scan is a process to cycles through all multiplex to check - the quality for each mux continously. - - * Hopefully fix some rounding errors in the EPG display. Ticket #69 - - * Use a ''livegrid'' (http://www.ext-livegrid.com/) for displaying EPG. - - * Remove configuration and settings (/home/hts/.hts/tvheadend) on a - deb package purge operation. Ticket #73 - - * If the Program Stream Information changes during a subscription, - react and send a subscriptionStop + subscriptionStart. - This happens on SVT (in sweden) when the transmission switches - from local to nationwide broadcast (AC3 audio is only present - in nationwide broadcast) - Ticket #78 - - * Channel editor has been reworked a bit. It uses an editorGrid, similar - to how other grids work in Tvheadend. Tags are mapped inline using - a list-of-values combobox (http://lovcombo.extjs.eu/) - - * Added a search IMDB direct link in the EPG window popup. - Ticket #79 - - * Add support for configuring DVB multiplexes by entering - all tuning parameters manually - Ticket #37 - - * Fix a bug causing channel <> tags mapping not to be restored on load. - - * Add exponential backoff for reconnect attempt in code word client. - Ticket #80 - - * Try to detect duplicate EPG entries from the DVB feed and adjust - EPG accordingly. The EPG code will search for events with the same - DVB event ID +- 2 events from the current one. If the event id is - equal, the prvious (old) entry will be removed in favor of the new one. - Reason for not blindingly trusting the event id is that some networks - seem to (incorrectly) reuse IDs. - Ticket #65 - - -- Andreas Öman Sat, 18 Jul 2009 23:19:18 +0200 - -hts-tvheadend (2.2) hts; urgency=low - - * Set $HOME so forked processes (XMLTV) will have correct environment - and to make the default storage of recorded videos to end up in the - correct place. - - * Update built-in DVB mux presets to dvb-apps:1275:9655c8cfeed8 - - * Add -h option to display usage. - - * Rewrite the internal streaming pipeline. - This is not externally visible, but needed for a future timeshifter. - - * Make it compile on gcc 4.4 - - * Send 'source' and 'network' information in HTSP.subscriptionStart message. - - * When deleting a channel any channel-bound autorecording would stay in - memory and, sooner or later, cause a crash. This has now been fixed. - - * Add extra scan for XMLTV grabbers in $PATH. Apart from $PATH we also - scan in /bin, /usr/bin, /usr/local/bin - - * Search for XMLTV grabbers in /usr/bin/perlbin/vendor (archlinux) - - * Fix a bug causing DVB card which does not implement the - FE_READ_UNCORRECTED_BLOCKS operation to report insane amount of - forward correction errors. - - -- Andreas Öman Sun, 07 Jun 2009 19:22:49 +0200 - -hts-tvheadend (2.1) hts; urgency=low - - * Add debconf setup scripts to create a superuser account. - - * HTSP server slightly modified. Now also supports the XBMC HTSP client. - - * tvheadend and showtime went separate ways. - - * tvheadend: Record post-processing added again, run command when a - recording is done. - - * tvheadend: Fix characterset translation bug introduced in r1902. - - -- Andreas Öman Thu, 28 May 2009 21:07:44 +0200 - -hts-tvheadend (2.0) unstable; urgency=low - - * tvheadend: All setup and configuration is done from the web user interface. - - * tvheadend: New web user interface based on ExtJS - - -- Andreas Öman Thu, 16 Oct 2008 19:47:23 +0200 - -hts-tvheadend (1.4) unstable; urgency=low - - * tvheadend: Add support for DVB-S (still in experimenal state) - - -- Andreas Öman Sat, 30 Mar 2008 18:00:00 +0100 - -hts-tvheadend (1.3) unstable; urgency=low - - * tvheadend: Add support for executing a post processing script after - recording is completed. - - * tvheadend: Mark I-frames as key-frames in recorder (should make seeking - work better). - - * tvheadend: Correctly set duration of packets in recorder. - - -- Andreas Öman Thu, 28 Mar 2008 18:00:00 +0100 - -hts-tvheadend (1.2) unstable; urgency=low - - * Tvheadend has been rewritten from scratch - - -- Andreas Öman Thu, 28 Feb 2008 17:30:00 +0100 - -hts-tvheadend (1.1) unstable; urgency=low - - * Bugfix: Tvheadend: Do not crash if event name is NULL - - * Rewrite tvheadend internals to fix many serious issues - - * tvheadend now correctly supports recording of h264 content - - * RTSP interface added to tvheadend that supports time shifting of live tv - - * Add web interface to tvheadend - - -- Andreas Öman Sat, 24 Nov 2007 08:11:00 +0100 - -hts-tvheadend (1.0) unstable; urgency=low - - * Initial release - - -- Andreas Öman Tue, 19 Sep 2007 19:20:00 +0200 - diff --git a/debian/rules b/debian/rules index 2bae8172..9b6d1783 100755 --- a/debian/rules +++ b/debian/rules @@ -1,38 +1,18 @@ #!/usr/bin/make -f - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -DEB_BUILD_GNU_TYPE := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +export DH_VERBOSE=1 %: dh $@ -override_dh_clean: - dh_testdir - dh_testroot - rm -rf build.* - dh_clean - -override_dh_auto_clean: - dh_clean - override_dh_auto_configure: - dh_testdir - ./configure --release --prefix=/usr + dh_auto_configure -- ${JOBSARGS} override_dh_auto_build: - $(MAKE) - -override_dh_install: - $(MAKE) DESTDIR=$(CURDIR)/debian/tvheadend install - -override_dh_installinit: - dh_installinit --name tvheadend + make ${JARGS} override_dh_strip: dh_strip --dbg-package=tvheadend-dbg -override_dh_autotest: - echo "skipped autotest" +override_dh_auto_install: + dh_auto_install --destdir=debian/tvheadend diff --git a/debian/tvheadend.tvheadend.init b/debian/tvheadend.tvheadend.init index 2e424b97..8f781893 100644 --- a/debian/tvheadend.tvheadend.init +++ b/debian/tvheadend.tvheadend.init @@ -13,7 +13,7 @@ # PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/usr/sbin:/usr/bin:/sbin:/bin -DESC="HTS Tvheadend" +DESC="Tvheadend" NAME=tvheadend DAEMON=/usr/bin/$NAME DAEMON_ARGS="-f -u hts -g video" diff --git a/support/configure.inc b/support/configure.inc index bf821f7b..048e74bd 100644 --- a/support/configure.inc +++ b/support/configure.inc @@ -17,8 +17,6 @@ BUILDDIR=build.${PLATFORM} DEFAULT_THEME="new" RELEASE=no -RELEASENAME=`head -n1 ${TOPDIR}/ChangeLog | awk '{print $2}' | sed s/\(// | sed s/\)//` - CONFIG_LIST=" cwc avahi @@ -125,12 +123,6 @@ EOF finalize() { -if [ ${RELEASE} = yes ]; then - echo Release build: ${RELEASENAME} - echo >>${CONFIG_H} "#define TVHEADEND_RELEASE_TAG \"${RELEASENAME}\"" -fi - - cat >> ${CONFIG_MAK} << EOF OSENV=${OSENV} LDFLAGS_cfg += -lm From ff57db5d827e56170bea7d92ecaa5376cb198e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 10 Apr 2012 21:18:46 +0200 Subject: [PATCH 34/41] Bump From 39d1600bf984d255dd8d15d1dbfd489a9ebd0f9f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 12 Apr 2012 14:35:06 +0200 Subject: [PATCH 35/41] cwc: Use only one fastest ECM reader Use only one - fastest - ECM reader when multiple CA readers/cards are available for one program. Signed-off-by: Jaroslav Kysela --- src/cwc.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/cwc.c b/src/cwc.c index 7db23099..9be063c6 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -151,7 +151,8 @@ typedef struct cwc_service { enum { CS_UNKNOWN, CS_RESOLVED, - CS_FORBIDDEN + CS_FORBIDDEN, + CS_IDLE } cs_keystate; void *cs_keys; @@ -742,6 +743,8 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, int len, int seq) { service_t *t = ct->cs_service; + cwc_service_t *ct2; + cwc_t *cwc2; ecm_pid_t *ep; char chaninfo[32]; int i; @@ -800,12 +803,25 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, msg[3 + 5], msg[3 + 6], msg[3 + 7], msg[3 + 8], msg[3 + 9], msg[3 + 10],msg[3 + 11],msg[3 + 12],msg[3 + 13],msg[3 + 14], msg[3 + 15], seq, delay); + + TAILQ_FOREACH(cwc2, &cwcs, cwc_link) { + LIST_FOREACH(ct2, &cwc2->cwc_services, cs_link) { + if (ct != ct2 && ct2->cs_service == t && + ct2->cs_keystate == CS_RESOLVED) { + ct->cs_keystate = CS_IDLE; + tvhlog(LOG_DEBUG, "cwc", + "Already has a key for service \"%s\", from %s:%i", + t->s_svcname, ct2->cs_cwc->cwc_hostname, ct2->cs_cwc->cwc_port); + return; + } + } + } if(ct->cs_keystate != CS_RESOLVED) tvhlog(LOG_INFO, "cwc", "Obtained key for for service \"%s\" in %lld ms, from %s", t->s_svcname, delay, ct->cs_cwc->cwc_hostname); - + ct->cs_keystate = CS_RESOLVED; memcpy(ct->cs_cw, msg + 3, 16); ct->cs_pending_cw_update = 1; @@ -1519,6 +1535,9 @@ cwc_table_input(struct th_descrambler *td, struct service *t, char chaninfo[32]; caid_t *c; + if (ct->cs_keystate == CS_IDLE) + return; + if(len > 4096) return; From e5eef814f2312429a7b3cffb1458f9af1c528cf8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 12 Apr 2012 14:42:26 +0200 Subject: [PATCH 36/41] cwc: Use hostname:port notation in log messages Show all cwc connection information to users. Multiple card readers can be configured on same IP but different ports. Signed-off-by: Jaroslav Kysela --- src/cwc.c | 93 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/src/cwc.c b/src/cwc.c index 9be063c6..49b5b554 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -591,10 +591,10 @@ cwc_decode_card_data_reply(cwc_t *cwc, uint8_t *msg, int len) memcpy(cwc->cwc_ua, &msg[6], 8); - tvhlog(LOG_INFO, "cwc", "%s: Connected as user 0x%02x " + tvhlog(LOG_INFO, "cwc", "%s:%i: Connected as user 0x%02x " "to a %s-card [0x%04x : %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x] " "with %d providers", - cwc->cwc_hostname, + cwc->cwc_hostname, cwc->cwc_port, msg[3], n, cwc->cwc_caid, cwc->cwc_ua[0], cwc->cwc_ua[1], cwc->cwc_ua[2], cwc->cwc_ua[3], cwc->cwc_ua[4], cwc->cwc_ua[5], cwc->cwc_ua[6], cwc->cwc_ua[7], nprov); @@ -617,8 +617,8 @@ cwc_decode_card_data_reply(cwc_t *cwc, uint8_t *msg, int len) cwc->cwc_providers[i].sa[6] = msg[9]; cwc->cwc_providers[i].sa[7] = msg[10]; - tvhlog(LOG_INFO, "cwc", "%s: Provider ID #%d: 0x%06x %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x", - cwc->cwc_hostname, i + 1, + tvhlog(LOG_INFO, "cwc", "%s:%i: Provider ID #%d: 0x%06x %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x", + cwc->cwc_hostname, cwc->cwc_port, i + 1, cwc->cwc_providers[i].id, cwc->cwc_providers[i].sa[0], cwc->cwc_providers[i].sa[1], @@ -641,16 +641,16 @@ cwc_decode_card_data_reply(cwc_t *cwc, uint8_t *msg, int len) if (!emm_allowed) { tvhlog(LOG_INFO, "cwc", - "%s: Will not forward EMMs (not allowed by server)", - cwc->cwc_hostname); + "%s:%i: Will not forward EMMs (not allowed by server)", + cwc->cwc_hostname, cwc->cwc_port); } else if (cwc->cwc_card_type != CARD_UNKNOWN) { - tvhlog(LOG_INFO, "cwc", "%s: Will forward EMMs", - cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: Will forward EMMs", + cwc->cwc_hostname, cwc->cwc_port); cwc->cwc_forward_emm = 1; } else { tvhlog(LOG_INFO, "cwc", - "%s: Will not forward EMMs (unsupported CA system)", - cwc->cwc_hostname); + "%s:%i: Will not forward EMMs (unsupported CA system)", + cwc->cwc_hostname, cwc->cwc_port); } } @@ -673,43 +673,43 @@ cwc_detect_card_type(cwc_t *cwc) case 0x17: case 0x06: cwc->cwc_card_type = CARD_IRDETO; - tvhlog(LOG_INFO, "cwc", "%s: irdeto card", - cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: irdeto card", + cwc->cwc_hostname, cwc->cwc_port); break; case 0x05: cwc->cwc_card_type = CARD_VIACCESS; - tvhlog(LOG_INFO, "cwc", "%s: viaccess card", - cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: viaccess card", + cwc->cwc_hostname, cwc->cwc_port); break; case 0x0b: cwc->cwc_card_type = CARD_CONAX; - tvhlog(LOG_INFO, "cwc", "%s: conax card", - cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: conax card", + cwc->cwc_hostname, cwc->cwc_port); break; case 0x01: cwc->cwc_card_type = CARD_SECA; - tvhlog(LOG_INFO, "cwc", "%s: seca card", - cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: seca card", + cwc->cwc_hostname, cwc->cwc_port); break; case 0x4a: cwc->cwc_card_type = CARD_DRE; - tvhlog(LOG_INFO, "cwc", "%s: dre card", - cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: dre card", + cwc->cwc_hostname, cwc->cwc_port); break; case 0x18: cwc->cwc_card_type = CARD_NAGRA; - tvhlog(LOG_INFO, "cwc", "%s: nagra card", - cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: nagra card", + cwc->cwc_hostname, cwc->cwc_port); break; case 0x09: cwc->cwc_card_type = CARD_NDS; - tvhlog(LOG_INFO, "cwc", "%s: nds card", - cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: nds card", + cwc->cwc_hostname, cwc->cwc_port); break; case 0x0d: cwc->cwc_card_type = CARD_CRYPTOWORKS; - tvhlog(LOG_INFO, "cwc", "%s: cryptoworks card", - cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: cryptoworks card", + cwc->cwc_hostname, cwc->cwc_port); break; default: cwc->cwc_card_type = CARD_UNKNOWN; @@ -819,8 +819,9 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, if(ct->cs_keystate != CS_RESOLVED) tvhlog(LOG_INFO, "cwc", - "Obtained key for for service \"%s\" in %lld ms, from %s", - t->s_svcname, delay, ct->cs_cwc->cwc_hostname); + "Obtained key for service \"%s\" in %lld ms, from %s:%i", + t->s_svcname, delay, ct->cs_cwc->cwc_hostname, + ct->cs_cwc->cwc_port); ct->cs_keystate = CS_RESOLVED; memcpy(ct->cs_cw, msg + 3, 16); @@ -907,15 +908,15 @@ cwc_read_message(cwc_t *cwc, const char *state, int timeout) int msglen, r; if((r = cwc_read(cwc, buf, 2, timeout))) { - tvhlog(LOG_INFO, "cwc", "%s: %s: Read error (header): %s", - cwc->cwc_hostname, state, strerror(r)); + tvhlog(LOG_INFO, "cwc", "%s:%i: %s: Read error (header): %s", + cwc->cwc_hostname, cwc->cwc_port, state, strerror(r)); return -1; } msglen = (buf[0] << 8) | buf[1]; if(msglen >= CWS_NETMSGSIZE) { - tvhlog(LOG_INFO, "cwc", "%s: %s: Invalid message size: %d", - cwc->cwc_hostname, state, msglen); + tvhlog(LOG_INFO, "cwc", "%s:%i: %s: Invalid message size: %d", + cwc->cwc_hostname, cwc->cwc_port, state, msglen); return -1; } @@ -923,14 +924,14 @@ cwc_read_message(cwc_t *cwc, const char *state, int timeout) so just wait 1 second here */ if((r = cwc_read(cwc, cwc->cwc_buf + 2, msglen, 1000))) { - tvhlog(LOG_INFO, "cwc", "%s: %s: Read error: %s", - cwc->cwc_hostname, state, strerror(r)); + tvhlog(LOG_INFO, "cwc", "%s:%i: %s: Read error: %s", + cwc->cwc_hostname, cwc->cwc_port, state, strerror(r)); return -1; } if((msglen = des_decrypt(cwc->cwc_buf, msglen + 2, cwc)) < 15) { - tvhlog(LOG_INFO, "cwc", "%s: %s: Decrypt failed", - state, cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: %s: Decrypt failed", + cwc->cwc_hostname, cwc->cwc_port, state); return -1; } return msglen; @@ -992,8 +993,8 @@ cwc_session(cwc_t *cwc) * Get login key */ if((r = cwc_read(cwc, cwc->cwc_buf, 14, 5000))) { - tvhlog(LOG_INFO, "cwc", "%s: No login key received: %s", - cwc->cwc_hostname, strerror(r)); + tvhlog(LOG_INFO, "cwc", "%s:%i: No login key received: %s", + cwc->cwc_hostname, cwc->cwc_port, strerror(r)); return; } @@ -1008,7 +1009,8 @@ cwc_session(cwc_t *cwc) return; if(cwc->cwc_buf[12] != MSG_CLIENT_2_SERVER_LOGIN_ACK) { - tvhlog(LOG_INFO, "cwc", "%s: Login failed", cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: Login failed", + cwc->cwc_hostname, cwc->cwc_port); return; } @@ -1022,7 +1024,8 @@ cwc_session(cwc_t *cwc) return; if(cwc->cwc_buf[12] != MSG_CARD_DATA) { - tvhlog(LOG_INFO, "cwc", "%s: Card data request failed", cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i: Card data request failed", + cwc->cwc_hostname, cwc->cwc_port); return; } @@ -1124,7 +1127,8 @@ cwc_thread(void *aux) cwc->cwc_caid = 0; cwc->cwc_connected = 0; cwc_comet_status_update(cwc); - tvhlog(LOG_INFO, "cwc", "Disconnected from %s", cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "Disconnected from %s:%i", + cwc->cwc_hostname, cwc->cwc_port); } if(subscriptions_active()) { @@ -1139,13 +1143,14 @@ cwc_thread(void *aux) ts.tv_nsec = 0; tvhlog(LOG_INFO, "cwc", - "%s: Automatic connection attempt in in %d seconds", - cwc->cwc_hostname, d); + "%s:%i: Automatic connection attempt in in %d seconds", + cwc->cwc_hostname, cwc->cwc_port, d); pthread_cond_timedwait(&cwc_config_changed, &cwc_mutex, &ts); } - tvhlog(LOG_INFO, "cwc", "%s destroyed", cwc->cwc_hostname); + tvhlog(LOG_INFO, "cwc", "%s:%i destroyed", + cwc->cwc_hostname, cwc->cwc_port); while((ct = LIST_FIRST(&cwc->cwc_services)) != NULL) { t = ct->cs_service; From 91f98a2850c3d33b36f7d0d662bea2d92d7e1bd4 Mon Sep 17 00:00:00 2001 From: Mattias Wadman Date: Fri, 13 Apr 2012 00:45:18 +0300 Subject: [PATCH 37/41] Update README --- README | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README b/README index 2893338c..d10ca7b3 100644 --- a/README +++ b/README @@ -1,4 +1,3 @@ - Tvheadend TV streaming server ============================= @@ -21,7 +20,7 @@ $ make Build the binary, after build the binary resides in 'build.Linux/'. Thus, to start it, just type: -$ build.Linux/tvheadend +$ build.linux/tvheadend Settings are stored in $HOME/.hts/tvheadend From c8af1f21d499d5cb1f37ca160db23993da9b3b9f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 12 Apr 2012 20:03:46 +0200 Subject: [PATCH 38/41] cwc: do not send ECM requests when NOKs are received Do not send ECM requests to the card reader when ECMs cannot be read. Signed-off-by: Jaroslav Kysela --- src/cwc.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/cwc.c b/src/cwc.c index 49b5b554..34bc004e 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -765,20 +765,48 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, if(ct->cs_okchannel == es->es_channel) ct->cs_okchannel = -1; + if (es->es_nok < 3) + es->es_nok++; + if(ct->cs_keystate == CS_FORBIDDEN) return; // We already know it's bad - es->es_nok = 1; + if (es->es_nok > 2) { + tvhlog(LOG_DEBUG, "cwc", + "Too many NOKs for service \"%s\"%s from %s:%i", + t->s_svcname, chaninfo, ct->cs_cwc->cwc_hostname, + ct->cs_cwc->cwc_port); + goto forbid; + } + + TAILQ_FOREACH(cwc2, &cwcs, cwc_link) { + LIST_FOREACH(ct2, &cwc2->cwc_services, cs_link) { + if (ct != ct2 && ct2->cs_service == t && + ct2->cs_keystate == CS_RESOLVED) { + tvhlog(LOG_DEBUG, "cwc", + "NOK from %s:%i: Already has a key for service \"%s\", from %s:%i", + ct->cs_cwc->cwc_hostname, ct->cs_cwc->cwc_port, + t->s_svcname, ct2->cs_cwc->cwc_hostname, ct2->cs_cwc->cwc_port); + es->es_nok = 3; /* do not send more ECM requests */ + goto forbid; + } + } + } tvhlog(LOG_DEBUG, "cwc", "Received NOK for service \"%s\"%s (seqno: %d " "Req delay: %lld ms)", t->s_svcname, chaninfo, seq, delay); +forbid: LIST_FOREACH(ep, &ct->cs_pids, ep_link) { for(i = 0; i <= ep->ep_last_section; i++) - if(ep->ep_sections[i] == NULL || - ep->ep_sections[i]->es_pending || - ep->ep_sections[i]->es_nok == 0) - return; + if(ep->ep_sections[i] == NULL) { + if(es->es_nok < 2) /* only first hit is allowed */ + return; + } else { + if(ep->ep_sections[i]->es_pending || + ep->ep_sections[i]->es_nok == 0) + return; + } } tvhlog(LOG_ERR, "cwc", "Can not descramble service \"%s\", access denied (seqno: %d " @@ -1594,6 +1622,9 @@ cwc_table_input(struct th_descrambler *td, struct service *t, es = ep->ep_sections[section]; + if (es->es_nok > 2) + break; /* too many NOK responses in a row */ + if(es->es_ecmsize == len && !memcmp(es->es_ecm, data, len)) break; /* key already sent */ From 3777a072890364c5b22f0cb4e7180fc592c1cab7 Mon Sep 17 00:00:00 2001 From: Georgi Chorbadzhiyski Date: Fri, 20 Apr 2012 17:45:55 +0300 Subject: [PATCH 39/41] cwc: Add Bulcrypt support. --- src/cwc.c | 39 +++++++++++++++++++++++++++++++++++++++ src/psi.c | 4 +++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/cwc.c b/src/cwc.c index 34bc004e..a45008bb 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -62,6 +62,7 @@ typedef enum { CARD_NAGRA, CARD_NDS, CARD_CRYPTOWORKS, + CARD_BULCRYPT, CARD_UNKNOWN } card_type_t; @@ -290,6 +291,7 @@ void cwc_emm_viaccess(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_nagra(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_nds(cwc_t *cwc, uint8_t *data, int len); void cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len); +void cwc_emm_bulcrypt(cwc_t *cwc, uint8_t *data, int len); /** @@ -668,6 +670,15 @@ static void cwc_detect_card_type(cwc_t *cwc) { uint8_t c_sys = cwc->cwc_caid >> 8; + + switch(cwc->cwc_caid) { + case 0x5581: + case 0x4aee: + cwc->cwc_card_type = CARD_BULCRYPT; + tvhlog(LOG_INFO, "cwc", "%s:%i: bulcrypt card", + cwc->cwc_hostname, cwc->cwc_port); + return; + } switch(c_sys) { case 0x17: @@ -1286,6 +1297,9 @@ cwc_emm(uint8_t *data, int len, uint16_t caid, void *ca_update_id) case CARD_CRYPTOWORKS: cwc_emm_cryptoworks(cwc, data, len); break; + case CARD_BULCRYPT: + cwc_emm_bulcrypt(cwc, data, len); + break; case CARD_UNKNOWN: break; } @@ -1797,6 +1811,31 @@ cwc_emm_cryptoworks(cwc_t *cwc, uint8_t *data, int len) cwc_send_msg(cwc, data, len, 0, 1); } +void +cwc_emm_bulcrypt(cwc_t *cwc, uint8_t *data, int len) +{ + int match = 0; + + switch (data[0]) { + case 0x82: /* unique */ + case 0x85: /* unique */ + match = len >= 10 && memcmp(data + 3, cwc->cwc_ua + 2, 3) == 0; + break; + case 0x84: /* shared */ + match = len >= 10 && memcmp(data + 3, cwc->cwc_ua + 2, 2) == 0; + break; + case 0x8b: /* shared-unknown */ + match = len >= 10 && memcmp(data + 4, cwc->cwc_ua + 2, 2) == 0; + break; + case 0x8a: /* global */ + match = len >= 10 && memcmp(data + 4, cwc->cwc_ua + 2, 1) == 0; + break; + } + + if (match) + cwc_send_msg(cwc, data, len, 0, 1); +} + /** * */ diff --git a/src/psi.c b/src/psi.c index 9dee140e..d27a5a9e 100644 --- a/src/psi.c +++ b/src/psi.c @@ -878,7 +878,9 @@ static struct strtab caidnametab[] = { { "GI", 0x4700 }, { "Telemann", 0x4800 }, { "DRECrypt", 0x4ae0 }, - { "DRECrypt2", 0x4ae1 } + { "DRECrypt2", 0x4ae1 }, + { "Bulcrypt", 0x4aee }, + { "Bulcrypt", 0x5581 }, }; const char * From 0e3bb418699349f7e4f5e9fa32166a7f9d897101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sat, 5 May 2012 22:16:14 +0200 Subject: [PATCH 40/41] Avoid division by zero --- src/parser_latm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/parser_latm.c b/src/parser_latm.c index 9d7369a9..eca91b80 100644 --- a/src/parser_latm.c +++ b/src/parser_latm.c @@ -71,6 +71,9 @@ read_audio_specific_config(elementary_stream_t *st, latm_private_t *latm, else sr = sri_to_rate(latm->sample_rate_index); + if(sr == 0) + return; + st->es_frame_duration = 1024 * 90000 / sr; latm->channel_config = read_bits(bs, 4); From 4ca5dda14a0e4fc7a78886e7a73058be96e3dad2 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Fri, 11 May 2012 14:51:27 +0100 Subject: [PATCH 41/41] Remove define that breaks build. --- src/dvb/dvb_preconf.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/dvb/dvb_preconf.c b/src/dvb/dvb_preconf.c index 07f8c6ab..ef1cf6d9 100644 --- a/src/dvb/dvb_preconf.c +++ b/src/dvb/dvb_preconf.c @@ -64,9 +64,7 @@ dvb_mux_preconf_add(th_dvb_adapter_t *tda, const struct mux *m, int num, break; case FE_QPSK: - #ifdef SYS_DVBS - dmc.dmc_fe_delsys = SYS_DVBS; - #endif + dmc.dmc_fe_delsys = SYS_DVBS; dmc.dmc_fe_params.u.qpsk.symbol_rate = m->symrate; dmc.dmc_fe_params.u.qpsk.fec_inner = m->fec;