Jump to content

Recommended Posts

I've seen this for a while now but I never really got around to doing anything... It seems UDPRecv has a 100ms delay if nothing is recieved (which is to be expected), but it totally ignores the value set in the TCPTimeout option. I'm not sure if that is intended or if it is a bug so I figured I'd ask here before throwing it up on the trac so I knew what to file it as.

I know "TCPTimeout" implies that it's only for TCP, but other things seem to use TCP and UDP interchangably in their names (TCPStartup/UDPStartup, etc) so I figured it could have just been accidentally left un-implemented in the UDPRecv code when that option was added, and that no one ever really brought it to everyone's attention. It just seems odd that you'd be able to control the delay for something like TCPAccept but not for UDPRecv, since there are things where having a 100ms wait after almost every UDPRecv call is not desirable...

EDIT: I guess I should have formatted my question better when originally writing this, what I meant to ask was:

Is there a reason why UDPRecv ignores the TCPTimeout option? Or is that a bug that should be filed in the trac?

Below is code to show what I'm talking about with the delay, it waits about 100ms after each call to UDPRecv.


;Make things like TCPAccept return instantly instead of blocking for the default
;100ms after no activity. Doing this is useful if your program does more than
;just wait for data on a specific socket.
Opt("TCPTimeout", 0)

;Bind a random port, what port doesn't matter, it only needs to be a valid socket
Global $Sock = UDPBind("", Random(1, 65535))

While 1
    $iTimer = TimerInit()
    $sRecv = UDPRecv($Sock, 512) ;Time how many milliseconds it takes to call UDPRecv and write time to stdout
    ConsoleWrite(TimerDiff($iTimer) & @CRLF)
Edited by Kealper
Link to post
Share on other sites

Been there, done that.

If you want to bypass the blocking you have to set up a permanent stream of data from and to the endpoints. And since with UDP you have to do all the packet checking, verifying and the "only one packet per UDPRecv" thing, this can get very frustrating.

But with TCP you have the same 100ms timeout problem. But there you can establish a constant In/Out Stream easier and dont have to worry about buffer loss/overflow.

The above statements are only my personal expierience with this problem, so it may not be right after all ;)

Oh and As i remember TCPTimeout is only a timeout for inital connecting with TCP/UDPConnect, not for recieving data.

Edited by qsek
Teamspeak 3 User Viewer - Quick and functional TS3 Query script, which shows online users.Cached Screenshot Deleter - Deletes older Fraps Screenshots if they exceed a specified limit.Unresolved Topics:Intercept and modify dragdrop text behaviour in scite
Link to post
Share on other sites

That's actually why I was asking... I've got a potential buffer overflow problem that is partly being caused by each call to UDPRecv blocking for 100ms... A server I made for a chat can be taken down if a client is sending too much data to another client and it can some times lock up its instance of the interpreter (autoit3.exe actually completely stops responding until the offending client stops blasting it with data or gets disconnected)... This seems to only happen when the server is unable to empty TCPRecv's temporary buffer into a more permanent buffer variable fast enough. Any delays with TCP functions like the 1ms delay in every call to TCPRecv, or the 100ms delay with every call to TCPAccept can be removed just by setting that TCPTimeout option to 0... But the problem comes in when that server is also listening for UDP packets as well (as a type of echo for checking if the server is online), and that 100ms per call ends up being enough to drive it over the edge if multiple clients are transferring files or something else that requires heavy data usage a few times now.

I'll admit I don't actually know if the 100ms delay in UDPRecv is completely needed... But if it is not, then it would be most helpful to either tie that delay in to the TCPTimeout option, or make a UDPTimeout option with a similar function.

