/* Copyright (C) 1998,2001 Free Software Foundation, Inc. This file is part of GNU Inetutils. GNU Inetutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Inetutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Inetutils; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include typedef struct request_table table_t; struct request_table { table_t *next, *prev; CTL_MSG request; time_t time; }; static table_t *table; static void table_delete (table_t *ptr) { table_t *t; if ((t = ptr->prev) != NULL) t->next = ptr->next; else table = ptr->next; if ((t = ptr->next) != NULL) t->prev = ptr->prev; free (ptr); } /* Look in the table for an invitation that matches given criteria. Linear search: premature optimisation is the root of all Evil) */ static CTL_MSG * lookup_request (CTL_MSG *request, int (*comp)(table_t *, CTL_MSG *, time_t *)) { table_t *ptr; time_t now; time (&now); if (debug) print_request ("lookup_request", request); for (ptr = table; ptr; ptr = ptr->next) { if (debug) print_request ("comparing against: ", &ptr->request); if ((ptr->time - now) > max_request_ttl) { /* the entry is too old */ if (debug) print_request ("deleting expired entry", &ptr->request); table_delete (ptr); } else { if (comp (ptr, request, &now) == 0) { if (debug) print_request ("found", &ptr->request); return &ptr->request; } } } if (debug) syslog (LOG_DEBUG, "not found"); return NULL; } static int fuzzy_comp (table_t *ptr, CTL_MSG *request, time_t *unused) { (void)unused; if (ptr->request.type == LEAVE_INVITE && strcmp(request->l_name, ptr->request.r_name) == 0 && strcmp(request->r_name, ptr->request.l_name) == 0) return 0; return 1; } /* Look in the table for an invitation that matches the current request looking for an invitation */ CTL_MSG * find_match (CTL_MSG *request) { return lookup_request (request, fuzzy_comp); } static int exact_comp (table_t *ptr, CTL_MSG *request, time_t *now) { if (request->type == ptr->request.type && request->pid == ptr->request.pid && strcmp(request->r_name, ptr->request.r_name) == 0 && strcmp(request->l_name, ptr->request.l_name) == 0) { ptr->time = *now; return 0; } return 1; } /* Look for an identical request, as opposed to a complementary one as find_match does */ CTL_MSG * find_request (CTL_MSG *request) { return lookup_request (request, exact_comp); } #define MAX_ID 16000 /* Generate a unique non-zero sequence number */ int new_id () { static int current_id = 0; current_id = (current_id + 1) % MAX_ID; /* 0 is reserved, helps to pick up bugs */ if (current_id == 0) current_id = 1; return current_id; } int insert_table (CTL_MSG *request, CTL_RESPONSE *response) { table_t *ptr; ptr = malloc (sizeof *ptr); if (!ptr) { syslog (LOG_CRIT, "out of memory"); exit (1); } request->id_num = new_id (); if (debug) print_request ("insert_table", request); response->id_num = htonl (request->id_num); time (&ptr->time); ptr->request = *request; ptr->prev = NULL; ptr->next = table; table = ptr; return 0; } /* Delete the invitation with id 'id_num' */ int delete_invite (unsigned long id_num) { table_t *ptr; for (ptr = table; ptr; ptr = ptr->next) if (ptr->request.id_num == id_num) { table_delete (ptr); return SUCCESS; } return NOT_HERE; }