|
|
|
@ -5,6 +5,7 @@ |
|
|
|
#include <stdio.h> |
|
|
|
#include <pcre.h> |
|
|
|
#include <glib.h> |
|
|
|
#include <time.h> |
|
|
|
|
|
|
|
#include "control_udp.h" |
|
|
|
#include "poller.h" |
|
|
|
@ -18,7 +19,9 @@ |
|
|
|
|
|
|
|
static pcre *parse_re; |
|
|
|
static pcre_extra *parse_ree; |
|
|
|
static GHashTable *cookies; |
|
|
|
static GHashTable *fresh_cookies, *stale_cookies; |
|
|
|
static GStringChunk *fresh_chunks, *stale_chunks; |
|
|
|
time_t oven_time; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -68,27 +71,33 @@ static void control_udp_incoming(int fd, void *p) { |
|
|
|
|
|
|
|
pcre_get_substring_list(buf, ovec, ret, &out); |
|
|
|
|
|
|
|
if (!cookies) |
|
|
|
cookies = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); |
|
|
|
if (!fresh_cookies) { |
|
|
|
fresh_cookies = g_hash_table_new(g_str_hash, g_str_equal); |
|
|
|
stale_cookies = g_hash_table_new(g_str_hash, g_str_equal); |
|
|
|
fresh_chunks = g_string_chunk_new(4 * 1024); |
|
|
|
stale_chunks = g_string_chunk_new(4 * 1024); |
|
|
|
time(&oven_time); |
|
|
|
} |
|
|
|
else { |
|
|
|
if (u->poller->now - oven_time >= 30) { |
|
|
|
g_hash_table_remove_all(stale_cookies); |
|
|
|
g_string_chunk_clear(stale_chunks); |
|
|
|
swap_ptrs(&stale_cookies, &fresh_cookies); |
|
|
|
swap_ptrs(&stale_chunks, &fresh_chunks); |
|
|
|
oven_time = u->poller->now; /* baked new cookies! */ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* XXX better hashing */ |
|
|
|
reply = g_hash_table_lookup(cookies, out[1]); |
|
|
|
reply = g_hash_table_lookup(fresh_cookies, out[1]); |
|
|
|
if (!reply) |
|
|
|
reply = g_hash_table_lookup(stale_cookies, out[1]); |
|
|
|
if (reply) { |
|
|
|
mylog(LOG_INFO, "Detected command from udp:" DF " as a duplicate", DP(sin)); |
|
|
|
sendto(fd, reply, strlen(reply), 0, (struct sockaddr *) &sin, sin_len); |
|
|
|
goto out; |
|
|
|
} |
|
|
|
|
|
|
|
ZERO(mh); |
|
|
|
mh.msg_name = &sin; |
|
|
|
mh.msg_namelen = sizeof(sin); |
|
|
|
mh.msg_iov = iov; |
|
|
|
mh.msg_iovlen = 2; |
|
|
|
|
|
|
|
iov[0].iov_base = (void *) out[1]; |
|
|
|
iov[0].iov_len = strlen(out[1]); |
|
|
|
iov[1].iov_base = " "; |
|
|
|
iov[1].iov_len = 1; |
|
|
|
|
|
|
|
if (out[2][0] == 'u' || out[2][0] == 'U') |
|
|
|
reply = call_update_udp(out, u->callmaster); |
|
|
|
else if (out[2][0] == 'l' || out[2][0] == 'L') |
|
|
|
@ -96,6 +105,17 @@ static void control_udp_incoming(int fd, void *p) { |
|
|
|
else if (out[9][0] == 'd' || out[9][0] == 'D') |
|
|
|
reply = call_delete_udp(out, u->callmaster); |
|
|
|
else if (out[12][0] == 'v' || out[12][0] == 'V') { |
|
|
|
ZERO(mh); |
|
|
|
mh.msg_name = &sin; |
|
|
|
mh.msg_namelen = sizeof(sin); |
|
|
|
mh.msg_iov = iov; |
|
|
|
mh.msg_iovlen = 2; |
|
|
|
|
|
|
|
iov[0].iov_base = (void *) out[1]; |
|
|
|
iov[0].iov_len = strlen(out[1]); |
|
|
|
iov[1].iov_base = " "; |
|
|
|
iov[1].iov_len = 1; |
|
|
|
|
|
|
|
if (out[13][0] == 'f' || out[13][0] == 'F') { |
|
|
|
ret = 0; |
|
|
|
if (!strcmp(out[14], "20040107")) |
|
|
|
@ -118,7 +138,9 @@ static void control_udp_incoming(int fd, void *p) { |
|
|
|
|
|
|
|
if (reply) { |
|
|
|
sendto(fd, reply, strlen(reply), 0, (struct sockaddr *) &sin, sin_len); |
|
|
|
g_hash_table_insert(cookies, strdup(out[1]), reply); /* XXX timeout entries */ |
|
|
|
g_hash_table_insert(fresh_cookies, g_string_chunk_insert(fresh_chunks, out[1]), |
|
|
|
g_string_chunk_insert(fresh_chunks, reply)); |
|
|
|
free(reply); |
|
|
|
} |
|
|
|
|
|
|
|
out: |
|
|
|
|