Jump to content
Sign in to follow this  
matrix200

TCPConnect timeout

Recommended Posts

i belive that Kips will still hang on an invalid tcpconnect for ~10 seconds before fail, i need something that A. return imediatly and the status can be checked on, or a way to adjust settings that are embedded into TCP... i vote for the earlier... this winsock stuff is the way to go, im building a UDF to replace TCPConnect and TCPSend (i cant figure out anyway to use autoit TCPSend with the winsock TCPConnect) but im not a pro with this stuff so any help would be apreciated, here is what i have:

Global Const $SCKTCPPROTOCOL = 0
Global Const $SCKUDPPROTOCOL = 0x01
Global Const $SCKCLOSED = 0
Global Const $SCKOPEN = 0x01
Global Const $SCKLISTENING = 0x02
Global Const $SCKCONNECTIONPENDING = 0x03
Global Const $SCKRESOLVINGHOST = 0x04
Global Const $SCKHOSTRESOLVED = 0x05
Global Const $SCKCONNECTING = 0x06
Global Const $SCKCONNECTED = 0x07
Global Const $SCKCLOSING = 0x08
Global Const $SCKERROR = 0x09

Func _TCPStartup()
    FileInstall("_OSWINSCK.dll",@scriptDir & "\_OSWINSCK.dll",1)
    FileInstall("_OSWINSCK.txt",@scriptDir & "\_OSWINSCK.txt",1)
    $runstring = "regsvr32 /s """ & @scriptDir & "\_OSWINSCK.dll"""
    $status = RunWait(@ComSpec & " /C " & $runstring, "", @SW_HIDE)
    return $status 
EndFunc

Func _TCPConnect($sAddr, $iPort, $iTimeout=100)
    Local $oSocket, $timer
    $oSocket = ObjCreate("OSWINSCK.Winsock")

    $oSocket.Protocol = $SCKTCPPROTOCOL; set protocol to be tcp
    $timer = TimerInit()
    $oSocket.Connect($sAddr, $iPort)

    While 1

        If $oSocket.State = $SCKERROR Then
            $oSocket = 0
            Return -2;connection error (will give up for now)
        EndIf

        If $oSocket.State = $SCKCONNECTED Then
            Return $oSocket; return object for connection
        EndIf

        If TimerDiff($timer) > $iTimeout Then
            $oSocket = 0
            Return -3; connection timeout
        EndIf

        Sleep(20)
    WEnd

EndFunc

Func _TCPSend($oSocket,$sData)
    $oSocket.SendData($sData)
EndFunc

the issue is that i dont see how to return the amount of data sent

other then that it works great, just need a socket close function

Share this post


Link to post
Share on other sites

ok so i dove in a bit on this COM stuff, but now im stuck, i just cant figure out how to retrieve recieved data

Func _TCP_OnDataArrival($Len)
    While 1
        $data=$ConnectSocket.GetDataBuffer
        If $data<>"" Then ExitLoop
    WEnd
    MsgBox(0,"Len/Dat",$Len&@CRLF&$data)
EndFunc

or

Func _TCP_OnDataArrival($Len)
    While 1
        $ConnectSocket.GetData($data,"vbLong",1024)
        If $data<>"" Then ExitLoop
    WEnd
    MsgBox(0,"Len/Dat",$Len&@CRLF&$data)
EndFunc

object.GetData(data, [vtype], [maxLen])

Retrieve data sent by the remote computer (acceptable values for vtype parameter are vbByte, vbInteger, vbLong, vbSingle, vbDouble, vbCurrency, vbDate, vbBoolean, vbError, vbString, vbArray + vbByte)

object.GetDataBuffer()

Returns data sent by the remote computer (For use in Javascript and similar languages, not supporting return parameters in functions)

the above functions are successfuly called when the data is recieved, and without the while loop $len will return the proper length, but i just cant GET the data... as you see in the quote from OstroSoft, object.GetData has some parameters, and im not sure if ive used them right.... any ideas?

Edited by JohnMC

Share this post


Link to post
Share on other sites

Try this, it cycles from 100ms to 500ms in 50ms steps. On my local lan connecting to a telnet server, 100ms port timeout is reliable. For yahoo reliable connection requires port timeout > 200ms.

#cs;========================================
    
    TCP PortScan example by Picaxe for TCP UDF V3.3.0.0 by Kip
    
    Server/Client Test usage: supply cmdline params as follows
    To start server:    Program_name server
    To start client:    Program_name client server_ipaddr
    
    To test on one computer, compile and run
    Program_name server
    Program_name client     (default server is local ipaddr)
    
    ;========================================
    TCP UDF V3 Functions:
    ;========================================
    _TCP_Server_Create($iPort, $sIP="0.0.0.0")
    _TCP_Server_Broadcast($sData)
    _TCP_Server_ClientList()
    _TCP_Server_ClientIP($hSocket)
    _TCP_Server_DisconnectClient($hSocket)
    _TCP_Server_Stop()
    
    _TCP_Client_Create($sIP , $iPort)
    _TCP_Client_Stop($hSocket)
    
    _TCP_Send($hSocket, $sText)
    _TCP_RegisterEvent($hSocket, $iEvent, $sFunction)
    
    Register $iEvent values:
    $TCP_SEND               ; Function ($hSocket, $iError)
    $TCP_RECEIVE            ; Function ($hSocket, $sReceived, $iError)
    $TCP_CONNECT            ; Function ($hSocket, $iError)                  => Client only
    $TCP_DISCONNECT         ; Function ($hSocket, $iError)
    $TCP_NEWCLIENT          ; Function ($hSocket, $iError)                  => Server only
