static void ghttp_cleanup(struct s_client *client) { s_ghttp *context = (s_ghttp *)client->ghttp; if(context) { NULLFREE(context->session_id); NULLFREE(context->host_id); NULLFREE(context->fallback_id); if(context->ecm_q) { ll_destroy(context->ecm_q); } if(context->post_contexts) { ll_destroy_data(context->post_contexts); } #ifdef WITH_SSL if(context->ssl_handle) { SSL_shutdown(context->ssl_handle); SSL_free(context->ssl_handle); } #endif NULLFREE(context); } }
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); if(!cl->kill_started) { cl->kill_started = 1; } else { cs_writeunlock(&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(&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) { 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 WITH_CARDREADER == 1 if(cl->typ == 'r') { cardreader_close(rdr); } #endif 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_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; } if(cl->cascadeusers) { ll_destroy_data(cl->cascadeusers); cl->cascadeusers = NULL; } add_garbage(cl->emmcache); #ifdef MODULE_CCCAM add_garbage(cl->cc); #endif #ifdef MODULE_SERIAL add_garbage(cl->serialdata); #endif add_garbage(cl); }