C++ Proxy

Hi. I would like to make a c++ proxy, but I have no idea where to start. I know most web browsers use port 80, but I don't know exactly what it does there. Any help is appreciated. Thanks!
port 80 is for HTTP traffic.
Nevermind. I figured it out. Thanks!
I'm curious OP, what exactly did you figure out here? What did you come up with?
The codes to long to put here, so i'll PM you.
Ok, its to long to pm so i'll post it in parts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#include "stdafx.h"
#include "winsock2.h"
#include <process.h>
#include <iostream>
#include <string>
#include <queue>
using namespace std;

#define SPACE_CHAR  ' '
int PROXY_PORT = 5555;
#define RESPONSE_BUFFER_SIZE 19192
#define MAX_THREADS		300

queue<SOCKET> socketBuffer;
HANDLE queueMutex;
HANDLE threadSymaphore;

SYSTEM_INFO sysInfo;

void GetTarget(const char* request,string& host, string& port);
string GetTargetResponse(int threadid, const char* TargetURL, const char* Port, const char* request,SOCKET& output);

void InitSockAddr(struct sockaddr_in& sockAddr, short family, unsigned long addr, unsigned short port)
{
	sockAddr.sin_family=family;
	sockAddr.sin_addr.s_addr=addr;
	sockAddr.sin_port=port;

};

unsigned __stdcall RequestThread( void * arg )
{
	int *Arg=(int*)arg;
	int tid=*Arg;
	while(true)
	{

	   SOCKET ioSock;

		WaitForSingleObject(queueMutex,INFINITE);
		
		if(socketBuffer.size()<1)
		{
			ReleaseMutex(queueMutex);
			continue;
		}

		try
		{
		ioSock=socketBuffer.front();
		socketBuffer.pop();
		ReleaseMutex(queueMutex);
		}catch(exception)
		{
			ReleaseMutex(queueMutex);
			continue;
		}

		try{

		const int bufferSize=1024;
		char buf[bufferSize];
		memset(buf,0,bufferSize);
		
		string data="";

		int recvLen=recv(ioSock,buf,bufferSize-1,0);
		if(recvLen<=0)
		{
			return 0;
		}
		data+=buf;

		while(recvLen>=bufferSize-1)
		{
			memset(buf,0,bufferSize);
			recvLen=recv(ioSock,buf,bufferSize-1,0);
			data+=buf;
		}

		string targetURL="";
		string Port="";
		GetTarget(data.c_str(),targetURL,Port);

		GetTargetResponse(tid,targetURL.c_str(),Port.c_str(),data.c_str(),ioSock);
		shutdown(ioSock,2);
		closesocket(ioSock);
		cout<<"Thread "<<tid<<" socket closed"<<endl;
		} catch(exception)
		{
			shutdown(ioSock,2);
			closesocket(ioSock);
		}
	}
		return 1;

}



