• Welcome to Valhalla Legends Archive.
 

[VB] D2GS Parser

Started by LivedKrad, July 14, 2005, 07:25 PM

Previous topic - Next topic

LivedKrad

I am at the end of my sanity! I cannot for the life of me figure out why my parsing routine continually comes up with packet values higher than the highest packet (0xB3) or why it comes up with packet values that are of size 0 in the packet size table. Someone help me please, for the safety of me and others around me:

*Note: According to the decompressing functions of D2GS.dll, the compressed data is passed to the decompressor, and is output like "data" + "2F" + loads of nulled padding. (0x2F in the packet size table is considered of value 0, so technically it shouldn't be a packet and thus why it is used as a terminator).


Public Sub D2GSParserRoutine(ByVal data As String)
If data = vbNullString Then
  Exit Sub
End If
Dim pid As Byte
Dim pSize As Long
Dim tmpSize As Byte
Dim pName As String
pid = Asc(Mid$(data, 1, 1))
'AddChat2 vbWhite, DebugOutput(data)

'If pid = &HFF Then
'Call D2GSParserRoutine(Mid$(data, 2))
'Exit Sub
'End If

  If pid > 179 Then
AddChat vbWhite, "Broke on packet: 0x" & Hex(pid)
  AddChat2 vbWhite, "Last packet dump: " & DebugOutput(lastPacketDump)
AddChat2 vbWhite, "Dump: " & DebugOutput(data)
Exit Sub
  Else
  pSize = PACKET_SIZE(pid)
pName = vbNullString
End If

If pid = &H2F Then
'AddChat vbMagenta, "End of packet."
Exit Sub
End If

If pSize = &HFFFFFFFF Then

Select Case pid
  Case &HAA
   tmpSize = Asc(Mid$(data, 7, 1))
  Case &HAC
   tmpSize = Asc(Mid$(data, 13, 1))
  Case &H26
   tmpSize = Parsechat(data)
    If tmpSize = 0 Then
     Exit Sub
    End If
  Case &H5B
   AddChat &H80FF&, "Player in game: " & Mid$(data, 9, 15)
   ObjectId.numPlayers = ObjectId.numPlayers + 1
   tmpSize = Asc(Mid$(data, 2, 1))
  Case &H94
   tmpSize = 6 + ((Asc(Mid$(data, 2, 1)) * 3))
   AddChat vbCyan, "precasting.."
  Case &H9C
   tmpSize = Asc(Mid$(data, 3, 1))
  Case &H9D
   tmpSize = Asc(Mid$(data, 3, 1))
  Case &HA8
   tmpSize = Asc(Mid$(data, 7, 1))
  Case Else
   AddChat2 vbWhite, "Encountered packet with unknown size: 0x" & Hex(pid)
   AddChat2 vbWhite, "Dump: " & DebugOutput(data)
   Form1.scktD2GS.Close
   Exit Sub
End Select

AddChat vbWhite, "Received packet: 0x" & Hex(pid)
lastPacketDump = Mid$(data, 1, tmpSize + 3)
Call D2GSParserRoutine(Mid$(data, tmpSize + 1))
End If

If pSize <> &HFFFFFFFF And pSize <> &H0 Then

Select Case pid
  Case &H1
   pName = "Game acceptance??"
   
  Case &H51
   Dim objectType As Byte
   Dim ObjId As Long
   pName = "World object location"
   objectType = Asc(Mid$(data, 7, 1))
   ObjId = gdword(Mid$(data, 3, 4))
   
         AddChat &H80FF&, "World map info: Object type " & Hex(objectType)
         
    If objectType = &HB Then
              AddChat &H80FF&, "Stash found within 10 paces."
              ObjectId.Stash = ObjId
              InsertDWORD &H2
              InsertDWORD ObjectId.Stash
              D2GSSend (&H13)
              Call SendChat("Opened stash, ID = " & ObjectId.Stash, vbNullString, &H1)
    End If
   
  Case &H5A
   pName = "Player status"
   Dim pType As Byte
   Dim character As String
   p_data = Mid$(data, 2, pSize)
   pType = getBYTE
   getBYTE
   getDWORD
   getBYTE
   character = getSTRING
   
    Select Case pType
     Case &H0
      AddChat &HA0522D, character & " has dropped due to timeout."
     Case &H2
      AddChat &HA0522D, character & " has joined our world. Diablo's minions grow stronger! Ahh!"
     Case &H3
      AddChat &HA0522D, character & " has left our world. Diablo 2 will be better off."
    End Select
   
  Case &H76
   pName = "Player location (World)"
   
  Case &H8B
   Dim playerID As Long
   Dim status As Byte
   pName = "Player relations"
   p_data = Mid$(data, 2, 5)
   
   playerID = getDWORD
   status = getBYTE
   
    Select Case status
     Case &H2
      AddChat vbGreen, "A player wishes to party with you."
      InsertBYTE &H8
      InsertDWORD playerID
      D2GSSend (&H5E)
     Case &H1
      AddChat vbGreen, "A player has joined a party."
     Case &H0
      AddChat vbGreen, "A player is not in a party."
            InsertBYTE &H6
      InsertDWORD playerID
      D2GSSend (&H5E)
    End Select
   
End Select

AddChat vbWhite, "Received packet: 0x" & Hex(pid) & " *" & pName & "*"
  lastPacketDump = Mid$(data, 1, pSize + 3)
Call D2GSParserRoutine(Mid$(data, pSize + 1))
End If

If pSize = 0 Then
  AddChat vbWhite, "Received invalid packet?: 0x" & Hex(pid)
  AddChat2 vbWhite, "Last packet dump: " & DebugOutput(lastPacketDump)
   AddChat2 vbWhite, "Dump: " & DebugOutput(data)
   Exit Sub
End If

End Sub

Ringo

#1
If you know the packets you need to read but have problems getting to them, make a filter parser :P
When i said the other day i had only 4 packets in a parser, i only had 4 packet lenghs in there as well.

[edit]
The 0x2F terminator is caused by the extra padding created inorder to stop it from crashing.

LivedKrad


Ringo

#3
The idea is to know as much as possible about the packets your trying to parse, like what values it has in it, and what numbers they should range in, and so on.
Iv tryed countless methods, and this is the better one iv come up with, but only works perfectly if you parse alot of packets.

    Case &HB4 to &HFF: PARSE_D2GS Mid(Data, 2)

    Case &H15
      'player reasign
        '15 01 XX XX XX XX >> >> ^^ ^^ 01
        If IsValid_0x15(Data, rLen) = True Then
            gs0x15 Left(Data, rLen - 1)
        End If
        PARSE_D2GS Mid(Data, rLen)


rLen should always return a lengh, even if the packet was found to be invalid (return 2)
This is kinda a sucky method, but it works :P
Iv since come up with a better method, but your welcome to this one if you want it :)

