- fix Building without Nagra not possible at Nagra_Merlin https://trac.streamboard...
[oscam.git] / module-cccam-cacheex.c
blob0b24bc227388bd282d29de11e4bee89071188480
1 #define MODULE_LOG_PREFIX "cccam"
3 #include "globals.h"
4 #include "oscam-array.h"
6 #if defined(CS_CACHEEX) && defined(MODULE_CCCAM)
8 #include "module-cacheex.h"
9 #include "module-cccam-data.h"
10 #include "module-cccam-cacheex.h"
11 #include "oscam-cache.h"
12 #include "oscam-client.h"
13 #include "oscam-ecm.h"
14 #include "oscam-string.h"
15 #include "oscam-chk.h"
16 #include "oscam-reader.h"
17 #ifdef CS_CACHEEX_AIO
18 #include "oscam-chk.h"
19 #include "oscam-config.h"
20 #endif
22 #define CSP_HASH_SWAP(n) (((((uint32_t)(n) & 0xFF)) << 24) | \
23 ((((uint32_t)(n) & 0xFF00)) << 8) | \
24 ((((uint32_t)(n) & 0xFF0000)) >> 8) | \
25 ((((uint32_t)(n) & 0xFF000000)) >> 24))
27 extern int32_t cc_cli_connect(struct s_client *cl);
28 extern int32_t cc_cmd_send(struct s_client *cl, uint8_t *buf, int32_t len, cc_msg_type_t cmd);
30 #ifdef CS_CACHEEX_AIO
31 void cc_cacheex_feature_trigger_in(struct s_client *cl, uint8_t *buf)
33 int32_t feature = 0;
34 int i = 0;
35 uint8_t filter_count;
36 uint8_t j, k, l, rc;
37 feature = buf[1] | (buf[0] << 8);
38 FTAB *lgonly_tab;
40 // check client & cacheex-mode
41 if(
42 !check_client(cl) ||
44 (cl->typ == 'c' && cl->account->cacheex.mode > 0) ||
45 (cl->typ == 'p' && cl->reader->cacheex.mode > 0)
49 return;
52 switch(feature)
54 // set localgenerated only
55 case 1:
56 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1))
58 if(cfg.cacheex_lg_only_remote_settings || cl->account->cacheex.lg_only_remote_settings)
59 cl->account->cacheex.localgenerated_only = buf[4];
60 else if(buf[4])
61 cl->account->cacheex.localgenerated_only = buf[4];
63 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3)
65 if(cfg.cacheex_lg_only_remote_settings || cl->reader->cacheex.lg_only_remote_settings)
66 cl->reader->cacheex.localgenerated_only = buf[4];
67 else if(buf[4])
68 cl->reader->cacheex.localgenerated_only = buf[4];
70 break;
71 // set localgenerated only caidtab
72 case 2:
73 filter_count = buf[i+4];
74 i += 5;
76 memset(&lgonly_tab, 0, sizeof(lgonly_tab));
78 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1))
80 lgonly_tab = &cl->account->cacheex.lg_only_tab;
82 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3)
84 lgonly_tab = &cl->reader->cacheex.lg_only_tab;
86 else
88 return;
91 // remotesettings enabled - replace local settings
92 if(cfg.cacheex_lg_only_remote_settings ||
94 (cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1) && cl->account->cacheex.lg_only_remote_settings)
95 || (cl->typ == 'p' && cl->reader->cacheex.mode == 3 && cl->reader->cacheex.lg_only_remote_settings)
99 ftab_clear(lgonly_tab);
101 for(j = 0; j < filter_count; j++)
103 FILTER d;
104 memset(&d, 0, sizeof(d));
106 d.caid = b2i(2, buf + i);
107 i += 2;
109 d.nprids = 1;
110 d.prids[0] = NO_PROVID_VALUE;
112 ftab_add(lgonly_tab, &d);
115 // remotesettings disabled - write additional remote-caids received
116 else
118 for(j = 0; j < filter_count; j++)
120 FILTER d;
121 memset(&d, 0, sizeof(d));
123 d.caid = b2i(2, buf + i);
124 i += 2;
126 d.nprids = 1;
127 d.prids[0] = NO_PROVID_VALUE;
129 if(!chk_lg_only_cp(d.caid, d.prids[0], lgonly_tab))
131 cs_log_dbg(D_CACHEEX, "%04X:%06X not found in local settings - adding them", d.caid, d.prids[0]);
133 for(l = rc = 0; (!rc) && (l < lgonly_tab->nfilts); l++)
135 if(lgonly_tab->filts[l].caid == d.caid)
137 rc = 1;
139 if(lgonly_tab->filts[l].nprids+1 <= CS_MAXPROV)
141 lgonly_tab->filts[l].prids[lgonly_tab->filts[l].nprids] = d.prids[0];
142 lgonly_tab->filts[l].nprids++;
144 else
146 cs_log_dbg(D_CACHEEX, "error: cacheex_lg_only_tab -> max. number(%i) of providers reached", CS_MAXPROV);
150 if(!rc)
152 ftab_add(lgonly_tab, &d);
157 break;
158 // set cacheex_ecm_filter - extended
159 case 4:
160 filter_count = buf[i+4];
161 i += 5;
163 CECSPVALUETAB *filter;
164 memset(&filter, 0, sizeof(filter));
166 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1) && cl->account->cacheex.allow_filter)
168 filter = &cl->account->cacheex.filter_caidtab;
170 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3 && cl->reader->cacheex.allow_filter)
172 filter = &cl->reader->cacheex.filter_caidtab;
174 else
176 return;
179 cecspvaluetab_clear(filter);
181 for(j = 0; j < filter_count; j++)
183 int32_t caid = -1, cmask = -1, provid = -1, srvid = -1;
184 CECSPVALUETAB_DATA d;
185 memset(&d, 0, sizeof(d));
187 caid = b2i(2, buf + i);
188 if(caid == 0xFFFF) caid = -1;
189 i += 2;
191 cmask = b2i(2, buf + i);
192 if(cmask == 0xFFFF) cmask = -1;
193 i += 2;
195 provid = b2i(3, buf + i);
196 if(provid == 0xFFFFFF) provid = -1;
197 i += 3;
199 srvid = b2i(2, buf + i);
200 if(srvid == 0xFFFF) srvid = -1;
201 i += 2;
203 if(caid > 0)
205 d.caid = caid;
206 d.cmask = cmask;
207 d.prid = provid;
208 d.srvid = srvid;
209 cecspvaluetab_add(filter, &d);
212 break;
213 // no push after
214 case 8: ;
215 CAIDVALUETAB *ctab;
216 memset(&ctab, 0, sizeof(ctab));
218 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1))
220 ctab = &cl->account->cacheex.cacheex_nopushafter_tab;
222 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3)
224 ctab = &cl->reader->cacheex.cacheex_nopushafter_tab;
226 else
228 return;
231 filter_count = buf[i+4];
232 i += 5;
234 caidvaluetab_clear(ctab);
236 for(j = 0; j < filter_count; j++)
238 uint16_t caid = 0, value = 0;
239 CAIDVALUETAB_DATA d;
240 memset(&d, 0, sizeof(d));
242 caid = b2i(2, buf + i);
243 if(caid == 0xFFFF) caid = -1;
244 i += 2;
246 value = b2i(2, buf + i);
247 if(value == 0xFFFF) value = -1;
248 i += 2;
250 if(caid > 0)
252 d.caid = caid;
253 d.value = value;
254 caidvaluetab_add(ctab, &d);
257 break;
258 // max_hop
259 case 16:
260 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1) && cl->account->cacheex.allow_maxhop)
262 cl->account->cacheex.maxhop = buf[4];
263 cl->account->cacheex.maxhop_lg = buf[5];
265 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3 && cl->reader->cacheex.allow_maxhop)
267 cl->reader->cacheex.maxhop = buf[4];
268 cl->reader->cacheex.maxhop_lg = buf[5];
270 break;
271 // aio-version
272 case 32:
273 if(cl->typ == 'c' && cl->account->cacheex.mode > 0)
275 char *ofs = (char *)buf + i + 4;
276 cs_strncpy(cl->account->cacheex.aio_version, ofs, sizeof(cl->account->cacheex.aio_version));
278 else if(cl->typ == 'p' && cl->reader->cacheex.mode > 0)
280 char *ofs = (char *)buf + i + 4;
281 cs_strncpy(cl->reader->cacheex.aio_version, ofs, sizeof(cl->reader->cacheex.aio_version));
283 break;
284 // lg_only_tab caid:prov1[,provN][;caid:prov]
285 case 64: ;
286 memset(&lgonly_tab, 0, sizeof(lgonly_tab));
288 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1))
290 lgonly_tab = &cl->account->cacheex.lg_only_tab;
292 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3)
294 lgonly_tab = &cl->reader->cacheex.lg_only_tab;
296 else
298 return;
301 filter_count = buf[i+4];
302 i += 5;
304 // remotesettings enabled - replace local settings
305 if(cfg.cacheex_lg_only_remote_settings ||
307 (cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1) && cl->account->cacheex.lg_only_remote_settings)
308 || (cl->typ == 'p' && cl->reader->cacheex.mode == 3 && cl->reader->cacheex.lg_only_remote_settings)
309 || !lgonly_tab->nfilts
313 ftab_clear(lgonly_tab);
315 for(j = 0; j < filter_count; j++)
317 FILTER d;
318 memset(&d, 0, sizeof(d));
320 d.caid = b2i(2, buf + i);
321 i += 2;
323 d.nprids = b2i(1, buf + i);
324 i += 1;
326 for(k=0; k < d.nprids; k++)
328 d.prids[k] = b2i(3, buf + i);
329 i += 3;
331 ftab_add(lgonly_tab, &d);
335 // remotesettings disabled - write additional remote-caid/provids received
336 else
338 for(j = 0; j < filter_count; j++)
340 FILTER d;
341 memset(&d, 0, sizeof(d));
343 d.caid = b2i(2, buf + i);
344 i += 2;
346 d.nprids = b2i(1, buf + i);
347 i += 1;
349 for(k=0; k < d.nprids; k++)
351 d.prids[k] = b2i(3, buf + i);
352 i += 3;
354 if(!chk_ident_filter(d.caid, d.prids[k], lgonly_tab))
356 cs_log_dbg(D_CACHEEX, "%04X:%06X not found in local settings - adding them", d.caid, d.prids[k]);
358 for(l = rc = 0; (!rc) && (l < lgonly_tab->nfilts); l++)
360 if(lgonly_tab->filts[l].caid == d.caid)
362 rc = 1;
364 if(lgonly_tab->filts[l].nprids+1 <= CS_MAXPROV)
366 lgonly_tab->filts[l].prids[lgonly_tab->filts[l].nprids] = d.prids[k];
367 lgonly_tab->filts[l].nprids++;
369 else
371 cs_log_dbg(D_CACHEEX, "error: cacheex_lg_only_tab -> max. number of providers reached");
375 if(!rc)
377 ftab_add(lgonly_tab, &d);
383 break;
384 default:
385 return;
389 void cc_cacheex_feature_trigger(struct s_client *cl, int32_t feature, uint8_t mode)
391 // size: (feature-bitfield & mask: 2) + payload-size: 2 + feature-payload :x
392 uint16_t size = 2 + 2;
393 int i = 0;
394 uint8_t j;
395 uint8_t payload[MAX_ECM_SIZE-size];
396 memset(payload, 0, sizeof(payload));
398 // check client & cacheex-mode
399 if(!check_client(cl))
401 return;
404 switch(feature)
406 FTAB *lgonly_tab;
407 // set localgenerated only
408 case 1:
409 // bitfield
410 i2b_buf(2, feature, payload + i);
411 i += 2;
412 // payload-size
413 i2b_buf(2, 1, payload + i);
414 i += 2;
416 size += 1;
418 // set payload
419 if(mode == 2)
421 if(cl->reader->cacheex.localgenerated_only_in)
422 payload[i] = cl->reader->cacheex.localgenerated_only_in;
423 else
424 payload[i] = cfg.cacheex_localgenerated_only_in;
426 else if(mode == 3)
428 if(cl->account->cacheex.localgenerated_only_in)
429 payload[i] = cl->account->cacheex.localgenerated_only_in;
430 else
431 payload[i] = cfg.cacheex_localgenerated_only_in;
434 break;
435 // set localgenerated only caidtab; cx-aio < 9.2.6-04
436 case 2: ;
437 if(mode == 2)
439 lgonly_tab = &cl->reader->cacheex.lg_only_in_tab;
440 if(!lgonly_tab->nfilts)
441 lgonly_tab = &cfg.cacheex_lg_only_in_tab;
443 else if(mode == 3)
445 lgonly_tab = &cl->account->cacheex.lg_only_in_tab;
446 if(!lgonly_tab->nfilts)
447 lgonly_tab = &cfg.cacheex_lg_only_in_tab;
449 else
451 return;
454 size += (lgonly_tab->nfilts * 2 + 1);
455 if(size < 32)
456 size = 32;
458 // bitfield
459 i2b_buf(2, feature, payload + i);
460 i += 2;
461 // payload-size
462 if((lgonly_tab->nfilts * 2 + 1) > (int)sizeof(payload))
464 cs_log_dbg(D_CACHEEX, "ERROR: too much localgenerated only caidtab-entries (max. 255)");
465 return;
467 i2b_buf(2, (lgonly_tab->nfilts * 2 + 1), payload + i); // n * caid + ctnum
468 i += 2;
469 // set payload
470 if(lgonly_tab->nfilts > 255)
472 cs_log_dbg(D_CACHEEX, "ERROR: too much localgenerated only caidtab-entries (max. 255)");
473 return;
475 payload[i] = lgonly_tab->nfilts;
476 i += 1;
478 for(j = 0; j < lgonly_tab->nfilts; j++)
480 FILTER *d = &lgonly_tab->filts[j];
481 if(d->caid)
483 i2b_buf(2, d->caid, payload + i);
484 i += 2;
486 else
488 continue;
491 break;
492 // cacchex_ecm_filter extendend
493 case 4: ;
494 CECSPVALUETAB *filter;
495 if(mode == 2)
497 filter = &cl->reader->cacheex.filter_caidtab;
498 // if not set, use global settings
499 if(cl->reader->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab.cevnum > 0)
500 filter = &cfg.cacheex_filter_caidtab;
501 // if aio, use global aio settings
502 if(cl->reader->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab_aio.cevnum > 0 && cl->cacheex_aio_checked && (cl->reader->cacheex.feature_bitfield & 4))
503 filter = &cfg.cacheex_filter_caidtab_aio;
505 else if(mode == 3)
507 filter = &cl->account->cacheex.filter_caidtab;
508 // if not set, use global settings
509 if(cl->account->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab.cevnum > 0)
510 filter = &cfg.cacheex_filter_caidtab;
511 // if aio, use global aio settings
512 if(cl->account->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab_aio.cevnum > 0 && cl->cacheex_aio_checked && (cl->account->cacheex.feature_bitfield & 4))
513 filter = &cfg.cacheex_filter_caidtab_aio;
515 else
517 return;
520 size += (filter->cevnum * 9 + 1);
522 // bitfield
523 i2b_buf(2, feature, payload + i);
524 i += 2;
525 // payload-size
526 if((filter->cevnum * 9 + 1) > (int)sizeof(payload))
528 cs_log_dbg(D_CACHEEX, "ERROR: to much cacheex_ecm_filter-entries (max. 63), only 30 default cccam-filters sent");
529 return;
531 i2b_buf(2, (filter->cevnum * 9 + 1), payload + i); // n * (caid2,mask2,provid3,srvid2) + ctnum1
532 i += 2;
533 // set payload
534 payload[i] = filter->cevnum;
535 i += 1;
537 for(j = 0; j < filter->cevnum; j++)
539 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
540 if(d->caid)
542 i2b_buf(2, d->caid, payload + i);
543 i += 2;
545 if(d->cmask)
547 i2b_buf(2, d->cmask, payload + i);
549 i += 2;
551 if(d->prid)
553 i2b_buf(3, d->prid, payload + i);
555 i += 3;
557 if(d->srvid)
559 i2b_buf(2, d->srvid, payload + i);
561 i += 2;
563 break;
564 // no push after
565 case 8: ;
566 CAIDVALUETAB *ctab;
567 if(mode == 2)
569 ctab = &cl->reader->cacheex.cacheex_nopushafter_tab;
570 if(!ctab->cvnum)
571 ctab = &cfg.cacheex_nopushafter_tab;
573 else if(mode == 3)
575 ctab = &cl->account->cacheex.cacheex_nopushafter_tab;
576 if(!ctab->cvnum)
577 ctab = &cfg.cacheex_nopushafter_tab;
579 else
581 return;
584 size += (ctab->cvnum * 4 + 1);
586 // bitfield
587 i2b_buf(2, feature, payload + i);
588 i += 2;
589 // payload-size
590 if((ctab->cvnum * 4 + 1) > (int)sizeof(payload))
592 cs_log_dbg(D_CACHEEX, "ERROR: to much no push after caidtvalueab-entries (max. 255)");
593 return;
595 i2b_buf(2, (ctab->cvnum * 4 + 1), payload + i); // n * (caid2+value2) + cvnum
596 i += 2;
597 // set payload
598 if(ctab->cvnum > 255)
600 cs_log_dbg(D_CACHEEX, "ERROR: to much no push after caidtvalueab-entries (max. 255)");
601 return;
603 payload[i] = ctab->cvnum;
604 i += 1;
606 for(j = 0; j < ctab->cvnum; j++)
608 CAIDVALUETAB_DATA *d = &ctab->cvdata[j];
609 if(d->caid)
611 i2b_buf(2, d->caid, payload + i);
612 i += 2;
613 i2b_buf(2, d->value, payload + i);
614 i += 2;
616 else
618 continue;
621 break;
622 // max hop
623 case 16:
624 // bitfield
625 i2b_buf(2, feature, payload + i);
626 i += 2;
627 // payload-size
628 i2b_buf(2, 2, payload + i);
629 i += 2;
631 size += 2;
633 // set payload
634 if(mode == 2)
636 if(cl->reader->cacheex.maxhop)
637 payload[i] = cl->reader->cacheex.maxhop;
638 else
639 payload[i] = 0;
640 i += 1;
642 if(cl->reader->cacheex.maxhop_lg)
643 payload[i] = cl->reader->cacheex.maxhop_lg;
644 else
645 payload[i] = 0;
647 else if(mode == 3)
649 if(cl->account->cacheex.maxhop)
650 payload[i] = cl->account->cacheex.maxhop;
651 else
652 payload[i] = 0;
653 i += 1;
655 if(cl->account->cacheex.maxhop_lg)
656 payload[i] = cl->account->cacheex.maxhop_lg;
657 else
658 payload[i] = 0;
660 break;
661 // aio-version
662 case 32: ;
663 uint8_t token[12];
665 // bitfield
666 i2b_buf(2, feature, payload + i);
667 i += 2;
668 // payload-size
669 i2b_buf(2, sizeof(token), payload + i);
670 i += 2;
672 size +=sizeof(token);
673 // set payload
675 snprintf((char *)token, sizeof(token), "%s", CS_AIO_VERSION);
676 uint8_t *ofs = payload + i;
677 memcpy(ofs, token, sizeof(token));
678 break;
679 // lg_only_tab
680 case 64: ;
681 // bitfield
682 i2b_buf(2, feature, payload + i);
683 i += 2;
685 if(mode == 2)
687 lgonly_tab = &cl->reader->cacheex.lg_only_in_tab;
688 if(!lgonly_tab->nfilts)
689 lgonly_tab = &cfg.cacheex_lg_only_in_tab;
691 else if(mode == 3)
693 lgonly_tab = &cl->account->cacheex.lg_only_in_tab;
694 if(!lgonly_tab->nfilts)
695 lgonly_tab = &cfg.cacheex_lg_only_in_tab;
697 else
699 return;
702 char *cx_aio_ftab;
703 cx_aio_ftab = cxaio_ftab_to_buf(lgonly_tab);
704 if(cs_strlen(cx_aio_ftab) > 0 && cx_aio_ftab[0] != '\0')
706 size += cs_strlen(cx_aio_ftab) * sizeof(char);
708 // payload-size
709 i2b_buf(2, cs_strlen(cx_aio_ftab), payload + i);
710 i += 2;
712 // filter counter
713 payload[i] = lgonly_tab->nfilts;
714 i += 1;
716 for(j=0; j<cs_strlen(cx_aio_ftab); j+=2)
718 payload[i] = (gethexval(cx_aio_ftab[j]) << 4) | gethexval(cx_aio_ftab[j + 1]);
719 i++;
723 if(size < 32)
724 size = 32;
726 NULLFREE(cx_aio_ftab);
727 break;
728 default:
729 return;
731 uint8_t buf[size];
732 memset(buf, 0, sizeof(buf));
733 memcpy(buf, payload, size);
735 cc_cmd_send(cl, payload, size, MSG_CACHE_FEATURE_TRIGGER);
738 void cc_cacheex_feature_request_save(struct s_client *cl, uint8_t *buf)
740 int32_t field = b2i(2, buf);
742 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 ||cl->account->cacheex.mode == 1))
744 cl->account->cacheex.feature_bitfield = field;
745 // flag 32 => aio-version
746 if(cl->account->cacheex.feature_bitfield & 32)
748 cc_cacheex_feature_trigger(cl, 32, 2);
752 if(cl->typ == 'p' && cl->reader->cacheex.mode == 3)
754 cl->reader->cacheex.feature_bitfield = field;
755 // flag 32 => aio-version
756 if(cl->reader->cacheex.feature_bitfield & 32)
758 cc_cacheex_feature_trigger(cl, 32, 3);
762 if(cl->typ == 'c' && cl->account->cacheex.mode == 3)
764 struct s_auth *acc = cl->account;
765 if(acc)
767 acc->cacheex.feature_bitfield = field;
768 // process feature-specific actions based on feature_bitfield received
770 // flag 1 => set localgenerated only flag
771 if(acc->cacheex.feature_bitfield & 1)
773 cc_cacheex_feature_trigger(cl, 1, 3);
775 // flag 2 => set localgenerated only caids flag
776 if(acc->cacheex.feature_bitfield & 2 && !(acc->cacheex.feature_bitfield & 64))
778 cc_cacheex_feature_trigger(cl, 2, 3);
780 // flag 4 => set cacheex_ecm_filter (extended)
781 if(acc->cacheex.feature_bitfield & 4)
783 cc_cacheex_feature_trigger(cl, 4, 3);
785 // flag 8 => np push after caids
786 if(acc->cacheex.feature_bitfield & 8)
788 cc_cacheex_feature_trigger(cl, 8, 3);
790 // flag 16 => maxhop
791 if(acc->cacheex.feature_bitfield & 16)
793 cc_cacheex_feature_trigger(cl, 16, 3);
795 // flag 32 => aio-version
796 if(acc->cacheex.feature_bitfield & 32)
798 cc_cacheex_feature_trigger(cl, 32, 3);
800 // flag 64 => lg_only_tab
801 if(acc->cacheex.feature_bitfield & 64)
803 cc_cacheex_feature_trigger(cl, 64, 3);
806 else
808 cs_log_dbg(D_CACHEEX, "feature_bitfield save failed - cl, %s", username(cl));
811 else if(cl->typ == 'p' && (cl->reader->cacheex.mode == 2 || cl->reader->cacheex.mode == 1))
813 struct s_reader *rdr = cl->reader;
814 if(rdr)
816 rdr->cacheex.feature_bitfield = field;
817 // process feature-specific actions
819 // flag 1 => set localgenerated_only; cause of rdr->cacheex.localgenerated_only_in is set
820 if(rdr->cacheex.feature_bitfield & 1)
822 cc_cacheex_feature_trigger(cl, 1, 2);
825 // flag 2 => set localgenerated_only_caidtab; cause of rdr->cacheex.localgenerated_only_in_caidtab is set
826 if(rdr->cacheex.feature_bitfield & 2 && !(rdr->cacheex.feature_bitfield & 64))
828 cc_cacheex_feature_trigger(cl, 2, 2);
831 // flag 4 => set cacchex_ecm_filter extendend
832 if(rdr->cacheex.feature_bitfield & 4)
834 cc_cacheex_feature_trigger(cl, 4, 2);
837 // flag 8 => np push after caids
838 if(rdr->cacheex.feature_bitfield & 8)
840 cc_cacheex_feature_trigger(cl, 8, 2);
842 // flag 16 => maxhop
843 if(rdr->cacheex.feature_bitfield & 16)
845 cc_cacheex_feature_trigger(cl, 16, 2);
847 // flag 32 => aio-version
848 if(rdr->cacheex.feature_bitfield & 32)
850 cc_cacheex_feature_trigger(cl, 32, 2);
852 // flag 64 => lg_only_tab
853 if(rdr->cacheex.feature_bitfield & 64)
855 cc_cacheex_feature_trigger(cl, 64, 2);
858 else
860 cs_log_dbg(D_CACHEEX, "feature_bitfield save failed - rdr, %s", username(cl));
865 void cc_cacheex_feature_request_reply(struct s_client *cl)
867 int32_t size = 2;
868 uint8_t rbuf[size];
870 i2b_buf(2, CACHEEX_FEATURES, rbuf);
871 cc_cmd_send(cl, rbuf, size, MSG_CACHE_FEATURE_EXCHANGE_REPLY);
874 void cc_cacheex_feature_request(struct s_client *cl)
876 int32_t size = 2;
877 uint8_t rbuf[2];
878 i2b_buf(2, CACHEEX_FEATURES, rbuf);
879 cc_cmd_send(cl, rbuf, size, MSG_CACHE_FEATURE_EXCHANGE);
881 #endif
883 void cc_cacheex_filter_out(struct s_client *cl)
885 struct s_reader *rdr = (cl->typ == 'c') ? NULL : cl->reader;
886 int i = 0, j;
887 CECSPVALUETAB *filter;
888 int32_t size = 482; // minimal size, keep it <= 512 for max UDP packet size without fragmentation
889 uint8_t buf[482];
890 memset(buf, 0, sizeof(buf));
892 if(rdr && (rdr->cacheex.mode == 2
893 #ifdef CS_CACHEEX_AIO
894 || rdr->cacheex.mode == 1
895 #endif
896 )) // mode == 2 send filters from rdr
898 filter = &rdr->cacheex.filter_caidtab;
899 #ifdef CS_CACHEEX_AIO
900 // if not set, use global settings
901 if(rdr->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab.cevnum > 0)
902 filter = &cfg.cacheex_filter_caidtab;
903 #endif
905 else if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode == 3) // mode == 3 send filters from acc
907 filter = &cl->account->cacheex.filter_caidtab;
908 #ifdef CS_CACHEEX_AIO
909 // if not set, use global settings
910 if(cl->account->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab.cevnum > 0)
911 filter = &cfg.cacheex_filter_caidtab;
912 #endif
914 else
916 return;
919 i2b_buf(2, filter->cevnum, buf + i);
920 i += 2;
922 int32_t max_filters = 30;
923 for(j = 0; j < max_filters; j++)
925 if(filter->cevnum > j)
927 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
928 i2b_buf(4, d->caid, buf + i);
930 i += 4;
933 for(j = 0; j < max_filters; j++)
935 if(filter->cevnum > j)
937 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
938 i2b_buf(4, d->cmask, buf + i);
940 i += 4;
943 for(j = 0; j < max_filters; j++)
945 if(filter->cevnum > j)
947 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
948 i2b_buf(4, d->prid, buf + i);
950 i += 4;
953 for(j = 0; j < max_filters; j++)
955 if(filter->cevnum > j)
957 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
958 i2b_buf(4, d->srvid, buf + i);
960 i += 4;
963 cs_log_dbg(D_CACHEEX, "cacheex: sending push filter request to %s", username(cl));
964 cc_cmd_send(cl, buf, size, MSG_CACHE_FILTER);
967 void cc_cacheex_filter_in(struct s_client *cl, uint8_t *buf)
969 struct s_reader *rdr = (cl->typ == 'c') ? NULL : cl->reader;
970 int i = 0, j;
971 int32_t caid, cmask, provid, srvid;
972 CECSPVALUETAB *filter;
974 // mode == 2 write filters to acc
975 if(cl->typ == 'c' && cl->account && (cl->account->cacheex.mode == 2
976 #ifdef CS_CACHEEX_AIO
977 || cl->account->cacheex.mode == 1
978 #endif
979 ) && cl->account->cacheex.allow_filter == 1)
981 filter = &cl->account->cacheex.filter_caidtab;
983 else if(rdr && rdr->cacheex.mode == 3 && rdr->cacheex.allow_filter == 1) // mode == 3 write filters to rdr
985 filter = &rdr->cacheex.filter_caidtab;
987 else
989 return;
992 cecspvaluetab_clear(filter);
993 i += 2;
995 int32_t max_filters = 30;
996 for(j = 0; j < max_filters; j++)
998 caid = b2i(4, buf + i);
999 if(caid > 0)
1001 CECSPVALUETAB_DATA d;
1002 memset(&d, 0, sizeof(d));
1003 d.caid = b2i(4, buf + i);
1004 cecspvaluetab_add(filter, &d);
1006 i += 4;
1009 for(j = 0; j < max_filters; j++)
1011 cmask = b2i(4, buf + i);
1012 if(j < filter->cevnum)
1014 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
1015 d->cmask = cmask;
1017 i += 4;
1020 for(j = 0; j < max_filters; j++)
1022 provid = b2i(4, buf + i);
1023 if(j < filter->cevnum)
1025 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
1026 d->prid = provid;
1028 i += 4;
1031 for(j = 0; j < max_filters; j++)
1033 srvid = b2i(4, buf + i);
1034 if(j < filter->cevnum)
1036 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
1037 d->srvid = srvid;
1039 i += 4;
1042 cs_log_dbg(D_CACHEEX, "cacheex: received push filter request from %s", username(cl));
1045 static int32_t cc_cacheex_push_chk(struct s_client *cl, struct ecm_request_t *er)
1047 struct cc_data *cc = cl->cc;
1048 if(chk_is_null_nodeid(cc->peer_node_id,8))
1050 cs_log_dbg(D_CACHEEX, "cacheex: NO peer_node_id got yet, skip!");
1051 return 0;
1055 ll_count(er->csp_lastnodes) >= cacheex_maxhop(cl) // check max 10 nodes to push
1056 #ifdef CS_CACHEEX_AIO
1057 && (!er->localgenerated || (er->localgenerated && (ll_count(er->csp_lastnodes) >= cacheex_maxhop_lg(cl)))) // check maxhop_lg if cw is lg-flagged
1058 #endif
1061 #ifdef CS_CACHEEX_AIO
1062 cs_log_dbg(D_CACHEEX, "cacheex: nodelist reached %d nodes(non-lg) or reached %d nodes(lg), no push", cacheex_maxhop(cl), cacheex_maxhop_lg(cl));
1063 #else
1064 cs_log_dbg(D_CACHEEX, "cacheex: nodelist reached %d nodes, no push", cacheex_maxhop(cl));
1065 #endif
1066 return 0;
1069 uint8_t *remote_node = cc->peer_node_id;
1071 // search existing peer nodes
1072 LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
1073 uint8_t *node;
1074 while((node = ll_li_next(li)))
1076 cs_log_dbg(D_CACHEEX, "cacheex: check node %" PRIu64 "X == %" PRIu64 "X ?",
1077 cacheex_node_id(node), cacheex_node_id(remote_node));
1079 if(memcmp(node, remote_node, 8) == 0)
1081 break;
1084 ll_li_destroy(li);
1086 // node found, so we got it from there, do not push
1087 if(node)
1089 cs_log_dbg(D_CACHEEX, "cacheex: node %" PRIu64 "X found in list => skip push!", cacheex_node_id(node));
1090 return 0;
1093 if(!cl->cc)
1095 if(cl->reader && !cl->reader->tcp_connected)
1097 cc_cli_connect(cl);
1101 if(!cc || !cl->udp_fd)
1103 cs_log_dbg(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl));
1104 return 0;
1107 // check if cw is already pushed
1108 if(check_is_pushed(er->cw_cache, cl))
1110 return 0;
1113 return 1;
1116 static int32_t cc_cacheex_push_out(struct s_client *cl, struct ecm_request_t *er)
1118 int8_t rc = (er->rc < E_NOTFOUND) ? E_FOUND : er->rc;
1120 if(rc != E_FOUND && rc != E_UNHANDLED)
1122 return -1; // Maybe later we could support other rcs
1125 if(cl->reader)
1127 if(!cl->reader->tcp_connected)
1129 cc_cli_connect(cl);
1133 struct cc_data *cc = cl->cc;
1134 if(!cc || !cl->udp_fd)
1136 cs_log_dbg(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl));
1137 return (-1);
1140 uint32_t size = sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw) + sizeof(uint8_t) +
1141 #ifdef CS_CACHEEX_AIO
1142 (ll_count(er->csp_lastnodes) + 1) * 8 + sizeof(uint8_t);
1143 #else
1144 (ll_count(er->csp_lastnodes) + 1) * 8;
1145 #endif
1147 uint8_t *buf;
1148 if(!cs_malloc(&buf, size + 20)) // camd35_send() adds +20
1150 return -1;
1153 // build ecm message
1154 //buf[0] = er->caid >> 8;
1155 //buf[1] = er->caid & 0xff;
1156 //buf[2] = er->prid >> 24;
1157 //buf[3] = er->prid >> 16;
1158 //buf[4] = er->prid >> 8;
1159 //buf[5] = er->prid & 0xff;
1160 //buf[10] = er->srvid >> 8;
1161 //buf[11] = er->srvid & 0xff;
1162 buf[12] = (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) & 0xff;
1163 buf[13] = (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) >> 8;
1164 //buf[12] = 0;
1165 //buf[13] = 0;
1166 buf[14] = rc;
1168 i2b_buf(2, er->caid, buf + 0);
1169 i2b_buf(4, er->prid, buf + 2);
1170 i2b_buf(2, er->srvid, buf + 10);
1172 if(er->cwc_cycletime && er->cwc_next_cw_cycle < 2)
1174 buf[18] = er->cwc_cycletime; // contains cwc stage3 cycletime
1176 if(er->cwc_next_cw_cycle == 1)
1178 buf[18] = (buf[18] | 0x80); // set bit 8 to high
1181 if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
1183 cl->account->cwc_info++;
1185 else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
1187 cl->cwc_info++;
1190 cs_log_dbg(D_CWC, "CWC (CE) push to %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X",
1191 username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
1194 buf[19] = er->ecm[0] != 0x80 && er->ecm[0] != 0x81 ? 0 : er->ecm[0];
1196 uint8_t *ofs = buf + 20;
1198 // write oscam ecmd5
1199 memcpy(ofs, er->ecmd5, sizeof(er->ecmd5)); // 16
1200 ofs += sizeof(er->ecmd5);
1202 // write csp hashcode
1203 i2b_buf(4, CSP_HASH_SWAP(er->csp_hash), ofs);
1204 ofs += 4;
1206 // write cw
1207 memcpy(ofs, er->cw, sizeof(er->cw)); // 16
1208 ofs += sizeof(er->cw);
1210 // write node count
1211 *ofs = ll_count(er->csp_lastnodes) + 1;
1212 ofs++;
1214 // write own node
1215 memcpy(ofs, cc->node_id, 8);
1216 ofs += 8;
1218 // write other nodes
1219 LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
1220 uint8_t *node;
1221 while((node = ll_li_next(li)))
1223 memcpy(ofs, node, 8);
1224 ofs += 8;
1226 ll_li_destroy(li);
1228 #ifdef CS_CACHEEX_AIO
1229 // add localgenerated cw-flag
1230 if(er->localgenerated)
1232 *ofs = 1;
1234 else
1236 *ofs = 0xFF;
1238 #endif
1240 int32_t res = cc_cmd_send(cl, buf, size + 20, MSG_CACHE_PUSH);
1241 if(res > 0) // cache-ex is pushing out, so no receive but last_g should be updated otherwise disconnect!
1243 if(cl->reader)
1245 cl->reader->last_s = cl->reader->last_g = time((time_t *)0); // correct
1248 if(cl)
1250 cl->last = time(NULL);
1254 NULLFREE(buf);
1255 return res;
1258 void cc_cacheex_push_in(struct s_client *cl, uint8_t *buf)
1260 struct cc_data *cc = cl->cc;
1261 ECM_REQUEST *er;
1263 if(!cc)
1265 return;
1268 if(cl->reader)
1270 cl->reader->last_s = cl->reader->last_g = time((time_t *)0);
1273 if(cl)
1275 cl->last = time(NULL);
1278 int8_t rc = buf[14];
1279 if(rc != E_FOUND && rc != E_UNHANDLED) // Maybe later we could support other rcs
1281 return;
1284 uint16_t size = buf[12] | (buf[13] << 8);
1285 if(size != sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw))
1287 cs_log_dbg(D_CACHEEX, "cacheex: %s received old cash-push format! data ignored!", username(cl));
1288 return;
1291 if(!(er = get_ecmtask()))
1293 return;
1296 er->caid = b2i(2, buf + 0);
1297 er->prid = b2i(4, buf + 2);
1298 er->srvid = b2i(2, buf + 10);
1299 er->ecm[0] = buf[19] != 0x80 && buf[19] != 0x81 ? 0 : buf[19]; // odd/even byte, usefull to send it over CSP and to check cw for swapping
1300 er->rc = rc;
1302 er->ecmlen = 0;
1304 if(buf[18])
1306 if(buf[18] & (0x01 << 7))
1308 er->cwc_cycletime = (buf[18] & 0x7F); // remove bit 8 to get cycletime
1309 er->cwc_next_cw_cycle = 1;
1311 else
1313 er->cwc_cycletime = buf[18];
1314 er->cwc_next_cw_cycle = 0;
1318 #ifndef CS_CACHEEX_AIO
1319 if (er->cwc_cycletime && er->cwc_next_cw_cycle < 2)
1321 if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
1323 cl->account->cwc_info++;
1325 else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
1327 cl->cwc_info++;
1330 cs_log_dbg(D_CWC, "CWC (CE) received from %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X",
1331 username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
1333 #endif
1335 uint8_t *ofs = buf + 20;
1337 // Read ecmd5
1338 memcpy(er->ecmd5, ofs, sizeof(er->ecmd5)); // 16
1339 ofs += sizeof(er->ecmd5);
1341 if(!check_cacheex_filter(cl, er))
1343 return;
1346 #ifdef CS_CACHEEX_AIO
1347 // check cacheex_ecm_filter
1348 if(check_client(cl) && cl->typ == 'p' && cl->reader && cl->reader->cacheex.mode == 2
1349 && ( (cl->reader->cacheex.filter_caidtab.cevnum > 0 && !chk_csp_ctab(er, &cl->reader->cacheex.filter_caidtab)) // reader cacheex_ecm_filter not matching if set
1350 || (cl->reader->cacheex.filter_caidtab.cevnum == 0 && (cl->reader->cacheex.feature_bitfield & 4) && cfg.cacheex_filter_caidtab_aio.cevnum > 0 && !chk_csp_ctab(er, &cfg.cacheex_filter_caidtab_aio)) // global cacheex_ecm_filter_aio not matching if set
1351 || (cl->reader->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab_aio.cevnum == 0 && cfg.cacheex_filter_caidtab.cevnum > 0 && !chk_csp_ctab(er, &cfg.cacheex_filter_caidtab)) // global cacheex_ecm_filter not matching if set
1355 cs_log_dbg(D_CACHEEX, "cacheex: received cache not matching cacheex_ecm_filter => pushing filter again");
1356 cc_cacheex_filter_out(cl); // get cache != cacheex_ecm_filter, send filter again - remote restarted
1357 if(cl->reader->cacheex.feature_bitfield & 4)
1358 cc_cacheex_feature_trigger(cl, 4, 2);
1359 free_push_in_ecm(er);
1360 return;
1363 if(check_client(cl) && cl->typ == 'c' && cl->account && cl->account->cacheex.mode == 3
1364 && ( (cl->account->cacheex.filter_caidtab.cevnum > 0 && !chk_csp_ctab(er, &cl->account->cacheex.filter_caidtab)) // account cacheex_ecm_filter not matching if set
1365 || (cl->account->cacheex.filter_caidtab.cevnum == 0 && (cl->account->cacheex.feature_bitfield & 4) && cfg.cacheex_filter_caidtab_aio.cevnum > 0 && !chk_csp_ctab(er, &cfg.cacheex_filter_caidtab_aio)) // global cacheex_ecm_filter_aio not matching if set
1366 || (cl->account->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab_aio.cevnum == 0 && cfg.cacheex_filter_caidtab.cevnum > 0 && !chk_csp_ctab(er, &cfg.cacheex_filter_caidtab)) // global cacheex_ecm_filter not matching if set
1370 cs_log_dbg(D_CACHEEX, "cacheex: received cache not matching cacheex_ecm_filter => pushing filter again");
1371 cc_cacheex_filter_out(cl); // get cache != cacheex_ecm_filter, send filter again - remote restarted
1372 if(cl->account->cacheex.feature_bitfield & 4)
1373 cc_cacheex_feature_trigger(cl, 4, 3);
1374 free_push_in_ecm(er);
1375 return;
1377 #endif
1379 // Read csp_hash
1380 er->csp_hash = CSP_HASH_SWAP(b2i(4, ofs));
1381 ofs += 4;
1383 // Read cw
1384 memcpy(er->cw, ofs, sizeof(er->cw)); // 16
1385 ofs += sizeof(er->cw);
1387 // Read lastnode count
1388 uint8_t count = *ofs;
1389 ofs++;
1391 #ifndef CS_CACHEEX_AIO
1392 // check max nodes
1393 if(count > cacheex_maxhop(cl))
1395 cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s",
1396 (int32_t)count, cacheex_maxhop(cl), username(cl));
1398 NULLFREE(er);
1399 return;
1401 #endif
1403 cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes %s", (int32_t)count, username(cl));
1405 // Read lastnodes
1406 uint8_t *data;
1407 if (er)
1409 er->csp_lastnodes = ll_create("csp_lastnodes");
1412 while(count)
1414 if(!cs_malloc(&data, 8))
1416 break;
1419 memcpy(data, ofs, 8);
1420 ofs += 8;
1421 ll_append(er->csp_lastnodes, data);
1422 count--;
1424 cs_log_dbg(D_CACHEEX, "cacheex: received node %" PRIu64 "X %s", cacheex_node_id(data), username(cl));
1427 #ifdef CS_CACHEEX_AIO
1428 if(b2i(1, ofs) == 1)
1430 er->localgenerated = 1;
1431 cs_log_dbg(D_CACHEEX, "cacheex: received ECM with localgenerated flag %04X@%06X:%04X %s", er->caid, er->prid, er->srvid, username(cl));
1433 //check max nodes for lg flagged cw:
1434 if(ll_count(er->csp_lastnodes) > cacheex_maxhop_lg(cl))
1436 cs_log_dbg(D_CACHEEX, "cacheex: received (lg) %d nodes (max=%d), ignored! %s", ll_count(er->csp_lastnodes), cacheex_maxhop_lg(cl), username(cl));
1437 free_push_in_ecm(er);
1438 return;
1441 // without localgenerated flag
1442 else
1444 //check max nodes:
1445 if(ll_count(er->csp_lastnodes) > cacheex_maxhop(cl))
1447 cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s", ll_count(er->csp_lastnodes), cacheex_maxhop(cl), username(cl));
1448 free_push_in_ecm(er);
1449 return;
1453 (cl->typ == 'p' && cl->reader && cl->reader->cacheex.mode == 2 && !chk_srvid_localgenerated_only_exception(er) // cx2
1454 && (
1455 // !aio
1456 (cl->cacheex_aio_checked && !cl->reader->cacheex.feature_bitfield
1457 && (
1458 !cfg.cacheex_lg_only_in_aio_only && !cl->reader->cacheex.lg_only_in_aio_only
1459 && (cfg.cacheex_localgenerated_only_in || cl->reader->cacheex.localgenerated_only_in || ((cl->reader->cacheex.feature_bitfield & 64) && (chk_lg_only(er, &cl->reader->cacheex.lg_only_in_tab) || chk_lg_only(er, &cfg.cacheex_lg_only_in_tab))) || ( !(cl->reader->cacheex.feature_bitfield & 64) && (chk_ctab_ex(er->caid, &cl->reader->cacheex.localgenerated_only_in_caidtab) || chk_ctab_ex(er->caid, &cfg.cacheex_localgenerated_only_in_caidtab))))
1463 // aio
1464 (cl->cacheex_aio_checked && cl->reader->cacheex.feature_bitfield
1465 && (
1466 cfg.cacheex_localgenerated_only_in || cl->reader->cacheex.localgenerated_only_in || ((cl->reader->cacheex.feature_bitfield & 64) && (chk_lg_only(er, &cl->reader->cacheex.lg_only_in_tab) || chk_lg_only(er, &cfg.cacheex_lg_only_in_tab))) || ( !(cl->reader->cacheex.feature_bitfield & 64) && (chk_ctab_ex(er->caid, &cl->reader->cacheex.localgenerated_only_in_caidtab) || chk_ctab_ex(er->caid, &cfg.cacheex_localgenerated_only_in_caidtab)))
1472 (cl->typ == 'c' && cl->account && cl->account->cacheex.mode == 3 && !chk_srvid_localgenerated_only_exception(er) // cx3
1473 && (
1474 // !aio
1475 (cl->cacheex_aio_checked && !cl->account->cacheex.feature_bitfield
1476 && (
1477 !cfg.cacheex_lg_only_in_aio_only && !cl->account->cacheex.lg_only_in_aio_only
1478 && (cfg.cacheex_localgenerated_only_in || cl->account->cacheex.localgenerated_only_in || ((cl->account->cacheex.feature_bitfield & 64) && (chk_lg_only(er, &cl->account->cacheex.lg_only_in_tab) || chk_lg_only(er, &cfg.cacheex_lg_only_in_tab))) || ( !(cl->account->cacheex.feature_bitfield & 64) && (chk_ctab_ex(er->caid, &cl->account->cacheex.localgenerated_only_in_caidtab) || chk_ctab_ex(er->caid, &cfg.cacheex_localgenerated_only_in_caidtab))))
1482 // aio
1483 (cl->cacheex_aio_checked && cl->account->cacheex.feature_bitfield
1484 && (
1485 cfg.cacheex_localgenerated_only_in || cl->account->cacheex.localgenerated_only_in || ((cl->account->cacheex.feature_bitfield & 64) && (chk_lg_only(er, &cl->account->cacheex.lg_only_in_tab) || chk_lg_only(er, &cfg.cacheex_lg_only_in_tab))) || ( !(cl->account->cacheex.feature_bitfield & 64) && (chk_ctab_ex(er->caid, &cl->account->cacheex.localgenerated_only_in_caidtab) || chk_ctab_ex(er->caid, &cfg.cacheex_localgenerated_only_in_caidtab)))
1492 cs_log_dbg(D_CACHEEX, "cacheex: drop ECM without localgenerated flag %04X@%06X:%04X %s", er->caid, er->prid, er->srvid, username(cl));
1493 free_push_in_ecm(er);
1494 return;
1497 #endif
1499 // for compatibility: add peer node if no node received
1500 if(!ll_count(er->csp_lastnodes))
1502 if(!cs_malloc(&data, 8))
1504 return;
1507 memcpy(data, cc->peer_node_id, 8);
1508 ll_append(er->csp_lastnodes, data);
1509 cs_log_dbg(D_CACHEEX, "cacheex: added missing remote node id %" PRIu64 "X", cacheex_node_id(data));
1512 #ifdef CS_CACHEEX_AIO
1513 if (er->cwc_cycletime && er->cwc_next_cw_cycle < 2)
1515 if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
1517 cl->account->cwc_info++;
1519 else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
1521 cl->cwc_info++;
1524 cs_log_dbg(D_CWC, "CWC (CE) received from %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X",
1525 username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
1527 #endif
1529 cacheex_add_to_cache(cl, er);
1532 void cc_cacheex_module_init(struct s_module *ph)
1534 ph->c_cache_push = cc_cacheex_push_out;
1535 ph->c_cache_push_chk = cc_cacheex_push_chk;
1538 #endif