void GetTarget(const char* request,string& host,string& port)
{
	host="";
	port="";

	//skip the first HTTP command
	while(*request!=' ')
	{
		++request;
	}
	//skip space
	while( (*request<'a' || *request>'z') && (*request<'A' || *request>'Z') )
				++request;
	const char* urlStart=request;

	if(    (*request=='H' || *request=='h')
		&& (*request=='T' || *request=='t')
		&& (*request=='T' || *request=='t')
		&& (*request=='P' || *request=='p')
		&& (*request==':')
		)
	{
		while(SPACE_CHAR==*request)
			++request;

		while(SPACE_CHAR!=*request && ':'!=*request && '\0'!=*request && '\r'!=*request && '\n'!=*request)
		{
			host+=*request;
			++request;
		}
		if(':'==*request)
		{
			while(SPACE_CHAR!=*request && ':'!=*request && '\0'!=*request && '\r'!=*request && '\n'!=*request)
			{
				port+=*request;
				++request;
			}
		}
		if(port.length()==0)
			port="80";

		return;
	}

	while(*request!='\0')
	{
		//Process "Host: "
		if(*request=='\n' && *(request+1)=='H' && *(request+2)=='o' && *(request+3)=='s' && *(request+4)=='t' && *(request+5)==':')
		{
			request+=6;

			while( (*request<'a' || *request>'z') && (*request<'A' || *request>'Z') )
				++request;
			//find host address in "Host: "
			while( *request!=SPACE_CHAR && *request!='\t' && *request!='\r' && *request!='\n' && *request!='\0' && *request!=':')
			{
				host+=*request;
				++request;
			}
			//find port number in "Host: "
			if(*request==':')
			{
				while( *request!=SPACE_CHAR && *request!='\t' && *request!='\r' && *request!='\n' && *request!='\0')
				{
					port+=*request;
					++request;
				}
			}
			break;
		}
		++request;
	}

	if(host.length()>0 && port.length()==0)
	{
		while(SPACE_CHAR!=*urlStart)
		{
			if(':'==*urlStart)
			{
				++urlStart;
				while(SPACE_CHAR!=*urlStart && '/'!=*urlStart && '\\'!=*urlStart)
					port+=*urlStart++;
				break;
			}
			++urlStart;
		}

		if(port.length()==0)
			port="80";

		return;
	}

}

bool isConnectionAlive(const char* buffer,int len)
{
	int count=0;
	while(count<len && *buffer!='\0')
	{
		if(0==strncmp(buffer,"\nConnection:",strlen("\nConnection:")))
		{
			buffer+=strlen("\nConnection:")+1;
			while(SPACE_CHAR==*buffer)
				++buffer;

			if( 0==strncmp(buffer,"Close",strlen("Close") ))
				return false;

			return true;
		}
		++buffer;
	}

	return true;
}

