#include #include #include #include #include #include #include #include #include #include #include #include #include #include static int child, finish = 0, seconds = 30; static void doalarm(int sig) { finish = 1; } static int conn(const char *path, int server) { struct sockaddr_un sun; int sock; sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) err(1, "socket()"); bzero(&sun, sizeof(sun)); sun.sun_len = sizeof(sun); sun.sun_family = AF_UNIX; strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); if (server) { if (bind(sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) err(1, "bind()"); if (listen(sock, 5) == -1) err(1, "listen()"); } else { if (connect(sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) err(1, "connect()"); } return (sock); } static void sendproc(const char *path, int sock) { ssize_t done; char byte; int packets; packets = 0; byte = 0x55; for (;;) { done = send(sock, &byte, 1, 0); assert(done == 1); done = recv(sock, &byte, 1, MSG_WAITALL); assert(done == 1); packets++; if (finish) { kill(child, SIGKILL); unlink(path); printf("%d packets/s\n", packets / seconds); exit(0); } } } static void recvproc(int sock) { char byte; ssize_t done; for (;;) { done = recv(sock, &byte, 1, MSG_WAITALL); assert(done == 1); done = send(sock, &byte, 1, 0); assert(done == 1); } } int main(int argc, char *argv[]) { char path[PATH_MAX]; int fd; switch (argc) { case 1: break; case 2: seconds = atoi(argv[1]); if (seconds > 0) break; /* FALLTHROUGH */ default: errx(1, "usage: %s ", getprogname()); } strlcpy(path, "/tmp/unixpingpong.XXXXXXXX", sizeof(path)); fd = mkstemp(path); assert(fd >= 0); close(fd); unlink(path); child = fork(); switch (child) { case -1: err(1, "fork()"); case 0: sleep(1); recvproc(conn(path, 0)); exit(0); default: fd = conn(path, 1); sleep(1); fd = accept(fd, NULL, NULL); if (fd < 0) err(1, "accept()"); signal(SIGALRM, doalarm); alarm(seconds); sendproc(path, fd); exit(0); } exit(0); }