#include #include #include #include #include #include #include "test.h" #include "tests.h" typedef struct priv PRIV; struct priv { int nbr; int nbw; int rfirst; int lfd; int cfd; } ; #define XFER ((10+9+8+7+6+5+4+3+2+1)*1000) static unsigned char data1[XFER]; static unsigned char data2[XFER]; static void set_nbio(int fd) { fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0)|O_NONBLOCK); } static void run_split_run_l(void *pv) { PRIV *p; pid_t mypid; int fd; int fd2; int i; char c; int blko; int blkn; int o; int n; struct pollfd pfd; p = pv; mypid = getpid(); printf("split: listener is %d\n",(int)mypid); printf("split: listener establishing connection\n"); mustwrite(p->lfd,&mypid,sizeof(pid_t)); sleep(1); SET_PIDCONN(fd,PIDCONN_LISTEN,0,0); mustwrite(p->lfd,"",1); SET_PIDCONN(fd2,PIDCONN_ACCEPT,fd,0); mustwrite(p->lfd,"",1); mustread(p->lfd,&c,1); if (p->nbw) set_nbio(fd2); mustwrite(p->lfd,"",1); mustread(p->lfd,&c,1); printf("split: listener writing\n"); mustwrite(p->lfd,"",1); mustread(p->lfd,&c,1); sleep(p->rfirst?2:1); blko = 0; for (n=10;n>=1;n--) { blkn = n * 1000; if (p->nbw) { o = 0; while (o < blkn) { i = write(fd2,data1+blko+o,blkn-o); if (i < 0) { if (errno == EWOULDBLOCK) { pfd.fd = fd2; pfd.events = POLLOUT | POLLWRNORM; i = poll(&pfd,1,INFTIM); if (i >= 0) continue; if (errno == EINTR) continue; printf("split: polling for NBIO write to connection (at %d): %s\n",blko+o,strerror(errno)); test_fail(); return; } printf("split: write (at %d) failed: %s\n",blko+o,strerror(errno)); test_fail(); return; } o += i; } } else { i = write(fd2,data1+blko,blkn); if (i < 0) { printf("split: write to connection: %s\n",strerror(errno)); test_fail(); } if (i != blkn) { printf("split: write to connection returned %d, expected %d\n",i,blkn); test_fail(); } } blko += blkn; } mustwrite(p->lfd,"",1); mustread(p->lfd,&c,1); printf("split: listener done\n"); sleep(1); } static void run_split_run_c(void *pv) { PRIV *p; pid_t lpid; int fd; char c; int o; int i; struct pollfd pfd; int n; int blkn; int blko; p = pv; printf("split: connecter is %d\n",(int)getpid()); mustread(p->cfd,&lpid,sizeof(pid_t)); printf("split: connecter establishing connection to %d\n",(int)lpid); sleep(1); mustread(p->cfd,&c,1); SET_PIDCONN(fd,PIDCONN_CONNECT,0,lpid); mustread(p->cfd,&c,1); mustwrite(p->cfd,"",1); if (p->nbr) set_nbio(fd); mustread(p->cfd,&c,1); mustwrite(p->cfd,"",1); printf("split: connecter reading\n"); mustread(p->cfd,&c,1); mustwrite(p->cfd,"",1); sleep(p->rfirst?1:2); blko = 0; for (n=1;n<=10;n++) { blkn = n * 1000; if (p->nbr) { o = 0; while (o < blkn) { i = read(fd,data2+blko+o,blkn-o); if (i < 0) { if (errno == EWOULDBLOCK) { pfd.fd = fd; pfd.events = POLLIN | POLLRDNORM; i = poll(&pfd,1,INFTIM); if (i >= 0) continue; if (errno == EINTR) continue; printf("split: polling for NBIO read from connection (at %d): %s\n",o,strerror(errno)); test_fail(); return; } printf("split: read (at %d) failed: %s\n",o,strerror(errno)); test_fail(); return; } o += i; } } else { i = read(fd,data2+blko,blkn); if (i < 0) { printf("split: read from connection: %s\n",strerror(errno)); test_fail(); } if (i != blkn) { printf("split: read from connection returned %d, expected %d\n",i,blkn); test_fail(); } } blko += blkn; } i = 0; for (o=0;o= 10) { printf("...more\n"); break; } printf("wrote [%d] = %02x, read [%d] = %02x\n", o,data1[o],o,data2[o]); i ++; } } mustwrite(p->cfd,"",1); mustread(p->cfd,&c,1); printf("split: connecter done\n"); sleep(1); } static void do_split(int nbr, int nbw, int rfirst) { PRIV p; KID *kl; KID *kc; printf("split: >>>>>>>> nbr=%d nbw=%d rfirst=%d\n",nbr,nbw,rfirst); local_socketpair(&p.lfd,&p.cfd); p.nbr = nbr; p.nbw = nbw; p.rfirst = rfirst; kl = fork_kid(&run_split_run_l,&p); kc = fork_kid(&run_split_run_c,&p); close(p.lfd); close(p.cfd); reap_kid(kl); reap_kid(kc); } static void setup_data(void) { int i; srandom(1); for (i=XFER-1;i>=0;i--) data1[i] = (random() >> 22) & 0xff; } static void run_split(void) { setup_data(); do_split(0,0,0); do_split(0,0,1); do_split(0,1,0); do_split(0,1,1); do_split(1,0,0); do_split(1,0,1); do_split(1,1,0); do_split(1,1,1); printf("split: done\n"); } const TEST test_split = { &run_split };