summaryrefslogtreecommitdiff
path: root/src/rpc/skabus_rpccctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc/skabus_rpccctl.c')
-rw-r--r--src/rpc/skabus_rpccctl.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/rpc/skabus_rpccctl.c b/src/rpc/skabus_rpccctl.c
new file mode 100644
index 0000000..a57f3be
--- /dev/null
+++ b/src/rpc/skabus_rpccctl.c
@@ -0,0 +1,121 @@
+ /* ISC license. */
+
+#include <sys/uio.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <skalibs/uint32.h>
+#include <skalibs/error.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/webipc.h>
+#include <skalibs/textmessage.h>
+#include <skabus/rpc.h>
+#include "skabus-rpccctl.h"
+
+int skabus_rpcc_start (skabus_rpcc_t *a, char const *path, tain_t const *deadline, tain_t *stamp)
+{
+ int fd = ipc_stream_nb() ;
+ if (fd < 0) return 0 ;
+ if (!ipc_timed_connect(fd, path, deadline, stamp))
+ {
+ fd_close(fd) ;
+ return 0 ;
+ }
+ textmessage_sender_init(&a->out, fd) ;
+ textmessage_receiver_init(&a->in, fd) ;
+ return 1 ;
+}
+
+void skabus_rpcc_end (skabus_rpcc_t *a)
+{
+ fd_close(textmessage_sender_fd(&a->out)) ;
+ textmessage_sender_free(&a->out) ;
+ textmessage_receiver_free(&a->in) ;
+}
+
+int skabus_rpcc_interface_register (skabus_rpcc_t *a, char const *ifname, char const *ifprog, char const *re, tain_t const *deadline, tain_t *stamp)
+{
+ size_t ifnamelen, ifproglen, relen ;
+ char *ifprogfn = realpath(ifprog, 0) ;
+ if (!ifprogfn) return 0 ;
+ ifnamelen = strlen(ifname) ;
+ ifproglen = strlen(ifprogfn) ;
+ relen = strlen(re) ;
+ if (ifnamelen > SKABUS_RPC_INTERFACE_MAXLEN || ifproglen > PATH_MAX || relen > SKABUS_RPC_RE_MAXLEN) goto terr ;
+ {
+ char buf[9] ;
+ struct iovec v[5] =
+ {
+ { .iov_base = "I", .iov_len = 1 },
+ { .iov_base = buf, .iov_len = 9 },
+ { .iov_base = ifname, .iov_len = ifnamelen + 1 },
+ { .iov_base = ifprogfn, .iov_len = ifproglen + 1 },
+ { .iov_base = re, .iov_len = relen + 1 }
+ } ;
+ buf[0] = (unsigned char)ifnamelen ;
+ uint32_pack_big(buf + 1, ifproglen) ;
+ uint32_pack_big(buf + 5, relen) ;
+ if (!textmessage_timed_commandv(&a->out, v, 5, deadline, stamp)) goto err ;
+ }
+ return 1 ;
+
+ terr:
+ errno = ENAMETOOLONG ;
+ err:
+ free(ifprogfn) ;
+ return 0 ;
+}
+
+int skabus_rpcc_interface_unregister (skabus_rpcc_t *a, char const *ifname, tain_t const *deadline, tain_t *stamp)
+{
+ size_t ifnamelen = strlen(ifname) ;
+ if (ifnamelen > SKABUS_RPC_INTERFACE_MAXLEN) return (errno = ENAMETOOLONG, 0) ;
+ {
+ unsigned char c = ifnamelen ;
+ struct iovec v[3] =
+ {
+ { .iov_base = "i", .iov_len = 1 },
+ { .iov_base = &c, .iov_len = 1 },
+ { .iov_base = ifname, .iov_len = ifnamelen + 1 }
+ } ;
+ if (!textmessage_timed_commandv(&a->out, v, 3, deadline, stamp)) return 0 ;
+ }
+ return 1 ;
+}
+
+int skabus_rpcc_query (skabus_rpcc_t *a, stralloc *reply, char const *ifname, char const *query, uint32_t timeout, tain_t const *deadline, tain_t *stamp)
+{
+ size_t ifnamelen = strlen(ifname) ;
+ size_t querylen = strlen(query) ;
+ if (ifnamelen > SKABUS_RPC_INTERFACE_MAXLEN || querylen > UINT32_MAX) return (errno = ENAMETOOLONG, 0) ;
+ {
+ char buf[9] ;
+ struct iovec v[4] =
+ {
+ { .iov_base = "Q", .iov_len = 1 },
+ { .iov_base = buf, .iov_len = 59 },
+ { .iov_base = ifname, .iov_len = ifnamelen + 1 },
+ { .iov_base = query, .iov_len = querylen + 1 },
+ } ;
+ buf[0] = ifnamelen ;
+ uint32_pack_big(buf + 1, querylen) ;
+ uint32_pack_big(buf + 5, timeout) ;
+ if (!textmessage_timed_sendv(&a->out, v, 4)) return 0 ;
+ }
+ {
+ struct iovec v ;
+ if (!textmessage_timed_receive(&a->in, &v, deadline, stamp)) return 0 ;
+ if (!v.iov_len) return (errno = EPROTO, 0) ;
+ if (*(unsigned char *)v.iov_base) return (errno = *(unsigned char)v.iov_base, 0) ;
+ if (!stralloc_catb(reply, (char *)v.iov_base + 1, v.iov_len - 1)) return 0 ;
+ }
+ return 1 ;
+}
+
+int skabus_rpcc_quit (skabus_rpcc_t *a, tain_t const *deadline, tain_t *stamp)
+{
+ return textmessage_timed_command(&a->out, ".", 1, deadline, stamp) ;
+}