Valhalla Legends Archive

Programming => Battle.net Bot Development => Topic started by: gotcha_ass on February 25, 2003, 07:30 PM

Title: another quick question
Post by: gotcha_ass on February 25, 2003, 07:30 PM
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:

StringData = Mid(PacketData, 25, End_of_String)

What do I need to replace End_of_String with?
Title: Re: another quick question
Post by: l)ragon on February 25, 2003, 10:09 PM
QuoteOk 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:

StringData = Mid(PacketData, 25, End_of_String)

What do I need to replace End_of_String with?


StringData = Mid(PacketData, 25, len(PacketData))

Title: Re: another quick question
Post by: Grok on February 26, 2003, 12:15 AM
QuoteStringData = Mid(PacketData, 25, len(PacketData))

 

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.
Title: Re: another quick question
Post by: gotcha_ass on February 26, 2003, 02:08 AM
thanx soo much
Title: Re: another quick question
Post by: Banana fanna fo fanna on February 26, 2003, 11:03 AM
stringData = right(packetData, len(packetData)-25)
Title: Re: another quick question
Post by: Camel on February 26, 2003, 01:05 PM
QuotestringData = right(packetData, len(packetData)-25)
mid(packetdata, 25) is easier to read :)
Title: Re: another quick question
Post by: Grok on February 26, 2003, 03:21 PM
QuotestringData = right(packetData, len(packetData)-25)

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

Title: Re: another quick question
Post by: Mesiah / haiseM on February 26, 2003, 04:23 PM
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.
Title: Re: another quick question
Post by: Camel on February 26, 2003, 05:31 PM
Quoteyes 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.
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:

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

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. ;)
Title: Re: another quick question
Post by: Banana fanna fo fanna on February 26, 2003, 05:45 PM
Dude that is HOT.
Title: Re: another quick question
Post by: Grok on February 26, 2003, 06:17 PM
Quotei 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. ;)

No you didn't.  VB Booleans are 16-bit.
Title: Re: another quick question
Post by: Camel on February 26, 2003, 07:11 PM
err, sorry. i did 4 bytes. it was a long time ago, leave me alone ;)
Title: Re: another quick question
Post by: gotcha_ass on February 26, 2003, 07:55 PM
Wohoo I did it ;D

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

How do I trim the VbCrLf off the end of the strings?
Title: Re: another quick question
Post by: Grok on February 26, 2003, 08:09 PM
Dim strLineArray() As String
strLineArray = Split(StringData, vbCrlf)

Now you have a 0-based array containing each line.
Title: Re: another quick question
Post by: gotcha_ass on February 27, 2003, 03:44 AM
QuoteDim strLineArray() As String
strLineArray = Split(StringData, vbCrlf)

Now you have a 0-based array containing each line.



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?
Title: Re: another quick question
Post by: iago on February 27, 2003, 05:51 AM
QuoteThat 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?

Throws it away.
Title: Re: another quick question
Post by: Camel on February 27, 2003, 11:15 AM
Quotei = InStr(StringData, vbCrLf) 'find position of first vbcrlf
i = instr(1, stringdata, vbcrlf)
Title: Re: another quick question
Post by: Spht on February 27, 2003, 11:56 AM
Quotei = instr(1, stringdata, vbcrlf)

It does the same thing.
Title: Re: another quick question
Post by: gotcha_ass on February 27, 2003, 12:57 PM
QuoteDim strLineArray() As String
strLineArray = Split(StringData, vbCrlf)

Now you have a 0-based array containing each line.

Ill just use this then. Thanks Grok
Title: Re: another quick question
Post by: Yoni on February 28, 2003, 04:36 AM
Quote     sck.peekdata ph, 4        'peek at the header up to packet length
    sck.getdata ph, ph.length 'now really get it
Bad!

(That is, assuming PeekData does recv with MSG_PEEK)
Title: Re: another quick question
Post by: Camel on February 28, 2003, 07:21 AM
gets rid of it

Split("1,2,3,4", ",") would return the same thing as
Array("1", "2", "3", "4")
and just for refrence, join does the opposite:
Join(Array("1", "2", "3", "4"), ",") = "1,2,3,4"
Title: Re: another quick question
Post by: Camel on February 28, 2003, 07:24 AM
QuoteBad!

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

[edit] comments
Title: Re: another quick question
Post by: Yoni on February 28, 2003, 10:19 AM
What if you receive under 4 bytes?
Title: Re: another quick question
Post by: Camel on February 28, 2003, 04:29 PM
QuoteWhat if you receive under 4 bytes?
*kicks yoni*
sub fucking_dataarrival(totaldata as intetger)
  if totaldata < 4 then exit sub
Title: Re: another quick question
Post by: Banana fanna fo fanna on March 01, 2003, 06:33 AM
Quote*kicks yoni*
sub fucking_dataarrival(totaldata as intetger)
  if totaldata < 4 then exit sub

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
Title: Re: another quick question
Post by: Yoni on March 01, 2003, 03:07 PM
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.
Title: Re: another quick question
Post by: Camel on March 02, 2003, 12:37 PM
QuoteWith 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.
no they aren't, they stay in the buffer until you read them! i do it all the time!
Title: Re: another quick question
Post by: Yoni on March 02, 2003, 03:56 PM
Hmm, alright...
What if you receive an entire packet 1 byte at a time?
Title: Re: another quick question
Post by: dxoigmn on March 02, 2003, 05:08 PM
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
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
Title: Re: another quick question
Post by: Mesiah / haiseM on March 02, 2003, 07:28 PM
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.
Title: Re: another quick question
Post by: tA-Kane on March 02, 2003, 07:45 PM
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...

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


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).
Title: Re: another quick question
Post by: Camel on March 03, 2003, 11:27 AM
QuoteHmm, alright...
What if you receive an entire packet 1 byte at a time?
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.
Title: Re: another quick question
Post by: Yoni on March 03, 2003, 02:23 PM
Quotebut just on a side note, it's pretty safe to assume that such a thing will never happen ;)
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.
Title: Re: another quick question
Post by: Camel on March 03, 2003, 03:46 PM
or, one could not...
Title: Re: another quick question
Post by: tA-Kane on March 03, 2003, 10:44 PM
Quoteor, one could not...
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.
Title: Re: another quick question
Post by: Skywing on March 04, 2003, 03:14 AM
Quoteit'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.
Split packets *are* common on Battle.net - ever joined a nearly-full channel?
Title: Re: another quick question
Post by: iago on March 04, 2003, 06:04 AM
QuoteSplit packets *are* common on Battle.net - ever joined a nearly-full channel?

Yes, that used to always crash my plugin :D
Title: Re: another quick question
Post by: Camel on March 04, 2003, 11:33 AM
QuoteSplit packets *are* common on Battle.net - ever joined a nearly-full channel?
i was referring to packets that are <4 bytes (eg, the first two bytes of the bnet packet header)
Title: Re: another quick question
Post by: Skywing on March 05, 2003, 08:18 AM
Quotei was referring to packets that are <4 bytes (eg, the first two bytes of the bnet packet header)
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.