| /* |
| * 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; |
| } |