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_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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
81
oscam-ecm.c
81
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));
|
||||
|
|
|
|||
|
|
@ -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 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 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 Compare Length:</A></TD><TD>
|
||||
<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
|
||||
|
||||
#define COMPRESSED_WIKI 1
|
||||
|
||||
struct wiki_entry {
|
||||
const char *param;
|
||||
const char *config;
|
||||
const char *section;
|
||||
const char *text;
|
||||
uint32_t param_ofs;
|
||||
uint32_t config_ofs;
|
||||
uint32_t section_ofs;
|
||||
uint32_t text_ofs;
|
||||
int8_t status;
|
||||
};
|
||||
|
||||
|
|
@ -19,6 +21,8 @@ int32_t wiki_count(void);
|
|||
const struct wiki_entry *wiki_get_entries(void);
|
||||
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);
|
||||
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_free(void);
|
||||
|
||||
|
|
|
|||
BIN
webif/wiki_gen
BIN
webif/wiki_gen
Binary file not shown.
Loading…
Reference in New Issue
Block a user