#ce;========================================

Global Const $FD_READ = 1
Global Const $FD_WRITE = 2
Global Const $FD_OOB = 4
Global Const $FD_ACCEPT = 8
Global Const $FD_CONNECT = 16
Global Const $FD_CLOSE = 32
Local $hWs2_32 = -1

Global Const $TCP_SEND = 1
Global Const $TCP_RECEIVE = 2
Global Const $TCP_CONNECT = 4
Global Const $TCP_DISCONNECT = 8
Global Const $TCP_NEWCLIENT = 16
Global Const $__TCP_WINDOW = GUICreate("Async Sockets UDF")
Global $__TCP_SOCKETS[1][7]

Global $fBinary = 0 ; TCPrecv binary flag 0=string/binary auto, 1=binary
Global $iBuffer = 4096 ; TCPrecv receive buffer maxlen
Global $fExit = False
Global $fServerFound = False
Global $hClientSkt = 0, $hServerSkt = 0, $iScanP, $sClientRec = "", $sSvrRec = "", $iSvrRecCnt = 0, $iClientRecCnt = 0
Global $sIp, $iConnectPort
Global $aPort = StringSplit("260,23,100,110,80,25", ",") ; telnet=23, pop3=110, http=80, smtp=25

TCPStartup()
$sIPName = "www.yahoo.com"
;~ $sIPName = "192.168.0.1"
$sIp = TCPNameToIP($sIPName)
HotKeySet("!{ESC}", "HotKeyExit") ; exit key is alt-esc
_Client()

Func HotKeyExit()
    $fExit = True
    _TCP_Client_Stop($hClientSkt)
    TCPShutdown()
EndFunc   ;==>HotKeyExit

;========================================
; Client example
;========================================
;#include "TCP.au3"
Func _Client()
    $iRecDly = 100
    $iScanP = 1
    Do
        If Not $fServerFound Then
            $hClientSkt = _TCP_Client_Create($sIp, $aPort[$iScanP])
            _TCP_RegisterEvent($hClientSkt, $TCP_RECEIVE, "ClientReceived")
            _TCP_RegisterEvent($hClientSkt, $TCP_CONNECT, "ClientConnected")
            _TCP_RegisterEvent($hClientSkt, $TCP_DISCONNECT, "ClientDisconnected")
            Sleep($iRecDly)
            If Not $fServerFound Then
                ToolTip("CLIENT: Connecting to " & $sIPName & " on port=" & $aPort[$iScanP] & " timeout=" & $iRecDly & "ms", 0, 20)
                _TCP_Client_Stop($hClientSkt)
            EndIf
            $iScanP += 1
            If $iScanP = $aPort[0] + 1 Then
                $iScanP = 1
                $iRecDly += 50
                If $iRecDly > 500 Then $iRecDly = 100
            EndIf
        EndIf
        Sleep(10)
    Until $fExit
EndFunc   ;==>_Client

Func ClientReceived($hClientSkt, $sReceived, $iError)
    $sClientRec = "CLIENT: Connected to " & $sIPName & " on Port:" & $iConnectPort _
        & @LF & 'First 100 characters received from ' & $sIPName & @LF & @LF & '"' & StringLeft($sReceived, 100) & '"' _
        & @LF & @LF & 'Rescaning in 4sec  Alt-Esc to Exit'
    ToolTip($sClientRec, 0, 20)
    _TCP_Client_Stop($hClientSkt)
    Sleep(3500)
    $fServerFound = False
EndFunc   ;==>ClientReceived

Func ClientConnected($hClientSkt, $iError)
    If Not $iError Then
        $fServerFound = True
        $iConnectPort = $aPort[$iScanP] 
        ToolTip("CLIENT: Connected to " & $sIPName & " on Port:" & $iConnectPort & " resuming scan in 3sec   Alt-Esc to Exit", 0, 20); ... we're connected.
        Switch $iConnectPort
            Case 80
                _TCP_Send($hClientSkt, "GET /index.html HTTP/1.0" & @CRLF & @CRLF)
            Case 23
                _TCP_Send($hClientSkt, @CRLF)
            Case 110
                
            Case Else
                
        EndSwitch
    EndIf
EndFunc   ;==>ClientConnected

Func ClientDisconnected($hClientSkt, $iError)
    $fServerFound = False
    _TCP_Client_Stop($hClientSkt)
EndFunc   ;==>ClientDisconnected

; valid ip returns 0
Func _IsValidIP($sIpaddr)
    $aAry = StringSplit($sIpaddr, ".")
    If $aAry[0] <> 4 Then Return 1
    For $i = 1 To $aAry[0]
        If $aAry[$i] < 0 Or $aAry[$i] > 255 Then Return 2
    Next
    Return 0