DWORD Receive(SOCKET& requestSock,WSABUF& proxyRecvBuf,WSAOVERLAPPED& proxyRecvOverlapped,DWORD& Flag,DWORD timeOut,bool wait)
{
		DWORD nRead=0;

		int ret=WSARecv(requestSock,&proxyRecvBuf,1,&nRead,&Flag,&proxyRecvOverlapped,NULL);

		if(ret==SOCKET_ERROR && (WSA_IO_PENDING!=WSAGetLastError()))
		{
			cout<<"Error when receiving"<<endl;
			return SOCKET_ERROR;
		}
		ret=WSAWaitForMultipleEvents(1,&proxyRecvOverlapped.hEvent,TRUE,timeOut,TRUE);

		if(WAIT_FAILED==ret)
		{
			cout<<"wait failed"<<endl;
			return SOCKET_ERROR;
		}

		ret=WSAGetOverlappedResult(requestSock,&proxyRecvOverlapped,&nRead,wait,&Flag);
/*
		if(FALSE==ret)
		{
			cout<<"receiving from overlapped fail"<<endl;
			return SOCKET_ERROR;
		}
*/
		return nRead;
}

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
string GetTargetResponse(int threadid,const char* TargetURL, const char* Port, const char* request,SOCKET& output)
{
	SOCKET requestSock;
	SOCKADDR_IN clientAddr;
	struct hostent *pHost;	
	bool keepAlive=false;

	requestSock=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
	pHost=gethostbyname(TargetURL);

	memset(&clientAddr,0,sizeof(clientAddr));

	int addrLen=sizeof(clientAddr);
	
	clientAddr.sin_family=AF_INET;
	
	memcpy(&clientAddr.sin_addr,pHost->h_addr, pHost->h_length);
	clientAddr.sin_port=htons(atoi(Port));

	if(0!=connect(requestSock,(SOCKADDR *)&clientAddr, sizeof(SOCKADDR_IN)))
	{
		closesocket(requestSock);
		return "";
	}
	
	WSAOVERLAPPED SendOverlapped;
	DWORD Flag=0;
	DWORD nSend=0;
	WSABUF clientRequestBuf;
	WSAEVENT sendEvent[1];

	clientRequestBuf.buf=(char*)request;
	clientRequestBuf.len=strlen(request);
	
	sendEvent[0]=WSACreateEvent();
	SendOverlapped.hEvent=sendEvent[0];

	int ret=WSASend(requestSock,&clientRequestBuf,1,&nSend,Flag,&SendOverlapped,NULL);

		if(ret==SOCKET_ERROR && (WSA_IO_PENDING!=WSAGetLastError()))
		{
			cout<<"Error when receiving"<<endl;
			return "";
		}

	DWORD nRead=0;
	const int bufferSize=RESPONSE_BUFFER_SIZE;
	char buf[bufferSize];
	char sendBuf[bufferSize];
	memset(buf,0,bufferSize);
	memset(sendBuf,0,bufferSize);
	string message="";

	WSAOVERLAPPED proxyResponseOverlapped,proxyRecvOverlapped;
	WSABUF proxyResponseBuf, proxyRecvBuf;
	WSAEVENT proxySendEvent[1],proxyRecvEvent[1];
	proxyResponseBuf.buf=sendBuf;
	proxyResponseBuf.len=bufferSize;
	proxyRecvBuf.buf=buf;
	proxyRecvBuf.len=bufferSize;


	proxySendEvent[0]=WSACreateEvent();
	proxyResponseOverlapped.hEvent=proxySendEvent[0];
	proxyRecvEvent[0]=WSACreateEvent();
	proxyRecvOverlapped.hEvent=proxyRecvEvent[0];
	
	int DATA_SIZE=bufferSize-1;
	int recvLen=0;

	::WSAWaitForMultipleEvents(1,sendEvent,FALSE,WSA_INFINITE,FALSE);
	
	ret=WSAGetOverlappedResult(requestSock,&SendOverlapped,&nSend,FALSE,&Flag);

//	nRead=Receive(requestSock,proxyRecvBuf,proxyRecvOverlapped,Flag,WSA_INFINITE,FALSE);
	nRead=recv(requestSock,proxyRecvBuf.buf,bufferSize,0);

	keepAlive=isConnectionAlive(proxyRecvBuf.buf,nRead);

	if(!keepAlive)
	{
			do
			{
				cout<<"Thread "<<threadid<<" [Connection:Closed]: "<<nRead<<endl;
					memcpy(sendBuf,buf,bufferSize);
//					WSASend(output,&proxyResponseBuf,1,&nSend,Flag,&proxyResponseOverlapped,NULL);
					send(output,sendBuf,nRead,0);
//					memset(buf,0,bufferSize);
					nRead=Receive(requestSock,proxyRecvBuf,proxyRecvOverlapped,Flag,WSA_INFINITE,FALSE);
//					nRead=recv(requestSock,buf,bufferSize,0);					
					if(0==nRead || SOCKET_ERROR==nRead)			
					{
						cout<<"socket error"<<endl;
						break;
					}

			}while(true);
	}
	else
	{
			do
			{
 				cout<<"Thread "<<threadid<<" [Connection:keep-alive]: "<<nRead<<endl;
					memcpy(sendBuf,buf,bufferSize);
//					WSASend(output,&proxyResponseBuf,1,&nSend,Flag,&proxyResponseOverlapped,NULL);
					send(output,sendBuf,nRead,0);

					memset(buf,0,bufferSize);
					nRead=Receive(requestSock,proxyRecvBuf,proxyRecvOverlapped,Flag,1000,FALSE);
					
					if(0==nRead || SOCKET_ERROR==nRead)			
					{
						cout<<"socket error"<<endl;
						break;
					}

			}while(true);
	}

		cout<<"close socket"<<endl;
		closesocket(requestSock);

		return "";

}

