Valhalla Legends Forums Archive | Battle.net Bot Development | another quick question

AuthorMessageTime
gotcha_ass
Ok I need to extract the strings out of the packetdata
The strings start at position 25, and go to the end of the string. How would I write the syntax to make Mid start at 25 and goto the end of the string?
So far I have:

[code]
StringData = Mid(PacketData, 25, End_of_String)
[/code]

What do I need to replace End_of_String with?
February 26, 2003, 1:30 AM
dRAgoN
[quote]Ok I need to extract the strings out of the packetdata
The strings start at position 25, and go to the end of the string. How would I write the syntax to make Mid start at 25 and goto the end of the string?
So far I have:

[code]
StringData = Mid(PacketData, 25, End_of_String)
[/code]

What do I need to replace End_of_String with?[/quote]


[code]
StringData = Mid(PacketData, 25, len(PacketData))
[/code]

February 26, 2003, 4:09 AM
Grok
[quote]


[code]
StringData = Mid(PacketData, 25, len(PacketData))
[/code]

[/quote]

When using Mid() to read from start to end-of-data,

StringData = Mid(PacketData, 25, len(PacketData) - 24)
or just
StringData = Mid(PacketData, 25)

are both acceptable forms.
February 26, 2003, 6:15 AM
gotcha_ass
thanx soo much
February 26, 2003, 8:08 AM
St0rm.iD
stringData = right(packetData, len(packetData)-25)
February 26, 2003, 5:03 PM
Camel
[quote]stringData = right(packetData, len(packetData)-25)[/quote]
mid(packetdata, 25) is easier to read :)
February 26, 2003, 7:05 PM
Grok
[quote]stringData = right(packetData, len(packetData)-25)[/quote]

stringData = right(packetData, len(packetData)-24)

February 26, 2003, 9:21 PM
MesiaH
yes it would be len() - 24 because if your starting at the 25 char, then you need to add one more char to it, so if you did len() - 25 then you would go back to an unwanted char.
February 26, 2003, 10:23 PM
Camel
[quote]yes it would be len() - 24 because if your starting at the 25 char, then you need to add one more char to it, so if you did len() - 25 then you would go back to an unwanted char.[/quote]
right, it's due to one of the things that, believe it or not, was intended to make vb n00b-friendly. in c, you might use "&buffer[24]" or "buffer+24" (obviously, buffer being a pointer to a char array). in vb the first charactor is 1 not zero, so you have to add 1. very annoying to count "multiple of four plus one"s.
imho, microsoft should have included at least minimal support for pointers. yes, there are undocumented functions such as strptr,varptr, and there is addressof, but just TRY and use them without crashing vb. you can also combine CopyMemory with ByRef/ByVal (ByRef = &; ByVal = *) to put a pointer in to a long, or turn a pointer in to data. but then, what if you have a string pointer? you need to grab ONE byte at a time and stop at the first NULL so you don't go beyond whatever allocated memory there is.
as long as i'm ranting about vb, what's up with all the signed variables!? i mean seriously...signed boolean? give me a fucking break.

[edit]oh yeah, and another thing
i'm surprised nobody, to my knowledge, has figgured out (and published) that you can use vb's types to outline your shit...you dont even need to do net short/long to host conversion in vb.
example:

[code]type packetheader
   the0xFFthing as byte
   id as byte
   length as integer
   data as string
end type

sub sck_dataarrival()
   dim ph as packetheader
   sck.peekdata ph, 4        'peek at the header up to packet length
   sck.getdata ph, ph.length 'now really get it
   parsebinary ph
end sub

sub parsebinary(packet as packetheader)
 //code...
end sub[/code]

i actually discovored this before i knew the first thing about c structs. i was writing a server clone for hotline a couple years ago, and it had a 64bit list of privs that it used for each account. rather than trying to bust out each one individually, i made a type, and threw 64 "dim privname as boolean"s in it. after that, just a copymemory from the string to the type, and i was all set. ;)
February 26, 2003, 11:31 PM
St0rm.iD
Dude that is HOT.
February 26, 2003, 11:45 PM
Grok
[quote]i actually discovored this before i knew the first thing about c structs. i was writing a server clone for hotline a couple years ago, and it had a 64bit list of privs that it used for each account. rather than trying to bust out each one individually, i made a type, and threw 64 "dim privname as boolean"s in it. after that, just a copymemory from the string to the type, and i was all set. ;)[/quote]

No you didn't.  VB Booleans are 16-bit.
February 27, 2003, 12:17 AM
Camel
err, sorry. i did 4 bytes. it was a long time ago, leave me alone ;)
February 27, 2003, 1:11 AM
gotcha_ass
Wohoo I did it ;D