EndFunc   ;==>_IsValidIP

;========================================
; Code from Telnet Server TCP UDF V3.3.0.0 by Kip
;========================================
Func _TCP_Server_Create($iPort, $sIp = "0.0.0.0")
    TCPStartup()
    $hListenSocket = _ASocket()
    _ASockSelect($hListenSocket, $__TCP_WINDOW, 0x0400, $FD_ACCEPT)
    GUIRegisterMsg(0x0400, "__TCP_OnAccept")
    _ASockListen($hListenSocket, $sIp, $iPort)
    $__TCP_SOCKETS[0][0] = $hListenSocket
    $__TCP_SOCKETS[0][1] = 0x0400
    Return $hListenSocket
EndFunc   ;==>_TCP_Server_Create
Func __TCP_OnAccept($hWnd, $iMsgID, $WParam, $LParam)
    Local $hSocket = $WParam
    Local $iError = _HiWord($LParam)
    Local $iEvent = _LoWord($LParam)
    If $iMsgID = $__TCP_SOCKETS[0][1] Then
        If $iEvent = $FD_ACCEPT Then
            If Not $iError Then
                ReDim $__TCP_SOCKETS[UBound($__TCP_SOCKETS) + 1][7]
                $uBound = UBound($__TCP_SOCKETS)
                $hClient = TCPAccept($hSocket)
                _ASockSelect($hClient, $__TCP_WINDOW, 0x0400 + $uBound - 1, BitOR($FD_READ, $FD_WRITE, $FD_CLOSE))
                GUIRegisterMsg(0x0400 + $uBound - 1, "__TCP_Server_OnSocketEvent")
                $__TCP_SOCKETS[UBound($__TCP_SOCKETS) - 1][0] = $hClient
                $__TCP_SOCKETS[UBound($__TCP_SOCKETS) - 1][1] = 0x0400 + $uBound - 1
                Call($__TCP_SOCKETS[0][6], $hClient, $iError)
            Else
                Call($__TCP_SOCKETS[0][6], 0, $iError)
            EndIf
        ElseIf $iEvent = $FD_CONNECT Then
            Call($__TCP_SOCKETS[0][4], $hSocket, $iError)
        EndIf
    EndIf
EndFunc   ;==>__TCP_OnAccept
Func _TCP_Client_Stop($hSocket)
    $iElement = 0
    For $i = 1 To UBound($__TCP_SOCKETS) - 1
        If $__TCP_SOCKETS[$i][0] = $hSocket Then
            $iElement = $i
            ExitLoop
        EndIf
    Next
    If $iElement Then
        _ASockShutdown($__TCP_SOCKETS[$iElement][0])
        TCPCloseSocket($__TCP_SOCKETS[$iElement][0])
        ___ArrayDelete($__TCP_SOCKETS, $iElement)
        Return 1
    EndIf
    Return 0
EndFunc   ;==>_TCP_Client_Stop
Func _TCP_Server_Stop()
    _ASockShutdown($__TCP_SOCKETS[0][0])
    TCPCloseSocket($__TCP_SOCKETS[0][0])
    $__TCP_SOCKETS[0][0] = ""
    $__TCP_SOCKETS[0][1] = ""
    $__TCP_SOCKETS[0][2] = ""
    $__TCP_SOCKETS[0][3] = ""
    $__TCP_SOCKETS[0][4] = ""
    $__TCP_SOCKETS[0][5] = ""
    $__TCP_SOCKETS[0][6] = ""
    For $i = UBound($__TCP_SOCKETS) - 1 To 1 Step -1
        ___ArrayDelete($__TCP_SOCKETS, $i)
    Next
    Return 1
EndFunc   ;==>_TCP_Server_Stop
Func __TCP_Server_OnSocketEvent($hWnd, $iMsgID, $WParam, $LParam)
    Local $hSocket = $WParam
    Local $iError = _HiWord($LParam)
    Local $iEvent = _LoWord($LParam)
    Local $sDataBuff
    $hSocket = 0
    $iElement = 0
    For $i = 1 To UBound($__TCP_SOCKETS) - 1
        If $__TCP_SOCKETS[$i][1] = $iMsgID Then
            $hSocket = $__TCP_SOCKETS[$i][0]
            $iElement = $i
            ExitLoop
        EndIf
    Next
    If $hSocket Then
        Switch $iEvent
            Case $FD_READ
                $sDataBuff = TCPRecv($hSocket, $iBuffer, $fBinary)
                Call($__TCP_SOCKETS[0][2], $hSocket, $sDataBuff, $iError)
            Case $FD_WRITE
                Call($__TCP_SOCKETS[0][3], $hSocket, $iError)
            Case $FD_CLOSE
                _ASockShutdown($hSocket)
                TCPCloseSocket($hSocket)
                Call($__TCP_SOCKETS[0][5], $hSocket, $iError)
                ___ArrayDelete($__TCP_SOCKETS, $iElement)
        EndSwitch
    EndIf
