Shanheavel Posted March 11, 2014 Posted March 11, 2014 Hi, I'm trying all day to write a working proxy server, but it still doesn't work correctly. I'm not good at network functions, so maybe I've forgot about something. It should receive, modify and send data between a browser and web server. Here is a code. I just added a short comments. I hope it will make the script more readably. expandcollapse popup#Region Tables #include <Array.au3> Global $sProxyIP = @IPAddress1, $iProxyPort = 8080, $iProxySocket = -1 Global $iNewSocket, $asLines[0], $sHost, $iLen Global $aiBrowserSocket[0], $asBrowserRecv[0], $aiServerSocket[0], $asServerRecv[0], $aiServerContentLen[0] #EndRegion Tables #Region Initialization If Not TCPStartup() Then Exit @ScriptLineNumber $iProxySocket = TCPListen($sProxyIP, $iProxyPort) If @error Then Exit @ScriptLineNumber #EndRegion Initialization While 1 ;Accepting new sockets $iNewSocket = TCPAccept($iProxySocket) If $iNewSocket >= 0 Then ProxyAddArray($iNewSocket) ;Browser --> Proxy For $socket = 0 To UBound($asBrowserRecv) - 1 $asBrowserRecv[$socket] = BinaryToString(TCPRecv($aiBrowserSocket[$socket], 1024 ^ 2)) If @error Then ProxyDeleteArray($socket) $socket += 1 ContinueLoop EndIf Next ;Browser data analyzing For $socket = 0 To UBound($asBrowserRecv) - 1 $sHost = '' $asLines = StringSplit($asBrowserRecv[$socket], @CRLF, 1) For $line = 1 To $asLines[0] If StringLeft($asLines[$line], 4) = 'Host' Then $sHost = StringTrimLeft($asLines[$line], 6) ExitLoop EndIf Next $aiServerSocket[$socket] = TCPConnect(TCPNameToIP($sHost), 80) If @error Then ProxyDeleteArray($socket) $socket += 1 ContinueLoop EndIf Next ;Proxy --> Web Page For $socket = 0 To UBound($aiServerSocket) - 1 If $aiServerSocket[$socket] < 0 Then ContinueLoop $asServerRecv[$socket] = TCPSend($aiServerSocket[$socket], $asBrowserRecv[$socket]) If @error Then $aiServerSocket[$socket] = -1 Next ;Web Page --> Proxy For $socket = 0 To UBound($aiServerSocket) - 1 If $aiServerSocket[$socket] < 0 Then ContinueLoop $iLen = 0 $asServerRecv[$socket] = BinaryToString(TCPRecv($aiServerSocket[$socket], 1024 ^ 2 * 10)) If StringLen($asServerRecv[$socket]) = 0 Then ContinueLoop $asLines = StringSplit($asServerRecv[$socket], @CRLF, 1) If @error Then $aiServerSocket[$socket] = -1 For $line = 1 To $asLines[0] ;Data lenght If StringLeft($asLines[$line], 14) = 'Content-Length' Then $iLen = StringTrimLeft($asLines[$line], 16) $aiServerContentLen[$socket] = $iLen ExitLoop EndIf Next Next ;Proxy --> Browser For $socket = 0 To UBound($aiBrowserSocket) - 1 If $aiServerContentLen[$socket] > StringLen($asBrowserRecv[$socket]) Then ContinueLoop TCPSend($aiBrowserSocket[$socket], $asServerRecv[$socket]) Next WEnd #Region Proxy Func ProxyAddArray($iSocket) _ArrayAdd($aiBrowserSocket, $iSocket) _ArrayAdd($asBrowserRecv, '') _ArrayAdd($aiServerSocket, -1) _ArrayAdd($asServerRecv, '') _ArrayAdd($aiServerContentLen, 0) EndFunc ;==>ProxyAddArray Func ProxyDeleteArray($iIndex) _ArrayAdd($aiBrowserSocket, $iIndex) _ArrayAdd($asBrowserRecv, $iIndex) _ArrayAdd($aiServerSocket, $iIndex) _ArrayAdd($asServerRecv, $iIndex) _ArrayAdd($aiServerContentLen, $iIndex) EndFunc ;==>ProxyDeleteArray #EndRegion Proxy Important: Before you will check this, you should change connection setting in your web browser. And please do not post links to other old proxy server from Autoit Forums. I've tried them all.
Shanheavel Posted March 12, 2014 Author Posted March 12, 2014 I see that no one is able to help me. So I wrote a new version of my proxy server. It does not use arrays. I think it is much simpler. However it still has problem with loading most sites. expandcollapse popup#Region Tables Global $sProxyIP = @IPAddress1, $iProxyPort = 8080, $iProxySocket = -1 Global $iBrowserSocket, $sBrowserRecv Global $iServerSocket, $sServerRecv, $iContentLenght #EndRegion Tables #Region Initialization If Not TCPStartup() Then Exit @ScriptLineNumber $iProxySocket = TCPListen($sProxyIP, $iProxyPort) If @error Then Exit @ScriptLineNumber #EndRegion Initialization While 1 Do $iBrowserSocket = TCPAccept($iProxySocket) Sleep(10) Until $iBrowserSocket > -1 For $i = 1 To 100 $sBrowserRecv = TCPRecv($iBrowserSocket, 1024 ^ 2) If $sBrowserRecv Then ExitLoop Sleep(10) Next If $sBrowserRecv Then If HTTPRequest() Then TCPSend($iBrowserSocket, $sServerRecv) EndIf TCPCloseSocket($iBrowserSocket) WEnd Func HTTPRequest() Local $asLines = StringSplit($sBrowserRecv, @CRLF, 1), $asLineParts[0] $iContentLenght = 0 For $line = 1 To $asLines[0] $asLineParts = StringSplit($asLines[$line], ': ', 1) If $asLineParts[0] < 2 Then ContinueLoop Assign('Browser ' & $asLineParts[1], $asLineParts[2]) Next $iServerSocket = TCPConnect(TCPNameToIP(Eval('Browser Host')), 80) If $iServerSocket < 0 Then Return If TCPSend($iServerSocket, $sBrowserRecv) <> StringLen($sBrowserRecv) Then Exit 2 $sServerRecv = TCPRecv($iServerSocket, 1024 ^ 2) If @error Then Return $sServerRecv = BinaryToString($sServerRecv, 1) $asLines = StringSplit($sServerRecv, @CRLF, 1) For $line = 1 To $asLines[0] $asLineParts = StringSplit($asLines[$line], ': ', 1) If $asLineParts[0] < 2 Then ContinueLoop Switch $asLineParts[1] Case 'Content-Length' $iContentLenght = $asLineParts[2] EndSwitch Next For $i = 1 To 100 If StringLen($sServerRecv) >= $iContentLenght Then ExitLoop $sServerRecv &= BinaryToString(TCPRecv($iServerSocket, 1024 ^ 2), 1) Sleep(10) Next If StringLen($sServerRecv) < $iContentLenght Then MsgBox(32, StringLen($sServerRecv) & '/' & $iContentLenght, $sServerRecv) EndIf Return 1 EndFunc ;==>HTTPRequest For example, it loads wikipedia.org only partly. Have you any idea, how to fix this?
ripdad Posted March 13, 2014 Posted March 13, 2014 Your script has an array error at this line: Func HTTPRequest() Local $asLines = StringSplit($sBrowserRecv, @CRLF, 1), $asLineParts[0]; <====== I know you said: And please do not post links to other old proxy server from Autoit Forums. I've tried them all. Â I'm not sure what you tried -- It's not perfect, but, did you try this? '?do=embed' frameborder='0' data-embedContent>> At the very least, you could get some ideas from it. "The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward
Shanheavel Posted March 13, 2014 Author Posted March 13, 2014 Your script has an array error at this line: Func HTTPRequest() Local $asLines = StringSplit($sBrowserRecv, @CRLF, 1), $asLineParts[0]; <====== It is hard to get an array error with StringSplit function, so I think  $asLineParts[0] is a problem for you. You probably have a older AutoIt version, where assigning empty arrays was not allowed. Just delete "[0]" at this point. And yes, I tried this. I have to admit that my code was inspired by yours. I want to write something like you, but much simpler.
ripdad Posted March 13, 2014 Posted March 13, 2014 Yes, I used an older version of AutoIt -- It slipped my mind about that new feature. You could strip my existing code to bare minimum. It wouldn't have any features though. In any case, I try not to add any more code than what is necessary to make it work with acceptable accuracy. It was a very slow process to make it that way. A lot of "trial and error". Also at this time, it's not a good idea to check for an error after TCPRecv, if you're using a newer version of AutoIt. A bug exist where it will exit the loop before you have received data. I assume it will get fixed in some future update. Ticket link: http://www.autoitscript.com/trac/autoit/ticket/2596 You'll find a work-around for it in my code, where I used several time-out schemes. The For Loop, 1 to 100 is one of them. "The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward
ripdad Posted March 14, 2014 Posted March 14, 2014 I ran some test with this arrangement today... ; Example Section Only ; ;=============================================== For $i = 1 To 100 $recv = TCPRecv($socket, 10240, 1) If @error And _WSA_GetLastError() Then; <- both conditions must exist to exitloop ExitLoop EndIf ; If StringLeft($recv, 2) = '0x' Then $string &= BinaryToString($recv) EndIf ; Sleep(10) Next ;=============================================== ; Func _WSA_GetLastError() Local $array = DllCall('ws2_32.dll', 'int', 'WSAGetLastError') If @error Then Return -1 Return $array[0] EndFunc ; If $recv is blank with an @error of -1 (meaning, it has not received data yet) and _WSA_GetLastError() is 0, then it will continue to loop. Otherwise, when both @error and _WSA_GetLastError() exist, it will then exit the loop. So far, This seems to work well. If it does okay over the next week, I'll update my code. "The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now