summaryrefslogtreecommitdiff
path: root/src/rpc/skabus_rpcd_interface.c
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2017-11-24 18:54:03 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2017-11-24 18:54:03 +0000
commit6432cead1941d5305bc2d7f22821ca8a98f43f78 (patch)
tree1898075255d0e9ac285a22326356c564c1b6c839 /src/rpc/skabus_rpcd_interface.c
parent2c5c19923ec56298c4e6b4a71084b27414fd96d6 (diff)
downloadskabus-6432cead1941d5305bc2d7f22821ca8a98f43f78.tar.xz
Add skabus-rpc-daemon, skabus-rpcd and the skabus_rpc library
Diffstat (limited to 'src/rpc/skabus_rpcd_interface.c')
-rw-r--r--src/rpc/skabus_rpcd_interface.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/rpc/skabus_rpcd_interface.c b/src/rpc/skabus_rpcd_interface.c
new file mode 100644
index 0000000..458b2d8
--- /dev/null
+++ b/src/rpc/skabus_rpcd_interface.c
@@ -0,0 +1,113 @@
+/* ISC license. */
+
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <regex.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/gensetdyn.h>
+#include <skalibs/avltree.h>
+#include <skabus/rpc.h>
+#include "skabus-rpcd.h"
+
+static inline void interface_free (interface_t *p)
+{
+ p->name[0] = p->name[1] = 0 ;
+ gensetdyn_free(&p->queries) ;
+}
+
+static void *if_dtok (uint32_t d, void *x)
+{
+ (void)x ;
+ return INTERFACE(d)->name ;
+}
+
+static int if_cmp (void const *a, void const *b, void *x)
+{
+ (void)x ;
+ return strncmp((char const *)a, (char const *)b, SKABUS_RPC_INTERFACE_MAXLEN) ;
+}
+
+gensetdyn interfaces = GENSETDYN_ZERO ;
+static avltree ifdict = AVLTREE_INIT(2, 3, 8, &if_dtok, &if_cmp, 0) ;
+
+static inline void interface_delete (uint32_t i)
+{
+ interface_t *y = INTERFACE(i) ;
+ if (!avltree_delete(&ifdict, y->name))
+ strerr_diefu1sys(111, "avltree_delete in interface_delete") ;
+ interface_free(y) ;
+ if (!gensetdyn_delete(&interfaces, i))
+ strerr_diefu1sys(111, "gensetdyn_delete in interface_delete") ;
+}
+
+static int query_fail_iter (char *s, void *reason)
+{
+ uint32_t i = *(uint32_t *)s ;
+ query_fail(i, *(char *)reason) ;
+ return 1 ;
+}
+
+static inline void client_interfacemove (client_t *c, uint32_t from, uint32_t to)
+{
+ uint32_t *ifaces = genalloc_s(uint32_t, &c->interfaces) ;
+ INTERFACE(ifaces[from])->index = to ;
+ ifaces[to] = ifaces[from] ;
+}
+
+void interface_remove (uint32_t i)
+ {
+ interface_t *y = INTERFACE(i) ;
+ client_t *c = CLIENT(y->client) ;
+ uint32_t n = gensetdyn_n(&y->queries) ;
+ char reason = ECONNRESET ;
+ gensetdyn_iter(&y->queries, &query_fail_iter, &reason) ;
+ n = genalloc_len(uint32_t, &c->interfaces) ;
+ client_interfacemove(c, n-1, y->index) ;
+ genalloc_setlen(uint32_t, &c->interfaces, n-1) ;
+ interface_delete(i) ;
+}
+
+int interface_lookup_by_name (char const *s, uint32_t *d)
+{
+ return avltree_search(&ifdict, s, d) ;
+}
+
+int interface_add (uint32_t *d, char const *name, size_t namelen, uint32_t client, char const *re, uint32_t id)
+{
+ uint32_t yy ;
+ int e ;
+ genalloc *g = &CLIENT(client)->interfaces ;
+ if (!genalloc_readyplus(uint32_t, g, 1)) return 0 ;
+ if (!gensetdyn_new(&interfaces, &yy)) return 0 ;
+ {
+ interface_t *y = INTERFACE(yy) ;
+ int r = regcomp(&y->re, re, REG_EXTENDED | REG_NOSUB) ;
+ if (r)
+ {
+ e = r == REG_ESPACE ? ENOMEM : EINVAL ;
+ goto err ;
+ }
+ memcpy(y->name, name, namelen) ; y->name[namelen] = 0 ;
+ y->id = id ;
+ y->client = client ;
+ y->index = genalloc_len(uint32_t, g) - 1 ;
+ y->queries = gensetdyn_zero ;
+ if (!avltree_insert(&ifdict, yy))
+ {
+ e = errno ;
+ regfree(&y->re) ;
+ goto err ;
+ }
+ }
+ genalloc_append(uint32_t, g, &yy) ;
+ *d = yy ;
+ return 1 ;
+
+ err:
+ if (!gensetdyn_delete(&interfaces, yy))
+ strerr_diefu1sys(111, "gensetdyn_delete in interface_add") ;
+ errno = e ;
+ return 0 ;
+}