#include #include #include #include #include #include #include #include #include #include #include #include #include static const char *name; typedef struct { int sock_fd; const char *remote_host; const char *remote_port; } ThreadArg; static void Error(const char *call) { fprintf(stderr, "%s:", name); perror(call); exit(EXIT_FAILURE); } static int Connect(const char *n, const char *p) { struct addrinfo *addr, *addr_p; struct addrinfo hints = {0}; int status; int sock = -1; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; status = getaddrinfo(n, p, &hints, &addr); if (status) { fprintf(stderr, "%s: %s\n", name, gai_strerror(status)); exit(EXIT_FAILURE); } for(addr_p = addr; addr_p && sock == -1; addr_p = addr_p->ai_next) { sock = socket(addr_p->ai_family, addr_p->ai_socktype, addr_p->ai_protocol); if (sock != -1) { if (connect(sock, addr_p->ai_addr, addr_p->ai_addrlen) == -1) { close(sock); sock = -1; } } } if (sock == -1) { fprintf(stderr, "%s: Failed to connect to %s:%s\n", name, n, p); exit(EXIT_FAILURE); } return sock; } static int Server(int p) { struct sockaddr_in addr; int sock_fd; if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { Error("socket"); } /* Bind port to address */ addr.sin_family=AF_INET; addr.sin_addr.s_addr=INADDR_ANY; addr.sin_port=htons(p); if (bind(sock_fd,(void*)&addr,sizeof(addr))==-1) { Error("bind"); } if (listen(sock_fd,5)==-1) { Error("listen"); } return sock_fd; } static void *ThreadCode(void *arg) { int fd; ThreadArg *ta = arg; struct pollfd fds[2] = {0}; int done = 0; fd = Connect(ta->remote_host, ta->remote_port); fds[0].fd = ta->sock_fd; fds[0].events = POLLRDNORM; fds[1].fd = fd; fds[1].events = POLLRDNORM; while(!done) { int f; if (poll(fds, 2, -1) == -1) { Error("poll"); } for(int f = 0; f < 2; f++) { if (fds[f].revents & POLLRDNORM) { char buff[1024]; int rd; if ((rd = read(fds[f].fd, buff, sizeof buff)) < 1) { done = 1; } else { write(fds[f ^ 1].fd, buff, rd); } } } } close(ta->sock_fd); close(fd); free(ta); return NULL; } int main(int argc, char *argv[]) { struct sockaddr_in addr; char buff[1025]; int len; socklen_t addrlen; int sock_fd; int connect_fd; name=argv[0]; if (argc != 4) { fprintf(stderr,"%s: usage %s local_port remote_address remote_port\n", name, name); exit(1); } sock_fd = Server((short)atoi(argv[1])); printf("%s: socket bound\n",name); while(1) { pthread_t thread; ThreadArg *arg; printf("%s: accepting\n",name); if ((connect_fd=accept(sock_fd,NULL,0))==-1) { Error("accept"); } if (!(arg = malloc(sizeof *arg))) { Error("malloc"); } arg->sock_fd = connect_fd; arg->remote_host = argv[2]; arg->remote_port = argv[3]; pthread_create(&thread, NULL, ThreadCode, arg); pthread_detach(thread); } return EXIT_SUCCESS; }