blob: e6de96c00f263b80e14b07d5c6ff666a17a27dff [file] [log] [blame] [raw]
/*
* Copyright 2015-2017 Rivoreo
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
//#include "common.h"
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
//#include "syncrw.h"
#include <stdio.h>
#include <errno.h>
#ifndef MAX
#define MAX(A,B) ((A)>(B)?(A):(B))
#endif
static int send_chunk(int wfd, int rfd) {
//fprintf(stderr, "function: send_chunk(%d, %d)\n", wfd, rfd);
char buffer[4096];
int rs;
do {
rs = read(rfd, buffer, sizeof buffer);
} while(rs < 0 && errno == EINTR);
if(rs < 0) return -1;
if(!rs) return 0;
int wss = 0;
do {
int ws = write(wfd, buffer + wss, rs - wss);
if(ws < 0) {
if(errno == EINTR) continue;
return -1;
}
wss += ws;
} while(wss < rs);
return wss;
}
int forward(int fd1, int fd2) {
//fprintf(stderr, "function: forward(%d, %d)\n", fd1, fd2);
fd_set fdset;
int max_fd = MAX(fd1, fd2);
int fd1_eof = 0, fd2_eof = 0;
do {
FD_ZERO(&fdset);
if(!fd1_eof) FD_SET(fd1, &fdset);
if(!fd2_eof) FD_SET(fd2, &fdset);
switch(select(max_fd + 1, &fdset, NULL, NULL, NULL)) {
case -1:
if(errno == EINTR) continue;
perror("select");
return -1;
case 0:
continue;
default:
if(FD_ISSET(fd1, &fdset)) {
switch(send_chunk(fd2, fd1)) {
case -1:
return -1;
case 0:
fd1_eof = 1;
break;
}
} else if(FD_ISSET(fd2, &fdset)) {
switch(send_chunk(fd1, fd2)) {
case -1:
return -1;
case 0:
fd2_eof = 1;
break;
}
}
}
//} while(!fd1_eof || !fd2_eof);
} while(!fd1_eof && !fd2_eof);
return 0;
}