Tontow


Elneroth

Quote from: Tontow on July 14, 2005, 08:52 PM
Do a search, but this link might be of some help. http://forum.valhallalegends.com/phpbbs/index.php?topic=12188.0

You do realize, he's the one who made that post, right? :p

Archangel

Quote from: Tontow on July 14, 2005, 08:52 PM
Do a search, but this link might be of some help. http://forum.valhallalegends.com/phpbbs/index.php?topic=12188.0

Dude.. lol...
Read the links you are posting before doing so.
I'm not an Addict.

Tontow

#7
Opps, umm, the Devil made me do it?

R.a.B.B.i.T


LivedKrad

Quote from: Ringo on July 14, 2005, 08:18 PM
The idea is to know as much as possible about the packets your trying to parse, like what values it has in it, and what numbers they should range in, and so on.
Iv tryed countless methods, and this is the better one iv come up with, but only works perfectly if you parse alot of packets.

    Case &HB4 to &HFF: PARSE_D2GS Mid(Data, 2)

    Case &H15
      'player reasign
        '15 01 XX XX XX XX >> >> ^^ ^^ 01
        If IsValid_0x15(Data, rLen) = True Then
            gs0x15 Left(Data, rLen - 1)
        End If
        PARSE_D2GS Mid(Data, rLen)


rLen should always return a lengh, even if the packet was found to be invalid (return 2)
This is kinda a sucky method, but it works :P
Iv since come up with a better method, but your welcome to this one if you want it :)

We all share information on the forums, Ringo. If you're holding out on a more efficient parsing method, I'm open for suggestions. According to the table found by UserLoser in D2Net.dll, I have the packet lengths right for the definite length ones. However, since the data still seems to be not working when I try the parsing, it's odd that the parser seems to break on invalid packets or ones that are greater than 0xB3. I'm not saying it's any cut on your documentation, but I just don't know what else to do. I've been over my coding over and over again and for the life of me I cannot figure out what my problem is.

Thanks, and appreciate all the help I can get.

Ringo

Split up the large packets as well as the small packets, and you wont get a problem with crap data (the lengh header of a new compressed packet) ;)

LivedKrad

"splitting up" these packets is the entire front-end point of the parser. So, once again, please elborate.

Ringo

Quote from: LivedKrad.fe on July 16, 2005, 12:09 PM
"splitting up" these packets is the entire front-end point of the parser. So, once again, please elborate.
You need to split up the compressed packets as well as splitting them up after you decompress them.
Thats why the server adds a lengh header to the buffer before sending it to you :P
The reassion they are clumped after there compressed, is because of the way a tcp socket works