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 static char *get_emmcache_filename(char *dest
, size_t destlen
, const char *filename
)
33 const char *slash
= "";
34 if(cfg
.emmlogdir
[strlen(cfg
.emmlogdir
) - 1] != '/')
38 snprintf(dest
, destlen
, "%s%s%s", cfg
.emmlogdir
, slash
, filename
);
42 void emm_save_cache(void)
44 if(boxtype_is("dbox2")) return; // don't save emmcache on these boxes, they lack resources and will crash!
46 if(!emm_cache_configured()){
47 cs_log("saving emmcache disabled since no reader is using it!");
56 get_emmcache_filename(fname
, sizeof(fname
), "oscam.emmcache");
60 get_config_filename(fname
, sizeof(fname
), "oscam.emmcache");
62 FILE *file
= fopen(fname
, "w");
66 cs_log("can't write emmcache to file %s", fname
);
71 int32_t count
= 0, result
= 0;
72 LL_ITER it
= ll_iter_create(emm_cache
);
75 while((c
= ll_iter_next(&it
)))
77 uint8_t tmp_emmd5
[MD5_DIGEST_LENGTH
* 2 + 1];
78 char_to_hex(c
->emmd5
, MD5_DIGEST_LENGTH
, tmp_emmd5
);
79 uint8_t tmp_emm
[c
->len
* 2 + 1];
80 char_to_hex(c
->emm
, c
->len
, tmp_emm
);
82 result
= fprintf(file
, "%s,%ld,%ld,%02X,%04X,%s\n", tmp_emmd5
, c
->firstseen
.time
, c
->lastseen
.time
, c
->type
, c
->len
, tmp_emm
);
86 result
= remove(fname
);
89 cs_log("error writing cache -> cache file removed!");
93 cs_log("error writing cache -> cache file could not be removed either!");
102 int64_t load_time
= comp_timeb(&te
, &ts
);
103 cs_log("saved %d emmcache records to %s in %"PRId64
" ms", count
, fname
, load_time
);
106 void load_emmstat_from_file(void)
108 if(boxtype_is("dbox2")) return; // dont load emmstat on these boxes, they lack resources and will crash!
110 if(!emm_cache_configured()){
111 cs_log("loading emmstats disabled since no reader is using it!");
122 get_emmcache_filename(fname
, sizeof(fname
), "oscam.emmstat");
126 get_config_filename(fname
, sizeof(fname
), "oscam.emmstat");
129 file
= fopen(fname
, "r");
132 cs_log_dbg(D_TRACE
, "can't read emmstats from file %s", fname
);
136 if(!cs_malloc(&line
, LINESIZE
))
145 struct s_reader
*rdr
= NULL
;
151 char *ptr
, *saveptr1
= NULL
;
154 while(fgets(line
, LINESIZE
, file
))
156 if(!line
[0] || line
[0] == '#' || line
[0] == ';')
159 if(!cs_malloc(&s
, sizeof(struct s_emmstat
)))
162 for(i
= 0, ptr
= strtok_r(line
, ",", &saveptr1
); ptr
&& i
< 7 ; ptr
= strtok_r(NULL
, ",", &saveptr1
), i
++)
168 cs_strncpy(buf
, split
[0], sizeof(buf
));
169 key_atob_l(split
[1], s
->emmd5
, MD5_DIGEST_LENGTH
* 2);
170 s
->firstwritten
.time
= atol(split
[2]);
171 s
->lastwritten
.time
= atol(split
[3]);
172 s
->type
= a2i(split
[4], 2);
173 s
->count
= a2i(split
[5], 4);
175 LL_ITER itr
= ll_iter_create(configured_readers
);
177 while((rdr
= ll_iter_next(&itr
)))
179 if(rdr
->cachemm
!=1) // skip: emmcache save is disabled
184 if(strcmp(rdr
->label
, buf
) == 0)
194 rdr
->emmstat
= ll_create("emmstat");
195 cs_lock_create(__func__
, &rdr
->emmstat_lock
, rdr
->label
, DEFAULT_LOCK_TIMEOUT
);
198 ll_append(rdr
->emmstat
, s
);
203 cs_log("emmstats could not be loaded for %s", buf
);
209 cs_log_dbg(D_EMM
, "emmstat ERROR: %s count=%d type=%d", buf
, s
->count
, s
->type
);
218 int64_t load_time
= comp_timeb(&te
, &ts
);
219 cs_log("loaded %d emmstat records from %s in %"PRId64
" ms", count
, fname
, load_time
);
222 void save_emmstat_to_file(void)
224 if(boxtype_is("dbox2")) return; // don't save emmstat on these boxes, they lack resources and will crash!
226 if(!emm_cache_configured())
228 cs_log("saving emmstats disabled since no reader is using it!");
236 get_emmcache_filename(fname
, sizeof(fname
), "oscam.emmstat");
240 get_config_filename(fname
, sizeof(fname
), "oscam.emmstat");
242 FILE *file
= fopen(fname
, "w");
246 cs_log("can't write to file %s", fname
);
253 int32_t count
= 0, result
= 0;
254 struct s_reader
*rdr
;
255 LL_ITER itr
= ll_iter_create(configured_readers
);
256 while((rdr
= ll_iter_next(&itr
)))
258 if(!rdr
->cachemm
|| rdr
->cachemm
== 2)
260 cs_log("reader %s skipped since emmcache save is disabled", rdr
->label
);
266 cs_writelock(__func__
, &rdr
->emmstat_lock
);
267 LL_ITER it
= ll_iter_create(rdr
->emmstat
);
269 while((s
= ll_iter_next(&it
)))
271 uint8_t tmp_emmd5
[MD5_DIGEST_LENGTH
* 2 + 1];
272 char_to_hex(s
->emmd5
, MD5_DIGEST_LENGTH
, tmp_emmd5
);
273 result
= fprintf(file
, "%s,%s,%ld,%ld,%02X,%04X\n", rdr
->label
, tmp_emmd5
, s
->firstwritten
.time
, s
->lastwritten
.time
, s
->type
, s
->count
);
276 cs_writeunlock(__func__
, &rdr
->emmstat_lock
);
278 result
= remove(fname
);
281 cs_log("error writing stats -> stat file removed!");
285 cs_log("error writing stats -> stat file could not be removed either!");
291 cs_writeunlock(__func__
, &rdr
->emmstat_lock
);
298 int64_t load_time
= comp_timeb(&te
, &ts
);
300 cs_log("saved %d emmstat records to %s in %"PRId64
" ms", count
, fname
, load_time
);
303 void emm_load_cache(void)
305 if(boxtype_is("dbox2")) return; // don't load emmcache on these boxes, they lack resources and will crash!
307 if(!emm_cache_configured()){
308 cs_log("loading emmcache disabled since no reader is using it!");
315 struct s_emmcache
*c
;
319 get_emmcache_filename(fname
, sizeof(fname
), "oscam.emmcache");
323 get_config_filename(fname
, sizeof(fname
), "oscam.emmcache");
326 file
= fopen(fname
, "r");
329 cs_log_dbg(D_TRACE
, "can't read emmcache from file %s", fname
);
339 char *ptr
, *saveptr1
= NULL
;
342 memset(line
, 0, sizeof(line
));
343 while(fgets(line
, sizeof(line
), file
))
345 if(!line
[0] || line
[0] == '#' || line
[0] == ';')
348 for(i
= 0, ptr
= strtok_r(line
, ",", &saveptr1
); ptr
&& i
< 7 ; ptr
= strtok_r(NULL
, ",", &saveptr1
), i
++)
356 if(!cs_malloc(&c
, sizeof(struct s_emmcache
)))
358 key_atob_l(split
[0], c
->emmd5
, MD5_DIGEST_LENGTH
*2);
359 c
->firstseen
.time
= atol(split
[1]);
360 c
->lastseen
.time
= atol(split
[2]);
361 c
->type
= a2i(split
[3], 2);
362 c
->len
= a2i(split
[4], 4);
363 key_atob_l(split
[5], c
->emm
, c
->len
*2);
365 if(valid
&& c
->len
!= 0)
369 emm_cache
= ll_create("emm cache");
372 ll_append(emm_cache
, c
);
383 int64_t load_time
= comp_timeb(&te
, &ts
);
384 cs_log("loaded %d emmcache records from %s in %"PRId64
" ms", count
, fname
, load_time
);
387 struct s_emmcache
*find_emm_cache(uint8_t *emmd5
)
389 struct s_emmcache
*c
;
393 { emm_cache
= ll_create("emm cache"); }
395 it
= ll_iter_create(emm_cache
);
396 while((c
= ll_iter_next(&it
)))
398 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
400 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "found emmcache match");
407 int32_t clean_stale_emm_cache_and_stat(uint8_t *emmd5
, int64_t gone
)
413 struct s_emmcache
*c
;
417 { emm_cache
= ll_create("emm cache"); }
419 it
= ll_iter_create(emm_cache
);
420 while((c
= ll_iter_next(&it
)))
422 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!
424 struct s_reader
*rdr
;
425 LL_ITER rdr_itr
= ll_iter_create(configured_readers
);
426 while((rdr
= ll_iter_next(&rdr_itr
)))
428 if(rdr
->emmstat
&& !(caid_is_irdeto(rdr
->caid
) || caid_is_videoguard(rdr
->caid
)))
430 remove_emm_stat(rdr
, c
->emmd5
); // clean stale entry from stats
434 ll_iter_remove_data(&it
); // clean stale entry from emmcache
440 int32_t emm_edit_cache(uint8_t *emmd5
, EMM_PACKET
*ep
, bool add
)
442 struct s_emmcache
*c
;
447 { emm_cache
= ll_create("emm cache"); }
449 it
= ll_iter_create(emm_cache
);
450 while((c
= ll_iter_next(&it
)))
452 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
456 return 0; // already added
458 ll_iter_remove_data(&it
);
465 if(!cs_malloc(&c
, sizeof(struct s_emmcache
)))
467 memcpy(c
->emmd5
, emmd5
, MD5_DIGEST_LENGTH
);
469 c
->len
= SCT_LEN(ep
->emm
);
470 cs_ftime(&c
->firstseen
);
471 c
->lastseen
= c
->firstseen
;
472 memcpy(c
->emm
, ep
->emm
, c
->len
);
473 ll_append(emm_cache
, c
);
475 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "added emm to cache:");
483 int32_t remove_emm_stat(struct s_reader
*rdr
, uint8_t *emmd5
)
486 if(rdr
&& rdr
->emmstat
)
488 cs_writelock(__func__
, &rdr
->emmstat_lock
);
490 LL_ITER itr
= ll_iter_create(rdr
->emmstat
);
491 while((c
= ll_iter_next(&itr
)))
493 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
495 ll_iter_remove_data(&itr
);
501 cs_writeunlock(__func__
, &rdr
->emmstat_lock
);
506 struct s_emmstat
*get_emm_stat(struct s_reader
*rdr
, uint8_t *emmd5
, uint8_t emmtype
)
508 if(!rdr
->cachemm
) return NULL
;
514 { rdr
->emmstat
= ll_create("emm stat"); }
516 it
= ll_iter_create(rdr
->emmstat
);
517 while((c
= ll_iter_next(&it
)))
519 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
521 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "found emmstat match (reader:%s, count:%d)", rdr
->label
, c
->count
);
526 if(cs_malloc(&c
, sizeof(struct s_emmstat
)))
528 memcpy(c
->emmd5
, emmd5
, MD5_DIGEST_LENGTH
);
530 ll_append(rdr
->emmstat
, c
);
531 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "added emmstat (reader:%s, count:%d)", rdr
->label
, c
->count
);