Go Back   RunUO - Ultima Online Emulation > Developer's Corner > Programming > C#

C# C# Discussion

Reply
 
Thread Tools Display Modes
Old 01-30-2008, 01:31 PM   #1 (permalink)
Newbie
 
Join Date: Sep 2006
Age: 20
Posts: 11
Default Problems with Game Server List Packet

OK, so I'm trying to understand the UO protocol. I've found several pages describing the packets that make up the protocol, amongst others;


- POLServer.com UO Packets Site - Home
- Category:UO Protocol - Wolfpack Wiki
- Ultima Online Protocol

The problem that all these pages have in common is that none of them describe the order in which the packets are sent. If anyone could give me a brief overview, that would be very much appreciated!

I've come as far as to intercept the client's seed packet and login packet (0x80), and now I'm wondering what packet to send in response. It seems that RunUO is sending the Game Server List packet (0xA8) for a successful login, and the Login Failed packet (0x82) for failed login.

Sending the Login Failed packet for a failed login works out perfectly for me - the messagebox is displayed in the client with the correct failure message. However, no matter what I do, I just cannot get the Server List packet to work! :\

If anyone could take a look at my code and spot any obvious flaws in the way I'm building my Server List packet, I'd greatly appreciate it!

Code:
                if (Database.DoesAccountPassExist(AccountPwd))
                {
                    using (AuthPacketOut OutPacket = new AuthPacketOut(AuthServerOpCode.ACCOUNT_LOGIN_OK))
                    {
                        OutPacket.Write((byte)0x5D); //Unknown
                        OutPacket.Write((ushort)RealmServerManager.Realms.Count);

                        for (int i = 0; i < RealmServerManager.Realms.Count; i++)
                        {
                            ServerInfo Realm = RealmServerManager.Realms[i];

                            OutPacket.Write((ushort)i);
                            OutPacket.WriteAsciiFixed(Realm.Name, 32);
                            OutPacket.Write((byte)Realm.FullPercent);
                            OutPacket.Write((sbyte)Realm.TimeZone);
                            OutPacket.Write((int)BitConverter.ToInt32(Realm.Address.Address.GetAddressBytes(), 0));
                        }

                        OutPacket.BaseStream.Position = 1;
                        OutPacket.Write((ushort)OutPacket.Length);

                        Client.Send(OutPacket);

                        if (Globals.IsDebugEnabled)
                            Console.WriteLine("Login OK - sent packet!\n");
                    }
                }
PacketOut.cs:

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using WowServ.Cryptography;

namespace WowServ.Network
{
    public class PacketOut : BinaryWriter
    {
        PacketID m_ID;

        public PacketOut(PacketID ID)
            : base(new MemoryStream())
        {
            m_ID = ID;
        }

        /// <summary>
        /// Writes a number of 0x00 byte values to the underlying stream.
        /// </summary>
        public void Fill(int length)
        {
            if (Position == Length)
            {
                this.BaseStream.SetLength(Length + length);
                Seek(0, SeekOrigin.End);
            }
            else
                Write(new byte[length], 0, length);
        }

        /// <summary>
        /// Writes a fixed-length ASCII-encoded string value to the underlying stream. To fit (size), the string content is either truncated or padded with null characters.
        /// </summary>
        public void WriteAsciiFixed(string value, int size)
        {
            if (value == null)
            {
                Console.WriteLine("Network: Attempted to WriteAsciiFixed() with null value\n");
                value = String.Empty;
            }

            byte[] buffer = Encoding.ASCII.GetBytes(value);

            if (buffer.Length >= size)
                Write(buffer, 0, size);
            else
            {
                Write(buffer, 0, buffer.Length);
                Fill(size - buffer.Length);
            }
        }

        /// <summary>
        /// Writes a C-style string to the stream
        /// </summary>
        /// <param name="str">String to write</param>
        public virtual void WriteCString(string str)
        {
            Write(Encoding.ASCII.GetBytes(str));
            Write('\0');
        }

