diff --git a/config.h b/config.h
old mode 100755
new mode 100644
index 4f47e8d..0660d54
--- a/config.h
+++ b/config.h
@@ -8,22 +8,22 @@
#define WEBIF_JQUERY 1
#define WEBIF_WIKI 1
#define WITH_COMPRESS_WEBIF 1
-#define WITH_SSL 1
+//#define WITH_SSL 1
#if defined(__linux__) || defined(__CYGWIN__)
#define HAVE_DVBAPI 1
#define WITH_EXTENDED_CW 1
#endif
//#define WITH_NEUTRINO 1
#define READ_SDT_CHARSETS 1
-#define CLOCKFIX 1
+//#define CLOCKFIX 1
#define CS_ANTICASC 1
#define WITH_DEBUG 1
#define WITH_LB 1
#define CS_CACHEEX 1
#define CS_CACHEEX_AIO 1
#define CW_CYCLE_CHECK 1
-#define LCDSUPPORT 1
-#define LEDSUPPORT 1
+//#define LCDSUPPORT 1
+//#define LEDSUPPORT 1
#define IPV6SUPPORT 1
//#define WITH_ARM_NEON 1
//#define WITH_SIGNING 1
@@ -37,10 +37,10 @@
#define MODULE_CCCSHARE 1
#define MODULE_GBOX 1
#define MODULE_RADEGAST 1
-#define MODULE_SERIAL 1
+//#define MODULE_SERIAL 1
#define MODULE_CONSTCW 1
-#define MODULE_PANDORA 1
-#define MODULE_GHTTP 1
+//#define MODULE_PANDORA 1
+//#define MODULE_GHTTP 1
#define MODULE_SCAM 1
#define MODULE_STREAMRELAY 1
diff --git a/globals.h b/globals.h
index b9f5046..28d0674 100755
--- a/globals.h
+++ b/globals.h
@@ -1045,6 +1045,7 @@ typedef struct s_cw_vote {
uint8_t cw[16];
uint8_t votes;
uint8_t local_votes;
+ uint8_t has_cacheex_vote; // FIX #2: flaga czy głos pochodzi z cacheex
struct s_reader *voters[MAX_VOTE_CANDIDATES];
} s_cw_vote;
diff --git a/oscam-config-global.c b/oscam-config-global.c
index 001417c..73b3d14 100755
--- a/oscam-config-global.c
+++ b/oscam-config-global.c
@@ -225,6 +225,14 @@ void cwvote_caidtab_fn(const char *token, char *value, void *setting, FILE *f)
}
}
+static void cwvote_local_weight_fixups_fn(void *UNUSED(var))
+{
+ if(cfg.cwvote_local_weight < 0.0f || cfg.cwvote_local_weight > 10.0f) {
+ cfg.cwvote_local_weight = 1.0f;
+ cs_log("CW Vote: local_weight out of range (0.0-10.0), using default value 1.0");
+ }
+}
+
#ifdef CS_CACHEEX
void cacheex_valuetab_fn(const char *token, char *value, void *setting, FILE *f)
{
@@ -337,6 +345,7 @@ void global_fixups_fn(void *UNUSED(var))
static const struct config_list global_opts[] =
{
DEF_OPT_FIXUP_FUNC(global_fixups_fn),
+ DEF_OPT_FIXUP_FUNC(cwvote_local_weight_fixups_fn),
#ifdef LEDSUPPORT
DEF_OPT_INT8("enableled" , OFS(enableled) , 0),
#endif
diff --git a/oscam-ecm.c b/oscam-ecm.c
index 8e68dfa..7107a8f 100755
--- a/oscam-ecm.c
+++ b/oscam-ecm.c
@@ -1298,6 +1298,7 @@ ECM_REQUEST *get_ecmtask(void)
if(!cs_malloc(&er, sizeof(ECM_REQUEST)))
{ return NULL; }
memset(er->vote_pool, 0, sizeof(er->vote_pool)); // Initialize vote_pool to zero
+ er->vote_pool_session = 0; // Initialize vote session to 0
cs_ftime(&er->tps);
er->rc = E_UNHANDLED;
er->client = cl;
@@ -3922,34 +3923,50 @@ int cw_vote_add(struct ecm_request_t *er, uint8_t *cw, struct s_reader *rdr)
{
int i, free_idx = -1;
int is_local = 0;
+ int is_cacheex = 0;
char cw_hex[33];
const char *source_label = "unknown";
+
+ // Flaga czy sprawdzać duplikaty źródła
+ // Dla cacheex/CSP nie sprawdzamy duplikatów - każde źródło cacheex/csp jest traktowane jako unikalne
+ int check_source_duplicates = 1;
if (rdr) {
source_label = rdr->label;
- // Wirtualne czytniki nie są lokalne
+ // Wirtualne czytniki nie są lokalne - to jest cacheex lub CSP
if (rdr == virtual_cacheex_reader || rdr == virtual_csp_reader) {
is_local = 0;
+ is_cacheex = 1;
+ // Dla wirtualnych readerów nie sprawdzamy duplikatów - każdy cache jest unikalny
+ check_source_duplicates = 0;
} else {
is_local = is_localreader(rdr, er);
+ is_cacheex = cacheex_reader(rdr) ? 1 : 0;
}
} else if (er->cacheex_src) {
+ is_cacheex = 1;
if (check_client(er->cacheex_src) && er->cacheex_src->account) {
source_label = er->cacheex_src->account->usr;
} else {
source_label = "CACHEEX_CLIENT";
}
+ // Dla cacheex_src nie sprawdzamy duplikatów
+ check_source_duplicates = 0;
} else if (er->from_csp) {
+ is_cacheex = 1;
source_label = "CSP";
+ // Dla CSP nie sprawdzamy duplikatów
+ check_source_duplicates = 0;
}
cs_hexdump(0, cw, 16, cw_hex, sizeof(cw_hex));
-// Sprawdź czy vote_pool jest pusta - jeśli nie, wyczyść ją
-// Używamy er->tps.time jako identyfikatora sesji ECM
+// Zarządzanie sesjami głosowania - używamy er->tps.time jako identyfikatora sesji ECM
+// Zamiast wyczyścić całą pulę, sprawdzamy czy sesja się zmieniła i wtedy resetujemy tylko wtedy
if (er->vote_pool_session != er->tps.time) {
+ // Sesja się zmieniła - resetujemy pulę głosowania
memset(er->vote_pool, 0, sizeof(er->vote_pool));
er->vote_pool_session = er->tps.time;
}
@@ -3962,23 +3979,50 @@ if (er->vote_pool_session != er->tps.time) {
// }
int max_cand = cfg.cwvote_max_candidates;
+ // Używamy konsekwentnie MIN(max_cand, MAX_VOTE_CANDIDATES) aby uniknąć overflow
+ int max_iter = (max_cand < MAX_VOTE_CANDIDATES) ? max_cand : MAX_VOTE_CANDIDATES;
// Sprawdź czy wpis jest poprawnie zainicjalizowany (votes > 0) i w granicach tablicy
// Porównujemy cały CW (16 bajtów), nie tylko compare_len
- for (i = 0; i < max_cand; i++) {
+ for (i = 0; i < max_iter; i++) {
if (er->vote_pool[i].votes == 0 && free_idx < 0)
free_idx = i;
- if (i < MAX_VOTE_CANDIDATES && er->vote_pool[i].votes > 0) {
+ if (er->vote_pool[i].votes > 0) {
int cmp = memcmp(er->vote_pool[i].cw, cw, 16);
if (cmp == 0) {
+ // Sprawdź unikalność źródła przed agregacją głosów
+ // Zapobiega wielokrotnemu głosowaniu z tego samego readera dla tego samego CW
+ // Dla cacheex/CSP (check_source_duplicates = 0) pomijamy to sprawdzenie
+ int duplicate_source = 0;
+
+ if (check_source_duplicates) {
+ int j;
+ for (j = 0; j < er->vote_pool[i].votes; j++) {
+ if (er->vote_pool[i].voters[j] == rdr) {
+ duplicate_source = 1;
+ break;
+ }
+ }
+ }
+
+ if (duplicate_source) {
+ // Źródło już głosowało dla tego CW - ignoruj
+ if (cfg.cwvote_log_enabled) {
+ cs_log("[Ai_vote_add] Duplicate source %s for same CW - ignoring", source_label);
+ }
+ return 0;
+ }
+
// CW już istnieje w puli - agreguj głosy niezależnie od źródła
// To pozwala na agregację głosów z różnych cacheex peerów dla tego samego CW
if (er->vote_pool[i].votes < MAX_VOTE_CANDIDATES) {
er->vote_pool[i].voters[er->vote_pool[i].votes] = rdr;
er->vote_pool[i].votes++;
if (is_local) er->vote_pool[i].local_votes++;
+ // FIX #2: Zapisz flagę czy głos pochodzi z cacheex
+ if (is_cacheex) er->vote_pool[i].has_cacheex_vote = 1;
}
// cs_log("[Ai_vote_add] Aggregated vote for existing CW → Votes: %d (local: %d) from %s",
// er->vote_pool[i].votes, er->vote_pool[i].local_votes, source_label);
@@ -3996,6 +4040,7 @@ if (er->vote_pool_session != er->tps.time) {
memcpy(er->vote_pool[free_idx].cw, cw, 16);
er->vote_pool[free_idx].votes = 1;
er->vote_pool[free_idx].local_votes = is_local ? 1 : 0;
+ er->vote_pool[free_idx].has_cacheex_vote = is_cacheex ? 1 : 0;
// Store the actual reader if available, otherwise NULL
er->vote_pool[free_idx].voters[0] = rdr;
@@ -4070,7 +4115,8 @@ int cw_vote_decide(struct ecm_request_t *er)
memcpy(er->cw, er->vote_pool[best].cw, 16);
// Update cacheex hit stats if the winning CW came from cacheex
- if (cfg.cwvote_enabled && er->cacheex_src) {
+ // FIX #2: Używamy flagi has_cacheex_vote zamiast er->cacheex_src
+ if (cfg.cwvote_enabled && er->vote_pool[best].has_cacheex_vote) {
struct s_client *src_cl = er->cacheex_src;
if (src_cl && src_cl->cwcacheexhit >= 0) {
src_cl->cwcacheexhit++;
@@ -4099,8 +4145,8 @@ int cw_vote_decide(struct ecm_request_t *er)
if (best >= 0) {
memcpy(er->cw, er->vote_pool[best].cw, 16);
- // Update cacheex hit stats if the winning CW came from cacheex
- if (cfg.cwvote_enabled && er->cacheex_src) {
+ // FIX #2: Używamy flagi has_cacheex_vote zamiast er->cacheex_src
+ if (cfg.cwvote_enabled && er->vote_pool[best].has_cacheex_vote) {
struct s_client *src_cl = er->cacheex_src;
if (src_cl && src_cl->cwcacheexhit >= 0) {
src_cl->cwcacheexhit++;
@@ -4133,17 +4179,18 @@ int cw_vote_decide(struct ecm_request_t *er)
if (has_majority || (timeout_reached && fallback == 1)) {
memcpy(er->cw, er->vote_pool[best].cw, 16);
- // Update cacheex hit stats if the winning CW came from cacheex
- if (cfg.cwvote_enabled && er->cacheex_src) {
- struct s_client *src_cl = er->cacheex_src;
- if (src_cl && src_cl->cwcacheexhit >= 0) {
- src_cl->cwcacheexhit++;
- if (src_cl->account) {
- src_cl->account->cwcacheexhit++;
- }
- first_client->cwcacheexhit++;
+ // Update cacheex hit stats if the winning CW came from cacheex
+ // FIX #2: Używamy flagi has_cacheex_vote zamiast er->cacheex_src
+ if (cfg.cwvote_enabled && er->vote_pool[best].has_cacheex_vote) {
+ struct s_client *src_cl = er->cacheex_src;
+ if (src_cl && src_cl->cwcacheexhit >= 0) {
+ src_cl->cwcacheexhit++;
+ if (src_cl->account) {
+ src_cl->account->cwcacheexhit++;
}
+ first_client->cwcacheexhit++;
}
+ }
if (cfg.cwvote_log_enabled) {
cs_hexdump(0, er->cw, 16, cw_hex, sizeof(cw_hex));
diff --git a/webif/config/global.html b/webif/config/global.html
index 140b232..ac3f374 100755
--- a/webif/config/global.html
+++ b/webif/config/global.html
@@ -147,7 +147,7 @@
| Ai Vote Compare Length: |
|