void proto_expectation_cleanup(struct proto_expectation *e) { if (!e) return; debug_expectation("Cleaning up expectation %p", e); while (e->head) { struct proto_expectation_stack *es = e->head; e->head = es->next; if (es->fields[POM_DIR_FWD]) ptype_cleanup(es->fields[POM_DIR_FWD]); if (es->fields[POM_DIR_REV]) ptype_cleanup(es->fields[POM_DIR_REV]); free(es); } if (e->session) conntrack_session_refcount_dec(e->session); timer_cleanup(e->expiry); free(e); }
int conntrack_session_bind(struct conntrack_entry *ce, struct conntrack_session *session) { if (ce->session) { pomlog(POMLOG_WARN "Warning, session already exists when trying to bind another session. TODO: implement merging"); conntrack_session_refcount_dec(ce->session); } conntrack_session_refcount_inc(session); ce->session = session; return POM_OK; }
void proto_expectation_cleanup(struct proto_expectation *e) { if (!e) return; if (e->flags & PROTO_EXPECTATION_FLAG_QUEUED) proto_expectation_remove(e); debug_expectation("Cleaning up expectation %p", e); while (e->head) { struct proto_expectation_stack *es = e->head; e->head = es->next; if (es->fields[POM_DIR_FWD]) ptype_cleanup(es->fields[POM_DIR_FWD]); if (es->fields[POM_DIR_REV]) ptype_cleanup(es->fields[POM_DIR_REV]); free(es); } if (e->priv && e->proto->info->ct_info->cleanup_handler) { if (e->proto->info->ct_info->cleanup_handler(e->priv) != POM_OK) pomlog(POMLOG_WARN "Unable to free the conntrack priv of the proto_expectation"); } if (e->session) conntrack_session_refcount_dec(e->session); if (e->expiry) timer_cleanup(e->expiry); if (e->callback_priv && e->callback_priv_cleanup) e->callback_priv_cleanup(e->callback_priv); free(e); }
int conntrack_cleanup(struct conntrack_tables *ct, uint32_t hash, struct conntrack_entry *ce) { // Remove the conntrack from the conntrack table pom_mutex_lock(&ct->locks[hash]); // Try to find the conntrack in the list struct conntrack_list *lst = NULL; for (lst = ct->table[hash]; lst && lst->ce != ce; lst = lst->next); if (!lst) { pom_mutex_unlock(&ct->locks[hash]); pomlog(POMLOG_ERR "Trying to cleanup a non existing conntrack : %p", ce); return POM_OK; } conntrack_lock(ce); if (ce->refcount) { debug_conntrack(POMLOG_ERR "Conntrack %p is still being referenced : %u !", ce, ce->refcount); conntrack_delayed_cleanup(ce, 1, core_get_clock_last()); conntrack_unlock(ce); pom_mutex_unlock(&ct->locks[hash]); return POM_OK; } if (lst->prev) lst->prev->next = lst->next; else ct->table[hash] = lst->next; if (lst->next) lst->next->prev = lst->prev; free(lst); pom_mutex_unlock(&ct->locks[hash]); if (ce->cleanup_timer && ce->cleanup_timer != (void *) -1) { conntrack_timer_cleanup(ce->cleanup_timer); ce->cleanup_timer = (void *) -1; // Mark that the conntrack is being cleaned up } // Once the conntrack is removed from the hash table, it will not be referenced ever again conntrack_unlock(ce); if (ce->parent) { debug_conntrack("Cleaning up conntrack %p, with parent %p", ce, ce->parent->ce); } else { debug_conntrack("Cleaning up conntrack %p, with no parent", ce); } if (ce->parent) { // Remove the child from the parent // Make sure the parent still exists uint32_t hash = ce->parent->hash; pom_mutex_lock(&ce->parent->ct->locks[hash]); for (lst = ce->parent->ct->table[hash]; lst && lst->ce != ce->parent->ce; lst = lst->next); if (lst) { conntrack_lock(ce->parent->ce); struct conntrack_node_list *tmp = ce->parent->ce->children; for (; tmp && tmp->ce != ce; tmp = tmp->next); if (tmp) { if (tmp->prev) tmp->prev->next = tmp->next; else ce->parent->ce->children = tmp->next; if (tmp->next) tmp->next->prev = tmp->prev; free(tmp); } else { pomlog(POMLOG_WARN "Conntrack %s not found in parent's %s children list", ce, ce->parent->ce); } if (!ce->parent->ce->children) // Parent has no child anymore, clean it up after some time conntrack_delayed_cleanup(ce->parent->ce, CONNTRACK_CHILDLESS_TIMEOUT, core_get_clock_last()); conntrack_unlock(ce->parent->ce); } else { debug_conntrack("Parent conntrack %p not found while cleaning child %p !", ce->parent->ce, ce); } pom_mutex_unlock(&ce->parent->ct->locks[hash]); free(ce->parent); } if (ce->session) conntrack_session_refcount_dec(ce->session); // Cleanup private stuff from the conntrack if (ce->priv && ce->proto->info->ct_info->cleanup_handler) { if (ce->proto->info->ct_info->cleanup_handler(ce->priv) != POM_OK) pomlog(POMLOG_WARN "Unable to free the private memory of a conntrack"); } // Cleanup the priv_list struct conntrack_priv_list *priv_lst = ce->priv_list; while (priv_lst) { if (priv_lst->cleanup) { if (priv_lst->cleanup(priv_lst->obj, priv_lst->priv) != POM_OK) pomlog(POMLOG_WARN "Error while cleaning up private objects in conntrack_entry"); } ce->priv_list = priv_lst->next; free(priv_lst); priv_lst = ce->priv_list; } // Cleanup the children while (ce->children) { struct conntrack_node_list *child = ce->children; ce->children = child->next; if (conntrack_cleanup(child->ct, child->hash, child->ce) != POM_OK) return POM_ERR; free(child); } if (ce->fwd_value) ptype_cleanup(ce->fwd_value); if (ce->rev_value) ptype_cleanup(ce->rev_value); pthread_mutex_destroy(&ce->lock); registry_perf_dec(ce->proto->perf_conn_cur, 1); free(ce); return POM_OK; }