1 /* ISC license. */
2 
3 #include <sys/uio.h>
4 #include <string.h>
5 #include <errno.h>
6 
7 #include <skalibs/allreadwrite.h>
8 #include <skalibs/error.h>
9 #include <skalibs/djbunix.h>
10 #include <skalibs/unix-timed.h>
11 #include <skalibs/ancil.h>
12 #include <skalibs/textmessage.h>
13 #include <skalibs/posixishard.h>
14 
getfd(void * p)15 static int getfd (void *p)
16 {
17   return ((int *)p)[0] ;
18 }
19 
get(void * p)20 static ssize_t get (void *p)
21 {
22   int *fd = p ;
23   int r = ancil_recv_fd(fd[0], '|') ;
24   if (r < 0) return error_isagain(errno) ? (errno = 0, 0) : r ;
25   fd[1] = r ;
26   return 1 ;
27 }
28 
textmessage_recv_channel(int sock,textmessage_receiver_t * asyncin,char * asyncbuf,size_t asyncbufsize,char const * after,size_t afterlen,tain_t const * deadline,tain_t * stamp)29 int textmessage_recv_channel (int sock, textmessage_receiver_t *asyncin, char *asyncbuf, size_t asyncbufsize, char const *after, size_t afterlen, tain_t const *deadline, tain_t *stamp)
30 {
31   struct iovec v ;
32   int fd[2] = { sock, -1 } ;
33   ssize_t r = timed_get(fd, &getfd, &get, deadline, stamp) ;
34   if (!r) errno = EPIPE ;
35   if (r <= 0) return 0 ;
36   textmessage_receiver_init(asyncin, fd[1], asyncbuf, asyncbufsize, TEXTMESSAGE_MAXLEN) ;
37   if (sanitize_read(textmessage_timed_receive(asyncin, &v, deadline, stamp)) <= 0) goto serr ;
38   if (v.iov_len != afterlen || memcmp(v.iov_base, after, afterlen)) goto berr ;
39   return 1 ;
40 
41  berr:
42   errno = EPROTO ;
43  serr:
44   textmessage_receiver_free(asyncin) ;
45   fd_close(fd[1]) ;
46   return 0 ;
47 }
48