[code]
StringData = Mid(PacketData, 25) 'remove only strings
Dim i As String
i = InStr(StringData, vbCrLf) 'find position of first vbcrlf
IX86verFileName = Mid(StringData, 1, i) 'Now holds the first NTString
ValueString = Mid(StringData, i + 1) 'How holds second NTString
           
'Dont forget to remove the VbCrLfs
[/code]

How do I trim the VbCrLf off the end of the strings?
February 27, 2003, 1:55 AM
Grok
Dim strLineArray() As String
strLineArray = Split(StringData, vbCrlf)

Now you have a 0-based array containing each line.
February 27, 2003, 2:09 AM
gotcha_ass
[quote]Dim strLineArray() As String
strLineArray = Split(StringData, vbCrlf)

Now you have a 0-based array containing each line.
[/quote]



That can replace my code?? Would be a lot easier that way. Does it keep the vbCrlf at the end of each string or throw it away?
February 27, 2003, 9:44 AM
iago
[quote]



That can replace my code?? Would be a lot easier that way. Does it keep the vbCrlf at the end of each string or throw it away?[/quote]

Throws it away.
February 27, 2003, 11:51 AM
Camel
[quote]i = InStr(StringData, vbCrLf) 'find position of first vbcrlf[/quote]
i = instr(1, stringdata, vbcrlf)
February 27, 2003, 5:15 PM
Spht
[quote]
i = instr(1, stringdata, vbcrlf)[/quote]

It does the same thing.
February 27, 2003, 5:56 PM
gotcha_ass
[quote]Dim strLineArray() As String
strLineArray = Split(StringData, vbCrlf)

Now you have a 0-based array containing each line.
[/quote]

Ill just use this then. Thanks Grok
February 27, 2003, 6:57 PM
Yoni
[quote][code]     sck.peekdata ph, 4        'peek at the header up to packet length
   sck.getdata ph, ph.length 'now really get it[/code][/quote]
Bad!

(That is, assuming PeekData does recv with MSG_PEEK)
February 28, 2003, 10:36 AM
Camel
gets rid of it

[code]Split("1,2,3,4", ",")[/code] would return the same thing as
[code]Array("1", "2", "3", "4")[/code]

and just for refrence, join does the opposite:
[code]Join(Array("1", "2", "3", "4"), ",") = "1,2,3,4"[/code]
February 28, 2003, 1:21 PM
Camel
[quote]
Bad!

(That is, assuming PeekData does recv with MSG_PEEK)[/quote]
hrm, didnt think about that...i dont think it does, but just to be safe you could do:
[code]    sck.getdata ph, 4        'peek at the header up to packet length
   sck.getdata ph.data, ph.length - 4 'grab the data[/code]

[edit] comments
February 28, 2003, 1:24 PM
Yoni
What if you receive under 4 bytes?
February 28, 2003, 4:19 PM
Camel
[quote]What if you receive under 4 bytes?[/quote]
*kicks yoni*
[code]sub fucking_dataarrival(totaldata as intetger)
 if totaldata < 4 then exit sub[/code]
February 28, 2003, 10:29 PM
St0rm.iD
[quote]
*kicks yoni*
[code]sub fucking_dataarrival(totaldata as intetger)
 if totaldata < 4 then exit sub[/code][/quote]

[code]
dim buffer as string
dim plen as integer

sub fucking_dataarival(totaldata as integer)
dim d as string
fucking.getdata d

buffer = buffer & d

if len(buffer) >= 4 and plen = 0 then
'get the length
end if

if len(buffer) >= plen
'houston we have a packet
dim packet as string
packet = left(buffer,plen)
buffer = right(buffer,len(buffer)-len(packet))
plen = 0
end if
end sub
[/code]
March 1, 2003, 12:33 PM
Yoni
With Camel's newest code, if you receive between 1 and 3 bytes, they are discarded, causing badly out-of-order packet parsing on the client.

Didn't read through it completely, but Storm's code is probably fine.
March 1, 2003, 9:07 PM
Camel
[quote]With Camel's newest code, if you receive between 1 and 3 bytes, they are discarded, causing badly out-of-order packet parsing on the client.[/quote]
no they aren't, they stay in the buffer until you read them! i do it all the time!
March 2, 2003, 6:37 PM
Yoni
Hmm, alright...
What if you receive an entire packet 1 byte at a time?
March 2, 2003, 9:56 PM
kamakazie
[code]Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)[/code]

bytesTotal is the total number of bytes in the internal buffer.  So even if he does receive 1 byte at a time, then it won't fail.  His code should work fine for BNCS packets.  The only thing I can think of is if he doesn't receive the full BNCS packet content each time.  You would have save the header in a static/global variable and wait until you receive the amount of data the header length says the BNCS packet is.  I believe it is easier to just receive into a buffer, then process packets from that buffer, and not worry about the Winsock's internal buffer.