        /// <summary>
        /// Writes a BigInteger to the stream
        /// </summary>
        /// <param name="bigInt">BigInteger to write</param>
        public virtual void WriteBigInt(BigInteger bigInt)
        {
            byte[] data = bigInt.GetBytes();

            base.Write(data);
        }

        /// <summary>
        /// Writes a BigInteger to the stream
        /// </summary>
        /// <param name="bigInt">BigInteger to write</param>
        /// <param name="length">maximum numbers of bytes to write for th BigInteger</param>
        public virtual void WriteBigInt(BigInteger bigInt, int length)
        {
            byte[] data = bigInt.GetBytes(length);

            base.Write(data);
        }

        /// <summary>
        /// Writes a BigInteger to the stream, while writing the length before it
        /// </summary>
        /// <param name="bigInt">BigInteger to write</param>
        public virtual void WriteBigIntLength(BigInteger bigInt)
        {
            byte[] data = bigInt.GetBytes();

            base.Write((byte)data.Length);
            base.Write(data);
        }

        /// <summary>
        /// Writes a BigInteger to the stream, while writing the length before it
        /// </summary>
        /// <param name="bigInt">BigInteger to write</param>
        /// <param name="length">maximum numbers of bytes to write for th BigInteger</param>
        public virtual void WriteBigIntLength(BigInteger bigInt, int length)
        {
            byte[] data = bigInt.GetBytes(length);

            base.Write((byte)length);
            base.Write(data);
        }

        /// <summary>
        /// Writes a short to the stream
        /// </summary>
        /// <param name="val">the value to write</param>
        public virtual void WriteShort(int val)
        {
            Write((short)val);
        }

        /// <summary>
        /// Writes a short to the stream
        /// </summary>
        /// <param name="val">the value to write</param>
        public virtual void WriteShort(uint val)
        {
            Write((short)val);
        }

        /// <summary>
        /// Writes the supplied value to the stream for a specified number of bytes
        /// </summary>
        /// <param name="val">Value to write</param>
        /// <param name="num">Number of bytes to write</param>
        public virtual void Fill(byte val, int num)
        {
            for (int i = 0; i < num; ++i)
            {
                Write((byte)val);
            }
        }

        /// <summary>
        /// Fetches all the data in this Packet's stream
        /// and returns them as a byte array for sending.
        /// Should NOT be called before ALL data is written
        /// to the packet!!
        /// </summary>
        /// <returns>A byte array of the packet's data.</returns>
        public byte[] GetBytes()
        {
            MemoryStream MemStream;
            MemStream = (MemoryStream)base.BaseStream;

            return MemStream.ToArray();
        }

        public int Position
        {
            get { return (int)base.BaseStream.Position; }
            set { base.BaseStream.Position = value; }
        }

        public int Length
        {
            get { return (int)base.BaseStream.Length; }
        }

        public UInt16 LengthUInt16
        {
            get { return (UInt16)base.BaseStream.Length; }
        }
    }
}
AuthPacketOut.cs:

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WowServ.Network;

namespace ServeUO.Network
{
    public class AuthPacketOut : PacketOut
    {
        public AuthPacketOut(AuthServerOpCode OpCode)
            : base(new PacketID(OpCode))
        {
            Write((byte)OpCode);
        }

        public AuthPacketOut(RealmAuthProofErrorCodes OpCode)
            : base(new PacketID(IDType.Authentication, (byte)OpCode))
        {
        }
    }
}
My client is UO Gold, version 4.0.6a (Patch 6). Encryption was removed with UO RICE.

Thanks in advance!

PS: Sorry to mods if this was in the wrong forum section. Didn't quite know where to put this...
Afr0man is offline   Reply With Quote
Old 01-30-2008, 04:20 PM   #2 (permalink)
Newbie
 
Join Date: Nov 2007
Age: 22
Posts: 69
Default

I don't remember the order, but if you use Razor you can log the packets and see the order.
Chase.XNA is offline   Reply With Quote
Old 01-30-2008, 06:49 PM   #3 (permalink)
Newbie
 
Join Date: Sep 2006
Age: 20
Posts: 11
Question Hm..

Thanks, that turned out to be very informative actually!
According to the logging I did with a program called UOLog, the packet coming from the server at this point in the login process is indeed the Server List packet. However, with one server in the list, the packet I logged was at 46 bytes (coming from one of the Razor servers), and the one I'm sending is only 44 bytes!
I can't for the life of me figure out why, however I changed this:

Code:
OutPacket.Write((int)BitConverter.ToInt32(Realm.Address.Address.GetAddressBytes(), 0));
to a uint, because the I read in one of the protocol descriptions that it was supposed to be a uint, not an int. Yet, RunUO seems to be sending an int! Does this any any effect at all, and is there a difference for different client versions here? At least it didn't increase my packet's size by the last two missing bytes, so I know something's still off.

But what?

Thanks in advance!

Edit - Log:

Code:
This log was recorded with Folko's UOLog.
Using client 4.0.8a T2A.

00:26:42.632 Client -> Server: 0x80 (AuthRequest), frequ: 1, len: 0x3E
0000: 80 41 66 72 30 00 00 00 00 00 00 00 00 00 00 00 ->.Afr0...........
0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 70 ->...............p
0020: 72 69 6E 73 00 00 00 00 00 00 00 00 00 00 00 00 ->rins............
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 5D       ->.............]

00:26:43.198 Server -> Client: 0xA8 (SendShards), frequ: 1, len: 0x2E
0000: A8 2E 00 5D 00 01 00 00 55 4F 47 61 6D 65 72 73 ->...]....UOGamers
0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0020: 00 00 00 00 00 00 00 00 00 FA F0 25 7E 4B       ->...........%~K

00:26:43.200 Client -> Server: 0xD9 (Unknown), frequ: 1, len: 0x10C
0000: D9 02 47 94 B2 45 00 00 00 06 00 00 00 00 00 00 ->..G..E..........
0010: 17 70 02 00 00 00 06 00 00 00 0F 00 00 07 CF 02 ->.p..............
0020: 00 00 08 00 00 00 05 00 00 00 04 00 00 00 00 20 ->............... 
0030: 00 09 00 00 4E 00 56 00 49 00 44 00 49 00 41 00 ->....N.V.I.D.I.A.
0040: 20 00 47 00 65 00 46 00 6F 00 72 00 63 00 65 00 -> .G.e.F.o.r.c.e.
0050: 20 00 38 00 36 00 30 00 30 00 20 00 47 00 54 00 -> .8.6.0.0. .G.T.
0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
00B0: 00 00 00 00 00 00 10 DE 00 00 04 02 00 00 00 F8 ->................
00C0: 0A 02 06 10 6E 00 6F 00 72 00 00 00 00 00 00 00 ->....n.o.r.......
00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
00E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0100: 00 00 00 00 00 00 00 00 00 00 00 00             ->............

00:27:32.30 Client -> Server: 0xA0 (SelectShard), frequ: 1, len: 0x03
0000: A0 00 00                                        ->...

00:27:32.224 Server -> Client: 0x8C (Relay), frequ: 1, len: 0x0B
0000: 8C 4B 7E 25 F0 0A 21 C4 D4 C8 9C                ->.K~%..!....

00:27:32.419 Client -> Server: 0x91 (RelayAuth), frequ: 1, len: 0x41
0000: 91 C4 D4 C8 9C 41 66 72 30 00 00 00 00 00 00 00 ->.....Afr0.......
0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0020: 00 00 00 70 72 69 6E 73 00 00 00 00 00 00 00 00 ->...prins........
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0040: 00                                              ->.

