📄 shl.c
字号:
/* * Softcam plugin to VDR (C++) * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */#include <stdio.h>#include <string.h>#include <errno.h>#include <malloc.h>#include <sys/ioctl.h>#include <sys/poll.h>#include <linux/dvb/dmx.h>#include <openssl/des.h>#include "system-common.h"#include "data.h"#include "filter.h"#include "misc.h"#include "log-sys.h"#define SYSTEM_SHL 0x4A60#define SYSTEM_NAME "@SHL"#define SYSTEM_PRI -10#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_SHL)#define L_SYS 15#define L_SYS_HOPPER LCLASS(L_SYS,L_SYS_LASTDEF<<1)#define L_SYS_HSTATS LCLASS(L_SYS,L_SYS_LASTDEF<<2)#define L_SYS_ALL LALL(L_SYS_HSTATS)static const struct LogModule lm_sys = { (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK, (LMOD_ENABLE|L_SYS_DEFDEF)&LOPT_MASK, "shl", { L_SYS_DEFNAMES,"pidHopper","hopperStats" } };ADD_MODULE(L_SYS,lm_sys)// evil hack, but it's not worth to put much effort in a dead system ...static cTimeMs __time;#define time_ms() ((int)__time.Elapsed())static cPlainKeyTypeReg<cPlainKeyStd,'Z',false> KeyReg;// -- cPesFilter ---------------------------------------------------------------class cPesFilter : public cPidFilter {public: cPesFilter(const char *Id, int Num, int DvbNum, int IdleTime); virtual void Start(int Pid, int Section, int Mask, int Mode, bool Crc); };cPesFilter::cPesFilter(const char *Id, int Num, int DvbNum, int IdleTime):cPidFilter(Id,Num,DvbNum,IdleTime){}void cPesFilter::Start(int Pid, int Section, int Mask, int Mode, bool Crc){ if(fd>=0) { Stop(); struct dmx_pes_filter_params FilterParams; FilterParams.input=DMX_IN_FRONTEND; FilterParams.output=DMX_OUT_TAP; FilterParams.pes_type=DMX_PES_OTHER; FilterParams.flags=DMX_IMMEDIATE_START; FilterParams.pid=Pid; CHECK(ioctl(fd,DMX_SET_PES_FILTER,&FilterParams)); pid=Pid; active=true; }}// -- cPidHopper ---------------------------------------------------------------struct FilterPacket { struct FilterPacket *next; int lastTime, dataLen; unsigned char lastData[1]; }; struct FilterData { cPidFilter *filter; int lastTime, lastRead, createTime, readCount; struct FilterPacket *first, *last; };class cPidHopper : public cAction {private: struct FilterData *d; int numFilters; cMutex sleepMutex; cCondVar sleep; // void PurgeFilter(struct FilterData *dd); void PurgePacket(struct FilterData *dd, struct FilterPacket *p);protected: virtual void Process(cPidFilter *filter, unsigned char *data, int len); virtual cPidFilter *CreateFilter(const char *Id, int Num, int DvbNum, int IdleTime);public: cPidHopper(int DvbNum, int NumFilters); virtual ~cPidHopper(); int Read(int pid, int & now, unsigned char *buff, int len, int timeout); bool AddPid(int pid); void CutOff(int now); };cPidHopper::cPidHopper(int DvbNum, int NumFilters):cAction("pidhopper",DvbNum){ numFilters=NumFilters; d=MALLOC(struct FilterData,NumFilters); memset(d,0,sizeof(struct FilterData)*NumFilters); PRINTF(L_SYS_HOPPER,"pid hopper started (%d filters)",numFilters);}cPidHopper::~cPidHopper(){ Lock(); int now=time_ms(), num=1; PRINTF(L_SYS_HSTATS,"active pids: (now=%d)\n",now); for(int i=0; i<numFilters; i++) { struct FilterData *dd=&d[i]; if(dd->filter) { if(dd->filter->Pid()>=0) PRINTF(L_SYS_HSTATS,"%2d. pid %04x lastTime=%4d lastRead=%4d created=%4d count=%4d", num++, dd->filter->Pid(), dd->lastTime>0 ? (now-dd->lastTime)/1000 : -1, dd->lastRead>0 ? (now-dd->lastRead)/1000 : -1, dd->createTime>0 ? (now-dd->createTime)/1000 : -1, dd->readCount); DelFilter(dd->filter); dd->filter=0; } PurgeFilter(dd); } Unlock(); free(d);}void cPidHopper::PurgeFilter(struct FilterData *dd){ if(dd->first && dd->last) PurgePacket(dd,dd->last);}void cPidHopper::PurgePacket(struct FilterData *dd, struct FilterPacket *p){ while(dd->first) { struct FilterPacket *del=dd->first; dd->first=del->next; if(dd->filter) PRINTF(L_SYS_HOPPER,"PID %04x purging packet %p (time=%d)",dd->filter->Pid(),del,del->lastTime); free(del); if(del==p) break; } if(!dd->first) dd->last=0;}void cPidHopper::CutOff(int now){ Lock(); PRINTF(L_SYS_HOPPER,"cutoff (now=%d)",now); for(int i=0; i<numFilters; i++) { struct FilterData *dd=&d[i]; struct FilterPacket *p=dd->first, *del=0; while(p) { if(p->lastTime>=now) break; del=p; p=p->next; } if(del) { PurgePacket(dd,del); dd->lastTime=dd->first ? dd->first->lastTime : -1; } } Unlock();}cPidFilter *cPidHopper::CreateFilter(const char *Id, int Num, int DvbNum, int IdleTime){ cPidFilter *filter=new cPesFilter(Id,Num,DvbNum,IdleTime); d[Num].filter=filter; d[Num].lastTime=-1; d[Num].lastRead=-1; d[Num].createTime=time_ms(); d[Num].readCount=0; d[Num].first=0; d[Num].last=0; return filter;}void cPidHopper::Process(cPidFilter *filter, unsigned char *data, int len){ if(data && len>0) { int now=time_ms(); for(int i=0; i<numFilters; i++) if(d[i].filter==filter) { do { int l=min(len,184); struct FilterPacket *p=(struct FilterPacket *)malloc(sizeof(struct FilterPacket)+l-1); if(p) { p->next=0; memcpy(p->lastData,data,l); p->dataLen=l; p->lastTime=now; if(d[i].first) d[i].last->next=p; else { d[i].first=p; d[i].lastTime=now; } d[i].last=p; PRINTF(L_SYS_HOPPER,"PID %04x queued packet %p (time=%d len=%d) (%s)",d[i].filter->Pid(),p,p->lastTime,l,d[i].first==p?"first":"queue"); } len-=l; data+=l; } while(len>0); sleep.Broadcast(); break; } }}bool cPidHopper::AddPid(int pid){ cPidFilter *filter=NewFilter(0); if(!filter) return false; filter->Start(pid,0,0,0,false); return true;}int cPidHopper::Read(int pid, int & now, unsigned char *buff, int len, int timeout){ Lock(); timeout+=time_ms(); PRINTF(L_SYS_HOPPER,"PID %04x read (now=%d)",pid,now); int n=-1; while(time_ms()<timeout) { struct FilterData *dd=0, *old=0; for(int i=0; i<numFilters; i++) if(d[i].filter) { if(d[i].filter->Pid()==pid) { dd=&d[i]; break; } if(!old || (d[i].lastRead<0 && d[i].createTime<old->createTime) || (d[i].lastRead>=0 && d[i].lastRead<old->lastRead)) old=&d[i]; } if(!dd) { LBSTARTF(L_SYS_VERBOSE); LBPUT("NEW "); if(!AddPid(pid)) { if(!old) break; LBPUT("{0x%04x/%d/%d} ",old->filter->Pid(),old->lastRead>0 ? (time_ms()-old->lastRead)/1000:-1,old->lastTime>0 ? (time_ms()-old->lastTime)/1000:-1); old->filter->Stop(); // purge LRU filter PurgeFilter(old); old->lastTime=-1; old->lastRead=-1; old->createTime=time_ms(); old->readCount=0; old->filter->Start(pid,0,0,0,false); } LBEND(); continue; } for(struct FilterPacket *p=dd->first; p; p=p->next) { if(p->lastTime>=now) { n=min(len,p->dataLen); memcpy(buff,p->lastData,n); now=p->lastTime; PRINTF(L_SYS_HOPPER,"PID %04x returning packet %p (time=%d)",dd->filter->Pid(),p,p->lastTime); PurgePacket(dd,p); dd->lastRead=time_ms(); dd->readCount++; dd->lastTime=dd->first ? dd->first->lastTime : -1; break; } else { PRINTF(L_SYS_HOPPER,"PID %04x skipping packet %p (time=%d)",dd->filter->Pid(),p,p->lastTime); if(!p->next) { PRINTF(L_SYS_HOPPER,"PID %04x queue empty",dd->filter->Pid()); PurgePacket(dd,p); break; } } } if(n>0) break; Unlock(); sleepMutex.Lock(); sleep.TimedWait(sleepMutex,200); sleepMutex.Unlock(); Lock(); } Unlock(); return n;}// -- cShl ---------------------------------------------------------------------class cShl {private: DES_key_schedule sched;public: void SetKey( const unsigned char *key); void Decode(unsigned char *data, int n); };void cShl::SetKey(const unsigned char *key){ DES_key_sched((DES_cblock *)key,&sched);}void cShl::Decode(unsigned char *data, int n){ int r=n&7; n-=r;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -