mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
The channel/CAM relations are now stored in the file 'cam.data'; fixed a flaw in handling timeouts for encrypted channels
This commit is contained in:
parent
882273d508
commit
d1ddb39781
@ -3383,6 +3383,7 @@ Dietmar Spingler <d_spingler@gmx.de>
|
||||
for suggesting to provide a way of using no DVB devices at all
|
||||
for suggesting that the -V and -h options should list the plugins in alphabetical order
|
||||
for suggesting to implement the setup option "Recording/Record key handling"
|
||||
for suggesting to cache the channel/CAM relations in the file 'cam.data'
|
||||
|
||||
Stefan Schallenberg <infos@nafets.de>
|
||||
for adding the functions IndexOf(), InsertUnique(), AppendUnique() and RemoveElement()
|
||||
|
8
HISTORY
8
HISTORY
@ -8882,10 +8882,16 @@ Video Disk Recorder Revision History
|
||||
- Added a short sleep to cTSBuffer::Action() to avoid high CPU usage (thanks to
|
||||
Sergey Chernyavskiy).
|
||||
|
||||
2017-01-08: Version 2.3.3
|
||||
2017-01-09: Version 2.3.3
|
||||
|
||||
- Added 'S3W ABS-3A' to sources.conf (thanks to Frank Richter).
|
||||
- Fixed a possible deadlock in the recordings handler thread.
|
||||
- Updated the Russian OSD texts (thanks to Andrey Pridvorov).
|
||||
- Added a missing dependency to the Makefile to avoid error messages in the
|
||||
clean-plugins target (thanks to Tobias Grimm).
|
||||
- The channel/CAM relations (i.e. the information which CAM can decrypt a given
|
||||
channel) are now stored in the file 'cam.data' in the cache directory (suggested
|
||||
by Dietmar Spingler). This speeds up switching to encrypted channels after
|
||||
newly starting VDR, in case there is more than one CAM in the system.
|
||||
- Fixed a flaw in handling timeouts for encrypted channels.
|
||||
|
||||
|
61
ci.c
61
ci.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: ci.c 4.3 2016/12/23 14:00:45 kls Exp $
|
||||
* $Id: ci.c 4.4 2017/01/09 12:51:05 kls Exp $
|
||||
*/
|
||||
|
||||
#include "ci.h"
|
||||
@ -13,6 +13,7 @@
|
||||
#include <malloc.h>
|
||||
#include <netinet/in.h>
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <time.h>
|
||||
@ -2317,6 +2318,7 @@ void cChannelCamRelation::ClrDecrypt(int CamSlotNumber)
|
||||
|
||||
// --- cChannelCamRelations --------------------------------------------------
|
||||
|
||||
#define MAX_CAM_NUMBER 32
|
||||
#define CHANNEL_CAM_RELATIONS_CLEANUP_INTERVAL 3600 // seconds between cleanups
|
||||
|
||||
cChannelCamRelations ChannelCamRelations;
|
||||
@ -2414,3 +2416,60 @@ void cChannelCamRelations::ClrDecrypt(tChannelID ChannelID, int CamSlotNumber)
|
||||
if (ccr)
|
||||
ccr->ClrDecrypt(CamSlotNumber);
|
||||
}
|
||||
|
||||
void cChannelCamRelations::Load(const char *FileName)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
fileName = FileName;
|
||||
if (access(fileName, R_OK) == 0) {
|
||||
dsyslog("loading %s", *fileName);
|
||||
if (FILE *f = fopen(fileName, "r")) {
|
||||
cReadLine ReadLine;
|
||||
char *s;
|
||||
while ((s = ReadLine.Read(f)) != NULL) {
|
||||
if (char *p = strchr(s, ' ')) {
|
||||
*p = 0;
|
||||
if (*++p) {
|
||||
tChannelID ChannelID = tChannelID::FromString(s);
|
||||
if (ChannelID.Valid()) {
|
||||
char *q;
|
||||
char *strtok_next;
|
||||
while ((q = strtok_r(p, " ", &strtok_next)) != NULL) {
|
||||
int CamSlotNumber = atoi(q);
|
||||
if (CamSlotNumber >= 1 && CamSlotNumber <= MAX_CAM_NUMBER)
|
||||
SetDecrypt(ChannelID, CamSlotNumber);
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
else
|
||||
LOG_ERROR_STR(*fileName);
|
||||
}
|
||||
}
|
||||
|
||||
void cChannelCamRelations::Save(void)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
dsyslog("saving %s", *fileName);
|
||||
cSafeFile f(fileName);
|
||||
if (f.Open()) {
|
||||
for (cChannelCamRelation *ccr = First(); ccr; ccr = Next(ccr)) {
|
||||
if (ccr->ChannelID().Valid()) {
|
||||
cString s;
|
||||
for (int i = 1; i <= MAX_CAM_NUMBER; i++) {
|
||||
if (ccr->CamDecrypt(i))
|
||||
s = cString::sprintf("%s%s%d", *s ? *s : "", *s ? " " : "", i);
|
||||
}
|
||||
if (*s)
|
||||
fprintf(f, "%s %s\n", *ccr->ChannelID().ToString(), *s);
|
||||
}
|
||||
}
|
||||
f.Close();
|
||||
}
|
||||
else
|
||||
LOG_ERROR_STR(*fileName);
|
||||
}
|
||||
|
5
ci.h
5
ci.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: ci.h 3.11 2015/01/31 14:36:41 kls Exp $
|
||||
* $Id: ci.h 4.1 2017/01/09 12:51:05 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CI_H
|
||||
@ -310,6 +310,7 @@ class cChannelCamRelation;
|
||||
class cChannelCamRelations : public cList<cChannelCamRelation> {
|
||||
private:
|
||||
cMutex mutex;
|
||||
cString fileName;
|
||||
cChannelCamRelation *GetEntry(tChannelID ChannelID);
|
||||
cChannelCamRelation *AddEntry(tChannelID ChannelID);
|
||||
time_t lastCleanup;
|
||||
@ -323,6 +324,8 @@ public:
|
||||
void SetDecrypt(tChannelID ChannelID, int CamSlotNumber);
|
||||
void ClrChecked(tChannelID ChannelID, int CamSlotNumber);
|
||||
void ClrDecrypt(tChannelID ChannelID, int CamSlotNumber);
|
||||
void Load(const char *FileName);
|
||||
void Save(void);
|
||||
};
|
||||
|
||||
extern cChannelCamRelations ChannelCamRelations;
|
||||
|
27
device.c
27
device.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.c 4.3 2016/12/23 14:43:44 kls Exp $
|
||||
* $Id: device.c 4.4 2017/01/09 12:51:05 kls Exp $
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
@ -90,6 +90,7 @@ cDevice::cDevice(void)
|
||||
|
||||
camSlot = NULL;
|
||||
startScrambleDetection = 0;
|
||||
scramblingTimeout = 0;
|
||||
|
||||
occupiedTimeout = 0;
|
||||
|
||||
@ -1574,6 +1575,7 @@ bool cDevice::Receiving(bool Dummy) const
|
||||
|
||||
void cDevice::Action(void)
|
||||
{
|
||||
time_t LastScrambledPacket = 0;
|
||||
if (Running() && OpenDvr()) {
|
||||
while (Running()) {
|
||||
// Read data from the DVR device:
|
||||
@ -1590,15 +1592,16 @@ void cDevice::Action(void)
|
||||
cs = CamSlot();
|
||||
CamSlotNumber = cs ? cs->SlotNumber() : 0;
|
||||
if (CamSlotNumber) {
|
||||
int t = time(NULL) - startScrambleDetection;
|
||||
if (LastScrambledPacket < startScrambleDetection)
|
||||
LastScrambledPacket = startScrambleDetection;
|
||||
time_t Now = time(NULL);
|
||||
if (TsIsScrambled(b)) {
|
||||
if (t > TS_SCRAMBLING_TIMEOUT)
|
||||
LastScrambledPacket = Now;
|
||||
if (Now - startScrambleDetection > scramblingTimeout)
|
||||
DetachReceivers = true;
|
||||
}
|
||||
else if (t > TS_SCRAMBLING_TIME_OK) {
|
||||
if (Now - LastScrambledPacket > TS_SCRAMBLING_TIME_OK)
|
||||
DescramblingOk = true;
|
||||
startScrambleDetection = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Distribute the packet to all attached receivers:
|
||||
@ -1606,14 +1609,17 @@ void cDevice::Action(void)
|
||||
for (int i = 0; i < MAXRECEIVERS; i++) {
|
||||
if (receiver[i] && receiver[i]->WantsPid(Pid)) {
|
||||
if (DetachReceivers && cs && (!cs->IsActivating() || receiver[i]->Priority() >= LIVEPRIORITY)) {
|
||||
dsyslog("detaching receiver - won't decrypt channel %s with CAM %d", *receiver[i]->ChannelID().ToString(), CamSlotNumber);
|
||||
dsyslog("CAM %d: won't decrypt channel %s, detaching receiver", CamSlotNumber, *receiver[i]->ChannelID().ToString());
|
||||
ChannelCamRelations.SetChecked(receiver[i]->ChannelID(), CamSlotNumber);
|
||||
Detach(receiver[i]);
|
||||
}
|
||||
else
|
||||
receiver[i]->Receive(b, TS_SIZE);
|
||||
if (DescramblingOk)
|
||||
if (DescramblingOk) {
|
||||
dsyslog("CAM %d: decrypts channel %s", CamSlotNumber, *receiver[i]->ChannelID().ToString());
|
||||
ChannelCamRelations.SetDecrypt(receiver[i]->ChannelID(), CamSlotNumber);
|
||||
startScrambleDetection = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
@ -1673,6 +1679,11 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
|
||||
if (camSlot && Receiver->priority > MINPRIORITY) { // priority check to avoid an infinite loop with the CAM slot's caPidReceiver
|
||||
camSlot->StartDecrypting();
|
||||
startScrambleDetection = time(NULL);
|
||||
scramblingTimeout = TS_SCRAMBLING_TIMEOUT;
|
||||
bool KnownToDecrypt = ChannelCamRelations.CamDecrypt(Receiver->ChannelID(), camSlot->SlotNumber());
|
||||
if (KnownToDecrypt)
|
||||
scramblingTimeout *= 10; // give it time to receive ECM/EMM
|
||||
dsyslog("CAM %d: %sknown to decrypt channel %s (scramblingTimeout = %ds)", camSlot->SlotNumber(), KnownToDecrypt ? "" : "not ", *Receiver->ChannelID().ToString(), scramblingTimeout);
|
||||
}
|
||||
Start();
|
||||
return true;
|
||||
|
3
device.h
3
device.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.h 4.2 2016/12/06 14:12:39 kls Exp $
|
||||
* $Id: device.h 4.3 2017/01/09 12:51:05 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DEVICE_H
|
||||
@ -425,6 +425,7 @@ public:
|
||||
|
||||
private:
|
||||
time_t startScrambleDetection;
|
||||
int scramblingTimeout;
|
||||
cCamSlot *camSlot;
|
||||
public:
|
||||
virtual bool HasCi(void);
|
||||
|
16
vdr.5
16
vdr.5
@ -8,7 +8,7 @@
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" vdr distribution.
|
||||
.\"
|
||||
.\" $Id: vdr.5 3.4 2015/02/17 13:43:53 kls Exp $
|
||||
.\" $Id: vdr.5 4.1 2017/01/09 13:35:08 kls Exp $
|
||||
.\"
|
||||
.TH vdr 5 "19 Feb 2015" "2.2" "Video Disk Recorder Files"
|
||||
.SH NAME
|
||||
@ -899,6 +899,20 @@ Note that the \fBevent id\fR that comes from the DVB data stream is actually
|
||||
just 16 bit wide. The internal representation in VDR allows for 32 bit to
|
||||
be used, so that external tools can generate EPG data that is guaranteed
|
||||
not to collide with the ids of existing data.
|
||||
.SS CAM DATA
|
||||
The file \fIcam.data\fR contains information about which CAM in the system can
|
||||
decrypt a particular channel.
|
||||
Each line in this file contains a channel id, followed by one or more (blank
|
||||
separated) numbers, indicating the CAMs that have successfully decrypted this
|
||||
channel earlier.
|
||||
|
||||
When tuning to an encrypted channel, this information is used to select the
|
||||
proper CAM for decrypting this channel. This channel/CAM relationship is not
|
||||
hardcoded, though. If a given channel can't be decrypted with a CAM listed
|
||||
in this file, other CAMs will be tried just as well. The main purpose of this
|
||||
file is to speed up channel switching in systems with more than one CAM.
|
||||
|
||||
This file will be read at program startup and saved when the program ends.
|
||||
.SS COMMANDLINE OPTIONS
|
||||
If started without any options, vdr tries to read any files in the directory
|
||||
/etc/vdr/conf.d with names that do not begin with a '.' and that end with '.conf'.
|
||||
|
7
vdr.c
7
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.tvdr.de
|
||||
*
|
||||
* $Id: vdr.c 4.9 2016/12/23 14:34:37 kls Exp $
|
||||
* $Id: vdr.c 4.10 2017/01/09 13:22:09 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -878,6 +878,10 @@ int main(int argc, char *argv[])
|
||||
if (!cPositioner::GetPositioner()) // no plugin has created a positioner
|
||||
new cDiseqcPositioner;
|
||||
|
||||
// CAM data:
|
||||
|
||||
ChannelCamRelations.Load(AddDirectory(CacheDirectory, "cam.data"));
|
||||
|
||||
// Channel:
|
||||
|
||||
if (!cDevice::WaitForAllDevicesReady(DEVICEREADYTIMEOUT))
|
||||
@ -1555,6 +1559,7 @@ Exit:
|
||||
|
||||
StopSVDRPClientHandler();
|
||||
StopSVDRPServerHandler();
|
||||
ChannelCamRelations.Save();
|
||||
PluginManager.StopPlugins();
|
||||
cRecordControls::Shutdown();
|
||||
RecordingsHandler.DelAll();
|
||||
|
Loading…
Reference in New Issue
Block a user