Detecting whether a particular CAM actually decrypts a given channel is now done separately for each receiver

This commit is contained in:
Klaus Schmidinger 2017-04-02 10:08:49 +02:00
parent f39d31631b
commit 0a5a7893a5
5 changed files with 50 additions and 48 deletions

View File

@ -8938,3 +8938,5 @@ Video Disk Recorder Revision History
The members of cEvent have been slightly rearranged to minimize the memory
requirements on both 32 and 64 bit systems.
- The file 'cam.data' is no longer written if it is read-only.
- Detecting whether a particular CAM actually decrypts a given channel is now
done separately for each receiver.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.c 4.11 2017/03/27 14:02:54 kls Exp $
* $Id: device.c 4.12 2017/04/02 10:08:49 kls Exp $
*/
#include "device.h"
@ -89,8 +89,6 @@ cDevice::cDevice(void)
nitFilter = NULL;
camSlot = NULL;
startScrambleDetection = 0;
scramblingTimeout = 0;
occupiedTimeout = 0;
@ -253,7 +251,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView
if (CamSlot->ModuleStatus() == msReady) {
if (CamSlot->ProvidesCa(Channel->Caids())) {
if (!ChannelCamRelations.CamChecked(Channel->GetChannelID(), CamSlot->MasterSlotNumber())) {
SlotPriority[CamSlot->Index()] = CamSlot->Priority();
SlotPriority[CamSlot->Index()] = CamSlot->MtdActive() ? IDLEPRIORITY : CamSlot->Priority(); // we don't need to take the priority into account here for MTD CAM slots, because they can be used with several devices in parallel
NumUsableSlots++;
}
}
@ -1652,50 +1650,47 @@ 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:
uchar *b = NULL;
if (GetTSPacket(b)) {
if (b) {
int Pid = TsPid(b);
// Check whether the TS packets are scrambled:
bool DetachReceivers = false;
bool DescramblingOk = false;
int CamSlotNumber = 0;
cCamSlot *cs = NULL;
if (startScrambleDetection) {
cs = CamSlot();
CamSlotNumber = cs ? cs->MasterSlotNumber() : 0;
if (CamSlotNumber) {
if (LastScrambledPacket < startScrambleDetection)
LastScrambledPacket = startScrambleDetection;
time_t Now = time(NULL);
if (TsIsScrambled(b)) {
LastScrambledPacket = Now;
if (Now - startScrambleDetection > scramblingTimeout)
DetachReceivers = true;
}
if (Now - LastScrambledPacket > TS_SCRAMBLING_TIME_OK)
DescramblingOk = true;
}
}
// Distribute the packet to all attached receivers:
Lock();
int Pid = TsPid(b);
bool IsScrambled = TsIsScrambled(b);
for (int i = 0; i < MAXRECEIVERS; i++) {
if (receiver[i] && receiver[i]->WantsPid(Pid)) {
if (DetachReceivers && cs && (!cs->IsActivating() || receiver[i]->Priority() >= LIVEPRIORITY)) {
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 && receiver[i]->ChannelID().Valid()) {
dsyslog("CAM %d: decrypts channel %s", CamSlotNumber, *receiver[i]->ChannelID().ToString());
ChannelCamRelations.SetDecrypt(receiver[i]->ChannelID(), CamSlotNumber);
startScrambleDetection = 0;
cReceiver *Receiver = receiver[i];
if (Receiver && Receiver->WantsPid(Pid)) {
Receiver->Receive(b, TS_SIZE);
// Check whether the TS packet is scrambled:
if (Receiver->startScrambleDetection) {
if (cCamSlot *cs = CamSlot()) {
int CamSlotNumber = cs->MasterSlotNumber();
if (Receiver->lastScrambledPacket < Receiver->startScrambleDetection)
Receiver->lastScrambledPacket = Receiver->startScrambleDetection;
time_t Now = time(NULL);
if (IsScrambled) {
Receiver->lastScrambledPacket = Now;
if (Now - Receiver->startScrambleDetection > Receiver->scramblingTimeout) {
if (!cs->IsActivating() || Receiver->Priority() >= LIVEPRIORITY) {
if (Receiver->ChannelID().Valid()) {
dsyslog("CAM %d: won't decrypt channel %s, detaching receiver", CamSlotNumber, *Receiver->ChannelID().ToString());
ChannelCamRelations.SetChecked(Receiver->ChannelID(), CamSlotNumber);
}
Detach(Receiver);
}
}
}
else if (Now - Receiver->lastScrambledPacket > TS_SCRAMBLING_TIME_OK) {
if (Receiver->ChannelID().Valid()) {
dsyslog("CAM %d: decrypts channel %s", CamSlotNumber, *Receiver->ChannelID().ToString());
ChannelCamRelations.SetDecrypt(Receiver->ChannelID(), CamSlotNumber);
}
Receiver->startScrambleDetection = 0;
}
}
}
}
}
@ -1756,12 +1751,13 @@ 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();
if (CamSlots.NumReadyMasterSlots() > 1) { // don't try different CAMs if there is only one
startScrambleDetection = time(NULL);
scramblingTimeout = TS_SCRAMBLING_TIMEOUT;
Receiver->startScrambleDetection = time(NULL);
Receiver->scramblingTimeout = TS_SCRAMBLING_TIMEOUT;
bool KnownToDecrypt = ChannelCamRelations.CamDecrypt(Receiver->ChannelID(), camSlot->MasterSlotNumber());
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);
Receiver->scramblingTimeout *= 10; // give it time to receive ECM/EMM
if (Receiver->ChannelID().Valid())
dsyslog("CAM %d: %sknown to decrypt channel %s (scramblingTimeout = %ds)", camSlot->MasterSlotNumber(), KnownToDecrypt ? "" : "not ", *Receiver->ChannelID().ToString(), Receiver->scramblingTimeout);
}
}
Start();

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.h 4.4 2017/02/21 13:23:24 kls Exp $
* $Id: device.h 4.5 2017/04/02 10:08:49 kls Exp $
*/
#ifndef __DEVICE_H
@ -426,8 +426,6 @@ public:
// Common Interface facilities:
private:
time_t startScrambleDetection;
int scramblingTimeout;
cCamSlot *camSlot;
public:
virtual bool HasCi(void);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: receiver.c 4.2 2017/02/21 10:59:27 kls Exp $
* $Id: receiver.c 4.3 2017/04/02 10:08:49 kls Exp $
*/
#include "receiver.h"
@ -16,6 +16,9 @@ cReceiver::cReceiver(const cChannel *Channel, int Priority)
device = NULL;
SetPriority(Priority);
numPids = 0;
lastScrambledPacket = 0;
startScrambleDetection = 0;
scramblingTimeout = 0;
SetPids(Channel);
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: receiver.h 4.1 2015/09/05 11:42:47 kls Exp $
* $Id: receiver.h 4.2 2017/04/02 10:08:49 kls Exp $
*/
#ifndef __RECEIVER_H
@ -22,6 +22,9 @@ private:
int priority;
int pids[MAXRECEIVEPIDS];
int numPids;
time_t lastScrambledPacket;
time_t startScrambleDetection;
int scramblingTimeout;
bool WantsPid(int Pid);
protected:
cDevice *Device(void) { return device; }