Пример #1
0
static void cacheex_del_hitcache(struct s_client *cl, ECM_REQUEST *er)
{
	HIT_KEY search;
	CACHE_HIT *result;

	memset(&search, 0, sizeof(HIT_KEY));
	search.caid = er->caid;
	search.prid = er->prid;
	search.srvid = er->srvid;

	if(cl && cl->grp)
		{
			result = find_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &cacheex_compare_hitkey);
			while(result)
			{
				result->grp &= ~cl->grp;
				result->grp_last_max_hitcache_time &= ~cl->grp;
				result = find_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &cacheex_compare_hitkey);
			}
		}

	SAFE_RWLOCK_WRLOCK(&hitcache_lock);
	search_remove_elem_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &cacheex_compare_hitkey);
    SAFE_RWLOCK_UNLOCK(&hitcache_lock);
}
Пример #2
0
/* this function shouldn't be called from irq */
u32 hash_entry_find(int hashd, u32 hash_key)
{
    struct hash_table_s *hash_table_ptr;
    struct hash_entry_s *hash_entry;
    u32 pseudo_key = 0;
    int loops;
    
    spin_lock(&hash_table_ptr->hash_lock);
    
    hash_table_ptr = find_hash_table(hashd);
    if (!hash_table_ptr->max_entries)
	return -1;

    hash_entry = hash_table_ptr->hash_entry;
    pseudo_key = hash_math_pseudo(hash_table_ptr, hash_key) % hash_table_ptr->max_entries;

    loops = 0;    
    do {
	if (hash_entry[pseudo_key].hash_key != hash_key)
	    pseudo_key = (pseudo_key + 1) % hash_table_ptr->max_entries;
	else {   
	
	    spin_unlock(&hash_table_ptr->hash_lock);
	    return hash_entry[pseudo_key].hash_addr;
	}
	
	loops++;
	
    } while(loops < hash_table_ptr->max_entries);
    
    spin_unlock(&hash_table_ptr->hash_lock);
    
    return 0;
}
Пример #3
0
static int32_t cacheex_check_hitcache(ECM_REQUEST *er, struct s_client *cl)
{
	CACHE_HIT *result;
	HIT_KEY search;
	memset(&search, 0, sizeof(HIT_KEY));
	search.caid = er->caid;
	search.prid = er->prid;
	search.srvid = er->srvid;
	SAFE_RWLOCK_RDLOCK(&hitcache_lock);
	result = find_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &cacheex_compare_hitkey);
	if(result){
		struct timeb now;
		cs_ftime(&now);
		int64_t gone = comp_timeb(&now, &result->time);
		uint64_t grp = cl?cl->grp:0;

		if(
			gone <= (cfg.max_hitcache_time*1000)
			&&
			(!grp || !result->grp || (grp & result->grp))
		)
		{
			SAFE_RWLOCK_UNLOCK(&hitcache_lock);
			return 1;
		}
	}
	SAFE_RWLOCK_UNLOCK(&hitcache_lock);
	return 0;
}
Пример #4
0
void hash_count_entries(int hashd) 
{
    struct hash_table_s *hash_table_ptr;    

    hash_table_ptr = find_hash_table(hashd);
    printk("hash_ptr %x\n", hash_table_ptr);
    printk("hash_max_entries %x\n", hash_table_ptr->max_entries);
    printk("hash_cur_entries %x\n", hash_table_ptr->cur_entries);
}
Пример #5
0
int unregister_hash_table(int hashd)
{
    struct hash_table_s *hash_table_ptr;    

    hash_table_ptr = find_hash_table(hashd);

    if (hash_table_ptr) {
        put_free_pages((u32)hash_table_ptr->hash_entry, (u8)(hash_table_ptr->page_order));
	put_free_pages((u32)hash_table_ptr, 0);
    }

    return 0;
}
Пример #6
0
static void cacheex_add_hitcache(struct s_client *cl, ECM_REQUEST *er)
{
	if (!cfg.max_hitcache_time) // we don't want check/save hitcache
		return;
	if (!cfg.cacheex_wait_timetab.cevnum)
		return;
	uint32_t cacheex_wait_time = get_cacheex_wait_time(er,NULL);
	if (!cacheex_wait_time)
		return;

	CACHE_HIT *result;
	HIT_KEY search;

	memset(&search, 0, sizeof(HIT_KEY));
	search.caid = er->caid;
	search.prid = er->prid;
	search.srvid = er->srvid;

	SAFE_RWLOCK_WRLOCK(&hitcache_lock);

	result = find_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &cacheex_compare_hitkey);
	if(!result) // not found, add it!
	{
		if(cs_malloc(&result, sizeof(CACHE_HIT)))
		{
			memset(result, 0, sizeof(CACHE_HIT));
			result->key.caid = er->caid;
			result->key.prid = er->prid;
			result->key.srvid = er->srvid;
			cs_ftime(&result->max_hitcache_time);
			add_hash_table(&ht_hitcache, &result->ht_node, &ll_hitcache, &result->ll_node, result, &result->key, sizeof(HIT_KEY));
		}
	}

	if(result)
	{
		if(cl)
		{
			result->grp |= cl->grp;
			result->grp_last_max_hitcache_time |= cl->grp;
		}
		cs_ftime(&result->time); //always update time;
	}

	SAFE_RWLOCK_UNLOCK(&hitcache_lock);
}
Пример #7
0
void add_hitcache(struct s_client *cl, ECM_REQUEST *er) {
	if (!cfg.max_hitcache_time)  //we don't want check/save hitcache
		return;
	if (!cfg.cacheex_wait_timetab.n)
		return;
	uint32_t cacheex_wait_time = get_cacheex_wait_time(er,NULL);
	if (!cacheex_wait_time)
		return;

	CACHE_HIT *result;
	HIT_KEY search;

	memset(&search, 0, sizeof(HIT_KEY));
	search.caid = er->caid;
	search.prid = er->prid;
	search.srvid = er->srvid;

	pthread_rwlock_wrlock(&hitcache_lock);

    result = find_hash_table(&ht_hitcache, &search, sizeof(HIT_KEY), &compare_hitkey);
    if(!result){  //not found, add it!

    	if(cs_malloc(&result, sizeof(CACHE_HIT))){
    	    memset(result, 0, sizeof(CACHE_HIT));
    	    result->key.caid = er->caid;
    	    result->key.prid = er->prid;
    	    result->key.srvid = er->srvid;

    		add_hash_table(&ht_hitcache, &result->ht_node, &ll_hitcache, &result->ll_node, result, &result->key, sizeof(HIT_KEY));
    	}
    }

    if(result){
		if(cl) result->grp |= cl->grp;
		cs_ftime(&result->time); //always update time;
    }

    pthread_rwlock_unlock(&hitcache_lock);
}
Пример #8
0
int hash_entry_add(int hashd, u32 hash_key, u32 hash_addr)
{
    struct hash_table_s *hash_table_ptr;
    struct hash_entry_s *hash_entry;
    u32 pseudo_key = 0;
    int loops;

    spin_lock(&hash_table_ptr->hash_lock);

    hash_table_ptr = find_hash_table(hashd);

    if (!hash_table_ptr->max_entries)
	return -1;

    hash_entry = hash_table_ptr->hash_entry;
    pseudo_key = hash_math_pseudo(hash_table_ptr, hash_key) % hash_table_ptr->max_entries;

    loops = 0;
    do {
	if (hash_entry[pseudo_key].hash_key != FREE_PSEUDO_KEY) {
	    pseudo_key = (pseudo_key + 1) % hash_table_ptr->max_entries;
	} else {
	    hash_entry[pseudo_key].hash_key = hash_key;
            hash_entry[pseudo_key].hash_addr = hash_addr;
	    hash_table_ptr->cur_entries++;
	    spin_unlock(&hash_table_ptr->hash_lock);
	    return 0;
	}
	
	loops++;
	
    } while(loops < hash_table_ptr->max_entries);
        
    spin_unlock(&hash_table_ptr->hash_lock);
    
    return -1;   
}
Пример #9
0
void add_cache(ECM_REQUEST *er){
	if(!er->csp_hash) return;

	ECMHASH *result = NULL;
	CW *cw = NULL;
#ifdef CS_CACHEEX
	bool add_new_cw=false;
#endif

	pthread_rwlock_wrlock(&cache_lock);

	//add csp_hash to cache
	result = find_hash_table(&ht_cache, &er->csp_hash, sizeof(int32_t), &compare_csp_hash);
	if(!result){
		if(cs_malloc(&result, sizeof(ECMHASH))){
			result->csp_hash = er->csp_hash;
			init_hash_table(&result->ht_cw, &result->ll_cw);
			cs_ftime(&result->first_recv_time);

			add_hash_table(&ht_cache, &result->ht_node, &ll_cache, &result->ll_node, result, &result->csp_hash, sizeof(int32_t));

		}else{
			pthread_rwlock_unlock(&cache_lock);
			cs_log("ERROR: NO added HASH to cache!!");
			return;
		}
	}

	cs_ftime(&result->upd_time);   //need to be updated at each cw! We use it for deleting this hash when no more cws arrive inside max_cache_time!


	//add cw to this csp hash
	cw = find_hash_table(&result->ht_cw, er->cw, sizeof(er->cw), &compare_cw);

	if(!cw){

		if(count_hash_table(&result->ht_cw)>=10){  //max 10 different cws stored
			pthread_rwlock_unlock(&cache_lock);
			return;
		}

		while(1){
			if(cs_malloc(&cw, sizeof(CW))){
				memcpy(cw->cw, er->cw, sizeof(er->cw));
				cw->odd_even = get_odd_even(er);
				cw->cwc_cycletime = er->cwc_cycletime;
				cw->cwc_next_cw_cycle = er->cwc_next_cw_cycle;
				cw->count= 0;
				cw->csp = 0;
				cw->cacheex = 0;
				cw->localcards=0;
				cw->proxy=0;
				cw->grp = 0;
				cw->caid = er->caid;
				cw->prid = er->prid;
				cw->srvid = er->srvid;
				cw->selected_reader=er->selected_reader;
	#ifdef CS_CACHEEX
				cw->cacheex_src=er->cacheex_src;
	#endif
				cw->pushout_client = NULL;

				while(1){
					if (pthread_rwlock_init(&cw->pushout_client_lock, NULL) == 0)
						break;

					cs_log("Error creating lock pushout_client_lock!");
					cs_sleepms(1);
				}


				add_hash_table(&result->ht_cw, &cw->ht_node, &result->ll_cw, &cw->ll_node, cw, cw->cw, sizeof(er->cw));

	#ifdef CS_CACHEEX
				add_new_cw=true;
	#endif
				break;
			}

			cs_log("ERROR: NO added CW to cache!! Re-trying...");
			cs_sleepms(1);
		}
	}

	//update if answered from csp/cacheex/local_proxy
	if(er->from_cacheex) cw->cacheex = 1;
	if(er->from_csp) cw->csp = 1;
#ifdef CS_CACHEEX
	if(!er->cacheex_src){
#endif
		if(is_localreader(er->selected_reader, er)) cw->localcards=1;
		else cw->proxy = 1;
#ifdef CS_CACHEEX
	}
#endif

	//always update group and counter
	cw->grp |= er->grp;
	cw->count++;

	//sort cw_list by counter (DESC order)
	if(cw->count>1)
		sort_list(&result->ll_cw, count_sort);

	pthread_rwlock_unlock(&cache_lock);


#ifdef CS_CACHEEX

	er->cw_cache=cw;
	cacheex_cache_push(er);


	//cacheex debug log lines and cw diff stuff
	if(check_client(er->cacheex_src)){
		if(add_new_cw){
			debug_ecm(D_CACHEEX|D_CSP, "got pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src));

			CW *cw_first = get_first_cw(result, er);

			if(er && cw_first){
			
			//compare er cw with mostly counted cached cw
			if(memcmp(er->cw, cw_first->cw, sizeof(er->cw)) != 0) {
				er->cacheex_src->cwcacheexerrcw++;
				if (er->cacheex_src->account)
					er->cacheex_src->account->cwcacheexerrcw++;

				if (((0x0200| 0x0800) & cs_dblevel)) { //avoid useless operations if debug is not enabled
					char cw1[16*3+2], cw2[16*3+2];
					cs_hexdump(0, er->cw, 16, cw1, sizeof(cw1));
					cs_hexdump(0, cw_first->cw, 16, cw2, sizeof(cw2));

					char ip1[20]="", ip2[20]="";
					if (check_client(er->cacheex_src))
						cs_strncpy(ip1, cs_inet_ntoa(er->cacheex_src->ip), sizeof(ip1));
					if (check_client(cw_first->cacheex_src))
						cs_strncpy(ip2, cs_inet_ntoa(cw_first->cacheex_src->ip), sizeof(ip2));
					else if (cw_first->selected_reader && check_client(cw_first->selected_reader->client))
						cs_strncpy(ip2, cs_inet_ntoa(cw_first->selected_reader->client->ip), sizeof(ip2));

					debug_ecm(D_CACHEEX| D_CSP, "WARNING: Different CWs %s from %s(%s)<>%s(%s): %s<>%s ", buf,
						er->from_csp ? "csp" : username(er->cacheex_src), ip1,
						check_client(cw_first->cacheex_src)?username(cw_first->cacheex_src):(cw_first->selected_reader?cw_first->selected_reader->label:"unknown/csp"), ip2,
						cw1, cw2);
				}
			}

		}
		}else
			debug_ecm(D_CACHEEX| D_CSP, "got duplicate pushed ECM %s from %s", buf, er->from_csp ? "csp" : username(er->cacheex_src));
	}

#endif
}
Пример #10
0
/*
 * This function returns cw (mostly received) in cache for er, or NULL if not found.
 * IMPORTANT:
 * 		- If found, DON'T forget to free returned ecm, because it is a copy useful to get data
 * 		- If found, and cacheex_src client of returned ecm is not NULL, and we want to access it,
 *        remember to check for its validity (client structure is still existent)
 *        E.g.: if(ecm->cacheex_src && is_valid_client(ecm->cacheex_src) && !ecm->cacheex_src->kill)
 *        We don't want make this stuff here to avoid useless cpu time if outside function we would not access to it.
 */
struct ecm_request_t *check_cache(ECM_REQUEST *er, struct s_client *cl)
{
	if(!er->csp_hash) return NULL;

	ECM_REQUEST *ecm = NULL;
	ECMHASH *result;
	CW *cw;
	uint64_t grp = cl?cl->grp:0;

	pthread_rwlock_rdlock(&cache_lock);

	result = find_hash_table(&ht_cache, &er->csp_hash, sizeof(int32_t),&compare_csp_hash);
	cw = get_first_cw(result, er);

	if(
		cw
		&&
	    (
			cw->csp    //csp have no grp!
			||
			!grp		   			     //csp client(no grp) searching for cache
			||
			(
			  grp
			  &&
			  cw->grp  //ecm group --> only when readers/ex-clients answer (e_found) it
			  && (grp & cw->grp)
			)
		 )
	){


#ifdef CS_CACHEEX

		//if preferlocalcards=2 for this ecm request, we can server ONLY cw from localcards readers until stage<3
		if(er->preferlocalcards==2 && !cw->localcards && er->stage<3){
		    pthread_rwlock_unlock(&cache_lock);
		    return NULL;
		}

		CWCHECK check_cw = get_cwcheck(er);
		if((!cw->proxy && !cw->localcards)  //cw received from ONLY cacheex/csp peers
		   && check_cw.counter>1
		   && cw->count < check_cw.counter
		   && (check_cw.mode || !er->cacheex_wait_time_expired)
		){
		    pthread_rwlock_unlock(&cache_lock);
		    return NULL;
		}
#endif


#ifdef CW_CYCLE_CHECK
		uint8_t cwc_ct = cw->cwc_cycletime > 0 ? cw->cwc_cycletime : 0;
		uint8_t cwc_ncwc = cw->cwc_next_cw_cycle < 2 ? cw->cwc_next_cw_cycle : 2;
		if(cw->got_bad_cwc)
		{
			pthread_rwlock_unlock(&cache_lock);
			return NULL;
		}
		if(checkcwcycle(cl, er, NULL, cw->cw, 0, cwc_ct, cwc_ncwc) != 0){
			cs_debug_mask(D_CWC | D_LB, "{client %s, caid %04X, srvid %04X} [check_cache] cyclecheck passed ecm in INT. cache, ecm->rc %d", (cl ? cl->account->usr : "******"), er->caid, er->srvid, ecm ? ecm->rc : -1);
		}else{
			cs_debug_mask(D_CWC, "cyclecheck [BAD CW Cycle] from Int. Cache detected.. {client %s, caid %04X, srvid %04X} [check_cache] -> skip cache answer", (cl ? cl->account->usr : "******"), er->caid, er->srvid);
			cw->got_bad_cwc = 1; // no need to check it again
			pthread_rwlock_unlock(&cache_lock);
			return NULL;
		}
#endif

		if (cs_malloc(&ecm, sizeof(ECM_REQUEST))){
			ecm->rc = E_FOUND;
			ecm->rcEx = 0;
			memcpy(ecm->cw, cw->cw, 16);
			ecm->grp = cw->grp;
			ecm->selected_reader = cw->selected_reader;
			ecm->cwc_cycletime = cw->cwc_cycletime;
			ecm->cwc_next_cw_cycle = cw->cwc_next_cw_cycle;
#ifdef CS_CACHEEX
			ecm->cacheex_src = cw->cacheex_src;
#endif
			ecm->cw_count = cw->count;
		}
	}

    pthread_rwlock_unlock(&cache_lock);
    return ecm;
}