EndFunc   ;==>__TCP_Server_OnSocketEvent
Func _TCP_Server_DisconnectClient($hSocket)
    $iElement = 0
    For $i = 1 To UBound($__TCP_SOCKETS) - 1
        If $__TCP_SOCKETS[$i][0] = $hSocket Then
            $iElement = $i
            ExitLoop
        EndIf
    Next
    If $iElement Then
        _ASockShutdown($hSocket)
        TCPCloseSocket($hSocket)
        ___ArrayDelete($__TCP_SOCKETS, $iElement)
        Return 1
    EndIf
    Return 0
EndFunc   ;==>_TCP_Server_DisconnectClient
Func _TCP_Server_ClientList()
    Local $aReturn[1]
    For $i = 1 To UBound($__TCP_SOCKETS) - 1
        If $__TCP_SOCKETS[$i][0] Then
            ReDim $aReturn[UBound($aReturn) + 1]
            $aReturn[UBound($aReturn) - 1] = $__TCP_SOCKETS[$i][0]
        EndIf
    Next
    $aReturn[0] = UBound($aReturn) - 1
    Return $aReturn
EndFunc   ;==>_TCP_Server_ClientList
Func _TCP_Server_Broadcast($sData)
    For $i = 1 To UBound($__TCP_SOCKETS) - 1
        If $__TCP_SOCKETS[$i][0] Then TCPSend($__TCP_SOCKETS[$i][0], $sData)
    Next
EndFunc   ;==>_TCP_Server_Broadcast
Func _TCP_Client_Create($sIp, $iPort)
    ReDim $__TCP_SOCKETS[UBound($__TCP_SOCKETS) + 1][7]
    $uBound = UBound($__TCP_SOCKETS)
    $hSocket = _ASocket()
    $__TCP_SOCKETS[UBound($__TCP_SOCKETS) - 1][0] = $hSocket
    $__TCP_SOCKETS[UBound($__TCP_SOCKETS) - 1][1] = 0x0400 + (UBound($__TCP_SOCKETS) - 1)
    _ASockSelect($hSocket, $__TCP_WINDOW, 0x0400 + (UBound($__TCP_SOCKETS) - 1), BitOR($FD_READ, $FD_WRITE, $FD_CONNECT, $FD_CLOSE))
    GUIRegisterMsg(0x0400 + (UBound($__TCP_SOCKETS) - 1), "__TCP_Client_OnSocketEvent")
    _ASockConnect($hSocket, $sIp, $iPort)
    Return $hSocket
EndFunc   ;==>_TCP_Client_Create
Func _TCP_RegisterEvent($hSocket, $iEvent, $sFunction)
    Local $iSelected = 0
    ;_ArrayDisplay($__TCP_SOCKETS)
    If $__TCP_SOCKETS[0][0] Then
        $iSelected = 0
    Else
        For $i = 0 To UBound($__TCP_SOCKETS) - 1
            If $__TCP_SOCKETS[$i][0] = $hSocket Then
                $iSelected = $i
                ExitLoop
            EndIf
        Next
        If Not $iSelected Then Return 0
    EndIf
    Switch $iEvent
        Case $TCP_SEND
            $__TCP_SOCKETS[$iSelected][3] = $sFunction
        Case $TCP_RECEIVE
            $__TCP_SOCKETS[$iSelected][2] = $sFunction
        Case $TCP_CONNECT
            $__TCP_SOCKETS[$iSelected][4] = $sFunction
        Case $TCP_DISCONNECT
            $__TCP_SOCKETS[$iSelected][5] = $sFunction
        Case $TCP_NEWCLIENT
            $__TCP_SOCKETS[$iSelected][6] = $sFunction
        Case Else
            Return 0
    EndSwitch
    Return 1
EndFunc   ;==>_TCP_RegisterEvent
Func _TCP_Server_ClientIP($hSocket)
    Local $pSocketAddress, $aReturn
    $pSocketAddress = DllStructCreate("short;ushort;uint;char[8]")
    $aReturn = DllCall("Ws2_32.dll", "int", "getpeername", "int", $hSocket, "ptr", DllStructGetPtr($pSocketAddress), "int*", DllStructGetSize($pSocketAddress))
    If @error Or $aReturn[0] <> 0 Then Return 0
    $aReturn = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($pSocketAddress, 3))
    If @error Then Return 0
    $pSocketAddress = 0
    Return $aReturn[0]
EndFunc   ;==>_TCP_Server_ClientIP
Func _TCP_Send($hSocket, $sText)
    Return TCPSend($hSocket, $sText)
EndFunc   ;==>_TCP_Send
Func __TCP_Client_OnSocketEvent($hWnd, $iMsgID, $WParam, $LParam)
    Local $iError = _HiWord($LParam)
    Local $iEvent = _LoWord($LParam)
    $hSocket = 0
    $iElement = 0
    For $i = 1 To UBound($__TCP_SOCKETS) - 1
        If $__TCP_SOCKETS[$i][1] = $iMsgID Then
            $hSocket = $__TCP_SOCKETS[$i][0]
            $iElement = $i
            ExitLoop
        EndIf
    Next
    If $hSocket Then
        Switch $iEvent
            Case $FD_READ; Data has arrived!
                $sDataBuff = TCPRecv($hSocket, $iBuffer, $fBinary)
                Call($__TCP_SOCKETS[$i][2], $hSocket, $sDataBuff, $iError)
                $sDataBuff = ""
            Case $FD_WRITE
                Call($__TCP_SOCKETS[$i][3], $hSocket, $iError)
            Case $FD_CONNECT
                Call($__TCP_SOCKETS[$i][4], $hSocket, $iError)
            Case $FD_CLOSE
                _ASockShutdown($hSocket)
                TCPCloseSocket($hSocket)
                Call($__TCP_SOCKETS[$i][5], $hSocket, $iError)
                ___ArrayDelete($__TCP_SOCKETS, $iElement)
        EndSwitch
    EndIf
