Valhalla Legends Forums Archive | .NET Platform | VB8 - Packet Buffer (annoying you yet?)

AuthorMessageTime
JoeTheOdd
Alright. I make an array list and add stuff to it. When it comes time, I make an array list, add sanity, add the ID, add the length, and add the other array list. Then I want to cast it to a byte array but noooo, VB wants to make it an Object array. When I try casting each Object to a byte, it yells at me. Obviously someone has figured it out but I've failed to find ANY way to do it, so if you'd enlighten me, it'd be appreciated.

[code]Public Class clsPacketBuffer

    Private myBuffer As New ArrayList()

    Public Sub add_uint8(ByVal uint8 As Byte)
        myBuffer.Add(uint8)
    End Sub

    Private Sub add_uint8array(ByVal uint8() As Byte)
        Dim b As Byte
        For Each b In uint8
            add_uint8(b)
        Next
    End Sub

    Public Sub add_uint16(ByVal uint16 As Short)
        add_uint8array(BitConverter.GetBytes(uint16))
    End Sub

    Public Sub add_uint32(ByVal uint32 As Integer)
        add_uint8array(BitConverter.GetBytes(uint32))
    End Sub

    Public Sub add_cstring(ByVal cstring As String)
        myBuffer.Add(cstring)
        add_uint8(0)
    End Sub

    Public Sub add_pstring(ByVal pstring As String)
        add_uint8(CType(Len(pstring), Byte))
        myBuffer.Add(pstring)
    End Sub

    Public Sub add_void(ByVal void As String)
        myBuffer.Add(void)
    End Sub

    Public Function GetPacket(ByVal PacketID As Byte) As Byte()
        Dim Packet As New ArrayList
        Packet.Add(CType(&HFF, Byte))
        Packet.Add(CType(PacketID, Byte))
        Packet.Add(CType(myBuffer.Count + 4, Short))
        Packet.Add(myBuffer)
        modFunctions.AddChat(Color.Blue, "[DEBUG] " + BitConverter.ToString(ObjectArrayToByteArray(Packet.ToArray)))
        GetPacket = ObjectArrayToByteArray(Packet.ToArray)
        myBuffer.Clear()
    End Function

    Private Function ObjectArrayToByteArray(ByVal O As Object()) As Byte()
        Dim B(0 To UBound(O)) As Byte, I As Integer
        For I = LBound(O) To UBound(O)
            B(I) = CType(O(I), Byte)
        Next I
        ObjectArrayToByteArray = B
    End Function

End Class[/code]
June 29, 2006, 3:57 AM
Myndfyr
http://www.jinxbot.net/mbncsutil/

See: DataBuffer class.
June 29, 2006, 4:24 AM
K
Since you're using VB Express, which should be .NET 2.0, you might want to just go ahead and use a List<byte>, or whatever the stupid VB notation is, like List Of Type Byte or whatever.
June 29, 2006, 6:02 PM
Myndfyr
Eww!  List<byte> is SO much more memory-intensive than a MemoryStream (System.IO in mscorlib). 
June 29, 2006, 8:48 PM
JoeTheOdd
I've already (kind of) ported MyndFyre's DataBuffer as well as the GetData from BnetPacket(?).

[code]Imports System
Imports System.IO
Imports System.Text
Imports System.Runtime.InteropServices

