//************************************************************************************
// 功能:监听本地1080端口数据,进行代理转发
// 服务端:可采用squid进行HTTP代理
// Socket Transmit to Socket
//
//************************************************************************************

// stdafx.h : 定义头文件。
//

#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <errno.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#pragma comment(lib,"WS2_32")


#define TIMEOUT 300
#define MAXSIZE 20480
#define HOSTLEN 40
#define CONNECTNUM 5

#define PROXY_HOST "192.168.5.136"
#define PROXY_PORT 3128





// proxy.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

struct transocket
{
	SOCKET fd1;
	SOCKET fd2;
};

//************************************************************************************
// 
// Socket Transmit to Socket
//
//************************************************************************************
DWORD WINAPI transmitdata(LPVOID data)
{
	SOCKET fd1, fd2;
	transocket *sock;
	struct timeval timeset;
	fd_set readfd, writefd;
	int result, i = 0;
	char read_in1[MAXSIZE], send_out1[MAXSIZE];
	char read_in2[MAXSIZE], send_out2[MAXSIZE];
	int read1 = 0, totalread1 = 0, send1 = 0;
	int read2 = 0, totalread2 = 0, send2 = 0;
	int sendcount1, sendcount2;
	int maxfd;
	int structsize1, structsize2;
	char host1[20], host2[20];
	int port1 = 0, port2 = 0;
	char tmpbuf[100];

	sock = (transocket *)data;
	fd1 = sock->fd1;
	fd2 = sock->fd2;

	memset(host1, 0, 20);
	memset(host2, 0, 20);
	memset(tmpbuf, 0, 100);

	structsize1 = sizeof(struct sockaddr);
	structsize2 = sizeof(struct sockaddr);

	maxfd = max(fd1, fd2) + 1;
	memset(read_in1, 0, MAXSIZE);
	memset(read_in2, 0, MAXSIZE);
	memset(send_out1, 0, MAXSIZE);
	memset(send_out2, 0, MAXSIZE);

	timeset.tv_sec = TIMEOUT;
	timeset.tv_usec = 0;

	while (1)
	{
		FD_ZERO(&readfd);
		FD_ZERO(&writefd);

		FD_SET((UINT)fd1, &readfd);
		FD_SET((UINT)fd1, &writefd);
		FD_SET((UINT)fd2, &writefd);
		FD_SET((UINT)fd2, &readfd);

		result = select(maxfd, &readfd, &writefd, NULL, &timeset);
		if ((result<0) && (errno != EINTR))
		{
			break;
		}
		else if (result == 0)
		{
			break;
		}

		if (FD_ISSET(fd1, &readfd))
		{
			/* must < MAXSIZE-totalread1, otherwise send_out1 will flow */
			if (totalread1 < MAXSIZE

				) {
				read1 = recv(fd1, read_in1, MAXSIZE - totalread1, 0);
				if ((read1 == SOCKET_ERROR) || (read1 == 0))
				{
					break;
				}

				memcpy(send_out1 + totalread1, read_in1, read1);
				totalread1 += read1;
				memset(read_in1, 0, MAXSIZE);
			}
		}

		if (FD_ISSET(fd2, &writefd))
		{
			int err = 0;
			sendcount1 = 0;
			while (totalread1>0)
			{
				send1 = send(fd2, send_out1 + sendcount1, totalread1, 0);
				if (send1 == 0)break;
				if ((send1<0) && (errno != EINTR))
				{
					err = 1;
					break;
				}

				if ((send1<0) && (errno == ENOSPC)) break;
				sendcount1 += send1;
				totalread1 -= send1;
			}

			if (err == 1) break;
			if ((totalread1>0) && (sendcount1>0))
			{
				memcpy(send_out1, send_out1 + sendcount1, totalread1);
				memset(send_out1 + totalread1, 0, MAXSIZE - totalread1);
			}
			else
				memset(send_out1, 0, MAXSIZE);
		}

		if (FD_ISSET(fd2, &readfd))
		{
			if (totalread2 < MAXSIZE

				) {
				read2 = recv(fd2, read_in2, MAXSIZE - totalread2, 0);
				if (read2 == 0)break;
				if ((read2<0) && (errno != EINTR))
				{
					break;
				}

				memcpy(send_out2 + totalread2, read_in2, read2);
				totalread2 += read2;
				memset(read_in2, 0, MAXSIZE);
			}
		}

		if (FD_ISSET(fd1, &writefd))
		{
			int err2 = 0;
			sendcount2 = 0;
			while (totalread2>0)
			{
				send2 = send(fd1, send_out2 + sendcount2, totalread2, 0);
				if (send2 == 0)break;
				if ((send2<0) && (errno != EINTR))
				{
					err2 = 1;
					break;
				}
				if ((send2<0) && (errno == ENOSPC)) break;
				sendcount2 += send2;
				totalread2 -= send2;
			}
			if (err2 == 1) break;
			if ((totalread2>0) && (sendcount2 > 0))
			{
				memcpy(send_out2, send_out2 + sendcount2, totalread2);
				memset(send_out2 + totalread2, 0, MAXSIZE - totalread2);
			}
			else
				memset(send_out2, 0, MAXSIZE);
		}
	}

	closesocket(fd1);
	closesocket(fd2);
	return 0;
}

