diff options
Diffstat (limited to '')
-rw-r--r-- | src/mds-server/interceptors.c | 376 |
1 files changed, 185 insertions, 191 deletions
diff --git a/src/mds-server/interceptors.c b/src/mds-server/interceptors.c index fccb0fa..a39e0d6 100644 --- a/src/mds-server/interceptors.c +++ b/src/mds-server/interceptors.c @@ -38,28 +38,26 @@ * @param client The intercepting client * @param index The index of the condition */ -__attribute__((nonnull)) -static void remove_intercept_condition(client_t* client, size_t index) +static void __attribute__((nonnull)) +remove_intercept_condition(client_t *client, size_t index) { - interception_condition_t* conds = client->interception_conditions; - size_t n = client->interception_conditions_count; - - /* Remove the condition from the list. */ - free(conds[index].condition); - memmove(conds + index, conds + index + 1, --n - index); - client->interception_conditions_count--; - - /* Shrink the list. */ - if (client->interception_conditions_count == 0) - { - free(conds); - client->interception_conditions = NULL; - } - else - if (xrealloc(conds, n, interception_condition_t)) - xperror(*argv); - else - client->interception_conditions = conds; + interception_condition_t *conds = client->interception_conditions; + size_t n = client->interception_conditions_count; + + /* Remove the condition from the list. */ + free(conds[index].condition); + memmove(conds + index, conds + index + 1, --n - index); + client->interception_conditions_count--; + + /* Shrink the list. */ + if (!client->interception_conditions_count) { + free(conds); + client->interception_conditions = NULL; + } else if (xrealloc(conds, n, interception_condition_t)) { + xperror(*argv); + } else { + client->interception_conditions = conds; + } } @@ -72,106 +70,100 @@ static void remove_intercept_condition(client_t* client, size_t index) * @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) +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* colon = NULL; - char* value; - size_t hash; - size_t i; - - /* Split header and value apart. */ - if ((value = strchr(header, ':')) != NULL) - { - *value = '\0'; /* NUL-terminate header. */ - colon = value; /* End of header. */ - value += 2; /* Skip over delimiter. */ - } - - /* Calcuate header hash (comparison optimisation) */ - hash = string_hash(header); - /* Undo header–value splitting. */ - if (colon != NULL) - *colon = ':'; - - /* Remove of update condition of already registered, - also look for non-modifying condition to swap position - with for optimisation. */ - for (i = 0; i < n; i++) - { - if ((conds[i].header_hash != hash) || !strequals(conds[i].condition, condition)) - { - /* Look for the first non-modifying, this is a part of the - optimisation where we put all modifying conditions at the - beginning. */ - if ((nonmodifying < 0) && conds[i].modifying) - nonmodifying = (ssize_t)i; - continue; + size_t n = client->interception_conditions_count; + interception_condition_t *conds = client->interception_conditions; + ssize_t nonmodifying = -1; + char *header = condition; + char *colon = NULL; + char *value; + size_t hash, i; + interception_condition_t temp; + + /* Split header and value apart. */ + if ((value = strchr(header, ':'))) { + *value = '\0'; /* NUL-terminate header. */ + colon = value; /* End of header. */ + value += 2; /* Skip over delimiter. */ } - - if (stop) - remove_intercept_condition(client, i); - else - { - /* Update parameters. */ - conds[i].priority = priority; - conds[i].modifying = modifying; - - if (modifying && (nonmodifying >= 0)) - { - /* Optimisation: put conditions that are modifying - at the beginning. When a client is intercepting - we most know if any satisfying condition is - modifying. With this optimisation the first - satisfying condition will tell us if there is - any satisfying condition that is modifying. */ - interception_condition_t temp = conds[nonmodifying]; - conds[nonmodifying] = conds[i]; - conds[i] = temp; - } + + /* Calcuate header hash (comparison optimisation) */ + hash = string_hash(header); + /* Undo header–value splitting. */ + if (colon) + *colon = ':'; + + /* Remove of update condition of already registered, + also look for non-modifying condition to swap position + with for optimisation. */ + for (i = 0; i < n; i++) { + if ((conds[i].header_hash != hash) || !strequals(conds[i].condition, condition)) { + /* Look for the first non-modifying, this is a part of the + optimisation where we put all modifying conditions at the + beginning. */ + if (nonmodifying < 0 && conds[i].modifying) + nonmodifying = (ssize_t)i; + continue; + } + + if (stop) { + remove_intercept_condition(client, i); + } else { + /* Update parameters. */ + conds[i].priority = priority; + conds[i].modifying = modifying; + + if (modifying && nonmodifying >= 0) { + /* Optimisation: put conditions that are modifying + at the beginning. When a client is intercepting + we most know if any satisfying condition is + modifying. With this optimisation the first + satisfying condition will tell us if there is + any satisfying condition that is modifying. */ + temp = conds[nonmodifying]; + conds[nonmodifying] = conds[i]; + conds[i] = temp; + } + } + return; } - return; - } - - if (stop) - eprint("client tried to stop intercepting messages that it does not intercept."); - else - { - /* Duplicate condition string. */ - fail_if (xstrdup_nn(condition, condition)); - - /* Grow the interception condition list. */ - fail_if (xrealloc(conds, n + 1, interception_condition_t)); - client->interception_conditions = conds; - /* Store condition. */ - 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)) - { - /* Optimisation: put conditions that are modifying - at the beginning. When a client is intercepting - we most know if any satisfying condition is - modifying. With this optimisation the first - satisfying condition will tell us if there is - any satisfying condition that is modifying. */ - interception_condition_t temp = conds[nonmodifying]; - conds[nonmodifying] = conds[n]; - conds[n] = temp; + + if (stop) { + eprint("client tried to stop intercepting messages that it does not intercept."); + } else { + /* Duplicate condition string. */ + fail_if (xstrdup_nn(condition, condition)); + + /* Grow the interception condition list. */ + fail_if (xrealloc(conds, n + 1, interception_condition_t)); + client->interception_conditions = conds; + /* Store condition. */ + 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) { + /* Optimisation: put conditions that are modifying + at the beginning. When a client is intercepting + we most know if any satisfying condition is + modifying. With this optimisation the first + satisfying condition will tell us if there is + any satisfying condition that is modifying. */ + temp = conds[nonmodifying]; + conds[nonmodifying] = conds[n]; + conds[n] = temp; + } } - } - return; - fail: - xperror(*argv); - free(condition); - return; + return; +fail: + xperror(*argv); + free(condition); + return; } @@ -185,18 +177,20 @@ void add_intercept_condition(client_t* client, char* condition, int64_t priority * @param count The number of accepted patterns * @return Evaluates to true if and only if a matching pattern was found */ -int is_condition_matching(interception_condition_t* cond, size_t* hashes, - char** keys, char** headers, size_t count) +int +is_condition_matching(interception_condition_t *cond, size_t *hashes, + char **keys, char **headers, size_t count) { - size_t i; - for (i = 0; i < count; i++) - if (*(cond->condition) == '\0') - return 1; - else if ((cond->header_hash == hashes[i]) && - (strequals(cond->condition, keys[i]) || - strequals(cond->condition, headers[i]))) - return 1; - return 0; + size_t i; + for (i = 0; i < count; i++) { + if (*cond->condition == '\0') + return 1; + else if ((cond->header_hash == hashes[i]) && + (strequals(cond->condition, keys[i]) || + strequals(cond->condition, headers[i]))) + return 1; + } + return 0; } @@ -211,33 +205,34 @@ int is_condition_matching(interception_condition_t* cond, size_t* hashes, * @param interception_out Storage slot for found interception * @return -1 on error, otherwise: evalutes to true iff a matching condition was found */ -int find_matching_condition(client_t* client, size_t* hashes, char** keys, char** headers, - size_t count, queued_interception_t* interception_out) +int +find_matching_condition(client_t *client, size_t *hashes, char **keys, char **headers, + size_t count, queued_interception_t *interception_out) { - pthread_mutex_t mutex = client->mutex; - interception_condition_t* conds = client->interception_conditions; - size_t n = 0, i; - - fail_if ((errno = pthread_mutex_lock(&(mutex)))); - - /* Look for a matching condition. */ - if (client->open) - n = client->interception_conditions_count; - for (i = 0; i < n; i++) - if (is_condition_matching(conds + i, hashes, keys, headers, count)) - { - /* Report matching condition. */ - interception_out->client = client; - interception_out->priority = conds[i].priority; - interception_out->modifying = conds[i].modifying; - break; - } - - pthread_mutex_unlock(&(mutex)); - - return i < n; - fail: - return -1; + pthread_mutex_t mutex = client->mutex; + interception_condition_t *conds = client->interception_conditions; + size_t n = 0, i; + + fail_if ((errno = pthread_mutex_lock(&(mutex)))); + + /* Look for a matching condition. */ + if (client->open) + n = client->interception_conditions_count; + for (i = 0; i < n; i++) { + if (is_condition_matching(conds + i, hashes, keys, headers, count)) { + /* Report matching condition. */ + interception_out->client = client; + interception_out->priority = conds[i].priority; + interception_out->modifying = conds[i].modifying; + break; + } + } + + pthread_mutex_unlock(&mutex); + + return i < n; +fail: + return -1; } @@ -252,44 +247,43 @@ int find_matching_condition(client_t* client, size_t* hashes, char** keys, char* * @param interceptions_count_out Slot at where to store the number of found interceptors * @return The found interceptors, `NULL` on error */ -queued_interception_t* get_interceptors(client_t* sender, size_t* hashes, char** keys, char** headers, - size_t count, size_t* interceptions_count_out) +queued_interception_t * +get_interceptors(client_t *sender, size_t *hashes, char **keys, char **headers, + size_t count, size_t *interceptions_count_out) { - queued_interception_t* interceptions = NULL; - size_t interceptions_count = 0, n = 0; - ssize_t node; - int saved_errno; - - /* Count clients. */ - foreach_linked_list_node (client_list, node) - n++; - - /* Allocate interceptor list. */ - fail_if (xmalloc(interceptions, n, queued_interception_t)); - - /* Search clients. */ - foreach_linked_list_node (client_list, node) - { - client_t* client = (client_t*)(void*)(client_list.values[node]); - - /* Look for and list a matching condition. */ - if (client->open && (client != sender)) - { - int r = find_matching_condition(client, hashes, keys, headers, count, - interceptions + interceptions_count); - fail_if (r == -1); - if (r) - /* List client of there was a matching condition. */ - interceptions_count++; + queued_interception_t *interceptions = NULL; + size_t interceptions_count = 0, n = 0; + ssize_t node; + int saved_errno, r; + client_t *client; + + /* Count clients. */ + foreach_linked_list_node (client_list, node) + n++; + + /* Allocate interceptor list. */ + fail_if (xmalloc(interceptions, n, queued_interception_t)); + + /* Search clients. */ + foreach_linked_list_node (client_list, node) { + client = (void *)(client_list.values[node]); + + /* Look for and list a matching condition. */ + if (client->open && (client != sender)) { + r = find_matching_condition(client, hashes, keys, headers, count, + interceptions + interceptions_count); + fail_if (r == -1); + if (r) + /* List client of there was a matching condition. */ + interceptions_count++; + } } - } - - *interceptions_count_out = interceptions_count; - return interceptions; - - fail: - saved_errno = errno; - free(interceptions); - return errno = saved_errno, NULL; -} + *interceptions_count_out = interceptions_count; + return interceptions; + +fail: + saved_errno = errno; + free(interceptions); + return errno = saved_errno, NULL; +} |