/* * transfer.c * The data I/O engine. * * Copyright (c) 2002 Christoph Pfisterer * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "netstrain.h" #include /* settings */ #define BUFSIZE (65536) #define SENDMULT (1) #define SENDBUFSIZE (BUFSIZE*(SENDMULT+1)) #define SENDBUFWRAP (BUFSIZE*SENDMULT) /* internal data */ static unsigned char *sendbuf = NULL; static unsigned char *recvbuf = NULL; static counter_t sendcount = 0; static counter_t recvcount = 0; static int sendoff = 0; static void (*hook)(counter_t, counter_t) = NULL; void transfer_init(void) { int i; if (recvbuf != NULL) return; sendbuf = (unsigned char *)malloc(SENDBUFSIZE); recvbuf = (unsigned char *)malloc(BUFSIZE); if (sendbuf == NULL || recvbuf == NULL) bailout("malloc buffers"); srand(time(NULL)); for (i = 0; i < SENDBUFWRAP; i++) { sendbuf[i] = (unsigned char)(256.0 * rand() / (RAND_MAX+1.0)); } for (; i < SENDBUFSIZE; i++) { sendbuf[i] = sendbuf[i - SENDBUFWRAP]; } sendoff = 0; } void transfer_hook(void (*hookfunc)(counter_t, counter_t)) { hook = hookfunc; } void transfer_run(int sock, int send) { int ret, got; fd_set rfds; fd_set wfds; transfer_init(); if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) bailout("fcntl"); for(;;) { FD_ZERO(&rfds); FD_SET(0, &rfds); FD_SET(sock, &rfds); if (send) { FD_ZERO(&wfds); FD_SET(sock, &wfds); } ret = select(sock + 1, &rfds, send ? &wfds : NULL, NULL, NULL); if (ret < 0 && errno != EINTR) bailout("select"); /* read from console, looking for EOF */ if (FD_ISSET(0, &rfds)) { got = read(0, recvbuf, 1); if (got == 0) { printf("Got EOF from console, shutting down\n"); break; } else if (got < 0) { if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) { bailout("read"); } } } /* read from socket, discarding all data */ if (FD_ISSET(sock, &rfds)) { got = read(sock, recvbuf, BUFSIZE); if (got == 0) { printf("Got EOF from socket, shutting down\n"); break; } else if (got < 0) { if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) { bailout("read"); } } else { recvcount += got; if (hook) (*hook)(sendcount, recvcount); } } /* write garbage to socket */ if (send && FD_ISSET(sock, &wfds)) { got = write(sock, sendbuf + sendoff, BUFSIZE); if (got < 0) { if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) { bailout("write"); } } else if (got > 0) { sendcount += got; sendoff = (sendoff + got) % SENDBUFWRAP; if (hook) (*hook)(sendcount, recvcount); } } } if (close(sock) < 0) bailout("close"); }