void RunServer()
{
	WSAData wsaData;
	if(WSAStartup(MAKEWORD(2,0),&wsaData)!=0)
	{
		cout<<"init failed"<<endl;
		return;
	}

	WSABUF dataBuf;
	WSAOVERLAPPED serverOverlapped;

	SOCKET serverSock, ioSock;
	SOCKADDR_IN serverAddr, clientAddr;
	memset(&serverAddr,0,sizeof(serverAddr));
	memset(&clientAddr,0,sizeof(clientAddr));

	int addrLen=sizeof(clientAddr);
	
//	InitSockAddr(serverAddr,AF_INET,htonl(INADDR_ANY),6666);
//	InitSockAddr(serverAddr,AF_INET,inet_addr("127.0.0.1"),6666);

//	serverSock=socket(AF_INET,SOCK_STREAM,0);
	serverSock=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);

	 if (serverSock == INVALID_SOCKET) 
     {
		   cout<<"invalid socket"<<endl;
           return;
      }

	 serverAddr.sin_family=AF_INET;
	 serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	 serverAddr.sin_port=htons(PROXY_PORT);
	
	if(SOCKET_ERROR==bind(serverSock, (SOCKADDR *)&serverAddr, sizeof(serverAddr)))
	{
		cout<<"cannot bind to socket:"<<endl;
		return;
	}
	
	if(listen(serverSock,5))
	{
		cout<<"listen failed"<<endl;
		return;
	}

	char localHostName[255];
	hostent *local_ent=NULL;
	in_addr local_addr;
	string hostIP="";
	if(gethostname(localHostName,sizeof(localHostName))==SOCKET_ERROR)
	{
		memset(localHostName,0,sizeof(localHostName));
	}
	else
	{
			local_ent=gethostbyname(localHostName);
			int i=0;
			while(local_ent->h_addr_list[i])
			{
				if(i>0)
				{
					hostIP+='.';
				}
				memcpy(&local_addr,local_ent->h_addr_list[i],sizeof(local_addr));
				hostIP+=inet_ntoa(local_addr);
				++i;
			}
	}

	cout<<"start http proxy server at "<<hostIP<<":"<<PROXY_PORT<<endl;

	queueMutex=CreateMutex(NULL,FALSE,NULL);
//	threadSymaphore=CreateSemaphore(NULL,50,50,NULL);
	fd_set fdread;
	int ret;
	const int ThreadNumber=MAX_THREADS;
	int threadArg[ThreadNumber];
	HANDLE threads[ThreadNumber];
	unsigned int threadId[ThreadNumber];

	for(int i=0;i<ThreadNumber;++i)
	{
		threadArg[i]=i;
		threads[i]=(HANDLE)_beginthreadex(NULL,0,RequestThread,&threadArg[i],0,&threadId[i]);
	}

	while(true)
	{
//		ioSock=accept(serverSock,(sockaddr*) &serverAddr,&addrLen);
		ioSock=accept(serverSock,NULL,NULL);
		
			WaitForSingleObject(queueMutex,INFINITE);
			socketBuffer.push(ioSock);
			ReleaseMutex(queueMutex);

//			WaitForSingleObject(threadSymaphore,INFINITE);
//			HANDLE thread=(HANDLE)_beginthreadex(NULL,0,RequestThread,&threadArg,0,&threadId);
//		    ::ReleaseSemaphore(threadSymaphore,1,NULL);
	//		RequestThread();
	}


	shutdown(serverSock,2);
	closesocket(serverSock);
	WSACleanup();
}

int main(int argc, char** argv)
{
	GetSystemInfo(&sysInfo);

	cout<<"HTTP Proxy Server"<<endl;
	cout<<"Number of Threads:"<<MAX_THREADS<<endl;

	RunServer();
	
	return 0;
}
Last edited on
Thats one hell of a file :) Seeing this makes me drool. :)

Good job sire.
Thanks.
Topic archived. No new replies allowed.