1*3b41d99dSChuck Silvers /*- 2*3b41d99dSChuck Silvers * SPDX-License-Identifier: BSD-2-Clause 3*3b41d99dSChuck Silvers * 4*3b41d99dSChuck Silvers * Copyright (c) 2020 Netflix, Inc. 5*3b41d99dSChuck Silvers * 6*3b41d99dSChuck Silvers * Redistribution and use in source and binary forms, with or without 7*3b41d99dSChuck Silvers * modification, are permitted provided that the following conditions 8*3b41d99dSChuck Silvers * are met: 9*3b41d99dSChuck Silvers * 1. Redistributions of source code must retain the above copyright 10*3b41d99dSChuck Silvers * notice, this list of conditions and the following disclaimer. 11*3b41d99dSChuck Silvers * 2. Redistributions in binary form must reproduce the above copyright 12*3b41d99dSChuck Silvers * notice, this list of conditions and the following disclaimer in the 13*3b41d99dSChuck Silvers * documentation and/or other materials provided with the distribution. 14*3b41d99dSChuck Silvers * 15*3b41d99dSChuck Silvers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*3b41d99dSChuck Silvers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*3b41d99dSChuck Silvers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*3b41d99dSChuck Silvers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*3b41d99dSChuck Silvers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*3b41d99dSChuck Silvers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*3b41d99dSChuck Silvers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*3b41d99dSChuck Silvers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*3b41d99dSChuck Silvers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*3b41d99dSChuck Silvers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*3b41d99dSChuck Silvers * SUCH DAMAGE. 26*3b41d99dSChuck Silvers * 27*3b41d99dSChuck Silvers * $FreeBSD$ 28*3b41d99dSChuck Silvers */ 29*3b41d99dSChuck Silvers 30*3b41d99dSChuck Silvers #include <sys/types.h> 31*3b41d99dSChuck Silvers #include <sys/socket.h> 32*3b41d99dSChuck Silvers #include <sys/sysctl.h> 33*3b41d99dSChuck Silvers #include <sys/uio.h> 34*3b41d99dSChuck Silvers 35*3b41d99dSChuck Silvers #include <netinet/in.h> 36*3b41d99dSChuck Silvers 37*3b41d99dSChuck Silvers #include <err.h> 38*3b41d99dSChuck Silvers #include <errno.h> 39*3b41d99dSChuck Silvers #include <fcntl.h> 40*3b41d99dSChuck Silvers #include <pthread.h> 41*3b41d99dSChuck Silvers #include <stdbool.h> 42*3b41d99dSChuck Silvers #include <stdio.h> 43*3b41d99dSChuck Silvers #include <stdlib.h> 44*3b41d99dSChuck Silvers #include <string.h> 45*3b41d99dSChuck Silvers #include <unistd.h> 46*3b41d99dSChuck Silvers 47*3b41d99dSChuck Silvers static int ls; 48*3b41d99dSChuck Silvers static char buf[1024*1024]; 49*3b41d99dSChuck Silvers static volatile bool accept_done = false; 50*3b41d99dSChuck Silvers static volatile bool read_done = false; 51*3b41d99dSChuck Silvers 52*3b41d99dSChuck Silvers static void * 53*3b41d99dSChuck Silvers server(void *arg) 54*3b41d99dSChuck Silvers { 55*3b41d99dSChuck Silvers struct sockaddr_in sin; 56*3b41d99dSChuck Silvers ssize_t rv; 57*3b41d99dSChuck Silvers socklen_t slen; 58*3b41d99dSChuck Silvers int ss; 59*3b41d99dSChuck Silvers ssize_t readlen = (uintptr_t)arg; 60*3b41d99dSChuck Silvers 61*3b41d99dSChuck Silvers slen = sizeof(sin); 62*3b41d99dSChuck Silvers ss = accept(ls, (void *)&sin, &slen); 63*3b41d99dSChuck Silvers if (ss < 0) 64*3b41d99dSChuck Silvers err(1, "accept ls"); 65*3b41d99dSChuck Silvers 66*3b41d99dSChuck Silvers accept_done = true; 67*3b41d99dSChuck Silvers 68*3b41d99dSChuck Silvers do { 69*3b41d99dSChuck Silvers rv = read(ss, buf, sizeof(buf)); 70*3b41d99dSChuck Silvers if (rv == -1) 71*3b41d99dSChuck Silvers err(2, "read receiver"); 72*3b41d99dSChuck Silvers if (rv == 0) 73*3b41d99dSChuck Silvers break; 74*3b41d99dSChuck Silvers readlen -= rv; 75*3b41d99dSChuck Silvers } while (readlen != 0); 76*3b41d99dSChuck Silvers 77*3b41d99dSChuck Silvers read_done = true; 78*3b41d99dSChuck Silvers 79*3b41d99dSChuck Silvers return NULL; 80*3b41d99dSChuck Silvers } 81*3b41d99dSChuck Silvers 82*3b41d99dSChuck Silvers int 83*3b41d99dSChuck Silvers main(int argc, char **argv) 84*3b41d99dSChuck Silvers { 85*3b41d99dSChuck Silvers pthread_t pt; 86*3b41d99dSChuck Silvers struct sockaddr_in sin; 87*3b41d99dSChuck Silvers off_t start, len; 88*3b41d99dSChuck Silvers socklen_t slen; 89*3b41d99dSChuck Silvers int fd, cs, on, flags, error; 90*3b41d99dSChuck Silvers 91*3b41d99dSChuck Silvers if (argc != 5) 92*3b41d99dSChuck Silvers errx(1, "usage: %s <file> <start> <len> <flags>", 93*3b41d99dSChuck Silvers getprogname()); 94*3b41d99dSChuck Silvers 95*3b41d99dSChuck Silvers start = strtoull(argv[2], NULL, 0); 96*3b41d99dSChuck Silvers len = strtoull(argv[3], NULL, 0); 97*3b41d99dSChuck Silvers flags = strtoul(argv[4], NULL, 0); 98*3b41d99dSChuck Silvers 99*3b41d99dSChuck Silvers fd = open(argv[1], O_RDONLY); 100*3b41d99dSChuck Silvers if (fd < 0) 101*3b41d99dSChuck Silvers err(1, "open"); 102*3b41d99dSChuck Silvers 103*3b41d99dSChuck Silvers ls = socket(PF_INET, SOCK_STREAM, 0); 104*3b41d99dSChuck Silvers if (ls < 0) 105*3b41d99dSChuck Silvers err(1, "socket ls"); 106*3b41d99dSChuck Silvers 107*3b41d99dSChuck Silvers on = 1; 108*3b41d99dSChuck Silvers if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (void *)&on, 109*3b41d99dSChuck Silvers (socklen_t)sizeof(on)) < 0) 110*3b41d99dSChuck Silvers err(1, "SO_REUSEADDR"); 111*3b41d99dSChuck Silvers 112*3b41d99dSChuck Silvers sin.sin_len = sizeof(sin); 113*3b41d99dSChuck Silvers sin.sin_family = AF_INET; 114*3b41d99dSChuck Silvers sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 115*3b41d99dSChuck Silvers sin.sin_port = 0; 116*3b41d99dSChuck Silvers if (bind(ls, (void *)&sin, sizeof(sin)) < 0) 117*3b41d99dSChuck Silvers err(1, "bind ls"); 118*3b41d99dSChuck Silvers 119*3b41d99dSChuck Silvers slen = sizeof(sin); 120*3b41d99dSChuck Silvers if (getsockname(ls, (void *)&sin, &slen) < 0) 121*3b41d99dSChuck Silvers err(1, "getsockname"); 122*3b41d99dSChuck Silvers 123*3b41d99dSChuck Silvers if (listen(ls, 5) < 0) 124*3b41d99dSChuck Silvers err(1, "listen ls"); 125*3b41d99dSChuck Silvers 126*3b41d99dSChuck Silvers error = pthread_create(&pt, NULL, server, (void *)(uintptr_t)len); 127*3b41d99dSChuck Silvers if (error) 128*3b41d99dSChuck Silvers errc(1, error, "pthread_create"); 129*3b41d99dSChuck Silvers 130*3b41d99dSChuck Silvers cs = socket(PF_INET, SOCK_STREAM, 0); 131*3b41d99dSChuck Silvers if (cs < 0) 132*3b41d99dSChuck Silvers err(1, "socket cs"); 133*3b41d99dSChuck Silvers 134*3b41d99dSChuck Silvers if (connect(cs, (void *)&sin, sizeof(sin)) < 0) 135*3b41d99dSChuck Silvers err(1, "connect cs"); 136*3b41d99dSChuck Silvers 137*3b41d99dSChuck Silvers while (!accept_done) 138*3b41d99dSChuck Silvers usleep(1000); 139*3b41d99dSChuck Silvers 140*3b41d99dSChuck Silvers if (sendfile(fd, cs, start, len, NULL, NULL, flags) < 0) 141*3b41d99dSChuck Silvers err(3, "sendfile"); 142*3b41d99dSChuck Silvers 143*3b41d99dSChuck Silvers while (!read_done) 144*3b41d99dSChuck Silvers usleep(1000); 145*3b41d99dSChuck Silvers 146*3b41d99dSChuck Silvers exit(0); 147*3b41d99dSChuck Silvers } 148