int main(int argc, char **argv) { int fd, fd_s, ctl_fd; pid_t extpid; int pfd[2]; int sk_bsize; int ret, snd, snd_size, rcv_size = 0, rcv_buf_size; #ifdef ZDTM_TCP_LOCAL test_init(argc, argv); #endif if (pipe(pfd)) { pr_perror("pipe() failed"); return 1; } extpid = fork(); if (extpid < 0) { pr_perror("fork() failed"); return 1; } else if (extpid == 0) { int size; char c; #ifndef ZDTM_TCP_LOCAL test_ext_init(argc, argv); #endif close(pfd[1]); read_safe(pfd[0], &port, sizeof(port)); fd = tcp_init_client(ZDTM_FAMILY, "127.0.0.1", port); if (fd < 0) return 1; ctl_fd = tcp_init_client(ZDTM_FAMILY, "127.0.0.1", port); if (fd < 0) return 1; snd_size = fill_sock_buf(fd); if (snd_size <= 0) return 1; write_safe(ctl_fd, &snd_size, sizeof(snd_size)); read_safe(ctl_fd, &rcv_buf_size, sizeof(rcv_buf_size)); while (1) { /* heart beat */ read_safe(ctl_fd, &ret, sizeof(ret)); if (ret < 0) break; rcv_buf_size += ret; snd = fill_sock_buf(fd); if (snd < 0) return -1; snd_size += snd; if (rcv_buf_size / 2) { ret = clean_sk_buf(fd, rcv_buf_size / 2); if (ret <= 0) return 1; } else ret = 0; rcv_buf_size -= ret; rcv_size += ret; write_safe(ctl_fd, &snd, sizeof(snd)); } read_safe(ctl_fd, &ret, sizeof(ret)); rcv_buf_size += ret; write_safe(ctl_fd, &snd_size, sizeof(snd_size)); if (read(ctl_fd, &c, 1) != 0) { pr_perror("read"); return 1; } if (shutdown(fd, SHUT_WR) == -1) { pr_perror("shutdown"); return 1; } size = clean_sk_buf(fd, 0); if (size < 0) return 1; if (size != rcv_buf_size) { fail("the received buffer contains only %d bytes (%d)\n", size, rcv_buf_size); } rcv_size += size; write_safe(ctl_fd, &rcv_size, sizeof(rcv_size)); close(fd); return 0; } #ifndef ZDTM_TCP_LOCAL test_init(argc, argv); #endif if ((fd_s = tcp_init_server(ZDTM_FAMILY, &port)) < 0) { pr_perror("initializing server failed"); return 1; } close(pfd[0]); write_safe(pfd[1], &port, sizeof(port)); close(pfd[1]); /* * parent is server of TCP connection */ fd = tcp_accept_server(fd_s); if (fd < 0) { pr_perror("can't accept client connection %m"); return 1; } ctl_fd = tcp_accept_server(fd_s); if (ctl_fd < 0) { pr_perror("can't accept client connection %m"); return 1; } sk_bsize = TCP_MAX_BUF; if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sk_bsize, sizeof(sk_bsize)) == -1) { pr_perror("Can't set snd buf"); return 1; } sk_bsize = TCP_MAX_BUF; if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sk_bsize, sizeof(sk_bsize)) == -1) { pr_perror("Can't set snd buf"); return 1; } snd_size = fill_sock_buf(fd); if (snd_size <= 0) return 1; read_safe(ctl_fd, &rcv_buf_size, sizeof(rcv_buf_size)); write_safe(ctl_fd, &snd_size, sizeof(snd_size)); test_daemon(); snd = 0; while (test_go()) { /* heart beat */ if (rcv_buf_size / 2) { ret = clean_sk_buf(fd, rcv_buf_size / 2); if (ret <= 0) return 1; } else ret = 0; rcv_size += ret; rcv_buf_size -= ret; write_safe(ctl_fd, &snd, sizeof(snd)); read_safe(ctl_fd, &ret, sizeof(ret)); rcv_buf_size += ret; snd = fill_sock_buf(fd); if (snd < 0) return -1; snd_size += snd; } ret = -1; write_safe(ctl_fd, &ret, sizeof(ret)); write_safe(ctl_fd, &snd, sizeof(ret)); read_safe(ctl_fd, &snd, sizeof(snd)); if (shutdown(ctl_fd, SHUT_WR) == -1) { pr_perror("shutdown"); return 1; } if (shutdown(fd, SHUT_WR) == -1) { pr_perror("shutdown"); return 1; } ret = clean_sk_buf(fd, 0); if (ret != rcv_buf_size) { fail("the received buffer contains only %d bytes (%d)\n", ret, rcv_buf_size); } rcv_size += ret; if (snd != rcv_size) { fail("The child sent %d bytes, but the parent received %d bytes\n", rcv_buf_size, rcv_size); return 1; } read_safe(ctl_fd, &ret, sizeof(ret)); if (ret != snd_size) { fail("The parent sent %d bytes, but the child received %d bytes\n", snd_size, ret); return 1; } pass(); return 0; }
int main(int argc, char **argv) { char *newns = getenv("ZDTM_NEWNS"); int fd, fd_s, ctl_fd; pid_t extpid; int pfd[2]; int ret = 0, snd_size = 0, rcv_size = 0; #ifndef ZDTM_TCP_LAST_ACK char buf[BUF_SIZE]; #endif if (newns) test_init(argc, argv); if (pipe(pfd)) { pr_perror("pipe() failed"); return 1; } extpid = fork(); if (extpid < 0) { pr_perror("fork() failed"); return 1; } else if (extpid == 0) { int size = 0; char c; if (!newns) test_ext_init(argc, argv); close(pfd[1]); if (read(pfd[0], &port, sizeof(port)) != sizeof(port)) { pr_perror("Can't read port\n"); return 1; } close(pfd[0]); fd = tcp_init_client(ZDTM_FAMILY, "127.0.0.1", port); if (fd < 0) return 1; ctl_fd = tcp_init_client(ZDTM_FAMILY, "127.0.0.1", port); if (ctl_fd < 0) return 1; /* == The preparation stage == */ if (read(ctl_fd, &size, sizeof(size)) != sizeof(size)) { pr_perror("read"); return 1; } if (shutdown(fd, SHUT_WR) == -1) { pr_perror("shutdown"); return 1; } if (write(ctl_fd, &size, sizeof(size)) != sizeof(size)) { pr_perror("write"); return 1; } /* == End of the preparation stage == */ /* Checkpoint/restore */ /* == The final stage == */ if (read(ctl_fd, &c, 1) != 0) { pr_perror("read"); return 1; } #ifdef ZDTM_TCP_LAST_ACK size = clean_sk_buf(fd); if (size < 0) return 1; #else if (read(fd, buf, sizeof(buf)) != sizeof(TEST_MSG) || strncmp(buf, TEST_MSG, sizeof(TEST_MSG))) { pr_perror("read"); return 1; } #endif if (write(ctl_fd, &size, sizeof(size)) != sizeof(size)) { pr_perror("write"); return 1; } /* == End of the final stage == */ close(ctl_fd); close(fd); return 0; } if (!newns) test_init(argc, argv); if ((fd_s = tcp_init_server(ZDTM_SRV_FAMILY, &port)) < 0) { pr_err("initializing server failed"); return 1; } close(pfd[0]); if (write(pfd[1], &port, sizeof(port)) != sizeof(port)) { pr_perror("Can't send port"); return 1; } close(pfd[1]); /* * parent is server of TCP connection */ fd = tcp_accept_server(fd_s); if (fd < 0) { pr_err("can't accept client connection"); return 1; } ctl_fd = tcp_accept_server(fd_s); if (ctl_fd < 0) { pr_err("can't accept client connection"); return 1; } /* == The preparation stage == */ #ifdef ZDTM_TCP_LAST_ACK snd_size = fill_sock_buf(fd); if (snd_size <= 0) return 1; #endif if (write(ctl_fd, &ret, sizeof(ret)) != sizeof(ret)) { pr_perror("read"); return 1; } if (read(ctl_fd, &ret, sizeof(ret)) != sizeof(ret)) { pr_perror("read"); return 1; } /* == End of the preparation stage */ #ifdef ZDTM_TCP_LAST_ACK if (shutdown(fd, SHUT_WR) == -1) { pr_perror("shutdown"); return 1; } #endif test_daemon(); test_waitsig(); /* == The final stage == */ if (shutdown(ctl_fd, SHUT_WR) == -1) { pr_perror("shutdown"); return 1; } #ifndef ZDTM_TCP_LAST_ACK if (write(fd, TEST_MSG, sizeof(TEST_MSG)) != sizeof(TEST_MSG)) { pr_perror("write"); return 1; } if (shutdown(fd, SHUT_WR) == -1) { pr_perror("shutdown"); return 1; } #endif rcv_size = clean_sk_buf(fd); if (ret != rcv_size) { fail("The child sent %d bytes, but the parent received %d bytes\n", ret, rcv_size); return 1; } if (read(ctl_fd, &ret, sizeof(ret)) != sizeof(ret)) { pr_perror("read"); return 1; } /* == End of the final stage == */ if (ret != snd_size) { fail("The parent sent %d bytes, but the child received %d bytes\n", snd_size, ret); return 1; } pass(); return 0; }