667 lines
18 KiB
C
Executable File
667 lines
18 KiB
C
Executable File
#define MODULE_LOG_PREFIX "gbox"
|
|
|
|
#include "globals.h"
|
|
|
|
#ifdef MODULE_GBOX
|
|
#include "module-gbox.h"
|
|
#include "module-gbox-cards.h"
|
|
#include "module-gbox-helper.h"
|
|
#include "oscam-lock.h"
|
|
#include "oscam-garbage.h"
|
|
#include "oscam-files.h"
|
|
#include "oscam-chk.h"
|
|
#include "oscam-string.h"
|
|
#include "oscam-time.h"
|
|
|
|
LLIST *gbox_cards;
|
|
CS_MUTEX_LOCK gbox_cards_lock;
|
|
uint8_t checkcode[7];
|
|
uint8_t last_checkcode[7];
|
|
uint8_t sid_verified = 0;
|
|
|
|
GBOX_CARDS_ITER *gbox_cards_iter_create(void)
|
|
{
|
|
GBOX_CARDS_ITER *gci;
|
|
if(!cs_malloc(&gci, sizeof(GBOX_CARDS_ITER)))
|
|
{ return NULL; }
|
|
cs_readlock(__func__, &gbox_cards_lock);
|
|
gci->it = ll_iter_create(gbox_cards);
|
|
return gci;
|
|
}
|
|
|
|
void gbox_cards_iter_destroy(GBOX_CARDS_ITER *gci)
|
|
{
|
|
cs_readunlock(__func__, &gbox_cards_lock);
|
|
if (gci) { add_garbage(gci); }
|
|
}
|
|
|
|
struct gbox_card *gbox_cards_iter_next(GBOX_CARDS_ITER *gci)
|
|
{
|
|
if (gci) { return ll_iter_next(&gci->it); }
|
|
else { return NULL; }
|
|
}
|
|
|
|
uint8_t gbox_get_crd_dist_lev(uint16_t crd_id)
|
|
{
|
|
uint8_t crd_dist = 0;
|
|
uint8_t crd_level = 0;
|
|
struct gbox_card *card;
|
|
cs_readlock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
if ((card->type == GBOX_CARD_TYPE_GBOX || card->type == GBOX_CARD_TYPE_CCCAM) && card->id.peer == crd_id)
|
|
{
|
|
crd_dist = card->dist;
|
|
crd_level = card->lvl;
|
|
break;
|
|
}
|
|
}
|
|
cs_readunlock(__func__, &gbox_cards_lock);
|
|
return ((crd_level << 4) | (crd_dist & 0xf));
|
|
}
|
|
|
|
void gbox_write_share_cards_info(void)
|
|
{
|
|
uint16_t card_count_shared = 0;
|
|
char *fext = FILE_SHARED_CARDS_INFO;
|
|
char *fname = get_gbox_tmp_fname(fext);
|
|
FILE *fhandle_shared;
|
|
fhandle_shared = fopen(fname, "w");
|
|
if(!fhandle_shared)
|
|
{
|
|
cs_log("Couldn't open %s: %s", fname, strerror(errno));
|
|
return;
|
|
}
|
|
|
|
struct gbox_card *card;
|
|
cs_readlock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
if (card->type == GBOX_CARD_TYPE_GBOX)
|
|
{
|
|
fprintf(fhandle_shared, "CardID %d at %s Card %08X Sl:%d Lev:%1d dist:%1d id:%04X\n",
|
|
card_count_shared, card->origin_peer->hostname, card->caprovid,
|
|
card->id.slot, card->lvl, card->dist, card->id.peer);
|
|
card_count_shared++;
|
|
}
|
|
}
|
|
cs_readunlock(__func__, &gbox_cards_lock);
|
|
//char tmp[32];
|
|
//fprintf(fhandle_shared, "my checkcode: %s",cs_hexdump(1, gbox_get_my_checkcode(), 7, tmp, sizeof(tmp)));
|
|
fclose(fhandle_shared);
|
|
cs_log_dbg(D_READER,"share.info written");
|
|
//cs_log("share.info written");
|
|
return;
|
|
}
|
|
|
|
uint16_t gbox_write_local_cards_info(void)
|
|
{
|
|
uint16_t card_count_local = 0;
|
|
char *fext = FILE_LOCAL_CARDS_INFO;
|
|
char *fname = get_gbox_tmp_fname(fext);
|
|
FILE *fhandle_local;
|
|
fhandle_local = fopen(fname, "w");
|
|
if(!fhandle_local)
|
|
{
|
|
cs_log("Couldn't open %s: %s", fname, strerror(errno));
|
|
return 0;
|
|
}
|
|
|
|
struct gbox_card *card;
|
|
cs_readlock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
switch (card->type)
|
|
{
|
|
case GBOX_CARD_TYPE_GBOX:
|
|
break;
|
|
case GBOX_CARD_TYPE_LOCAL:
|
|
fprintf(fhandle_local, "CardID:%2d %s %08X Sl:%2d id:%04X\n",
|
|
card_count_local, "Local_Card", card->caprovid, card->id.slot, card->id.peer);
|
|
card_count_local++;
|
|
break;
|
|
case GBOX_CARD_TYPE_BETUN:
|
|
fprintf(fhandle_local, "CardID:%2d %s %08X Sl:%2d id:%04X\n",
|
|
card_count_local, "Betun_Card", card->caprovid, card->id.slot, card->id.peer);
|
|
card_count_local++;
|
|
break;
|
|
case GBOX_CARD_TYPE_CCCAM:
|
|
fprintf(fhandle_local, "CardID:%2d %s %08X Sl:%2d id:%04X\n",
|
|
card_count_local, "CCcam_Card", card->caprovid, card->id.slot, card->id.peer);
|
|
card_count_local++;
|
|
break;
|
|
case GBOX_CARD_TYPE_PROXY:
|
|
fprintf(fhandle_local, "CardID:%2d %s %08X Sl:%2d id:%04X\n",
|
|
card_count_local, "Proxy_Card", card->caprovid, card->id.slot, card->id.peer);
|
|
card_count_local++;
|
|
break;
|
|
default:
|
|
cs_log("Invalid card type: %d in gbox_write_cards_info", card->type);
|
|
break;
|
|
}
|
|
}
|
|
cs_readunlock(__func__, &gbox_cards_lock);
|
|
fclose(fhandle_local);
|
|
cs_log_dbg(D_READER,"sc.info written");
|
|
//cs_log("sc.info written");
|
|
return card_count_local;
|
|
}
|
|
|
|
void gbox_write_stats(void)
|
|
{
|
|
int32_t card_count = 0;
|
|
struct gbox_good_srvid *srvid_good = NULL;
|
|
struct gbox_bad_srvid *srvid_bad = NULL;
|
|
char *fext = FILE_STATS;
|
|
char *fname = get_gbox_tmp_fname(fext);
|
|
FILE *fhandle;
|
|
fhandle = fopen(fname, "w");
|
|
if(!fhandle)
|
|
{
|
|
cs_log("Couldn't open %s: %s", fname, strerror(errno));
|
|
return;
|
|
}
|
|
fprintf(fhandle, "Statistics for peer cards received\n");
|
|
struct gbox_card *card;
|
|
cs_readlock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
if (card->type == GBOX_CARD_TYPE_GBOX)
|
|
{
|
|
fprintf(fhandle, "\nCard# %04d CaProv:%08X ID:%04X #CWs:%d AVGtime:%d ms",
|
|
card_count +1, card->caprovid, card->id.peer, card->no_cws_returned, card->average_cw_time);
|
|
fprintf(fhandle, "\n Good SID: ");
|
|
LL_ITER it2 = ll_iter_create(card->goodsids);
|
|
while((srvid_good = ll_iter_next(&it2)))
|
|
{ fprintf(fhandle, "%04X ", srvid_good->srvid.sid); }
|
|
fprintf(fhandle, "\n Bad SID: ");
|
|
it2 = ll_iter_create(card->badsids);
|
|
while((srvid_bad = ll_iter_next(&it2)))
|
|
{ fprintf(fhandle, "%04X ", srvid_bad->srvid.sid); }
|
|
card_count++;
|
|
}
|
|
} // end of while ll_iter_next
|
|
cs_readunlock(__func__, &gbox_cards_lock);
|
|
|
|
fclose(fhandle);
|
|
return;
|
|
}
|
|
|
|
void init_gbox_cards_list(void)
|
|
{
|
|
gbox_cards = ll_create("gbox.cards");
|
|
cs_lock_create(__func__, &gbox_cards_lock, "gbox_cards_lock", 5000);
|
|
}
|
|
|
|
static void gbox_free_card(struct gbox_card *card)
|
|
{
|
|
ll_destroy_data(&card->badsids);
|
|
ll_destroy_data(&card->goodsids);
|
|
add_garbage(card);
|
|
return;
|
|
}
|
|
|
|
uint8_t *gbox_get_my_checkcode(void)
|
|
{
|
|
return &checkcode[0];
|
|
}
|
|
|
|
uint8_t *gbox_update_my_checkcode(void)
|
|
{
|
|
checkcode[0] = 0x15;
|
|
checkcode[1] = 0x30;
|
|
checkcode[2] = 0x02;
|
|
checkcode[3] = 0x04;
|
|
checkcode[4] = 0x19;
|
|
checkcode[5] = 0x19;
|
|
checkcode[6] = 0x66;
|
|
|
|
struct gbox_card *card;
|
|
cs_readlock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
if(card->lvl)
|
|
{
|
|
checkcode[0] ^= (0xFF & (card->caprovid >> 24));
|
|
checkcode[1] ^= (0xFF & (card->caprovid >> 16));
|
|
checkcode[2] ^= (0xFF & (card->caprovid >> 8));
|
|
checkcode[3] ^= (0xFF & (card->caprovid));
|
|
checkcode[4] ^= (0xFF & (card->id.slot));
|
|
checkcode[5] ^= (0xFF & (card->id.peer >> 8));
|
|
checkcode[6] ^= (0xFF & (card->id.peer));
|
|
}
|
|
}
|
|
cs_readunlock(__func__, &gbox_cards_lock);
|
|
|
|
if(memcmp(last_checkcode, checkcode, 7))
|
|
{
|
|
memcpy(last_checkcode, checkcode, 7);
|
|
//cs_log_dump(gbox_get_my_checkcode(), 7, "my checkcode updated:");
|
|
cs_log_dump_dbg(D_READER, gbox_get_my_checkcode(), 7, "my checkcode updated:");
|
|
}
|
|
return &checkcode[0];
|
|
}
|
|
|
|
uint16_t gbox_count_cards(void)
|
|
{
|
|
return ll_count(gbox_cards);
|
|
}
|
|
|
|
uint16_t gbox_count_peer_cards(uint16_t peer_id)
|
|
{
|
|
uint16_t counter = 0;
|
|
struct gbox_card *card;
|
|
|
|
cs_readlock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
if (card->origin_peer && card->origin_peer->gbox.id == peer_id)
|
|
{ counter++; }
|
|
}
|
|
cs_readunlock(__func__, &gbox_cards_lock);
|
|
|
|
return counter;
|
|
}
|
|
|
|
void gbox_delete_cards(uint8_t delete_type, uint16_t criteria)
|
|
{
|
|
struct gbox_card *card;
|
|
uint8_t found;
|
|
|
|
cs_writelock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
found = 0;
|
|
switch (delete_type)
|
|
{
|
|
case GBOX_DELETE_FROM_PEER:
|
|
if (card->origin_peer && card->origin_peer->gbox.id == criteria)
|
|
{ found = 1; }
|
|
break;
|
|
case GBOX_DELETE_WITH_ID:
|
|
if (card->id.peer == criteria)
|
|
{ found = 1; }
|
|
break;
|
|
case GBOX_DELETE_WITH_TYPE:
|
|
if (card->type == criteria)
|
|
{ found = 1; }
|
|
break;
|
|
default:
|
|
cs_log("Invalid delete type: %d in gbox_delete_cards", delete_type);
|
|
break;
|
|
}
|
|
if (found)
|
|
{
|
|
cs_log_dbg(D_READER, "remove card from card_list - peer: %04X %08X dist %d", card->id.peer, card->caprovid, card->dist);
|
|
ll_remove(gbox_cards, card);
|
|
}
|
|
}
|
|
cs_writeunlock(__func__, &gbox_cards_lock);
|
|
return;
|
|
}
|
|
static uint8_t check_card_properties(uint32_t caprovid, uint16_t id_peer, uint8_t slot, uint8_t distance, uint8_t type)
|
|
{
|
|
uint8_t ret = 1;
|
|
|
|
if (!distance) //local card
|
|
{ return ret; }
|
|
|
|
struct gbox_card *card;
|
|
cs_writelock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
if (card->caprovid == caprovid && card->id.peer == id_peer && card->id.slot == slot && type != GBOX_CARD_TYPE_CCCAM)
|
|
{
|
|
if (distance < card->dist) //better card
|
|
{
|
|
ll_remove(gbox_cards, card);
|
|
ret = 1; //let card pass
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
ret = 0; //skip card
|
|
break;
|
|
}
|
|
}
|
|
if (card->caprovid == caprovid && card->id.peer == id_peer && type == GBOX_CARD_TYPE_CCCAM)
|
|
{
|
|
if (distance < card->dist) //better card
|
|
{
|
|
ll_remove(gbox_cards, card);
|
|
ret = 1; //let card pass
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
ret = 0; //skip card
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
cs_writeunlock(__func__, &gbox_cards_lock);
|
|
return ret;
|
|
}
|
|
|
|
void gbox_add_card(uint16_t id_peer, uint32_t caprovid, uint8_t slot, uint8_t level, uint8_t distance, uint8_t type, struct gbox_peer *origin_peer)
|
|
{
|
|
uint16_t caid = gbox_get_caid(caprovid);
|
|
uint32_t provid = gbox_get_provid(caprovid);
|
|
|
|
if(!caprovid) //skip caprov 00000000
|
|
{ return; }
|
|
//don't insert 0100:000000
|
|
if(caid_is_seca(caid) && (!provid))
|
|
{ return; }
|
|
//skip CAID 18XX providers
|
|
// if(caid_is_nagra(caid) && (provid))
|
|
// { return; }
|
|
|
|
struct gbox_card *card;
|
|
if(!cs_malloc(&card, sizeof(struct gbox_card)))
|
|
{
|
|
cs_log("Card allocation failed");
|
|
return;
|
|
}
|
|
if (check_card_properties(caprovid, id_peer, slot, distance, type) && !check_peer_ignored(id_peer))
|
|
{
|
|
cs_log_dbg(D_READER, "add card to card_list - peer: %04X %08X dist %d", id_peer, caprovid, distance);
|
|
card->caprovid = caprovid;
|
|
card->id.peer = id_peer;
|
|
card->id.slot = slot;
|
|
card->dist = distance;
|
|
card->lvl = level;
|
|
card->badsids = ll_create("badsids");
|
|
card->goodsids = ll_create("goodsids");
|
|
card->no_cws_returned = 0;
|
|
card->average_cw_time = 0;
|
|
card->type = type;
|
|
card->origin_peer = origin_peer;
|
|
cs_writelock(__func__, &gbox_cards_lock);
|
|
ll_append(gbox_cards, card);
|
|
cs_writeunlock(__func__, &gbox_cards_lock);
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void gbox_free_list(LLIST *card_list)
|
|
{
|
|
if(card_list)
|
|
{
|
|
cs_writelock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(card_list);
|
|
struct gbox_card *card;
|
|
while((card = ll_iter_next_remove(&it)))
|
|
{ gbox_free_card(card); }
|
|
ll_destroy(&gbox_cards);
|
|
cs_writeunlock(__func__, &gbox_cards_lock);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void gbox_free_cardlist(void)
|
|
{
|
|
gbox_free_list(gbox_cards);
|
|
return;
|
|
}
|
|
|
|
void gbox_add_good_sid(uint16_t id_card, uint16_t caid, uint8_t slot, uint16_t sid_ok, uint32_t cw_time)
|
|
{
|
|
struct gbox_card *card = NULL;
|
|
struct gbox_good_srvid *srvid = NULL;
|
|
uint8_t factor = 0;
|
|
|
|
cs_writelock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
if(card->id.peer == id_card && gbox_get_caid(card->caprovid) == caid && card->id.slot == slot)
|
|
{
|
|
card->no_cws_returned++;
|
|
if (!card->no_cws_returned)
|
|
{ card->no_cws_returned = 10; } // wrap around
|
|
if (card->no_cws_returned < 10)
|
|
{ factor = card->no_cws_returned; }
|
|
else
|
|
{ factor = 10; }
|
|
card->average_cw_time = ((card->average_cw_time * (factor-1)) + cw_time) / factor;
|
|
LL_ITER it2 = ll_iter_create(card->goodsids);
|
|
while((srvid = ll_iter_next(&it2)))
|
|
{
|
|
if(srvid->srvid.sid == sid_ok)
|
|
{
|
|
srvid->last_cw_received = time(NULL);
|
|
cs_writeunlock(__func__, &gbox_cards_lock);
|
|
return; // sid_ok is already in the list of goodsids
|
|
}
|
|
}
|
|
|
|
if(!cs_malloc(&srvid, sizeof(struct gbox_good_srvid)))
|
|
{
|
|
cs_writeunlock(__func__, &gbox_cards_lock);
|
|
cs_log("Good SID allocation failed");
|
|
return;
|
|
}
|
|
srvid->srvid.sid = sid_ok;
|
|
srvid->srvid.provid_id = gbox_get_provid(card->caprovid);
|
|
srvid->last_cw_received = time(NULL);
|
|
cs_log_dbg(D_READER, "Adding good SID: %04X for CAID: %04X Provider: %04X on CardID: %04X", sid_ok, caid, gbox_get_provid(card->caprovid), id_card);
|
|
ll_append(card->goodsids, srvid);
|
|
break;
|
|
}
|
|
} // end of ll_iter_next
|
|
// return dist_c;
|
|
cs_writeunlock(__func__, &gbox_cards_lock);
|
|
return;
|
|
}
|
|
|
|
void gbox_remove_bad_sid(uint16_t id_peer, uint8_t id_slot, uint16_t sid)
|
|
{
|
|
struct gbox_card *card = NULL;
|
|
struct gbox_bad_srvid *srvid = NULL;
|
|
|
|
cs_writelock(__func__, &gbox_cards_lock);
|
|
LL_ITER it2 = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it2)))
|
|
{
|
|
if(card->id.peer == id_peer && card->id.slot == id_slot)
|
|
{
|
|
LL_ITER it3 = ll_iter_create(card->badsids);
|
|
while((srvid = ll_iter_next(&it3)))
|
|
{
|
|
if(srvid->srvid.sid == sid)
|
|
{
|
|
ll_iter_remove_data(&it3); // remove sid_ok from badsids
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
cs_writeunlock(__func__, &gbox_cards_lock);
|
|
}
|
|
|
|
uint8_t gbox_next_free_slot(uint16_t id)
|
|
{
|
|
struct gbox_card *c;
|
|
uint8_t lastslot = 0;
|
|
|
|
cs_readlock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
while((c = ll_iter_next(&it)))
|
|
{
|
|
if(id == c->id.peer && c->id.slot > lastslot)
|
|
{ lastslot = c->id.slot; }
|
|
}
|
|
cs_readunlock(__func__, &gbox_cards_lock);
|
|
return ++lastslot;
|
|
}
|
|
|
|
static int8_t is_already_pending(LLIST *pending_cards, uint16_t peer_id, uint8_t slot)
|
|
{
|
|
if (!pending_cards)
|
|
{ return -1; }
|
|
|
|
int8_t ret = 0;
|
|
struct gbox_card_id *current_id;
|
|
LL_LOCKITER *li = ll_li_create(pending_cards, 0);
|
|
while ((current_id = ll_li_next(li)))
|
|
{
|
|
if (current_id->peer == peer_id && current_id->slot == slot)
|
|
{
|
|
ret = 1;
|
|
break;
|
|
}
|
|
}
|
|
ll_li_destroy(li);
|
|
return ret;
|
|
}
|
|
|
|
uint8_t gbox_get_cards_for_ecm(uint8_t *send_buf, int32_t len2, uint8_t max_cards, ECM_REQUEST *er, uint32_t *current_avg_card_time, uint16_t peer_id, uint8_t force_remm)
|
|
{
|
|
if (!send_buf || !er)
|
|
{ return 0; }
|
|
|
|
uint8_t nb_matching_crds = 0;
|
|
struct gbox_good_srvid *srvid_good = NULL;
|
|
struct gbox_bad_srvid *srvid_bad = NULL;
|
|
uint8_t enough = 0;
|
|
time_t time_since_lastcw;
|
|
|
|
// loop over good only
|
|
cs_readlock(__func__, &gbox_cards_lock);
|
|
LL_ITER it = ll_iter_create(gbox_cards);
|
|
LL_ITER it2;
|
|
struct gbox_card *card;
|
|
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
if(card->origin_peer && card->origin_peer->gbox.id == peer_id && card->type == GBOX_CARD_TYPE_GBOX &&
|
|
gbox_get_caid(card->caprovid) == er->caid && gbox_get_provid(card->caprovid) == er->prid && !is_already_pending(er->gbox_cards_pending, card->id.peer, card->id.slot))
|
|
{
|
|
sid_verified = 0;
|
|
|
|
// check if sid is good
|
|
it2 = ll_iter_create(card->goodsids);
|
|
while((srvid_good = ll_iter_next(&it2)))
|
|
{
|
|
if(srvid_good->srvid.provid_id == er->prid && srvid_good->srvid.sid == er->srvid)
|
|
{
|
|
if (!enough || *current_avg_card_time > card->average_cw_time)
|
|
{
|
|
time_since_lastcw = llabs(srvid_good->last_cw_received - time(NULL));
|
|
*current_avg_card_time = card->average_cw_time;
|
|
if (enough)
|
|
{ len2 = len2 - 3; }
|
|
else
|
|
{
|
|
nb_matching_crds++;
|
|
if (time_since_lastcw < GBOX_SID_CONFIRM_TIME && er->gbox_ecm_status == GBOX_ECM_NEW_REQ)
|
|
{ enough = 1; }
|
|
}
|
|
i2b_buf(2, card->id.peer, send_buf + len2);
|
|
send_buf[len2 + 2] = card->id.slot;
|
|
len2 = len2 + 3;
|
|
sid_verified = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(nb_matching_crds == max_cards)
|
|
{ break; }
|
|
}
|
|
}
|
|
cs_readunlock(__func__, &gbox_cards_lock);
|
|
|
|
// loop over bad and unknown cards
|
|
cs_writelock(__func__, &gbox_cards_lock);
|
|
it = ll_iter_create(gbox_cards);
|
|
while((card = ll_iter_next(&it)))
|
|
{
|
|
if(card->origin_peer && card->origin_peer->gbox.id == peer_id && card->type == GBOX_CARD_TYPE_GBOX &&
|
|
gbox_get_caid(card->caprovid) == er->caid && gbox_get_provid(card->caprovid) == er->prid && !is_already_pending(er->gbox_cards_pending, card->id.peer, card->id.slot) && !enough)
|
|
{
|
|
sid_verified = 0;
|
|
|
|
// check if sid is good
|
|
it2 = ll_iter_create(card->goodsids);
|
|
while((srvid_good = ll_iter_next(&it2)))
|
|
{
|
|
if(srvid_good->srvid.provid_id == er->prid && srvid_good->srvid.sid == er->srvid)
|
|
{
|
|
sid_verified = 1;
|
|
cs_log_dbg(D_READER, "ID: %04X SL: %02X SID: %04X is good", card->id.peer, card->id.slot, srvid_good->srvid.sid);
|
|
}
|
|
}
|
|
if(!sid_verified)
|
|
{
|
|
// check if sid is bad
|
|
LL_ITER itt = ll_iter_create(card->badsids);
|
|
while((srvid_bad = ll_iter_next(&itt)))
|
|
{
|
|
if(srvid_bad->srvid.provid_id == er->prid && srvid_bad->srvid.sid == er->srvid)
|
|
{
|
|
if (srvid_bad->bad_strikes < 3)
|
|
{
|
|
sid_verified = 2;
|
|
if(!force_remm)
|
|
{
|
|
srvid_bad->bad_strikes++;
|
|
}
|
|
else
|
|
{
|
|
srvid_bad->bad_strikes = 1;
|
|
//cs_log("cards.c - get card for ecm - Block bad SID: %04X - %d bad strikes", srvid_bad->srvid.sid, srvid_bad->bad_strikes);
|
|
}
|
|
}
|
|
else
|
|
{ sid_verified = 1; }
|
|
cs_log_dbg(D_READER, "CRD_ID: %04X Slot: %d SID: %04X failed to relpy %d times", card->id.peer, card->id.slot, srvid_bad->srvid.sid, srvid_bad->bad_strikes);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// sid is neither good nor bad
|
|
if(sid_verified != 1)
|
|
{
|
|
i2b_buf(2, card->id.peer, send_buf + len2);
|
|
send_buf[len2 + 2] = card->id.slot;
|
|
len2 = len2 + 3;
|
|
nb_matching_crds++;
|
|
|
|
if (!sid_verified)
|
|
{
|
|
if(!cs_malloc(&srvid_bad, sizeof(struct gbox_bad_srvid)))
|
|
{
|
|
cs_log("ServID allocation failed");
|
|
cs_writeunlock(__func__, &gbox_cards_lock);
|
|
return 0;
|
|
}
|
|
|
|
srvid_bad->srvid.sid = er->srvid;
|
|
srvid_bad->srvid.provid_id = gbox_get_provid(card->caprovid);
|
|
srvid_bad->bad_strikes = 1;
|
|
ll_append(card->badsids, srvid_bad);
|
|
cs_log_dbg(D_READER, "ID: %04X SL: %02X SID: %04X is not checked", card->id.peer, card->id.slot, srvid_bad->srvid.sid);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(nb_matching_crds == max_cards)
|
|
{ break; }
|
|
}
|
|
}
|
|
cs_writeunlock(__func__, &gbox_cards_lock);
|
|
return nb_matching_crds;
|
|
}
|
|
|
|
#endif
|