예제 #1
0
void cacheex_timeout(ECM_REQUEST *er)
{
	if(er->cacheex_wait_time_expired)
		return;
	er->cacheex_wait_time_expired = 1;
	if(er->rc >= E_UNHANDLED)
	{
		cs_log_dbg(D_LB, "{client %s, caid %04X, prid %06X, srvid %04X} cacheex timeout! ",
					(check_client(er->client) ? er->client->account->usr : "******"), er->caid, er->prid, er->srvid);

		// if check_cw mode=0, first try to get cw from cache without check counter!
		CWCHECK check_cw = get_cwcheck(er);
		if(!check_cw.mode)
		{
			struct ecm_request_t *ecm = NULL;
			ecm = check_cache(er, er->client);

			if(ecm) // found in cache
			{
				struct s_write_from_cache *wfc = NULL;
				if(!cs_malloc(&wfc, sizeof(struct s_write_from_cache)))
				{
					NULLFREE(ecm);
					return;
				}
				wfc->er_new = er;
				wfc->er_cache = ecm;
				if(!add_job(er->client, ACTION_ECM_ANSWER_CACHE, wfc, sizeof(struct s_write_from_cache))) // write_ecm_answer_fromcache
					{ NULLFREE(ecm); }
				return;
			}
		}

		// check if "normal" readers selected, if not send NOT FOUND!
		// cacheex1-client (having always no "normal" reader),
		// or not-cacheex-1 client with no normal readers available (or filtered by LB)
		if((er->reader_count + er->fallback_reader_count - er->cacheex_reader_count) <= 0)
		{
			if(!cfg.wait_until_ctimeout)
			{
				er->rc = E_NOTFOUND;
				er->selected_reader = NULL;
				er->rcEx = 0;
				cs_log_dbg(D_LB, "{client %s, caid %04X, prid %06X, srvid %04X} cacheex timeout: NO \"normal\" readers... not_found! ",
							(check_client(er->client) ? er->client->account->usr : "******"), er->caid, er->prid, er->srvid);

				send_dcw(er->client, er);
				return;
			}
		}
		else
		{
			if(er->stage < 2)
			{
				debug_ecm(D_TRACE, "request for %s %s", username(er->client), buf);
				request_cw_from_readers(er, 0);
			}
		}
	}
}
예제 #2
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;
}