Meh, I guess I'm just rambling by now...

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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By AoRaToS
      I started working on this program in the summer of 2008 then I stopped cause I faced some problems I couldn't overcome back then. Now that I've practiced more and have become a better scripter/programmer I'm releasing the program to the public to get some opinions. I know it's not a new concept but it's the first program I started besides some small stuff I did just for practice! I won't post the source code yet because it's still under construction, although I'm sure I've posted early stages of the code with bugs in the past in some topic...
      What I wanted was a simple, small, serverless program that would work without installation cause I wanted it for where I work, so I ended up with this!
      I have attached some images of various versions, also visit the forum thread.
      The package includes s!mpL3 LAN Messenger and the full change log.
      Current version! [04/07/2019]
      Check the Change Log below!
      Read the license before using this software.
    • By HansHenrik
      edit: this is probably in the wrong place, can a moderator move it to wherever it belongs?

      is there any way to completely disable TCPTimeout and make TCPRecv() wait indefinitely? maybe setting it to 0 or -1 or something? 
      the docs doesn't seem to mention any way to disable it

      - the underlying C code would set SO_RCVTIMEO to 0 , aka

      DWORD timeout=0;
      setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
    • By Turtlix21
      I've a problem with receiving data on my PC by TCP and UDP. I can send data to another computer, but can't receive it.
      I'm not shure where is the problem (on PC or on "another comupers")
      This is client code:
      ;TCP client TCPStartup() $socket = TCPConnect("", 7777) ;try to connect to server and save number of socket If $socket = -1 Then ;if $socket = -1 then error MsgBox(16, "Error:", "Can't connect to server") EndIf $sendedBytes = TCPSend($socket, "nothing here :)") ;send message to connected socket If $sendedBytes = 0 Then ;if receiving data TCPSend(...) = 0 then error MsgBox(16, "Error", "Can't send message") EndIf TCPCloseSocket($socket) TCPShutdown() and server code:
      ;TCP server TCPStartup() $mainsocket = TCPListen("", 7777) ;making main receiving socket While 1 ;receiving loop $acceptedSocket = TCPAccept($mainsocket) ;possible connection to accept If $acceptedSocket <> -1 Then $receivedData = TCPRecv($acceptedSocket, 1024) ;if main socket is connected then receive message MsgBox(64, "Received message!", "Message: " & $receivedData) TCPCloseSocket($acceptedSocket) ;close open connecion EndIf WEnd TCPShutdown()  
      When server is on PC I can't receive any messages from any other computers.
      When client is on PC I can receive messages on any another computer.
      I tried to turn off antiviruses and windows firewall but it did't change anything
      Error code from client from TCPConnect is 10060 (connection time out) and from TCPSend: 10038
      I've found something about 10060 error code, Microsoft says "Connection timed out. A connection attempt failed because the connected party did not properly respond after a period of time, or the established connection failed because the connected host has failed to respond."
      So it means that the problem is with time of response but it makes no sense couse "another computer" is Virtual Machine with bridge internet connection from PC (pings beetwen PC  and VM are lower than 1ms.
      About 10038 error code microsoft says that this is problem with socket and it actually makes sense.
    • By j0kky
      Hi guysssss,
      have you ever heard of STUN?! No?
      When you are under a NAT and you try to connect to an online server, you make the request using an internal port and your local IP.
      But when your request arrives to the router, it uses its own port list and it enstablishes the connection to the final server using a different port (which has a different port number, but it is associated to your internal port) and the public (external) IP. So, the server responds to your request using the couple external IP\port assigned by the router.
      Well, STUN is a protocol that permits you to know your external IP but, more interesting, your external port associated to your internal port.
      But, which is the point?
      Client/Server connections don't require to know these informations, but what about P2P connection?
      STUN UDF is the second step (the first was my winsock UDF, which is used in this script) to UDP Hole Punching technique:
      Here you are the function:
      ; #FUNCTION# ======================================================================================================================== ; Name...........: _STUN ; Description ...: Makes a STUN request and processes the response ; Syntax.........: _STUN($iLocalPort, $iStunServer = "", $iStunPort = "") ; Parameters ....: $iLocalPort - The local port to be tested ; |1 : 65535 ; $iStunServer - name of the STUN server [Default = ""] ; $iStunPort - STUN server port, used only if $iStunServer <> "" ; |1 : 65535 - [Default = 3478] ; Return values .: On success it returns an array: ; |[0] - The external IP address ; |[1] - The external port ; On failure it returns -1 and sets @error to non zero: ; |-1 - internal error ; |-2 - missing DLL (Ws2_32.dll) ; |-3 - Unable to connect to internet ; |-4 - $iLocalPort is not a valid port ; |-5 - can't bind to $iLocalPort, try a different port ; |-6 - problem with servers ; Remarks .......: This function is used by a client to know which external port/IP correspond to the indicated internal port. ; By default it is used a STUN server list composed by: ; stun.l.google.com:19302, stun1.l.google.com:19302, stun.ekiga.net:3478, stun.ideasip.com:3478, stun.schlund.de:3478 ; If $iStunServer is indicated, the first element of the list is replaced by $iStunServer:$iStunPort ; Author ........: j0kky ; Modified ......: 1.0.0 ; Links .........: STUN RFC 5389: https://tools.ietf.org/html/rfc5389 ; ==================================================================================================================================== #include "winsock.au3" Func _STUN($iLocalPort, $iStunServer = "", $iStunPort = "") $iLocalPort = Int($iLocalPort) If ($iLocalPort < 1) Or ($iLocalPort > 65535) Then Return SetError(-4, 0, -1) $iExtended = 0 If $iStunServer = Default Then $iStunServer = "" $iStunServer = String($iStunServer) If $iStunServer Then $iStunServer = StringRegExpReplace($iStunServer, "^http.?://", "") If StringRight($iStunServer, 1) = "/" Then $iStunServer = StringTrimRight($iStunServer, 1) If Not StringRegExp($iStunServer, ".+\..{2,}") Then $iStunServer = "" ; invalid parameter $iExtended = -1 EndIf EndIf $hWs2 = DllOpen("Ws2_32.dll") If @error Then Return SetError(-2, $iExtended, -1) $tHeader = DllStructCreate("ushort MessageType; ushort MessageLenght; ulong MagicCookie; byte TransactionID[12]") $aRet = DllCall($hWs2, "ushort", "htons", "ushort", 0x0001) If @error Then DllClose($hWs2) Return SetError(-1, $iExtended, -1) Else DllStructSetData($tHeader, "MessageType", $aRet[0]) ;MessageType EndIf DllStructSetData($tHeader, "MessageLenght", 0x0000) ;MessageLenght $aRet = DllCall($hWs2, "ulong", "htonl", "ulong", 0x2112A442) If @error Then DllClose($hWs2) Return SetError(-1, $iExtended, -1) Else DllStructSetData($tHeader, "MagicCookie", $aRet[0]) ;MagicCookie EndIf For $i = 1 To 12 DllStructSetData($tHeader, "TransactionID", Random(0x00, 0xff, 1), $i) ;TransactionID Next _UDPStartup() If @error Then DllClose($hWs2) Return SetError(-1, $iExtended, -1) EndIf $sLocalIP = _GetIPs() If @error Then _UDPShutdown() DllClose($hWs2) Return SetError(-3, $iExtended, -1) EndIf $sLocalIP = $sLocalIP[0] If $iStunServer Then $sFirstServer = $iStunServer If $iStunPort Then $nFirstPort = $iStunPort Else $nFirstPort = 3478 EndIf Else $sFirstServer = "stun.l.google.com" $nFirstPort = 19302 EndIf Local $aStunServer[5][2] = [[$sFirstServer, $nFirstPort], ["stun1.l.google.com", 19302], ["stun.ekiga.net", 3478], ["stun.ideasip.com", 3478], ["stun.schlund.de", 3478]] $nBindSocket = _UDPBind($sLocalIP, $iLocalPort) If @error Then Return SetError(-5, $iExtended, -1) For $j = 0 To 4 $iError = 0 $sServerName = $aStunServer[$j][0] $sServerIP = _TCPNameToIP($sServerName) If @error Then $iError = -6 If Not $iError Then ;RFC indicates that $nRcMaxValue should be equal to 7 and $nRm should be equal to 16, ;but, following those rules, if the server doesn't respond quickly, the script is blocked for more than 1 minute $tByteHeader = DllStructCreate("byte[" & DllStructGetSize($tHeader) & "]", DllStructGetPtr($tHeader)) Local $nRTO = 500, $hTime = TimerInit(), $nRTOTotal = 0, $nRc = 0, $nRcMaxValue = 2, $aRecv = "", $nRm = 2 Do If ($nRc < $nRcMaxValue) And (TimerDiff($hTime) >= $nRTOTotal) Then _UDPSendTo($sServerIP, $aStunServer[$j][1], DllStructGetData($tByteHeader, 1), $nBindSocket) If @error Then $iError = -1 $nRTOTotal += $nRTO * (2 ^ $nRc) $nRc += 1 If $nRc = $nRcMaxValue Then $hTime = TimerInit() EndIf $aRecv = _UDPRecvFrom($nBindSocket, 2048, 1) If @error Then $iError = -1 Sleep(100) Until ($aRecv <> -1) Or (($nRc = $nRcMaxValue) And (TimerDiff($hTime) >= $nRTO * $nRm)) If Not IsArray($aRecv) Then $iError = -1 EndIf If Not $iError Then $dResponse = $aRecv[0] $aRet = DllCall($hWs2, "ushort", "ntohs", "ushort", BinaryMid($dResponse, 3, 2)) ;MessageLenght If @error Then $iError = -1 Else $nMessageLenght = $aRet[0] EndIf If Not ($nMessageLenght > 0) Then $iError = -6 EndIf If Not $iError Then $dResponse = BinaryMid($dResponse, 1, $nMessageLenght + 20) ;message lenght plus header size $aRet = DllCall($hWs2, "ushort", "ntohs", "ushort", BinaryMid($dResponse, 1, 2)) ;MessageType If @error Then $iError = -1 Else $nMessageType = $aRet[0] If Not (($nMessageType = 0x0101) Or ($nMessageType = 0x0111)) Then $iError = -6 EndIf EndIf If Not $iError Then $nByteNumber = 1 If $nMessageType = 0x0101 Then ;Binding success response Do $iError = 0 $aRet = DllCall($hWs2, "ushort", "ntohs", "ushort", BinaryMid($dResponse, 20 + $nByteNumber, 2)) ;Attribute Type If @error Then $iError = -1 Else $nAttributeType = $aRet[0] EndIf If Not $iError And (($nAttributeType = 0x0001) Or ($nAttributeType = 0x0020)) Then ;MAPPED-ADDRESS or XOR-MAPPED-ADDRESS $aRet = DllCall($hWs2, "ushort", "ntohs", "ushort", BinaryMid($dResponse, 24 + $nByteNumber, 2)) ;Family If @error Then $iError = -1 Else $nFamily = $aRet[0] EndIf EndIf If Not $iError Then Local $aResult[2] If $nAttributeType = 0x0020 Then ;XOR-MAPPED-ADDRESS $aRet = DllCall($hWs2, "ushort", "ntohs", "ushort", BinaryMid($dResponse, 26 + $nByteNumber, 2)) ;Port If @error Then $iError = -1 Else $aResult[1] = BitXOR($aRet[0], 0x2112) ;Xored with the most significant 16 bit of Magic Cookie EndIf If Not $iError Then If $nFamily = 0x0001 Then ;IPv4 $dNBOIP = BinaryMid($dResponse, 28 + $nByteNumber, 4) $dNBOCookie = Binary("0x" & Hex(0x2112A442)) $tNBOXoredIP = DllStructCreate("byte[4]") For $i = 1 To 4 DllStructSetData($tNBOXoredIP, 1, BitXOR(BinaryMid($dNBOIP, $i, 1), BinaryMid($dNBOCookie, $i, 1)), $i) Next $aRet = DllCall($hWs2, "ptr", "inet_ntoa", "ulong", Int(DllStructGetData($tNBOXoredIP, 1))) If @error Then $iError = -1 ElseIf $aRet[0] = Null Then $iError = -6 Else $aResult[0] = DllStructGetData(DllStructCreate("char[15]", $aRet[0]), 1) ;IP address xored with Magic Cookie EndIf Else ;IPv6 $dNBOIP = BinaryMid($dResponse, 28 + $nByteNumber, 16) $dNBOConcatenation = BinaryMid($dResponse, 5, 16) $tNBOXoredIP = DllStructCreate("byte[16]") For $i = 1 To 16 DllStructSetData($tNBOXoredIP, 1, BitXOR(BinaryMid($dNBOIP, $i, 1), BinaryMid($dNBOConcatenation, $i, 1)), $i) Next $tIP = DllStructCreate("char[46]") $aRet = DllCall($hWs2, "ptr", "inet_ntop", _ "int", 23, "ptr", DllStructGetPtr($tNBOXoredIP), "ptr", DllStructGetPtr($tIP), "ULONG_PTR", DllStructGetSize($tIP)) If @error Then $iError = -1 ElseIf $aRet[0] = Null Then $iError = -6 Else $aResult[0] = DllStructGetData($tIP, 1) ;IP address EndIf EndIf EndIf ExitLoop 2 ElseIf $nAttributeType = 0x0001 Then ;MAPPED-ADDRESS $aRet = DllCall($hWs2, "ushort", "ntohs", "ushort", BinaryMid($dResponse, 26 + $nByteNumber, 2)) ;Port If @error Then $iError = -1 Else $aResult[1] = $aRet[0] EndIf If Not $iError Then If $nFamily = 0x0001 Then ;IPv4 $aRet = DllCall($hWs2, "ptr", "inet_ntoa", "ulong", BinaryMid($dResponse, 28 + $nByteNumber, 4)) If @error Then $iError = -1 ElseIf $aRet[0] = Null Then $iError = -6 Else $aResult[0] = DllStructGetData(DllStructCreate("char[15]", $aRet[0]), 1) ;IP address EndIf Else ;IPv6 $tNBOIP = DllStructCreate("byte[16]") DllStructSetData($tNBOIP, 1, BinaryMid($dResponse, 28 + $nByteNumber, 16)) $tIP = DllStructCreate("char[46]") $aRet = DllCall($hWs2, "ptr", "inet_ntop", _ "int", 23, "ptr", DllStructGetPtr($tNBOIP), "ptr", DllStructGetPtr($tIP), "ULONG_PTR", DllStructGetSize($tIP)) If @error Then $iError = -1 ElseIf $aRet[0] = Null Then $iError = -6 Else $aResult[0] = DllStructGetData($tIP, 1) ;IP address EndIf EndIf EndIf ExitLoop 2 Else $aRet = DllCall($hWs2, "ushort", "ntohs", "ushort", BinaryMid($dResponse, 22 + $nByteNumber, 2)) ;Attribute Lenght If @error Then $iError = -1 Else $nAttributeLenght = $aRet[0] If Not (Mod($nAttributeLenght, 4) = 0) Then $nAttributeLenght += 4 - Mod($nAttributeLenght, 4) ;padding $nByteNumber += 4 + $nAttributeLenght ;TLV EndIf EndIf EndIf Until $nByteNumber > $nMessageLenght Else ;0x0111 = Binding error response $iError = -6 EndIf EndIf Next _UDPCloseSocket($nBindSocket) _UDPShutdown() DllClose($hWs2) If $iError Then $aResult = -1 If $iStunServer And ($iStunServer <> $sServerName) Then $iExtended = -2 Return SetError($iError, $iExtended, $aResult) EndFunc ;==>_STUN  
      Please test it (especially if you have an IPv6 interface) and report every bug you can try
    • By topten
      Hi I have an idea of creating a parental filter (freeware) , which will be protecting children from navigating to adult websites.  I want to ask, what is your opinion, how to do it best way?
      How to catch the traffic from the very beginning?
      For example if a user is starting IE or Firefox, or if he has some alternate BLABLA-browser - how can I catch the url before actual navigation to website, so that my script could first check if the website is ok, and then if it decides that the website is not ok, just block connection to this IP.
      Looking forward to your opinions, Great thanx in advance!
  • Create New...