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