void gbox_write_share_cards_info(void) { uint16_t card_count_shared = 0; uint16_t card_count_expired = 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); fclose(fhandle_shared); fext = FILE_BACKUP_CARDS_INFO; fname = get_gbox_tmp_fname(fext); FILE *fhandle_expired; fhandle_expired = fopen(fname, "w"); if(!fhandle_expired) { cs_log("Couldn't open %s: %s", fname, strerror(errno)); return; } cs_readlock(__func__, &gbox_cards_lock); LL_ITER it2 = ll_iter_create(gbox_backup_cards); while((card = ll_iter_next(&it2))) { if (card->type == GBOX_CARD_TYPE_GBOX) { fprintf(fhandle_expired, "CardID %2d at %s Card %08X Sl:%2d Lev:%1d dist:%1d id:%04X\n", card_count_expired, card->origin_peer->hostname, card->caprovid, card->id.slot, card->lvl, card->dist, card->id.peer); card_count_expired++; } } cs_readunlock(__func__, &gbox_cards_lock); fclose(fhandle_expired); return; }
void gbox_write_shared_cards_info(void) { int32_t card_count = 0; int32_t i = 0; FILE *fhandle; fhandle = fopen(FILE_SHARED_CARDS_INFO, "w"); if(!fhandle) { cs_log("Couldn't open %s: %s\n", FILE_SHARED_CARDS_INFO, strerror(errno)); return; } LL_ITER it; struct gbox_card *card; //write local cards it = ll_iter_create(local_gbox.cards); while((card = ll_iter_next(&it))) { fprintf(fhandle, "CardID %4d at oscam Card %08X Sl:%2d Lev:%2d dist:%2d id:%04X\n", card_count, card->provid_1, card->slot, card->lvl, card->dist, card->peer_id); card_count++; } // end of while ll_iter_next struct s_client *cl; for(i = 0, cl = first_client; cl; cl = cl->next, i++) { if(cl->gbox) { struct s_reader *rdr = cl->reader; struct gbox_peer *peer = cl->gbox; if((rdr->card_status == CARD_INSERTED) && (cl->typ == 'p')) { it = ll_iter_create(peer->gbox.cards); while((card = ll_iter_next(&it))) { fprintf(fhandle, "CardID %4d at %s Card %08X Sl:%2d Lev:%2d dist:%2d id:%04X\n", card_count, cl->reader->device, card->provid_1, card->slot, card->lvl, card->dist, card->peer_id); card_count++; } // end of while ll_iter_next } // end of if INSERTED && 'p' } // end of if cl->gbox } // end of for cl->next fclose(fhandle); return; }
static void cs_waitforcardinit(void) { if (cfg.waitforcards) { cs_log("waiting for local card init"); int32_t card_init_done; do { card_init_done = 1; struct s_reader *rdr; LL_ITER itr = ll_iter_create(configured_readers); while((rdr = ll_iter_next(&itr))) { if (rdr->enable && !is_cascading_reader(rdr) && (rdr->card_status == CARD_NEED_INIT || rdr->card_status == UNKNOWN)) { card_init_done = 0; break; } } if (!card_init_done) cs_sleepms(300); // wait a little bit //alarm(cfg.cmaxidle + cfg.ctimeout / 1000 + 1); } while (!card_init_done && !exit_oscam); if (cfg.waitforcards_extra_delay>0 && !exit_oscam) cs_sleepms(cfg.waitforcards_extra_delay); cs_log("init for all local cards done"); } }
static void *arm_led_thread_main(void *UNUSED(thread_data)) { uint8_t running = 1; while (running) { LL_ITER iter = ll_iter_create(arm_led_actions); struct s_arm_led *arm_led; while ((arm_led = ll_iter_next(&iter))) { int32_t led, action; time_t now, start; led = arm_led->led; action = arm_led->action; now = time((time_t)0); start = arm_led->start_time; ll_iter_remove_data(&iter); if (action == LED_STOP_THREAD) { running = 0; break; } if (now - start < ARM_LED_TIMEOUT) { arm_switch_led_from_thread(led, action); } } if (running) { sleep(60); } } ll_clear_data(arm_led_actions); pthread_exit(NULL); return NULL; }
void log_list_thread(void) { char buf[LOG_BUF_SIZE]; log_running = 1; set_thread_name(__func__); do { log_list_queued = 0; LL_ITER it = ll_iter_create(log_list); struct s_log *log; while((log = ll_iter_next_remove(&it))) { int8_t do_flush = ll_count(log_list) == 0; //flush on writing last element cs_strncpy(buf, log->txt, LOG_BUF_SIZE); if(log->direct_log) { cs_write_log(buf, do_flush); } else { write_to_log(buf, log, do_flush); } NULLFREE(log->txt); NULLFREE(log); } if(!log_list_queued) // The list is empty, sleep until new data comes in and we are woken up sleepms_on_cond(&log_thread_sleep_cond_mutex, &log_thread_sleep_cond, 60 * 1000); } while(log_running); ll_destroy(log_list); log_list = NULL; }
static void account_au_fn(const char *token, char *value, void *setting, FILE *f) { struct s_auth *account = setting; if (value) { // set default values for usage during runtime from Webif account->autoau = 0; if (!account->aureader_list) account->aureader_list = ll_create("aureader_list"); if (streq(value, "1")) account->autoau = 1; strtolower(value); ll_clear(account->aureader_list); LL_ITER itr = ll_iter_create(configured_readers); struct s_reader *rdr; char *pch, *saveptr1 = NULL; for (pch = strtok_r(value, ",", &saveptr1); pch != NULL; pch = strtok_r(NULL, ",", &saveptr1)) { ll_iter_reset(&itr); while ((rdr = ll_iter_next(&itr))) { if (streq(rdr->label, pch) || account->autoau) { ll_append(account->aureader_list, rdr); } } } return; } if (account->autoau == 1) { fprintf_conf(f, token, "%d\n", account->autoau); } else if (account->aureader_list) { value = mk_t_aureader(account); if (strlen(value) > 0) fprintf_conf(f, token, "%s\n", value); free_mk_t(value); } else if (cfg.http_full_cfg) { fprintf_conf(f, token, "%s\n", ""); } }
static void camd33_request_emm() { uchar mbuf[20]; struct s_reader *aureader = NULL, *rdr = NULL; //TODO: just take the first reader in list LL_ITER itr = ll_iter_create(cur_client()->aureader_list); while ((rdr = ll_iter_next(&itr))) { aureader=rdr; break; } if (!aureader) return; if (aureader->hexserial[0]) { log_emm_request(aureader); mbuf[0]=0; mbuf[1]=aureader->caid>>8; mbuf[2]=aureader->caid&0xff; memcpy(mbuf+3, aureader->hexserial, 4); memcpy(mbuf+7, &aureader->prid[0][1], 3); memcpy(mbuf+10, &aureader->prid[2][1], 3); camd33_send(mbuf, 13); }
static void camd33_request_emm(void) { uchar mbuf[20]; struct s_reader *aureader = NULL, *rdr = NULL; //TODO: just take the first reader in list LL_ITER itr = ll_iter_create(cur_client()->aureader_list); while((rdr = ll_iter_next(&itr))) { aureader = rdr; break; } if(!aureader) { return; } if(aureader->hexserial[0]) { cs_log("%s emm-request sent (reader=%s, caid=%04X, auprovid=%06X)", username(cur_client()), aureader->label, aureader->caid, aureader->auprovid ? aureader->auprovid : b2i(4, aureader->prid[0])); mbuf[0] = 0; mbuf[1] = aureader->caid >> 8; mbuf[2] = aureader->caid & 0xff; memcpy(mbuf + 3, aureader->hexserial, 4); memcpy(mbuf + 7, &aureader->prid[0][1], 3); memcpy(mbuf + 10, &aureader->prid[2][1], 3); camd33_send(mbuf, 13); }
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_add_good_card(struct s_client *cl, uint16_t id_card, uint16_t caid, uint32_t prov, uint16_t sid_ok) { struct gbox_peer *peer = cl->gbox; struct gbox_card *card = NULL; struct gbox_srvid *srvid = NULL; LL_ITER it = ll_iter_create(peer->gbox.cards); while((card = ll_iter_next(&it))) { if(card->peer_id == id_card && card->caid == caid && card->provid == prov) { cl->reader->currenthops = card->dist; LL_ITER it2 = ll_iter_create(card->goodsids); while((srvid = ll_iter_next(&it2))) { if(srvid->sid == sid_ok) { return; // sid_ok is already in the list of goodsids } } LL_ITER it3 = ll_iter_create(card->badsids); while((srvid = ll_iter_next(&it3))) { if(srvid->sid == sid_ok) { ll_iter_remove_data(&it3); // remove sid_ok from badsids break; } } if(!cs_malloc(&srvid, sizeof(struct gbox_srvid))) { return; } srvid->sid = sid_ok; srvid->peer_idcard = id_card; srvid->provid_id = card->provid; cs_debug_mask(D_READER, "GBOX Adding good SID: %04X for CAID: %04X Provider: %04X on CardID: %04X\n", sid_ok, caid, card->provid, id_card); ll_append(card->goodsids, srvid); break; } }//end of ll_iter_next //return dist_c; }
struct s_reader *get_reader_by_label(char *lbl) { struct s_reader *rdr; LL_ITER itr = ll_iter_create(configured_readers); while((rdr = ll_iter_next(&itr))) { if(streq(lbl, rdr->label)) { break; } } return rdr; }
int32_t ICC_Async_Init_Locks (void) { // Init device specific locks here, called from init thread // before reader threads are running struct s_reader *rdr; LL_ITER itr = ll_iter_create(configured_readers); while((rdr = ll_iter_next(&itr))) { if (rdr->crdr.lock_init) rdr->crdr.lock_init(rdr); } return OK; }
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; } 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, "CardID %4d Card %08X id:%04X #CWs:%d AVGtime:%d ms\n", card_count, card->caprovid, card->id.peer, card->no_cws_returned, card->average_cw_time); fprintf(fhandle, "Good SIDs:\n"); LL_ITER it2 = ll_iter_create(card->goodsids); while((srvid_good = ll_iter_next(&it2))) { fprintf(fhandle, "%04X\n", srvid_good->srvid.sid); } fprintf(fhandle, "Bad SIDs:\n"); it2 = ll_iter_create(card->badsids); while((srvid_bad = ll_iter_next(&it2))) { fprintf(fhandle, "%04X #%d\n", srvid_bad->srvid.sid, srvid_bad->bad_strikes); } card_count++; } } // end of while ll_iter_next cs_readunlock(__func__, &gbox_cards_lock); fclose(fhandle); return; }
/* * returns string of comma separated values */ char *mk_t_emmbylen(struct s_reader *rdr) { char *value, *pos, *dot = ""; int32_t num, needed = 0; struct s_emmlen_range *blocklen; if(!rdr->blockemmbylen) { return ""; } LL_ITER it = ll_iter_create(rdr->blockemmbylen); while((blocklen = ll_iter_next(&it))) { needed += 5 + 1; // max digits of int16 + "," if(blocklen->max == 0) { needed += 1 + 1; // "-" + "," } else if(blocklen->min != blocklen->max) { needed += 1 + 5 + 1; // "-" + max digits of int16 + "," } } // the trailing zero is already included: it's the first "," if(!cs_malloc(&value, needed)) { return ""; } pos = value; ll_iter_reset(&it); while((blocklen = ll_iter_next(&it))) { if(blocklen->min == blocklen->max) { num = snprintf(pos, needed, "%s%d", dot, blocklen->min); } else if(blocklen->max == 0) { num = snprintf(pos, needed, "%s%d-", dot, blocklen->min); } else { num = snprintf(pos, needed, "%s%d-%d", dot, blocklen->min, blocklen->max); } pos += num; needed -= num; dot = ","; } return value; }
void gbox_free_cardlist(LLIST *card_list) { if(card_list) { 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_NULL(card_list); } return; }
void 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; } 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); }
void log_list_thread(void) { char buf[LOG_BUF_SIZE]; int last_count=ll_count(log_list), count, grow_count=0, write_count; do { LL_ITER it = ll_iter_create(log_list); struct s_log *log; write_count = 0; while ((log=ll_iter_next_remove(&it))) { int8_t do_flush = ll_count(log_list) == 0; //flush on writing last element cs_strncpy(buf, log->txt, LOG_BUF_SIZE); if (log->direct_log) cs_write_log(buf, do_flush); else write_to_log(buf, log, do_flush); free(log->txt); free(log); //If list is faster growing than we could write to file, drop list: write_count++; if (write_count%10000 == 0) { //check every 10000 writes: count = ll_count(log_list); if (count > last_count) { grow_count++; if (grow_count > 5) { //5 times still growing cs_write_log("------------->logging temporary disabled (30s) - too much data!\n", 1); cfg.disablelog = 1; ll_iter_reset(&it); while ((log=ll_iter_next_remove(&it))) { //clear log free(log->txt); free(log); } cs_sleepms(30*1000); cfg.disablelog = 0; grow_count = 0; last_count = 0; break; } } else grow_count = 0; last_count = count; } } cs_sleepms(250); } while(1); }
int32_t dvbapi_edit_channel_cache(int32_t demux_id, int32_t pidindex, uint8_t add) { struct s_ecmpids *p = &demux[demux_id].ECMpids[pidindex]; struct s_channel_cache *c; LL_ITER it; int32_t count = 0; if(!channel_cache) { channel_cache = ll_create("channel cache"); } it = ll_iter_create(channel_cache); while((c = ll_iter_next(&it))) { if(demux[demux_id].program_number == c->srvid && p->CAID == c->caid && p->ECM_PID == c->pid && (p->PROVID == c->prid || p->PROVID == 0)) { if(add && p->CHID == c->chid) { return 0; //already added } ll_iter_remove_data(&it); count++; } } if(add) { if(!cs_malloc(&c, sizeof(struct s_channel_cache))) { return count; } c->srvid = demux[demux_id].program_number; c->caid = p->CAID; c->pid = p->ECM_PID; c->prid = p->PROVID; c->chid = p->CHID; ll_append(channel_cache, c); #ifdef WITH_DEBUG char buf[ECM_FMT_LEN]; ecmfmt(c->caid, 0, c->prid, c->chid, c->pid, c->srvid, 0, 0, 0, 0, buf, ECM_FMT_LEN, 0, 0); cs_debug_mask(D_DVBAPI, "[DVBAPI] added to channel cache: %s", buf); #endif count++; } return count; }
/* * Creates a string ready to write as a token into config or WebIf for au readers. You must free the returned value through free_mk_t(). */ char *mk_t_aureader(struct s_auth *account) { int32_t pos = 0; char *dot = ""; char *value; if (ll_count(account->aureader_list) == 0 || !cs_malloc(&value, 256)) return ""; value[0] = '\0'; struct s_reader *rdr; LL_ITER itr = ll_iter_create(account->aureader_list); while ((rdr = ll_iter_next(&itr))) { pos += snprintf(value + pos, 256-pos, "%s%s", dot, rdr->label); dot = ","; } return value; }
int32_t cacheex_add_stats(struct s_client *cl, uint16_t caid, uint16_t srvid, uint32_t prid, uint8_t direction) { if(!cfg.cacheex_enable_stats) { return -1; } // create list if doesn't exist if(!cl->ll_cacheex_stats) { cl->ll_cacheex_stats = ll_create("ll_cacheex_stats"); } time_t now = time((time_t *)0); LL_ITER itr = ll_iter_create(cl->ll_cacheex_stats); S_CACHEEX_STAT_ENTRY *cacheex_stats_entry; // check for existing entry while((cacheex_stats_entry = ll_iter_next(&itr))) { if(cacheex_stats_entry->cache_srvid == srvid && cacheex_stats_entry->cache_caid == caid && cacheex_stats_entry->cache_prid == prid && cacheex_stats_entry->cache_direction == direction) { // we already have this entry - just add count and time cacheex_stats_entry->cache_count++; cacheex_stats_entry->cache_last = now; return cacheex_stats_entry->cache_count; } } // if we land here we have to add a new entry if(cs_malloc(&cacheex_stats_entry, sizeof(S_CACHEEX_STAT_ENTRY))) { cacheex_stats_entry->cache_caid = caid; cacheex_stats_entry->cache_srvid = srvid; cacheex_stats_entry->cache_prid = prid; cacheex_stats_entry->cache_count = 1; cacheex_stats_entry->cache_last = now; cacheex_stats_entry->cache_direction = direction; ll_iter_insert(&itr, cacheex_stats_entry); return 1; } return 0; }
void free_joblist(struct s_client *cl) { pthread_mutex_trylock(&cl->thread_lock); LL_ITER it = ll_iter_create(cl->joblist); struct job_data *data; while((data = ll_iter_next(&it))) { free_job_data(data); } ll_destroy(cl->joblist); cl->joblist = NULL; cl->account = NULL; if(cl->work_job_data) // Free job_data that was not freed by work_thread { free_job_data(cl->work_job_data); } cl->work_job_data = NULL; pthread_mutex_unlock(&cl->thread_lock); pthread_mutex_destroy(&cl->thread_lock); }
static S_COOL_CHANHANDLE *find_chanhandle(int32_t demux_index, int32_t pid) { // Find matching channel, if it exists. if(ll_count(ll_cool_chanhandle) > 0) { LL_ITER itr = ll_iter_create(ll_cool_chanhandle); S_COOL_CHANHANDLE *handle_item; while((handle_item = ll_iter_next(&itr))) { if(handle_item->demux_index == demux_index && handle_item->pid == pid) { return handle_item; } } } return NULL; }
static S_COOL_FILTER *find_filter_by_chanhandle(S_COOL_CHANHANDLE *chanhandle, int32_t filter_num) { // Find matching channel, if it exists. if(ll_count(ll_cool_filter) > 0) { LL_ITER itr = ll_iter_create(ll_cool_filter); S_COOL_FILTER *filter_item; while((filter_item = ll_iter_next(&itr))) { if(filter_item->chanhandle == chanhandle && filter_item->filter_num == filter_num) { return filter_item; } } } return NULL; }
static int32_t remove_filter(S_COOL_FILTER *filter_handle) { if(ll_count(ll_cool_filter) > 0) { LL_ITER itr = ll_iter_create(ll_cool_filter); S_COOL_FILTER *filter_item; while((filter_item = ll_iter_next(&itr))) { if(filter_item == filter_handle) { ll_iter_remove_data(&itr); return 0; } } } return -1; }
static int32_t remove_chanhandle(S_COOL_CHANHANDLE *handle) { // Find matching channel, if it exists. if(ll_count(ll_cool_chanhandle) > 0) { LL_ITER itr = ll_iter_create(ll_cool_chanhandle); S_COOL_CHANHANDLE *handle_item; while((handle_item = ll_iter_next(&itr))) { if(handle_item == handle) { ll_iter_remove_data(&itr); return 0; } } } return -1; }
void log_list_thread() { char buf[LOG_BUF_SIZE]; while (1) { LL_ITER it = ll_iter_create(log_list); struct s_log *log; while ((log=ll_iter_next_remove(&it))) { int8_t do_flush = ll_count(log_list) == 0; //flush on writing last element cs_strncpy(buf, log->txt, LOG_BUF_SIZE); if (log->direct_log) cs_write_log(buf, do_flush); else write_to_log(buf, log, do_flush); free(log->txt); free(log); } cs_sleepms(50); } }
void free_joblist(struct s_client *cl) { int32_t lock_status = pthread_mutex_trylock(&cl->thread_lock); LL_ITER it = ll_iter_create(cl->joblist); struct job_data *data; while((data = ll_iter_next(&it))) { free_job_data(data); } ll_destroy(&cl->joblist); cl->account = NULL; if(cl->work_job_data) // Free job_data that was not freed by work_thread { free_job_data(cl->work_job_data); } cl->work_job_data = NULL; if(lock_status == 0) { SAFE_MUTEX_UNLOCK(&cl->thread_lock); } pthread_mutex_destroy(&cl->thread_lock); }
void gbox_remove_cards_without_goodsids(LLIST *card_list) { if(card_list) { LL_ITER it = ll_iter_create(card_list); struct gbox_card *card; while((card = ll_iter_next(&it))) { if(ll_count(card->goodsids) == 0) { ll_iter_remove(&it); gbox_free_card(card); } else { ll_destroy_data_NULL(card->badsids); } } } return; }
void dvbapi_save_channel_cache(void) { char fname[256]; get_config_filename(fname, sizeof(fname), "oscam.ccache"); FILE *file = fopen(fname, "w"); if(!file) { cs_log("dvbapi channelcache can't write to file %s", fname); return; } LL_ITER it = ll_iter_create(channel_cache); struct s_channel_cache *c; while((c = ll_iter_next(&it))) { fprintf(file, "%04X,%06X,%04X,%04X,%06X\n", c->caid, c->prid, c->srvid, c->pid, c->chid); } fclose(file); cs_log("dvbapi channelcache saved to %s", fname); }
struct s_channel_cache *dvbapi_find_channel_cache(int32_t demux_id, int32_t pidindex, int8_t caid_and_prid_only) { struct s_ecmpids *p = &demux[demux_id].ECMpids[pidindex]; struct s_channel_cache *c; LL_ITER it; if(!channel_cache) { channel_cache = ll_create("channel cache"); } it = ll_iter_create(channel_cache); while((c = ll_iter_next(&it))) { if(caid_and_prid_only) { if(p->CAID == c->caid && (p->PROVID == c->prid || p->PROVID == 0)) // PROVID ==0 some provider no provid in PMT table { return c; } } else { if(demux[demux_id].program_number == c->srvid && p->CAID == c->caid && p->ECM_PID == c->pid && (p->PROVID == c->prid || p->PROVID == 0)) // PROVID ==0 some provider no provid in PMT table { #ifdef WITH_DEBUG char buf[ECM_FMT_LEN]; ecmfmt(c->caid, 0, c->prid, c->chid, c->pid, c->srvid, 0, 0, 0, 0, buf, ECM_FMT_LEN, 0, 0); cs_debug_mask(D_DVBAPI, "[DVBAPI] found in channel cache: %s", buf); #endif return c; } } } return NULL; }