skalibs

Mirror/fork of https://skarnet.org/software/skalibs/
git clone https://ccx.te2000.cz/git/skalibs
Log | Files | Refs | README | LICENSE

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 }