EndFunc   ;==>__TCP_Client_OnSocketEvent

;========================================
; Zatorg's Asynchronous Sockets UDF Starts from here.
;========================================
Func _ASocket($iAddressFamily = 2, $iType = 1, $iProtocol = 6)
    If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
    Local $hSocket = DllCall($hWs2_32, "uint", "socket", "int", $iAddressFamily, "int", $iType, "int", $iProtocol)
    If @error Then
        SetError(1, @error)
        Return -1
    EndIf
    If $hSocket[0] = -1 Then
        SetError(2, _WSAGetLastError())
        Return -1
    EndIf
    Return $hSocket[0]
EndFunc   ;==>_ASocket
Func _ASockShutdown($hSocket)
    If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
    Local $iRet = DllCall($hWs2_32, "int", "shutdown", "uint", $hSocket, "int", 2)
    If @error Then
        SetError(1, @error)
        Return False
    EndIf
    If $iRet[0] <> 0 Then
        SetError(2, _WSAGetLastError())
        Return False
    EndIf
    Return True
EndFunc   ;==>_ASockShutdown
Func _ASockClose($hSocket)
    If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
    Local $iRet = DllCall($hWs2_32, "int", "closesocket", "uint", $hSocket)
    If @error Then
        SetError(1, @error)
        Return False
    EndIf
    If $iRet[0] <> 0 Then
        SetError(2, _WSAGetLastError())
        Return False
    EndIf
    Return True
EndFunc   ;==>_ASockClose
Func _ASockSelect($hSocket, $hWnd, $uiMsg, $iEvent)
    If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
    Local $iRet = DllCall( _
            $hWs2_32, _
            "int", "WSAAsyncSelect", _
            "uint", $hSocket, _
            "hwnd", $hWnd, _
            "uint", $uiMsg, _
            "int", $iEvent _
            )
    If @error Then
        SetError(1, @error)
        Return False
    EndIf
    If $iRet[0] <> 0 Then
        SetError(2, _WSAGetLastError())
        Return False
    EndIf
    Return True
EndFunc   ;==>_ASockSelect
; Note: you can see that $iMaxPending is set to 5 by default.
; IT DOES NOT MEAN THAT DEFAULT = 5 PENDING CONNECTIONS
; 5 == SOMAXCONN, so don't worry be happy
Func _ASockListen($hSocket, $sIp, $uiPort, $iMaxPending = 5); 5 == SOMAXCONN => No need to change it.
    Local $iRet
    Local $stAddress
    If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
    $stAddress = __SockAddr($sIp, $uiPort)
    If @error Then
        SetError(@error, @extended)
        Return False
    EndIf
    $iRet = DllCall($hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($stAddress), "int", DllStructGetSize($stAddress))
    If @error Then
        SetError(3, @error)
        Return False
    EndIf
    If $iRet[0] <> 0 Then
        $stAddress = 0; Deallocate
        SetError(4, _WSAGetLastError())
        Return False
    EndIf
    $iRet = DllCall($hWs2_32, "int", "listen", "uint", $hSocket, "int", $iMaxPending)
    If @error Then
        SetError(5, @error)
        Return False
    EndIf
    If $iRet[0] <> 0 Then
        $stAddress = 0; Deallocate
        SetError(6, _WSAGetLastError())
        Return False
    EndIf
    Return True
EndFunc   ;==>_ASockListen
Func _ASockConnect($hSocket, $sIp, $uiPort)
    Local $iRet
    Local $stAddress
    If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
    $stAddress = __SockAddr($sIp, $uiPort)
    If @error Then
        SetError(@error, @extended)
        Return False
    EndIf
    $iRet = DllCall($hWs2_32, "int", "connect", "uint", $hSocket, "ptr", DllStructGetPtr($stAddress), "int", DllStructGetSize($stAddress))
    If @error Then
        SetError(3, @error)
        Return False
    EndIf
    $iRet = _WSAGetLastError()
    If $iRet = 10035 Then; WSAEWOULDBLOCK
        Return True; Asynchronous connect attempt has been started.
    EndIf
    SetExtended(1); Connected immediately
    Return True
EndFunc   ;==>_ASockConnect
; A wrapper function to ease all the pain in creating and filling the sockaddr struct
Func __SockAddr($sIp, $iPort, $iAddressFamily = 2)
    Local $iRet
    Local $stAddress
    If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
    $stAddress = DllStructCreate("short; ushort; uint; char[8]")
    If @error Then
        SetError(1, @error)
        Return False
    EndIf
    DllStructSetData($stAddress, 1, $iAddressFamily)
    $iRet = DllCall($hWs2_32, "ushort", "htons", "ushort", $iPort)
    DllStructSetData($stAddress, 2, $iRet[0])
    $iRet = DllCall($hWs2_32, "uint", "inet_addr", "str", $sIp)
    If $iRet[0] = 0xffffffff Then; INADDR_NONE
        $stAddress = 0; Deallocate
        SetError(2, _WSAGetLastError())
        Return False
    EndIf
    DllStructSetData($stAddress, 3, $iRet[0])
    Return $stAddress
