#include #include #include #include #include "gamelist.h" #include "logging.h" #define BUCKET_NUM 127 static struct list_head *bucket; static unsigned int hash_entry(struct game_entry *entry) { unsigned int hash = 0x12345678; hash = ((hash << 5) ^ (hash >> 27)) ^ ((entry->ip >> 0) & 0xFF); hash = ((hash << 5) ^ (hash >> 27)) ^ ((entry->ip >> 8) & 0xFF); hash = ((hash << 5) ^ (hash >> 27)) ^ ((entry->ip >> 16) & 0xFF); hash = ((hash << 5) ^ (hash >> 27)) ^ ((entry->ip >> 24) & 0xFF); hash = ((hash << 5) ^ (hash >> 27)) ^ ((entry->port1 >> 0) & 0xFF); hash = ((hash << 5) ^ (hash >> 27)) ^ ((entry->port1 >> 8) & 0xFF); return hash % BUCKET_NUM; } static int compare_entry(struct game_entry *a, struct game_entry *b) { return (a->gameid == b->gameid && a->ip == b->ip && a->port1 == b->port1 && a->port2 == b->port2); } int gamelist_add(struct game_entry *entry) { unsigned int hash = hash_entry(entry); struct game_entry *search; list_for_each_entry(search, &bucket[hash], list) { if (compare_entry(search, entry)) { search->modtime = time(NULL); return 0; } } entry->modtime = time(NULL); list_add_tail(&entry->list, &bucket[hash]); return 0; } int gamelist_gc_and_dump(int (*callback)(struct game_entry *entry), int timeout) { long now = time(NULL); int i; for (i = 0; i < BUCKET_NUM; i++) { struct game_entry *entry, *tmp; list_for_each_entry_safe(entry, tmp, &bucket[i], list) { if (entry->modtime + timeout >= now) { callback(entry); } else { list_del(&entry->list); free(entry); } } } return 0; } int gamelist_init() { bucket = malloc(sizeof(struct list_head) * BUCKET_NUM); if (bucket == NULL) { log_print(LOG_ERROR, "scan_init(): out of memory"); return -1; } int i; for (i = 0; i < BUCKET_NUM; i++) INIT_LIST_HEAD(&bucket[i]); return 0; }