Sogou proxy server program, which has been implemented using Python on the Internet. This version has poor performance in some cases (such as thunder download), so I used C ++ to implement a version developed based on the POCO framework, it should have good portability (change the _ snprintf function name ). The complete source code is as follows:
[Cpp]
# Include <stdio. h>
# Include <time. h>
# Include <vector>
# Include <string>
# Include <Poco/ErrorHandler. h>
# Include <Poco/Net/Socket. h>
# Include <Poco/Net/HTTPServer. h>
# Include <Poco/Net/HTTPServerRequest. h>
# Include <Poco/Net/HTTPServerRequestImpl. h>
# Include <Poco/Net/HTTPServerResponse. h>
# Include <Poco/Net/HTTPRequestHandler. h>
# Include <Poco/Net/HTTPClientSession. h>
Using namespace std;
Using namespace Poco;
Using namespace Poco: Net;
Class EH: public ErrorHandler
{
Virtual void exception (const Exception & exc)
{
Printf ("% s: % s \ n", exc. what (), exc. message (). c_str ());
}
Virtual void exception (const std: exception & exc)
{
Printf ("% s \ n", exc. what ());
}
Virtual void exception ()
{
Printf ("Unknown exception \ n ");
}
};
Const int BUFFER_SIZE = 65536;
Class ProxyService: public HTTPRequestHandler
{
HTTPClientSession client;
Static unsigned int hashTag (const string & s)
{
Unsigned int code = s. length ();
For (int I = 0; I <s. length ()/4; ++ I)
{
Unsigned int a = (s [I * 4] & 0 xffu) + (s [I * 4 + 1] & 0 xffu) <8 );
Unsigned int B = (s [I * 4 + 2] & 0 xffu) + (s [I * 4 + 3] & 0 xffu) <8 );
Code + =;
Code ^ = (code <5) ^ B) <0xb;
Code + = code> 0xb;
}
Switch (s. length () % 4)
{
Case 1:
Code + = s [s. length ()-1] & 0 xffu;
Code ^ = code <0xa;
Code + = code> 1;
Break;
Case 2:
Code + = (s [s. length ()-2] & 0 xffu) + (s [s. length ()-1] & 0 xffu) <8 );
Code ^ = code <0xb;
Code + = code> 0x11;
Break;
Case 3:
Code + = (s [s. length ()-3] & 0 xffu) + (s [s. length ()-2] & 0 xffu) <8 );
Code ^ = (code ^ (s [s. length ()-1] & 0 xffu) <2) <0x10;
Code + = code> 0xb;
Break;
}
Code ^ = code <3;
Code + = code> 5;
Code ^ = code <4;
Code + = code> 0x11;
Code ^ = code <0x19;
Code + = code> 6;
Return code;
}
Static string hexString (unsigned int x)
{
Char buff [20];
_ Snprintf (buff, 16, "% 08x", x );
Return string (buff, buff + 8 );
}
Void write (istream & in, ostream & out)
{
Char buffer [BUFFER_SIZE];
Streamsize sz;
While (in. good () & out. good ())
{
In. read (buffer, sizeof (buffer ));
Sz = in. gcount ();
If (sz <= 0)
Break;
If (out. good ())
Out. write (buffer, sz );
}
}
Public:
ProxyService ()
{
Static char xid = '0 ';
Char host [] = "h0.edu.bj.ie.sogou.com ";
Char id = xid + 1;
If (id> '9 ')
Id = '0 ';
Host [1] = id;
Xid = id;
Client. setHost (host );
Client. setPort (80 );
}
Virtual void handleRequest (HTTPServerRequest & request, HTTPServerResponse & response)
{
Static const string authToken = "5FA7CF6A1809B3B514FA66A1ECA16FEB/30/78 e7ff933a9a3063 ";
String timestamp (hexString (unsigned) time (0 )));
String tag (hexString (hashTag (timestamp + request. getHost () + "SogouExplorerProxy ")));
Try
{
HTTPRequest clientRequest (request. getMethod (), request. getURI (), request. getVersion ());
For (NameValueCollection: ConstIterator I = request. begin (); I! = Request. end (); ++ I)
ClientRequest. set (I-> first, I-> second );
ClientRequest. set ("X-Sogou-Auth", authToken );
ClientRequest. set ("X-Sogou-Tag", tag );
ClientRequest. set ("X-Sogou-Timestamp", timestamp );
Ostream & OS = client. sendRequest (clientRequest );
OS. flush ();
If (toUpper (request. getMethod () = "POST ")
{
Write (request. stream (), OS );
OS. flush ();
}
HTTPResponse clientResponse;
Istream & is = client. receiveResponse (clientResponse );
Response. setStatusAndReason (clientResponse. getStatus (), clientResponse. getReason ());
For (NameValueCollection: ConstIterator I = clientResponse. begin (); I! = ClientResponse. end (); ++ I)
Response. set (I-> first, I-> second );
Ostream & out = response. send ();
Out. flush ();
If (toUpper (request. getMethod () = "CONNECT" & clientResponse. getStatus () = HTTPResponse: HTTP_ OK)
{
Char buffer [BUFFER_SIZE];
Int sz;
Istream & in = request. stream ();
Sz = (int) is. readsome (buffer, sizeof (buffer ));
If (sz> 0)
{
Out. write (buffer, sz );
Out. flush ();
}
Sz = (int) in. readsome (buffer, sizeof (buffer ));
If (sz> 0)
{
OS. write (buffer, sz );
OS. flush ();
}
StreamSocket s1 = client. socket ();
StreamSocket s2 = (HTTPServerRequestImpl *) & request)-> socket ();
Vector <Socket> list, l2, l3;
While (true)
{
List. clear ();
List. push_back (s1 );
List. push_back (s2 );
Socket: select (list, l2, l3, Timespan (20, 0 ));
If (list. empty ())
Break;
If (list [0] = s2)
{
Sz = s2.receiveBytes (buffer, sizeof (buffer ));
If (sz <= 0)
Break;
S1.sendBytes (buffer, sz );
}
Else
{
Sz = s1.receiveBytes (buffer, sizeof (buffer ));
If (sz <= 0)
Break;
S2.sendBytes (buffer, sz );
}
}
}
Else
{
Write (is, out );
Out. flush ();
}
}
Catch (const Exception &)
{
Client. reset ();
}
}
};
Class ProxyRequestHandlerFactory: public HTTPRequestHandlerFactory
{
Public:
Virtual HTTPRequestHandler * createRequestHandler (const HTTPServerRequest & request)
{
Return new ProxyService;
}
};
Int main (int argc, char ** argv)
{
ThreadPool: defaultPool (). addCapacity (128-ThreadPool: defaultPool (). capacity ());
ServerSocket socket;
Socket. bind (SocketAddress ("127.0.0.1", 8008), true );
Socket. listen ();
HTTPServerParams * params = new HTTPServerParams;
Params-> setMaxThreads (64 );
Params-> setServerName ("ProxyService ");
Params-> setSoftwareVersion ("1.0 ");
HTTPServer server (new ProxyRequestHandlerFactory (), socket, params );
Server. start ();
While (true)
{
Thread: sleep (1, 65535 );
}
Server. stop ();
Return 0;
}