00:27:32.998 Server -> Client: 0xA9 (SendCharsAndCities), frequ: 1, len: 0x3AB
0000: A9 AB 03 05 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
00A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
00B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
00E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0130: 0A 00 59 65 77 00 00 00 00 00 00 00 00 00 00 00 ->..Yew...........
0140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0150: 00 54 68 65 20 45 6D 70 61 74 68 20 41 62 62 65 ->.The Empath Abbe
0160: 79 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->y...............
0170: 01 4D 69 6E 6F 63 00 00 00 00 00 00 00 00 00 00 ->.Minoc..........
0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0190: 54 68 65 20 42 61 72 6E 61 63 6C 65 00 00 00 00 ->The Barnacle....
01A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 ->................
01B0: 42 72 69 74 61 69 6E 00 00 00 00 00 00 00 00 00 ->Britain.........
01C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 53 ->...............S
01D0: 77 65 65 74 20 44 72 65 61 6D 73 20 49 6E 6E 00 ->weet Dreams Inn.
01E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 4D ->...............M
01F0: 6F 6F 6E 67 6C 6F 77 00 00 00 00 00 00 00 00 00 ->oonglow.........
0200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 54 68 ->..............Th
0210: 65 20 53 63 68 6F 6C 61 72 73 20 49 6E 6E 00 00 ->e Scholars Inn..
0220: 00 00 00 00 00 00 00 00 00 00 00 00 00 04 54 72 ->..............Tr
0230: 69 6E 73 69 63 00 00 00 00 00 00 00 00 00 00 00 ->insic...........
0240: 00 00 00 00 00 00 00 00 00 00 00 00 00 54 68 65 ->.............The
0250: 20 54 72 61 76 65 6C 65 72 27 73 20 49 6E 6E 00 -> Traveler's Inn.
0260: 00 00 00 00 00 00 00 00 00 00 00 00 05 4D 61 67 ->.............Mag
0270: 69 6E 63 69 61 00 00 00 00 00 00 00 00 00 00 00 ->incia...........
0280: 00 00 00 00 00 00 00 00 00 00 00 00 54 68 65 20 ->............The 
0290: 47 72 65 61 74 20 48 6F 72 6E 73 20 54 61 76 65 ->Great Horns Tave
02A0: 72 6E 00 00 00 00 00 00 00 00 00 06 4A 68 65 6C ->rn..........Jhel
02B0: 6F 6D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->om..............
02C0: 00 00 00 00 00 00 00 00 00 00 00 54 68 65 20 4D ->...........The M
02D0: 65 72 63 65 6E 61 72 79 20 49 6E 6E 00 00 00 00 ->ercenary Inn....
02E0: 00 00 00 00 00 00 00 00 00 00 07 53 6B 61 72 61 ->...........Skara
02F0: 20 42 72 61 65 00 00 00 00 00 00 00 00 00 00 00 -> Brae...........
0300: 00 00 00 00 00 00 00 00 00 00 54 68 65 20 46 61 ->..........The Fa
0310: 6C 63 6F 6E 65 72 27 73 20 49 6E 6E 00 00 00 00 ->lconer's Inn....
0320: 00 00 00 00 00 00 00 00 00 08 56 65 73 70 65 72 ->..........Vesper
0330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0340: 00 00 00 00 00 00 00 00 00 54 68 65 20 49 72 6F ->.........The Iro
0350: 6E 77 6F 6F 64 20 49 6E 6E 00 00 00 00 00 00 00 ->nwood Inn.......
0360: 00 00 00 00 00 00 00 00 09 48 61 76 65 6E 00 00 ->.........Haven..
0370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->................
0380: 00 00 00 00 00 00 00 00 42 75 63 6B 6C 65 72 27 ->........Buckler'
0390: 73 20 48 69 64 65 61 77 61 79 00 00 00 00 00 00 ->s Hideaway......
03A0: 00 00 00 00 00 00 00 00 00 00 08                ->...........

00:28:33.76 Client -> Server: 0x73 (PingPong), frequ: 1, len: 0x02
0000: 73 00                                           ->s.

00:28:33.257 Server -> Client: 0x73 (PingPong), frequ: 2, len: 0x02
0000: 73 00                                           ->s.

Packet statistics

Client->Server:
80: 1 times, 62 bytes (~62 bytes per packet) //AuthRequest
91: 1 times, 65 bytes (~65 bytes per packet) //RelayAuth
A0: 1 times, 3 bytes (~3 bytes per packet) //SelectShard
D9: 1 times, 268 bytes (~268 bytes per packet) //Unknown

