aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mds-server.c142
-rw-r--r--src/mds-server.h11
2 files changed, 151 insertions, 2 deletions
diff --git a/src/mds-server.c b/src/mds-server.c
index d90ce6a..dd52624 100644
--- a/src/mds-server.c
+++ b/src/mds-server.c
@@ -24,6 +24,7 @@
#include <libmdsserver/mds-message.h>
#include <libmdsserver/macros.h>
#include <libmdsserver/util.h>
+#include <libmdsserver/hash-help.h>
#include <alloca.h>
#include <signal.h>
@@ -656,16 +657,62 @@ void message_received(client_t* client) /* TODO */
/* Make the client listen for messages addressed to it. */
if (intercept)
{
+ size_t size = 64; /* Atleast 25, otherwise we get into problems at ((intercept & 2)) */
+ char* buf = malloc((size + 1) * sizeof(char));
+ if (buf == NULL)
+ {
+ perror(*argv);
+ return;
+ }
+
pthread_mutex_lock(&(client->mutex));
if ((intercept & 1)) /* from payload */
{
- /* TODO */
+ char* payload = client->message.payload;
+ if (client->message.payload_size == 0) /* All messages */
+ {
+ *buf = '\0';
+ add_intercept_condition(client, buf, priority, modifying, stop);
+ }
+ else /* Filtered messages */
+ for (;;)
+ {
+ char* end = strchrnul(payload, '\n');
+ size_t len = (size_t)(end - payload);
+ if (len == 0)
+ {
+ payload++;
+ break;
+ }
+ if (len > size)
+ {
+ char* old_buf = buf;
+ buf = realloc(buf, ((size <<= 1) + 1) * sizeof(char));
+ if (buf == NULL)
+ {
+ perror(*argv);
+ free(old_buf);
+ return;
+ }
+ }
+ memcpy(buf, payload, len);
+ buf[len] = '\0';
+ add_intercept_condition(client, buf, priority, modifying, stop);
+ if (*end == '\0')
+ break;
+ payload = end + 1;
+ }
}
if ((intercept & 2)) /* "To: $(client->id)" */
{
- /* TODO */
+ snprintf(buf, size, "To: %" PRIu32 ":%" PRIu32,
+ (uint32_t)(client->id >> 32),
+ (uint32_t)(client->id >> 0));
+ add_intercept_condition(client, buf, priority, modifying, stop);
}
pthread_mutex_unlock(&(client->mutex));
+
+ free(buf);
}
@@ -701,6 +748,97 @@ void message_received(client_t* client) /* TODO */
/**
+ * Add an interception condition for a client
+ *
+ * @param client The client
+ * @param condition The header, optionally with value, to look for, or empty (not `NULL`) for all messages
+ * @param priority Interception priority
+ * @param modifying Whether the client may modify the messages
+ * @param stop Whether the condition should be removed rather than added
+ */
+void add_intercept_condition(client_t* client, char* condition, int64_t priority, int modifying, int stop)
+{
+ size_t n = client->interception_conditions_count;
+ interception_condition_t* conds = client->interception_conditions;
+ ssize_t nonmodifying = -1;
+ char* header = condition;
+ char* value;
+ size_t hash;
+ size_t i;
+
+ if ((condition = strdup(condition)) == NULL)
+ {
+ perror(*argv);
+ return;
+ }
+
+ if ((value = strchr(header, ':')) != NULL)
+ {
+ *value = '\0'; /* NUL-terminate header. */
+ value += 2; /* Skip over delimiter. */
+ }
+
+ hash = string_hash(header);
+
+ for (i = 0; i < n; i++)
+ {
+ if (conds[i].header_hash == hash)
+ if (strequals(conds[i].condition, condition))
+ {
+ if (stop)
+ {
+ memmove(conds + i, conds + i + 1, --n - i);
+ client->interception_conditions_count--;
+ conds = realloc(conds, n * sizeof(interception_condition_t));
+ if (conds == NULL)
+ perror(*argv);
+ else
+ client->interception_conditions = conds;
+ }
+ else
+ {
+ conds[i].priority = priority;
+ conds[i].modifying = modifying;
+ if (modifying && (nonmodifying >= 0))
+ {
+ interception_condition_t temp = conds[nonmodifying];
+ conds[nonmodifying] = conds[i];
+ conds[i] = temp;
+ }
+ }
+ return;
+ }
+ if ((nonmodifying < 0) && conds[i].modifying)
+ nonmodifying = (ssize_t)i;
+ }
+
+ if (stop)
+ eprint("client tried to stop intercepting messages that it does not intercept.");
+ else
+ {
+ conds = realloc(conds, (n + 1) * sizeof(interception_condition_t));
+ if (conds == NULL)
+ {
+ perror(*argv);
+ return;
+ }
+ client->interception_conditions = conds;
+ client->interception_conditions_count++;
+ conds[n].condition = condition;
+ conds[n].header_hash = hash;
+ conds[n].priority = priority;
+ conds[n].modifying = modifying;
+ if (modifying && (nonmodifying >= 0))
+ {
+ interception_condition_t temp = conds[nonmodifying];
+ conds[nonmodifying] = conds[n];
+ conds[n] = temp;
+ }
+ }
+}
+
+
+/**
* Exec into the mdsinitrc script
*
* @param args The arguments to the child process
diff --git a/src/mds-server.h b/src/mds-server.h
index c8a4ac2..3c82c42 100644
--- a/src/mds-server.h
+++ b/src/mds-server.h
@@ -128,6 +128,17 @@ void* slave_loop(void* data);
void message_received(client_t* client);
/**
+ * Add an interception condition for a client
+ *
+ * @param client The client
+ * @param condition The header, optionally with value, to look for, or empty (not `NULL`) for all messages
+ * @param priority Interception priority
+ * @param modifying Whether the client may modify the messages
+ * @param stop Whether the condition should be removed rather than added
+ */
+void add_intercept_condition(client_t* client, char* condition, int64_t priority, int modifying, int stop);
+
+/**
* Exec into the mdsinitrc script
*
* @param args The arguments to the child process