Path: blob/main/tools/regression/netinet/tcpstream/tcpstream.c
39491 views
/*-1* Copyright (c) 2004 Robert N. M. Watson2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526/*27* tcpstream sets up a simple TCP client and server, and then streams a28* predictable pseudo-random byte sequence through it using variable block29* sizes. The intent is to detect corruption of data in the TCP stream.30*/3132#include <sys/types.h>33#include <sys/errno.h>34#include <sys/socket.h>3536#include <netinet/in.h>3738#include <arpa/inet.h>3940#include <err.h>41#include <errno.h>42#include <stdio.h>43#include <stdlib.h>44#include <string.h>45#include <unistd.h>4647#define MAX_LOOPS 1024048#define MAX_LONGS 10244950static void51usage(void)52{5354fprintf(stderr, "tcpstream client [ip] [port] [seed]\n");55fprintf(stderr, "tcpstream server [port] [seed]\n");56exit(-1);57}5859static void60fill_buffer(long *buffer, int len)61{62int i;6364for (i = 0; i < len; i++)65buffer[i] = htonl(random());66}6768static int69check_buffer(long *buffer, int len)70{71int i;7273for (i = 0; i < len; i++) {74if (buffer[i] != htonl(random()))75return (0);76}77return (1);78}7980static void81tcpstream_client(struct sockaddr_in sin, long seed)82{83long buffer[MAX_LONGS];84ssize_t len;85int i, j, sock;8687srandom(seed);8889sock = socket(PF_INET, SOCK_STREAM, 0);90if (sock == -1)91errx(-1, "socket: %s", strerror(errno));9293if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) == -1)94errx(-1, "connect: %s", strerror(errno));9596for (j = 0; j < MAX_LOOPS; j++) {97for (i = 0; i < MAX_LONGS; i++) {98fill_buffer(buffer, i);99len = send(sock, buffer, i * sizeof(long), 0);100if (len == -1) {101printf("%d bytes written of %d expected\n",102len, i * sizeof(long));103fflush(stdout);104perror("send");105goto done;106}107}108}109110done:111close(sock);112}113114static void115tcpstream_server(struct sockaddr_in sin, long seed)116{117int i, j, listen_sock, accept_sock;118struct sockaddr_in other_sin;119long buffer[MAX_LONGS];120socklen_t addrlen;121ssize_t len;122123int input_byte_counter;124125listen_sock = socket(PF_INET, SOCK_STREAM, 0);126if (listen_sock == -1)127errx(-1, "socket: %s", strerror(errno));128129if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) == -1)130errx(-1, "bind: %s", strerror(errno));131132if (listen(listen_sock, -1) == -1)133errx(-1, "listen: %s", strerror(errno));134135while (1) {136bzero(&other_sin, sizeof(other_sin));137addrlen = sizeof(other_sin);138139accept_sock = accept(listen_sock, (struct sockaddr *)140&other_sin, &addrlen);141if (accept_sock == -1) {142perror("accept");143continue;144}145printf("connection opened from %s:%d\n",146inet_ntoa(other_sin.sin_addr), ntohs(other_sin.sin_port));147input_byte_counter = 0;148149srandom(seed);150151for (j = 0; j < MAX_LOOPS; j++) {152for (i = 0; i < MAX_LONGS; i++) {153len = recv(accept_sock, buffer,154i * sizeof(long), MSG_WAITALL);155if (len != i * sizeof(long)) {156perror("recv");157goto done;158}159if (check_buffer(buffer, i) == 0) {160fprintf(stderr,161"Corruption in block beginning %d and ending %d\n", input_byte_counter,162input_byte_counter + len);163fprintf(stderr,164"Block size %d\n", i * sizeof(long));165goto done;166}167input_byte_counter += len;168}169}170done:171printf("connection closed\n");172close(accept_sock);173}174}175176int177main(int argc, char *argv[])178{179struct sockaddr_in sin;180long port, seed;181char *dummy;182183if (argc < 2)184usage();185if (strcmp(argv[1], "client") == 0) {186if (argc != 5)187usage();188189bzero(&sin, sizeof(sin));190sin.sin_len = sizeof(sin);191sin.sin_family = AF_INET;192193if (inet_aton(argv[2], &sin.sin_addr) != 1)194errx(-1, "%s: %s", argv[2], strerror(EINVAL));195196port = strtoul(argv[3], &dummy, 10);197if (port < 1 || port > 65535 || *dummy != '\0')198usage();199sin.sin_port = htons(port);200201seed = strtoul(argv[4], &dummy, 10);202if (*dummy != '\0')203usage();204205tcpstream_client(sin, seed);206207} else if (strcmp(argv[1], "server") == 0) {208if (argc != 4)209usage();210211bzero(&sin, sizeof(sin));212sin.sin_len = sizeof(sin);213sin.sin_family = AF_INET;214sin.sin_addr.s_addr = INADDR_ANY;215216port = strtoul(argv[2], &dummy, 10);217if (port < 1 || port > 65535 || *dummy != '\0')218usage();219sin.sin_port = htons(port);220221seed = strtoul(argv[3], &dummy, 10);222if (*dummy != '\0')223usage();224225tcpstream_server(sin, seed);226} else227usage();228229return (0);230}231232233