40 posts in this topic
Parsing binary data frames from an asynchronous source
I was just working on a project that involved decoding a stream of binary data from a serial port in AutoIt. It took me a few hours to figure out how to process the data efficiently in AutoIt and I did not find any helpful examples on how to do so, so I thought I would share my core example and maybe save someone else some time. There may be a more efficient way to do this, but this works well for me.
#cs Author: ToasterKing This is an example of a way to parse streaming binary data that follows a strict format with a header and footer. In this example, each frame is 5 bytes with a 2-byte header of 0xD5AA and a 1-byte footer of 0xAD. The _BinaryParse() function accumulates incoming data in a buffer. Once a footer is found, it searches backward for the header, and if it is in the right position, it extracts the remaining 2 bytes in the middle, then moves on to looking for the next frame. #ce ; The data source might be something asynchronous like serial or TCP, but since this is just an example, I'm just putting the data in a variable. Local $fSomeData $fSomeData = Binary("0xD5AA24B1") ; Binary data constituting almost a complete frame. _BinaryParse($fSomeData) ; Call the function with the received data. It isn't a complete frame, so it is just stored in the buffer until more data is received. $fSomeData = Binary("0xAD62D5AA92E7AD") ; Remainder of the previous frame, one garbage byte (0x62) which should be skipped, and a complete additional frame. _BinaryParse($fSomeData) ; The function should be able to parse both frames now. Func _BinaryParse($fNewData) Local Static $fBinaryReceived = Binary("") ; Buffer for received data ConsoleWrite("Hey, the function is called!" & @CRLF) ; Add new data to the buffer. ; This ridiculous monstrosity is the only way I could find to append binary data to binary data in AutoIt. It must be converted to strings first. ; Both, one, or no substrings will begin with "0x" depending on whether they contained binary data. To be converted back to binary properly, only one instance ; of "0x" must exist at the beginning of the string. $fBinaryReceived = Binary("0x" & StringReplace(String($fBinaryReceived) & String($fNewData),"0x","")) ConsoleWrite("Data in the buffer: " & String($fBinaryReceived) & @CRLF) Local $iLength = BinaryLen($fBinaryReceived) ; Count the bytes in the data If $iLength > 0 Then Local $fBinaryReceivedTemp = $fBinaryReceived ; Create temporary copy to work on Local $fByte1,$fByte2 For $i = 1 To $iLength If BinaryMid($fBinaryReceivedTemp,$i,1) = 0xAD Then ; If the 1-byte footer found ConsoleWrite("Footer found at end of " & $i & " of " & $iLength & " bytes!" & @CRLF) If BinaryMid($fBinaryReceivedTemp,$i - 4,1) = 0xD5 And BinaryMid($fBinaryReceivedTemp,$i - 3,1) = 0xAA Then ; and the 2-byte header is found 4 bytes before that ConsoleWrite("Header found before the footer!" & @CRLF) $fByte1 = BinaryMid($fBinaryReceivedTemp,$i - 2,1) ; Get 1st byte in the body (between header and footer) $fByte2 = BinaryMid($fBinaryReceivedTemp,$i - 1,1) ; Get 2nd byte in the body (between header and footer) ConsoleWrite("Here is the critical data: " & String($fByte1) & " " & String($fByte2) & @CRLF) ; Just display the 2 bytes for demonstration purposes. Normally, you'd do something more useful with it here. EndIf $fBinaryReceived = BinaryMid($fBinaryReceivedTemp,$i + 1) ; Truncate the original data to remove all of the bytes just processed, then continue processing $fBinaryReceivedTemp EndIf Next EndIf EndFunc
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!
TCP port forwarding
Hello everyone. I'm wondering if its possible:
I want to try create a simple autoit script that will
1) first he must connect to some IP in internet port 80
2) then he must listen for incoming connections from other IP'S ports 8000 - 8200 [in total over 200 connections]
3) that script must send all recieved data from that [IP in internet port 80 ] to [other IP'S ports 8000 - 8200]
is that very hard to do ? Any suggestions or maybe some similar examples that can help me to do this ?
all those 200 connections must receive data at the same time at once is it possible to do so ?
Unstable TCP socket connection server keeps disconnecting and connecting all the time
I am working on a code of Client-Server Connection for a while (Like Teamviewer) , the problem is that the server keeps disconnecting and connecting all the time , In the client i wrote a code to notify me each time server is online , I am getting around 10 notifications each 1 minute from same server :
This is the server code :
TCPStartup() Local $ConnectedSocket Local $My_IP = "127.0.0.1" Local $My_PORT = '5000' Local $UserID = "MyID" ; Connect Connect($My_IP, $My_PORT) While 1 If TCPConnect($My_IP, $My_PORT) <> -1 Then $recv = TCPRecv($ConnectedSocket, 2048) $RecvSpl = StringSplit($recv, "|") Switch $RecvSpl Case "order1" ; Do something MsgBox(64,"Success","You are now connected to the client") AddLogToClinet("My server is Online", $UserID, "Green") EndSwitch Else $Connected = False Connect($IP, $My_PORT) EndIf Sleep(100) WEnd ; Connect To the Client Func Connect($IP, $Port) Local $iConnectAttempts = 0 TCPStartup() Do $ConnectedSocket = TCPConnect($IP, $Port) Sleep(1000) Until ($ConnectedSocket > 0 or $iConnectAttempts > 10) Return SetError(@error, 0, $ConnectedSocket) EndFunc ;==>Connect ; Send To Client Func SockSend($Cmd, $Text) TCPSend($ConnectedSocket, $Cmd & $SockSpl & $Text & $PocketSpl, 4) EndFunc ;==>SockSend ; Add Log To Server Func AddLogToClinet($Data, $UserID, $Color) SockSend("AddLog", $Data & $SockSpl & $UserID & $SockSpl & $Color) EndFunc ;==>AddLogToClinet At first the Connection function was :
; Connect To the Client ( Old ) Func Connect($IP, $Port) TCPStartup() $ConnectedSocket = TCPConnect($IP, $Port) If @error Then Connect($IP, $My_PORT) ; <<<<<<<<<<<<<<< This was the causing recursion error Else $Connected = True EndIf EndFunc ;==>Connect It was working good , except I had 'recursion level has been exceeded error (old one)
I've tried increasing the delay for current code by :
Opt("TCPTimeout", 5000) However it did not help yet what do you suggest to me ?
I am working on a desktop remote application so I made a simple server and client to send binary screen captures from client to server. All it's good if I test both scripts on my computer but when the client is in other network many screen shots are corrupted and some of them looks good. Have any idea why?
#include <ScreenCapture.au3> #include <Memory.au3> #include <WinAPI.au3> #include <GDIPlus.au3> TCPStartup() $Client = TCPConnect(@IPAddress1,12100) _GDIPlus_Startup() While True Local $hHBitmap = _ScreenCapture_Capture('') Local $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap) $bData = _GDIPlus_StreamImage2BinaryString($hBitmap) _GDIPlus_BitmapDispose($hBitmap) _WinAPI_DeleteObject($hHBitmap) TCPSend($Client,'~stream:' & BinaryLen($bData)) While BinaryLen($bData) $a = TCPSend($Client, $bData) $bData = BinaryMid($bData, $a+1, BinaryLen($bData)-$a) WEnd Sleep(10) WEnd TCPCloseSocket($Client) TCPShutdown() _GDIPlus_Shutdown() Func _GDIPlus_StreamImage2BinaryString($hBitmap, $sFormat = "JPG", $iQuality = 100) ;UEZ Local $sImgCLSID, $tGUID, $tParams, $tData Switch $sFormat Case "JPG" $sImgCLSID = _GDIPlus_EncodersGetCLSID($sFormat) $tGUID = _WinAPI_GUIDFromString($sImgCLSID) $tData = DllStructCreate("int Quality") DllStructSetData($tData, "Quality", $iQuality) ;quality 0-100 Local $pData = DllStructGetPtr($tData) $tParams = _GDIPlus_ParamInit(1) _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData) Case "PNG", "BMP", "GIF", "TIF" $sImgCLSID = _GDIPlus_EncodersGetCLSID($sFormat) $tGUID = _WinAPI_GUIDFromString($sImgCLSID) Case Else Return SetError(1, 0, 0) EndSwitch Local $hStream = _WinAPI_CreateStreamOnHGlobal() ;http://msdn.microsoft.com/en-us/library/ms864401.aspx If @error Then Return SetError(2, 0, 0) _GDIPlus_ImageSaveToStream($hBitmap, $hStream, DllStructGetPtr($tGUID), DllStructGetPtr($tParams)) If @error Then Return SetError(3, 0, 0) Local $hMemory = _WinAPI_GetHGlobalFromStream($hStream) ;http://msdn.microsoft.com/en-us/library/aa911736.aspx If @error Then Return SetError(4, 0, 0) Local $iMemSize = _MemGlobalSize($hMemory) If Not $iMemSize Then Return SetError(5, 0, 0) Local $pMem = _MemGlobalLock($hMemory) $tData = DllStructCreate("byte[" & $iMemSize & "]", $pMem) Local $bData = DllStructGetData($tData, 1) _WinAPI_ReleaseStream($hStream) ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms221473(v=vs.85).aspx _MemGlobalFree($hMemory) Return $bData EndFunc ;==>_GDIPlus_StreamImage2BinaryString
Global $Buffer, $BufferSize Global $Count = 0 TCPStartup() $Server = TCPListen(@IPAddress1,12100) If @error Then MsgBox(0,'',@error) Do $Socket = TCPAccept($Server) Sleep(10) Until $Socket <> -1 While True $Recv = TCPRecv($Socket,10240) If $Recv = -1 Then ExitLoop ElseIf $Recv Then If StringLeft($Recv,7) = '~stream' Then $BufferSize = StringSplit($Recv,':') $Buffer = '0x' Do $Recv = TCPRecv($Socket,10240) If BinaryLen($Recv) <> 0 Then $BufferSize -= BinaryLen($Recv) $Buffer &= StringTrimLeft($Recv,2) EndIf Until $BufferSize = 0 $hFile = FileOpen(@ScriptDir & '\Screen' & $Count & '.jpeg',18) FileWrite($hFile,$Buffer) FileClose($hFile) $Buffer = Null $Count += 1 EndIf If $Count = 100 Then ExitLoop EndIf Sleep(10) WEnd TCPCloseSocket($Socket) TCPCloseSocket($Server) TCPShutdown() Exit