Public Class PacketBuffer
    Private m_ms As MemoryStream = New MemoryStream
    Private m_len As Integer = 0

    Public Sub Insert_BOOL(ByVal b As Boolean)
        If b Then
            Insert_DWORD(1)
        Else
            Insert_DWORD(0)
        End If
    End Sub

    Public Sub Insert_BYTE(ByVal b As Byte)
        m_ms.WriteByte(b)
        m_len += 1
    End Sub

    Public Sub Insert_WORD(ByVal w As UShort)
        m_ms.Write(BitConverter.GetBytes(w), 0, 2)
        m_len += 2
    End Sub

    Public Sub Insert_DWORD(ByVal d As UInteger)
        m_ms.Write(BitConverter.GetBytes(d), 0, 4)
        m_len += 4
    End Sub

    Public Sub Insert_QWORD(ByVal q As ULong)
        m_ms.Write(BitConverter.GetBytes(q), 0, 8)
        m_len += 8
    End Sub

    Public Sub Insert_CSTR(ByVal s As String)
        Dim B As Byte
        For Each B In Encoding.ASCII.GetBytes(s)
            Insert_BYTE(B)
        Next
        Insert_BYTE(0)
    End Sub

    Public Sub Insert_PSTR(ByVal s As String)
        If s.Length < 256 Then
            Insert_BYTE(s.Length & &HFF)
            Dim B As Byte
            For Each B In Encoding.ASCII.GetBytes(s)
                Insert_BYTE(B)
            Next
        End If
    End Sub

    Public Sub Insert_PWSTR(ByVal s As String)
        If s.Length < 65536 Then
            Insert_WORD(s.Length & &HFFFFFF)
            Dim B As Byte
            For Each B In Encoding.ASCII.GetBytes(s)
                Insert_BYTE(B)
            Next
        End If
    End Sub

    Public Sub Insert_VOID(ByVal v As String)
        Dim B As Byte
        For Each B In Encoding.ASCII.GetBytes(v)
            Insert_BYTE(B)
        Next
    End Sub

    Public Function GetData(ByVal PacketID As Byte) As Byte()
        Dim baseData() As Byte = GetData()
        Dim ret(Count + 3) As Byte
        ret(0) = &HFF
        ret(1) = PacketID
        Dim len() As Byte = BitConverter.GetBytes(CType((Count + 4 & &HFFFF), UShort))
        ret(2) = len(0)
        ret(3) = len(1)
        Buffer.BlockCopy(baseData, 0, ret, 4, baseData.Length)
        Return ret
    End Function

    Public Function GetData() As Byte()
        Dim ret(m_len) As Byte
        Buffer.BlockCopy(m_ms.GetBuffer(), 0, ret, 0, m_len)
        Return ret
    End Function

    Public ReadOnly Property Count() As Integer
        Get
            Return m_len
        End Get
    End Property

End Class[/code]
June 29, 2006, 8:56 PM
Dyndrilliac
Edit: I feel kind of stupid. Nevermind. I realize now I had a "::" operator where a "->" operator should have been.

I'm converting the above code to C++.NET, and I'm having a bit of trouble with the Insert_CSTR method. I'm using the following namespaces:[code]using namespace System;
using namespace System::Data;
using namespace System::IO;
using namespace System::Text;
using namespace System::Runtime::InteropServices;[/code]Here's my code:[code]Void __inline Insert_CSTR(String^ cstring) {
array<Byte>^ByteArray = Encoding::ASCII->GetBytes(cstring);
for (UInt16 i = 0; i < ByteArray->GetLength(); i++) {
Insert_BYTE(ByteArray[i]);
}
Insert_BYTE(0);
}[/code]Here's the error:[code]f:\backup\public\source code\c++.net\personal projects\dyslexicchat v2\clsPacketBuffer.h(59) : error C2039: 'GetBytes' : is not a member of 'System::Text::Encoding::ASCII'
        f:\backup\public\source code\c++.net\personal projects\dyslexicchat v2\clsPacketBuffer.h(59) : see declaration of 'System::Text::Encoding::ASCII'
f:\backup\public\source code\c++.net\personal projects\dyslexicchat v2\clsPacketBuffer.h(59) : error C3861: 'GetBytes': identifier not found[/code]I'm wondering where the GetBytes() method that the code shows is located; I'm using the .NET Framework v2.0.
August 31, 2006, 12:15 AM
TheMinistered
Uhm, the very first thing I wanted to point out is that you use 'AddVoid'.  The identifier void is associated with no data type.  I guess you could coin it as a string datatype, but that totally defies the definition of VOID.  If you wanted to associate any data type in .NET with void it would have to be OBJECT (my best guess).  Although, I personally wouldn't associate any data type in vb with void.

Then you implement CString and other weird STRING formats.  I don't see the neccesity of this.  You should stick with one string format, if possible, and comply to it through out your whole project -- otherwise things get real confusing and messy.  just a tip
September 22, 2006, 6:29 PM
Myndfyr
[quote author=TheMinistered link=topic=15296.msg158691#msg158691 date=1158949746]
Uhm, the very first thing I wanted to point out is that you use 'AddVoid'.  The identifier void is associated with no data type.  I guess you could coin it as a string datatype, but that totally defies the definition of VOID.  If you wanted to associate any data type in .NET with void it would have to be OBJECT (my best guess).  Although, I personally wouldn't associate any data type in vb with void.

Then you implement CString and other weird STRING formats.  I don't see the neccesity of this.  You should stick with one string format, if possible, and comply to it through out your whole project -- otherwise things get real confusing and messy.  just a tip
[/quote]

I implemented the InsertCString, InsertPascalString, and InsertWidePascalString methods in a generalized packet buffer that I used in a networking project in the past.  They're the three most common string formats, and when you include overloads to specify Encoding instances, they become incredibly flexible.
September 22, 2006, 7:28 PM

Search