store match rules per client

This commit is contained in:
hippoz 2022-12-31 17:55:32 +02:00
parent 2a07d8dd38
commit 0d5385f295
Signed by: hippoz
GPG key ID: 56C4E02A85F2FBED
3 changed files with 53 additions and 46 deletions

View file

@ -189,6 +189,7 @@ int match_rule_check(match_rule_t *rule, wire_message_t *msg, wire_context_t *ct
wire_message_body_string_t strings[MATCH_RULE_MAX_ARG];
memset(strings, 0, sizeof(strings));
/* TODO: handle failure */
TRYST(wire_collect_strings(ctx, msg, strings, MATCH_RULE_MAX_ARG));
for (int i = 0; i < MATCH_RULE_MAX_ARG; i++) {

View file

@ -36,6 +36,7 @@ int jb_server_client_add(struct jb_server *s, int fd)
s->clients[i].state = JB_CLIENT_STATE_WAIT_AUTH;
s->fds[i].fd = fd;
s->fds[i].events = POLLIN;
s->clients_count++;
return i;
}
}
@ -93,12 +94,14 @@ int jb_server_name_add(struct jb_server *s, char *name, int client_index)
return -1;
}
int jb_server_match_add(struct jb_server *s, char *match, int client_index)
int jb_server_client_match_add(struct jb_server *s, int client_index, char *match)
{
struct jb_client *c = &s->clients[client_index];
for (int i = 0; i < JB_MAX_MATCH; i++) {
if (s->matches[i].client_index < 0) {
s->matches[i].rule = match_rule_from_string(match);
s->matches[i].client_index = client_index;
if (!c->matches[i]) {
c->matches[i] = match_rule_from_string(match);
c->match_count++;
return 0;
}
}
@ -171,26 +174,28 @@ void jb_server_name_remove(struct jb_server *s, int i)
void jb_server_client_remove(struct jb_server *s, int i)
{
if (s->clients[i].fd >= 0) {
close(s->clients[i].fd);
struct jb_client *c = &s->clients[i];
if (c->fd >= 0) {
close(c->fd);
}
// TODO: slow
for (int i = 0; i < JB_MAX_MATCH; i++) {
if (s->matches[i].client_index == i) {
s->matches[i].client_index = -1;
match_rule_free(s->matches[i].rule);
s->matches[i].rule = NULL;
if (c->matches[i]) {
match_rule_free(c->matches[i]);
c->matches[i] = NULL;
}
}
jb_server_name_remove(s, s->clients[i].unique_name_index);
jb_server_name_remove(s, s->clients[i].owned_name_index);
s->clients[i].unique_name_index = -1;
s->clients[i].owned_name_index = -1;
s->clients[i].fd = -1;
s->clients[i].state = JB_CLIENT_STATE_NONE;
jb_server_name_remove(s, c->unique_name_index);
jb_server_name_remove(s, c->owned_name_index);
c->unique_name_index = -1;
c->owned_name_index = -1;
c->match_count = 0;
c->fd = -1;
c->state = JB_CLIENT_STATE_NONE;
s->fds[i].fd = -1;
s->fds[i].events = 0;
s->fds[i].revents = 0;
s->clients_count--;
}
void jb_server_client_error(struct jb_server *s, int i, const char *msg)
@ -211,11 +216,23 @@ ssize_t jb_server_client_recv(struct jb_server *s, int i, void *buf, size_t n)
int jb_server_broadcast_message(struct jb_server *s, wire_message_t *msg, wire_context_t *ctx, char *sender_unique_name)
{
for (int i = 0; i < JB_MAX_MATCH; i++) {
if (s->matches[i].rule) {
if (match_rule_check(s->matches[i].rule, msg, ctx) >= 0) {
struct jb_client *client = &s->clients[s->matches[i].client_index];
int left = s->clients_count;
for (int i = 0; i < JB_MAX_CLIENTS && left > 0; i++) {
if (s->clients[i].match_count <= 0) {
continue;
}
left--;
struct jb_client *c = &s->clients[i];
int match_left = c->match_count;
for (int i = 0; i < JB_MAX_MATCH && match_left > 0; i++) {
if (!c->matches[i]) {
continue;
}
match_left--;
if (match_rule_check(c->matches[i], msg, ctx) >= 0) {
uint8_t reply_data[4096];
memset(reply_data, 0, 4096);
wire_context_t reply_ctx = {
@ -225,7 +242,7 @@ int jb_server_broadcast_message(struct jb_server *s, wire_message_t *msg, wire_c
};
TRYST(wire_compose_unicast_reply(&reply_ctx, ctx, msg, sender_unique_name));
TRYST(send(client->fd, reply_data, reply_ctx.byte_cursor, 0));
TRYST(send(c->fd, reply_data, reply_ctx.byte_cursor, 0));
}
}
}
@ -419,7 +436,7 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data,
return -1;
}
TRYST(jb_server_match_add(s, match, i));
TRYST(jb_server_client_match_add(s, i, match));
printf("client index %d just added match rule: '%s'\n", i, match);
@ -487,17 +504,9 @@ void jb_server_free(struct jb_server *s)
{
if (!s) return;
if (s->sock_fd) close(s->sock_fd);
// names are allocated on the heap
for (int i = 0; i < JB_MAX_NAMES; i++) {
if (s->names[i].name) {
free(s->names[i].name);
}
}
// matches are allocated on the heap
for (int i = 0; i < JB_MAX_MATCH; i++) {
if (s->matches[i].rule) {
match_rule_free(s->matches[i].rule);
}
// freeing all clients will also free all matches and names
for (int i = 0; i < JB_MAX_CLIENTS; i++) {
jb_server_client_remove(s, i);
}
free(s);
}
@ -538,9 +547,13 @@ struct jb_server *jb_server_create(const char *socket_path)
s->clients[i].owned_name_index = -1;
s->clients[i].unique_name_index = -1;
s->clients[i].state = JB_CLIENT_STATE_NONE;
s->clients[i].match_count = 0;
s->fds[i].fd = -1;
s->fds[i].events = 0;
s->fds[i].revents = 0;
for (int j = 0; j < JB_MAX_MATCH; j++) {
s->clients[i].matches[j] = NULL;
}
}
for (int i = 0; i < JB_MAX_NAMES; i++) {
@ -548,11 +561,7 @@ struct jb_server *jb_server_create(const char *socket_path)
s->names[i].name = NULL;
}
s->names_count = 0;
for (int i = 0; i < JB_MAX_MATCH; i++) {
s->matches[i].client_index = -1;
s->matches[i].rule = NULL;
}
s->clients_count = 0;
s->fds[JB_MAX_CLIENTS].fd = s->sock_fd;
s->fds[JB_MAX_CLIENTS].events = POLLIN;

View file

@ -8,7 +8,7 @@
// TODO: dynamically size the arrays
#define JB_MAX_CLIENTS 256
#define JB_MAX_NAMES 512
#define JB_MAX_MATCH 512
#define JB_MAX_MATCH 12
#define JB_BACKLOG 12
enum {
@ -23,6 +23,8 @@ struct jb_client {
uint8_t state;
int16_t unique_name_index;
int16_t owned_name_index;
int8_t match_count;
match_rule_t *matches[JB_MAX_MATCH];
};
struct jb_name {
@ -30,19 +32,14 @@ struct jb_name {
int32_t client_index;
};
struct jb_match {
match_rule_t *rule;
int32_t client_index;
};
struct jb_server {
int sock_fd;
int fd_num;
int names_count;
int clients_count;
struct jb_client clients[JB_MAX_CLIENTS];
struct jb_name names[JB_MAX_NAMES];
struct pollfd fds[JB_MAX_CLIENTS + 1];
struct jb_match matches[JB_MAX_MATCH];
};