Server->Client:
8C: 1 times, 11 bytes (~11 bytes per packet) //Relay
A8: 1 times, 46 bytes (~46 bytes per packet) //SendShards
A9: 1 times, 939 bytes (~939 bytes per packet) //SendCharsAndCities

Bidirectional packets:
73: 2 times, 4 bytes (~2 bytes per packet) //PingPong
End of statistics

Bytes sent: 400.
Bytes received: 998.
Total 1398 bytes.
Client was active for 1 minutes
That results in 0.02 kb/s.
Afr0man is offline   Reply With Quote
Old 01-31-2008, 12:13 AM   #4 (permalink)
Newbie
 
Join Date: Nov 2007
Age: 22
Posts: 69
Default

it looks like your forgetting to add the packet length. because its a dynamic size packet you need to add a ushort after the packet id that will tell the client the packet size. when you create the packet you should write the packet id and if it is a dynamic size packet you should write two extra byte, then when you're compiling the packet you want to Seek(1, SeekOrgin.Begin) and write the packet lenght.

Take a look at RunUOs Packet class if you're having trouble.
Chase.XNA is offline   Reply With Quote
Old 01-31-2008, 02:56 AM   #5 (permalink)
Newbie
 
Join Date: Sep 2006
Age: 20
Posts: 11
Default

I'd advise you to take your password out of the packet log, Afr0.

Edit: Hm? I didn't post this? Who did? A mod? Anyways, thanks for warning me, but that account was created yesterday on server with auto account creation on, and I've no use for it other than for testing purposes.

Last edited by Afr0man; 01-31-2008 at 10:12 AM.
Afr0man is offline   Reply With Quote
Old 01-31-2008, 10:14 AM   #6 (permalink)
Newbie
 
Join Date: Sep 2006
Age: 20
Posts: 11
Default

Thanks for your response Chase.XNA!

I now did like this to pad out the packet length:

