diff --git a/GNUmakefile b/GNUmakefile
index d9cefa5..f713ce2 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -141,6 +141,7 @@ libuhub_SOURCES := \
src/util/log.c \
src/util/memory.c \
src/util/misc.c \
+ src/util/timeout.c \
src/core/netevent.c \
src/network/connection.c \
src/network/network.c \
diff --git a/src/util/timeout.c b/src/util/timeout.c
new file mode 100644
index 0000000..58bfad5
--- /dev/null
+++ b/src/util/timeout.c
@@ -0,0 +1,121 @@
+/*
+ * uhub - A tiny ADC p2p connection hub
+ * Copyright (C) 2007-2009, Jan Vidar Krey
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along wtimeout_evtith this program. If not, see .
+ *
+ */
+
+#include "uhub.h"
+#include "util/timeout.h"
+
+void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr)
+{
+ t->callback = cb;
+ t->ptr = ptr;
+ t->prev = 0;
+ t->next = 0;
+}
+
+void timeout_evt_reset(struct timeout_evt* t)
+{
+ t->prev = 0;
+ t->next = 0;
+}
+
+int timeout_evt_is_scheduled(struct timeout_evt* t)
+{
+ return !!t->prev;
+}
+
+void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max)
+{
+ t->last = now;
+ t->max = max;
+ t->events = hub_malloc_zero(max * sizeof(struct timeout_evt*));
+}
+
+void timeout_queue_shutdown(struct timeout_queue* t)
+{
+ hub_free(t->events);
+ t->events = 0;
+ t->max = 0;
+}
+
+size_t timeout_queue_process(struct timeout_queue* t, time_t now)
+{
+ size_t pos;
+ size_t events = 0;
+ struct timeout_evt* evt = 0;
+ for (pos = t->last; pos < now; pos++)
+ {
+ while ((evt = t->events[pos % t->max]))
+ {
+ timeout_queue_remove(t, evt);
+ timeout_evt_reset(evt);
+ evt->callback(evt);
+ events++;
+ }
+ }
+ t->last = now;
+ return events;
+}
+
+void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
+{
+ struct timeout_evt* first;
+ size_t pos = ((t->last + seconds) % t->max);
+ evt->timestamp = t->last + seconds;
+ evt->next = 0;
+
+ first = t->events[pos];
+
+ if (!first)
+ {
+ t->events[pos] = evt;
+ evt->prev = evt;
+ }
+ else
+ {
+ evt->prev = first->prev;
+ first->prev = evt;
+ }
+}
+
+void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt)
+{
+ size_t pos = (evt->timestamp % t->max);
+ struct timeout_evt* first = t->events[pos];
+
+ if (first == evt)
+ {
+ first->next->prev = first->prev;
+ t->events[pos] = first->next;
+ }
+ else
+ {
+ evt->prev->next = evt->next;
+ if (evt->next)
+ evt->next->prev = evt->prev;
+ else
+ first->prev = evt->prev;
+ }
+}
+
+void timeout_queue_reschedule(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
+{
+ if (timeout_evt_is_scheduled(evt))
+ timeout_queue_remove(t, evt);
+ timeout_queue_insert(t, evt, seconds);
+}
\ No newline at end of file
diff --git a/src/util/timeout.h b/src/util/timeout.h
new file mode 100644
index 0000000..b86e222
--- /dev/null
+++ b/src/util/timeout.h
@@ -0,0 +1,56 @@
+/*
+ * uhub - A tiny ADC p2p connection hub
+ * Copyright (C) 2007-2009, Jan Vidar Krey
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A 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 this program. If not, see .
+ *
+ */
+
+#ifndef HAVE_UHUB_TIMEOUT_HANDLER_H
+#define HAVE_UHUB_TIMEOUT_HANDLER_H
+
+struct timeout_evt;
+struct timeout_queue;
+
+typedef void (*timeout_evt_cb)(struct timeout_evt*);
+
+struct timeout_evt
+{
+ time_t timestamp;
+ timeout_evt_cb callback;
+ void* ptr;
+ struct timeout_evt* prev;
+ struct timeout_evt* next;
+};
+
+void timeout_evt_initialize(struct timeout_evt*, timeout_evt_cb, void* ptr);
+void timeout_evt_reset(struct timeout_evt*);
+int timeout_evt_is_scheduled(struct timeout_evt*);
+
+
+struct timeout_queue
+{
+ time_t last;
+ size_t max;
+ struct timeout_evt** events;
+};
+
+void timeout_queue_initialize(struct timeout_queue*, time_t now, size_t max);
+void timeout_queue_shutdown(struct timeout_queue*);
+size_t timeout_queue_process(struct timeout_queue*, time_t now);
+void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t seconds);
+void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*);
+void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds);
+
+#endif /* HAVE_UHUB_TIMEOUT_HANDLER_H */