textmessage_recv_channel.c (1262B)
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 15 static int getfd (void *p) 16 { 17 return ((int *)p)[0] ; 18 } 19 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 29 int textmessage_recv_channel (int sock, textmessage_receiver *asyncin, char *asyncbuf, size_t asyncbufsize, char const *after, size_t afterlen, tain const *deadline, tain *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 }