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
|
/* ISC license. */
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <regex.h>
#include <skalibs/posixplz.h>
#include <skalibs/strerr.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 (void *s, void *reason)
{
query_fail(*(uint32_t *)s, *(unsigned 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) ;
unsigned 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 = skalibs_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 ;
}
|