📄 tps.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 <stdlib.h>#include <unistd.h>#include <string.h>#include <libsi/section.h>#include "viaccess.h"#include "log-viaccess.h"#include "tps.h"#include "opentv.h"#include "st20.h"#include "sc.h"#include "scsetup.h"#include "system-common.h"#include "filter.h"#include "misc.h"#include "helper.h"#define CHECK_TIME 5*60*1000#define LOADBIN_TIME 60*60*1000#define TPSAU_TIME 30*60*1000//#define TRUST_BOXTIME // should we trust the local time on this machine?//#define DUMP_TPSAU "/var/tmp"// -- cRC6 ---------------------------------------------------------------------/* * This code implements the RC6-32/20 block cipher. * * The algorithm is due to Ron Rivest and RSA Labs. This code is based on code * which was written by Martin Hinner <mhi@penguin.cz> in 1999, no copyright is * claimed. */#define RC6_WORDSIZE 32#define RC6_P32 0xB7E15163L#define RC6_Q32 0x9E3779B9Lunsigned int cRC6::rol(unsigned int v, unsigned int cnt){ cnt&=(RC6_WORDSIZE-1); return (v<<cnt) | (v>>(RC6_WORDSIZE-cnt));}unsigned int cRC6::ror(unsigned int v, unsigned int cnt){ cnt&=(RC6_WORDSIZE-1); return (v>>cnt) | (v<<(RC6_WORDSIZE-cnt));}void cRC6::SetKey(const unsigned char *Key, int len){ key[0]=RC6_P32; for(int v=1; v<RC6_MAX; v++) key[v]=key[v-1]+RC6_Q32; len/=4; unsigned int a=0, b=0, l[len]; memcpy(l,Key,len*4); for(int i=0,j=0,v=3*(len>RC6_MAX ? len : RC6_MAX) ; v>0; v--) { a=key[i]=rol(key[i]+a+b,3); b= l[j]=rol( l[j]+a+b,a+b); i++; i%=RC6_MAX; j++; j%=len; }}void cRC6::Decrypt(unsigned char *data){ unsigned int *l=(unsigned int *)data; unsigned int a, b, c, d; a=l[0]-key[RC6_MAX-2]; b=l[1]; c=l[2]-key[RC6_MAX-1]; d=l[3]; for(int i=RC6_ROUNDS; i>0; i--) { unsigned int t=a; unsigned int u=b; a=d; d=c; b=t; c=u; u=rol((d*(2*d+1)),5); t=rol((b*(2*b+1)),5); c=ror(c-key[2*i+1],t)^u; a=ror(a-key[2*i ],u)^t; } l[0]=a; l[1]=b-key[0]; l[2]=c; l[3]=d-key[1];}// -- cTransponderTime ---------------------------------------------------------class cTransponderTime : public cSimpleItem {private: time_t sattime; cTimeMs reftime; cMutex mutex; cCondVar wait; int source, transponder; bool hasHandler;public: cTransponderTime(int Source, int Transponder); bool Is(int Source, int Transponder) const; void Set(time_t st); time_t Now(void); void SetHasHandler(bool on) { hasHandler=on; } bool HasHandler(void) const { return hasHandler; } };cTransponderTime::cTransponderTime(int Source, int Transponder){ source=Source; transponder=Transponder;#ifdef TRUST_BOXTIME sattime=time(0);#else sattime=-1;#endif hasHandler=false;}bool cTransponderTime::Is(int Source, int Transponder) const{ return source==Source && transponder==Transponder;}void cTransponderTime::Set(time_t st){ cMutexLock lock(&mutex); if(sattime<0 || reftime.Elapsed()>5*1000) { reftime.Set(-100); sattime=st; wait.Broadcast(); char str[32]; struct tm utm; st=Now(); time_t now=time(0); gmtime_r(&st,&utm); asctime_r(&utm,str); stripspace(str); PRINTF(L_SYS_TIME,"%x:%x: %s (delta %ld)",source,transponder,str,st-now); }}time_t cTransponderTime::Now(void){ cMutexLock lock(&mutex); if(sattime<0) { if(!wait.TimedWait(mutex,3*1000)) { PRINTF(L_SYS_TIME,"%x:%x: unsuccessfull wait",source,transponder); return -1; } } return sattime+(reftime.Elapsed()/1000);}// -- cSatTimeHook -------------------------------------------------------------class cSatTimeHook : public cLogHook {private: cTransponderTime *ttime;public: cSatTimeHook(cTransponderTime *Ttime); ~cSatTimeHook(); virtual void Process(int pid, unsigned char *data); };cSatTimeHook::cSatTimeHook(cTransponderTime *Ttime):cLogHook(HOOK_SATTIME,"sattime"){ ttime=Ttime; pids.AddPid(0x14,0x71,0xff,0x03); ttime->SetHasHandler(true);}cSatTimeHook::~cSatTimeHook(){ ttime->SetHasHandler(false);}void cSatTimeHook::Process(int pid, unsigned char *data){ if(data && ttime) { if(data[0]==0x70) { // TDT SI::TDT tdt(data,false); tdt.CheckParse(); ttime->Set(tdt.getTime()); } else if(data[0]==0x73) { // TOT SI::TOT tot(data,false); if(!tot.CheckCRCAndParse()) return; ttime->Set(tot.getTime()); } }}// -- cSatTime -----------------------------------------------------------------class cSatTime {private: static cMutex mutex; static cSimpleList<cTransponderTime> list; // int cardNum; cTransponderTime *ttime; // void CheckHandler(void);public: cSatTime(int CardNum, int Source, int Transponder); time_t Now(void); };cMutex cSatTime::mutex;cSimpleList<cTransponderTime> cSatTime::list;cSatTime::cSatTime(int CardNum, int Source, int Transponder){ cardNum=CardNum; cMutexLock lock(&mutex); for(ttime=list.First(); ttime; ttime=list.Next(ttime)) if(ttime->Is(Source,Transponder)) break; if(!ttime) { ttime=new cTransponderTime(Source,Transponder); if(ttime) list.Add(ttime); PRINTF(L_SYS_TIME,"%x:%x: created new transpondertime",Source,Transponder); } else PRINTF(L_SYS_TIME,"%x:%x: using existing transpondertime",Source,Transponder); CheckHandler();}time_t cSatTime::Now(void){ CheckHandler(); return ttime ? ttime->Now() : -1;}void cSatTime::CheckHandler(void){ if(ttime) { if(!cSoftCAM::TriggerHook(cardNum,HOOK_SATTIME) && !ttime->HasHandler()) { cSatTimeHook *hook=new cSatTimeHook(ttime); cSoftCAM::AddHook(cardNum,hook); PRINTF(L_SYS_TIME,"added hook"); } }}// -- cOpenTVModule ------------------------------------------------------------class cOpenTVModule {private: int id, modlen; unsigned char *mem; int received; info_header_t info; code_header_t code; data_header_t data; // bool Decompress(void); bool DoDecompress(unsigned char *out_ptr, const unsigned char *in_ptr, int dsize, int data_size, int usize); bool ParseSections(void); void Dump(void);public: cOpenTVModule(const unsigned char *data); ~cOpenTVModule(); int AddPart(const unsigned char *data, int len); const info_header_t *InfoHdr(void) const { return &info; } const code_header_t *CodeHdr(void) const { return &code; } const data_header_t *DataHdr(void) const { return &data; } // inline static int Id(const unsigned char *data) { return UINT16_BE(&data[3]); } inline static int Offset(const unsigned char *data) { return UINT32_BE(&data[16]); } inline static int Length(const unsigned char *data) { return UINT32_BE(&data[20]); } };cOpenTVModule::cOpenTVModule(const unsigned char *data){ id=Id(data); modlen=Length(data); received=0; mem=MALLOC(unsigned char,modlen);}cOpenTVModule::~cOpenTVModule(){ free(mem);}int cOpenTVModule::AddPart(const unsigned char *data, int slen){ if(Id(data)==id) { int off=Offset(data); int mlen=Length(data); int rec=slen-28; if(mlen!=modlen || (off+rec)>mlen || !mem) { PRINTF(L_SYS_TPSAU,"length mismatch while adding to OpenTV module"); return -1; } memcpy(&mem[off],data+24,rec); received+=rec; if(received==mlen) { if(!Decompress()) { PRINTF(L_SYS_TPSAU,"failed to decompress OpenTV module"); return -1; } if(!ParseSections()) { PRINTF(L_SYS_TPSAU,"DATA & CODE section not located in OpenTV module"); return -1; } Dump(); return 1; } } return 0;}void cOpenTVModule::Dump(void){#ifdef DUMP_TPSAU#warning Dumping TPS AU data { char fname[32]; snprintf(fname,sizeof(fname),"%s/decomp.bin.%d.%x",DUMP_TPSAU,getpid(),(int)time(0)); int fd=open(fname,O_CREAT|O_TRUNC|O_WRONLY,DEFFILEMODE); if(fd>=0) { write(fd,mem,modlen); close(fd); PRINTF(L_SYS_TPSAU,"dumped to file '%s'",fname); } }#endif}bool cOpenTVModule::ParseSections(void){ int sections=0; for(int idx=0; idx<modlen;) { unsigned int hdr=UINT32_BE(mem+idx); unsigned int s_len=UINT32_BE(mem+idx+4); switch(hdr) { case INFO_SECTION_HDR: info.magic=hdr; info.bsssize=UINT32_BE(mem+idx+8); info.stacksize=UINT32_BE(mem+idx+12); sections|=1; break; case CODE_SECTION_HDR: code.magic=hdr; code.size=s_len-8; code.m_id=UINT32_BE(mem+idx+8); code.entry_point=UINT16_BE(mem+idx+12); code.end=UINT16_BE(mem+idx+14); code.code=mem+idx+8; sections|=2; break; case DATA_SECTION_HDR: data.magic=hdr; data.dlen=s_len-8; data.data=mem+idx+8; sections|=4; break; case SWAP_SECTION_HDR: case GDBO_SECTION_HDR: break; case LAST_SECTION_HDR: case 0: idx=modlen; break; case COMP_SECTION_HDR: PRINTF(L_GEN_DEBUG,"OpenTV module still compressed in ParseSections()"); return 0; default: PRINTF(L_SYS_TPSAU,"unknown section hdr %08x (%c%c%c%c) in OpenTV module",hdr,(hdr>>24)&0xFF,(hdr>>16)&0xFF,(hdr>>8)&0xFF,hdr&0xFF); break; } idx+=s_len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -