ftrigr_updateb.c (1829B)
1 /* ISC license. */ 2 3 #include <sys/types.h> 4 #include <sys/uio.h> 5 #include <stdint.h> 6 #include <errno.h> 7 8 #include <skalibs/gccattributes.h> 9 #include <skalibs/uint16.h> 10 #include <skalibs/genalloc.h> 11 #include <skalibs/gensetdyn.h> 12 #include <skalibs/textclient.h> 13 #include <s6/ftrigr.h> 14 15 #include <skalibs/posixishard.h> 16 17 static inline int appears (uint16_t, uint16_t const *, size_t) gccattr_pure ; 18 19 static inline int appears (uint16_t id, uint16_t const *list, size_t len) 20 { 21 while (len) if (id == list[--len]) return 1 ; 22 return 0 ; 23 } 24 25 static int msghandler (struct iovec const *v, void *context) 26 { 27 ftrigr_t *a = (ftrigr_t *)context ; 28 ftrigr1_t *p ; 29 int addit = 1 ; 30 char const *s = v->iov_base ; 31 uint16_t id ; 32 if (v->iov_len != 4) return (errno = EPROTO, 0) ; 33 uint16_unpack_big(s, &id) ; 34 p = GENSETDYN_P(ftrigr1_t, &a->data, id) ; 35 if (!p) return 1 ; 36 if (p->state != FR1STATE_LISTENING) return (errno = EINVAL, 0) ; 37 if (!genalloc_readyplus(uint16_t, &a->list, 1)) return 0 ; 38 switch (s[2]) 39 { 40 case 'd' : 41 if (!stralloc_catb(&p->what, s + 3, 1)) return 0 ; 42 p->state = FR1STATE_WAITACK ; 43 break ; 44 case '!' : 45 if (!stralloc_catb(&p->what, s + 3, 1)) return 0 ; 46 if (p->options & FTRIGR_REPEAT) 47 { 48 if (p->what.len > 1 49 && appears(id+1, genalloc_s(uint16_t, &a->list), genalloc_len(uint16_t, &a->list))) 50 addit = 0 ; 51 } 52 else p->state = FR1STATE_WAITACKDATA ; 53 break ; 54 default : return (errno = EPROTO, 0) ; 55 } 56 if (addit) 57 { 58 id++ ; genalloc_append(uint16_t, &a->list, &id) ; 59 } 60 return 1 ; 61 } 62 63 int ftrigr_updateb (ftrigr_t *a) 64 { 65 size_t curlen = genalloc_len(uint16_t, &a->list) ; 66 int r = textclient_update(&a->connection, &msghandler, a) ; 67 return r < 0 ? r : (int)(genalloc_len(uint16_t, &a->list) - curlen) ; 68 }