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; // dont 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
);
63 while((c
= ll_iter_next(&it
)))
65 uchar tmp_emmd5
[MD5_DIGEST_LENGTH
* 2 + 1];
66 char_to_hex(c
->emmd5
, MD5_DIGEST_LENGTH
, tmp_emmd5
);
67 uchar tmp_emm
[c
->len
* 2 + 1];
68 char_to_hex(c
->emm
, c
->len
, tmp_emm
);
69 result
= fprintf(file
, "%s,%ld,%ld,%02X,%04X,%s\n", tmp_emmd5
, c
->firstseen
.time
, c
->lastseen
.time
, c
->type
, c
->len
, tmp_emm
);
73 result
= remove(fname
);
76 cs_log("error writing cache -> cache file removed!");
80 cs_log("error writing cache -> cache file could not be removed either!");
89 int64_t load_time
= comp_timeb(&te
, &ts
);
90 cs_log("saved %d emmcache records to %s in %"PRId64
" ms", count
, fname
, load_time
);
93 void load_emmstat_from_file(void)
95 if(boxtype_is("dbox2")) return; // dont load emmstat on these boxes, they lack resources and will crash!
97 if(!emm_cache_configured()){
98 cs_log("loading emmstats disabled since no reader is using it!");
109 get_tmp_dir_filename(fname
, sizeof(fname
), "oscam.emmstat");
113 get_config_filename(fname
, sizeof(fname
), "oscam.emmstat");
115 file
= fopen(fname
, "r");
118 cs_log_dbg(D_TRACE
, "can't read emmstats from file %s", fname
);
122 if(!cs_malloc(&line
, LINESIZE
))
131 struct s_reader
*rdr
= NULL
;
137 char *ptr
, *saveptr1
= NULL
;
140 while(fgets(line
, LINESIZE
, file
))
142 if(!line
[0] || line
[0] == '#' || line
[0] == ';')
145 if(!cs_malloc(&s
, sizeof(struct s_emmstat
)))
148 for(i
= 0, ptr
= strtok_r(line
, ",", &saveptr1
); ptr
&& i
< 7 ; ptr
= strtok_r(NULL
, ",", &saveptr1
), i
++)
153 strncpy(buf
, split
[0], sizeof(buf
) - 1);
154 key_atob_l(split
[1], s
->emmd5
, MD5_DIGEST_LENGTH
*2);
155 s
->firstwritten
.time
= atol(split
[2]);
156 s
->lastwritten
.time
= atol(split
[3]);
157 s
->type
= a2i(split
[4], 2);
158 s
->count
= a2i(split
[5], 4);
160 LL_ITER itr
= ll_iter_create(configured_readers
);
162 while((rdr
= ll_iter_next(&itr
)))
164 if(rdr
->cachemm
!=1) //skip: emmcache save is disabled
168 if(strcmp(rdr
->label
, buf
) == 0)
178 rdr
->emmstat
= ll_create("emmstat");
179 cs_lock_create(__func__
, &rdr
->emmstat_lock
, rdr
->label
, DEFAULT_LOCK_TIMEOUT
);
182 ll_append(rdr
->emmstat
, s
);
187 cs_log("emmstats could not be loaded for %s", buf
);
193 cs_log_dbg(D_EMM
, "emmstat ERROR: %s count=%d type=%d", buf
, s
->count
, s
->type
);
202 int64_t load_time
= comp_timeb(&te
, &ts
);
203 cs_log("loaded %d emmstat records from %s in %"PRId64
" ms", count
, fname
, load_time
);
206 void save_emmstat_to_file(void)
208 if(boxtype_is("dbox2")) return; // dont save emmstat on these boxes, they lack resources and will crash!
210 if(!emm_cache_configured()){
211 cs_log("saving emmstats disabled since no reader is using it!");
219 get_tmp_dir_filename(fname
, sizeof(fname
), "oscam.emmstat");
223 get_config_filename(fname
, sizeof(fname
), "oscam.emmstat");
225 FILE *file
= fopen(fname
, "w");
229 cs_log("can't write to file %s", fname
);
236 int32_t count
= 0, result
= 0;
237 struct s_reader
*rdr
;
238 LL_ITER itr
= ll_iter_create(configured_readers
);
239 while((rdr
= ll_iter_next(&itr
)))
241 if(!rdr
->cachemm
|| rdr
->cachemm
== 2)
243 cs_log("reader %s skipped since emmcache save is disabled", rdr
->label
);
249 cs_writelock(__func__
, &rdr
->emmstat_lock
);
250 LL_ITER it
= ll_iter_create(rdr
->emmstat
);
252 while((s
= ll_iter_next(&it
)))
254 uchar tmp_emmd5
[MD5_DIGEST_LENGTH
* 2 + 1];
255 char_to_hex(s
->emmd5
, MD5_DIGEST_LENGTH
, tmp_emmd5
);
256 result
= fprintf(file
, "%s,%s,%ld,%ld,%02X,%04X\n", rdr
->label
, tmp_emmd5
, s
->firstwritten
.time
, s
->lastwritten
.time
, s
->type
, s
->count
);
259 cs_writeunlock(__func__
, &rdr
->emmstat_lock
);
261 result
= remove(fname
);
264 cs_log("error writing stats -> stat file removed!");
268 cs_log("error writing stats -> stat file could not be removed either!");
274 cs_writeunlock(__func__
, &rdr
->emmstat_lock
);
281 int64_t load_time
= comp_timeb(&te
, &ts
);
283 cs_log("saved %d emmstat records to %s in %"PRId64
" ms", count
, fname
, load_time
);
286 void emm_load_cache(void)
288 if(boxtype_is("dbox2")) return; // dont load emmcache on these boxes, they lack resources and will crash!
290 if(!emm_cache_configured()){
291 cs_log("loading emmcache disabled since no reader is using it!");
298 struct s_emmcache
*c
;
302 get_tmp_dir_filename(fname
, sizeof(fname
), "oscam.emmcache");
306 get_config_filename(fname
, sizeof(fname
), "oscam.emmcache");
309 file
= fopen(fname
, "r");
312 cs_log_dbg(D_TRACE
, "can't read emmcache from file %s", fname
);
322 char *ptr
, *saveptr1
= NULL
;
325 memset(line
, 0, sizeof(line
));
326 while(fgets(line
, sizeof(line
), file
))
328 if(!line
[0] || line
[0] == '#' || line
[0] == ';')
331 for(i
= 0, ptr
= strtok_r(line
, ",", &saveptr1
); ptr
&& i
< 7 ; ptr
= strtok_r(NULL
, ",", &saveptr1
), i
++)
339 if(!cs_malloc(&c
, sizeof(struct s_emmcache
)))
341 key_atob_l(split
[0], c
->emmd5
, MD5_DIGEST_LENGTH
*2);
342 c
->firstseen
.time
= atol(split
[1]);
343 c
->lastseen
.time
= atol(split
[2]);
344 c
->type
= a2i(split
[3], 2);
345 c
->len
= a2i(split
[4], 4);
346 key_atob_l(split
[5], c
->emm
, c
->len
*2);
348 if(valid
&& c
->len
!= 0)
352 emm_cache
= ll_create("emm cache");
355 ll_append(emm_cache
, c
);
366 int64_t load_time
= comp_timeb(&te
, &ts
);
367 cs_log("loaded %d emmcache records from %s in %"PRId64
" ms", count
, fname
, load_time
);
370 struct s_emmcache
*find_emm_cache(uchar
*emmd5
)
372 struct s_emmcache
*c
;
376 { emm_cache
= ll_create("emm cache"); }
378 it
= ll_iter_create(emm_cache
);
379 while((c
= ll_iter_next(&it
)))
381 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
383 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "found emmcache match");
390 int32_t clean_stale_emm_cache_and_stat(uchar
*emmd5
, int64_t gone
)
396 struct s_emmcache
*c
;
400 { emm_cache
= ll_create("emm cache"); }
402 it
= ll_iter_create(emm_cache
);
403 while((c
= ll_iter_next(&it
)))
406 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!
408 struct s_reader
*rdr
;
409 LL_ITER rdr_itr
= ll_iter_create(configured_readers
);
410 while((rdr
= ll_iter_next(&rdr_itr
)))
412 if(rdr
->emmstat
&& !(caid_is_irdeto(rdr
->caid
) || caid_is_videoguard(rdr
->caid
)))
414 remove_emm_stat(rdr
, c
->emmd5
); // clean stale entry from stats
418 ll_iter_remove_data(&it
); // clean stale entry from emmcache
424 int32_t emm_edit_cache(uchar
*emmd5
, EMM_PACKET
*ep
, bool add
)
426 struct s_emmcache
*c
;
431 { emm_cache
= ll_create("emm cache"); }
433 it
= ll_iter_create(emm_cache
);
434 while((c
= ll_iter_next(&it
)))
436 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
440 return 0; //already added
442 ll_iter_remove_data(&it
);
449 if(!cs_malloc(&c
, sizeof(struct s_emmcache
)))
451 memcpy(c
->emmd5
, emmd5
, MD5_DIGEST_LENGTH
);
453 c
->len
= SCT_LEN(ep
->emm
);
454 cs_ftime(&c
->firstseen
);
455 c
->lastseen
= c
->firstseen
;
456 memcpy(c
->emm
, ep
->emm
, c
->len
);
457 ll_append(emm_cache
, c
);
459 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "added emm to cache:");
466 int32_t remove_emm_stat(struct s_reader
*rdr
, uchar
*emmd5
)
469 if(rdr
&& rdr
->emmstat
)
471 cs_writelock(__func__
, &rdr
->emmstat_lock
);
473 LL_ITER itr
= ll_iter_create(rdr
->emmstat
);
474 while((c
= ll_iter_next(&itr
)))
476 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
478 ll_iter_remove_data(&itr
);
484 cs_writeunlock(__func__
, &rdr
->emmstat_lock
);
489 struct s_emmstat
*get_emm_stat(struct s_reader
*rdr
, uchar
*emmd5
, uchar emmtype
)
491 if(!rdr
->cachemm
) return NULL
;
497 { rdr
->emmstat
= ll_create("emm stat"); }
499 it
= ll_iter_create(rdr
->emmstat
);
500 while((c
= ll_iter_next(&it
)))
502 if(!memcmp(emmd5
, c
->emmd5
, MD5_DIGEST_LENGTH
))
504 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "found emmstat match (reader:%s, count:%d)", rdr
->label
, c
->count
);
509 if(cs_malloc(&c
, sizeof(struct s_emmstat
)))
511 memcpy(c
->emmd5
, emmd5
, MD5_DIGEST_LENGTH
);
513 ll_append(rdr
->emmstat
, c
);
514 cs_log_dump_dbg(D_EMM
, c
->emmd5
, MD5_DIGEST_LENGTH
, "added emmstat (reader:%s, count:%d)", rdr
->label
, c
->count
);