https://github.com/iriszero48/PortForwardingServer
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <err.h>
#include <pthread.h>
#include <stdbool.h>
#include <math.h>
#include <arpa/inet.h>
static uint64_t recvCount, sendCount;
void TimePrinter()
{
time_t t = time(NULL);
struct tm* lt = localtime(&t);
fflush(stdout);
printf("[ %d-%d-%d %d:%d:%d ] ", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min,
lt->tm_sec);
}
void Show()
{
while (true)
{
fflush(stdout);
printf("\r\033[k");
printf("recv:%.fkB - send:%.fkB", round(recvCount / 1024.), round(sendCount / 1024.));
sleep(1);
}
}
void Transfer(void* argv)
{
void* buf[1024] = { 0 };
int len;
while ((len = read(((int*)argv)[0], buf, 1024)) > 0)
{
write(((int*)argv)[1], buf, len);
if (((int*)argv)[2]) recvCount += len;
else sendCount += len;
}
close(((int*)argv)[0]);
close(((int*)argv)[1]);
}
int main(const int argc, char* argv[])
{
if (argc != 3) err(1, "Usage: PortForwardingServer UserPort ClientPort.\n");
TimePrinter();
printf("init...\n");
int one = 1;
//User listen
struct sockaddr_in inSerAddr, inCliAddr;
socklen_t socklen = sizeof inCliAddr;
const int inSock = socket(AF_INET, SOCK_STREAM, 0);
if (inSock < 0) err(1, "(in)Can't open socket %d.", ntohs(inSerAddr.sin_port));
setsockopt(inSock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
inSerAddr.sin_family = AF_INET;
inSerAddr.sin_addr.s_addr = INADDR_ANY;
inSerAddr.sin_port = htons(atoi(argv[1]));
if (bind(inSock, (struct sockaddr *)&inSerAddr, sizeof inSerAddr) == -1)
{
close(inSock);
err(1, "(in)Can't bind %d.", ntohs(inSerAddr.sin_port));
}
listen(inSock, 5);
//Client listen
struct sockaddr_in outSerAddr, outCliAddr;
const int outSock = socket(AF_INET, SOCK_STREAM, 0);
if (outSock < 0) err(1, "(out)Can't open socket %d.", ntohs(outSerAddr.sin_port));
setsockopt(outSock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
outSerAddr.sin_family = AF_INET;
outSerAddr.sin_addr.s_addr = INADDR_ANY;
outSerAddr.sin_port = htons(atoi(argv[2]));
if (bind(outSock, (struct sockaddr *)&outSerAddr, sizeof(outSerAddr)) == -1)
{
close(outSock);
err(1, "(out)Can't bind %d.", ntohs(outSerAddr.sin_port));
}
listen(outSock, 5);
//Start log
pthread_t logThread;
if (pthread_create(&logThread, NULL, (void *)&Show, NULL) != 0) perror("(log)Can't create thread");
else
{
TimePrinter();
printf("(log)Thread start.\n");
}
while (true)
{
TimePrinter();
printf("Link start...\n");
//User accept
const int inCliFd = accept4(inSock, (struct sockaddr *)&inCliAddr, &socklen, SOCK_CLOEXEC);
TimePrinter();
printf("(in)Got connection %d.\n", ntohs(inSerAddr.sin_port));
if (inCliFd == -1) perror("(in)Can't accept.");
//Client accept
const int outCliFd = accept4(outSock, (struct sockaddr *)&outCliAddr, &socklen, SOCK_CLOEXEC);
TimePrinter();
printf("(out)Got connection %d.\n", ntohs(outSerAddr.sin_port));
if (outCliFd == -1) perror("(out)Can't accept.");
//Swap data
pthread_t i2oThread, o2iThread2;
void* ret;
int i2o[3] = { inCliFd, outCliFd, false };
int o2i[3] = { outCliFd, inCliFd, true };
if (pthread_create(&i2oThread, NULL, (void *)&Transfer, (void*)i2o) != 0)
perror("(in2out)Can't create thread.");
if (pthread_create(&o2iThread2, NULL, (void *)&Transfer, (void*)o2i) != 0)
perror("(out2in)Can't create thread.");
TimePrinter();
printf("Swaping User-%s:%d <=> Client-%s:%d.\n", inet_ntoa(inCliAddr.sin_addr), ntohs(inCliAddr.sin_port),
inet_ntoa(outCliAddr.sin_addr), ntohs(outCliAddr.sin_port));
if (pthread_join(i2oThread, &ret) != 0) perror("(in2out)Can't join with thread.");
if (pthread_join(o2iThread2, &ret) != 0) perror("(out2in)Can't join with thread.");
TimePrinter();
printf("Drop.\n");
}
}