86 lines
1.8 KiB
C
86 lines
1.8 KiB
C
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <time.h>
|
||
|
|
||
|
#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;
|
||
|
}
|