#include-once ; ;*************************************************************************************************** ;..........File: WSA_NBTCP.au3 (Windows Sockets API - Non-Blocking Transmission Control Protocol) ;.......Version: 1.00 ;.Project Dates: Start:2017-11-27 End:2018-01-15 ;...Released by: ripdad ;..............:------------------------------------------------------------------------------------ ;...Description: This is an accumulation of WSA code from many sources and modified to suit myself. ;..............: These functions have been thoroughly tested using a Local Proxy Server, which ;..............: is about the most strenuous test you can use. ;..............:------------------------------------------------------------------------------------ ;..Requirements; - AutoIt Versions: 3.3.8.1 thru 3.3.15.0 (32Bit only). ;..............: - TCPStartup() at beginning of script on startup. ;..............: - TCPShutDown() and _WSA_Cleanup() on exit. ;..............:------------------------------------------------------------------------------------ ;.......Credits: MSDN, ProgAndy, JScript, funkey and various websites, for gleaning technical ;..............: information about TCP and DLL calls. ;*************************************************************************************************** ; ; ;--------------------------------------------------- ; #CURRENT_USER_FUNCTIONS ;--------------------------------------------------- ; _WSA_Cleanup ; _WSA_FormatMessage ; _WSA_GetLastError ; _WSA_TCPAccept ; _WSA_TCPCloseSocket ; _WSA_TCPConnect ; _WSA_TCPListen ; _WSA_TCPRecv ; _WSA_TCPSend ; ;--------------------------------------------------- ; #INTERNAL_FUNCTIONS ;--------------------------------------------------- ; __TimeoutManager ; __TimeoutReset ; ;--------------------------------------------------- ; #EXTRA_FUNCTIONS ;--------------------------------------------------- ; _WSA_GetAddrInfo ; _WSA_GetHostByAddr ; _WSAAsyncGetHostByName ; _WSAAsyncGetHostByName_Callback ; _WSA_GetNameInfo ; ;--------------------------------------------------- ; #UDF SETUP ;--------------------------------------------------- If Not IsDeclared('hWS2_32') Then Local Const $hWS2_32 = DllOpen('Ws2_32.dll') If @error Then MsgBox(8208, 'WSA DLL ERROR', 'Ws2_32.dll') Exit EndIf EndIf ; Local $WSAAsyncGetHostByName_lParam Local $nResetTimer = 0, $IDXTO = 10 Local $aRecvTO[$IDXTO + 1][2] = [[$IDXTO, '']] ; ; ; ; ; #FUNCTION# *************************************************************************************** ; Name.........: _WSA_Cleanup() ;*************************************************************************************************** Func _WSA_Cleanup() DllClose($hWS2_32) EndFunc ; ; ; #FUNCTION# *************************************************************************************** ; Name.........: _WSA_FormatMessage() ;..............:------------------------------------------------------------------------------------ ; Modified.....: 2017-11-27 restructured ;..............:------------------------------------------------------------------------------------ ; Dependencies.: to be used with _WSA_GetLastError() returns ;*************************************************************************************************** Func _WSA_FormatMessage($nError) Switch Number($nError) Case 6, 8, 87, 995, 996, 997, 10004, 10009, 10013, 10014, 10022, 10024 Case 10036 To 10071, 10091 To 10093, 10101 To 10112, 11001 To 11031 Case Else Return $nError EndSwitch Local $aResult = DllCall('kernel32.dll', 'int', 'FormatMessage', 'dword', 0x00001000, 'ptr', 0, 'int', $nError, 'int', 0, 'str', '', 'int', 2048, 'ptr', 0) Return $nError & @CRLF & StringStripWS($aResult[5], 7) EndFunc ; ; ; #FUNCTION# ======================================================================================= ; Name.........: _WSA_GetLastError() ;..............:------------------------------------------------------------------------------------ ; Modified.....: 2017-11-27 restructured ;..............:------------------------------------------------------------------------------------ ; Dependencies.: a handle to ws2_32.dll ;=================================================================================================== Func _WSA_GetLastError() Local $aResult = DllCall($hWS2_32, 'int', 'WSAGetLastError') Local $nError = Number($aResult[0]) ; Switch $nError Case 6, 8, 87, 995, 996, 997, 10004, 10009, 10013, 10014, 10022, 10024 Case 10036 To 10071, 10091 To 10093, 10101 To 10112, 11001 To 11031 Case Else Return 0; <- no error EndSwitch Return $nError; <- valid WSA error EndFunc ; ; ; #FUNCTION# *************************************************************************************** ; Name.........: _WSA_TCPAccept() ;..............:------------------------------------------------------------------------------------ ; Version......: AutoIt v3.3.8.1+ (32bit) ;..............:------------------------------------------------------------------------------------ ; Dependencies.: a handle to ws2_32.dll, _WSA_GetLastError() ;..............:------------------------------------------------------------------------------------ ; Return Value.: @error and no socket returns 0, else returns a non-blocking accepted socket ;..............:------------------------------------------------------------------------------------ ; @error.......; -1 = dll error ;..............: -2 = socket error ;..............: else, WSA Error Code ;..............: ; .............: A list of WSA Error Codes can be found here: ;..............: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ;*************************************************************************************************** Func _WSA_TCPAccept($nListenSocket) ; Sleep(10); set idle speed (not a good idea for this function to be called in microseconds when idle - which is 99% of the time for this function) ; Local $tSockAddr = DllStructCreate('short sin_family;ushort sin_port;ulong s_addr;char sin_zero[8];') Local $nAddrLen = DllStructGetSize($tSockAddr) ; ;[try accept] Local $aResult = DllCall($hWS2_32, 'uint', 'accept', 'uint', $nListenSocket, 'struct*', $tSockAddr, 'int*', $nAddrLen) If @error Then Return SetError(-1, 0, 0); dll error ; ;[check for errors] Local $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ; Local $nSocket = $aResult[0] ; ;[process results] If ($nSocket < 1) Or ($nSocket = 4294967295) Then Return SetError(0, 0, 0); <- nothing to do EndIf ; ;[set non-blocking mode] Local $aResult = DllCall($hWS2_32, 'int', 'ioctlsocket', 'int', $nSocket, 'dword', 0x8004667E, 'uint*', 1) $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] <> 0 Then Return SetError(-2, 0, 0); socket error Else; <- success Return SetError(0, 0, $nSocket); return non-blocking socket EndIf EndFunc ; ; ; ; #FUNCTION# *************************************************************************************** ; Name.........: _WSA_TCPCloseSocket() ;..............:------------------------------------------------------------------------------------ ; Version......: AutoIt v3.3.8.1+ (32bit) ;..............:------------------------------------------------------------------------------------ ; Dependencies.: a handle to ws2_32.dll ;..............:------------------------------------------------------------------------------------ ; Return Value.: -1 = socket error, 0 = not a socket, else returns 1 (success) ;..............:------------------------------------------------------------------------------------ ; @error.......; -1 = socket error ;*************************************************************************************************** Func _WSA_TCPCloseSocket($nSocket) If (StringIsDigit($nSocket) < 1) Or ($nSocket < 1) Then Return SetError(0, 0, 0); not a socket EndIf ; Local $aResult = DllCall($hWS2_32, 'int', 'closesocket', 'int', $nSocket) If IsArray($aResult) Then If $aResult[0] <> 0 Then Return SetError(-1, 0, -1); socket error Else Return SetError(0, 0, 1); success EndIf EndIf EndFunc ; ; ; #FUNCTION# *************************************************************************************** ; Name.........: _WSA_TCPConnect() ;..............:------------------------------------------------------------------------------------ ; Version......: AutoIt v3.3.8.1+ (32bit) ;..............:------------------------------------------------------------------------------------ ; Description..: TCP socket connection (non-blocking) ;..............:------------------------------------------------------------------------------------ ; Dependencies.: a handle to ws2_32.dll, _WSA_GetLastError() ;..............:------------------------------------------------------------------------------------ ; Return Value.: @error returns 0, else returns a non-blocking connected socket ;..............:------------------------------------------------------------------------------------ ; @error.......; -1 = dll error ;..............: -2 = ip incorrect ;..............: -3 = port incorrect ;..............: -4 = socket error ;..............: else, WSA Error Code ;..............: ; .............: A list of WSA Error Codes can be found here: ;..............: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ;*************************************************************************************************** Func _WSA_TCPConnect($sIPAddress, $nPort) ; ;[get ip handle] Local $aResult = DllCall($hWS2_32, 'ulong', 'inet_addr', 'str', $sIPAddress) If @error Then Return SetError(-1, 0, -1); dll error Local $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] < 1 Or $aResult[0] = 4294967295 Then Return SetError(-2, 0, 0); ip incorrect Else; <- success, we have a ip handle Local $hIPAddr = $aResult[0] EndIf ; ;[get port handle] $aResult = DllCall($hWS2_32, 'ushort', 'htons', 'ushort', $nPort) $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] < 1 Then Return SetError(-3, 0, 0); port incorrect Else; <- success, we have a port handle Local $hPort = $aResult[0] 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, $hPort) DllStructSetData($tSockAddr, 3, $hIPAddr) Local $nSize = DllStructGetSize($tSockAddr) ; ;[create socket] $aResult = DllCall($hWS2_32, 'uint', 'socket', 'int', 2, 'int', 1, 'int', 6); AF_INET, SOCK_STREAM, IPPROTO_TCP $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] < 1 Or $aResult[0] = 4294967295 Then Return SetError(-4, 0, 0); socket error Else; <- success, we have a socket Local $nSocket = $aResult[0] EndIf ; ;[set non-blocking mode] $aResult = DllCall($hWS2_32, 'int', 'ioctlsocket', 'int', $nSocket, 'dword', 0x8004667E, 'uint*', 1) $nError = _WSA_GetLastError() If $nError Or $aResult[0] <> 0 Then _WSA_TCPCloseSocket($nSocket) Return SetError($nError, 0, 0); WSA Error Code EndIf ; ;[set timeout] Local $t1 = DllStructCreate('int;int') DllStructSetData($t1, 1, 1) DllStructSetData($t1, 2, $nSocket) Local $t2 = DllStructCreate('int;int') DllStructSetData($t2, 1, 5); <- 5 seconds DllStructSetData($t2, 2, 0); <- 0 microseconds ; ;[try connect] $aResult = DllCall($hWS2_32, 'int', 'connect', 'int', $nSocket, 'struct*', $tSockAddr, 'int', $nSize) $nError = _WSA_GetLastError() If $nError Then _WSA_TCPCloseSocket($nSocket) Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] > 0 Then _WSA_TCPCloseSocket($nSocket) Return SetError(-4, 0, 0); socket error EndIf ; ;[init timeout] $aResult = DllCall($hWS2_32, 'int', 'select', 'int', $nSocket, 'struct*', $t1, 'struct*', $t1, 'ptr', 0, 'struct*', $t2) $nError = _WSA_GetLastError() If $nError Then _WSA_TCPCloseSocket($nSocket) Return SetError($nError, 0, 0); WSA Error Code ElseIf Number($aResult[0]) = 0 Then Return SetError(10060, 0, 0); WSAETIMEDOUT Else Return SetError(0, 0, $nSocket); return non-blocking socket EndIf EndFunc ; ; ; #FUNCTION# *************************************************************************************** ; Name.........: _WSA_TCPListen() ;..............:------------------------------------------------------------------------------------ ; Version......: AutoIt v3.3.8.1+ (32bit) ;..............:------------------------------------------------------------------------------------ ; Dependencies.: a handle to ws2_32.dll, _WSA_GetLastError() ;..............:------------------------------------------------------------------------------------ ; Syntax.......: _WSA_TCPListen($sIPAddress, $nPort, $nMaxConnections) ;..............:------------------------------------------------------------------------------------ ; Return Value.: @error returns 0, else returns a non-blocking socket ;..............:------------------------------------------------------------------------------------ ; @error.......; -1 = dll error ;..............: -2 = ip incorrect ;..............: -3 = port incorrect ;..............: -4 = socket error ;..............: else, WSA Error Code ;..............: ; .............: A list of WSA Error Codes can be found here: ;..............: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ;*************************************************************************************************** Func _WSA_TCPListen($sIPAddress, $nPort, $nMaxConnections = 16) ; ;[get ip handle] Local $aResult = DllCall($hWS2_32, 'ulong', 'inet_addr', 'str', $sIPAddress) If @error Then Return SetError(-1, 0, 0); dll error ; ;[check for errors] Local $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] < 1 Or $aResult[0] = 4294967295 Then Return SetError(-2, 0, 0); ip incorrect Else Local $hIPAddr = $aResult[0] EndIf ; ;[get port handle] $aResult = DllCall($hWS2_32, 'ushort', 'htons', 'ushort', $nPort) $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] < 1 Then Return SetError(-3, 0, 0); port incorrect Else Local $hPort = $aResult[0] EndIf ; ;[create socket] $aResult = DllCall($hWS2_32, 'uint', 'socket', 'int', 2, 'int', 1, 'int', 6); AF_INET, SOCK_STREAM, IPPROTO_TCP $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] < 1 Or $aResult[0] = 4294967295 Then Return SetError(-4, 0, 0); Socket_Error Else Local $nSocket = $aResult[0] 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, $hPort) DllStructSetData($tSockAddr, 3, $hIPAddr) Local $nSize = DllStructGetSize($tSockAddr) ; $aResult = DllCall($hWS2_32, 'int', 'bind', 'int', $nSocket, 'struct*', $tSockAddr, 'int', $nSize) $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] <> 0 Then Return SetError(-4, 0, 0); Socket_Error EndIf ; ;[try listen] $aResult = DllCall($hWS2_32, 'int', 'listen', 'int', $nSocket, 'int', $nMaxConnections) $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] <> 0 Then _WSA_TCPCloseSocket($nSocket) Return SetError(-4, 0, 0); Socket_Error EndIf ; ;[set non-blocking mode] $aResult = DllCall($hWS2_32, 'int', 'ioctlsocket', 'int', $nSocket, 'dword', 0x8004667E, 'uint*', 1) $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] <> 0 Then _WSA_TCPCloseSocket($nSocket) Return SetError(-4, 0, 0); Socket_Error Else Return SetError(0, 0, $nSocket); return non-blocking socket EndIf EndFunc ; ; ; #FUNCTION# *************************************************************************************** ; Name.........: _WSA_TCPRecv() ;..............:------------------------------------------------------------------------------------ ; Modified.....: 2017-11-27 restructured for non-blocking sockets with a timeout. ;..............:------------------------------------------------------------------------------------ ; Version......: AutoIt v3.3.8.1+ (32bit) ;..............:------------------------------------------------------------------------------------ ; Dependencies.: a handle to ws2_32.dll, _WSA_GetLastError(), __TimeoutReset(), __TimeoutManager() ;..............:------------------------------------------------------------------------------------ ; Syntax.......: _WSA_TCPRecv($nSocket, $nMaxLen, $nBinaryMode, $nTimeout) ;..............:------------------------------------------------------------------------------------ ; Parameters...; ($nSocket) ;..............: An active TCP/IP socket. ;..............:------------------------------------------------------------------------------------ ;..............: ($nMaxLen) ;..............: The maximum number of bytes to receive. (default: 65536) 64kb's ;..............: ;..............: [REMARKS] ;..............: You may read that 65535 is the maximum value here. That only applies to UDP. ;..............: In reality, TCP streams can be set higher. But not so high that you can't ;..............: manage the incoming data efficiently. ;..............: ;..............: The lower the number, the slower the speed of receiving data. ;..............: For instance: Receiving a 100mb string at 65536 on a local network, ;..............: will finish in about 25 seconds. Using 8192, it will finish in about ;..............: 200 seconds. ;..............: ;..............: For smaller strings, like 50 kb's or lower, 8192 is okay, but for ;..............: strings larger than that, you would need to use a higher setting. ;..............: ;..............: Web pages these days can be 100 kb's to 1 or 2 mb's in size. ;..............: 16384 or 32768 would be suitable for those. Anything much larger ;..............: than that needs to be at 65536. ;..............: ;..............: Of course, when downloading from the web, you are at the mercy of ;..............: whatever speed the remote server is programmed to send. ;..............:------------------------------------------------------------------------------------ ;..............: ($nBinaryMode) ;..............: 0 = receive raw data (default) ;..............: 1 = receive binary data ;..............:------------------------------------------------------------------------------------ ;..............: ($nTimeout) ;..............: 0 = do not use timeout ;..............: >0 = seconds (default: 10) ;..............: ;..............: [REMARKS] ;..............: If data is resumed within the timeout period, the timeout timer cancels. ;..............: If a timeout occurs, it will return a 10060 error. (WSAETIMEDOUT) ;..............: It's up to you to close the socket as with any error. ;..............:------------------------------------------------------------------------------------ ; Return Value.: data when available, else returns blank ;..............: ;..............: [REMARKS] ;..............: This function will return immediately whether data is received or not. ;..............: Which is mainly used for multiple socket operations. This is so there ;..............: won't be any delays or freezing or hanging with a GUI. ;..............:------------------------------------------------------------------------------------ ; @extended....; number of bytes received ;..............:------------------------------------------------------------------------------------ ; @error.......; -1 = dll error, else WSA Error Code ;..............: ; .............: A list of WSA Error Codes can be found here: ;..............: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ;*************************************************************************************************** Func _WSA_TCPRecv($nSocket, $nMaxLen = 65536, $nBinaryMode = 0, $nTimeout = 10) ; ;[set buffer type] If $nBinaryMode Then Local $tBuffer = DllStructCreate('byte[' & $nMaxLen & ']') Else Local $tBuffer = DllStructCreate('char[' & $nMaxLen & ']') EndIf ; ;[try receive] Local $aResult = DllCall($hWS2_32, 'int', 'recv', 'int', $nSocket, 'struct*', $tBuffer, 'int', $nMaxLen, 'int', 0) If @error Then Return SetError(-1, 0, '') ; ;[check for errors] Local $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, ''); WSA Error Code ; Local $nBytes = Number($aResult[0]) Local $sData = '' ; ;[process results] If $nBytes > 0 Then; data received $sData = DllStructGetData($tBuffer, 1) If $nBinaryMode Then $sData = StringLeft($sData, ($nBytes * 2) + 2); extract binary data Else $sData = StringLeft($sData, $nBytes); extract raw data EndIf ElseIf $nBytes = 0 Then $nError = 10054; disconnected Else $nBytes = 0; no data received EndIf ; ;[process timeout] If $nTimeout > 0 Then If $nError <> 0 Then __TimeoutManager($nSocket, 0, 0, 1); reset settings to 0 ElseIf $nBytes = 0 Then; no data received If __TimeoutManager($nSocket, $nTimeout, 0, 0) <> 0 Then; get timeout status $nError = 10060; WSAETIMEDOUT EndIf Else; receiving data __TimeoutManager($nSocket, 0, 1, 0); reset timeout to 0 EndIf EndIf ; Return SetError($nError, $nBytes, $sData) EndFunc ; ; ; #FUNCTION# *************************************************************************************** ; Name.........: _WSA_TCPSend() ;..............:------------------------------------------------------------------------------------ ; Modified.....: 2017-11-27 restructured for non-blocking sockets ;..............:------------------------------------------------------------------------------------ ; Version......: AutoIt v3.3.8.1+ (32bit) ;..............:------------------------------------------------------------------------------------ ; Dependencies.: a handle to ws2_32.dll, _WSA_GetLastError() ;..............:------------------------------------------------------------------------------------ ; Return Value.: number of bytes sent ;..............:------------------------------------------------------------------------------------ ; @extended....; number of bytes sent ;..............:------------------------------------------------------------------------------------ ; @error.......; -1 = dll error, else WSA Error Code ;..............: ; .............: A list of WSA Error Codes can be found here: ;..............: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx ;*************************************************************************************************** Func _WSA_TCPSend($nSocket, $sData, $nBinaryMode = 0) ; Local $nBytes = StringLen($sData) If $nBytes < 1 Then Return SetError(0, 0, 0); <- nothing to do ; ;[set buffer type] If $nBinaryMode Then Local $tBuffer = DllStructCreate('byte[' & $nBytes & ']') Else Local $tBuffer = DllStructCreate('char[' & $nBytes & ']') EndIf ; DllStructSetData($tBuffer, 1, $sData) Local $nSize = DllStructGetSize($tBuffer) ; ;[set timeout] Local $t1 = DllStructCreate('int;int') DllStructSetData($t1, 1, 1) DllStructSetData($t1, 2, $nSocket) Local $t2 = DllStructCreate('int;int') DllStructSetData($t2, 1, 10); <- 10 seconds DllStructSetData($t2, 2, 0); <- 0 microseconds ; ;[try send] Local $aResult = DllCall($hWS2_32, 'int', 'send', 'int', $nSocket, 'struct*', $tBuffer, 'int', $nSize, 'int', 0) If @error Then Return SetError(-1, 0, 0); dll error ; ;[check for errors] Local $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ; ;[init timeout] (dual purpose call: [1] time-wait until buffer is empty with ACK. [2] time-out when server doesn't respond.) Local $aSelect = DllCall($hWS2_32, 'int', 'select', 'int', $nSocket, 'struct*', $t1, 'struct*', $t1, 'ptr', 0, 'struct*', $t2) ; ;[check for errors] $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ; ;[check for timeout] If Number($aSelect[0]) = 0 Then Return SetError(10060, 0, 0); WSAETIMEDOUT ; ;[process results] $nBytes = Number($aResult[0]) If $nBytes > 0 Then; bytes sent ; pass through ElseIf $nBytes = 0 Then $nError = 10054; disconnected Else $nBytes = 0; no bytes sent EndIf ; Return SetError($nError, $nBytes, $nBytes) EndFunc ; ; ; ;*************************************************************************************************** ; INTERNAL FUNCTIONS ;*************************************************************************************************** ; ; The two functions below have no direct effect on the operations of TCP. ; Both functions only handle the recv timeout array. ; ; ; ; ; #FUNCTION# *************************************************************************************** ; Name.........: __TimeoutManager() ;..............:------------------------------------------------------------------------------------ ; Description..: This function handles timeouts for each socket from _WSA_TCPRecv() ;*************************************************************************************************** Func __TimeoutManager($nSocket, $nTimeout, $nReset = 0, $nError = 0) ; If $nResetTimer = 0 Then AdlibRegister('__TimeoutReset', 5100); poll every 5 seconds EndIf $nResetTimer = TimerInit() ; ; process an existing socket For $ix = 1 To $IDXTO If $aRecvTO[$ix][0] <> $nSocket Then ContinueLoop EndIf ; If $nError <> 0 Then $aRecvTO[$ix][0] = 0; reset settings $aRecvTO[$ix][1] = 0 Return 0 ElseIf $nReset <> 0 Then $aRecvTO[$ix][1] = 0; cancel timeout Return 0 ElseIf $aRecvTO[$ix][1] < 1 Then $aRecvTO[$ix][1] = TimerInit() Return 0 ElseIf TimerDiff($aRecvTO[$ix][1]) > ($nTimeout * 1000) Then $aRecvTO[$ix][0] = 0 $aRecvTO[$ix][1] = 0 Return 1; trigger a timeout Else Sleep(10); idle speed Return 0; timeout in progress EndIf Next ; ; add new socket to array For $ix = 1 To $IDXTO If $aRecvTO[$ix][0] > 0 Then ContinueLoop EndIf ; If ($ix + 2) > $IDXTO Then $IDXTO += 5 ReDim $aRecvTO[$IDXTO + 1][2] EndIf ; $aRecvTO[$ix][0] = $nSocket $aRecvTO[$ix][1] = 0 Return 0 Next EndFunc ; ; ; #FUNCTION# *************************************************************************************** ; Name.........: __TimeoutReset() ;..............:------------------------------------------------------------------------------------ ; Description..: This function resizes the array to keep it from growing over time and zeros all ;..............: elements of stray socket numbers, if they exist. ;*************************************************************************************************** Func __TimeoutReset() ; If TimerDiff($nResetTimer) > 5000 Then; inactive for 5 seconds ; If $IDXTO > 10 Then $IDXTO = 10 ReDim $aRecvTO[$IDXTO + 1][2]; resize array $aRecvTO[0][0] = $IDXTO EndIf ; For $ix = 1 To $IDXTO $aRecvTO[$ix][0] = 0; zero elements $aRecvTO[$ix][1] = 0 Next ; AdlibUnRegister('__TimeoutReset') $nResetTimer = 0 EndIf EndFunc ; ; ; ; ;##################### ;# EXTRA_FUNCTIONS # ;##################### ; ; ; ;*************************************************************************************************** ; Original Function: _getaddrinfo() by funkey 2014.06.04 ; https://www.autoitscript.com/forum/topic/161820-using-ipaddress-macros-to-determine-if-a-computer-moved-to-another-network/?do=findComment&comment=1175304 ; ; Related..: TCPNameToIP() ; Status...: Current via Microsoft ; Remarks..: Limited to IPv4 Only - Single I.P. ; Modified.: 2015-08-15 by ripdad ;*************************************************************************************************** Func _WSA_GetAddrInfo($sHostName) Local $aResult = DllCall($hWS2_32, 'int', 'getaddrinfo', 'str', $sHostName, 'ptr', 0, 'ptr', 0, 'ptr*', 0) If @error Then Return SetError(-1, 0, 0) Local $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0) EndIf ; Local $hResult = $aResult[4] Local $tAddr = DllStructCreate('int ai_flags;int ai_family;int ai_socktype;int ai_protocol;uint ai_addrlen;ptr ai_canonname;ptr ai_addr', $hResult) Local $tName = DllStructCreate('short sin_family;USHORT sin_port;ULONG sin_addr;char sin_zero[8]', DllStructGetData($tAddr, 'ai_addr')) $aResult = DllCall('ws2_32.dll', 'str', 'inet_ntoa', 'ptr', DllStructGetData($tName, 'sin_addr')) DllCall($hWS2_32, 'none', 'freeaddrinfo', 'ptr', $hResult) Return $aResult[0] EndFunc ; ; ; ;*************************************************************************************************** ; Original Function: _WSAAsyncGetHostByName_Timeout() by funkey 2015.04.13 ; https://www.autoitscript.com/forum/topic/169440-getaddrinfo-timeout/#comment-1239246 ; ; Related..: TCPNameToIP() ; Status...: Current via Microsoft ; Remarks..: Limited to IPv4 Only - Single I.P. ; Modified.: 2015-07-30, 2018-01-15 by ripdad ;*************************************************************************************************** Func _WSAAsyncGetHostByName($sHostName, $hGUI) Local Const $wMsg = BitOR(0x400, 0x99); WM_USER Local $tBuf = DllStructCreate('char buffer[1024]') ; $WSAAsyncGetHostByName_lParam = 0 GUIRegisterMsg($wMsg, '_WSAAsyncGetHostByName_Callback') ; Local $aResult = DllCall($hWS2_32, 'handle', 'WSAAsyncGetHostByName', 'hwnd', $hGUI, 'uint', $wMsg, 'str', $sHostName, 'struct*', $tBuf, 'int', 1024) If @error Or Not $aResult[0] Then GUIRegisterMsg($wMsg, '') Return SetError(-1, _WSA_GetLastError(), 0) EndIf ; For $iTime = 1 To 320; ~ 5 seconds If $WSAAsyncGetHostByName_lParam <> 0 Then ExitLoop EndIf Sleep(10) Next ; GUIRegisterMsg($wMsg, '') ; If $iTime >= 320 Then DllCall($hWS2_32, 'int', 'WSACancelAsyncRequest', 'handle', $aResult[0]) Return SetError(-2, 10060, 0); WSAETIMEDOUT EndIf ; Local $WSAGETASYNCERROR = BitShift($WSAAsyncGetHostByName_lParam, 16) If $WSAGETASYNCERROR Then Return SetError(-3, $WSAGETASYNCERROR, 0); WSA Error code EndIf ; Local $tHostent = DllStructCreate('ptr h_name;ptr h_aliases;short h_addrtype;short h_length;ptr h_addr_list', 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 ; $aResult = DllCall($hWS2_32, 'str', 'inet_ntoa', 'long', $iIP) If @error Or Not $aResult[0] Then Return SetError(-7, _WSA_GetLastError(), 0) Else Return SetError(0, 0, $aResult[0]) EndIf EndFunc ; Func _WSAAsyncGetHostByName_Callback($hWnd, $iMsgID, $wParam, $lParam) #forceref $hWnd, $iMsgID, $wParam ; If $lParam Then $WSAAsyncGetHostByName_lParam = $lParam EndIf EndFunc ; ; ; ;*************************************************************************************************** ; Name.....: _WSA_GetNameInfo() ; Related..: TCPIPToName() ; Status...: Current via Microsoft ; Modified.: 2017-07-30 by ripdad ;*************************************************************************************************** Func _WSA_GetNameInfo($sIPAddress, $nPort) ; ;[get ip handle] Local $aResult = DllCall($hWS2_32, 'ulong', 'inet_addr', 'str', $sIPAddress) If @error Then Return SetError(-1, 0, 0); dll error ; ;[check for errors] Local $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] < 1 Or $aResult[0] = 4294967295 Then Return SetError(-2, 0, 0); ip incorrect Else Local $hIPAddr = $aResult[0] EndIf ; ;[get port handle] $aResult = DllCall($hWS2_32, 'ushort', 'htons', 'ushort', $nPort) $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] < 1 Then Return SetError(-3, 0, 0); port incorrect Else Local $hPort = $aResult[0] EndIf ; ;[set struct] Local $tSockAddr = DllStructCreate('short sin_family;ushort sin_port;ulong sin_addr;char sin_zero[8];') DllStructSetData($tSockAddr, 1, 2); AF_INET DllStructSetData($tSockAddr, 2, $hPort) DllStructSetData($tSockAddr, 3, $hIPAddr) ; Local $tHost = DllStructCreate('char[1025]'); NI_MAXHOST Local $tServ = DllStructCreate('char[32]'); NI_MAXSERV ; Local $p1 = DllStructGetPtr($tSockAddr); sa[in] Local $s1 = DllStructGetSize($tSockAddr); salen[in] Local $p2 = DllStructGetPtr($tHost); host[out] Local $s2 = DllStructGetSize($tHost); hostlen[in] Local $p3 = DllStructGetPtr($tServ); serv[out] Local $s3 = DllStructGetSize($tServ); servlen[in] Local $fg = 0x0004; flags[in] NI_NOFQDN ; $aResult = DllCall($hWS2_32, 'int', 'getnameinfo', 'ptr', $p1, 'int', $s1, 'ptr', $p2, 'dword', $s2, 'ptr', $p3, 'dword', $s3, 'int', $fg) $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0); WSA Error Code ElseIf $aResult[0] <> 0 Then Return SetError(-4, 0, 0); failed Else Return DllStructGetData($tHost, 1) EndIf EndFunc ; ; ; ;*************************************************************************************************** ; Name.....: _WSA_GetHostByAddr() ; Related..: TCPIPToName() ; Status...: Deprecated via Microsoft (still works though) ; Modified.: 2017-07-29 by ripdad ;*************************************************************************************************** Func _WSA_GetHostByAddr($sIPAddress) Local $aResult = DllCall($hWS2_32, 'ulong', 'inet_addr', 'str', $sIPAddress) If @error Then Return SetError(-1, 0, 0) If $aResult[0] < 0 Then Return SetError(-2, 0, 0) ; $aResult = DllCall($hWS2_32, 'ptr', 'gethostbyaddr', 'ptr*', $aResult[0], 'int', 4, 'int', 2) Local $nError = _WSA_GetLastError() If $nError Then Return SetError($nError, 0, 0) ; Local $tHostent = DllStructCreate('ptr;ptr;short;short;ptr', $aResult[0]) Local $tStruct = DllStructCreate('char[128]', DllStructGetData($tHostent, 1)) Return DllStructGetData($tStruct, 1) EndFunc ;