diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/include/skalibs/sassclient.h | 44 | ||||
| -rw-r--r-- | src/include/skalibs/sassserver.h | 29 | ||||
| -rw-r--r-- | src/include/skalibs/unixonacid.h | 2 | ||||
| -rw-r--r-- | src/libunixonacid/sassclient-internal.h | 22 | ||||
| -rw-r--r-- | src/libunixonacid/sassclient_ack.c | 24 | ||||
| -rw-r--r-- | src/libunixonacid/sassclient_cancel.c | 39 | ||||
| -rw-r--r-- | src/libunixonacid/sassclient_cancel_internal.c | 21 | ||||
| -rw-r--r-- | src/libunixonacid/sassclient_end.c | 20 | ||||
| -rw-r--r-- | src/libunixonacid/sassclient_send.c | 11 | ||||
| -rw-r--r-- | src/libunixonacid/sassclient_sendv.c | 63 | ||||
| -rw-r--r-- | src/libunixonacid/sassclient_start.c | 36 | ||||
| -rw-r--r-- | src/libunixonacid/sassclient_update.c | 58 | ||||
| -rw-r--r-- | src/libunixonacid/sassserver.c | 234 |
13 files changed, 603 insertions, 0 deletions
diff --git a/src/include/skalibs/sassclient.h b/src/include/skalibs/sassclient.h new file mode 100644 index 0000000..b932414 --- /dev/null +++ b/src/include/skalibs/sassclient.h @@ -0,0 +1,44 @@ +/* ISC license. */ + +#ifndef SKALIBS_SASSCLIENT_H +#define SKALIBS_SASSCLIENT_H + +#include <pthread.h> + +#include <skalibs/tai.h> +#include <skalibs/textclient.h> +#include <skalibs/gensetdyn.h> +#include <skalibs/genqdyn.h> + +typedef struct sassclient_s sassclient, *sassclient_ref ; +struct sassclient_s +{ + textclient connection ; + gensetdyn store ; /* sassclient_data */ + genqdyn results ; /* char id[4] + char status[4] */ + pthread_mutex_t connection_mutex ; + pthread_mutex_t results_mutex ; +} ; +#define SASSCLIENT_ZERO { .connection = TEXTCLIENT_ZERO, .store = GENSETDYN_ZERO, .results = GENQDYN_ZERO } + +typedef int sassclient_cb_func (char const *, size_t, void *) ; +typedef sassclient_cb_func *sassclient_cb_func_ref ; + +extern int sassclient_start (sassclient *, char const *const *, char const *, char const *, tain const *, tain *) ; +#define sassclient_start_g(a, argv, banner1, banner2, deadline) sassclient_start(a, argv, banner1, banner2, (deadline), &STAMP) +extern void sassclient_end (sassclient *) ; + +#define sassclient_fd(a) textclient_fd(&(a)->connection) +extern int sassclient_update (sassclient *) ; +extern int sassclient_ack (sassclient *, uint32_t *, int *) ; + +extern int sassclient_send (sassclient *, uint32_t *, uint32_t, uint32_t, char const *, size_t, sassclient_cb_func_ref, void *, tain const *, tain *) ; +#define sassclient_send_g(a, id, timeout, opcode, s, len, cb, data, deadline) sassclient_send(a, id, timeout, opcode, s, len, cb, data, (deadline), &STAMP) + +extern int sassclient_sendv (sassclient *, uint32_t *, uint32_t, uint32_t, struct iovec const *, unsigned int, sassclient_cb_func_ref, void *, tain const *, tain *) ; +#define sassclient_sendv_g(a, id, timeout, opcode, v, n, cb, data, deadline) sassclient_sendv(a, id, timeout, opcode, v, n, cb, data, (deadline), &STAMP) + +extern int sassclient_cancel (sassclient *, uint32_t, tain const *, tain *) ; +#define sassclient_cancel_g(a, id, deadline) sassclient_cancel(a, id, (deadline), &STAMP) + +#endif diff --git a/src/include/skalibs/sassserver.h b/src/include/skalibs/sassserver.h new file mode 100644 index 0000000..fcd1286 --- /dev/null +++ b/src/include/skalibs/sassserver.h @@ -0,0 +1,29 @@ +/* ISC license. */ + +#ifndef SKALIBS_SASSSERVER_H +#define SKALIBS_SASSSERVER_H + +#include <sys/uio.h> +#include <stdint.h> + +#include <skalibs/tai.h> +#include <skalibs/iopause.h> + +typedef void *sassserver_send_func (uint32_t, uint32_t, char const *, size_t) ; +typedef sassserver_send_func *sassserver_send_func_ref ; + +typedef void sassserver_cancel_func (void *) ; +typedef sassserver_cancel_func *sassserver_cancel_func_ref ; + +extern void sassserver_init (char const *, char const *, sassserver_send_func_ref, sassserver_cancel_func_ref, tain const *, tain *stamp) ; +#define sassserver_init_g(banner1, banner2, deadline) sassserver_init(banner1, banner2, (deadline), &STAMP) +extern unsigned int sassserver_prepare_iopause (iopause_fd *, tain *) ; +extern void sassserver_timeout (void) ; +extern int sassserver_event (iopause_fd const *) ; +extern void *sassserver_data (uint32_t) ; + +extern void sassserver_async_failure (uint32_t, int) ; +extern void sassserver_async_success (uint32_t, char const *, size_t) ; +extern void sassserver_async_successv (uint32_t, struct iovec const *, unsigned int) ; + +#endif diff --git a/src/include/skalibs/unixonacid.h b/src/include/skalibs/unixonacid.h index d9f952c..1cba96a 100644 --- a/src/include/skalibs/unixonacid.h +++ b/src/include/skalibs/unixonacid.h @@ -12,5 +12,7 @@ #include <skalibs/unixconnection.h> #include <skalibs/kolbak.h> #include <skalibs/skaclient.h> +#include <skalibs/sassclient.h> +#include <skalibs/sassserver.h> #endif diff --git a/src/libunixonacid/sassclient-internal.h b/src/libunixonacid/sassclient-internal.h new file mode 100644 index 0000000..5ddf0f4 --- /dev/null +++ b/src/libunixonacid/sassclient-internal.h @@ -0,0 +1,22 @@ +/* ISC license. */ + +#ifndef SKALIBS_SASSCLIENT_INTERNAL_H +#define SKALIBS_SASSCLIENT_INTERNAL_H + +#include <stddef.h> +#include <stdint.h> + +#include <skalibs/tai.h> +#include <skalibs/sassclient.h> + +typedef struct sassclient_data_s sassclient_data, *sassclient_data_ref ; +struct sassclient_data_s +{ + void *data ; + sassclient_cb_func_ref cb ; +} ; + +extern int sassclient_cancel_internal (sassclient *, uint32_t, tain const *, tain *) ; +#define asyncnss_cancel_internal_g(a, id, deadline) sassclient_cancel_internal(a, id, (deadline), &STAMP) + +#endif diff --git a/src/libunixonacid/sassclient_ack.c b/src/libunixonacid/sassclient_ack.c new file mode 100644 index 0000000..4fd765f --- /dev/null +++ b/src/libunixonacid/sassclient_ack.c @@ -0,0 +1,24 @@ +/* ISC license. */ + +#include <errno.h> +#include <pthread.h> + +#include <skalibs/uint32.h> +#include <skalibs/genqdyn.h> +#include <skalibs/sassclient.h> + +int sassclient_ack (sassclient *a, uint32_t *id, int *status) +{ + uint32_t x ; + char const *s ; + int e = pthread_mutex_lock(&a->results_mutex) ; + if (e) return (errno = e, -1) ; + if (!genqdyn_n(&a->results)) { pthread_mutex_unlock(&a->results_mutex) ; return 0 ; } + s = GENQDYN_PEEK(char const, &a->results) ; + uint32_unpack_big(s, id) ; + uint32_unpack_big(s + 4, &x) ; + genqdyn_pop(&a->results) ; + pthread_mutex_unlock(&a->results_mutex) ; + *status = x ; + return 1 ; +} diff --git a/src/libunixonacid/sassclient_cancel.c b/src/libunixonacid/sassclient_cancel.c new file mode 100644 index 0000000..bc4273e --- /dev/null +++ b/src/libunixonacid/sassclient_cancel.c @@ -0,0 +1,39 @@ +/* ISC license. */ + +#include <stdint.h> +#include <errno.h> +#include <time.h> +#include <pthread.h> + +#include <skalibs/uint32.h> +#include <skalibs/tai.h> +#include <skalibs/textclient.h> +#include <skalibs/gensetdyn.h> +#include <skalibs/sassclient.h> +#include "sassclient-internal.h" + +int sassclient_cancel (sassclient *a, uint32_t id, tain const *deadline, tain *stamp) +{ + int e ; + + { + struct timespec ts ; + tain diff ; + tain_sub(&diff, deadline, stamp) ; + if (!timespec_from_tain_relative(&ts, &diff)) return 0 ; + e = pthread_mutex_timedlock(&a->connection_mutex, &ts) ; +// e = pthread_mutex_clocklock(&a->connection_mutex, CLOCK_MONOTONIC, &ts) ; + if (e) return (errno = e, 0) ; + } + + e = sassclient_cancel_internal(a, id, deadline, stamp) ; + if (e) goto err ; + gensetdyn_delete(&a->store, id) ; + pthread_mutex_unlock(&a->connection_mutex) ; + return 1 ; + + err: + pthread_mutex_unlock(&a->connection_mutex) ; + errno = e ; + return 0 ; +} diff --git a/src/libunixonacid/sassclient_cancel_internal.c b/src/libunixonacid/sassclient_cancel_internal.c new file mode 100644 index 0000000..d9fbd5d --- /dev/null +++ b/src/libunixonacid/sassclient_cancel_internal.c @@ -0,0 +1,21 @@ +/* ISC license. */ + +#include <sys/uio.h> +#include <stdint.h> +#include <errno.h> + +#include <skalibs/uint32.h> +#include <skalibs/textclient.h> + +#include "sassclient-internal.h" + +int asyncnss_cancel_internal (sassclient *a, uint32_t id, tain const *deadline, tain *stamp) +{ + struct iovec answer ; + char pack[5] = "-" ; + + uint32_pack_big(pack + 1, id) ; + if (!textclient_exchange(&a->connection, pack, 5, &answer, deadline, stamp)) return errno ; + if (answer.iov_len != 1) return EPROTO ; + return *(uint8_t *)answer.iov_base ; +} diff --git a/src/libunixonacid/sassclient_end.c b/src/libunixonacid/sassclient_end.c new file mode 100644 index 0000000..3e8b106 --- /dev/null +++ b/src/libunixonacid/sassclient_end.c @@ -0,0 +1,20 @@ +/* ISC license. */ + +#include <pthread.h> + +#include <skalibs/textclient.h> +#include <skalibs/gensetdyn.h> +#include <skalibs/genqdyn.h> +#include <skalibs/sassclient.h> + +void sassclient_end (sassclient *a) +{ + static sassclient const zero = SASSCLIENT_ZERO ; + if (textclient_fd(&a->connection) == -1) return ; + textclient_end(&a->connection) ; + gensetdyn_free(&a->store) ; + genqdyn_free(&a->results) ; + pthread_mutex_destroy(&a->connection_mutex) ; + pthread_mutex_destroy(&a->results_mutex) ; + *a = zero ; +} diff --git a/src/libunixonacid/sassclient_send.c b/src/libunixonacid/sassclient_send.c new file mode 100644 index 0000000..9ede61a --- /dev/null +++ b/src/libunixonacid/sassclient_send.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include <sys/uio.h> + +#include <skalibs/sassclient.h> + +int sassclient_send (sassclient *a, uint32_t *id, uint32_t timeout, uint32_t opcode, char const *s, size_t len, sassclient_cb_func_ref cb, void *data, tain const *deadline, tain *stamp) +{ + struct iovec v = { .iov_base = (char *)s, .iov_len = len } ; + return sassclient_sendv(a, id, timeout, opcode, &v, 1, cb, data, deadline, stamp) ; +} diff --git a/src/libunixonacid/sassclient_sendv.c b/src/libunixonacid/sassclient_sendv.c new file mode 100644 index 0000000..ef38679 --- /dev/null +++ b/src/libunixonacid/sassclient_sendv.c @@ -0,0 +1,63 @@ +/* ISC license. */ + +#include <sys/uio.h> +#include <stdint.h> +#include <errno.h> +#include <time.h> +#include <limits.h> +#include <pthread.h> + +#include <skalibs/uint32.h> +#include <skalibs/tai.h> +#include <skalibs/siovec.h> +#include <skalibs/gensetdyn.h> +#include <skalibs/textclient.h> +#include <skalibs/sassclient.h> +#include "sassclient-internal.h" + +int sassclient_sendv (sassclient *a, uint32_t *cid, uint32_t timeout, uint32_t opcode, struct iovec const *vv, unsigned int n, sassclient_cb_func_ref cb, void *data, tain const *deadline, tain *stamp) +{ + size_t len = siovec_len(vv, n) ; + uint32_t id ; + int e ; + struct iovec answer ; + sassclient_data *p ; + char pack[17] = "+" ; + struct iovec v[1 + n] ; + if (len + 11 > UINT32_MAX) return (errno = ENAMETOOLONG, 0) ; + + { + struct timespec ts ; + tain diff ; + tain_sub(&diff, deadline, stamp) ; + if (!timespec_from_tain_relative(&ts, &diff)) return 0 ; + e = pthread_mutex_timedlock(&a->connection_mutex, &ts) ; +// e = pthread_mutex_clocklock(&a->connection_mutex, CLOCK_MONOTONIC, &ts) ; + if (e) return (errno = e, 0) ; + } + + if (!gensetdyn_new(&a->store, &id)) goto err ; + v[0].iov_base = pack ; + v[0].iov_len = 17 ; + for (unsigned int i = 0 ; i < n ; i++) v[i+1] = vv[i] ; + uint32_pack_big(pack + 1, id) ; + uint32_pack_big(pack + 5, timeout) ; + uint32_pack_big(pack + 9, opcode) ; + uint32_pack_big(pack + 13, len) ; + if (!textclient_exchangev(&a->connection, v, 1 + n, &answer, deadline, stamp)) { e = errno ; goto err0 ; } + if (answer.iov_len == 1) { e = *(unsigned char *)answer.iov_base ; goto err0 ; } + if (answer.iov_len != 5 || *(unsigned char *)answer.iov_base) { e = EPROTO ; goto err0 ; } + p = GENSETDYN_P(sassclient_data, &a->store, id) ; + p->cb = cb ; + p->data = data ; + pthread_mutex_unlock(&a->connection_mutex) ; + *cid = id ; + return 1 ; + + err0: + gensetdyn_delete(&a->store, id) ; + errno = e ; + err: + pthread_mutex_unlock(&a->connection_mutex) ; + return 0 ; +} diff --git a/src/libunixonacid/sassclient_start.c b/src/libunixonacid/sassclient_start.c new file mode 100644 index 0000000..73ad732 --- /dev/null +++ b/src/libunixonacid/sassclient_start.c @@ -0,0 +1,36 @@ +/* ISC license. */ + +#include <string.h> +#include <errno.h> +#include <pthread.h> + +#include <skalibs/posixplz.h> +#include <skalibs/textclient.h> +#include <skalibs/gensetdyn.h> +#include <skalibs/genqdyn.h> +#include <skalibs/sassclient.h> +#include "sassclient-internal.h" + +int sassclient_start (sassclient *a, char const *const *argv, char const *banner1, char const *banner2, tain const *deadline, tain *stamp) +{ + int e ; + if (sassclient_fd(a) >= 0) return (errno = EBUSY, 0) ; + e = pthread_mutex_init(&a->connection_mutex, 0) ; + if (e) goto err ; + e = pthread_mutex_init(&a->results_mutex, 0) ; + if (e) goto err0 ; + if (!textclient_startf(&a->connection, argv, (char const *const *)environ, TEXTCLIENT_OPTION_WAITPID, banner1, strlen(banner1), banner2, strlen(banner2), deadline, stamp)) + goto err1 ; + gensetdyn_init(&a->store, sizeof(sassclient_data), 8, 3, 8) ; + genqdyn_init(&a->results, 8, 1, 10) ; + return 1 ; + + err1: + e = errno ; + pthread_mutex_destroy(&a->results_mutex) ; + err0: + pthread_mutex_destroy(&a->connection_mutex) ; + err: + errno = e ; + return 0 ; +} diff --git a/src/libunixonacid/sassclient_update.c b/src/libunixonacid/sassclient_update.c new file mode 100644 index 0000000..01a0427 --- /dev/null +++ b/src/libunixonacid/sassclient_update.c @@ -0,0 +1,58 @@ +/* ISC license. */ + +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <pthread.h> + +#include <skalibs/uint32.h> +#include <skalibs/textclient.h> +#include <skalibs/gensetdyn.h> +#include <skalibs/genqdyn.h> +#include <skalibs/sassclient.h> +#include "sassclient-internal.h" + +#include <skalibs/posixishard.h> + +static int sassclient_msghandler (struct iovec const *v, void *aux) +{ + sassclient *a = aux ; + char const *s = v->iov_base ; + int e ; + sassclient_data *p ; + uint32_t id ; + char res[8] ; + if (v->iov_len < 8) return (errno = EPROTO, 0) ; + uint32_unpack_big(s, &id) ; + memcpy(res, s, 4) ; s += 4 ; + p = GENSETDYN_P(sassclient_data, &a->store, id) ; + if (memcmp(s, "\0\0\0", 4)) + { + if (v->iov_len != 8) return (errno = EPROTO, 0) ; + memcpy(res + 4, s, 4) ; + } + else + { + e = (*p->cb)(s + 8, v->iov_len - 8, p->data) ; + uint32_pack_big(res + 4, e) ; + } + e = pthread_mutex_lock(&a->results_mutex) ; + if (e) return (errno = e, 0) ; + if (!genqdyn_push(&a->results, res)) + { + pthread_mutex_unlock(&a->results_mutex) ; + return 0 ; + } + pthread_mutex_unlock(&a->results_mutex) ; + if (!gensetdyn_delete(&a->store, id)) return 0 ; + return 1 ; +} + +int sassclient_update (sassclient *a) +{ + int e = pthread_mutex_lock(&a->connection_mutex) ; + if (e) return (errno = e, -1) ; + e = textclient_update(&a->connection, &sassclient_msghandler, a) ; + pthread_mutex_unlock(&a->connection_mutex) ; + return e < 0 ? -1 : !!e ; +} diff --git a/src/libunixonacid/sassserver.c b/src/libunixonacid/sassserver.c new file mode 100644 index 0000000..7ca3ad7 --- /dev/null +++ b/src/libunixonacid/sassserver.c @@ -0,0 +1,234 @@ +/* ISC license. */ + +#include <sys/uio.h> +#include <string.h> +#include <stdint.h> +#include <errno.h> + +#include <skalibs/uint32.h> +#include <skalibs/error.h> +#include <skalibs/strerr.h> +#include <skalibs/tai.h> +#include <skalibs/iopause.h> +#include <skalibs/gensetdyn.h> +#include <skalibs/avltree.h> +#include <skalibs/textmessage.h> +#include <skalibs/textclient.h> +#include <skalibs/sassserver.h> + +typedef struct sassserver_query_s sassserver_query, sassserver_query_ref ; +struct sassserver_query_s +{ + uint32_t id ; + tain deadline ; + void *data ; +} ; + +static sassserver_send_func_ref sassserver_sendf ; +static sassserver_cancel_func_ref sassserver_cancelf ; + +static gensetdyn sassserver_queries = GENSETDYN_INIT(sassserver_query, 8, 3, 8) ; +#define SASSSERVER_QUERY(i) GENSETDYN_P(sassserver_query, &sassserver_queries, (i)) + +void *sassserver_data (uint32_t handle) +{ + return SASSSERVER_QUERY(handle)->data ; +} + +static void *sassserver_deadline_dtok (uint32_t d, void *aux) +{ + return &GENSETDYN_P(sassserver_query, (gensetdyn *)aux, d)->deadline ; +} + +static int sassserver_deadline_cmp (void const *a, void const *b, void *aux) +{ + tain const *aa = a ; + tain const *bb = b ; + (void)aux ; + return tain_less(aa, bb) ? -1 : tain_less(bb, aa) ; +} + +static avltree sassserver_by_deadline = AVLTREE_INIT(8, 3, 8, &sassserver_deadline_dtok, &sassserver_deadline_cmp, &sassserver_queries) ; + +static void *sassserver_id_dtok (uint32_t d, void *aux) +{ + return &GENSETDYN_P(sassserver_query, (gensetdyn *)aux, d)->id ; +} + +static int sassserver_id_cmp (void const *a, void const *b, void *aux) +{ + uint32_t const *aa = a ; + uint32_t const *bb = b ; + (void)aux ; + return *aa < *bb ? -1 : *aa > *bb ; +} + +static avltree sassserver_by_id = AVLTREE_INIT(8, 3, 8, &sassserver_id_dtok, &sassserver_id_cmp, &sassserver_queries) ; + +static void sassserver_sync_answer (int e) +{ + char pack[4] ; + uint32_pack_big(pack, (uint32_t)e) ; + if (!textmessage_put(textmessage_sender_1, pack, 4)) + strerr_diefu1sys(111, "textmessage_put") ; +} + +static void sassserver_remove (uint32_t handle) +{ + sassserver_query *p = SASSSERVER_QUERY(handle) ; + avltree_delete(&sassserver_by_deadline, &p->deadline) ; + avltree_delete(&sassserver_by_id, &p->id) ; + gensetdyn_delete(&sassserver_queries, handle) ; +} + +void sassserver_async_failure (uint32_t handle, int e) +{ + sassserver_query *p = SASSSERVER_QUERY(handle) ; + char pack[8] ; + uint32_pack_big(pack, p->id) ; + uint32_pack_big(pack + 4, (uint32_t)e) ; + if (!textmessage_put(textmessage_sender_x, pack, 8)) + strerr_diefu1sys(111, "textmessage_put") ; + sassserver_remove(handle) ; +} + +void sassserver_async_successv (uint32_t handle, struct iovec const *v, unsigned int n) +{ + sassserver_query *p = SASSSERVER_QUERY(handle) ; + char pack[8] = "\0\0\0\0\0\0\0" ; + struct iovec vv[n+1] ; + vv[0].iov_base = pack ; vv[0].iov_len = 8 ; + for (unsigned int i = 0 ; i < n ; i++) vv[i+1] = v[i] ; + uint32_pack_big(pack, p->id) ; + if (!textmessage_putv(textmessage_sender_x, vv, n+1)) + strerr_diefu1sys(111, "textmessage_putv") ; + sassserver_remove(handle) ; +} + +void sassserver_async_success (uint32_t handle, char const *s, size_t len) +{ + struct iovec v = { .iov_base = (char *)s, .iov_len = len } ; + sassserver_async_successv(handle, &v, 1) ; +} + +static inline void sassserver_uniquify (tain *deadline) +{ + static tain const nanosec = { .sec = TAI_ZERO, .nano = 1 } ; + uint32_t dummy ; + while (avltree_search(&sassserver_by_deadline, deadline, &dummy)) + tain_add(deadline, deadline, &nanosec) ; +} + +static int sassserver_parse_protocol (struct iovec const *v, void *aux) +{ + char const *s = v->iov_base ; + size_t vlen = v->iov_len ; + (void)aux ; + if (vlen-- < 5) strerr_dief1x(100, "invalid client request") ; + switch (*s++) + { + case '-' : /* cancel */ + { + uint32_t handle, id ; + if (vlen != 4) strerr_dief1x(100, "invalid client request") ; + uint32_unpack_big(s, &id) ; + if (!avltree_search(&sassserver_by_id, &id, &handle)) sassserver_sync_answer(EINVAL) ; + (*sassserver_cancelf)(SASSSERVER_QUERY(handle)->data) ; + sassserver_remove(handle) ; + sassserver_sync_answer(0) ; + break ; + } + case '+' : /* send */ + { + sassserver_query *p ; + uint32_t handle ; + uint32_t timeout ; + uint32_t opcode ; + uint32_t len ; + if (vlen < 16) strerr_dief1x(100, "invalid client request") ; + if (!gensetdyn_new(&sassserver_queries, &handle)) strerr_diefu1sys(111, "gensetdyn_new") ; + p = SASSSERVER_QUERY(handle) ; + uint32_unpack_big(s, &p->id) ; s += 4 ; vlen -= 4 ; + uint32_unpack_big(s, &timeout) ; s += 4 ; vlen -= 4 ; + uint32_unpack_big(s, &opcode) ; s += 4 ; vlen -= 4 ; + uint32_unpack_big(s, &len) ; s += 4 ; vlen -= 4 ; + if (len != vlen) strerr_dief1x(100, "invalid client request") ; + if (timeout) + { + if (!tain_from_millisecs(&p->deadline, timeout)) strerr_dief1x(100, "invalid client request") ; + tain_add_g(&p->deadline, &p->deadline) ; + } + else tain_add_g(&p->deadline, &tain_infinite_relative) ; + sassserver_uniquify(&p->deadline) ; + if (!avltree_insert(&sassserver_by_deadline, handle)) strerr_diefu1sys(111, "avltree_insert") ; + if (!avltree_insert(&sassserver_by_id, handle)) strerr_diefu1sys(111, "avltree_insert") ; + p->data = (*sassserver_sendf)(handle, opcode, s, len) ; + if (!p->data) + { + int e = errno ; + sassserver_remove(handle) ; + sassserver_sync_answer(e) ; + } + else sassserver_sync_answer(0) ; + break ; + } + default : strerr_dief1x(100, "invalid client request") ; + } + return 1 ; +} + +void sassserver_init (char const *banner1, char const *banner2, sassserver_send_func_ref sendf, sassserver_cancel_func_ref cancelf, tain const *deadline, tain *stamp) +{ + if (!textclient_server_01x_init(banner1, strlen(banner1), banner2, strlen(banner2), deadline, stamp)) + strerr_diefu1sys(111, "sync with client") ; + sassserver_sendf = sendf ; + sassserver_cancelf = cancelf ; +} + +unsigned int sassserver_prepare_iopause (iopause_fd *x, tain *deadline) +{ + uint32_t i ; + if (avltree_min(&sassserver_by_deadline, &i)) tain_earliest1(deadline, &SASSSERVER_QUERY(i)->deadline) ; + x[0].fd = 0 ; + x[0].events = IOPAUSE_READ ; + x[1].fd = 1 ; + x[1].events = textmessage_sender_isempty(textmessage_sender_1) ? 0 : IOPAUSE_WRITE ; + x[2].fd = textmessage_sender_fd(textmessage_sender_x) ; + x[2].events = textmessage_sender_isempty(textmessage_sender_x) ? 0 : IOPAUSE_WRITE ; + return 3 ; +} + +void sassserver_timeout (void) +{ + uint32_t i ; + while (avltree_min(&sassserver_by_deadline, &i)) + { + sassserver_query *p = SASSSERVER_QUERY(i) ; + if (tain_future(&p->deadline)) break ; + avltree_delete(&sassserver_by_deadline, &p->deadline) ; + avltree_delete(&sassserver_by_id, &p->id) ; + (*sassserver_cancelf)(p->data) ; + sassserver_async_failure(p->id, ETIMEDOUT) ; + gensetdyn_delete(&sassserver_queries, i) ; + } +} + +int sassserver_event (iopause_fd const *x) +{ + if (x[1].revents & IOPAUSE_WRITE) + if (!textmessage_sender_flush(textmessage_sender_1) && !error_isagain(errno)) + strerr_diefu1sys(111, "flush stdout") ; + if (x[2].revents & IOPAUSE_WRITE) + if (!textmessage_sender_flush(textmessage_sender_x) && !error_isagain(errno)) + strerr_diefu1sys(111, "flush asyncout") ; + + if (!textmessage_receiver_isempty(textmessage_receiver_0) || x[0].revents & IOPAUSE_READ) + { + if (textmessage_handle(textmessage_receiver_0, &sassserver_parse_protocol, 0) == -1) + { + if (errno != EPIPE) strerr_diefu1sys(111, "read messages from client") ; + return 1 ; + } + } + return 0 ; +} |
