/*
* 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 <fcntl.h>
/* 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");
}
syntax highlighted by Code2HTML, v. 0.9.1