1 #define MODULE_LOG_PREFIX "camd35"
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"
17 #include "oscam-chk.h"
18 #include "oscam-config.h"
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))
29 void camd35_cacheex_feature_trigger_in(struct s_client
*cl
, uint8_t *buf
)
35 feature
= buf
[21] | (buf
[20] << 8);
38 // check client & cacheex-mode
42 (cl
->typ
== 'c' && cl
->account
->cacheex
.mode
> 0) ||
43 (cl
->typ
== 'p' && cl
->reader
->cacheex
.mode
> 0)
52 // set localgenerated only
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];
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];
66 cl
->reader
->cacheex
.localgenerated_only
= buf
[24];
69 // set localgenerated only caidtab
71 filter_count
= buf
[i
+4];
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
;
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
++)
102 memset(&d
, 0, sizeof(d
));
104 d
.caid
= b2i(2, buf
+ i
);
108 d
.prids
[0] = NO_PROVID_VALUE
;
110 ftab_add(lgonly_tab
, &d
);
113 // remotesettings disabled - write additional remote-caids received
116 for(j
= 0; j
< filter_count
; j
++)
119 memset(&d
, 0, sizeof(d
));
121 d
.caid
= b2i(2, buf
+ i
);
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
)
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
++;
144 cs_log_dbg(D_CACHEEX
, "error: cacheex_lg_only_tab -> max. number(%i) of providers reached", CS_MAXPROV
);
150 ftab_add(lgonly_tab
, &d
);
156 // set cacheex_ecm_filter - extended
158 filter_count
= buf
[i
+4];
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
;
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;
189 cmask
= b2i(2, buf
+ i
);
190 if(cmask
== 0xFFFF) cmask
= -1;
193 provid
= b2i(3, buf
+ i
);
194 if(provid
== 0xFFFFFF) provid
= -1;
197 srvid
= b2i(2, buf
+ i
);
198 if(srvid
== 0xFFFF) srvid
= -1;
207 cecspvaluetab_add(filter
, &d
);
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
;
229 filter_count
= buf
[i
+4];
232 caidvaluetab_clear(ctab
);
234 for(j
= 0; j
< filter_count
; j
++)
236 uint16_t caid
= 0, value
= 0;
238 memset(&d
, 0, sizeof(d
));
240 caid
= b2i(2, buf
+ i
);
241 if(caid
== 0xFFFF) caid
= -1;
244 value
= b2i(2, buf
+ i
);
245 if(value
== 0xFFFF) value
= -1;
252 caidvaluetab_add(ctab
, &d
);
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];
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
));
282 // lg_only_tab caid:prov1[,provN][;caid:prov]
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
;
299 filter_count
= buf
[i
+4];
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
++)
316 memset(&d
, 0, sizeof(d
));
318 d
.caid
= b2i(2, buf
+ i
);
321 d
.nprids
= b2i(1, buf
+ i
);
324 for(k
=0; k
< d
.nprids
; k
++)
326 d
.prids
[k
] = b2i(3, buf
+ i
);
329 ftab_add(lgonly_tab
, &d
);
333 // remotesettings disabled - write additional remote-caid/provids received
336 for(j
= 0; j
< filter_count
; j
++)
339 memset(&d
, 0, sizeof(d
));
341 d
.caid
= b2i(2, buf
+ i
);
344 d
.nprids
= b2i(1, buf
+ i
);
347 for(k
=0; k
< d
.nprids
; k
++)
349 d
.prids
[k
] = b2i(3, buf
+ i
);
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
)
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
++;
369 cs_log_dbg(D_CACHEEX
, "error: cacheex_lg_only_tab -> max. number of providers reached");
375 ftab_add(lgonly_tab
, &d
);
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;
393 uint8_t payload
[MAX_ECM_SIZE
-size
];
394 memset(payload
, 0, sizeof(payload
));
396 // check client & cacheex-mode
397 if(!check_client(cl
))
405 // set localgenerated only
412 i2b_buf(2, feature
, payload
+ i
);
415 i2b_buf(2, 1, payload
+ i
);
420 if(cl
->reader
->cacheex
.localgenerated_only_in
)
421 payload
[i
] = cl
->reader
->cacheex
.localgenerated_only_in
;
423 payload
[i
] = cfg
.cacheex_localgenerated_only_in
;
427 if(cl
->account
->cacheex
.localgenerated_only_in
)
428 payload
[i
] = cl
->account
->cacheex
.localgenerated_only_in
;
430 payload
[i
] = cfg
.cacheex_localgenerated_only_in
;
434 // set localgenerated only caidtab; cx-aio < 9.2.6-04
438 lgonly_tab
= &cl
->reader
->cacheex
.lg_only_in_tab
;
439 if(!lgonly_tab
->nfilts
)
440 lgonly_tab
= &cfg
.cacheex_lg_only_in_tab
;
444 lgonly_tab
= &cl
->account
->cacheex
.lg_only_in_tab
;
445 if(!lgonly_tab
->nfilts
)
446 lgonly_tab
= &cfg
.cacheex_lg_only_in_tab
;
453 size
+= (lgonly_tab
->nfilts
* 2 + 1);
458 i2b_buf(2, feature
, payload
+ i
);
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)");
466 i2b_buf(2, (lgonly_tab
->nfilts
* 2 + 1), payload
+ i
); // n * caid + ctnum
469 if(lgonly_tab
->nfilts
> 255)
471 cs_log_dbg(D_CACHEEX
, "ERROR: too much localgenerated only caidtab-entries (max. 255)");
474 payload
[i
] = lgonly_tab
->nfilts
;
477 for(j
= 0; j
< lgonly_tab
->nfilts
; j
++)
479 FILTER
*d
= &lgonly_tab
->filts
[j
];
482 i2b_buf(2, d
->caid
, payload
+ i
);
491 // cacchex_ecm_filter extendend
493 CECSPVALUETAB
*filter
;
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
;
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
;
519 size
+= (filter
->cevnum
* 9 + 1);
524 i2b_buf(2, feature
, payload
+ i
);
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");
532 i2b_buf(2, (filter
->cevnum
* 9 + 1), payload
+ i
); // n * (caid2,mask2,provid3,srvid2) + ctnum1
535 payload
[i
] = filter
->cevnum
;
538 for(j
= 0; j
< filter
->cevnum
; j
++)
540 CECSPVALUETAB_DATA
*d
= &filter
->cevdata
[j
];
543 i2b_buf(2, d
->caid
, payload
+ i
);
548 i2b_buf(2, d
->cmask
, payload
+ i
);
554 i2b_buf(3, d
->prid
, payload
+ i
);
560 i2b_buf(2, d
->srvid
, payload
+ i
);
565 camd35_cacheex_send_push_filter(cl
, 2);
572 ctab
= &cl
->reader
->cacheex
.cacheex_nopushafter_tab
;
574 ctab
= &cfg
.cacheex_nopushafter_tab
;
578 ctab
= &cl
->account
->cacheex
.cacheex_nopushafter_tab
;
580 ctab
= &cfg
.cacheex_nopushafter_tab
;
587 size
+= (ctab
->cvnum
* 4 + 1);
592 i2b_buf(2, feature
, payload
+ i
);
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)");
600 i2b_buf(2, (ctab
->cvnum
* 4 + 1), payload
+ i
); // n * (caid2+value2) + cvnum
603 if(ctab
->cvnum
> 255)
605 cs_log_dbg(D_CACHEEX
, "ERROR: to much no push after caidtvalueab-entries (max. 255)");
608 payload
[i
] = ctab
->cvnum
;
611 for(j
= 0; j
< ctab
->cvnum
; j
++)
613 CAIDVALUETAB_DATA
*d
= &ctab
->cvdata
[j
];
616 i2b_buf(2, d
->caid
, payload
+ i
);
618 i2b_buf(2, d
->value
, payload
+ i
);
634 i2b_buf(2, feature
, payload
+ i
);
637 i2b_buf(2, 2, payload
+ i
);
642 if(cl
->reader
->cacheex
.maxhop
)
643 payload
[i
] = cl
->reader
->cacheex
.maxhop
;
648 if(cl
->reader
->cacheex
.maxhop_lg
)
649 payload
[i
] = cl
->reader
->cacheex
.maxhop_lg
;
655 if(cl
->account
->cacheex
.maxhop
)
656 payload
[i
] = cl
->account
->cacheex
.maxhop
;
661 if(cl
->account
->cacheex
.maxhop_lg
)
662 payload
[i
] = cl
->account
->cacheex
.maxhop_lg
;
676 i2b_buf(2, feature
, payload
+ i
);
679 i2b_buf(2, sizeof(token
), payload
+ i
);
683 snprintf((char *)token
, sizeof(token
), "%s", CS_AIO_VERSION
);
684 uint8_t *ofs
= payload
+ i
;
685 memcpy(ofs
, token
, sizeof(token
));
690 i2b_buf(2, feature
, payload
+ i
);
695 lgonly_tab
= &cl
->reader
->cacheex
.lg_only_in_tab
;
696 if(!lgonly_tab
->nfilts
)
697 lgonly_tab
= &cfg
.cacheex_lg_only_in_tab
;
701 lgonly_tab
= &cl
->account
->cacheex
.lg_only_in_tab
;
702 if(!lgonly_tab
->nfilts
)
703 lgonly_tab
= &cfg
.cacheex_lg_only_in_tab
;
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);
717 i2b_buf(2, cs_strlen(cx_aio_ftab
), payload
+ i
);
721 payload
[i
] = lgonly_tab
->nfilts
;
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]);
734 NULLFREE(cx_aio_ftab
);
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
;
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);
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);
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
;
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);
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);
875 cs_log_dbg(D_CACHEEX
, "feature_bitfield save failed - rdr, %s", username(cl
));
880 void camd35_cacheex_feature_request(struct s_client
*cl
)
885 memset(buf
, 0, sizeof(buf
));
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
);
901 memset(rbuf
, 0, sizeof(rbuf
));
906 i2b_buf(2, CACHEEX_FEATURES
, rbuf
+ i
);
908 camd35_send_without_timeout(cl
, rbuf
, 12); //send adds +20
916 void camd35_cacheex_send_push_filter(struct s_client
*cl
, uint8_t mode
)
918 struct s_reader
*rdr
= cl
->reader
;
920 CECSPVALUETAB
*filter
;
921 //maximum size: 20+255
923 memset(buf
, 0, sizeof(buf
));
927 //mode==2 send filters from 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
;
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
;
951 i2b_buf(2, filter
->cevnum
, buf
+ i
);
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
);
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
);
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
);
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
);
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
;
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
;
1020 cecspvaluetab_clear(filter
);
1023 int32_t max_filters
= 15;
1024 for(j
=0; j
<max_filters
; j
++)
1026 caid
= b2i(4, buf
+ i
);
1028 CECSPVALUETAB_DATA d
;
1029 memset(&d
, 0, sizeof(d
));
1030 d
.caid
= b2i(4, buf
+ i
);
1031 cecspvaluetab_add(filter
, &d
);
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
];
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
];
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
];
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
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
));
1081 cs_log_dbg(D_CACHEEX
, "cacheex: nodelist reached %d nodes, no push", cacheex_maxhop(cl
));
1088 if(!cl
->reader
->tcp_connected
)
1090 cs_log_dbg(D_CACHEEX
, "cacheex: not connected %s -> no push", username(cl
));
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!");
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);
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)
1117 //node found, so we got it from there, do not push:
1120 cs_log_dbg(D_CACHEEX
,
1121 "cacheex: node %" PRIu64
"X found in list => skip push!", cacheex_node_id(node
));
1125 //check if cw is already pushed
1126 if(check_is_pushed(er
->cw_cache
, cl
))
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
));
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
1144 if(!camd35_tcp_connect(cl
))
1146 cs_log_dbg(D_CACHEEX
, "cacheex: not connected %s -> no push", username(cl
));
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);
1155 (ll_count(er
->csp_lastnodes
) + 1) * 8;
1158 if(!cs_malloc(&buf
, size
+ 20)) //camd35_send() adds +20
1161 buf
[0] = 0x3f; //New Command: Cache-push
1162 buf
[1] = size
& 0xff;
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
))
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
);
1198 memcpy(ofs
, er
->cw
, sizeof(er
->cw
)); //16
1199 ofs
+= sizeof(er
->cw
);
1202 *ofs
= ll_count(er
->csp_lastnodes
) + 1;
1206 memcpy(ofs
, camd35_node_id
, 8);
1209 //write other nodes:
1210 LL_LOCKITER
*li
= ll_li_create(er
->csp_lastnodes
, 0);
1212 while((node
= ll_li_next(li
)))
1214 memcpy(ofs
, node
, 8);
1219 #ifdef CS_CACHEEX_AIO
1220 // add localgenerated cw-flag
1221 if(er
->localgenerated
)
1230 int32_t res
= camd35_send(cl
, buf
, size
);
1235 static void camd35_cacheex_push_in(struct s_client
*cl
, uint8_t *buf
)
1238 if(rc
!= E_FOUND
&& rc
!= E_UNHANDLED
) //Maybe later we could support other rcs
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
));
1249 if(!(er
= get_ecmtask()))
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
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;
1270 er
->cwc_cycletime
= buf
[18];
1271 er
->cwc_next_cw_cycle
= 0;
1275 uint8_t *ofs
= buf
+ 20;
1278 memcpy(er
->ecmd5
, ofs
, sizeof(er
->ecmd5
)); //16
1279 ofs
+= sizeof(er
->ecmd5
);
1281 if(!check_cacheex_filter(cl
, er
))
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
);
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
);
1320 er
->csp_hash
= CSP_HASH_SWAP(b2i(4, ofs
));
1324 memcpy(er
->cw
, ofs
, sizeof(er
->cw
)); //16
1325 ofs
+= sizeof(er
->cw
);
1327 //Check auf neues Format:
1329 if(size
> (sizeof(er
->ecmd5
) + sizeof(er
->csp_hash
) + sizeof(er
->cw
)))
1333 uint8_t count
= *ofs
;
1336 #ifndef CS_CACHEEX_AIO
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
));
1345 cs_log_dbg(D_CACHEEX
, "cacheex: received %d nodes %s", (int32_t)count
, username(cl
));
1347 er
->csp_lastnodes
= ll_create("csp_lastnodes");
1351 if(!cs_malloc(&data
, 8))
1353 memcpy(data
, ofs
, 8);
1355 ll_append(er
->csp_lastnodes
, data
);
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
);
1375 // without localgenerated flag
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
);
1387 (cl
->typ
== 'p' && cl
->reader
&& cl
->reader
->cacheex
.mode
== 2 && !chk_srvid_localgenerated_only_exception(er
) // cx1&2
1390 (cl
->cacheex_aio_checked
&& !cl
->reader
->cacheex
.feature_bitfield
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
))
1398 (cl
->cacheex_aio_checked
&& cl
->reader
->cacheex
.feature_bitfield
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
1409 (cl
->cacheex_aio_checked
&& !cl
->account
->cacheex
.feature_bitfield
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
))
1417 (cl
->cacheex_aio_checked
&& cl
->account
->cacheex
.feature_bitfield
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
);
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
);
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
))
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
);
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 ;)
1481 ECM_REQUEST
*er
= NULL
;
1484 for(i
= 0; i
< cfg
.max_pending
; i
++)
1486 if (cl
->ecmtask
[i
].idx
== idx
)
1488 er
= &cl
->ecmtask
[i
];
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
;
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
))
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
)
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];
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
));
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
)
1592 case 0x3c: // Cache-push filter request
1593 if(client
->account
&& client
->account
->cacheex
.mode
==2){
1594 camd35_cacheex_push_filter(client
, mbuf
, 2);
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;
1612 case 0x3e: // Cache-push id answer
1613 camd35_cacheex_push_receive_remote_id(client
, mbuf
);
1615 case 0x3f: // Cache-push
1616 camd35_cacheex_push_in(client
, mbuf
);
1618 #ifdef CS_CACHEEX_AIO
1619 case 0x40: // cacheex-features request
1620 camd35_cacheex_feature_request_reply(client
, mbuf
);
1622 case 0x41: // cacheex-features answer
1623 // camd35_cacheex_feature_request_save(client, mbuf);
1625 case 0x42: // cacheex-feature trigger in
1626 camd35_cacheex_feature_trigger_in(client
, mbuf
);
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
;
1640 case 0x3c: // Cache-push filter request
1641 if(rdr
->cacheex
.mode
==3){
1642 camd35_cacheex_push_filter(client
, buf
, 3);
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
);
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;
1659 case 0x3f: //cache-push
1660 camd35_cacheex_push_in(client
, buf
);
1662 #ifdef CS_CACHEEX_AIO
1663 case 0x40: // cacheex-features request
1664 camd35_cacheex_feature_request_reply(client
, buf
);
1666 case 0x41: // cacheex-features answer
1667 // camd35_cacheex_feature_request_save(client, buf);
1669 case 0x42: // cacheex-feature trigger in
1670 camd35_cacheex_feature_trigger_in(client
, buf
);
1674 return 0; // Not processed by cacheex
1676 return 1; // Processed by cacheex
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
));
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
;