Compare commits
2 Commits
a42f823e85
...
c93526a32f
| Author | SHA1 | Date | |
|---|---|---|---|
| c93526a32f | |||
| d76a2b2171 |
14
config.h
Executable file → Normal file
14
config.h
Executable file → Normal file
|
|
@ -8,22 +8,22 @@
|
||||||
#define WEBIF_JQUERY 1
|
#define WEBIF_JQUERY 1
|
||||||
#define WEBIF_WIKI 1
|
#define WEBIF_WIKI 1
|
||||||
#define WITH_COMPRESS_WEBIF 1
|
#define WITH_COMPRESS_WEBIF 1
|
||||||
#define WITH_SSL 1
|
//#define WITH_SSL 1
|
||||||
#if defined(__linux__) || defined(__CYGWIN__)
|
#if defined(__linux__) || defined(__CYGWIN__)
|
||||||
#define HAVE_DVBAPI 1
|
#define HAVE_DVBAPI 1
|
||||||
#define WITH_EXTENDED_CW 1
|
#define WITH_EXTENDED_CW 1
|
||||||
#endif
|
#endif
|
||||||
//#define WITH_NEUTRINO 1
|
//#define WITH_NEUTRINO 1
|
||||||
#define READ_SDT_CHARSETS 1
|
#define READ_SDT_CHARSETS 1
|
||||||
#define CLOCKFIX 1
|
//#define CLOCKFIX 1
|
||||||
#define CS_ANTICASC 1
|
#define CS_ANTICASC 1
|
||||||
#define WITH_DEBUG 1
|
#define WITH_DEBUG 1
|
||||||
#define WITH_LB 1
|
#define WITH_LB 1
|
||||||
#define CS_CACHEEX 1
|
#define CS_CACHEEX 1
|
||||||
#define CS_CACHEEX_AIO 1
|
#define CS_CACHEEX_AIO 1
|
||||||
#define CW_CYCLE_CHECK 1
|
#define CW_CYCLE_CHECK 1
|
||||||
#define LCDSUPPORT 1
|
//#define LCDSUPPORT 1
|
||||||
#define LEDSUPPORT 1
|
//#define LEDSUPPORT 1
|
||||||
#define IPV6SUPPORT 1
|
#define IPV6SUPPORT 1
|
||||||
//#define WITH_ARM_NEON 1
|
//#define WITH_ARM_NEON 1
|
||||||
//#define WITH_SIGNING 1
|
//#define WITH_SIGNING 1
|
||||||
|
|
@ -37,10 +37,10 @@
|
||||||
#define MODULE_CCCSHARE 1
|
#define MODULE_CCCSHARE 1
|
||||||
#define MODULE_GBOX 1
|
#define MODULE_GBOX 1
|
||||||
#define MODULE_RADEGAST 1
|
#define MODULE_RADEGAST 1
|
||||||
#define MODULE_SERIAL 1
|
//#define MODULE_SERIAL 1
|
||||||
#define MODULE_CONSTCW 1
|
#define MODULE_CONSTCW 1
|
||||||
#define MODULE_PANDORA 1
|
//#define MODULE_PANDORA 1
|
||||||
#define MODULE_GHTTP 1
|
//#define MODULE_GHTTP 1
|
||||||
#define MODULE_SCAM 1
|
#define MODULE_SCAM 1
|
||||||
#define MODULE_STREAMRELAY 1
|
#define MODULE_STREAMRELAY 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1045,6 +1045,7 @@ typedef struct s_cw_vote {
|
||||||
uint8_t cw[16];
|
uint8_t cw[16];
|
||||||
uint8_t votes;
|
uint8_t votes;
|
||||||
uint8_t local_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];
|
struct s_reader *voters[MAX_VOTE_CANDIDATES];
|
||||||
} s_cw_vote;
|
} s_cw_vote;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
#ifdef CS_CACHEEX
|
||||||
void cacheex_valuetab_fn(const char *token, char *value, void *setting, FILE *f)
|
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[] =
|
static const struct config_list global_opts[] =
|
||||||
{
|
{
|
||||||
DEF_OPT_FIXUP_FUNC(global_fixups_fn),
|
DEF_OPT_FIXUP_FUNC(global_fixups_fn),
|
||||||
|
DEF_OPT_FIXUP_FUNC(cwvote_local_weight_fixups_fn),
|
||||||
#ifdef LEDSUPPORT
|
#ifdef LEDSUPPORT
|
||||||
DEF_OPT_INT8("enableled" , OFS(enableled) , 0),
|
DEF_OPT_INT8("enableled" , OFS(enableled) , 0),
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
65
oscam-ecm.c
65
oscam-ecm.c
|
|
@ -1298,6 +1298,7 @@ ECM_REQUEST *get_ecmtask(void)
|
||||||
if(!cs_malloc(&er, sizeof(ECM_REQUEST)))
|
if(!cs_malloc(&er, sizeof(ECM_REQUEST)))
|
||||||
{ return NULL; }
|
{ return NULL; }
|
||||||
memset(er->vote_pool, 0, sizeof(er->vote_pool)); // Initialize vote_pool to zero
|
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);
|
cs_ftime(&er->tps);
|
||||||
er->rc = E_UNHANDLED;
|
er->rc = E_UNHANDLED;
|
||||||
er->client = cl;
|
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 i, free_idx = -1;
|
||||||
int is_local = 0;
|
int is_local = 0;
|
||||||
|
int is_cacheex = 0;
|
||||||
char cw_hex[33];
|
char cw_hex[33];
|
||||||
const char *source_label = "unknown";
|
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) {
|
if (rdr) {
|
||||||
source_label = rdr->label;
|
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) {
|
if (rdr == virtual_cacheex_reader || rdr == virtual_csp_reader) {
|
||||||
is_local = 0;
|
is_local = 0;
|
||||||
|
is_cacheex = 1;
|
||||||
|
// Dla wirtualnych readerów nie sprawdzamy duplikatów - każdy cache jest unikalny
|
||||||
|
check_source_duplicates = 0;
|
||||||
} else {
|
} else {
|
||||||
is_local = is_localreader(rdr, er);
|
is_local = is_localreader(rdr, er);
|
||||||
|
is_cacheex = cacheex_reader(rdr) ? 1 : 0;
|
||||||
}
|
}
|
||||||
} else if (er->cacheex_src) {
|
} else if (er->cacheex_src) {
|
||||||
|
is_cacheex = 1;
|
||||||
if (check_client(er->cacheex_src) && er->cacheex_src->account) {
|
if (check_client(er->cacheex_src) && er->cacheex_src->account) {
|
||||||
source_label = er->cacheex_src->account->usr;
|
source_label = er->cacheex_src->account->usr;
|
||||||
} else {
|
} else {
|
||||||
source_label = "CACHEEX_CLIENT";
|
source_label = "CACHEEX_CLIENT";
|
||||||
}
|
}
|
||||||
|
// Dla cacheex_src nie sprawdzamy duplikatów
|
||||||
|
check_source_duplicates = 0;
|
||||||
} else if (er->from_csp) {
|
} else if (er->from_csp) {
|
||||||
|
is_cacheex = 1;
|
||||||
source_label = "CSP";
|
source_label = "CSP";
|
||||||
|
// Dla CSP nie sprawdzamy duplikatów
|
||||||
|
check_source_duplicates = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cs_hexdump(0, cw, 16, cw_hex, sizeof(cw_hex));
|
cs_hexdump(0, cw, 16, cw_hex, sizeof(cw_hex));
|
||||||
|
|
||||||
|
|
||||||
// Sprawdź czy vote_pool jest pusta - jeśli nie, wyczyść ją
|
// Zarządzanie sesjami głosowania - używamy er->tps.time jako identyfikatora sesji ECM
|
||||||
// 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) {
|
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));
|
memset(er->vote_pool, 0, sizeof(er->vote_pool));
|
||||||
er->vote_pool_session = er->tps.time;
|
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;
|
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
|
// Sprawdź czy wpis jest poprawnie zainicjalizowany (votes > 0) i w granicach tablicy
|
||||||
// Porównujemy cały CW (16 bajtów), nie tylko compare_len
|
// 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)
|
if (er->vote_pool[i].votes == 0 && free_idx < 0)
|
||||||
free_idx = i;
|
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);
|
int cmp = memcmp(er->vote_pool[i].cw, cw, 16);
|
||||||
|
|
||||||
if (cmp == 0) {
|
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
|
// 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
|
// 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) {
|
if (er->vote_pool[i].votes < MAX_VOTE_CANDIDATES) {
|
||||||
er->vote_pool[i].voters[er->vote_pool[i].votes] = rdr;
|
er->vote_pool[i].voters[er->vote_pool[i].votes] = rdr;
|
||||||
er->vote_pool[i].votes++;
|
er->vote_pool[i].votes++;
|
||||||
if (is_local) er->vote_pool[i].local_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",
|
// 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);
|
// 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);
|
memcpy(er->vote_pool[free_idx].cw, cw, 16);
|
||||||
er->vote_pool[free_idx].votes = 1;
|
er->vote_pool[free_idx].votes = 1;
|
||||||
er->vote_pool[free_idx].local_votes = is_local ? 1 : 0;
|
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
|
// Store the actual reader if available, otherwise NULL
|
||||||
er->vote_pool[free_idx].voters[0] = rdr;
|
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);
|
memcpy(er->cw, er->vote_pool[best].cw, 16);
|
||||||
|
|
||||||
// Update cacheex hit stats if the winning CW came from cacheex
|
// 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;
|
struct s_client *src_cl = er->cacheex_src;
|
||||||
if (src_cl && src_cl->cwcacheexhit >= 0) {
|
if (src_cl && src_cl->cwcacheexhit >= 0) {
|
||||||
src_cl->cwcacheexhit++;
|
src_cl->cwcacheexhit++;
|
||||||
|
|
@ -4099,8 +4145,8 @@ int cw_vote_decide(struct ecm_request_t *er)
|
||||||
if (best >= 0) {
|
if (best >= 0) {
|
||||||
memcpy(er->cw, er->vote_pool[best].cw, 16);
|
memcpy(er->cw, er->vote_pool[best].cw, 16);
|
||||||
|
|
||||||
// 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->cacheex_src) {
|
if (cfg.cwvote_enabled && er->vote_pool[best].has_cacheex_vote) {
|
||||||
struct s_client *src_cl = er->cacheex_src;
|
struct s_client *src_cl = er->cacheex_src;
|
||||||
if (src_cl && src_cl->cwcacheexhit >= 0) {
|
if (src_cl && src_cl->cwcacheexhit >= 0) {
|
||||||
src_cl->cwcacheexhit++;
|
src_cl->cwcacheexhit++;
|
||||||
|
|
@ -4134,7 +4180,8 @@ int cw_vote_decide(struct ecm_request_t *er)
|
||||||
memcpy(er->cw, er->vote_pool[best].cw, 16);
|
memcpy(er->cw, er->vote_pool[best].cw, 16);
|
||||||
|
|
||||||
// Update cacheex hit stats if the winning CW came from cacheex
|
// 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;
|
struct s_client *src_cl = er->cacheex_src;
|
||||||
if (src_cl && src_cl->cwcacheexhit >= 0) {
|
if (src_cl && src_cl->cwcacheexhit >= 0) {
|
||||||
src_cl->cwcacheexhit++;
|
src_cl->cwcacheexhit++;
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@
|
||||||
<TR><TD><A>Ai Vote Log Enabled:</A></TD><TD><input name="cwvote_log_enabled" value="0" type="hidden"><input name="cwvote_log_enabled" value="1" type="checkbox" ##CWVOTELOGENABLEDCHECKED##></TD></TR>
|
<TR><TD><A>Ai Vote Log Enabled:</A></TD><TD><input name="cwvote_log_enabled" value="0" type="hidden"><input name="cwvote_log_enabled" value="1" type="checkbox" ##CWVOTELOGENABLEDCHECKED##></TD></TR>
|
||||||
<TR><TD><A>Ai Vote Timeout (ms):</A></TD><TD><input name="cwvote_timeout" type="text" size="8" maxlength="8" value="##CWVOTETIMEOUT##"> <small>(default 1000)</small></TD></TR>
|
<TR><TD><A>Ai Vote Timeout (ms):</A></TD><TD><input name="cwvote_timeout" type="text" size="8" maxlength="8" value="##CWVOTETIMEOUT##"> <small>(default 1000)</small></TD></TR>
|
||||||
<TR><TD><A>Ai Vote Min Votes:</A></TD><TD><input name="cwvote_min_votes" type="text" size="4" maxlength="3" value="##CWVOTEMINVOTES##"> <small>(default min. 2)</small></TD></TR>
|
<TR><TD><A>Ai Vote Min Votes:</A></TD><TD><input name="cwvote_min_votes" type="text" size="4" maxlength="3" value="##CWVOTEMINVOTES##"> <small>(default min. 2)</small></TD></TR>
|
||||||
<TR><TD><A>Ai Vote Local Weight:</A></TD><TD><input name="cwvote_local_weight" type="text" size="5" maxlength="4" value="##CWVOTELOCALWEIGHT##"> <small>(default 2.0)</small></TD></TR>
|
<TR><TD><A>Ai Vote Local Weight:</A></TD><TD><input name="cwvote_local_weight" type="text" size="5" maxlength="5" value="##CWVOTELOCALWEIGHT##"> <small>(0.0-10.0, default 2.0)</small></TD></TR>
|
||||||
<TR><TD><A>Ai Vote Max Candidates:</A></TD><TD><input name="cwvote_max_candidates" type="text" size="4" maxlength="3" value="##CWVOTEMAXCANDIDATES##"> <small>(default 8 caution! use max 16)</small></TD></TR>
|
<TR><TD><A>Ai Vote Max Candidates:</A></TD><TD><input name="cwvote_max_candidates" type="text" size="4" maxlength="3" value="##CWVOTEMAXCANDIDATES##"> <small>(default 8 caution! use max 16)</small></TD></TR>
|
||||||
<TR><TD><A>Ai Vote Compare Length:</A></TD><TD>
|
<TR><TD><A>Ai Vote Compare Length:</A></TD><TD>
|
||||||
<select name="cwvote_compare_len">
|
<select name="cwvote_compare_len">
|
||||||
|
|
|
||||||
1498
webif/pages_wiki.c
Executable file → Normal file
1498
webif/pages_wiki.c
Executable file → Normal file
File diff suppressed because one or more lines are too long
12
webif/pages_wiki.h
Executable file → Normal file
12
webif/pages_wiki.h
Executable file → Normal file
|
|
@ -7,11 +7,13 @@
|
||||||
|
|
||||||
#ifdef WEBIF_WIKI
|
#ifdef WEBIF_WIKI
|
||||||
|
|
||||||
|
#define COMPRESSED_WIKI 1
|
||||||
|
|
||||||
struct wiki_entry {
|
struct wiki_entry {
|
||||||
const char *param;
|
uint32_t param_ofs;
|
||||||
const char *config;
|
uint32_t config_ofs;
|
||||||
const char *section;
|
uint32_t section_ofs;
|
||||||
const char *text;
|
uint32_t text_ofs;
|
||||||
int8_t status;
|
int8_t status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -19,6 +21,8 @@ int32_t wiki_count(void);
|
||||||
const struct wiki_entry *wiki_get_entries(void);
|
const struct wiki_entry *wiki_get_entries(void);
|
||||||
const char *wiki_get_help(const char *config, const char *section, const char *param);
|
const char *wiki_get_help(const char *config, const char *section, const char *param);
|
||||||
int8_t wiki_get_status(const char *config, const char *section, const char *param);
|
int8_t wiki_get_status(const char *config, const char *section, const char *param);
|
||||||
|
void wiki_get_data(const char **data, size_t *data_len, size_t *data_olen);
|
||||||
|
char *wiki_get_decompressed_data(void);
|
||||||
void webif_wiki_prepare(void);
|
void webif_wiki_prepare(void);
|
||||||
void webif_wiki_free(void);
|
void webif_wiki_free(void);
|
||||||
|
|
||||||
|
|
|
||||||
BIN
webif/wiki_gen
BIN
webif/wiki_gen
Binary file not shown.
Loading…
Reference in New Issue
Block a user