public override byte[] OnRecv(byte[] data, int length)
        {
            for (int i = 0; i < length; i++)
            {
                input.Add(data[i]);
            }
            while (input.Length >= 6)
            {
                if (needDecode && SS_Hash != null)
                {
                    Decode(input);
                    needDecode = false;
                }
                input.pos = 0;
                ushort len = input.GetWord();
                if (input.Length < len + 2)
                {
                    return(null);
                }

                needDecode = true;
                data       = input.GetArray(4, len - 2);
                OP code = (OP)(input[2] + (input[3] << 8));
                input.Remove(0, len + 2);
                SetInput(data);

                RunMsg(code);
            }
            return(null);
        }
        public override byte[] OnRecv(byte[] section, int length)
        {
            int t;

            byte[] data;

            for (int i = 0; i < length; i++)
            {
                input.Add(section[i]);
            }
            RealmType code = (RealmType)input[0];

            switch (code)
            {
            case RealmType.LOGON_CHALLENGE:                    //   Logon challenge
            case RealmType.RECONNECT_CHALLENGE:
            {
                if (input.Length < 34 || input.Length < 34 + input[33])
                {
                    return(null);
                }

                int clientVersion = input.Seek(11).GetWord();

                //byte[] blu = input.GetArray(5, input[33]);
                //Console.WriteLine("DEBUG:" + clientVersion);

                userName = input.GetArray(34, input[33]);

                data = input; input.Length = 0;

                sUserName = System.Text.Encoding.ASCII.GetString(userName);
                //string ble = System.Text.Encoding.ASCII.GetString(blu);

                byte [] hash = rl.GetUserPasswordHash(sUserName);
                //Console.WriteLine("DEBUG - ble:" + ble + "user: "******" code: " + code);
                    }

                    ByteArrayBuilder p = new ByteArrayBuilder();
                    p.Add((byte)1, 3);
                    p.Add(new byte[116]);
                    return(p);
                }

                if (LogMessageEvent != null)
                {
                    LogMessageEvent(sUserName + " code: " + code);
                }

                byte [] res = new Byte[hash.Length + salt.Length];
                Const.rand.NextBytes(salt);
#if CHECK
                salt = new byte[] { 0x33, 0xf1, 0x40, 0xd4, 0x6c, 0xb6, 0x6e, 0x63, 0x1f, 0xdb, 0xbb, 0xc9, 0xf0, 0x29, 0xad, 0x88, 0x98, 0xe0, 0x5e, 0xe5, 0x33, 0x87, 0x61, 0x18, 0x18, 0x5e, 0x56, 0xdd, 0xe8, 0x43, 0x67, 0x4f };
#endif

                t = 0;
                foreach (byte s in salt)
                {
                    res[t++] = s;
                }
                foreach (byte s in hash)
                {
                    res[t++] = s;
                }

                SHA1    sha   = new SHA1CryptoServiceProvider();
                byte [] hash2 = sha.ComputeHash(res, 0, res.Length);
                byte [] x     = Reverse(hash2);

                rN = Reverse(N);
                Const.rand.NextBytes(b);
#if CHECK
                b = new byte[] { 0x86, 0x92, 0xE3, 0xA6, 0xBA, 0x48, 0xB5, 0xB1, 0x00, 0x4C, 0xEF, 0x76, 0x82, 0x51, 0x27, 0xB7, 0xEB, 0x7D, 0x1A, 0xEF };
#endif
                rb = Reverse(b);


                BigInteger bi  = new BigInteger(x);
                BigInteger bi2 = new BigInteger(rN);
                G = new BigInteger(new byte[] { 7 });
                v = G.modPow(bi, bi2);

                K = new BigInteger(new Byte[] { 3 });
                BigInteger temp1 = K * v;
                BigInteger temp2 = G.modPow(new BigInteger(rb), new BigInteger(rN));
                BigInteger temp3 = temp1 + temp2;
                B = temp3 % new BigInteger(rN);

                ByteArrayBuilder pack = new ByteArrayBuilder();
                pack.Add((byte)0, 0, 0);
                pack.Add(Reverse(B.getBytes(32)));
                pack.Add((byte)1, 7, 32);
                pack.Add(N);
                pack.Add(salt);
                pack.Add(new byte[16]);
                return(pack);
            }

            case RealmType.LOGON_PROOF:                    //   Logon proof
            case RealmType.RECONNECT_PROOF:
            {
                if (input.Length < 53)
                {
                    return(null);
                }

                byte[] A   = input.GetArray(1, 32);
                byte[] kM1 = input.GetArray(33, 20);

                data         = input;
                input.Length = 0;


#if CHECK
                A = new byte[] { 0x23, 0x2f, 0xb1, 0xb8, 0x85, 0x29, 0x64, 0x3d, 0x95, 0xb8, 0xdc, 0xe7, 0x8f, 0x27, 0x50, 0xc7, 0x5b, 0x2d, 0xf3, 0x7a, 0xcb, 0xa8, 0x73, 0xeb, 0x31, 0x07, 0x38, 0x39, 0xed, 0xa0, 0x73, 0x8d };
#endif

                byte [] rA = Reverse(A);

                byte [] AB = Concat(A, Reverse(B.getBytes(32)));

                SHA1    shaM1 = new SHA1CryptoServiceProvider();
                byte [] U     = shaM1.ComputeHash(AB);

                byte [] rU = Reverse(U);

                // SS_Hash
                BigInteger temp1 = v.modPow(new BigInteger(rU), new BigInteger(rN));
                BigInteger temp2 = temp1 * new BigInteger(rA);
                BigInteger temp3 = temp2.modPow(new BigInteger(rb), new BigInteger(rN));

                byte [] S1 = new byte[16];
                byte [] S2 = new byte[16];
                byte [] S  = temp3.getBytes(32);
                byte [] rS = Reverse(S);

                for (t = 0; t < 16; t++)
                {
                    S1[t] = rS[t * 2];
                    S2[t] = rS[(t * 2) + 1];
                }
                byte [] hashS1  = shaM1.ComputeHash(S1);
                byte [] hashS2  = shaM1.ComputeHash(S2);
                byte [] SS_Hash = new byte[hashS1.Length + hashS2.Length];
                for (t = 0; t < hashS1.Length; t++)
                {
                    SS_Hash[t * 2]       = hashS1[t];
                    SS_Hash[(t * 2) + 1] = hashS2[t];
                }

                // cal M1
                byte [] NHash    = shaM1.ComputeHash(N);
                byte [] GHash    = shaM1.ComputeHash(G.getBytes());
                byte [] userHash = shaM1.ComputeHash(userName);
                byte [] NG_Hash  = new byte[20];
                for (t = 0; t < 20; t++)
                {
                    NG_Hash[t] = (byte)(NHash[t] ^ GHash[t]);
                }
                byte [] Temp = Concat(NG_Hash, userHash);
                Temp = Concat(Temp, salt);
                Temp = Concat(Temp, A);
                Temp = Concat(Temp, Reverse(B.getBytes(32)));
                Temp = Concat(Temp, SS_Hash);

                byte [] M1 = shaM1.ComputeHash(Temp);

                ByteArrayBuilder pack;
                if (!ByteArray.Same(M1, kM1))
                {
                    if (LogMessageEvent != null)
                    {
                        LogMessageEvent(sUserName + " code: " + code);
                    }

                    pack = new ByteArrayBuilder();
                    pack.Add((byte)1, 3);
                    pack.Add(new byte[24]);
                    return(pack);
                }

                if (LogMessageEvent != null)
                {
                    LogMessageEvent(sUserName + " code: " + code);
                }

                rl.SetUserSessionKey(sUserName, SS_Hash);

                // cal M2
                Temp = Concat(A, M1);
                Temp = Concat(Temp, SS_Hash);
                byte [] M2 = shaM1.ComputeHash(Temp);

                pack = new ByteArrayBuilder();
                pack.Add((byte)1, 0);
                pack.Add(M2);
                pack.Add(new byte[4]);

                return(pack);
            }

            case RealmType.UPDATESRV:                     // Update server
                if (input.Length < 1)
                {
                    return(null);
                }
                data = input; input.Length = 0;
                if (LogMessageEvent != null)
                {
                    LogMessageEvent("UPDATESRV");
                }
                break;

            case RealmType.REALMLIST:                     // Realm List
            {
                if (input.Length < 1)
                {
                    return(null);
                }
                byte[] request = input.GetArray(1, 4);
                input.Length = 0;
                if (LogMessageEvent != null)
                {
                    LogMessageEvent("REALMLIST");
                }
                ByteArrayBuilder pack = new ByteArrayBuilder(false);
                pack.Add((byte)RealmType.REALMLIST, 0, 0);
                pack.Add(request);

                rl.GetRealmList(sUserName, pack);

                pack.Add((byte)0, (byte)0);
                pack.Set(1, (ushort)(pack.Length - 3));

                return(pack);
            }

            default:
                data = input; input.Length = 0;
                if (LogMessageEvent != null)
                {
                    LogMessageEvent("Receive unknown command {0}" + data[0]);
                }
                break;
            }
            byte [] ret = { 0, 0 };
            return(ret);
        }