EndFunc   ;==>__SockAddr
Func _WSAGetLastError()
    If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
    Local $iRet = DllCall($hWs2_32, "int", "WSAGetLastError")
    If @error Then
        ConsoleWrite("+> _WSAGetLastError(): WSAGetLastError() failed. Script line number: " & @ScriptLineNumber & @CRLF)
        SetExtended(1)
        Return 0
    EndIf
    Return $iRet[0]
EndFunc   ;==>_WSAGetLastError
; Got these here:
; http://www.autoitscript.com/forum/index.php?showtopic=5620&hl=MAKELONG
Func _MakeLong($LoWord, $HiWord)
    Return BitOR($HiWord * 0x10000, BitAND($LoWord, 0xFFFF)); Thanks Larry
EndFunc   ;==>_MakeLong
Func _HiWord($Long)
    Return BitShift($Long, 16); Thanks Valik
EndFunc   ;==>_HiWord
Func _LoWord($Long)
    Return BitAND($Long, 0xFFFF); Thanks Valik
EndFunc   ;==>_LoWord

; ================================================================
; Name...........: _ArrayDelete
; Description ...: Deletes the specified element from the given array.
; Syntax.........: _ArrayDelete(ByRef $avArray, $iElement)
; Parameters ....: $avArray  - Array to modify
;                  $iElement - Element to delete
; Return values .: Success - New size of the array
;                  Failure - 0, sets @error to:
;                  |1 - $avArray is not an array
;                  |3 - $avArray has too many dimensions (only up to 2D supported)
;                  |(2 - Deprecated error code)
; Author ........: Cephas <cephas at clergy dot net>
; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - array passed ByRef, 
;                       Ultima - 2D arrays supported, reworked function 
;                       (no longer needs temporary array; faster when deleting from end)
; Remarks .......: If the array has one element left (or one row for 2D arrays), 
;                       it will be set to "" after _ArrayDelete() is used on it.
; Related .......: _ArrayAdd, _ArrayInsert, _ArrayPop, _ArrayPush
; ================================================================
Func ___ArrayDelete(ByRef $avArray, $iElement)
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)
    Local $iUBound = UBound($avArray, 1) - 1
    If Not $iUBound Then
        $avArray = ""
        Return 0
    EndIf
    ; Bounds checking
    If $iElement < 0 Then $iElement = 0
    If $iElement > $iUBound Then $iElement = $iUBound
    ; Move items after $iElement up by 1
    Switch UBound($avArray, 0)
        Case 1
            For $i = $iElement To $iUBound - 1
                $avArray[$i] = $avArray[$i + 1]
            Next
            ReDim $avArray[$iUBound]
        Case 2
            Local $iSubMax = UBound($avArray, 2) - 1
            For $i = $iElement To $iUBound - 1
                For $j = 0 To $iSubMax
                    $avArray[$i][$j] = $avArray[$i + 1][$j]
                Next
            Next
            ReDim $avArray[$iUBound][$iSubMax + 1]
        Case Else
            Return SetError(3, 0, 0)
    EndSwitch
    Return $iUBound
EndFunc   ;==>___ArrayDelete

Edit: fixed missing _tcp_client_stop call

Edited by picaxe

Share this post


Link to post
Share on other sites

the above functions are successfuly called when the data is recieved, and without the while loop $len will return the proper length, but i just cant GET the data... as you see in the quote from OstroSoft, object.GetData has some parameters, and im not sure if ive used them right.... any ideas?

The value for the second parameter should be the constant of the value I believe:

vbByte = 17

vbInteger = 2

vbLong = 3

vbSingle = 4

vbDouble = 5

vbCurrency = 6

vbDate = 7

vbBoolean = 11

vbError = 10

vbString = 8

vbArray = 8192

So vbArray + vbByte is 0x2011.

Share this post


Link to post
Share on other sites

Dampe, thank you for that idea, if i cant get this working shortly i will use that method for sure

Authenticity, thankyou, i had been looking for this, i figured no way in hell was i suposed to use a string to detemin the data type, however i guess i just to catch on quick enough, would it look like this:

Func _TCP_OnDataArrival($Len)
    While 1
        $ConnectSocket.GetData($data,0x3,1024)
        If $data<>"" Then ExitLoop
    WEnd
    MsgBox(0,"Len/Dat",$Len&@CRLF&$data)
EndFunc

because i already have a Const $SCKCONNECTIONPENDING = 0x03

sorry if this leads to a noob style lesson in conversion!

if the above is correct, it still doesnt work, OSWINSCK will call this function on data arrival like it should, it will set $Len like it should, but the data does not get inserted in $data, it just loops.

Share this post


Link to post
Share on other sites

Few things:

