From d75a0902bc4e31ce830084b9a7173d0c922eb435 Mon Sep 17 00:00:00 2001 From: Jose Bollo Date: Wed, 16 Oct 2019 10:59:40 +0200 Subject: Instanciate checks It prepares the requests with identifiers. This avoid a fault when a pending agent ask had its client disconnecting. Signed-off-by: Jose Bollo --- src/cyn-server.c | 108 ++++++++++++++++++++++++++++++++++------------ src/cynagora-protocol.txt | 39 +++++++++++------ 2 files changed, 106 insertions(+), 41 deletions(-) diff --git a/src/cyn-server.c b/src/cyn-server.c index 97a44d1..b3aa3b3 100644 --- a/src/cyn-server.c +++ b/src/cyn-server.c @@ -49,6 +49,7 @@ typedef struct client client_t; typedef struct agent agent_t; typedef struct ask ask_t; +typedef struct check check_t; #define MAX_PUTX_ITEMS 15 @@ -87,8 +88,8 @@ struct client /** enter/leave status, record if enter is pending */ unsigned entering: 1; - /** indicate if some check were made */ - unsigned checked: 1; + /** indicate if some caching were made by the client */ + unsigned caching: 1; /** polling callback */ pollitem_t pollitem; @@ -98,6 +99,9 @@ struct client /** last askid */ uint32_t askid; + + /** list of pending checks */ + check_t *checks; }; /** structure for pending asks */ @@ -113,6 +117,19 @@ struct ask uint32_t id; }; +/** structure for pending checks */ +struct check +{ + /** pointer to the next check */ + check_t *next; + + /** the client if still valid */ + client_t *client; + + /** is check? otherwise it is test */ + bool ischeck; +}; + /** structure for servers */ struct cyn_server { @@ -333,18 +350,17 @@ exp2get( /** callback of checking */ static void -testcheckcb( - void *closure, +replycheck( + client_t *cli, const data_value_t *value, bool ischeck ) { - client_t *cli = closure; char text[30]; const char *etxt, *vtxt; if (!value) { vtxt = _no_; - etxt = NULL; + etxt = "-"; } else { if (!strcmp(value->value, ALLOW)) vtxt = _yes_; @@ -352,6 +368,8 @@ testcheckcb( vtxt = _no_; else vtxt = _done_; + if (value->expire >= 0) + cli->caching = 1; etxt = exp2check(value->expire, text, sizeof text); } putx(cli, vtxt, etxt, NULL); @@ -365,20 +383,54 @@ checkcb( void *closure, const data_value_t *value ) { - testcheckcb(closure, value, true); + check_t *check = closure; + check_t **pc; + client_t *cli; + + cli = check->client; + if (cli) { + pc = &cli->checks; + while (*pc) + if (*pc != check) + pc = &(*pc)->next; + else { + *pc = check->next; + break; + } + replycheck(cli, value, check->ischeck); + } + free(check); } -/** callback of testing */ +/** initiate the check */ static void -testcb( - void *closure, - const data_value_t *value +makecheck( + client_t *cli, + unsigned count, + const char *args[], + bool ischeck ) { - testcheckcb(closure, value, false); + data_key_t key; + check_t *check; + + check = malloc(sizeof *check); + if (!check) + replycheck(cli, NULL, ischeck); + else { + check->ischeck = ischeck; + check->client = cli; + check->next = cli->checks; + cli->checks = check; + + key.client = args[1]; + key.session = args[2]; + key.user = args[3]; + key.permission = args[4]; + (ischeck ? cyn_check_async : cyn_test_async)(checkcb, check, &key); + } } - /** callback of getting list of entries */ static void @@ -531,12 +583,7 @@ onrequest( break; case 'c': /* check */ if (ckarg(args[0], _check_, 1) && count == 5) { - cli->checked = 1; - key.client = args[1]; - key.session = args[2]; - key.user = args[3]; - key.permission = args[4]; - cyn_check_async(checkcb, cli, &key); + makecheck(cli, count, args, true); return; } break; @@ -639,12 +686,7 @@ onrequest( break; case 't': /* test */ if (ckarg(args[0], _test_, 1) && count == 5) { - cli->checked = 1; - key.client = args[1]; - key.session = args[2]; - key.user = args[3]; - key.permission = args[4]; - cyn_test_async(testcb, cli, &key); + makecheck(cli, count, args, false); return; } break; @@ -662,8 +704,8 @@ onchange( void *closure ) { client_t *cli = closure; - if (cli->checked) { - cli->checked = 0; + if (cli->caching) { + cli->caching = 0; putx(cli, _clear_, cyn_changeid_string(), NULL); flushw(cli); } @@ -677,11 +719,20 @@ destroy_client( bool closefds ) { ask_t *ask; + check_t *check; data_value_t value; /* remove observers */ cyn_on_change_remove(onchange, cli); + /* clean of checks */ + check = cli->checks; + cli->checks = NULL; + while (check != NULL) { + check->client = NULL; + check = check->next; + } + /* close protocol */ if (closefds) close(cli->pollitem.fd); @@ -782,12 +833,13 @@ create_client( cli->invalid = 0; /* not invalid */ cli->entered = 0; /* not entered */ cli->entering = 0; /* not entering */ - cli->checked = 0; /* no check made */ + cli->caching = 0; /* no caching made */ cli->pollitem.handler = on_client_event; cli->pollitem.closure = cli; cli->pollitem.fd = fd; cli->asks = NULL; cli->askid = 0; + cli->checks = NULL; return 0; error3: prot_destroy(cli->prot); diff --git a/src/cynagora-protocol.txt b/src/cynagora-protocol.txt index ebebd4e..10668ca 100644 --- a/src/cynagora-protocol.txt +++ b/src/cynagora-protocol.txt @@ -10,27 +10,40 @@ invalidate cache: s->c clear CACHEID -test a permission: +### test a permission - c->s test CLIENT SESSION USER PERMISSION - s->c (done|yes|no) [EXPIRE] +synopsis: -check a permission: + c->s test CLIENT SESSION USER PERMISSION + s->c (done|yes|no) [EXPIRE] - c->s check CLIENT SESSION USER PERMISSION - s->c (yes|no) [EXPIRE] -enter critical (admin) - c->s enter - s->c done +### check a permission -leave critical (admin) +synopsis: - c->s leave [commit|rollback] - s->c done|error ... + c->s check CLIENT SESSION USER PERMISSION + s->c (yes|no) [EXPIRE] + + +### enter critical (admin) + +synopsis: + + c->s enter + s->c done + +### leave critical (admin) + +synopsis: + + c->s leave [commit|rollback] + s->c done|error ... + +### erase (admin) -erase (admin): +synopsis: c->s drop CLIENT SESSION USER PERMISSION s->c done|error ... -- cgit 1.2.3-korg