fixed CMake warnings on Debian 11
[oscam.git] / module-camd35-cacheex.c
blobac21c11638672ebe32357c6d1dbf7f84fb73334b
1 #define MODULE_LOG_PREFIX "camd35"
3 #include "globals.h"
4 #include "oscam-array.h"
6 #if defined(CS_CACHEEX) && (defined(MODULE_CAMD35) || defined(MODULE_CAMD35_TCP))
8 #include "module-cacheex.h"
9 #include "module-camd35.h"
10 #include "module-camd35-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-reader.h"
16 #ifdef CS_CACHEEX_AIO
17 #include "oscam-chk.h"
18 #include "oscam-config.h"
19 #endif
21 uint8_t camd35_node_id[8];
23 #define CSP_HASH_SWAP(n) (((((uint32_t)(n) & 0xFF)) << 24) | \
24 ((((uint32_t)(n) & 0xFF00)) << 8) | \
25 ((((uint32_t)(n) & 0xFF0000)) >> 8) | \
26 ((((uint32_t)(n) & 0xFF000000)) >> 24))
28 #ifdef CS_CACHEEX_AIO
29 void camd35_cacheex_feature_trigger_in(struct s_client *cl, uint8_t *buf)
31 int32_t feature = 0;
32 uint16_t i = 20;
33 uint8_t filter_count;
34 uint8_t j, k, l, rc;
35 feature = buf[21] | (buf[20] << 8);
36 FTAB *lgonly_tab;
38 // check client & cacheex-mode
39 if(
40 !check_client(cl) ||
42 (cl->typ == 'c' && cl->account->cacheex.mode > 0) ||
43 (cl->typ == 'p' && cl->reader->cacheex.mode > 0)
47 return;
50 switch(feature)
52 // set localgenerated only
53 case 1:
54 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1))
56 if(cfg.cacheex_lg_only_remote_settings || cl->account->cacheex.lg_only_remote_settings)
57 cl->account->cacheex.localgenerated_only = buf[24];
58 else if(buf[24])
59 cl->account->cacheex.localgenerated_only = buf[24];
61 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3)
63 if(cfg.cacheex_lg_only_remote_settings || cl->reader->cacheex.lg_only_remote_settings)
64 cl->reader->cacheex.localgenerated_only = buf[24];
65 else if(buf[24])
66 cl->reader->cacheex.localgenerated_only = buf[24];
68 break;
69 // set localgenerated only caidtab
70 case 2:
71 filter_count = buf[i+4];
72 i += 5;
74 memset(&lgonly_tab, 0, sizeof(lgonly_tab));
76 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1))
78 lgonly_tab = &cl->account->cacheex.lg_only_tab;
80 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3)
82 lgonly_tab = &cl->reader->cacheex.lg_only_tab;
84 else
86 return;
89 // remotesettings enabled - replace local settings
90 if(cfg.cacheex_lg_only_remote_settings ||
92 (cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1) && cl->account->cacheex.lg_only_remote_settings)
93 || (cl->typ == 'p' && cl->reader->cacheex.mode == 3 && cl->reader->cacheex.lg_only_remote_settings)
97 ftab_clear(lgonly_tab);
99 for(j = 0; j < filter_count; j++)
101 FILTER d;
102 memset(&d, 0, sizeof(d));
104 d.caid = b2i(2, buf + i);
105 i += 2;
107 d.nprids = 1;
108 d.prids[0] = NO_PROVID_VALUE;
110 ftab_add(lgonly_tab, &d);
113 // remotesettings disabled - write additional remote-caids received
114 else
116 for(j = 0; j < filter_count; j++)
118 FILTER d;
119 memset(&d, 0, sizeof(d));
121 d.caid = b2i(2, buf + i);
122 i += 2;
124 d.nprids = 1;
125 d.prids[0] = NO_PROVID_VALUE;
127 if(!chk_lg_only_cp(d.caid, d.prids[0], lgonly_tab))
129 cs_log_dbg(D_CACHEEX, "%04X:%06X not found in local settings - adding them", d.caid, d.prids[0]);
131 for(l = rc = 0; (!rc) && (l < lgonly_tab->nfilts); l++)
133 if(lgonly_tab->filts[l].caid == d.caid)
135 rc = 1;
137 if(lgonly_tab->filts[l].nprids+1 <= CS_MAXPROV)
139 lgonly_tab->filts[l].prids[lgonly_tab->filts[l].nprids] = d.prids[0];
140 lgonly_tab->filts[l].nprids++;
142 else
144 cs_log_dbg(D_CACHEEX, "error: cacheex_lg_only_tab -> max. number(%i) of providers reached", CS_MAXPROV);
148 if(!rc)
150 ftab_add(lgonly_tab, &d);
155 break;
156 // set cacheex_ecm_filter - extended
157 case 4:
158 filter_count = buf[i+4];
159 i += 5;
161 CECSPVALUETAB *filter;
162 memset(&filter, 0, sizeof(filter));
164 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1) && cl->account->cacheex.allow_filter)
166 filter = &cl->account->cacheex.filter_caidtab;
168 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3 && cl->reader->cacheex.allow_filter)
170 filter = &cl->reader->cacheex.filter_caidtab;
172 else
174 return;
177 cecspvaluetab_clear(filter);
179 for(j = 0; j < filter_count; j++)
181 int32_t caid = -1, cmask = -1, provid = -1, srvid = -1;
182 CECSPVALUETAB_DATA d;
183 memset(&d, 0, sizeof(d));
185 caid = b2i(2, buf + i);
186 if(caid == 0xFFFF) caid = -1;
187 i += 2;
189 cmask = b2i(2, buf + i);
190 if(cmask == 0xFFFF) cmask = -1;
191 i += 2;
193 provid = b2i(3, buf + i);
194 if(provid == 0xFFFFFF) provid = -1;
195 i += 3;
197 srvid = b2i(2, buf + i);
198 if(srvid == 0xFFFF) srvid = -1;
199 i += 2;
201 if(caid > 0)
203 d.caid = caid;
204 d.cmask = cmask;
205 d.prid = provid;
206 d.srvid = srvid;
207 cecspvaluetab_add(filter, &d);
210 break;
211 // no push after
212 case 8: ;
213 CAIDVALUETAB *ctab;
214 memset(&ctab, 0, sizeof(ctab));
216 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1))
218 ctab = &cl->account->cacheex.cacheex_nopushafter_tab;
220 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3)
222 ctab = &cl->reader->cacheex.cacheex_nopushafter_tab;
224 else
226 return;
229 filter_count = buf[i+4];
230 i += 5;
232 caidvaluetab_clear(ctab);
234 for(j = 0; j < filter_count; j++)
236 uint16_t caid = 0, value = 0;
237 CAIDVALUETAB_DATA d;
238 memset(&d, 0, sizeof(d));
240 caid = b2i(2, buf + i);
241 if(caid == 0xFFFF) caid = -1;
242 i += 2;
244 value = b2i(2, buf + i);
245 if(value == 0xFFFF) value = -1;
246 i += 2;
248 if(caid > 0)
250 d.caid = caid;
251 d.value = value;
252 caidvaluetab_add(ctab, &d);
255 break;
256 // max hop
257 case 16:
258 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1) && cl->account->cacheex.allow_maxhop)
260 cl->account->cacheex.maxhop = buf[24];
261 cl->account->cacheex.maxhop_lg = buf[25];
263 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3 && cl->reader->cacheex.allow_maxhop)
265 cl->reader->cacheex.maxhop = buf[24];
266 cl->reader->cacheex.maxhop_lg = buf[25];
268 break;
269 // aio-version
270 case 32:
271 if(cl->typ == 'c' && cl->account->cacheex.mode > 0)
273 char *ofs = (char *)buf + i + 4;
274 cs_strncpy(cl->account->cacheex.aio_version, ofs, sizeof(cl->account->cacheex.aio_version));
276 else if(cl->typ == 'p' && cl->reader->cacheex.mode > 0)
278 char *ofs = (char *)buf + i + 4;
279 cs_strncpy(cl->reader->cacheex.aio_version, ofs, sizeof(cl->reader->cacheex.aio_version));
281 break;
282 // lg_only_tab caid:prov1[,provN][;caid:prov]
283 case 64: ;
284 memset(&lgonly_tab, 0, sizeof(lgonly_tab));
286 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1))
288 lgonly_tab = &cl->account->cacheex.lg_only_tab;
290 else if(cl->typ == 'p' && cl->reader->cacheex.mode == 3)
292 lgonly_tab = &cl->reader->cacheex.lg_only_tab;
294 else
296 return;
299 filter_count = buf[i+4];
300 i += 5;
302 // remotesettings enabled - replace local settings
303 if(cfg.cacheex_lg_only_remote_settings ||
305 (cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1) && cl->account->cacheex.lg_only_remote_settings)
306 || (cl->typ == 'p' && cl->reader->cacheex.mode == 3 && cl->reader->cacheex.lg_only_remote_settings)
307 || !lgonly_tab->nfilts
311 ftab_clear(lgonly_tab);
313 for(j = 0; j < filter_count; j++)
315 FILTER d;
316 memset(&d, 0, sizeof(d));
318 d.caid = b2i(2, buf + i);
319 i += 2;
321 d.nprids = b2i(1, buf + i);
322 i += 1;
324 for(k=0; k < d.nprids; k++)
326 d.prids[k] = b2i(3, buf + i);
327 i += 3;
329 ftab_add(lgonly_tab, &d);
333 // remotesettings disabled - write additional remote-caid/provids received
334 else
336 for(j = 0; j < filter_count; j++)
338 FILTER d;
339 memset(&d, 0, sizeof(d));
341 d.caid = b2i(2, buf + i);
342 i += 2;
344 d.nprids = b2i(1, buf + i);
345 i += 1;
347 for(k=0; k < d.nprids; k++)
349 d.prids[k] = b2i(3, buf + i);
350 i += 3;
352 if(!chk_ident_filter(d.caid, d.prids[k], lgonly_tab))
354 cs_log_dbg(D_CACHEEX, "%04X:%06X not found in local settings - adding them", d.caid, d.prids[k]);
356 for(l = rc = 0; (!rc) && (l < lgonly_tab->nfilts); l++)
358 if(lgonly_tab->filts[l].caid == d.caid)
360 rc = 1;
362 if(lgonly_tab->filts[l].nprids+1 <= CS_MAXPROV)
364 lgonly_tab->filts[l].prids[lgonly_tab->filts[l].nprids] = d.prids[k];
365 lgonly_tab->filts[l].nprids++;
367 else
369 cs_log_dbg(D_CACHEEX, "error: cacheex_lg_only_tab -> max. number of providers reached");
373 if(!rc)
375 ftab_add(lgonly_tab, &d);
381 break;
382 default:
383 return;
387 void camd35_cacheex_feature_trigger(struct s_client *cl, int32_t feature, uint8_t mode)
389 // size: 20 + (feature-bitfield & mask: 2) + payload-size: 2 + feature-payload :x
390 uint16_t size = 20 + 2 + 2;
391 int i = 0;
392 uint8_t j;
393 uint8_t payload[MAX_ECM_SIZE-size];
394 memset(payload, 0, sizeof(payload));
396 // check client & cacheex-mode
397 if(!check_client(cl))
399 return;
402 switch(feature)
404 FTAB *lgonly_tab;
405 // set localgenerated only
406 case 1:
407 size += 1;
408 if(size < 32)
409 size = 32;
411 // bitfield
412 i2b_buf(2, feature, payload + i);
413 i += 2;
414 // payload-size
415 i2b_buf(2, 1, payload + i);
416 i += 2;
417 // set payload
418 if(mode == 2)
420 if(cl->reader->cacheex.localgenerated_only_in)
421 payload[i] = cl->reader->cacheex.localgenerated_only_in;
422 else
423 payload[i] = cfg.cacheex_localgenerated_only_in;
425 else if(mode == 3)
427 if(cl->account->cacheex.localgenerated_only_in)
428 payload[i] = cl->account->cacheex.localgenerated_only_in;
429 else
430 payload[i] = cfg.cacheex_localgenerated_only_in;
433 break;
434 // set localgenerated only caidtab; cx-aio < 9.2.6-04
435 case 2: ;
436 if(mode == 2)
438 lgonly_tab = &cl->reader->cacheex.lg_only_in_tab;
439 if(!lgonly_tab->nfilts)
440 lgonly_tab = &cfg.cacheex_lg_only_in_tab;
442 else if(mode == 3)
444 lgonly_tab = &cl->account->cacheex.lg_only_in_tab;
445 if(!lgonly_tab->nfilts)
446 lgonly_tab = &cfg.cacheex_lg_only_in_tab;
448 else
450 return;
453 size += (lgonly_tab->nfilts * 2 + 1);
454 if(size < 32)
455 size = 32;
457 // bitfield
458 i2b_buf(2, feature, payload + i);
459 i += 2;
460 // payload-size
461 if((lgonly_tab->nfilts * 2 + 1) > (int)sizeof(payload))
463 cs_log_dbg(D_CACHEEX, "ERROR: too much localgenerated only caidtab-entries (max. 255)");
464 return;
466 i2b_buf(2, (lgonly_tab->nfilts * 2 + 1), payload + i); // n * caid + ctnum
467 i += 2;
468 // set payload
469 if(lgonly_tab->nfilts > 255)
471 cs_log_dbg(D_CACHEEX, "ERROR: too much localgenerated only caidtab-entries (max. 255)");
472 return;
474 payload[i] = lgonly_tab->nfilts;
475 i += 1;
477 for(j = 0; j < lgonly_tab->nfilts; j++)
479 FILTER *d = &lgonly_tab->filts[j];
480 if(d->caid)
482 i2b_buf(2, d->caid, payload + i);
483 i += 2;
485 else
487 continue;
490 break;
491 // cacchex_ecm_filter extendend
492 case 4: ;
493 CECSPVALUETAB *filter;
494 if(mode == 2)
496 filter = &cl->reader->cacheex.filter_caidtab;
497 // if not set, use global settings
498 if(cl->reader->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab.cevnum > 0)
499 filter = &cfg.cacheex_filter_caidtab;
500 // if aio, use global aio settings
501 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))
502 filter = &cfg.cacheex_filter_caidtab_aio;
504 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(cl->account->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab_aio.cevnum > 0 && cl->cacheex_aio_checked && (cl->account->cacheex.feature_bitfield & 4))
512 filter = &cfg.cacheex_filter_caidtab_aio;
514 else
516 return;
519 size += (filter->cevnum * 9 + 1);
520 if(size < 32)
521 size = 32;
523 // bitfield
524 i2b_buf(2, feature, payload + i);
525 i += 2;
526 // payload-size
527 if((filter->cevnum * 9 + 1) > (int)sizeof(payload))
529 cs_log_dbg(D_CACHEEX, "ERROR: to much cacheex_ecm_filter-entries (max. 63), only 15 default camd3-filters sent");
530 return;
532 i2b_buf(2, (filter->cevnum * 9 + 1), payload + i); // n * (caid2,mask2,provid3,srvid2) + ctnum1
533 i += 2;
534 // set payload
535 payload[i] = filter->cevnum;
536 i += 1;
538 for(j = 0; j < filter->cevnum; j++)
540 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
541 if(d->caid)
543 i2b_buf(2, d->caid, payload + i);
544 i += 2;
546 if(d->cmask)
548 i2b_buf(2, d->cmask, payload + i);
550 i += 2;
552 if(d->prid)
554 i2b_buf(3, d->prid, payload + i);
556 i += 3;
558 if(d->srvid)
560 i2b_buf(2, d->srvid, payload + i);
562 i += 2;
565 camd35_cacheex_send_push_filter(cl, 2);
566 break;
567 // no push after
568 case 8: ;
569 CAIDVALUETAB *ctab;
570 if(mode == 2)
572 ctab = &cl->reader->cacheex.cacheex_nopushafter_tab;
573 if(!ctab->cvnum)
574 ctab = &cfg.cacheex_nopushafter_tab;
576 else if(mode == 3)
578 ctab = &cl->account->cacheex.cacheex_nopushafter_tab;
579 if(!ctab->cvnum)
580 ctab = &cfg.cacheex_nopushafter_tab;
582 else
584 return;
587 size += (ctab->cvnum * 4 + 1);
588 if(size < 32)
589 size = 32;
591 // bitfield
592 i2b_buf(2, feature, payload + i);
593 i += 2;
594 // payload-size
595 if((ctab->cvnum * 4 + 1) > (int)sizeof(payload))
597 cs_log_dbg(D_CACHEEX, "ERROR: to much no push after caidtvalueab-entries (max. 255)");
598 return;
600 i2b_buf(2, (ctab->cvnum * 4 + 1), payload + i); // n * (caid2+value2) + cvnum
601 i += 2;
602 // set payload
603 if(ctab->cvnum > 255)
605 cs_log_dbg(D_CACHEEX, "ERROR: to much no push after caidtvalueab-entries (max. 255)");
606 return;
608 payload[i] = ctab->cvnum;
609 i += 1;
611 for(j = 0; j < ctab->cvnum; j++)
613 CAIDVALUETAB_DATA *d = &ctab->cvdata[j];
614 if(d->caid)
616 i2b_buf(2, d->caid, payload + i);
617 i += 2;
618 i2b_buf(2, d->value, payload + i);
619 i += 2;
621 else
623 continue;
626 break;
627 // maxhop
628 case 16:
629 size += 2;
630 if(size < 32)
631 size = 32;
633 // bitfield
634 i2b_buf(2, feature, payload + i);
635 i += 2;
636 // payload-size
637 i2b_buf(2, 2, payload + i);
638 i += 2;
639 // set payload
640 if(mode == 2)
642 if(cl->reader->cacheex.maxhop)
643 payload[i] = cl->reader->cacheex.maxhop;
644 else
645 payload[i] = 0;
646 i += 1;
648 if(cl->reader->cacheex.maxhop_lg)
649 payload[i] = cl->reader->cacheex.maxhop_lg;
650 else
651 payload[i] = 0;
653 else if(mode == 3)
655 if(cl->account->cacheex.maxhop)
656 payload[i] = cl->account->cacheex.maxhop;
657 else
658 payload[i] = 0;
659 i += 1;
661 if(cl->account->cacheex.maxhop_lg)
662 payload[i] = cl->account->cacheex.maxhop_lg;
663 else
664 payload[i] = 0;
666 break;
667 // aio-version
668 case 32: ;
669 size += 12;
670 if(size < 32)
671 size = 32;
673 uint8_t token[12];
675 // bitfield
676 i2b_buf(2, feature, payload + i);
677 i += 2;
678 // payload-size
679 i2b_buf(2, sizeof(token), payload + i);
680 i += 2;
681 // set payload
683 snprintf((char *)token, sizeof(token), "%s", CS_AIO_VERSION);
684 uint8_t *ofs = payload + i;
685 memcpy(ofs, token, sizeof(token));
686 break;
687 // lg_only_tab
688 case 64: ;
689 // bitfield
690 i2b_buf(2, feature, payload + i);
691 i += 2;
693 if(mode == 2)
695 lgonly_tab = &cl->reader->cacheex.lg_only_in_tab;
696 if(!lgonly_tab->nfilts)
697 lgonly_tab = &cfg.cacheex_lg_only_in_tab;
699 else if(mode == 3)
701 lgonly_tab = &cl->account->cacheex.lg_only_in_tab;
702 if(!lgonly_tab->nfilts)
703 lgonly_tab = &cfg.cacheex_lg_only_in_tab;
705 else
707 return;
710 char *cx_aio_ftab;
711 cx_aio_ftab = cxaio_ftab_to_buf(lgonly_tab);
712 if(cs_strlen(cx_aio_ftab) > 0 && cx_aio_ftab[0] != '\0')
714 size += cs_strlen(cx_aio_ftab) * sizeof(char);
716 // payload-size
717 i2b_buf(2, cs_strlen(cx_aio_ftab), payload + i);
718 i += 2;
720 // filter counter
721 payload[i] = lgonly_tab->nfilts;
722 i += 1;
724 for(j=0; j<cs_strlen(cx_aio_ftab); j+=2)
726 payload[i] = (gethexval(cx_aio_ftab[j]) << 4) | gethexval(cx_aio_ftab[j + 1]);
727 i++;
731 if(size < 32)
732 size = 32;
734 NULLFREE(cx_aio_ftab);
735 break;
736 default:
737 return;
740 uint8_t buf[size];
741 memset(buf, 0, sizeof(buf));
742 buf[0] = 0x42; // camd35_cacheex_feature_trigger
744 buf[1] = (size - 20) & 0xFF;
745 buf[2] = (size - 20) >> 8;
747 uint8_t *ofs = buf + 20;
748 memcpy(ofs, payload, size - 20);
750 camd35_send_without_timeout(cl, buf, size-20); //send adds +20
753 void camd35_cacheex_feature_request_save(struct s_client *cl, uint8_t *buf)
755 int32_t field = b2i(2, (buf+20));
757 if(cl->typ == 'c' && (cl->account->cacheex.mode == 2 || cl->account->cacheex.mode == 1))
759 cl->account->cacheex.feature_bitfield = field;
760 // flag 32 => aio-version
761 if(cl->account->cacheex.feature_bitfield & 32)
763 camd35_cacheex_feature_trigger(cl, 32, 2);
767 if(cl->typ == 'p' && cl->reader->cacheex.mode == 3)
769 cl->reader->cacheex.feature_bitfield = field;
770 // flag 32 => aio-version
771 if(cl->reader->cacheex.feature_bitfield & 32)
773 camd35_cacheex_feature_trigger(cl, 32, 3);
777 if(cl->typ == 'c' && cl->account->cacheex.mode == 3)
779 struct s_auth *acc = cl->account;
780 if(acc)
782 acc->cacheex.feature_bitfield = field;
783 // process feature-specific actions based on feature_bitfield received
785 // flag 1 => set localgenerated only flag
786 if(acc->cacheex.feature_bitfield & 1)
788 camd35_cacheex_feature_trigger(cl, 1, 3);
790 // flag 2 => set localgenerated only caids flag
791 if(acc->cacheex.feature_bitfield & 2 && !(acc->cacheex.feature_bitfield & 64))
793 camd35_cacheex_feature_trigger(cl, 2, 3);
795 // flag 4 => set cacheex_ecm_filter (extended)
796 if(acc->cacheex.feature_bitfield & 4)
798 camd35_cacheex_feature_trigger(cl, 4, 3);
800 // flag 8 => np push after caids
801 if(acc->cacheex.feature_bitfield & 8)
803 camd35_cacheex_feature_trigger(cl, 8, 3);
805 // flag 16 => maxhop
806 if(acc->cacheex.feature_bitfield & 16)
808 camd35_cacheex_feature_trigger(cl, 16, 3);
810 // flag 32 => aio-version
811 if(acc->cacheex.feature_bitfield & 32)
813 camd35_cacheex_feature_trigger(cl, 32, 3);
815 // flag 64 => lg_only_tab
816 if(acc->cacheex.feature_bitfield & 64)
818 camd35_cacheex_feature_trigger(cl, 64, 3);
821 else
823 cs_log_dbg(D_CACHEEX, "feature_bitfield save failed - cl, %s", username(cl));
826 else if(cl->typ == 'p' && (cl->reader->cacheex.mode == 2 || cl->reader->cacheex.mode == 1))
828 struct s_reader *rdr = cl->reader;
829 if(rdr)
831 rdr->cacheex.feature_bitfield = field;
832 // process feature-specific actions
834 // flag 1 => set localgenerated_only; cause of rdr->cacheex.localgenerated_only_in is set
835 if(rdr->cacheex.feature_bitfield & 1)
837 camd35_cacheex_feature_trigger(cl, 1, 2);
840 // flag 2 => set lg_only_tab; cause of rdr->cacheex.lg_only_in_tab is set
841 if(rdr->cacheex.feature_bitfield & 2 && !(rdr->cacheex.feature_bitfield & 64))
843 camd35_cacheex_feature_trigger(cl, 2, 2);
846 // // flag 4 => set cacheex_ecm_filter (extended)
847 if(rdr->cacheex.feature_bitfield & 4)
849 camd35_cacheex_feature_trigger(cl, 4, 2);
852 // flag 8 => no push after caids
853 if(rdr->cacheex.feature_bitfield & 8)
855 camd35_cacheex_feature_trigger(cl, 8, 2);
857 // flag 16 => maxhop
858 if(rdr->cacheex.feature_bitfield & 16)
860 camd35_cacheex_feature_trigger(cl, 16, 2);
862 // flag 32 => aio-version
863 if(rdr->cacheex.feature_bitfield & 32)
865 camd35_cacheex_feature_trigger(cl, 32, 2);
867 // flag 64 => lg_only_tab
868 if(rdr->cacheex.feature_bitfield & 64)
870 camd35_cacheex_feature_trigger(cl, 64, 2);
873 else
875 cs_log_dbg(D_CACHEEX, "feature_bitfield save failed - rdr, %s", username(cl));
880 void camd35_cacheex_feature_request(struct s_client *cl)
882 int i = 20;
884 uint8_t buf[32];
885 memset(buf, 0, sizeof(buf));
886 buf[0] = 0x40;
887 buf[1] = 12;
888 buf[2] = 0;
890 i2b_buf(2, CACHEEX_FEATURES, buf + i); // set feature-list here
892 camd35_send_without_timeout(cl, buf, 12); //send adds +20
895 void camd35_cacheex_feature_request_reply(struct s_client *cl, uint8_t *buf)
897 camd35_cacheex_feature_request_save(cl, buf);
898 int i = 20;
900 uint8_t rbuf[32];
901 memset(rbuf, 0, sizeof(rbuf));
902 rbuf[0] = 0x41;
903 rbuf[1] = 12;
904 rbuf[2] = 0;
906 i2b_buf(2, CACHEEX_FEATURES, rbuf + i);
908 camd35_send_without_timeout(cl, rbuf, 12); //send adds +20
910 #endif
914 * send push filter
916 void camd35_cacheex_send_push_filter(struct s_client *cl, uint8_t mode)
918 struct s_reader *rdr = cl->reader;
919 int i = 20, j;
920 CECSPVALUETAB *filter;
921 //maximum size: 20+255
922 uint8_t buf[20+242];
923 memset(buf, 0, sizeof(buf));
924 buf[0] = 0x3c;
925 buf[1] = 0xf2;
927 //mode==2 send filters from rdr
928 if(mode == 2 && rdr)
930 filter = &rdr->cacheex.filter_caidtab;
931 #ifdef CS_CACHEEX_AIO
932 // if not set, use global settings
933 if(rdr->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab.cevnum > 0)
934 filter = &cfg.cacheex_filter_caidtab;
935 #endif
937 //mode==3 send filters from acc
938 else if(mode == 3 && cl->typ == 'c' && cl->account)
940 filter = &cl->account->cacheex.filter_caidtab;
941 #ifdef CS_CACHEEX_AIO
942 // if not set, use global settings
943 if(cl->account->cacheex.filter_caidtab.cevnum == 0 && cfg.cacheex_filter_caidtab.cevnum > 0)
944 filter = &cfg.cacheex_filter_caidtab;
945 #endif
947 else {
948 return;
951 i2b_buf(2, filter->cevnum, buf + i);
952 i += 2;
954 int32_t max_filters = 15;
955 for(j=0; j<max_filters; j++)
957 if(filter->cevnum > j){
958 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
959 i2b_buf(4, d->caid, buf + i);
961 i += 4;
964 for(j=0; j<max_filters; j++)
966 if(filter->cevnum > j){
967 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
968 i2b_buf(4, d->cmask, buf + i);
970 i += 4;
973 for(j=0; j<max_filters; j++)
975 if(filter->cevnum > j){
976 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
977 i2b_buf(4, d->prid, buf + i);
979 i += 4;
982 for(j=0; j<max_filters; j++)
984 if(filter->cevnum > j){
985 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
986 i2b_buf(4, d->srvid, buf + i);
988 i += 4;
991 cs_log_dbg(D_CACHEEX, "cacheex: sending push filter request to %s", username(cl));
992 camd35_send_without_timeout(cl, buf, 242); //send adds +20
996 * store received push filter
998 static void camd35_cacheex_push_filter(struct s_client *cl, uint8_t *buf, uint8_t mode)
1000 struct s_reader *rdr = cl->reader;
1001 int i = 20, j;
1002 int32_t caid, cmask, provid, srvid;
1003 CECSPVALUETAB *filter;
1005 //mode==2 write filters to acc
1006 if(mode == 2 && cl->typ == 'c' && cl->account && cl->account->cacheex.mode == 2
1007 && cl->account->cacheex.allow_filter == 1)
1009 filter = &cl->account->cacheex.filter_caidtab;
1011 //mode==3 write filters to rdr
1012 else if(mode == 3 && rdr && rdr->cacheex.allow_filter == 1)
1014 filter = &rdr->cacheex.filter_caidtab;
1016 else {
1017 return;
1020 cecspvaluetab_clear(filter);
1021 i += 2;
1023 int32_t max_filters = 15;
1024 for(j=0; j<max_filters; j++)
1026 caid = b2i(4, buf + i);
1027 if(caid > 0){
1028 CECSPVALUETAB_DATA d;
1029 memset(&d, 0, sizeof(d));
1030 d.caid = b2i(4, buf + i);
1031 cecspvaluetab_add(filter, &d);
1033 i += 4;
1036 for(j=0; j<max_filters; j++)
1038 cmask = b2i(4, buf + i);
1039 if(j<filter->cevnum){
1040 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
1041 d->cmask = cmask;
1043 i += 4;
1046 for(j=0; j<max_filters; j++)
1048 provid = b2i(4, buf + i);
1049 if(j<filter->cevnum){
1050 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
1051 d->prid = provid;
1053 i += 4;
1056 for(j=0; j<max_filters; j++)
1058 srvid = b2i(4, buf + i);
1059 if(j<filter->cevnum){
1060 CECSPVALUETAB_DATA *d = &filter->cevdata[j];
1061 d->srvid = srvid;
1063 i += 4;
1066 cs_log_dbg(D_CACHEEX, "cacheex: received push filter request from %s", username(cl));
1069 static int32_t camd35_cacheex_push_chk(struct s_client *cl, ECM_REQUEST *er)
1072 ll_count(er->csp_lastnodes) >= cacheex_maxhop(cl) // check max 10 nodes to push
1073 #ifdef CS_CACHEEX_AIO
1074 && (!er->localgenerated || (er->localgenerated && (ll_count(er->csp_lastnodes) >= cacheex_maxhop_lg(cl)))) // check maxhop_lg if cw is lg-flagged
1075 #endif
1078 #ifdef CS_CACHEEX_AIO
1079 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));
1080 #else
1081 cs_log_dbg(D_CACHEEX, "cacheex: nodelist reached %d nodes, no push", cacheex_maxhop(cl));
1082 #endif
1083 return 0;
1086 if(cl->reader)
1088 if(!cl->reader->tcp_connected)
1090 cs_log_dbg(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl));
1091 return 0;
1095 //if(chk_is_null_nodeid(remote_node,8)){
1096 if(!cl->ncd_skey[8])
1098 cs_log_dbg(D_CACHEEX, "cacheex: NO peer_node_id got yet, skip!");
1099 return 0;
1102 uint8_t *remote_node = cl->ncd_skey; //it is sended by reader(mode 2) or client (mode 3) each 30s using keepalive msgs
1104 //search existing peer nodes:
1105 LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
1106 uint8_t *node;
1107 while((node = ll_li_next(li)))
1109 cs_log_dbg(D_CACHEEX, "cacheex: check node %" PRIu64 "X == %" PRIu64 "X ?", cacheex_node_id(node), cacheex_node_id(remote_node));
1110 if(memcmp(node, remote_node, 8) == 0)
1112 break;
1115 ll_li_destroy(li);
1117 //node found, so we got it from there, do not push:
1118 if(node)
1120 cs_log_dbg(D_CACHEEX,
1121 "cacheex: node %" PRIu64 "X found in list => skip push!", cacheex_node_id(node));
1122 return 0;
1125 //check if cw is already pushed
1126 if(check_is_pushed(er->cw_cache, cl))
1127 { return 0; }
1129 cs_log_dbg(D_CACHEEX, "cacheex: push ok %" PRIu64 "X to %" PRIu64 "X %s", cacheex_node_id(camd35_node_id), cacheex_node_id(remote_node), username(cl));
1131 return 1;
1134 static int32_t camd35_cacheex_push_out(struct s_client *cl, struct ecm_request_t *er)
1136 int8_t rc = (er->rc < E_NOTFOUND) ? E_FOUND : er->rc;
1137 if(rc != E_FOUND && rc != E_UNHANDLED) { return -1; } //Maybe later we could support other rcs
1139 //E_FOUND : we have the CW,
1140 //E_UNHANDLED : incoming ECM request
1142 if(cl->reader)
1144 if(!camd35_tcp_connect(cl))
1146 cs_log_dbg(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl));
1147 return (-1);
1151 uint32_t size = sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw) + sizeof(uint8_t) +
1152 #ifdef CS_CACHEEX_AIO
1153 (ll_count(er->csp_lastnodes) + 1) * 8 + sizeof(uint8_t);
1154 #else
1155 (ll_count(er->csp_lastnodes) + 1) * 8;
1156 #endif
1157 uint8_t *buf;
1158 if(!cs_malloc(&buf, size + 20)) //camd35_send() adds +20
1159 { return -1; }
1161 buf[0] = 0x3f; //New Command: Cache-push
1162 buf[1] = size & 0xff;
1163 buf[2] = size >> 8;
1164 buf[3] = rc;
1166 i2b_buf(2, er->srvid, buf + 8);
1167 i2b_buf(2, er->caid, buf + 10);
1168 i2b_buf(4, er->prid, buf + 12);
1169 //i2b_buf(2, er->idx, buf + 16); // Not relevant...?
1171 if(er->cwc_cycletime && er->cwc_next_cw_cycle < 2)
1173 buf[18] = er->cwc_cycletime; // contains cwc stage3 cycletime
1174 if(er->cwc_next_cw_cycle == 1)
1175 { buf[18] = (buf[18] | 0x80); } // set bit 8 to high
1177 if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
1178 { cl->account->cwc_info++; }
1179 else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
1180 { cl->cwc_info++; }
1182 cs_log_dbg(D_CWC, "CWC (CE) push to %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
1185 buf[19] = er->ecm[0] != 0x80 && er->ecm[0] != 0x81 ? 0 : er->ecm[0];
1187 uint8_t *ofs = buf + 20;
1189 //write oscam ecmd5:
1190 memcpy(ofs, er->ecmd5, sizeof(er->ecmd5)); //16
1191 ofs += sizeof(er->ecmd5);
1193 //write csp hashcode:
1194 i2b_buf(4, CSP_HASH_SWAP(er->csp_hash), ofs);
1195 ofs += 4;
1197 //write cw:
1198 memcpy(ofs, er->cw, sizeof(er->cw)); //16
1199 ofs += sizeof(er->cw);
1201 //write node count:
1202 *ofs = ll_count(er->csp_lastnodes) + 1;
1203 ofs++;
1205 //write own node:
1206 memcpy(ofs, camd35_node_id, 8);
1207 ofs += 8;
1209 //write other nodes:
1210 LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0);
1211 uint8_t *node;
1212 while((node = ll_li_next(li)))
1214 memcpy(ofs, node, 8);
1215 ofs += 8;
1217 ll_li_destroy(li);
1219 #ifdef CS_CACHEEX_AIO
1220 // add localgenerated cw-flag
1221 if(er->localgenerated)
1223 *ofs = 1;
1225 else
1227 *ofs = 0xFF;
1229 #endif
1230 int32_t res = camd35_send(cl, buf, size);
1231 NULLFREE(buf);
1232 return res;
1235 static void camd35_cacheex_push_in(struct s_client *cl, uint8_t *buf)
1237 int8_t rc = buf[3];
1238 if(rc != E_FOUND && rc != E_UNHANDLED) //Maybe later we could support other rcs
1239 { return; }
1241 ECM_REQUEST *er;
1242 uint16_t size = buf[1] | (buf[2] << 8);
1243 if(size < sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw))
1245 cs_log_dbg(D_CACHEEX, "cacheex: %s received old cache-push format! data ignored!", username(cl));
1246 return;
1249 if(!(er = get_ecmtask()))
1250 { return; }
1252 er->srvid = b2i(2, buf + 8);
1253 er->caid = b2i(2, buf + 10);
1254 er->prid = b2i(4, buf + 12);
1255 er->pid = b2i(2, buf + 16);
1256 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
1257 er->rc = rc;
1259 er->ecmlen = 0;
1261 if(buf[18])
1263 if(buf[18] & (0x01 << 7))
1265 er->cwc_cycletime = (buf[18] & 0x7F); // remove bit 8 to get cycletime
1266 er->cwc_next_cw_cycle = 1;
1268 else
1270 er->cwc_cycletime = buf[18];
1271 er->cwc_next_cw_cycle = 0;
1275 uint8_t *ofs = buf + 20;
1277 //Read ecmd5
1278 memcpy(er->ecmd5, ofs, sizeof(er->ecmd5)); //16
1279 ofs += sizeof(er->ecmd5);
1281 if(!check_cacheex_filter(cl, er))
1283 return;
1286 #ifdef CS_CACHEEX_AIO
1287 // check incoming cache
1288 if(check_client(cl) && cl->typ == 'p' && cl->reader && cl->reader->cacheex.mode == 2
1289 && ( (cl->reader->cacheex.filter_caidtab.cevnum > 0 && !chk_csp_ctab(er, &cl->reader->cacheex.filter_caidtab)) // reader cacheex_ecm_filter not matching if set
1290 || (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
1291 || (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
1295 cs_log_dbg(D_CACHEEX, "cacheex: received cache not matching cacheex_ecm_filter => pushing filter again");
1296 camd35_cacheex_send_push_filter(cl, 2); // get cache != cacheex_ecm_filter, send filter again - remote restarted
1297 if(cl->reader->cacheex.feature_bitfield & 4)
1298 camd35_cacheex_feature_trigger(cl, 4, 2);
1299 free_push_in_ecm(er);
1300 return;
1303 if(check_client(cl) && cl->typ == 'c' && cl->account && cl->account->cacheex.mode == 3
1304 && ( (cl->account->cacheex.filter_caidtab.cevnum > 0 && !chk_csp_ctab(er, &cl->account->cacheex.filter_caidtab)) // account cacheex_ecm_filter not matching if set
1305 || (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
1306 || (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
1310 cs_log_dbg(D_CACHEEX, "cacheex: received cache not matching cacheex_ecm_filter => pushing filter again");
1311 camd35_cacheex_send_push_filter(cl, 3); // get cache != cacheex_ecm_filter, send filter again - remote restarted
1312 if(cl->account->cacheex.feature_bitfield & 4)
1313 camd35_cacheex_feature_trigger(cl, 4, 3);
1314 free_push_in_ecm(er);
1315 return;
1317 #endif
1319 //Read csp_hash:
1320 er->csp_hash = CSP_HASH_SWAP(b2i(4, ofs));
1321 ofs += 4;
1323 //Read cw:
1324 memcpy(er->cw, ofs, sizeof(er->cw)); //16
1325 ofs += sizeof(er->cw);
1327 //Check auf neues Format:
1328 uint8_t *data;
1329 if(size > (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)))
1332 //Read lastnodes:
1333 uint8_t count = *ofs;
1334 ofs++;
1336 #ifndef CS_CACHEEX_AIO
1337 //check max nodes:
1338 if(count > cacheex_maxhop(cl))
1340 cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s", (int32_t)count, cacheex_maxhop(cl), username(cl));
1341 NULLFREE(er);
1342 return;
1344 #endif
1345 cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes %s", (int32_t)count, username(cl));
1346 if (er){
1347 er->csp_lastnodes = ll_create("csp_lastnodes");
1349 while(count)
1351 if(!cs_malloc(&data, 8))
1352 { break; }
1353 memcpy(data, ofs, 8);
1354 ofs += 8;
1355 ll_append(er->csp_lastnodes, data);
1356 count--;
1357 cs_log_dbg(D_CACHEEX, "cacheex: received node %" PRIu64 "X %s", cacheex_node_id(data), username(cl));
1360 #ifdef CS_CACHEEX_AIO
1361 // check byte after nodelist for "localgenerated CW"-flag
1362 if(b2i(1, ofs) == 1)
1364 er->localgenerated = 1;
1365 cs_log_dbg(D_CACHEEX, "cacheex: received ECM with localgenerated flag %04X@%06X:%04X %s", er->caid, er->prid, er->srvid, username(cl));
1367 //check max nodes for lg flagged cw:
1368 if(ll_count(er->csp_lastnodes) > cacheex_maxhop_lg(cl))
1370 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));
1371 free_push_in_ecm(er);
1372 return;
1375 // without localgenerated flag
1376 else
1378 //check max nodes:
1379 if(ll_count(er->csp_lastnodes) > cacheex_maxhop(cl))
1381 cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s", ll_count(er->csp_lastnodes), cacheex_maxhop(cl), username(cl));
1382 free_push_in_ecm(er);
1383 return;
1387 (cl->typ == 'p' && cl->reader && cl->reader->cacheex.mode == 2 && !chk_srvid_localgenerated_only_exception(er) // cx1&2
1388 && (
1389 // !aio
1390 (cl->cacheex_aio_checked && !cl->reader->cacheex.feature_bitfield
1391 && (
1392 !cfg.cacheex_lg_only_in_aio_only && !cl->reader->cacheex.lg_only_in_aio_only
1393 && (cfg.cacheex_localgenerated_only_in || cl->reader->cacheex.localgenerated_only_in || chk_lg_only(er, &cl->reader->cacheex.lg_only_in_tab) || chk_lg_only(er, &cfg.cacheex_lg_only_in_tab))
1397 // aio
1398 (cl->cacheex_aio_checked && cl->reader->cacheex.feature_bitfield
1399 && (
1400 cfg.cacheex_localgenerated_only_in || cl->reader->cacheex.localgenerated_only_in || chk_lg_only(er, &cl->reader->cacheex.lg_only_in_tab) || chk_lg_only(er, &cfg.cacheex_lg_only_in_tab)
1406 (cl->typ == 'c' && cl->account && cl->account->cacheex.mode == 3 && !chk_srvid_localgenerated_only_exception(er) // cx3
1407 && (
1408 // !aio
1409 (cl->cacheex_aio_checked && !cl->account->cacheex.feature_bitfield
1410 && (
1411 !cfg.cacheex_lg_only_in_aio_only && !cl->account->cacheex.lg_only_in_aio_only
1412 && (cfg.cacheex_localgenerated_only_in || cl->account->cacheex.localgenerated_only_in || chk_lg_only(er, &cl->account->cacheex.lg_only_in_tab) || chk_lg_only(er, &cfg.cacheex_lg_only_in_tab))
1416 // aio
1417 (cl->cacheex_aio_checked && cl->account->cacheex.feature_bitfield
1418 && (
1419 cfg.cacheex_localgenerated_only_in || cl->account->cacheex.localgenerated_only_in || chk_lg_only(er, &cl->account->cacheex.lg_only_in_tab) || chk_lg_only(er, &cfg.cacheex_lg_only_in_tab)
1426 cs_log_dbg(D_CACHEEX, "cacheex: drop ECM without localgenerated flag %04X@%06X:%04X %s", er->caid, er->prid, er->srvid, username(cl));
1427 free_push_in_ecm(er);
1428 return;
1431 #endif
1433 else
1435 cs_log_dbg(D_CACHEEX, "cacheex: received old cachex from %s", username(cl));
1436 er->csp_lastnodes = ll_create("csp_lastnodes");
1439 //store remote node id if we got one. The remote node is the first node in the node list
1440 data = ll_has_elements(er->csp_lastnodes);
1441 if(data && !cl->ncd_skey[8]) //Ok, this is tricky, we use newcamd key storage for saving the remote node
1443 memcpy(cl->ncd_skey, data, 8);
1444 cl->ncd_skey[8] = 1; //Mark as valid node
1446 cs_log_dbg(D_CACHEEX, "cacheex: received cacheex from remote node id %" PRIu64 "X", cacheex_node_id(cl->ncd_skey));
1448 //for compatibility: add peer node if no node received (not working now, maybe later):
1449 if(!ll_count(er->csp_lastnodes) && cl->ncd_skey[8])
1451 if(!cs_malloc(&data, 8))
1453 #ifdef CS_CACHEEX_AIO
1454 free_push_in_ecm(er);
1455 #endif
1456 return;
1458 memcpy(data, cl->ncd_skey, 8);
1459 ll_append(er->csp_lastnodes, data);
1460 cs_log_dbg(D_CACHEEX, "cacheex: added missing remote node id %" PRIu64 "X", cacheex_node_id(data));
1463 #ifdef CS_CACHEEX_AIO
1464 if (er->cwc_cycletime && er->cwc_next_cw_cycle < 2)
1466 if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
1467 { cl->account->cwc_info++; }
1468 else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
1469 { cl->cwc_info++; }
1470 cs_log_dbg(D_CWC, "CWC (CE) received from %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
1472 #endif
1473 cacheex_add_to_cache(cl, er);
1476 void camd35_cacheex_recv_ce1_cwc_info(struct s_client *cl, uint8_t *buf, int32_t idx)
1478 if(!(buf[0] == 0x01 && buf[18] < 0xFF && buf[18] > 0x00)) // cwc info ; normal camd3 ecms send 0xFF but we need no cycletime of 255 ;)
1479 return;
1481 ECM_REQUEST *er = NULL;
1482 int32_t i;
1484 for(i = 0; i < cfg.max_pending; i++)
1486 if (cl->ecmtask[i].idx == idx)
1488 er = &cl->ecmtask[i];
1489 break;
1493 if(!er)
1494 { return; }
1496 int8_t rc = buf[3];
1497 if(rc != E_FOUND)
1498 { return; }
1500 if(buf[18])
1502 if(buf[18] & (0x01 << 7))
1504 er->cwc_cycletime = (buf[18] & 0x7F); // remove bit 8 to get cycletime
1505 er->parent->cwc_cycletime = er->cwc_cycletime;
1506 er->cwc_next_cw_cycle = 1;
1507 er->parent->cwc_next_cw_cycle = er->cwc_next_cw_cycle;
1509 else
1511 er->cwc_cycletime = buf[18];
1512 er->parent->cwc_cycletime = er->cwc_cycletime;
1513 er->cwc_next_cw_cycle = 0;
1514 er->parent->cwc_next_cw_cycle = er->cwc_next_cw_cycle;
1518 if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
1519 { cl->account->cwc_info++; }
1520 else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
1521 { cl->cwc_info++; }
1523 cs_log_dbg(D_CWC, "CWC (CE1) received from %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
1529 * when a server client connects
1531 static void camd35_server_client_init(struct s_client *cl)
1533 if(!cl->init_done)
1535 cl->cacheex_needfilter = 1;
1540 * store received remote id
1542 static void camd35_cacheex_push_receive_remote_id(struct s_client *cl, uint8_t *buf)
1545 memcpy(cl->ncd_skey, buf + 20, 8);
1546 cl->ncd_skey[8] = 1;
1547 cs_log_dbg(D_CACHEEX, "cacheex: received id answer from %s: %" PRIu64 "X", username(cl), cacheex_node_id(cl->ncd_skey));
1551 void camd35_cacheex_init_dcw(struct s_client *client, ECM_REQUEST *er)
1553 uint8_t *buf = er->src_data; // get orig request
1555 if(((client->typ == 'c' && client->account && client->account->cacheex.mode)
1556 || ((client->typ == 'p' || client->typ == 'r') && (client->reader && client->reader->cacheex.mode)))
1557 && er->cwc_cycletime && er->cwc_next_cw_cycle < 2) // ce1
1559 buf[18] = er->cwc_cycletime; // contains cwc stage3 cycletime
1560 if(er->cwc_next_cw_cycle == 1)
1561 { buf[18] = (buf[18] | 0x80); } // set bit 8 to high
1562 if(client->typ == 'c' && client->account && client->account->cacheex.mode)
1563 { client->account->cwc_info++; }
1564 else if((client->typ == 'p' || client->typ == 'r') && (client->reader && client->reader->cacheex.mode))
1565 { client->cwc_info++; }
1566 cs_log_dbg(D_CWC, "CWC (CE1) push to %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X", username(client), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
1567 buf[19] = er->ecm[0];
1572 * send own id
1574 void camd35_cacheex_push_send_own_id(struct s_client *cl, uint8_t *mbuf)
1576 uint8_t rbuf[32]; //minimal size
1577 if(!cl->crypted) { return; }
1578 cs_log_dbg(D_CACHEEX, "cacheex: received id request from node %" PRIu64 "X %s", cacheex_node_id(mbuf + 20), username(cl));
1579 memset(rbuf, 0, sizeof(rbuf));
1580 rbuf[0] = 0x3e;
1581 rbuf[1] = 12;
1582 rbuf[2] = 0;
1583 memcpy(rbuf + 20, camd35_node_id, 8);
1584 cs_log_dbg(D_CACHEEX, "cacheex: sending own id %" PRIu64 "X request %s", cacheex_node_id(camd35_node_id), username(cl));
1585 camd35_send(cl, rbuf, 12); //send adds +20
1588 bool camd35_cacheex_server(struct s_client *client, uint8_t *mbuf)
1590 switch(mbuf[0])
1592 case 0x3c: // Cache-push filter request
1593 if(client->account && client->account->cacheex.mode==2){
1594 camd35_cacheex_push_filter(client, mbuf, 2);
1596 break;
1597 case 0x3d: // Cache-push id request
1598 camd35_cacheex_push_receive_remote_id(client, mbuf); //reader send request id with its nodeid, so we save it!
1599 camd35_cacheex_push_send_own_id(client, mbuf);
1600 if(client->cacheex_needfilter && client->account && client->account->cacheex.mode==3){
1601 camd35_cacheex_send_push_filter(client, 3);
1602 client->cacheex_needfilter = 0;
1604 #ifdef CS_CACHEEX_AIO
1605 if(!client->cacheex_aio_checked && ((client->account && client->account->cacheex.mode > 0) || (client->reader && client->reader->cacheex.mode > 0)))
1607 camd35_cacheex_feature_request(client);
1608 client->cacheex_aio_checked = 1;
1610 #endif
1611 break;
1612 case 0x3e: // Cache-push id answer
1613 camd35_cacheex_push_receive_remote_id(client, mbuf);
1614 break;
1615 case 0x3f: // Cache-push
1616 camd35_cacheex_push_in(client, mbuf);
1617 break;
1618 #ifdef CS_CACHEEX_AIO
1619 case 0x40: // cacheex-features request
1620 camd35_cacheex_feature_request_reply(client, mbuf);
1621 break;
1622 case 0x41: // cacheex-features answer
1623 // camd35_cacheex_feature_request_save(client, mbuf);
1624 break;
1625 case 0x42: // cacheex-feature trigger in
1626 camd35_cacheex_feature_trigger_in(client, mbuf);
1627 break;
1628 #endif
1629 default:
1630 return 0; // Not processed by cacheex
1632 return 1; // Processed by cacheex
1635 bool camd35_cacheex_recv_chk(struct s_client *client, uint8_t *buf)
1637 struct s_reader *rdr = client->reader;
1638 switch(buf[0])
1640 case 0x3c: // Cache-push filter request
1641 if(rdr->cacheex.mode==3){
1642 camd35_cacheex_push_filter(client, buf, 3);
1644 break;
1645 case 0x3d: // Cache-push id request
1646 camd35_cacheex_push_receive_remote_id(client, buf); //client send request id with its nodeid, so we save it!
1647 camd35_cacheex_push_send_own_id(client, buf);
1648 break;
1649 case 0x3e: // Cache-push id answer
1650 camd35_cacheex_push_receive_remote_id(client, buf);
1651 #ifdef CS_CACHEEX_AIO
1652 if(!client->cacheex_aio_checked && ((client->account && client->account->cacheex.mode > 0) || (client->reader && client->reader->cacheex.mode > 0)))
1654 camd35_cacheex_feature_request(client);
1655 client->cacheex_aio_checked = 1;
1657 #endif
1658 break;
1659 case 0x3f: //cache-push
1660 camd35_cacheex_push_in(client, buf);
1661 break;
1662 #ifdef CS_CACHEEX_AIO
1663 case 0x40: // cacheex-features request
1664 camd35_cacheex_feature_request_reply(client, buf);
1665 break;
1666 case 0x41: // cacheex-features answer
1667 // camd35_cacheex_feature_request_save(client, buf);
1668 break;
1669 case 0x42: // cacheex-feature trigger in
1670 camd35_cacheex_feature_trigger_in(client, buf);
1671 break;
1672 #endif
1673 default:
1674 return 0; // Not processed by cacheex
1676 return 1; // Processed by cacheex
1680 * request remote id
1682 void camd35_cacheex_push_request_remote_id(struct s_client *cl)
1684 uint8_t rbuf[32];//minimal size
1685 memset(rbuf, 0, sizeof(rbuf));
1686 rbuf[0] = 0x3d;
1687 rbuf[1] = 12;
1688 rbuf[2] = 0;
1689 memcpy(rbuf + 20, camd35_node_id, 8);
1690 cs_log_dbg(D_CACHEEX, "cacheex: sending id request to %s", username(cl));
1691 camd35_send(cl, rbuf, 12); //send adds +20
1694 void camd35_cacheex_module_init(struct s_module *ph)
1696 ph->c_cache_push = camd35_cacheex_push_out;
1697 ph->c_cache_push_chk = camd35_cacheex_push_chk;
1698 ph->s_init = camd35_server_client_init;
1701 #endif