Edit: added 2 sentences
March 2, 2003, 11:08 PM
MesiaH
ill go with kamakazie on that one, ive never seen a BNCS packet do that, but data frames are spread out in lots of protocols, and i beleive its best to use your own buffer to do the things you want, for obvious reasons already stated.
March 3, 2003, 1:28 AM
tA-Kane
Here's the VB-ish code (since I don't use VB, I don't know how accurate it is) for how my lagbuffering works...

[CODE]
BnetGameSocket.LagBuffer As String

Event BnetGameSocket.DataAvailable()
Me.ReadData(Me.ReadAll)
End Event

Sub BnetGameSocket.ReadData(Data As String)
Dim PacketData As String
Dim PacketDataLen As Integer, PacketID As Integer
 
'New data gets appended to the lag buffer below
Me.LagBuffer = Me.LagBuffer & Data
 
Do
 If LenB(Me.LagBuffer) < 4 Then
  'Received data length is less then minimum packet length (0xff & id & length)
  Exit
 End If
 'StringToInteger is a custom function which
 'converts binary string data to an integer
 '(similar to Val(), but base 256 instead of base 10)
 PacketID = AscB(MidB(Me.LagBuffer,2,1))
 PacketDataLen = StringToInteger(MidB(Me.LagBuffer,3,2))
 'Remove header length from packet length to get data length
 PacketDataLen = PacketDataLen-4
 If PacketDataLen < 0 Then
  'Cannot have less than 0 datalength
  Me.Close
  Exit
 ElseIf PacketDataLen < LenB(Me.LagBuffer) Then
  'LagBuffer does not contain the whole packet
  Exit
 End If
 'get packet data
 PacketData = MidB(Me.LagBuffer,5,PacketDataLen-4)
 'send packet to the method which calls the appropriate packet handler, based on PacketID
 Me.PacketReceived(PacketID,PacketData)
 'remove packet from the lag buffer
 '(location of next packet data is 1+(PacketLen))
 Me.LagBuffer = MidB(Me.LagBuffer,1+PacketDataLen+4)
Loop
End Sub

[/CODE]

The reason I call ReadData() instead of just having the ReadData() code in .DataAvailable event, is so that I can test my socket without actually connecting to Battle.net, by calling ReadData() from a different source (such as a test window).
March 3, 2003, 1:45 AM
Camel
[quote]Hmm, alright...
What if you receive an entire packet 1 byte at a time?[/quote]
it'll work fine
peekdata doesnt remove anything from the buffer. only getdata does that. it'll keep grabbing the first 4 bytes with peekdata until the ammount of data in the buffer is at least the size of the packet, and then get the entire packet

but just on a side note, it's pretty safe to assume that such a thing will never happen ;)

[edit] you could also use getdata and declare the variable using "static" instead of "dim". that way it would retain the packet length from one _dataarrival to the next.
March 3, 2003, 5:27 PM
Yoni
[quote]but just on a side note, it's pretty safe to assume that such a thing will never happen ;)[/quote]
Not really.
Maybe on real Battle.net it won't happen, since it's configured for optimal efficiency.
But one could make a fake server that is evil and sends packets 1 byte at a time on purpose.
March 3, 2003, 8:23 PM
Camel
or, one could not...
March 3, 2003, 9:46 PM
tA-Kane
[quote]or, one could not...[/quote]It wouldn't be hard to put all data-to-be-sent into a buffer, and then create a timer that activates once every, say..., 100ms, which sends then removes the first byte in the buffer, OR, if the buffer is empty, then it does nothing.
March 4, 2003, 4:44 AM
Skywing
[quote]
it'll work fine
peekdata doesnt remove anything from the buffer. only getdata does that. it'll keep grabbing the first 4 bytes with peekdata until the ammount of data in the buffer is at least the size of the packet, and then get the entire packet

but just on a side note, it's pretty safe to assume that such a thing will never happen ;)

[edit] you could also use getdata and declare the variable using "static" instead of "dim". that way it would retain the packet length from one _dataarrival to the next.[/quote]
Split packets *are* common on Battle.net - ever joined a nearly-full channel?
March 4, 2003, 9:14 AM
iago
[quote]
Split packets *are* common on Battle.net - ever joined a nearly-full channel?[/quote]

Yes, that used to always crash my plugin :D
March 4, 2003, 12:04 PM
Camel
[quote]Split packets *are* common on Battle.net - ever joined a nearly-full channel?[/quote]
i was referring to packets that are <4 bytes (eg, the first two bytes of the bnet packet header)
March 4, 2003, 5:33 PM
Skywing
[quote]
i was referring to packets that are <4 bytes (eg, the first two bytes of the bnet packet header)[/quote]
Yes.  The most likely time for this to happen is when packets are split -- such as, say, part of a header in one TCP packet and part in the next.
March 5, 2003, 2:18 PM

Search