DWORD WINAPI ThreadNewConnect(LPVOID lpParam)
{
	transocket sock;
	sock.fd1 = *(SOCKET *)lpParam;


	//连接远程服务器
	sock.fd2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (sock.fd2 == INVALID_SOCKET)
	{
		printf("远程 socket 错误代码:%d\n", WSAGetLastError());
		closesocket(sock.fd1);
		return 0;
	}

	sockaddr_in conn_sin;
	conn_sin.sin_family = AF_INET;
	InetPton(AF_INET, TEXT(PROXY_HOST), &conn_sin.sin_addr.s_addr);
	conn_sin.sin_port = htons(PROXY_PORT);

	if (connect(sock.fd2, (SOCKADDR*)&conn_sin, sizeof(conn_sin)) == SOCKET_ERROR)
	{
		printf("连接代理服务器 错误代码:%d\n", WSAGetLastError());
		closesocket(sock.fd1);
		closesocket(sock.fd2);
		return 0;
	}
	

	DWORD dwThreadID;
	HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)transmitdata, (LPVOID)&sock, 0, &dwThreadID);

	struct sockaddr_in local_sin;
	int structsize1 = sizeof(struct sockaddr);
	getpeername(sock.fd1, (struct sockaddr *)&local_sin, &structsize1);
	char localip[20], connip[20];
	inet_ntop(AF_INET, (void*)&local_sin.sin_addr, localip, 16);
	inet_ntop(AF_INET, (void*)&conn_sin.sin_addr, connip, 16);
	printf("开始数据双向传送%s:%d <-----> %s:%d\n", localip, local_sin.sin_port, connip , conn_sin.sin_port);
	
	WaitForSingleObject(hThread , -1);
	printf("----------------------------------------\n\n线程结束 线程id:%d\n\n----------------------------------------\n\n", GetCurrentThreadId());
	return 0;
}

int main()
{
	WSADATA wsaData;
	int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != NO_ERROR)
	{
		printf("WSAStartup 错误代码:%d\n", WSAGetLastError());
		WSACleanup();
		return 0;
	}

	SOCKET hLocalSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (hLocalSocket == INVALID_SOCKET)
	{
		printf("本地socket 错误代码:%d\n", WSAGetLastError());
		WSACleanup();
		return 0;
	}
	sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(1080);
	sin.sin_addr.S_un.S_addr = INADDR_ANY;
	if (bind(hLocalSocket, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
	{
		printf("绑定本地端口 错误代码:%d\n", WSAGetLastError());
		WSACleanup();
		return 0;
	}


	if (listen(hLocalSocket, 1024) == SOCKET_ERROR)
	{
		printf("监听本地端口 错误代码:%d\n", WSAGetLastError());
		WSACleanup();
		return 0;
	}

	sockaddr_in remoteAddr;
	int nAddrLen = sizeof(remoteAddr);
	while (1)
	{
		SOCKET Srev1 = accept(hLocalSocket, (SOCKADDR *)&remoteAddr, &nAddrLen);
		DWORD dwThreadId = 0;
		HANDLE hThread = CreateThread(NULL, 0, ThreadNewConnect, (void*)&Srev1, 0, &dwThreadId);
		printf("----------------------------------------\n\n新连接,线程ID:%d\n\n----------------------------------------\n\n", dwThreadId);
	}
	closesocket(hLocalSocket);
	WSACleanup();
}