예제 #1
0
void free_client(struct s_client *cl)
{
    if (!cl)
        return;
    struct s_reader *rdr = cl->reader;

    // Remove client from client list. kill_thread also removes this client, so here just if client exits itself...
    struct s_client *prev, *cl2;
    cs_writelock(&clientlist_lock);
    cl->kill = 1;
    for (prev = first_client, cl2 = first_client->next;
            prev->next != NULL;
            prev = prev->next, cl2 = cl2->next)
    {
        if (cl == cl2)
            break;
    }
    if (cl == cl2)
        prev->next = cl2->next; // Remove client from list
    int32_t bucket = (uintptr_t)cl / 16 % CS_CLIENT_HASHBUCKETS;
    // Remove client from hashed list
    if (first_client_hashed[bucket] == cl) {
        first_client_hashed[bucket] = cl->nexthashed;
    } else {
        for (prev = first_client_hashed[bucket], cl2 = first_client_hashed[bucket]->nexthashed;
                prev->nexthashed != NULL;
                prev = prev->nexthashed, cl2 = cl2->nexthashed)
        {
            if (cl == cl2)
                break;
        }
        if (cl == cl2)
            prev->nexthashed = cl2->nexthashed;
    }
    cs_writeunlock(&clientlist_lock);

    // Clean reader. The cleaned structures should be only used by the reader thread, so we should be save without waiting
    if (rdr) {
        remove_reader_from_ecm(rdr);
        remove_reader_from_active(rdr);
        if(rdr->ph.cleanup)
            rdr->ph.cleanup(cl);
        if (cl->typ == 'r')
            cardreader_close(rdr);
        if (cl->typ == 'p')
            network_tcp_connection_close(rdr, "cleanup");
        cl->reader = NULL;
    }

    // Clean client specific data
    if (cl->typ == 'c') {
        cs_statistics(cl);
        cl->last_caid = 0xFFFF;
        cl->last_srvid = 0xFFFF;
        cs_statistics(cl);
        cs_sleepms(500); //just wait a bit that really really nobody is accessing client data
        struct s_module *module = get_module(cl);
        if (module->cleanup)
            module->cleanup(cl);
    }

    // Close network socket if not already cleaned by previous cleanup functions
    if (cl->pfd)
        close(cl->pfd);

    // Clean all remaining structures
    free_joblist(cl);

    cleanup_ecmtasks(cl);
    add_garbage(cl->emmcache);
#ifdef MODULE_CCCAM
    add_garbage(cl->cc);
#endif
#ifdef MODULE_SERIAL
    add_garbage(cl->serialdata);
#endif
    add_garbage(cl);
}
예제 #2
0
파일: oscam-client.c 프로젝트: FFTEAM/oscam
void free_client(struct s_client *cl)
{
	if(!cl)
		{ return; }
	struct s_reader *rdr = cl->reader;

	// Remove client from client list. kill_thread also removes this client, so here just if client exits itself...
	struct s_client *prev, *cl2;
	cs_writelock(__func__, &clientlist_lock);
	if(!cl->kill_started)
	{
		cl->kill_started = 1;
	}
	else
	{
		cs_writeunlock(__func__, &clientlist_lock);
		cs_log("[free_client] ERROR: free already started!");
		return;
	}
	cl->kill = 1;
	for(prev = first_client, cl2 = first_client->next;
			prev->next != NULL;
			prev = prev->next, cl2 = cl2->next)
	{
		if(cl == cl2)
			{ break; }
	}
	if(cl == cl2)
		{ prev->next = cl2->next; } // Remove client from list
	int32_t bucket = (uintptr_t)cl / 16 % CS_CLIENT_HASHBUCKETS;
	// Remove client from hashed list
	if(first_client_hashed[bucket] == cl)
	{
		first_client_hashed[bucket] = cl->nexthashed;
	}
	else
	{
		for(prev = first_client_hashed[bucket], cl2 = first_client_hashed[bucket]->nexthashed;
				prev->nexthashed != NULL;
				prev = prev->nexthashed, cl2 = cl2->nexthashed)
		{
			if(cl == cl2)
				{ break; }
		}
		if(cl == cl2)
			{ prev->nexthashed = cl2->nexthashed; }
	}
	cs_writeunlock(__func__, &clientlist_lock);

	cleanup_ecmtasks(cl);

	// Clean reader. The cleaned structures should be only used by the reader thread, so we should be save without waiting
	if(rdr)
	{
		ll_destroy_data(&rdr->emmstat);
		remove_reader_from_active(rdr);

		cs_sleepms(1000); //just wait a bit that really really nobody is accessing client data

		if(rdr->ph.cleanup)
			{ rdr->ph.cleanup(cl); }
		if(cl->typ == 'r')
			{ cardreader_close(rdr); }
		if(cl->typ == 'p')
			{ network_tcp_connection_close(rdr, "cleanup"); }
		cl->reader = NULL;
	}

	// Clean client specific data
	if(cl->typ == 'c')
	{
		cs_statistics(cl);
		cl->last_caid = NO_CAID_VALUE;
		cl->last_provid = NO_PROVID_VALUE;
		cl->last_srvid = NO_SRVID_VALUE;
		cs_statistics(cl);

		cs_sleepms(1000); //just wait a bit that really really nobody is accessing client data
	}

	struct s_module *module = get_module(cl);
	if(module->cleanup)
		{ module->cleanup(cl); }

	// Close network socket if not already cleaned by previous cleanup functions
	if(cl->pfd)
		{ close(cl->pfd); }

	// Clean all remaining structures
	free_joblist(cl);
	NULLFREE(cl->work_mbuf);

	if(cl->ecmtask)
	{
		add_garbage(cl->ecmtask);
		cl->ecmtask = NULL;
	}

	ll_destroy_data(&cl->cascadeusers);

	ftab_clear(&cl->ftab);
	ftab_clear(&cl->fchid);
	tuntab_clear(&cl->ttab);
	caidtab_clear(&cl->ctab);

    NULLFREE(cl->cltab.aclass);
 	NULLFREE(cl->cltab.bclass);

	NULLFREE(cl->cw_rass);
	ll_destroy_data(&cl->ra_buf);
	NULLFREE(cl->aes_keys);

#ifdef MODULE_CCCAM
	add_garbage(cl->cc);
#endif
#ifdef MODULE_SERIAL
	add_garbage(cl->serialdata);
#endif
	add_garbage(cl);
}