# Include "stdafx. H"
# Include "proxy. H"
# Include <winsock2.h> // winsocket API 2. 0
# Include <stdlib. h>
# Include <stdio. h>
# Include <string. h>
# Ifdef _ debug
# Define new debug_new
# UNDEF this_file
Static char this_file [] = _ file __;
# Endif
//////////////////////////////////////// /////////////////////////////////////
# Define HTTP "http ://"
# Define FTP "ftp ://"
# Define proxyport 5001 // proxy Port
# Define bufsize 10240 // buffer size
Cwinapp theapp;
Using namespace STD;
Uint proxytoserver (lpvoid pparam );
Uint usertoproxythread (void * pparam );
Struct socketpair {
Socket user_proxy; // socket: Local Machine to proxy service machine
Socket proxy_server; // socket: proxy server to remote host
Bool isuser_proxyclosed; // The status from the local machine to the proxy service machine
Bool isproxy_serverclosed; // proxy server to remote host status
};
Struct proxyparam {
Char Address [256]; // remote host address
Handle user_svrok; // connection status from the proxy server to the remote host
Socketpair * ppair; // maintain a set of socket pointers
Int port; // port used to connect the remote host
}; // This structure is used to exchange information between the proxy server and the remote host.
Socket glisten_socket; // The socket used for listening.
Int startserver () // start the service
{
Wsadata;
Sockaddr_in local;
Socket listen_socket;
If (: wsastartup (0x202, & wsadata )! = 0)
{Printf ("/nerror in startup session./N"); wsacleanup (); Return-1 ;};
Local. sin_family = af_inet;
Local. sin_addr.s_addr = inaddr_any;
Local. sin_port = htons (proxyport );
Listen_socket = socket (af_inet, sock_stream, 0 );
If (listen_socket = invalid_socket)
{Printf ("/nerror in new a socket."); wsacleanup (); Return-2 ;}
If (: BIND (listen_socket, (sockaddr *) & Local, sizeof (local ))! = 0)
{Printf ("/n error in binding socket."); wsacleanup (); Return-3 ;};
If (: Listen (listen_socket, 5 )! = 0)
{Printf ("/n error in listen."); wsacleanup (); Return-4 ;}
Glisten_socket = listen_socket;
Afxbeginthread (usertoproxythread, null); // start listening
Return 1;
}
Int closeserver () // close the service
{
Closesocket (glisten_socket );
Wsacleanup ();
Return 1;
}
// Analyze the received characters to obtain the remote host address
Int getaddressandport (char * STR, char * address, int * port)
{
Char Buf [bufsize], command [512], proto [128], * P;
Int J;
Sscanf (STR, "% S % s", command, Buf, proto );
P = strstr (BUF, HTTP );
// HTTP
If (P)
{
P + = strlen (HTTP );
For (INT I = 0; I <strlen (p); I ++)
If (* (p + I) = '/') break;
* (P + I) = 0;
Strcpy (address, P );
P = strstr (STR, HTTP );
For (Int J = 0; j <I + strlen (HTTP); j ++)
* (P + J) = ''; // remove the remote host name: Get http:/www.csdn.net/http1.1 ==> get/http1.1
* Port = 80; // default http port
}
Else
{// FTP, not supported. The following code can be omitted.
P = strstr (BUF, FTP );
If (! P) return 0;
P + = strlen (FTP );
For (INT I = 0; I <strlen (p); I ++)
If (* (p + I) = '/') break; // get the remote host
* (P + I) = 0;
For (j = 0; j <strlen (p); j ++)
If (* (p + J) = ':')
{* Port = atoi (p + J + 1); // get the port
* (P + J) = 0;
}
Else * Port = 21;
Strcpy (address, P );
P = strstr (STR, FTP );
For (j = 0; j <I + strlen (FTP); j ++)
* (P + J) = '';
}
Return 1;
}
// Obtain local data and send it to the remote host
Uint usertoproxythread (void * pparam)
{
Char buffer [bufsize];
Int Len;
Sockaddr_in from;
Socket msg_socket;
Int fromlen, retval;
Socketpair spair;
Proxyparam proxyp;
Cwinthread * pchildthread;
Fromlen = sizeof (from );
Msg_socket = accept (glisten_socket, (struct sockaddr *) & from, & fromlen );
Afxbeginthread (usertoproxythread, pparam); // start another listener.
If (msg_socket = invalid_socket)
{Printf ("/nerror in accept"); Return-5 ;}
// Read the customer's first line of data
Spair. isuser_proxyclosed = false;
Spair. isproxy_serverclosed = true;
Spair. user_proxy = msg_socket;
Retval = Recv (spair. user_proxy, buffer, sizeof (buffer), 0 );
If (retval = socket_error)
{Printf ("/nerror Recv ");
If (spair. isuser_proxyclosed = false)
{Closesocket (spair. user_proxy );
Spair. isuser_proxyclosed = true;
}
}
If (retval = 0)
{Printf ("client close connection/N ");
If (spair. isuser_proxyclosed = false)
{Closesocket (spair. user_proxy );
Spair. isuser_proxyclosed = true;
}
}
Len = retval;
# Ifdef _ debug
Buffer [Len] = 0;
Printf ("/n received % d bytes, data [% s] From Client/N", retval, buffer );
# Endif
//
Spair. isuser_proxyclosed = false;
Spair. isproxy_serverclosed = true;
Spair. user_proxy = msg_socket;
Proxyp. ppair = & spair;
Proxyp. user_svrok = createevent (null, true, false, null );
Getaddressandport (buffer, proxyp. Address, & proxyp. Port );
Pchildthread = afxbeginthread (proxytoserver, (lpvoid) & proxyp );
: Waitforsingleobject (proxyp. user_svrok, 60000); // wait for join
: Closehandle (proxyp. user_svrok );
While (spair. isproxy_serverclosed = false & spair. isuser_proxyclosed = false)
{
Retval = Send (spair. proxy_server, buffer, Len, 0 );
If (retval = socket_error)
{Printf ("/n send () failed: Error % d/N", wsagetlasterror ());
If (spair. isproxy_serverclosed = false)
{
Closesocket (spair. proxy_server );
Spair. isproxy_serverclosed = true;
}
Continue;
}
Retval = Recv (spair. user_proxy, buffer, sizeof (buffer), 0 );
If (retval = socket_error)
{Printf ("/nerror Recv ");
If (spair. isuser_proxyclosed = false)
{Closesocket (spair. user_proxy );
Spair. isuser_proxyclosed = true;
}
Continue;
}
If (retval = 0)
{Printf ("client close connection/N ");
If (spair. isuser_proxyclosed = false)
{Closesocket (spair. user_proxy );
Spair. isuser_proxyclosed = true;
}
Break;
}
Len = retval;
# Ifdef _ debug
Buffer [Len] = 0;
Printf ("/n received % d bytes, data [% s] From Client/N", retval, buffer );
# Endif
} // End while
If (spair. isproxy_serverclosed = false)
{
Closesocket (spair. proxy_server );
Spair. isproxy_serverclosed = true;
}
If (spair. isuser_proxyclosed = false)
{Closesocket (spair. user_proxy );
Spair. isuser_proxyclosed = true;
}
: Waitforsingleobject (pchildthread-> m_hthread, 20000); // shocould check the return value
Return 0;
}
// Read the remote host data and send it to the local client
Uint proxytoserver (lpvoid pparam ){
Proxyparam * PHA = (proxyparam *) pparam;
Char buffer [bufsize];
Char * SERVER_NAME = "localhost ";
Unsigned short port;
Int retval, Len;
Unsigned int ADDR;
Int socket_type;
Struct sockaddr_in server;
Struct hostent * HP;
Socket conn_socket;
Socket_type = sock_stream;
SERVER_NAME = PHA-> address;
Port = PHA-> port;
If (isalpha (SERVER_NAME [0]) {/* server address is a name */
HP = gethostbyname (SERVER_NAME );
}
Else {/* convert NNN. NNN address to a usable one */
ADDR = inet_addr (SERVER_NAME );
HP = gethostbyaddr (char *) & ADDR, 4, af_inet );
}
If (HP = NULL ){
Fprintf (stderr, "client: cannot resolve Address [% s]: Error % d/N ",
SERVER_NAME, wsagetlasterror ());
: Setevent (PHA-> user_svrok );
Return 0;
}
//
// Copy the resolved information into the sockaddr_in Structure
//
Memset (& server, 0, sizeof (server ));
Memcpy (& (server. sin_addr), HP-> h_addr, HP-> h_length );
Server. sin_family = hp-> h_addrtype;
Server. sin_port = htons (port );
Conn_socket = socket (af_inet, socket_type, 0);/* open a socket */
If (conn_socket <0 ){
Fprintf (stderr, "client: Error opening socket: Error % d/N ",
Wsagetlasterror ());
Ppair> isproxy_serverclosed = true;
: Setevent (PHA-> user_svrok );
Return-1;
}
# Ifdef _ debug
Printf ("Client Connecting to: % s/n", HP-> h_name );
# Endif
If (connect (conn_socket, (struct sockaddr *) & server, sizeof (server ))
= Socket_error ){
Fprintf (stderr, "Connect () failed: % d/N", wsagetlasterror ());
Ppair> isproxy_serverclosed = true;
: Setevent (PHA-> user_svrok );
Return-1;
}
Ppair-> proxy_server = conn_socket;
Ppair> isproxy_serverclosed = false;
: Setevent (PHA-> user_svrok );
// Cook up a string to send
While (! Ppair> isproxy_serverclosed &&! Ppair> isuser_proxyclosed)
{
Retval = Recv (conn_socket, buffer, sizeof (buffer), 0 );
If (retval = socket_error ){
Fprintf (stderr, "Recv () failed: Error % d/N", wsagetlasterror ());
Closesocket (conn_socket );
Ppair> isproxy_serverclosed = true;
Break;
}
Len = retval;
If (retval = 0 ){
Printf ("server closed connection/N ");
Closesocket (conn_socket );
Ppair> isproxy_serverclosed = true;
Break;
}
Retval = Send (Fig-> ppair-> user_proxy, buffer, Len, 0 );
If (retval = socket_error ){
Fprintf (stderr, "Send () failed: Error % d/N", wsagetlasterror ());
Closesocket (Fig-> ppair-> user_proxy );
Ppair-> isuser_proxyclosed = true;
Break;
}
# Ifdef _ debug
Buffer [Len] = 0;
Printf ("received % d bytes, data [% s] from server/N", retval, buffer );
# Endif
}
If (PHA-> ppair-> isproxy_serverclosed = false)
{
Closesocket (PHA-> ppair-> proxy_server );
Ppair> isproxy_serverclosed = true;
}
If (PHA-> ppair-> isuser_proxyclosed = false)
{Closesocket (Fig-> ppair-> user_proxy );
Ppair-> isuser_proxyclosed = true;
}
Return 1;
}
Int _ tmain (INT argc, tchar * argv [], tchar * envp [])
{
Int nretcode = 0;
// Initialize the socket
If (! Afxwininit (: getmodulehandle (null), null,: getcommandline (), 0 ))
{
// Handle errors
Cerr <_ T ("Fatal error: MFC initialization failed") <Endl;
Nretcode = 1;
}
Else
{
// The main program starts.
Startserver ();
While (1)
If (getchar () = 'q') break;
Closeserver ();
}
Return nretcode;
}