summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2017-04-06 13:39:48 +0200
committerPaweł Redman <pawel.redman@gmail.com>2017-04-06 13:39:48 +0200
commit18e72e3773935fa7e316ca3d32e1fa49ef58f44d (patch)
treed91006956cc8073b1b50fd30660a886459c6eb03 /src/main.c
parentda4626cb5a741a9b7861dd54f8570a00753a5d92 (diff)
Refactor large parts of the program.
The new design assures revDNS/WHOIS queries will be done exactly once, no matter how many requests the Schachtmeister gets. This commit also adds cache timeouts.
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c85
1 files changed, 78 insertions, 7 deletions
diff --git a/src/main.c b/src/main.c
index 69653c7..fc377e3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -17,9 +17,21 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "shared.h"
+#include <time.h>
int server_sockfd;
+static struct timespec time_ref;
+
+uint64_t get_time(void)
+{
+ static struct timespec now;
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ return (uint64_t)(now.tv_sec - time_ref.tv_sec) * TIME_SECOND +
+ now.tv_nsec + 1;
+}
+
static int parse_req_addr(char *begin, char *end, uint32_t *out)
{
char *p;
@@ -48,6 +60,68 @@ static int parse_req_addr(char *begin, char *end, uint32_t *out)
return 0;
}
+void handle_request(struct sockaddr_in *ret_addr, uint32_t query)
+{
+ db_entry *entry;
+ job_t *reply_job;
+ uint64_t now = get_time();
+
+ DEBUG("query %08X\n", query);
+
+ entry = db_find(query);
+ if (!entry) {
+ eprintf("handle_request: out of memory\n");
+ return;
+ }
+
+ reply_job = job_create(JOB_REPLY, entry);
+ reply_job->ipv4 = query;
+ memcpy(&reply_job->ret_addr, ret_addr, sizeof(struct sockaddr_in));
+
+ if (entry->revdns.state == DB_VALID
+ && entry->revdns.exp_time <= now) {
+ entry->revdns.state = DB_INVALID;
+ DEBUG("revDNS for %08X expired\n", query);
+ }
+
+ if (entry->whois.state == DB_VALID
+ && entry->whois.exp_time <= now) {
+ entry->whois.state = DB_INVALID;
+ DEBUG("WHOIS for %08X expired\n", query);
+ }
+
+ if (entry->revdns.state == DB_VALID &&
+ entry->whois.state == DB_VALID) {
+ job_enqueue(reply_job);
+ goto out;
+ }
+
+ if (entry->revdns.state == DB_INVALID) {
+ job_t *job;
+
+ DEBUG("revDNS cache miss for %08X\n", query);
+ job = job_create(JOB_REVDNS, entry);
+ job->ipv4 = query;
+ job_enqueue(job);
+ entry->revdns.state = DB_IN_PROGRESS;
+ }
+
+ if (entry->whois.state == DB_INVALID) {
+ job_t *job;
+
+ DEBUG("WHOIS cache miss for %08X\n", query);
+ job = job_create(JOB_WHOIS, entry);
+ job->ipv4 = query;
+ job_enqueue(job);
+ entry->whois.state = DB_IN_PROGRESS;
+ }
+
+ eli_append(&entry->waiting_jobs, reply_job, waiting_list);
+
+out:
+ pthread_mutex_unlock(&entry->mutex);
+}
+
#define NUM_WORKERS 8 // FIXME: shouldn't be hardcoded
int main(void)
@@ -57,6 +131,8 @@ int main(void)
pthread_t workers[NUM_WORKERS];
size_t i;
+ clock_gettime(CLOCK_MONOTONIC_RAW, &time_ref);
+
if (lists_load("schachts.list", 0)) {
eprintf("fatal error: couldn't load the lists\n");
goto error_lists;
@@ -88,7 +164,6 @@ int main(void)
socklen_t addrlen = sizeof(addr);
ssize_t size;
uint32_t query;
- job_t *job;
size = recvfrom(server_sockfd, buffer, sizeof(buffer), 0,
(void*)&addr, &addrlen);
@@ -111,11 +186,7 @@ int main(void)
&query))
continue;
- job = job_create();
- job->type = JOB_TEST;
- job->query = query;
- memcpy(&job->reply_to, &addr, sizeof(addr));
- job_enqueue(job);
+ handle_request(&addr, query);
}
job_quit();
@@ -123,7 +194,7 @@ int main(void)
for (i = 0; i < NUM_WORKERS; i++)
pthread_join(workers[i], NULL);
- cache_destroy();
+ db_destroy();
// todo: clear all jobs
error_recvfrom: