summaryrefslogtreecommitdiff
path: root/src/rpc/skabus_rpccctl.c
blob: 83b72acd550e108a1593b5d74869a76542efbed1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
 /* ISC license. */

#include <sys/uio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <limits.h>

#include <skalibs/posixishard.h>
#include <skalibs/uint32.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) ; 
}