aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJose Bollo <jose.bollo@iot.bzh>2019-10-07 17:16:22 +0200
committerJose Bollo <jose.bollo@iot.bzh>2019-10-07 17:17:14 +0200
commit4c52ca4ea2c7b2d9f50fcc867d40e5b2170d4f3c (patch)
tree5f807602f19531bedb55aecd38fa002ef61f5dbd
parent2db8fa8c75a173ad49b06a97aefe16b279e5bbee (diff)
Add documentation and fixes
Documents the client API Fixes few bugs Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
-rw-r--r--compat/src/lib-compat.c12
-rw-r--r--src/cyn-server.c30
-rw-r--r--src/cyn-server.h51
-rw-r--r--src/cynagora.c416
-rw-r--r--src/cynagora.h292
-rw-r--r--src/main-cynagoradm.c2
6 files changed, 604 insertions, 199 deletions
diff --git a/compat/src/lib-compat.c b/compat/src/lib-compat.c
index 8035292..a7c1532 100644
--- a/compat/src/lib-compat.c
+++ b/compat/src/lib-compat.c
@@ -151,12 +151,12 @@ struct cynara_admin;
int cynara_admin_initialize(struct cynara_admin **pp_cynara_admin)
{
- return from_status(cynagora_open((cynagora_t**)pp_cynara_admin, cynagora_Admin, 1, 0));
+ return from_status(cynagora_create((cynagora_t**)pp_cynara_admin, cynagora_Admin, 1, 0));
}
int cynara_admin_finish(struct cynara_admin *p_cynara_admin)
{
- cynagora_close((cynagora_t*)p_cynara_admin);
+ cynagora_destroy((cynagora_t*)p_cynara_admin);
return CYNARA_API_SUCCESS;
}
@@ -413,7 +413,7 @@ int cynara_async_initialize(cynara_async **pp_cynara, const cynara_async_configu
if (p_cynara == NULL)
ret = CYNARA_API_OUT_OF_MEMORY;
else {
- ret = from_status(cynagora_open(&p_cynara->rcyn, cynagora_Check, p_conf ? p_conf->szcache : 1, 0));
+ ret = from_status(cynagora_create(&p_cynara->rcyn, cynagora_Check, p_conf ? p_conf->szcache : 1, 0));
if (ret != CYNARA_API_SUCCESS)
free(p_cynara);
else {
@@ -439,7 +439,7 @@ void cynara_async_finish(cynara_async *p_cynara)
}
}
- cynagora_close(p_cynara->rcyn);
+ cynagora_destroy(p_cynara->rcyn);
while((req = p_cynara->reqs)) {
p_cynara->reqs = req->next;
@@ -569,12 +569,12 @@ int cynara_configuration_set_cache_size(cynara_configuration *p_conf,
int cynara_initialize(cynara **pp_cynara, const cynara_configuration *p_conf)
{
- return from_status(cynagora_open((cynagora_t**)pp_cynara, cynagora_Check, p_conf ? p_conf->szcache : 1, 0));
+ return from_status(cynagora_create((cynagora_t**)pp_cynara, cynagora_Check, p_conf ? p_conf->szcache : 1, 0));
}
int cynara_finish(cynara *p_cynara)
{
- cynagora_close((cynagora_t*)p_cynara);
+ cynagora_destroy((cynagora_t*)p_cynara);
return CYNARA_API_SUCCESS;
}
diff --git a/src/cyn-server.c b/src/cyn-server.c
index 1921142..d751fda 100644
--- a/src/cyn-server.c
+++ b/src/cyn-server.c
@@ -108,6 +108,13 @@ struct cyn_server
pollitem_t check;
};
+/**
+ * Log the protocol
+ * @param cli the client handle
+ * @param c2s direction: if not 0: client to server, if 0: server to client
+ * @param count count of fields
+ * @param fields the fields
+ */
static
void
dolog(
@@ -365,12 +372,16 @@ onrequest(
/* version hand-shake */
if (!cli->version) {
- if (!ckarg(args[0], _cynagora_, 0) || count != 2 || !ckarg(args[1], "1", 0))
- goto invalid;
- putx(cli, _yes_, "1", cyn_changeid_string(), NULL);
- flushw(cli);
+ if (ckarg(args[0], _cynagora_, 0)) {
+ if (count < 2 || !ckarg(args[1], "1", 0))
+ goto invalid;
+ putx(cli, _yes_, "1", cyn_changeid_string(), NULL);
+ flushw(cli);
+ cli->version = 1;
+ return;
+ }
+ /* switch automatically to version 1 */
cli->version = 1;
- return;
}
switch(args[0][0]) {
@@ -703,7 +714,7 @@ on_agent_server_event(
on_server_event(pollitem, events, pollfd, server_Agent);
}
-/** destroy a server */
+/* see cyn-server.h */
void
cyn_server_destroy(
cyn_server_t *server
@@ -719,7 +730,7 @@ cyn_server_destroy(
}
}
-/** create a server */
+/* see cyn-server.h */
int
cyn_server_create(
cyn_server_t **server,
@@ -821,7 +832,7 @@ error:
return rc;
}
-/** stop the server */
+/* see cyn-server.h */
void
cyn_server_stop(
cyn_server_t *server,
@@ -830,7 +841,7 @@ cyn_server_stop(
server->stopped = status ?: INT_MIN;
}
-/** create a server */
+/* see cyn-server.h */
int
cyn_server_serve(
cyn_server_t *server
@@ -842,4 +853,3 @@ cyn_server_serve(
}
return server->stopped == INT_MIN ? 0 : server->stopped;
}
-
diff --git a/src/cyn-server.h b/src/cyn-server.h
index 8117724..d2c7984 100644
--- a/src/cyn-server.h
+++ b/src/cyn-server.h
@@ -23,16 +23,25 @@
typedef struct cyn_server cyn_server_t;
+/**
+ * Boolean flag telling whether the server logs or not its received commands
+ */
extern
bool
cyn_server_log;
-extern
-void
-cyn_server_destroy(
- cyn_server_t *server
-);
-
+/**
+ * Create a cynagora server
+ *
+ * @param server where to store the handler of the created server
+ * @param admin_socket_spec specification of the admin socket
+ * @param check_socket_spec specification of the check socket
+ * @param agent_socket_spec specification of the agent socket
+ *
+ * @return 0 on success or a negative -errno value
+ *
+ * @see cyn_server_destroy
+ */
extern
int
cyn_server_create(
@@ -42,12 +51,42 @@ cyn_server_create(
const char *agent_socket_spec
);
+/**
+ * Destroy a created server and release its resources
+ *
+ * @param server the handler of the server
+ *
+ * @see cyn_server_create
+ */
+extern
+void
+cyn_server_destroy(
+ cyn_server_t *server
+);
+
+/**
+ * Start the cynagora server and returns only when stopped
+ *
+ * @param server the handler of the server
+ *
+ * @return 0 on success or a negative -errno value
+ *
+ * @see cyn_server_stop
+ */
extern
int
cyn_server_serve(
cyn_server_t *server
);
+/**
+ * Stop the cynagora server
+ *
+ * @param server the handler of the server
+ * @param status the status that the function cyn_server_serve should return
+ *
+ * @see cyn_server_serve
+ */
extern
void
cyn_server_stop(
diff --git a/src/cynagora.c b/src/cynagora.c
index 1165e64..ee55dc6 100644
--- a/src/cynagora.c
+++ b/src/cynagora.c
@@ -52,9 +52,7 @@ struct asreq
struct asreq *next;
/** callback function */
- void (*callback)(
- void *closure,
- int status);
+ cynagora_async_check_cb_t *callback;
/** closure of the callback */
void *closure;
@@ -75,9 +73,6 @@ struct cynagora
/** type of link */
cynagora_type_t type;
- /** spec of the socket */
- const char *socketspec;
-
/** protocol manager object */
prot_t *prot;
@@ -96,7 +91,7 @@ struct cynagora
/** async */
struct {
/** control callback */
- cynagora_async_ctl_t controlcb;
+ cynagora_async_ctl_cb_t *controlcb;
/** closure */
void *closure;
@@ -104,12 +99,17 @@ struct cynagora
/** requests */
asreq_t *requests;
} async;
-};
-static void disconnection(cynagora_t *cynagora);
+ /** spec of the socket */
+ char socketspec[];
+};
/**
- * Flush the write buffer
+ * Flush the write buffer of the client
+ *
+ * @param cynagora the handler of the client
+ *
+ * @return 0 in case of success or a negative -errno value
*/
static
int
@@ -141,7 +141,14 @@ flushw(
/**
* Put the command made of arguments ...
* Increment the count of pending requests.
- * Return 0 in case of success or a negative number on error.
+ *
+ * @param cynagora the handler of the client
+ * @param command the command to send
+ * @param optarg an optional argument or NULL
+ * @param optkey an optional key or NULL
+ * @param optval an optional value or NULL
+ *
+ * @return 0 in case of success or a negative -errno value
*/
static
int
@@ -156,8 +163,10 @@ putxkv(
prot_t *prot;
char text[30];
+ /* retrieves the protocol handler */
prot = cynagora->prot;
for(trial = 0 ; ; trial++) {
+ /* fill the protocol handler with command and its arguments */
rc = prot_put_field(prot, command);
if (!rc && optarg)
rc = prot_put_field(prot, optarg);
@@ -183,19 +192,33 @@ putxkv(
if (!rc)
rc = prot_put_end(prot);
if (!rc) {
+ /* success ! */
/* client always flushes */
cynagora->pending++;
return flushw(cynagora);
}
+
+ /* failed to fill protocol, cancel current composition */
prot_put_cancel(prot);
+
+ /* fail if was last trial */
if (trial >= 1)
return rc;
+
+ /* try to flush the output buffer */
rc = flushw(cynagora);
if (rc)
return rc;
}
}
+/**
+ * Wait some input event
+ *
+ * @param cynagora the handler of the client
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
static
int
wait_input(
@@ -210,19 +233,28 @@ wait_input(
return rc < 0 ? -errno : 0;
}
+/**
+ * Get the next reply if any
+ *
+ * @param cynagora the handler of the client
+ *
+ * @return the count of field of the reply (can be 0)
+ * or -EAGAIN if there is no reply
+ */
static
int
get_reply(
cynagora_t *cynagora
) {
int rc;
+ uint32_t cacheid;
prot_next(cynagora->prot);
rc = prot_get(cynagora->prot, &cynagora->reply.fields);
if (rc > 0) {
if (0 == strcmp(cynagora->reply.fields[0], _clear_)) {
- cache_clear(cynagora->cache,
- rc > 1 ? (uint32_t)atol(cynagora->reply.fields[1]) : 0);
+ cacheid = rc > 1 ? (uint32_t)atol(cynagora->reply.fields[1]) : 0;
+ cache_clear(cynagora->cache, cacheid);
rc = 0;
} else {
if (0 != strcmp(cynagora->reply.fields[0], _item_))
@@ -233,6 +265,16 @@ get_reply(
return rc;
}
+/**
+ * Wait for a reply
+ *
+ * @param cynagora the handler of the client
+ * @param block
+ *
+ * @return the count of fields greater than 0 or a negative -errno value
+ * or -EAGAIN if nothing and block == 0
+ * or -EPIPE if broken link
+ */
static
int
wait_reply(
@@ -242,11 +284,13 @@ wait_reply(
int rc;
for(;;) {
- prot_next(cynagora->prot);
+ /* get the next reply if any */
rc = get_reply(cynagora);
if (rc > 0)
return rc;
+
if (rc < 0) {
+ /* wait for an answer */
rc = prot_read(cynagora->prot, cynagora->fd);
while (rc <= 0) {
if (rc == 0)
@@ -261,6 +305,13 @@ wait_reply(
}
}
+/**
+ * Read and process any input data
+ *
+ * @param cynagora the client handler
+ *
+ * @return 0 on success or a negative -errno error code
+ */
static
int
flushr(
@@ -272,6 +323,13 @@ flushr(
return rc;
}
+/**
+ * Test if the first field is "done"
+ *
+ * @param cynagora the handler of the client
+ *
+ * @return 0 if done or -ECANCELED otherwise
+ */
static
int
status_done(
@@ -280,6 +338,14 @@ status_done(
return strcmp(cynagora->reply.fields[0], _done_) ? -ECANCELED : 0;
}
+/**
+ * Translates the check/test reply to a forbiden/granted status
+ *
+ * @param cynagora the handler of the client
+ * @param expire where to store the expiration read
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
static
int
status_check(
@@ -305,6 +371,13 @@ status_check(
return rc;
}
+/**
+ * Wait for a reply
+ *
+ * @param cynagora the handler of the client
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
static
int
wait_pending_reply(
@@ -320,6 +393,14 @@ wait_pending_reply(
}
}
+/**
+ * Wait the reply "done"
+ *
+ * @param cynagora the handler of the client
+ *
+ * @return 0 in case of success or a negative -errno value
+ * -ECANCELED when received an error status
+ */
static
int
wait_done(
@@ -331,6 +412,15 @@ wait_done(
return rc;
}
+/**
+ * Calls the asynchronous control callback with operation and the given events
+ *
+ * @param cynagora the handler of the client
+ * @param op operation (see epoll_ctl)
+ * @param events the events (see epoll_ctl)
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
static
int
async(
@@ -343,6 +433,11 @@ async(
: 0;
}
+/**
+ * Disconnect the client
+ *
+ * @param cynagora the handler of the client
+ */
static
void
disconnection(
@@ -355,6 +450,13 @@ disconnection(
}
}
+/**
+ * connect the client
+ *
+ * @param cynagora the handler of the client
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
static
int
connection(
@@ -391,6 +493,13 @@ connection(
return rc;
}
+/**
+ * ensure the connection is opened
+ *
+ * @param cynagora the handler of the client
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
static
int
ensure_opened(
@@ -401,10 +510,63 @@ ensure_opened(
return cynagora->fd < 0 ? connection(cynagora) : 0;
}
-/************************************************************************************/
+/**
+ * Check or test synchronously
+ *
+ * @param cynagora
+ * @param key
+ * @param action
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
+static
+int
+check_or_test(
+ cynagora_t *cynagora,
+ const cynagora_key_t *key,
+ const char *action
+) {
+ int rc;
+ time_t expire;
+
+ /* forbids 2 queries interleaved */
+ if (cynagora->async.requests != NULL)
+ return -EINPROGRESS;
+
+ /* ensure opened */
+ rc = ensure_opened(cynagora);
+ if (rc < 0)
+ return rc;
+
+ /* ensure there is no clear cache pending */
+ flushr(cynagora);
+
+ /* check cache item */
+ rc = cache_search(cynagora->cache, key);
+ if (rc >= 0)
+ return rc;
+
+ /* send the request */
+ rc = putxkv(cynagora, action, 0, key, 0);
+ if (rc >= 0) {
+ /* get the response */
+ rc = wait_pending_reply(cynagora);
+ if (rc >= 0) {
+ rc = status_check(cynagora, &expire);
+ if (rc >= 0 && action == _check_ && cynagora->cache)
+ cache_put(cynagora->cache, key, rc, expire);
+ }
+ }
+ return rc;
+}
+
+/******************************************************************************/
+/*** PUBLIC METHODS ***/
+/******************************************************************************/
+/* see cynagora.h */
int
-cynagora_open(
+cynagora_create(
cynagora_t **prcyn,
cynagora_type_t type,
uint32_t cache_size,
@@ -415,10 +577,18 @@ cynagora_open(
/* socket spec */
switch(type) {
+ case cynagora_Admin:
+ socketspec = cyn_get_socket_admin(socketspec);
+ break;
+
+ case cynagora_Agent:
+ socketspec = cyn_get_socket_agent(socketspec);
+ break;
+
+ case cynagora_Check:
default:
- case cynagora_Check: socketspec = cyn_get_socket_check(socketspec); break;
- case cynagora_Admin: socketspec = cyn_get_socket_admin(socketspec); break;
- case cynagora_Agent: socketspec = cyn_get_socket_agent(socketspec); break;
+ socketspec = cyn_get_socket_check(socketspec);
+ break;
}
/* allocate the structure */
@@ -434,12 +604,11 @@ cynagora_open(
goto error2;
/* socket spec */
- strcpy((char*)(cynagora+1), socketspec);
+ strcpy(cynagora->socketspec, socketspec);
/* record type and weakly create cache */
- cache_create(&cynagora->cache, CACHESIZE(cache_size));
+ cache_create(&cynagora->cache, CACHESIZE(cache_size)); /* ignore errors */
cynagora->type = type;
- cynagora->socketspec = socketspec;
cynagora->async.controlcb = NULL;
cynagora->async.closure = 0;
cynagora->async.requests = NULL;
@@ -457,6 +626,7 @@ error:
return rc;
}
+/* see cynagora.h */
void
cynagora_disconnect(
cynagora_t *cynagora
@@ -464,8 +634,9 @@ cynagora_disconnect(
disconnection(cynagora);
}
+/* see cynagora.h */
void
-cynagora_close(
+cynagora_destroy(
cynagora_t *cynagora
) {
cynagora_async_setup(cynagora, NULL, NULL);
@@ -475,85 +646,33 @@ cynagora_close(
free(cynagora);
}
+/* see cynagora.h */
int
-cynagora_enter(
- cynagora_t *cynagora
+cynagora_cache_resize(
+ cynagora_t *cynagora,
+ uint32_t size
) {
- int rc;
-
- if (cynagora->type != cynagora_Admin)
- return -EPERM;
- if (cynagora->async.requests != NULL)
- return -EINPROGRESS;
- rc = ensure_opened(cynagora);
- if (rc < 0)
- return rc;
-
- rc = putxkv(cynagora, _enter_, 0, 0, 0);
- if (rc >= 0)
- rc = wait_done(cynagora);
- return rc;
+ return cache_resize(&cynagora->cache, CACHESIZE(size));
}
-int
-cynagora_leave(
- cynagora_t *cynagora,
- bool commit
+/* see cynagora.h */
+void
+cynagora_cache_clear(
+ cynagora_t *cynagora
) {
- int rc;
-
- if (cynagora->type != cynagora_Admin)
- return -EPERM;
- if (cynagora->async.requests != NULL)
- return -EINPROGRESS;
- rc = ensure_opened(cynagora);
- if (rc < 0)
- return rc;
-
- rc = putxkv(cynagora, _leave_, commit ? _commit_ : 0/*default: rollback*/, 0, 0);
- if (rc >= 0)
- rc = wait_done(cynagora);
- return rc;
+ cache_clear(cynagora->cache, 0);
}
-static
+/* see cynagora.h */
int
-check_or_test(
+cynagora_cache_check(
cynagora_t *cynagora,
- const cynagora_key_t *key,
- const char *action
+ const cynagora_key_t *key
) {
- int rc;
- time_t expire;
-
- if (cynagora->async.requests != NULL)
- return -EINPROGRESS;
- rc = ensure_opened(cynagora);
- if (rc < 0)
- return rc;
-
- /* ensure there is no clear cache pending */
- flushr(cynagora);
-
- /* check cache item */
- rc = cache_search(cynagora->cache, key);
- if (rc >= 0)
- return rc;
-
- /* send the request */
- rc = putxkv(cynagora, action, 0, key, 0);
- if (rc >= 0) {
- /* get the response */
- rc = wait_pending_reply(cynagora);
- if (rc >= 0) {
- rc = status_check(cynagora, &expire);
- if (cynagora->cache && rc >= 0)
- cache_put(cynagora->cache, key, rc, expire);
- }
- }
- return rc;
+ return cache_search(cynagora->cache, key);
}
+/* see cynagora.h */
int
cynagora_check(
cynagora_t *cynagora,
@@ -562,6 +681,7 @@ cynagora_check(
return check_or_test(cynagora, key, _check_);
}
+/* see cynagora.h */
int
cynagora_test(
cynagora_t *cynagora,
@@ -570,37 +690,12 @@ cynagora_test(
return check_or_test(cynagora, key, _test_);
}
-int
-cynagora_set(
- cynagora_t *cynagora,
- const cynagora_key_t *key,
- const cynagora_value_t *value
-) {
- int rc;
-
- if (cynagora->type != cynagora_Admin)
- return -EPERM;
- if (cynagora->async.requests != NULL)
- return -EINPROGRESS;
- rc = ensure_opened(cynagora);
- if (rc < 0)
- return rc;
-
- rc = putxkv(cynagora, _set_, 0, key, value);
- if (rc >= 0)
- rc = wait_done(cynagora);
- return rc;
-}
-
+/* see cynagora.h */
int
cynagora_get(
cynagora_t *cynagora,
const cynagora_key_t *key,
- void (*callback)(
- void *closure,
- const cynagora_key_t *key,
- const cynagora_value_t *value
- ),
+ cynagora_get_cb_t *callback,
void *closure
) {
int rc;
@@ -633,6 +728,7 @@ cynagora_get(
return rc;
}
+/* see cynagora.h */
int
cynagora_log(
cynagora_t *cynagora,
@@ -657,11 +753,10 @@ cynagora_log(
return rc < 0 ? rc : cynagora->reply.count < 2 ? 0 : !strcmp(cynagora->reply.fields[1], _on_);
}
-
+/* see cynagora.h */
int
-cynagora_drop(
- cynagora_t *cynagora,
- const cynagora_key_t *key
+cynagora_enter(
+ cynagora_t *cynagora
) {
int rc;
@@ -673,44 +768,84 @@ cynagora_drop(
if (rc < 0)
return rc;
- rc = putxkv(cynagora, _drop_, 0, key, 0);
+ rc = putxkv(cynagora, _enter_, 0, 0, 0);
if (rc >= 0)
rc = wait_done(cynagora);
return rc;
}
-/************************************************************************************/
-
+/* see cynagora.h */
int
-cynagora_cache_resize(
+cynagora_leave(
cynagora_t *cynagora,
- uint32_t size
+ int commit
) {
- return cache_resize(&cynagora->cache, CACHESIZE(size));
+ int rc;
+
+ if (cynagora->type != cynagora_Admin)
+ return -EPERM;
+ if (cynagora->async.requests != NULL)
+ return -ECANCELED;
+ rc = ensure_opened(cynagora);
+ if (rc < 0)
+ return rc;
+
+ rc = putxkv(cynagora, _leave_, commit ? _commit_ : 0/*default: rollback*/, 0, 0);
+ if (rc >= 0)
+ rc = wait_done(cynagora);
+ return rc;
}
-void
-cynagora_cache_clear(
- cynagora_t *cynagora
+/* see cynagora.h */
+int
+cynagora_set(
+ cynagora_t *cynagora,
+ const cynagora_key_t *key,
+ const cynagora_value_t *value
) {
- cache_clear(cynagora->cache, 0);
+ int rc;
+
+ if (cynagora->type != cynagora_Admin)
+ return -EPERM;
+ if (cynagora->async.requests != NULL)
+ return -ECANCELED;
+ rc = ensure_opened(cynagora);
+ if (rc < 0)
+ return rc;
+
+ rc = putxkv(cynagora, _set_, 0, key, value);
+ if (rc >= 0)
+ rc = wait_done(cynagora);
+ return rc;
}
+/* see cynagora.h */
int
-cynagora_cache_check(
+cynagora_drop(
cynagora_t *cynagora,
const cynagora_key_t *key
) {
- return cache_search(cynagora->cache, key);
-}
+ int rc;
+ if (cynagora->type != cynagora_Admin)
+ return -EPERM;
+ if (cynagora->async.requests != NULL)
+ return -ECANCELED;
+ rc = ensure_opened(cynagora);
+ if (rc < 0)
+ return rc;
-/************************************************************************************/
+ rc = putxkv(cynagora, _drop_, 0, key, 0);
+ if (rc >= 0)
+ rc = wait_done(cynagora);
+ return rc;
+}
+/* see cynagora.h */
int
cynagora_async_setup(
cynagora_t *cynagora,
- cynagora_async_ctl_t controlcb,
+ cynagora_async_ctl_cb_t *controlcb,
void *closure
) {
asreq_t *ar;
@@ -721,15 +856,19 @@ cynagora_async_setup(
ar->callback(ar->closure, -ECANCELED);
free(ar);
}
+
/* remove existing polling */
async(cynagora, EPOLL_CTL_DEL, 0);
+
/* records new data */
cynagora->async.controlcb = controlcb;
cynagora->async.closure = closure;
+
/* record to polling */
return async(cynagora, EPOLL_CTL_ADD, EPOLLIN);
}
+/* see cynagora.h */
int
cynagora_async_process(
cynagora_t *cynagora
@@ -776,14 +915,13 @@ cynagora_async_process(
}
}
+/* see cynagora.h */
int
cynagora_async_check(
cynagora_t *cynagora,
const cynagora_key_t *key,
int simple,
- void (*callback)(
- void *closure,
- int status),
+ cynagora_async_check_cb_t *callback,
void *closure
) {
int rc;
diff --git a/src/cynagora.h b/src/cynagora.h
index 3b856da..d17476c 100644
--- a/src/cynagora.h
+++ b/src/cynagora.h
@@ -26,93 +26,240 @@ typedef enum cynagora_type cynagora_type_t;
typedef struct cynagora_key cynagora_key_t;
typedef struct cynagora_value cynagora_value_t;
+/**
+ * type of the client interface
+ */
enum cynagora_type {
+ /** type for checking permissions */
cynagora_Check,
+ /** type for adminstration */
cynagora_Admin,
+ /** type for handling agents */
cynagora_Agent
};
+/**
+ * Describes a query key
+ */
struct cynagora_key {
+ /** client item of the key */
const char *client;
+ /** session item of the key */
const char *session;
+ /** user item of the key */
const char *user;
+ /** permission item of the key */
const char *permission;
};
+/**
+ * Describes the value associated to a key
+ */
struct cynagora_value {
+ /** the associated value */
const char *value;
+ /** the expiration */
time_t expire;
};
+/**
+ * Callback for enumeration of items (admin)
+ * The function is called for each entry matching the selection key
+ * with the key and the associated value for that entry
+ *
+ * @see cynagora_get
+ */
+typedef void cynagora_get_cb_t(
+ void *closure,
+ const cynagora_key_t *key,
+ const cynagora_value_t *value);
+
+/**
+ * Callback for receiving asynchronousely the replies to the queries
+ * Receives:
+ * closure: the closure given to cynagora_async_check
+ * status: 0 if forbidden
+ * 1 if granted
+ * -ECANCELED if cancelled
+ */
+typedef void cynagora_async_check_cb_t(
+ void *closure,
+ int status);
+
+/**
+ * Callback for managing the connection in an external loop
+ *
+ * That callback receives epoll_ctl operations, a file descriptor number and
+ * a mask of expected events.
+ *
+ * @see epoll_ctl
+ */
+typedef int cynagora_async_ctl_cb_t(
+ void *closure,
+ int op,
+ int fd,
+ uint32_t events);
+
+/**
+ * Create a client to the permission server cynagora
+ * The client is created but not connected. The connection is made on need.
+ *
+ * @param cynagora pointer to the handle of the opened client
+ * @param type type of the client to open
+ * @param cache_size requested cache size
+ * @param socketspec specification of the socket to connect to or NULL for
+ * using the default
+ *
+ * @return 0 in case of success and in that case *cynagora is filled
+ * a negative -errno value and *cynara is set to NULL
+ *
+ * @see cynagora_destroy, cynagora_cache_resize
+ */
extern
int
-cynagora_open(
+cynagora_create(
cynagora_t **cynagora,
cynagora_type_t type,
uint32_t cache_size,
const char *socketspec
);
+/**
+ * Destroy the client handler and release its memory
+ *
+ * @param cynagora the client handler to close
+ *
+ * @see cynagora_create
+ */
extern
void
-cynagora_disconnect(
+cynagora_destroy(
cynagora_t *cynagora
);
+/**
+ * Ask the client to disconnect from the server.
+ * The client will reconnect if needed.
+ *
+ * @param cynagora the client handler
+ */
extern
void
-cynagora_close(
+cynagora_disconnect(
cynagora_t *cynagora
);
+/**
+ * Clear the cache
+ *
+ * @param cynagora the client handler
+ *
+ * @see cynagora_cache_resize
+ */
extern
-int
-cynagora_enter(
+void
+cynagora_cache_clear(
cynagora_t *cynagora
);
+/**
+ * Resize the cache
+ *
+ * @param cynagora the client handler
+ * @param size new expected cache
+ *
+ * @return 0 on success or -ENOMEM if out of memory
+ *
+ * @see cynagora_cache_clear, cynagora_create
+ */
extern
int
-cynagora_leave(
+cynagora_cache_resize(
cynagora_t *cynagora,
- bool commit
+ uint32_t size
);
+/**
+ * Check a key against the cache
+ *
+ * @param cynagora the client handler
+ * @param key the key to check
+ *
+ * @return 0 if forbidden, 1 if authorize, -ENOENT if cache miss
+ *
+ * @see cynagora_check
+ */
extern
int
-cynagora_check(
+cynagora_cache_check(
cynagora_t *cynagora,
const cynagora_key_t *key
);
+/**
+ * Query the permission database for the key (synchronous)
+ * Allows agent resolution.
+ *
+ * @param cynagora the client handler
+ * @param key the key to check
+ *
+ * @return 0 if permission forbidden, 1 if permission granted
+ * or if error a negative -errno value
+ *
+ * @see cynagora_test, cynagora_cache_check
+ */
extern
int
-cynagora_test(
+cynagora_check(
cynagora_t *cynagora,
const cynagora_key_t *key
);
+/**
+ * Query the permission database for the key (synchronous)
+ * Avoids agent resolution.
+ *
+ * @param cynagora the client handler
+ * @param key
+ * @return
+ *
+ * @see cynagora_check
+ */
extern
int
-cynagora_set(
+cynagora_test(
cynagora_t *cynagora,
- const cynagora_key_t *key,
- const cynagora_value_t *value
+ const cynagora_key_t *key
);
+/**
+ * List any value of the permission database that matches the key (admin, synchronous)
+ *
+ * @param cynagora the client handler
+ * @param key the selection key
+ * @param callback the callback for receiving items
+ * @param closure closure of the callback
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
extern
int
cynagora_get(
cynagora_t *cynagora,
const cynagora_key_t *key,
- void (*callback)(
- void *closure,
- const cynagora_key_t *key,
- const cynagora_value_t *value
- ),
+ cynagora_get_cb_t *callback,
void *closure
);
+/**
+ * Query or set the logging of requests (admin, synchronous)
+ *
+ * @param cynagora the client handler
+ * @param on should set on
+ * @param off should set off
+ *
+ * @return 0 if not logging, 1 if logging or a negative -errno value
+ */
extern
int
cynagora_log(
@@ -121,61 +268,132 @@ cynagora_log(
int off
);
+/**
+ * Enter cancelable section for modifying database (admin, synchronous)
+ *
+ * @param cynagora the handler of the client
+ *
+ * @return 0 in case of success or a negative -errno value
+ * -EPERM if not a admin client
+ * -EINPROGRESS if already entered
+ *
+ * @see cynagora_leave, cynagora_set, cynagora_drop
+ */
extern
int
-cynagora_drop(
- cynagora_t *cynagora,
- const cynagora_key_t *key
+cynagora_enter(
+ cynagora_t *cynagora
);
+/**
+ * Leave cancelable section for modifying database (admin, synchronous)
+ *
+ * @param cynagora the handler of the client
+ * @param commit if zero, cancel the modifications in progress otherwise if
+ * not zero, commit the changes
+ *
+ * @return 0 in case of success or a negative -errno value
+ * -EPERM if not a admin client
+ * -ECANCELED if not entered
+ *
+ * @see cynagora_enter, cynagora_set, cynagora_drop
+ */
extern
-void
-cynagora_cache_clear(
- cynagora_t *cynagora
+int
+cynagora_leave(
+ cynagora_t *cynagora,
+ int commit
);
+/**
+ * Set a rule (either create or change it) (admin, synchronous)
+ * This call requires to have entered the cancelable section.
+ *
+ * @param cynagora the handler of the client
+ * @param key the key to set
+ * @param value the value to set to the key
+ *
+ * @return 0 in case of success or a negative -errno value
+ * -EPERM if not a admin client
+ * -ECANCELED if not entered
+ *
+ * @see cynagora_enter, cynagora_leave, cynagora_drop
+ */
extern
int
-cynagora_cache_check(
+cynagora_set(
cynagora_t *cynagora,
- const cynagora_key_t *key
+ const cynagora_key_t *key,
+ const cynagora_value_t *value
);
+/**
+ * Drop items matching the key selector (admin, synchronous)
+ * This call requires to have entered the cancelable section.
+ *
+ * @param cynagora the handler of the client
+ * @param key Filter of the keys to drop
+ *
+ * @return 0 in case of success or a negative -errno value
+ * -EPERM if not a admin client
+ * -ECANCELED if not entered
+ *
+ * @see cynagora_enter, cynagora_leave, cynagora_set
+ */
extern
int
-cynagora_cache_resize(
+cynagora_drop(
cynagora_t *cynagora,
- uint32_t size
+ const cynagora_key_t *key
);
-typedef int (*cynagora_async_ctl_t)(
- void *closure,
- int op,
- int fd,
- uint32_t events);
-
+/**
+ * Set the asynchronous control function
+ *
+ * @param cynagora the handler of the client
+ * @param controlcb
+ * @param closure
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
extern
int
cynagora_async_setup(
cynagora_t *cynagora,
- cynagora_async_ctl_t controlcb,
+ cynagora_async_ctl_cb_t *controlcb,
void *closure
);
+/**
+ * Process the inputs of the client
+ *
+ * @param cynagora the handler of the client
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
extern
int
cynagora_async_process(
cynagora_t *cynagora
);
+/**
+ * Check the key asynchronousely (async)
+ *
+ * @param cynagora the handler of the client
+ * @param key the key to query
+ * @param simple if zero allows agent process else if not 0 forbids it
+ * @param callback the callback to call on reply
+ * @param closure a closure for the callback
+ *
+ * @return 0 in case of success or a negative -errno value
+ */
extern
int
cynagora_async_check(
cynagora_t *cynagora,
const cynagora_key_t *key,
int simple,
- void (*callback)(
- void *closure,
- int status),
+ cynagora_async_check_cb_t *callback,
void *closure
);
diff --git a/src/main-cynagoradm.c b/src/main-cynagoradm.c
index 216dd7e..7b657c0 100644
--- a/src/main-cynagoradm.c
+++ b/src/main-cynagoradm.c
@@ -764,7 +764,7 @@ int main(int ac, char **av)
/* initialize server */
signal(SIGPIPE, SIG_IGN); /* avoid SIGPIPE! */
- rc = cynagora_open(&cynagora, cynagora_Admin, cachesize, socket);
+ rc = cynagora_create(&cynagora, cynagora_Admin, cachesize, socket);
if (rc < 0) {
fprintf(stderr, "initialization failed: %s\n", strerror(-rc));
return 1;