1 #define MODULE_LOG_PREFIX "cccam"
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"
18 #include "oscam-chk.h"
19 #include "oscam-config.h"
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
);
31 void cc_cacheex_feature_trigger_in(struct s_client
*cl
, uint8_t *buf
)
37 feature
= buf
[1] | (buf
[0] << 8);
40 // check client & cacheex-mode
44 (cl
->typ
== 'c' && cl
->account
->cacheex
.mode
> 0) ||
45 (cl
->typ
== 'p' && cl
->reader
->cacheex
.mode
> 0)
54 // set localgenerated only
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];
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];
68 cl
->reader
->cacheex
.localgenerated_only
= buf
[4];
71 // set localgenerated only caidtab
73 filter_count
= buf
[i
+4];
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
;
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
++)
104 memset(&d
, 0, sizeof(d
));
106 d
.caid
= b2i(2, buf
+ i
);
110 d
.prids
[0] = NO_PROVID_VALUE
;
112 ftab_add(lgonly_tab
, &d
);
115 // remotesettings disabled - write additional remote-caids received
118 for(j
= 0; j
< filter_count
; j
++)
121 memset(&d
, 0, sizeof(d
));
123 d
.caid
= b2i(2, buf
+ i
);
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
)
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
++;
146 cs_log_dbg(D_CACHEEX
, "error: cacheex_lg_only_tab -> max. number(%i) of providers reached", CS_MAXPROV
);
152 ftab_add(lgonly_tab
, &d
);
158 // set cacheex_ecm_filter - extended
160 filter_count
= buf
[i
+4];
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
;
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;
191 cmask
= b2i(2, buf
+ i
);
192 if(cmask
== 0xFFFF) cmask
= -1;
195 provid
= b2i(3, buf
+ i
);
196 if(provid
== 0xFFFFFF) provid
= -1;
199 srvid
= b2i(2, buf
+ i
);
200 if(srvid
== 0xFFFF) srvid
= -1;
209 cecspvaluetab_add(filter
, &d
);
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
;
231 filter_count
= buf
[i
+4];
234 caidvaluetab_clear(ctab
);
236 for(j
= 0; j
< filter_count
; j
++)
238 uint16_t caid
= 0, value
= 0;
240 memset(&d
, 0, sizeof(d
));
242 caid
= b2i(2, buf
+ i
);
243 if(caid
== 0xFFFF) caid
= -1;
246 value
= b2i(2, buf
+ i
);
247 if(value
== 0xFFFF) value
= -1;
254 caidvaluetab_add(ctab
, &d
);
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];
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
));
284 // lg_only_tab caid:prov1[,provN][;caid:prov]
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
;
301 filter_count
= buf
[i
+4];
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
++)
318 memset(&d
, 0, sizeof(d
));
320 d
.caid
= b2i(2, buf
+ i
);
323 d
.nprids
= b2i(1, buf
+ i
);
326 for(k
=0; k
< d
.nprids
; k
++)
328 d
.prids
[k
] = b2i(3, buf
+ i
);
331 ftab_add(lgonly_tab
, &d
);
335 // remotesettings disabled - write additional remote-caid/provids received
338 for(j
= 0; j
< filter_count
; j
++)
341 memset(&d
, 0, sizeof(d
));
343 d
.caid
= b2i(2, buf
+ i
);
346 d
.nprids
= b2i(1, buf
+ i
);
349 for(k
=0; k
< d
.nprids
; k
++)
351 d
.prids
[k
] = b2i(3, buf
+ i
);
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
)
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
++;
371 cs_log_dbg(D_CACHEEX
, "error: cacheex_lg_only_tab -> max. number of providers reached");
377 ftab_add(lgonly_tab
, &d
);
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;
395 uint8_t payload
[MAX_ECM_SIZE
-size
];
396 memset(payload
, 0, sizeof(payload
));
398 // check client & cacheex-mode
399 if(!check_client(cl
))
407 // set localgenerated only
410 i2b_buf(2, feature
, payload
+ i
);
413 i2b_buf(2, 1, payload
+ i
);
421 if(cl
->reader
->cacheex
.localgenerated_only_in
)
422 payload
[i
] = cl
->reader
->cacheex
.localgenerated_only_in
;
424 payload
[i
] = cfg
.cacheex_localgenerated_only_in
;
428 if(cl
->account
->cacheex
.localgenerated_only_in
)
429 payload
[i
] = cl
->account
->cacheex
.localgenerated_only_in
;
431 payload
[i
] = cfg
.cacheex_localgenerated_only_in
;
435 // set localgenerated only caidtab; cx-aio < 9.2.6-04
439 lgonly_tab
= &cl
->reader
->cacheex
.lg_only_in_tab
;
440 if(!lgonly_tab
->nfilts
)
441 lgonly_tab
= &cfg
.cacheex_lg_only_in_tab
;
445 lgonly_tab
= &cl
->account
->cacheex
.lg_only_in_tab
;
446 if(!lgonly_tab
->nfilts
)
447 lgonly_tab
= &cfg
.cacheex_lg_only_in_tab
;
454 size
+= (lgonly_tab
->nfilts
* 2 + 1);
459 i2b_buf(2, feature
, payload
+ i
);
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)");
467 i2b_buf(2, (lgonly_tab
->nfilts
* 2 + 1), payload
+ i
); // n * caid + ctnum
470 if(lgonly_tab
->nfilts
> 255)
472 cs_log_dbg(D_CACHEEX
, "ERROR: too much localgenerated only caidtab-entries (max. 255)");
475 payload
[i
] = lgonly_tab
->nfilts
;
478 for(j
= 0; j
< lgonly_tab
->nfilts
; j
++)
480 FILTER
*d
= &lgonly_tab
->filts
[j
];
483 i2b_buf(2, d
->caid
, payload
+ i
);
492 // cacchex_ecm_filter extendend
494 CECSPVALUETAB
*filter
;
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
;
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
;
520 size
+= (filter
->cevnum
* 9 + 1);
523 i2b_buf(2, feature
, payload
+ i
);
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");
531 i2b_buf(2, (filter
->cevnum
* 9 + 1), payload
+ i
); // n * (caid2,mask2,provid3,srvid2) + ctnum1
534 payload
[i
] = filter
->cevnum
;
537 for(j
= 0; j
< filter
->cevnum
; j
++)
539 CECSPVALUETAB_DATA
*d
= &filter
->cevdata
[j
];
542 i2b_buf(2, d
->caid
, payload
+ i
);
547 i2b_buf(2, d
->cmask
, payload
+ i
);
553 i2b_buf(3, d
->prid
, payload
+ i
);
559 i2b_buf(2, d
->srvid
, payload
+ i
);
569 ctab
= &cl
->reader
->cacheex
.cacheex_nopushafter_tab
;
571 ctab
= &cfg
.cacheex_nopushafter_tab
;
575 ctab
= &cl
->account
->cacheex
.cacheex_nopushafter_tab
;
577 ctab
= &cfg
.cacheex_nopushafter_tab
;
584 size
+= (ctab
->cvnum
* 4 + 1);
587 i2b_buf(2, feature
, payload
+ i
);
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)");
595 i2b_buf(2, (ctab
->cvnum
* 4 + 1), payload
+ i
); // n * (caid2+value2) + cvnum
598 if(ctab
->cvnum
> 255)
600 cs_log_dbg(D_CACHEEX
, "ERROR: to much no push after caidtvalueab-entries (max. 255)");
603 payload
[i
] = ctab
->cvnum
;
606 for(j
= 0; j
< ctab
->cvnum
; j
++)
608 CAIDVALUETAB_DATA
*d
= &ctab
->cvdata
[j
];
611 i2b_buf(2, d
->caid
, payload
+ i
);
613 i2b_buf(2, d
->value
, payload
+ i
);
625 i2b_buf(2, feature
, payload
+ i
);
628 i2b_buf(2, 2, payload
+ i
);
636 if(cl
->reader
->cacheex
.maxhop
)
637 payload
[i
] = cl
->reader
->cacheex
.maxhop
;
642 if(cl
->reader
->cacheex
.maxhop_lg
)
643 payload
[i
] = cl
->reader
->cacheex
.maxhop_lg
;
649 if(cl
->account
->cacheex
.maxhop
)
650 payload
[i
] = cl
->account
->cacheex
.maxhop
;
655 if(cl
->account
->cacheex
.maxhop_lg
)
656 payload
[i
] = cl
->account
->cacheex
.maxhop_lg
;
666 i2b_buf(2, feature
, payload
+ i
);
669 i2b_buf(2, sizeof(token
), payload
+ i
);
672 size
+=sizeof(token
);
675 snprintf((char *)token
, sizeof(token
), "%s", CS_AIO_VERSION
);
676 uint8_t *ofs
= payload
+ i
;
677 memcpy(ofs
, token
, sizeof(token
));
682 i2b_buf(2, feature
, payload
+ i
);
687 lgonly_tab
= &cl
->reader
->cacheex
.lg_only_in_tab
;
688 if(!lgonly_tab
->nfilts
)
689 lgonly_tab
= &cfg
.cacheex_lg_only_in_tab
;
693 lgonly_tab
= &cl
->account
->cacheex
.lg_only_in_tab
;
694 if(!lgonly_tab
->nfilts
)
695 lgonly_tab
= &cfg
.cacheex_lg_only_in_tab
;
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);
709 i2b_buf(2, cs_strlen(cx_aio_ftab
), payload
+ i
);
713 payload
[i
] = lgonly_tab
->nfilts
;
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]);
726 NULLFREE(cx_aio_ftab
);
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
;
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);
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);
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
;
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);
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);
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
)
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
)
878 i2b_buf(2, CACHEEX_FEATURES
, rbuf
);
879 cc_cmd_send(cl
, rbuf
, size
, MSG_CACHE_FEATURE_EXCHANGE
);
883 void cc_cacheex_filter_out(struct s_client
*cl
)
885 struct s_reader
*rdr
= (cl
->typ
== 'c') ? NULL
: cl
->reader
;
887 CECSPVALUETAB
*filter
;
888 int32_t size
= 482; // minimal size, keep it <= 512 for max UDP packet size without fragmentation
890 memset(buf
, 0, sizeof(buf
));
892 if(rdr
&& (rdr
->cacheex
.mode
== 2
893 #ifdef CS_CACHEEX_AIO
894 || rdr
->cacheex
.mode
== 1
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
;
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
;
919 i2b_buf(2, filter
->cevnum
, buf
+ i
);
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
);
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
);
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
);
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
);
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
;
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
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
;
992 cecspvaluetab_clear(filter
);
995 int32_t max_filters
= 30;
996 for(j
= 0; j
< max_filters
; j
++)
998 caid
= b2i(4, buf
+ i
);
1001 CECSPVALUETAB_DATA d
;
1002 memset(&d
, 0, sizeof(d
));
1003 d
.caid
= b2i(4, buf
+ i
);
1004 cecspvaluetab_add(filter
, &d
);
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
];
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
];
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
];
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!");
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
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
));
1064 cs_log_dbg(D_CACHEEX
, "cacheex: nodelist reached %d nodes, no push", cacheex_maxhop(cl
));
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);
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)
1086 // node found, so we got it from there, do not push
1089 cs_log_dbg(D_CACHEEX
, "cacheex: node %" PRIu64
"X found in list => skip push!", cacheex_node_id(node
));
1095 if(cl
->reader
&& !cl
->reader
->tcp_connected
)
1101 if(!cc
|| !cl
->udp_fd
)
1103 cs_log_dbg(D_CACHEEX
, "cacheex: not connected %s -> no push", username(cl
));
1107 // check if cw is already pushed
1108 if(check_is_pushed(er
->cw_cache
, cl
))
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
1127 if(!cl
->reader
->tcp_connected
)
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
));
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);
1144 (ll_count(er
->csp_lastnodes
) + 1) * 8;
1148 if(!cs_malloc(&buf
, size
+ 20)) // camd35_send() adds +20
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;
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
))
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
);
1207 memcpy(ofs
, er
->cw
, sizeof(er
->cw
)); // 16
1208 ofs
+= sizeof(er
->cw
);
1211 *ofs
= ll_count(er
->csp_lastnodes
) + 1;
1215 memcpy(ofs
, cc
->node_id
, 8);
1218 // write other nodes
1219 LL_LOCKITER
*li
= ll_li_create(er
->csp_lastnodes
, 0);
1221 while((node
= ll_li_next(li
)))
1223 memcpy(ofs
, node
, 8);
1228 #ifdef CS_CACHEEX_AIO
1229 // add localgenerated cw-flag
1230 if(er
->localgenerated
)
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!
1245 cl
->reader
->last_s
= cl
->reader
->last_g
= time((time_t *)0); // correct
1250 cl
->last
= time(NULL
);
1258 void cc_cacheex_push_in(struct s_client
*cl
, uint8_t *buf
)
1260 struct cc_data
*cc
= cl
->cc
;
1270 cl
->reader
->last_s
= cl
->reader
->last_g
= time((time_t *)0);
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
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
));
1291 if(!(er
= get_ecmtask()))
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
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;
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
))
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
);
1335 uint8_t *ofs
= buf
+ 20;
1338 memcpy(er
->ecmd5
, ofs
, sizeof(er
->ecmd5
)); // 16
1339 ofs
+= sizeof(er
->ecmd5
);
1341 if(!check_cacheex_filter(cl
, er
))
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
);
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
);
1380 er
->csp_hash
= CSP_HASH_SWAP(b2i(4, ofs
));
1384 memcpy(er
->cw
, ofs
, sizeof(er
->cw
)); // 16
1385 ofs
+= sizeof(er
->cw
);
1387 // Read lastnode count
1388 uint8_t count
= *ofs
;
1391 #ifndef CS_CACHEEX_AIO
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
));
1403 cs_log_dbg(D_CACHEEX
, "cacheex: received %d nodes %s", (int32_t)count
, username(cl
));
1409 er
->csp_lastnodes
= ll_create("csp_lastnodes");
1414 if(!cs_malloc(&data
, 8))
1419 memcpy(data
, ofs
, 8);
1421 ll_append(er
->csp_lastnodes
, data
);
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
);
1441 // without localgenerated flag
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
);
1453 (cl
->typ
== 'p' && cl
->reader
&& cl
->reader
->cacheex
.mode
== 2 && !chk_srvid_localgenerated_only_exception(er
) // cx2
1456 (cl
->cacheex_aio_checked
&& !cl
->reader
->cacheex
.feature_bitfield
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
))))
1464 (cl
->cacheex_aio_checked
&& cl
->reader
->cacheex
.feature_bitfield
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
1475 (cl
->cacheex_aio_checked
&& !cl
->account
->cacheex
.feature_bitfield
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
))))
1483 (cl
->cacheex_aio_checked
&& cl
->account
->cacheex
.feature_bitfield
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
);
1499 // for compatibility: add peer node if no node received
1500 if(!ll_count(er
->csp_lastnodes
))
1502 if(!cs_malloc(&data
, 8))
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
))
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
);
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
;