Author | Message | Time |
---|---|---|
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 |