What you should send depend on what the function expects to receive, so it might be the value of vbLong for example or the type name of it, if it's so then you'll need to send a string like "Long" or "Currency" for long or currency types respectively.

You can declare as much global const with the same value but different names like -> Global Const $vbLong = 3.

The problem IMO is that you're sending maxlen parameter as 1024 but expect to retrieve only 4 bytes, use array instead.

Share this post


Link to post
Share on other sites

thanks for continuing to help, im trying very hard to learn this...

ive tried every data type and combination of code i can think of.. just to make sure im not crazy i tried to make this code in js and it works! so here is the js code that works and the autoit code that fails

oWinsock = new ActiveXObject("OSWINSCK.Winsock");

WScript.ConnectObject(oWinsock, "oWinsock_");
oWinsock.Connect("192.168.0.1","2021");

function oWinsock_OnConnect() {
  oWinsock.SendData('TESTJAVA[-]PING');
}

function oWinsock_OnDataArrival(bytesTotal) {
  var sBuffer = oWinsock.GetDataBuffer();
  WScript.Echo(sBuffer);
}


WScript.Sleep(3000);

$oSocket = ObjCreate("OSWINSCK.Winsock")

ObjEvent($oSocket, "_TCP_")
$oSocket.Connect("192.168.0.1",2021)

Sleep(3000)

Func _TCP_OnConnect()
    $oSocket.SendData("TESTSCRIPT[-]PING")
EndFunc

Func _TCP_OnDataArrival($Len)
    $data=$oSocket.GetDataBuffer()
    MsgBox(0,"Data",$data)
EndFunc

i just dont get it, its the same! :)

Share this post


Link to post
Share on other sites

btw... again autoit will send the data properly, and the $len variable is correct (its the length of the string returned)

any ideas? could this be a bug or incompatability? it seems black and white to me, i dont see anything i could do different in the autoit script

Edited by JohnMC

Share this post


Link to post
Share on other sites

Yeah, lol you tell me...

I'm toying around with this object. Give me a few minutes I'll break this mother... What you need first before attempting to go further with the client is sort of Do...Until $oWinsock.State = 7 and exit the program if it takes more than 5 seconds to get this state.... I'll keep testing.

Edit: Heh, JohnMC I'm almost there... crossing my fingers :)

Edit: Meh, I'm done with this. Can't find a clue of what is wrong with this one. Use TCP* instead... much better for socket communication than OSWINSCK...

Edited by Authenticity

Share this post


Link to post
Share on other sites

Yeah, lol you tell me...

I'm toying around with this object. Give me a few minutes I'll break this mother... What you need first before attempting to go further with the client is sort of Do...Until $oWinsock.State = 7 and exit the program if it takes more than 5 seconds to get this state.... I'll keep testing.

Edit: Heh, JohnMC I'm almost there... crossing my fingers :)

Edit: Meh, I'm done with this. Can't find a clue of what is wrong with this one. Use TCP* instead... much better for socket communication than OSWINSCK...

LOL i didnt even realize that you had picked up on this... well thanks for the try, im still looking for a better way to do tcp commands with timeout but ill have to think harder i guess...

i think ill have my script write or unpack a vb script file and run it, and then communicate the results somehow! kinda feel like im cheating on autoit, ive never had to do this! and is gona kill me seeing as i had been writing a script that operates accross a LAN and i was hoping to make it serverless!

Edited by JohnMC

Share this post


Link to post
Share on other sites

Bump. Has this TCPtimeout issue been fixed? If not it should be imo. I desperately need it for a proxy list checker I'm witting. When a single processed application spends more than 8seconds on a single proxy out of 1000, that is no good.

Edited by Roman9

Share this post


Link to post
Share on other sites

Hello.

I have the same situation - I need to check ports FROM multiple servers remotely.

I use cycle to do it and list. After that I use psexec to start a remote program

I need to make a commandline tools that check port fast - 3-5 second timeout.

Its really strange that autoit still have no such possibility.

Share this post


Link to post
Share on other sites

anything new about this topic? because i had the same problem and don´t get a solution.

Maybe this helps us? -> http://support.microsoft.com/?scid=kb%3Ben-us%3B170359&x=11&y=12

Edited by sc4ry

Share this post


Link to post
Share on other sites

Hey,

i tried the code with the OSWINSCK.dll and it works fine (on xp).

but it doesnt work with win 7 ... did anyone know why?

$runstring = "regsvr32 /s " & @ScriptDir & "\OSWINSCK.dll"
$status = _RunDOS($runstring)

here the return-value is 5 and the $socket then is 0 ...

Share this post


Link to post
Share on other sites

I came up with a workaround for this issue; it's not the cleanest solution, but I tried to make it as reusable as possible. Hopefully this helps the next person who stumbles accross this thread like I did.

Instead of tackling this issue with one script, I broke it into two:

TestPort.au3:

#NoTrayIcon
TCPStartup()
Local $socket = TCPConnect($cmdline[1], $cmdline[2])
If @error Then Exit (1)

ExampleScript.au3

#include <WinAPI.au3>

;---This section is optional, but allows you to compile both scripts into one executable
FileInstall("C:\LocationOfTestPort.EXE\TestPort.exe", @TempDir & "\TestPort.exe", 1)
OnAutoItExitRegister("_CleanUp")
;---