Code:
                if (Database.DoesAccountPassExist(AccountPwd))
                {
                    using (AuthPacketOut OutPacket = new AuthPacketOut(AuthServerOpCode.ACCOUNT_LOGIN_OK))
                    {
                        OutPacket.Write((byte)0x5D);   //Unknown
                        OutPacket.Write((ushort)0x00); //Packet length
                        OutPacket.Write((ushort)RealmServerManager.Realms.Count);

                        for (int i = 0; i < RealmServerManager.Realms.Count; i++)
                        {
                            ServerInfo Realm = RealmServerManager.Realms[i];

                            OutPacket.Write((ushort)i);
                            OutPacket.WriteAsciiFixed(Realm.Name, 32);
                            OutPacket.Write((byte)Realm.FullPercent);
                            OutPacket.Write((sbyte)Realm.TimeZone);
                            OutPacket.Write((int)Realm.Address.Address.Address);
                        }

                        OutPacket.BaseStream.Position = 1;
                        OutPacket.Write((ushort)OutPacket.Length);
                        Console.WriteLine("PacketLength: " + OutPacket.Length.ToString());

                        Client.Send(OutPacket);

                        if (Globals.IsDebugEnabled)
                            Console.WriteLine("Login OK - sent packet!n");
                    }
It still doesn't work though! >_<
I'm going to try to experiment with RunUO's EnsurePacketLength() function, but in the meantime I'd appreciate any further help on this issue.

Thanks!
Afr0man is offline   Reply With Quote
Old 01-31-2008, 12:09 PM   #7 (permalink)
Master of the Internet
 
Join Date: Mar 2006
Location: Germany
Age: 17
Posts: 14,546
Send a message via AIM to Suil Ban Send a message via MSN to Suil Ban
Default

Quote:
Originally Posted by Afr0man View Post
I'd advise you to take your password out of the packet log, Afr0.

Edit: Hm? I didn't post this? Who did? A mod? Anyways, thanks for warning me, but that account was created yesterday on server with auto account creation on, and I've no use for it other than for testing purposes.
I did, with the password in the packet log.
__________________

Now open - uo15.net - The best in Publish 15 emulation
Suil Ban is offline   Reply With Quote
Old 02-02-2008, 03:51 AM   #8 (permalink)
Newbie
 
Join Date: Sep 2006
Age: 20
Posts: 11
Default :\

Aaah I need help! Aren't there any RunUO devs on these forums somewhere?

I tried wrapping BinaryWriter.BaseStream.SetLength() into a function called EnsureCapacity(), to ensure that the packet was 46 bytes (even though it already was, since I padded out the packet length).

Still nothing! :\

BTW, are all members on this forum as 'helpful' as Radwen? I strongly advice staying away from the 'Ask Radwen' thread for answers to technical issues.
Afr0man is offline   Reply With Quote
Old 02-02-2008, 02:38 PM   #9 (permalink)
Newbie
 
Join Date: Nov 2007
Age: 22
Posts: 69
Default

Post your Packet class and ServerList packet so I can see what kind of changes you've made.
Chase.XNA is offline   Reply With Quote
Old 02-05-2008, 07:36 AM   #10 (permalink)
Newbie
 
Join Date: Sep 2006
Age: 20
Posts: 11
Default Here ya go

PacketOut.cs:

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using WowServ.Cryptography;

namespace WowServ.Network
{
    public class PacketOut : BinaryWriter
    {
        PacketID m_ID;

        public PacketOut(PacketID ID)
            : base(new MemoryStream())
        {
            m_ID = ID;
        }

        /// <summary>
        /// Writes a number of 0x00 byte values to the underlying stream.
        /// </summary>
        public void Fill(int length)
        {
            if (Position == Length)
            {
                this.BaseStream.SetLength(Length + length);
                Seek(0, SeekOrigin.End);
            }
            else
                Write(new byte[length], 0, length);
        }

        /// <summary>
        /// Ensures that the packet's datastream is set to a given length.
        /// </summary>
        /// <param name="Length">The length of the stream, in bytes.</param>
        public void EnsureCapacity(int Length)
        {
            this.BaseStream.SetLength(Length);
        }

        /// <summary>
        /// Writes a fixed-length ASCII-encoded string value to the underlying stream. To fit (size), the string content is either truncated or padded with null characters.
        /// </summary>
        public void WriteAsciiFixed(string value, int size)
        {
            if (value == null)
            {
                Console.WriteLine("Network: Attempted to WriteAsciiFixed() with null valuen");
                value = String.Empty;
            }

            byte[] buffer = Encoding.ASCII.GetBytes(value);

            if (buffer.Length >= size)
                Write(buffer, 0, size);
            else
            {
                Write(buffer, 0, buffer.Length);
                Fill(size - buffer.Length);
            }
        }

        /// <summary>
        /// Writes a C-style string to the stream
        /// </summary>
        /// <param name="str">String to write</param>
        public virtual void WriteCString(string str)
        {
            Write(Encoding.ASCII.GetBytes(str));
            Write('');
        }

        /// <summary>
        /// Writes a BigInteger to the stream
        /// </summary>
        /// <param name="bigInt">BigInteger to write</param>
        public virtual void WriteBigInt(BigInteger bigInt)
        {
            byte[] data = bigInt.GetBytes();

            base.Write(data);
        }

        /// <summary>
        /// Writes a BigInteger to the stream
        /// </summary>
        /// <param name="bigInt">BigInteger to write</param>
        /// <param name="length">maximum numbers of bytes to write for th BigInteger</param>
        public virtual void WriteBigInt(BigInteger bigInt, int length)
        {
            byte[] data = bigInt.GetBytes(length);

            base.Write(data);
        }

        /// <summary>
        /// Writes a BigInteger to the stream, while writing the length before it
        /// </summary>
        /// <param name="bigInt">BigInteger to write</param>
        public virtual void WriteBigIntLength(BigInteger bigInt)
        {
            byte[] data = bigInt.GetBytes();

            base.Write((byte)data.Length);
            base.Write(data);
        }

        /// <summary>
        /// Writes a BigInteger to the stream, while writing the length before it
        /// </summary>
        /// <param name="bigInt">BigInteger to write</param>
        /// <param name="length">maximum numbers of bytes to write for th BigInteger</param>
        public virtual void WriteBigIntLength(BigInteger bigInt, int length)
        {
            byte[] data = bigInt.GetBytes(length);

            base.Write((byte)length);
            base.Write(data);
        }

        /// <summary>
        /// Writes a short to the stream
        /// </summary>
        /// <param name="val">the value to write</param>
        public virtual void WriteShort(int val)
        {
            Write((short)val);
        }

        /// <summary>
        /// Writes a short to the stream
        /// </summary>
        /// <param name="val">the value to write</param>
        public virtual void WriteShort(uint val)
        {
            Write((short)val);
        }

        /// <summary>
        /// Writes the supplied value to the stream for a specified number of bytes
        /// </summary>
        /// <param name="val">Value to write</param>
        /// <param name="num">Number of bytes to write</param>
        public virtual void Fill(byte val, int num)
        {
            for (int i = 0; i < num; ++i)
            {
                Write((byte)val);
            }
        }

        /// <summary>
        /// Fetches all the data in this Packet's stream
        /// and returns them as a byte array for sending.
        /// Should NOT be called before ALL data is written
        /// to the packet!!
        /// </summary>
        /// <returns>A byte array of the packet's data.</returns>
        public byte[] GetBytes()
        {
            MemoryStream MemStream;
            MemStream = (MemoryStream)base.BaseStream;

            return MemStream.ToArray();
        }

        public int Position
        {
            get { return (int)base.BaseStream.Position; }
            set { base.BaseStream.Position = value; }
        }

        public int Length
        {
            get { return (int)base.BaseStream.Length; }
        }

        public UInt16 LengthUInt16
        {
            get { return (UInt16)base.BaseStream.Length; }
        }
    }
}
Code:
        private static void SendLoginOKPacket(AuthClient Client)
        {
            using (AuthPacketOut OutPacket = new AuthPacketOut(AuthServerOpCode.ACCOUNT_LOGIN_OK))
            {
                OutPacket.EnsureCapacity(6 + (RealmServerManager.Realms.Count * 40));

                OutPacket.Write((ushort)0x00); //Packet length
                OutPacket.Write((byte)0x5D);   //Unknown
                OutPacket.Write((ushort)RealmServerManager.Realms.Count);

                for (int i = 0; i < RealmServerManager.Realms.Count; i++)
                {
                    ServerInfo Realm = RealmServerManager.Realms[i];

                    OutPacket.Write((ushort)i);
                    OutPacket.WriteAsciiFixed(Realm.Name, 32);
                    OutPacket.Write((byte)Realm.FullPercent);
                    OutPacket.Write((sbyte)Realm.TimeZone);
                    OutPacket.Write((int)Globals.GetAddressValue(Realm.Address.Address));
                }

                OutPacket.BaseStream.Position = 0;
                OutPacket.Write((ushort)OutPacket.Length);

                Console.WriteLine("PacketLength: " + OutPacket.Length.ToString());

                Client.Send(OutPacket);

                if (Globals.IsDebugEnabled)
                    Console.WriteLine("Login OK - sent packet!n");
            }
        }
Afr0man is offline   Reply With Quote
Old 02-05-2008, 02:49 PM   #11 (permalink)
Newbie
 
Join Date: Nov 2007
Age: 22
Posts: 69
Default

OutPacket.BaseStream.Position = 0;
OutPacket.Write((ushort)OutPacket.Length);

isn't right, you're overwriting the packet id, it should be "OutPacket.BaseStream.Position = 1;."

It would be better to write the length in the EnsureCapacity method. Also, Im not sure if you can use a BinaryWriter, I've never tried it but you might want to compare the bytes of your packet to the bytes of a packet you logged from the EA client.

**edit daat99: removed irrelevant and unhelpful comment that wasn't supposed to be here...
If you want to make comments like that in the future please provide some helpful insight with them.**

Last edited by daat99; 02-05-2008 at 11:37 PM.
Chase.XNA is offline   Reply With Quote
Reply

Bookmarks


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off



Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0 RC5