revert breaks some stupid old compilers
[oscam.git] / oscam-emm-cache.c
blob60254867c0d9f3f890b8f75c2edf2998567ce3cc
1 #define MODULE_LOG_PREFIX "emmcache"
3 #include "globals.h"
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"
11 #define LINESIZE 1024
12 #define DEFAULT_LOCK_TIMEOUT 1000000
14 static LLIST *emm_cache;
16 bool emm_cache_configured(void)
18 struct s_reader *rdr;
19 bool enable = false;
20 LL_ITER itr = ll_iter_create(configured_readers);
21 while((rdr = ll_iter_next(&itr)))
23 if(rdr->cachemm == 1)
25 enable = true;
28 return enable;
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!");
37 return;
40 char fname[256];
41 struct timeb ts, te;
43 if(!cfg.emmlogdir)
45 get_tmp_dir_filename(fname, sizeof(fname), "oscam.emmcache");
47 else
49 get_config_filename(fname, sizeof(fname), "oscam.emmcache");
51 FILE *file = fopen(fname, "w");
53 if(!file)
55 cs_log("can't write emmcache to file %s", fname);
56 return;
59 cs_ftime(&ts);
60 int32_t count = 0, result = 0;
61 LL_ITER it = ll_iter_create(emm_cache);
62 struct s_emmcache *c;
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);
70 if(result < 0)
72 fclose(file);
73 result = remove(fname);
74 if(!result)
76 cs_log("error writing cache -> cache file removed!");
78 else
80 cs_log("error writing cache -> cache file could not be removed either!");
82 return;
84 count++;
87 fclose(file);
88 cs_ftime(&te);
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!");
99 return;
102 char buf[256];
103 char fname[256];
104 char *line;
105 FILE *file;
107 if(!cfg.emmlogdir)
109 get_tmp_dir_filename(fname, sizeof(fname), "oscam.emmstat");
111 else
113 get_config_filename(fname, sizeof(fname), "oscam.emmstat");
115 file = fopen(fname, "r");
116 if(!file)
118 cs_log_dbg(D_TRACE, "can't read emmstats from file %s", fname);
119 return;
122 if(!cs_malloc(&line, LINESIZE))
124 fclose(file);
125 return;
128 struct timeb ts, te;
129 cs_ftime(&ts);
131 struct s_reader *rdr = NULL;
132 struct s_emmstat *s;
134 int32_t i = 1;
135 int32_t valid = 0;
136 int32_t count = 0;
137 char *ptr, *saveptr1 = NULL;
138 char *split[7];
140 while(fgets(line, LINESIZE, file))
142 if(!line[0] || line[0] == '#' || line[0] == ';')
143 { continue; }
145 if(!cs_malloc(&s, sizeof(struct s_emmstat)))
146 { continue; }
148 for(i = 0, ptr = strtok_r(line, ",", &saveptr1); ptr && i < 7 ; ptr = strtok_r(NULL, ",", &saveptr1), i++)
149 { split[i] = ptr; }
150 valid = (i == 6);
151 if(valid)
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
166 continue;
168 if(strcmp(rdr->label, buf) == 0)
170 break;
174 if(rdr != NULL)
176 if(!rdr->emmstat)
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);
183 count++;
185 else
187 cs_log("emmstats could not be loaded for %s", buf);
188 NULLFREE(s);
191 else
193 cs_log_dbg(D_EMM, "emmstat ERROR: %s count=%d type=%d", buf, s->count, s->type);
194 NULLFREE(s);
198 fclose(file);
199 NULLFREE(line);
201 cs_ftime(&te);
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!");
212 return;
215 char fname[256];
217 if(!cfg.emmlogdir)
219 get_tmp_dir_filename(fname, sizeof(fname), "oscam.emmstat");
221 else
223 get_config_filename(fname, sizeof(fname), "oscam.emmstat");
225 FILE *file = fopen(fname, "w");
227 if(!file)
229 cs_log("can't write to file %s", fname);
230 return;
233 struct timeb ts, te;
234 cs_ftime(&ts);
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);
244 continue;
247 if(rdr->emmstat)
249 cs_writelock(__func__, &rdr->emmstat_lock);
250 LL_ITER it = ll_iter_create(rdr->emmstat);
251 struct s_emmstat *s;
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);
257 if(result < 0)
259 cs_writeunlock(__func__, &rdr->emmstat_lock);
260 fclose(file);
261 result = remove(fname);
262 if(!result)
264 cs_log("error writing stats -> stat file removed!");
266 else
268 cs_log("error writing stats -> stat file could not be removed either!");
270 return;
272 count++;
274 cs_writeunlock(__func__, &rdr->emmstat_lock);
278 fclose(file);
280 cs_ftime(&te);
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!");
292 return;
295 char fname[256];
296 char line[1024];
297 FILE *file;
298 struct s_emmcache *c;
300 if(!cfg.emmlogdir)
302 get_tmp_dir_filename(fname, sizeof(fname), "oscam.emmcache");
304 else
306 get_config_filename(fname, sizeof(fname), "oscam.emmcache");
309 file = fopen(fname, "r");
310 if(!file)
312 cs_log_dbg(D_TRACE, "can't read emmcache from file %s", fname);
313 return;
316 struct timeb ts, te;
317 cs_ftime(&ts);
319 int32_t count = 0;
320 int32_t i = 1;
321 int32_t valid = 0;
322 char *ptr, *saveptr1 = NULL;
323 char *split[7];
325 memset(line, 0, sizeof(line));
326 while(fgets(line, sizeof(line), file))
328 if(!line[0] || line[0] == '#' || line[0] == ';')
329 { continue; }
331 for(i = 0, ptr = strtok_r(line, ",", &saveptr1); ptr && i < 7 ; ptr = strtok_r(NULL, ",", &saveptr1), i++)
333 split[i] = ptr;
336 valid = (i == 6);
337 if(valid)
339 if(!cs_malloc(&c, sizeof(struct s_emmcache)))
340 { continue; }
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)
350 if(!emm_cache)
352 emm_cache = ll_create("emm cache");
355 ll_append(emm_cache, c);
356 count++;
358 else
360 NULLFREE(c);
364 fclose(file);
365 cs_ftime(&te);
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;
373 LL_ITER it;
375 if(!emm_cache)
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");
384 return c;
387 return NULL;
390 int32_t clean_stale_emm_cache_and_stat(uchar *emmd5, int64_t gone)
392 struct timeb now;
393 cs_ftime(&now);
394 int32_t count = 0;
396 struct s_emmcache *c;
397 LL_ITER it;
399 if(!emm_cache)
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
415 count++;
418 ll_iter_remove_data(&it); // clean stale entry from emmcache
421 return count;
424 int32_t emm_edit_cache(uchar *emmd5, EMM_PACKET *ep, bool add)
426 struct s_emmcache *c;
427 LL_ITER it;
428 int32_t count = 0;
430 if(!emm_cache)
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))
438 if(add)
440 return 0; //already added
442 ll_iter_remove_data(&it);
443 count++;
447 if(add)
449 if(!cs_malloc(&c, sizeof(struct s_emmcache)))
450 { return count; }
451 memcpy(c->emmd5, emmd5, MD5_DIGEST_LENGTH);
452 c->type = ep->type;
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);
458 #ifdef WITH_DEBUG
459 cs_log_dump_dbg(D_EMM, c->emmd5, MD5_DIGEST_LENGTH, "added emm to cache:");
460 #endif
461 count++;
464 return count;
466 int32_t remove_emm_stat(struct s_reader *rdr, uchar *emmd5)
468 int32_t count = 0;
469 if(rdr && rdr->emmstat)
471 cs_writelock(__func__, &rdr->emmstat_lock);
472 struct s_emmstat *c;
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);
479 count++;
480 break;
484 cs_writeunlock(__func__, &rdr->emmstat_lock);
486 return count;
489 struct s_emmstat *get_emm_stat(struct s_reader *rdr, uchar *emmd5, uchar emmtype)
491 if(!rdr->cachemm) return NULL;
493 struct s_emmstat *c;
494 LL_ITER it;
496 if(!rdr->emmstat)
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);
505 return c;
509 if(cs_malloc(&c, sizeof(struct s_emmstat)))
511 memcpy(c->emmd5, emmd5, MD5_DIGEST_LENGTH);
512 c->type = emmtype;
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);
516 return c;