ConsoleWrite(_TCPConnectTimeout("192.168.1.12", 3389, 1000) & @CRLF)

;nTimeOut is in millis
Func _TCPConnectTimeout($sIP, $nPort, $nTimeOut = 1000)
    ;If you dont want to use FileInstall change this to the full path of TestPort.exe
    $iPID = Run(@TempDir & '\TestPort.exe ' & $sIP & ' ' & $nPort, "", @SW_HIDE)
    $hPID = _WinAPI_OpenProcess(0x0400, 0, $iPID)
    $nStep = 10
    $i = 0
    While ProcessExists($iPID)
        If $i < $nTimeOut Then
            Sleep($nStep)
            $i = $i + $nStep
        Else
            _WinAPI_CloseHandle($hPID)
            ;Timeout reached; return 2
            Return SetError(2, 2, 2)
        EndIf
    WEnd
    Local $t_ExitCode = DllStructCreate('int')
    Local $avRET = DllCall('kernel32.dll', 'int', 'GetExitCodeProcess', 'ptr', $hPID, 'ptr', DllStructGetPtr($t_ExitCode))
    If @error Then
        _WinAPI_CloseHandle($hPID)
        ;Internal error; return 3
        Return SetError(3, 3, 3)
    Else
        _WinAPI_CloseHandle($hPID)
        ;return exit code of our port tester
        Return DllStructGetData($t_ExitCode, 1)
    EndIf
EndFunc   ;==>_TCPConnectTimeout

;Only needed if you are using FileInstall
Func _CleanUp()
    FileDelete(@TempDir & "\TestPort.exe")
EndFunc   ;==>_CleanUp

TestPort will need to be compiled first since it is called by ExampleScript. Any time you run _TCPConnectTimeout(), it will create a child process, wait for it to finish the connection, or close it if it has taken too long.

Returns:

0 Success

1 Connect failure

2 Timeout reached

3 Internal Error

Share this post


Link to post
Share on other sites

Hello.

The issue due to some fellow from a different forum is that Autoit network functions use *BLOCKING* ports. These use the *WINDOWS* network default timeouts.

I've mentioned in the bug / feature request system quite a long time ago to modify the functions of Autoit, so that they do *NOT* always open blocking ports, but non blocking ports. Then it would be possible to define really short timeout periods.

 

The fellow I mentioned above was so kind to write a small EXE for me, that I use with FileInstall() when I need to check port status from autoit really fast.

This is the source code of how this can be done:

program chkPort;
// Input: chkport-ip <ip address> <port> [timeout]
// Output: Text message + Errorlevel
// 0 if we connect,
// 1 if we timeout,
// 2 if we get a socket failure,
// 3 for an invalid address.

uses sockets,inetaux,strutils,winsock2,sysutils;
var
ConSock : LongInt;
sAddr : TInetSockAddr;
timeout : dword;
result : boolean;

procedure setnonblockingsocket( s : integer );
var
nb : dword;
begin
nb := 1; // 1 = nonblocking, 0 = blocking
winsock2.ioctlsocket( s , FIONBIO , @nb );
end;

function is_writable_socket( sck : integer; timeout : dword ) : boolean;
var
fds : tfdset;
tv : timeval;
result : boolean;
begin
fd_zero( fds );
fd_set( sck , fds );
tv.tv_sec := timeout div 1000;
tv.tv_usec := timeout mod 1000;

// select (socket+1 , read , write , except , timeout) - wait
// "timeout" to see if data can be written to "socket" without
// blocking

result := select( sck + 1 , nil , @fds , nil , @tv ) > 0;
is_writable_socket := result;
end;

begin
// create a socket, die if we fail
ConSock := Socket(af_inet, sock_stream, 0);
if ConSock = -1 then begin
writeln('Could not open socket: ');
halt(2);
end
else begin

// make it non-blocking
SetNonBlockingSocket(ConSock);

// if timeout defined use it, otherwise default to 2 secs
If paramcount >= 3 then Timeout := numb2dec(paramstr(3),10)
else timeout := 2000;

// fill in the socket info - protocol, address, port
with sAddr do begin
Family := af_inet;
Port := htons(numb2dec(paramstr(2),10));
Addr := StrToAddr(paramstr(1));
end;

// die if we can't turn the address into something useable
If saddr.Addr = 0 then begin
writeln('Could not resolve ',paramstr(1));
halt(3);
end;

// otherwise try to connect
Result := (fpConnect(ConSock, @sAddr, sizeof(sAddr)) = 0);

// and see if it become writeable in the time allowed
result := result or is_writable_socket(consock, timeout);

// close the socket
Shutdown(ConSock, 2);

// and report results
If result then writeln('Port listening')
else begin
Writeln('Port not listening');
halt(1);
end;
end;
end.

You can checkout the compiled EXE here from my dropbox: https://dl.dropboxusercontent.com/u/19989673/ChkPort-IP/chkport.exe

<edit>

opened a new feature request, as I couldn't find the old one:

https://www.autoitscript.com/trac/autoit/ticket/2835#ticket

</edit>

Regards, Rudi.

Edited by rudi

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...