10 Years of Service
66%

[HIDE-THANKS]
Code:
>;------------------------------------------------------------------------------------
; LocalProxyServer_v0.12b.au3
; Updated: September 22, 2015
; AutoIt Version Required: v3.3.8.1+
;------------------------------------------------------------------------------------
;- Changed default proxy IP to 127.0.0.1, which is more secure.
;- Merged multiple For Loops into one, which is more efficient.
;- Removed a few functions and integrated code into the active loop.
;- Removed some of the debug code that was used during development.
;- Added _WSAAsyncGetHostByName(), which has a 3 second timeout.
;- Added an inactivity timeout per individual socket.
;------------------------------------------------------------------------------------
; Credit: This script is based on code from EnrMa:
; https://www.autoitscript.com/forum/topic/44138-autoit-proxy-server/#comment-774282
;------------------------------------------------------------------------------------
;
#NoTrayIcon
Opt('MustDeclareVars', 1)
Opt('TrayAutoPause', 0)
Opt('WinWaitDelay', 0)
;
Local Const $sTitle = 'Local Proxy Server v0.12b'
Local Const $sPathIcon = @WindowsDir & '\system32\shell32.dll'
TraySetIcon($sPathIcon, 19)
TraySetToolTip($sTitle)
;
If Not TCPStartup() Then
Exit MsgBox(8208, $sTitle, 'Error: TCPStartup' & @TAB, 5)
EndIf
;
Local Const $hWS2_32 = DllOpen(@WindowsDir & '\system32\ws2_32.dll')
If $hWS2_32 < 1 Then
Exit MsgBox(8208, $sTitle, 'Error: ws2_32.dll' & @TAB, 5)
EndIf
;
Local Const $sFileIni = @ScriptDir & '\Proxy.ini'
If Not FileExists($sFileIni) Then
IniSetup()
EndIf
;
Local Const Enum $PortNumber, $ClientSocket, $RemoteSocket, $ProtocolState, $RemoteHost, $RemoteIP, $ContentLength, $ReceivedBytes, $RemoteClose, $Inactivity
Local $sPattern_BlackList, $sPattern_WhiteList, $nSocketHTTP, $nSocketHTTPS, $WSAAsyncGetHostByName_lParam
Local $sHostIP, $sBody, $sHeader, $sMethod, $sValue, $nError, $nExtended, $nSocket, $sHost, $sRecv
Local $Active = 0, $nCookies = 0, $nCount = 0, $nMsec = 250, $nTotalBytes = 0, $WhiteListActive = 1
;
Local $IDX = 9
Local $a[$IDX + 1][10]
Local $aHostCache[10][2]
;
DllCall('uxtheme.dll', 'none', 'SetThemeAppProperties', 'int', 1)
Local $ID_GUI = GUICreate($sTitle, 430, 234, Default, Default, Default, 8)
GUISetFont(8.5, Default, Default, 'microsoft sans serif')
GUISetIcon($sPathIcon, 19, $ID_GUI)
GUICtrlCreateGroup('', 350, 0, 76, 145)
GUICtrlCreateGroup('', 350, 145, 76, 55)
Local $ID_EDT = GUICtrlCreateEdit('', 5, 5, 340, 195)
Local $ID_WHL = GUICtrlCreateCheckbox('WhiteList', 358, 15, 60, 20, 0x1000)
Local $ID_CKS = GUICtrlCreateCheckbox('Cookies', 358, 40, 60, 20, 0x1000)
Local $ID_INI = GUICtrlCreateButton('Config', 358, 65, 60, 20, 0x1002)
Local $ID_UPD = GUICtrlCreateButton('Update', 358, 90, 60, 20, 0x1002)
Local $ID_BTN = GUICtrlCreateButton('Clear', 358, 115, 60, 20, 0x1002)
Local $ID_TBR = GUICtrlCreateLabel('0.00 B', 358, 160, 60, 20, 0x1201)
Local $ID_LBL = GUICtrlCreateLabel('', 358, 185, 60, 7, 0x1000)
Local $ID_ST1 = GUICtrlCreateLabel('0', 5, 205, 82, 20, 0x1201)
Local $ID_ST2 = GUICtrlCreateLabel('0', 90, 205, 82, 20, 0x1201)
Local $ID_ST3 = GUICtrlCreateLabel('0', 175, 205, 82, 20, 0x1201)
Local $ID_ST4 = GUICtrlCreateLabel('0', 260, 205, 82, 20, 0x1201)
Local $ID_ST5 = GUICtrlCreateLabel('0', 345, 205, 81, 20, 0x1201)
GUICtrlSetTip($ID_UPD, 'Update Black and White Lists')
GUICtrlSetTip($ID_WHL, 'Enable/Disable WhiteList')
GUICtrlSetTip($ID_CKS, 'Enable/Disable Cookies')
GUICtrlSetTip($ID_INI, 'Open INI for Editing')
GUICtrlSetTip($ID_TBR, 'Total Bytes Received')
GUICtrlSetTip($ID_BTN, 'Clear the Window')
GUICtrlSetTip($ID_LBL, 'Activity')
GUICtrlSetOnEvent($ID_UPD, 'UpdateLists')
GUICtrlSetOnEvent($ID_TBR, 'BytesClear')
GUICtrlSetOnEvent($ID_WHL, 'WhiteList')
GUICtrlSetOnEvent($ID_BTN, 'EditClear')
GUICtrlSetOnEvent($ID_CKS, 'Cookies')
GUICtrlSetOnEvent($ID_INI, 'OpenINI')
GUICtrlSetBkColor($ID_LBL, 0x008000)
GUICtrlSetLimit($ID_EDT, 100000)
GUICtrlSetState($ID_WHL, 1)
GUICtrlSetState($ID_CKS, 1)
GUISetOnEvent(-3, 'Minimize')
OnAutoItExitRegister('ExitApp')
ProxySetup()
GUISetState(@SW_SHOW, $ID_GUI)
Opt('GUIOnEventMode', 1)
;
While 1; <- main loop
;==================================================================================== Section 1
Do; <- idler loop
Sleep($nMsec)
;
$nSocket = TCPAccept($nSocketHTTP)
If $nSocket > 0 Then
SocketToArray($nSocket, 80, 2); http
EndIf
;
$nSocket = TCPAccept($nSocketHTTPS)
If $nSocket > 0 Then
SocketToArray($nSocket, 443, 1); connect->https
EndIf
Until $Active
;
;==================================================================================== Section 2
For $i = 1 To $IDX; <- active loop
If $a[$i][$ClientSocket] < 1 Then
ContinueLoop
EndIf
;
; <- receive request from client
$sRecv = _WSA_TCPRecv($a[$i][$ClientSocket], 32768, 1)
If @error Then
CloseSocket($i); [E101] client closed socket
ContinueLoop
EndIf
;
If @extended > 0 Then
$sRecv = BinaryToString($sRecv)
$sMethod = StringLeft($sRecv, 7)
If StringRegExp($sMethod, '(?i)(GET|POST|CONNECT|HEAD|PUT|OPTIONS|TRACE)') Then
$sHeader = StringLeft($sRecv, StringInStr($sRecv, @CRLF & @CRLF) + 3)
;
$sHost = StringRegExpReplace($sHeader, '(?is).*Host:\s(.*?)\r\n.*', '\1')
If @extended = 0 Then
CloseSocket($i, '[E102] Header: Host Not Found', 1)
ContinueLoop
EndIf
$sHost = StringRegExpReplace($sHost, '(:.*)', ''); <- remove unwanted port number in Host string
;
If StringRegExp($sHost, $sPattern_BlackList) Then
CloseSocket($i, '[blacklisted] ' & $sHost, 1)
ContinueLoop
ElseIf $WhiteListActive And StringRegExp($sHost, $sPattern_WhiteList) = 0 Then
CloseSocket($i, '[unlisted] ' & $sHost, 1)
ContinueLoop
EndIf
;
; modify header
$sRecv = StringRegExpReplace($sRecv, '(?is)(.*?)(https?://.*?|ftps?://.*?)(/.*\r\n)', '\1\3')
$sRecv = StringRegExpReplace($sRecv, '(?is)(Accept-Encoding:.*?\r\n)', 'Accept-Encoding: identity' & @CRLF)
$sRecv = StringReplace($sRecv, 'Proxy-Connection', 'Connection')
;
If $nCookies = 0 Then
$sRecv = StringRegExpReplace($sRecv, '(?is)(Cookie:.*?\r\n)', '')
$sRecv = StringRegExpReplace($sRecv, '(?is)(Referer:.*?\r\n)', '')
EndIf
;
; handles change of host address on an existing socket
If $a[$i][$RemoteSocket] > 0 And $sHost <> $a[$i][$RemoteHost] Then
TCPCloseSocket($a[$i][$RemoteSocket])
$a[$i][$RemoteSocket] = 0
;
If StringMatch($sMethod, 'CONNECT') Then
$a[$i][$ProtocolState] = 1
$a[$i][$PortNumber] = 443
Else
$a[$i][$ProtocolState] = 2
$a[$i][$PortNumber] = 80
EndIf
EndIf
;
;======================================================================== Section 3
; <- connect to remote host
If $a[$i][$RemoteSocket] = 0 Then
$a[$i][$RemoteHost] = $sHost
;
$sHostIP = HostCache('GetHost', $a[$i][$RemoteHost]); <- the host cache saves repeated calls to _WSAAsyncGetHostByName()
If @error Then; <- host not found in cache
$sHostIP = _WSAAsyncGetHostByName($a[$i][$RemoteHost])
$nError = @error
$nExtended = @extended
;
If $nError Then
CloseSocket($i, '[E103] ' & $a[$i][$RemoteHost] & '/' & $nError & '/' & _WSA_FormatMessage($nExtended), 1)
ContinueLoop
Else
HostCache('SaveHost', $a[$i][$RemoteHost], $sHostIP)
EndIf
EndIf
;
$a[$i][$RemoteIP] = $sHostIP
;
$a[$i][$RemoteSocket] = _TCPConnect($a[$i][$RemoteIP], $a[$i][$PortNumber])
$nError = @error
$nExtended = @extended
;
If $nError Then
HostCache('RemoveHost', $a[$i][$RemoteHost]); <- forces another query from _WSAAsyncGetHostByName() in case ip has changed
CloseSocket($i, '[E104] ' & $a[$i][$RemoteHost] & '/' & $nError & '/' & _WSA_FormatMessage($nExtended), 1)
EndIf
EndIf
EndIf
;
If $a[$i][$RemoteSocket] < 1 Then
ContinueLoop
EndIf
;
;============================================================================ Section 4
; <- send routing
If $a[$i][$ProtocolState] = 1 Then; init https session with client
_WSA_TCPSend($a[$i][$ClientSocket], 'HTTP/1.1 200 Connection Established' & @CRLF & @CRLF, 1)
$nError = @error
$nExtended = @extended
;
If $nError Then
CloseSocket($i, '[E105] ' & $a[$i][$RemoteHost] & '/' & $nError & '/' & _WSA_FormatMessage($nExtended))
Else
$a[$i][$ProtocolState] = 3; move from 1 to 3 (https host connected)
EndIf
ContinueLoop; <- there is no data to send to host yet
Else
_WSA_TCPSend($a[$i][$RemoteSocket], $sRecv, 1); send client request to remote host
$nError = @error
$nExtended = @extended
;
If $nError Then
CloseSocket($i, '[E106] ' & $a[$i][$RemoteHost] & '/' & $nError & '/' & _WSA_FormatMessage($nExtended), 1)
EndIf
EndIf
EndIf
;
If $a[$i][$RemoteSocket] < 1 Then
ContinueLoop
EndIf
;
;================================================================================ Section 5
; <- receive response from remote host and send to client
$sRecv = _WSA_TCPRecv($a[$i][$RemoteSocket], 32768, 1)
$nError = @error
$nExtended = @extended
;
If $nError Then
If $nError <> -2 Then
CloseSocket($i, '[E107] ' & $a[$i][$RemoteHost] & '/' & $nError & '/' & _WSA_FormatMessage($nExtended), 1)
Else
CloseSocket($i, '', 1); <- some servers close their socket when data is fully sent
EndIf
ContinueLoop
ElseIf $nExtended = 0 Then; no data received
$a[$i][$Inactivity] += 1
If $a[$i][$Inactivity] > 500 Then; close socket after a period of inactivity
CloseSocket($i)
EndIf
ContinueLoop
Else
$Active = 1; global reset
$a[$i][$Inactivity] = 1; individual reset
$nTotalBytes += $nExtended; add to total bytes received
$sRecv = BinaryToString($sRecv)
EndIf
;
; get http header information
If StringMatch(StringLeft($sRecv, 6), 'HTTP/1') And $a[$i][$ProtocolState] = 2 Then
$sHeader = StringLeft($sRecv, StringInStr($sRecv, @CRLF & @CRLF) + 3)
$sBody = StringTrimLeft($sRecv, StringInStr($sRecv, @CRLF & @CRLF) + 3)
$a[$i][$ReceivedBytes] = StringLen($sBody); <- get initial body size
;
$sValue = StringRegExpReplace($sHeader, '(?is).*Connection:\s(.*?)\r\n.*', '\1', 1)
If @extended And StringMatch($sValue, 'close') Then
$a[$i][$RemoteClose] = 1; close
Else
$a[$i][$RemoteClose] = 0; keep-alive
EndIf
;
$sValue = StringRegExpReplace($sHeader, '(?is).*Content-Length:\s(.*?)\r\n.*', '\1', 1)
If @extended And StringIsDigit($sValue) Then
$a[$i][$ContentLength] = Number($sValue)
Else
$a[$i][$ContentLength] = -1; unknown
EndIf
Else
$a[$i][$ReceivedBytes] += $nExtended; <- continue adding body size
EndIf
;
; send remote data to client
_WSA_TCPSend($a[$i][$ClientSocket], $sRecv, 1)
$nError = @error
$nExtended = @extended
;
If $nError Then
CloseSocket($i, '[E108] ' & $a[$i][$RemoteHost] & '/' & $nError & '/' & _WSA_FormatMessage($nExtended))
ElseIf $a[$i][$RemoteClose] And $a[$i][$ReceivedBytes] = $a[$i][$ContentLength] Then
CloseSocket($i)
EndIf
Next
;
; display bytes delay
$nCount += 1
If $nCount > 50 Then
GUICtrlSetData($ID_TBR, GetByteFormat($nTotalBytes))
$nCount = 0
EndIf
;
;==================================================================================== Section 6
; <- proxy reset
$Active += 1
If $Active > 500 Then; <- represents 500 turns of the main loop with no activity
GUICtrlSetBkColor($ID_LBL, 0x008000)
;
For $i = 1 To $IDX
CloseSocket($i); kill all sockets
Next
;
$IDX = 9
ReDim $a[$IDX + 1][10]; reset main array
$nMsec = 250; idle at 250 msec
$Active = 0; not active
EndIf
WEnd
;
Func SocketToArray($nSock, $nPort, $nState)
For $i = 1 To $IDX
If $a[$i][$PortNumber] Then
ContinueLoop
EndIf
;
If ($i + 2) > $IDX Then
$IDX += 5
ReDim $a[$IDX + 1][10]
EndIf
;
$a[$i][$PortNumber] = $nPort
$a[$i][$ClientSocket] = $nSock
$a[$i][$RemoteSocket] = 0
$a[$i][$ProtocolState] = $nState; 1=connect, 2=http, 3=https
$a[$i][$RemoteHost] = ''
$a[$i][$RemoteIP] = ''
$a[$i][$ContentLength] = -1
$a[$i][$ReceivedBytes] = 0
$a[$i][$RemoteClose] = 0
$a[$i][$Inactivity] = 0
;
GUICtrlSetBkColor($ID_LBL, 0x00FF00)
$nMsec = 10
$Active = 1
ExitLoop
Next
EndFunc
;
Func HostCache($sCommand, $sHost, $sIP = '')
Local $nRows = UBound($aHostCache) - 1
;
If $sCommand = 'GetHost' Then
For $i = 0 To $nRows
If $aHostCache[$i][0] == $sHost Then
Return $aHostCache[$i][1]; <- host ip
EndIf
Next
Return SetError(1); <- host not found
ElseIf $sCommand = 'SaveHost' Then
For $i = 0 To $nRows
If $aHostCache[$i][0] = '' Then
$aHostCache[$i][0] = $sHost; <- save host address
$aHostCache[$i][1] = $sIP; <- save host ip
If ($i + 2) > $nRows Then
ReDim $aHostCache[$nRows + 5][2]
EndIf
Return
EndIf
Next
ElseIf $sCommand = 'RemoveHost' Then
For $i = 0 To $nRows
If $aHostCache[$i][0] <> $sHost Then
ContinueLoop
EndIf
;
For $j = $nRows To 0 Step -1
If $aHostCache[$j][0] <> '' Then
$aHostCache[$i][0] = $aHostCache[$j][0]
$aHostCache[$i][1] = $aHostCache[$j][1]
$aHostCache[$j][0] = ''
$aHostCache[$j][1] = ''
Return
EndIf
Next
Next
EndIf
EndFunc
;
Func CloseSocket($i, $sMsg = '', $nMode = 0)
If StringLen($sMsg) Then; display message
GUICtrlSetState($ID_EDT, 256); $GUI_FOCUS
Local $str = GUICtrlRead($ID_EDT)
GUICtrlSetData($ID_EDT, '')
GUICtrlSetData($ID_EDT, $str & $sMsg & @CRLF, 1)
EndIf
;
If $nMode Then; send client error
$sMsg = 'HTTP/1.1 503 Service Unavailable' & @CRLF
$sMsg &= 'Content-Length: 0' & @CRLF
$sMsg &= 'Connection: close' & @CRLF & @CRLF
_WSA_TCPSend($a[$i][$ClientSocket], $sMsg, 1)
EndIf
;
If $a[$i][$RemoteSocket] > 0 Then
TCPCloseSocket($a[$i][$RemoteSocket])
EndIf
;
If $a[$i][$ClientSocket] > 0 Then
TCPCloseSocket($a[$i][$ClientSocket])
EndIf
;
For $j = 0 To 9
$a[$i][$j] = ''; <- clear all fields
Next
EndFunc
;
Func GetByteFormat($n_b); v0.4
If StringIsDigit($n_b) = 0 Then
Return '0.00 B'
EndIf
$n_b = Number($n_b)
;
Local $a_ab = StringSplit('B|KB|MB|GB|TB', '|')
;
For $i = 1 To $a_ab[0]; "bytes" in -> div -> abrv -> out
If $n_b < 1024 Then
$n_b = String(Round($n_b, 2))
If StringInStr($n_b, '.') = 0 Then
$n_b &= '.00'
ElseIf StringLeft(StringRight($n_b, 2), 1) = '.' Then
$n_b &= '0'
EndIf
Return $n_b & ' ' & $a_ab[$i]
EndIf
$n_b /= 1024
Next
EndFunc
;
Func ProxySetup()
$sPattern_BlackList = SRE_GetList('BlackList')
$sPattern_WhiteList = SRE_GetList('WhiteList')
;
Local $sIP = IniRead($sFileIni, 'System', 'ProxyIP', '127.0.0.1')
Local $nPort = IniRead($sFileIni, 'System', 'ProxyPort', '8080')
Local $nPortSSL = IniRead($sFileIni, 'System', 'ProxyPortSSL', '8143')
;
$nSocketHTTP = TCPListen($sIP, $nPort)
If @error Then
Local $msg = 'Error: HTTP Proxy could not bind socket on IP: ' & $sIP & ' Port: ' & $nPort
Exit MsgBox(8208, $sTitle, $msg & @TAB, 5)
EndIf
;
$nSocketHTTPS = TCPListen($sIP, $nPortSSL)
If @error Then
Local $msg = 'Error: HTTPS Proxy could not bind socket on IP: ' & $sIP & ' Port: ' & $nPortSSL
Exit MsgBox(8208, $sTitle, $msg & @TAB, 5)
EndIf
;
GUICtrlSetData($ID_ST1, @OSVersion & '_' & @OSArch)
GUICtrlSetData($ID_ST2, 'AutoIt v' & @AutoItVersion)
GUICtrlSetData($ID_ST3, 'IP: ' & $sIP)
GUICtrlSetData($ID_ST4, 'HTTP: ' & $nPort)
GUICtrlSetData($ID_ST5, 'HTTPS: ' & $nPortSSL)
GUICtrlSetState($ID_EDT, 256); $GUI_FOCUS
EndFunc
;
Func StringMatch($s, $c, $d = '|'); v0.1
$s = StringLower($s)
$c = StringLower($c)
Local $x = StringSplit($c, $d, 1)
;
For $i = 1 To $x[0]
If $s == $x[$i] Then
Return $i
EndIf
Next
Return 0
EndFunc
;
Func BytesClear()
GUICtrlSetData($ID_TBR, '0.00 B')
GUICtrlSetState($ID_EDT, 256); $GUI_FOCUS
$nTotalBytes = 0
EndFunc
;
Func EditClear()
GUICtrlSetState($ID_EDT, 256)
GUICtrlSetData($ID_EDT, '')
EndFunc
;
Func Cookies()
GUICtrlSetState($ID_EDT, 256)
$nCookies = BitXOR($nCookies, 0, 1)
EndFunc
;
Func WhiteList()
GUICtrlSetState($ID_EDT, 256)
$WhiteListActive = BitXOR($WhiteListActive, 0, 1)
EndFunc
;
Func Minimize()
GUISetState(@SW_MINIMIZE, $ID_GUI)
EndFunc
;
Func ExitApp()
GUIDelete($ID_GUI)
DllClose($hWS2_32)
TCPShutdown()
Exit
EndFunc
;
;<-[List Functions]
;
Func OpenINI()
If Not FileExists($sFileIni) Then
Exit MsgBox(8208, $sTitle, 'File Not Found!' & @CRLF & $sFileIni & @TAB, 5)
EndIf
;
GUICtrlSetState($ID_EDT, 256); $GUI_FOCUS
ShellExecute($sFileIni)
EndFunc
;
Func UpdateLists()
$sPattern_BlackList = SRE_GetList('BlackList')
$sPattern_WhiteList = SRE_GetList('WhiteList')
GUICtrlSetState($ID_EDT, 256); $GUI_FOCUS
Local $str = GUICtrlRead($ID_EDT)
GUICtrlSetData($ID_EDT, '')
GUICtrlSetData($ID_EDT, $str & '[updated Lists]' & @CRLF, 1)
EndFunc
;
Func SRE_GetList($sList)
If Not FileExists($sFileIni) Then
Exit MsgBox(8208, $sTitle, 'File Not Found!' & @CRLF & $sFileIni & @TAB, 5)
EndIf
;
Local $aList = IniReadSection($sFileIni, $sList)
If @error Or Not IsArray($aList) Then
Exit MsgBox(8208, $sTitle, 'Invalid INI File!' & @CRLF & $sFileIni & @TAB, 5)
EndIf
;
Local $str = ''
;
For $i = 1 To $aList[0][0]
If StringStripWS($aList[$i][0], 8) Then
$str &= '|' & StringStripWS($aList[$i][0], 3)
EndIf
Next
Return '(?i)(' & StringTrimLeft($str, 1) & ')'
EndFunc
;
Func IniSetup()
;NOTE: The value 0 is not used at this time, except as a fill value for the list entries.
Local $sData = '[WhiteList]' & @CRLF
$sData &= 'ocsp.geotrust.com=0' & @CRLF; certificate verifier
$sData &= 'ocsp.verisign.com=0' & @CRLF; certificate verifier
$sData &= 'autoitscript.com=0' & @CRLF; website
$sData &= 'autoit-cdn.com=0' & @CRLF; resource server
$sData &= 'youtube.com=0' & @CRLF; website
$sData &= 'googlevideo.com=0' & @CRLF; resource server
$sData &= 'ytimg.com=0' & @CRLF; resource server
$sData &= 'yahoo.com=0' & @CRLF; website
$sData &= 'yimg.com=0' & @CRLF; resource server
$sData &= 'google.ro=0' & @CRLF; website
$sData &= 'gstatic.com=0' & @CRLF; resource server
$sData &= 'ezlan.net=0' & @CRLF; website
$sData &= 'faqs.org=0' & @CRLF; website
$sData &= 'php.net=0' & @CRLF; website
$sData &= @CRLF
$sData &= '[blackList]' & @CRLF
$sData &= 'ads1.com=0' & @CRLF; example
$sData &= 'ads2.com=0' & @CRLF; example
$sData &= @CRLF
$sData &= '[system]' & @CRLF
$sData &= 'ProxyIP=127.0.0.1' & @CRLF
$sData &= 'ProxyPort=8080' & @CRLF
$sData &= 'ProxyPortSSL=8143' & @CRLF
$sData &= @CRLF
;
Local $hFile = FileOpen($sFileIni, 1)
If $hFile = -1 Or Not FileWrite($hFile, $sData) Then
Exit MsgBox(8208, $sTitle, 'Cannot Write To File:' & @CRLF & $sFileIni & @TAB, 5)
EndIf
FileClose($hFile)
EndFunc
;
;<-[WSA TCP Functions]
;
;======================================================================================
;#FUNCTION#....:
; Name.........: _WSA_TCPRecv()
;..............:
; Version......: AutoIt v3.3.8.1+
;..............:
; Dependencies.: _WSA_GetLastError() and a handle to ws2_32.dll
;..............:
; @error.......; 0 no error.
;..............: -1 socket error.
;..............: -2 disconnected.
;..............: -3 dll error.
;..............:
; @extended....; If @error Then returns a WSA Error Code.
;............. : Else returns number of bytes received.
;..............:
; Return Value.: If Not @error And @extended > 0 Then returns data.
;..............: Else returns blank.
;..............:
; Remarks......: Link to WSA Error Codes:
; http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
;======================================================================================
Func _WSA_TCPRecv($nSocket, $nMaxLen = 4096, $nBinaryMode = 0)
;[set non-blocking mode]
Local $aResult = DllCall($hWS2_32, 'int', 'ioctlsocket', 'int', $nSocket, 'dword', 0x8004667E, 'uint*', 1)
If @error Then
Return SetError(-3, 0, ''); dll error
ElseIf $aResult[0] <> 0 Then
Return SetError(-1, _WSA_GetLastError(), ''); socket error
EndIf; WSAGetLastError will return socket errors with this statement (example: 10038-invalid socket).
;
;[set buffer type]
If $nBinaryMode Then
Local $tBuffer = DllStructCreate('byte[' & $nMaxLen & ']')
Else
Local $tBuffer = DllStructCreate('char buffer[' & $nMaxLen & ']')
EndIf
;
;[receive data]
$aResult = DllCall($hWS2_32, 'int', 'recv', 'int', $nSocket, 'struct*', $tBuffer, 'int', $nMaxLen, 'int', 0)
If @error Then
Return SetError(-3, _WSA_GetLastError(), ''); dll error
EndIf
;
;[check WSA error]
Local $nError = _WSA_GetLastError()
If $nError <> 0 And $nError <> 10035 Then; <- WSAEWOULDBLOCK (non-blocking socket (non-fatal error))
Return SetError(-1, $nError, ''); socket error
EndIf
;
Local $nBytes = $aResult[0]
;
;[set blocking mode]
$aResult = DllCall($hWS2_32, 'int', 'ioctlsocket', 'int', $nSocket, 'dword', 0x8004667E, 'uint*', 0)
If @error Then
Return SetError(-3, 0, ''); dll error
ElseIf $aResult[0] <> 0 Then
Return SetError(-1, _WSA_GetLastError(), ''); socket error
EndIf
;
Local $sData = ''
$nError = 0
;
;[process results]
If $nBytes > 0 Then; data received
$sData = DllStructGetData($tBuffer, 1)
If $nBinaryMode Then; extract binary data
$sData = StringLeft($sData, ($nBytes * 2) + 2)
Else; extract raw data
$sData = StringLeft($sData, $nBytes)
EndIf
ElseIf $nBytes == 0 Then
$nError = -2; disconnected
Else
$nBytes = 0; no data received
EndIf
;
Return SetError($nError, Number($nBytes), $sData)
EndFunc
;
;======================================================================================
;#FUNCTION#....:
; Name.........: _WSA_TCPSend()
;..............:
; Version......: AutoIt v3.3.8.1+
;..............:
; Dependencies.: _WSA_GetLastError() and a handle to ws2_32.dll
;..............:
; @error.......; 0 no error.
;..............: -1 socket error.
;..............: -2 disconnected.
;..............: -3 dll error.
;..............:
; @extended....; If @error Then @extended returns a WSA Error Code.
;............. : Else returns 0.
;..............:
; Return Value.: If Not @error Then returns number of bytes sent.
;..............: Else returns 0.
;..............:
; Remarks......: Link to WSA Error Codes:
; http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
;======================================================================================
Func _WSA_TCPSend($nSocket, $sData, $nBinaryMode = 0)
;[set non-blocking mode]
Local $aResult = DllCall($hWS2_32, 'int', 'ioctlsocket', 'int', $nSocket, 'dword', 0x8004667E, 'uint*', 1)
If @error Then
Return SetError(-3, 0, 0); dll error
ElseIf $aResult[0] <> 0 Then
Return SetError(-1, _WSA_GetLastError(), 0); socket error
EndIf; WSAGetLastError will return socket errors with this statement (ie: 10038-invalid socket).
;
Local $nBytes = StringLen($sData)
;
If $nBinaryMode Then
Local $tBuffer = DllStructCreate('byte[' & $nBytes & ']')
Else
Local $tBuffer = DllStructCreate('char buffer[' & $nBytes & ']')
EndIf
;
DllStructSetData($tBuffer, 1, $sData)
;
;[send data]
$aResult = DllCall($hWS2_32, 'int', 'send', 'int', $nSocket, 'struct*', $tBuffer, 'int', $nBytes, 'int', 0)
If @error Then
Return SetError(-3, 0, 0); dll error
EndIf
;
;[check WSA error]
Local $nError = _WSA_GetLastError()
If $nError <> 0 And $nError <> 10035 Then; <- WSAEWOULDBLOCK (non-blocking socket (non-fatal error))
Return SetError(-1, $nError, 0); socket error
EndIf
;
$nBytes = $aResult[0]
;
;[set blocking mode]
$aResult = DllCall($hWS2_32, 'int', 'ioctlsocket', 'int', $nSocket, 'dword', 0x8004667E, 'uint*', 0)
If @error Then
Return SetError(-3, 0, 0); dll error
ElseIf $aResult[0] <> 0 Then
Return SetError(-1, _WSA_GetLastError(), 0); socket error
EndIf
;
$nError = 0
;
;[process results]
If $nBytes > 0 Then; bytes sent
; pass through
ElseIf $nBytes == 0 Then
$nError = -2; disconnected
Else
$nBytes = 0; no bytes sent
EndIf
;
Return SetError($nError, 0, Number($nBytes))
EndFunc
;
;====================================================================================
;#FUNCTION#
; Name........: _TCPConnect()
;
; This is a rewrite of the original code - all credits go to ProgAndy and JScript.
; Purpose: format is easier to debug and maintain.
;
; Original Link:
; http://www.autoitscript.com/forum/topic/127415-tcpconnect-sipaddr-iport-itimeout/
;..............:
; Version......: AutoIt v3.3.8.1+
;..............:
; Description..: Attempts a socket connection with a timeout.
;..............:
; Dependencies.: _WSA_GetLastError() and a handle to ws2_32.dll
;..............:
; @error.......; 0 no error - socket is returned in blocking mode.
;..............: -1 could not create socket.
;..............: -2 ip incorrect.
;..............: -3 could not get port.
;..............: -4 could not set blocking or non-blocking mode.
;..............: -5 could not connect.
;..............: -6 timed out.
;..............: -7 dll error.
; .............:
; @extended....; If @error Then returns a WSA Error Code.
;..............: Else returns 0.
;..............:
; Return Value.: If @error Then returns -1.
;..............: Else returns socket.
;..............:
; Remarks......: Link to WSA Error Codes:
; http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
;====================================================================================
Func _TCPConnect($sIPAddr, $iPort, $iTimeout = 3000); <- default: 3 seconds
;[create socket]
Local $hSock = DllCall($hWS2_32, 'uint', 'socket', 'int', 2, 'int', 1, 'int', 6); AF_INET, SOCK_STREAM, IPPROTO_TCP
If @error Then
Return SetError(-7, 0, -1); dll error
ElseIf $hSock[0] = -1 Or $hSock[0] = 4294967295 Then; 4294967295 = 0xFFFFFFFF
Return SetError(-1, _WSA_GetLastError(), -1); could not create socket
EndIf
$hSock = $hSock[0]
;
;[get ip handle]
Local $aIP = DllCall($hWS2_32, 'ulong', 'inet_addr', 'str', $sIPAddr)
If @error Then
TCPCloseSocket($hSock)
Return SetError(-7, 0, -1); dll error
ElseIf $aIP[0] = -1 Or $aIP[0] = 4294967295 Then
TCPCloseSocket($hSock)
Return SetError(-2, _WSA_GetLastError(), -1); ip incorrect
EndIf
;
;[get port handle]
Local $aPort = DllCall($hWS2_32, 'ushort', 'htons', 'ushort', $iPort)
If @error Then
TCPCloseSocket($hSock)
Return SetError(-7, 0, -1); dll error
ElseIf $aPort[0] < 1 Then
TCPCloseSocket($hSock)
Return SetError(-3, _WSA_GetLastError(), -1); could not get port
EndIf
;
;[set socket to non-blocking mode for timeout]
Local $aResult = DllCall($hWS2_32, 'int', 'ioctlsocket', 'int', $hSock, 'dword', 0x8004667E, 'uint*', 1); FIONBIO, NON-BLOCKING
If @error Then
TCPCloseSocket($hSock)
Return SetError(-7, 0, -1); dll error
ElseIf $aResult[0] <> 0 Then
TCPCloseSocket($hSock)
Return SetError(-4, _WSA_GetLastError(), -1); socket error (could not set non-blocking mode)
EndIf
;
;[set binding]
Local $tSockAddr = DllStructCreate('short sin_family;ushort sin_port;ulong sin_addr;char sin_zero[8];')
DllStructSetData($tSockAddr, 1, 2)
DllStructSetData($tSockAddr, 2, $aPort[0])
DllStructSetData($tSockAddr, 3, $aIP[0])
;
;[attempt connect]
$aResult = DllCall($hWS2_32, 'int', 'connect', 'int', $hSock, 'struct*', $tSockAddr, 'int', DllStructGetSize($tSockAddr))
If @error Then
TCPCloseSocket($hSock)
Return SetError(-7, 0, -1); dll error
ElseIf $aResult[0] <> 0 And _WSA_GetLastError() <> 10035 Then; <- WSAEWOULDBLOCK - non-blocking socket (no data queued on socket - non-fatal error)
TCPCloseSocket($hSock)
Return SetError(-5, _WSA_GetLastError(), -1); could not connect
EndIf
;
;[set timeout]
Local $t1 = DllStructCreate('uint;int')
DllStructSetData($t1, 1, 1)
DllStructSetData($t1, 2, $hSock)
;
Local $t2 = DllStructCreate('long;long')
DllStructSetData($t2, 1, Floor($iTimeout / 1000))
DllStructSetData($t2, 2, Mod($iTimeout, 1000) * 1000)
;
;[init timeout]
$aResult = DllCall($hWS2_32, 'int', 'select', 'int', $hSock, 'struct*', $t1, 'struct*', $t1, 'ptr', 0, 'struct*', $t2)
Local $nError = @error
Local $nExtended = _WSA_GetLastError()
;
If $nError Then
TCPCloseSocket($hSock)
Return SetError(-7, $nExtended, -1); dll error
ElseIf ($aResult[0] == 0) Then
TCPCloseSocket($hSock)
Return SetError(-6, 10060, -1); WSAETIMEDOUT
EndIf
;
;[set socket to blocking mode again]
$aResult = DllCall($hWS2_32, 'int', 'ioctlsocket', 'int', $hSock, 'dword', 0x8004667E, 'uint*', 0); FIONBIO, BLOCKING ulong*
If @error Then
TCPCloseSocket($hSock)
Return SetError(-7, 0, -1); dll error
ElseIf $aResult[0] <> 0 Then
TCPCloseSocket($hSock)
Return SetError(-4, _WSA_GetLastError(), -1); socket error (could not set blocking mode)
EndIf
;
Return SetError(0, 0, $hSock)
EndFunc
;
Func _WSA_GetLastError()
Local $aResult = DllCall($hWS2_32, 'int', 'WSAGetLastError')
If @error Then
Return SetError(-1, 0, -1); dll error
ElseIf $aResult[0] > 5 Then
Return SetError(0, 0, $aResult[0])
Else
Return SetError(0, 0, 0)
EndIf
EndFunc
;
Func _WSA_FormatMessage($nError)
If $nError > 5 Then
Local $aResult = DllCall('kernel32.dll', 'int', 'FormatMessage', 'dword', 0x00001000, 'ptr', 0, 'int', $nError, 'int', 0, 'str', '', 'int', 2048, 'ptr', 0)
If Not @error And IsArray($aResult) Then
$nError = String($nError) & @CRLF & StringStripWS($aResult[5], 7)
EndIf
EndIf
Return $nError
EndFunc
;
;=====================================================================================
;_WSAAsyncGetHostByName_Timeout() by funkey 2015.04.13
;https://www.autoitscript.com/forum/topic/169440-getaddrinfo-timeout/#comment-1239246
;modified: 2015-08-30 by ripdad
;=====================================================================================
Func _WSAAsyncGetHostByName($sHostName)
Local Const $wMsg = BitOR(0x400, 0x99); WM_USER
Local $tBuf = DllStructCreate('char buffer[1024]')
;
$WSAAsyncGetHostByName_lParam = 0
GUIRegisterMsg($wMsg, '_WSAAsyncGetHostByName_Callback')
;
Local $aRet = DllCall($hWS2_32, 'handle', 'WSAAsyncGetHostByName', 'hwnd', $ID_GUI, 'uint', $wMsg, 'str', $sHostName, 'struct*', $tBuf, 'int', 1024)
If @error Or Not $aRet[0] Then
GUIRegisterMsg($wMsg, '')
Return SetError(1, _WSA_GetLastError(), 0)
EndIf
;
For $iTime = 1 To 200; ~ 3 seconds
If $WSAAsyncGetHostByName_lParam <> 0 Then
ExitLoop
EndIf
Sleep(10)
Next
;
GUIRegisterMsg($wMsg, '')
;
If $iTime >= 200 Then
DllCall($hWS2_32, 'int', 'WSACancelAsyncRequest', 'handle', $aRet[0])
Return SetError(2, 10060, 0); WSAETIMEDOUT
EndIf
;
Local $WSAGETASYNCERROR = BitShift($WSAAsyncGetHostByName_lParam, 16)
If $WSAGETASYNCERROR Then
Return SetError(3, $WSAGETASYNCERROR, 0); WSAGetLastError code
EndIf
;
Local Const $tagHostent = 'ptr h_name;ptr h_aliases;short h_addrtype;short h_length;ptr h_addr_list'
Local $tHostent = DllStructCreate($tagHostent, DllStructGetPtr($tBuf))
If DllStructGetData($tHostent, 'h_addrtype') <> 2 Then; AF_INET
Return SetError(4, 0, 0)
EndIf
;
Local $ptrList = DllStructGetData($tHostent, 'h_addr_list')
If $ptrList = 0 Then
Return SetError(5, 0, 0)
EndIf
;
Local $tAddrList = DllStructCreate('ptr', $ptrList)
Local $tIPs = DllStructCreate('uint', DllStructGetData($tAddrList, 1))
Local $iIP = DllStructGetData($tIPs, 1)
If $iIP = 0 Then
Return SetError(6, 0, 0)
EndIf
;
$aRet = DllCall($hWS2_32, 'str', 'inet_ntoa', 'long', $iIP)
If @error Or Not $aRet[0] Then
Return SetError(7, _WSA_GetLastError(), 0)
Else
Return SetError(0, 0, $aRet[0])
EndIf
EndFunc
;
Func _WSAAsyncGetHostByName_Callback($hWnd, $iMsgID, $wParam, $lParam)
#forceref $hWnd, $iMsgID, $wParam
;
If $lParam Then
$WSAAsyncGetHostByName_lParam = $lParam
EndIf
EndFunc
;
Last edited by a moderator: