1 #define MODULE_LOG_PREFIX "emmcache"
4 #include "oscam-config.h"
5 #include "oscam-string.h"
6 #include "oscam-emm-cache.h"
7 #include "oscam-files.h"
8 #include "oscam-time.h"
9 #include "oscam-lock.h"
10 #include "cscrypt/md5.h"
12 #define DEFAULT_LOCK_TIMEOUT 1000000
14 static LLIST
*emm_cache
;
16 bool emm_cache_configured(void)
20 LL_ITER itr
= ll_iter_create(configured_readers
);
21 while((rdr
= ll_iter_next(&itr
)))
31 void emm_save_cache(void)
33 if(boxtype_is("dbox2")) return; // don't save emmcache on these boxes, they lack resources and will crash!
35 if(!emm_cache_configured()){
36 cs_log("saving emmcache disabled since no reader is using it!");
45 get_tmp_dir_filename(fname
, sizeof(fname
), "oscam.emmcache");
49 get_config_filename(fname
, sizeof(fname
), "oscam.emmcache");
51 FILE *file
= fopen(fname
, "w");
55 cs_log("can't write emmcache to file %s", fname
);
60 int32_t count
= 0, result
= 0;
61 LL_ITER it
= ll_iter_create(emm_cache
);
64 while((c
= ll_iter_next(&it
)))
66 uint8_t tmp_emmd5
[MD5_DIGEST_LENGTH
* 2 + 1];
67 char_to_hex(c
->emmd5
, MD5_DIGEST_LENGTH
, tmp_emmd5
);
68 uint8_t tmp_emm
[c
->len
* 2 + 1];
69 char_to_hex(c
->emm
, c
->len
, tmp_emm
);
71 result
= fprintf(file
, "%s,%ld,%ld,%02X,%04X,%s\n", tmp_emmd5
, c
->firstseen
.time
, c
->lastseen
.time
, c
->type
, c
->len
, tmp_emm
);
75 result
= remove(fname
);
78 cs_log("error writing cache -> cache file removed!");
82 cs_log("error writing cache -> cache file could not be removed either!");
91 int64_t load_time
= comp_timeb(&te
, &ts
);
92 cs_log("saved %d emmcache records to %s in %"PRId64
" ms", count
, fname
, load_time
);
95 void load_emmstat_from_file(void)
97 if(boxtype_is("dbox2")) return; // dont load emmstat on these boxes, they lack resources and will crash!
99 if(!emm_cache_configured()){
100 cs_log("loading emmstats disabled since no reader is using it!");
111 get_tmp_dir_filename(fname
, sizeof(fname
), "oscam.emmstat");
115 get_config_filename(fname
, sizeof(fname
), "oscam.emmstat");
118 file
= fopen(fname
, "r");
121 cs_log_dbg(D_TRACE
, "can't read emmstats from file %s", fname
);
125 if(!cs_malloc(&line
, LINESIZE
))
134 struct s_reader
*rdr
= NULL
;
140 char *ptr
, *saveptr1
= NULL
;
143 while(fgets(line
, LINESIZE
, file
))
145 if(!line
[0] || line
[0] == '#' || line
[0] == ';')
148 if(!cs_malloc(&s
, sizeof(struct s_emmstat
)))
151 for(i
= 0, ptr
= strtok_r(line
, ",", &saveptr1
); ptr
&& i
< 7 ; ptr
= strtok_r(NULL
, ",", &saveptr1
), i
++)
157 cs_strncpy(buf
, split
[0], sizeof(buf
));
158 key_atob_l(split
[1], s
->emmd5
, MD5_DIGEST_LENGTH
* 2);
159 s
->firstwritten
.time
= atol(split
[2]);
160 s
->lastwritten
.time
= atol(split
[3]);
161 s
->type
= a2i(split
[4], 2);
162 s
->count
= a2i(split
[5], 4);
164 LL_ITER itr
= ll_iter_create(configured_readers
);
166 while((rdr
= ll_iter_next(&itr
)))
168 if(rdr
->cachemm
!=1) // skip: emmcache save is disabled
173 if(strcmp(rdr
->label
, buf
) == 0)
183 rdr
->emmstat
= ll_create("emmstat");
184 cs_lock_create(__func__
, &rdr
->emmstat_lock
, rdr
->label
, DEFAULT_LOCK_TIMEOUT
);
187 ll_append(rdr
->emmstat
, s
);
192 cs_log("emmstats could not be loaded for %s", buf
);
198 cs_log_dbg(D_EMM
, "emmstat ERROR: %s count=%d type=%d", buf
, s
->count
, s
->type
);
207 int64_t load_time
= comp_timeb(&te
, &ts
);
208 cs_log("loaded %d emmstat records from %s in %"PRId64
" ms", count
, fname
, load_time
);
211 void save_emmstat_to_file(void)
213 if(boxtype_is("dbox2")) return; // don't save emmstat on these boxes, they lack resources and will crash!
215 if(!emm_cache_configured())
217 cs_log("saving emmstats disabled since no reader is using it!");
225 get_tmp_dir_filename(fname
, sizeof(fname
), "oscam.emmstat");
229 get_config_filename(fname
, sizeof(fname
), "oscam.emmstat");
231 FILE *file
= fopen(fname
, "w");
235 cs_log("can't write to file %s", fname
);
242 int32_t count
= 0, result
= 0;
243 struct s_reader
*rdr
;
244 LL_ITER itr
= ll_iter_create(configured_readers
);
245 while((rdr
= ll_iter_next(&itr
)))
247 if(!rdr
->cachemm
|| rdr
->cachemm
== 2)
249 cs_log("reader %s skipped since emmcache save is disabled", rdr
->label
);
255 cs_writelock(__func__
, &rdr
->emmstat_lock
);
256 LL_ITER it
= ll_iter_create(rdr
->emmstat
);
258 while((s
= ll_iter_next(&it
)))
260 uint8_t tmp_emmd5
[MD5_DIGEST_LENGTH
* 2 + 1];
261 char_to_hex(s
->emmd5
, MD5_DIGEST_LENGTH
, tmp_emmd5
);
262 result
= fprintf(file
, "%s,%s,%ld,%ld,%02X,%04X\n", rdr
->label
, tmp_emmd5
, s
->firstwritten
.time
, s
->lastwritten
.time
, s
->type
, s
->count
);
265 cs_writeunlock(__func__
, &rdr
->emmstat_lock
);
267 result
= remove(fname
);
270 cs_log("error writing stats -> stat file removed!");
274 cs_log("error writing stats -> stat file could not be removed either!");
280 cs_writeunlock(__func__
, &rdr
->emmstat_lock
);
287 int64_t load_time
= comp_timeb(&te
, &ts
);
289 cs_log("saved %d emmstat records to %s in %"PRId64
" ms", count
, fname
, load_time
);
292 void emm_load_cache(void)
294 if(boxtype_is("dbox2")) return; // don't load emmcache on these boxes, they lack resources and will crash!
296 if(!emm_cache_configured()){
297 cs_log("loading emmcache disabled since no reader is using it!");
304 struct s_emmcache
*c
;
308 get_tmp_dir_filename(fname
, sizeof(fname
), "oscam.emmcache");
312 get_config_filename(fname
, sizeof(fname
), "oscam.emmcache");
315 file
= fopen(fname
, "r");
318 cs_log_dbg(D_TRACE
, "can't read emmcache from file %s", fname
);
328 char *ptr
, *saveptr1
= NULL
;
331 memset(line
, 0, sizeof(line
));
332 while(fgets(line
, sizeof(line
), file
))
334 if(!line
[0] || line
[0] == '#' || line
[0] == ';')
337 for(i
= 0, ptr
= strtok_r(line
, ",", &saveptr1
); ptr
&& i
< 7 ; ptr
= strtok_r(NULL
, ",", &saveptr1
), i
++)
345 if(!cs_malloc(&c
, sizeof(struct s_emmcache
)))
347 key_atob_l(split
[0], c
->emmd5
, MD5_DIGEST_LENGTH
*2);
348 c
->firstseen
.time
= atol(split
[1]);
349 c
->lastseen
.time
= atol(split
[2]);
350 c
->type
= a2i(split
[3], 2);
351 c
->len
= a2i(split
[4], 4);
352 key_atob_l(split
[5], c
->emm
, c
->len
*2);
354 if(valid
&& c
->len
!= 0)
358 emm_cache
= ll_create("emm cache");
361 ll_append(emm_cache
, c
);
372 int64_t load_time
= comp_timeb(&te
, &ts
);
373 cs_log("loaded %d emmcache records from %s in %"PRId64
" ms", count
, fname
, load_time
);
376 struct s_emmcache
*find_emm_cache(uint8_t *emmd5
)
378 struct s_emmcache
*c
;
382 { emm_cache
= ll_create("emm cache"); }
384 it
= ll_iter_create(emm_cache
);
385 while((c
= ll_iter_next(&it
)))
387 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
389 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "found emmcache match");
396 int32_t clean_stale_emm_cache_and_stat(uint8_t *emmd5
, int64_t gone
)
402 struct s_emmcache
*c
;
406 { emm_cache
= ll_create("emm cache"); }
408 it
= ll_iter_create(emm_cache
);
409 while((c
= ll_iter_next(&it
)))
411 if(comp_timeb(&now
, &c
->lastseen
) > gone
&& memcmp(c
->emmd5
, emmd5
, MD5_DIGEST_LENGTH
)) // clean older than gone ms and dont clean if its the current emm!
413 struct s_reader
*rdr
;
414 LL_ITER rdr_itr
= ll_iter_create(configured_readers
);
415 while((rdr
= ll_iter_next(&rdr_itr
)))
417 if(rdr
->emmstat
&& !(caid_is_irdeto(rdr
->caid
) || caid_is_videoguard(rdr
->caid
)))
419 remove_emm_stat(rdr
, c
->emmd5
); // clean stale entry from stats
423 ll_iter_remove_data(&it
); // clean stale entry from emmcache
429 int32_t emm_edit_cache(uint8_t *emmd5
, EMM_PACKET
*ep
, bool add
)
431 struct s_emmcache
*c
;
436 { emm_cache
= ll_create("emm cache"); }
438 it
= ll_iter_create(emm_cache
);
439 while((c
= ll_iter_next(&it
)))
441 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
445 return 0; // already added
447 ll_iter_remove_data(&it
);
454 if(!cs_malloc(&c
, sizeof(struct s_emmcache
)))
456 memcpy(c
->emmd5
, emmd5
, MD5_DIGEST_LENGTH
);
458 c
->len
= SCT_LEN(ep
->emm
);
459 cs_ftime(&c
->firstseen
);
460 c
->lastseen
= c
->firstseen
;
461 memcpy(c
->emm
, ep
->emm
, c
->len
);
462 ll_append(emm_cache
, c
);
464 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "added emm to cache:");
472 int32_t remove_emm_stat(struct s_reader
*rdr
, uint8_t *emmd5
)
475 if(rdr
&& rdr
->emmstat
)
477 cs_writelock(__func__
, &rdr
->emmstat_lock
);
479 LL_ITER itr
= ll_iter_create(rdr
->emmstat
);
480 while((c
= ll_iter_next(&itr
)))
482 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
484 ll_iter_remove_data(&itr
);
490 cs_writeunlock(__func__
, &rdr
->emmstat_lock
);
495 struct s_emmstat
*get_emm_stat(struct s_reader
*rdr
, uint8_t *emmd5
, uint8_t emmtype
)
497 if(!rdr
->cachemm
) return NULL
;
503 { rdr
->emmstat
= ll_create("emm stat"); }
505 it
= ll_iter_create(rdr
->emmstat
);
506 while((c
= ll_iter_next(&it
)))
508 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
510 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "found emmstat match (reader:%s, count:%d)", rdr
->label
, c
->count
);
515 if(cs_malloc(&c
, sizeof(struct s_emmstat
)))
517 memcpy(c
->emmd5
, emmd5
, MD5_DIGEST_LENGTH
);
519 ll_append(rdr
->emmstat
, c
);
520 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "added emmstat (reader:%s, count:%d)", rdr
->label
, c
->count
);