예제 #1
0
        private int HandlePerformanceCounter(ConnInfo Conn, List <byte> buf)
        {
            TGSPerformanceCounter packet = new TGSPerformanceCounter();
            int pos = Marshal.SizeOf(packet);

            packet = (TGSPerformanceCounter)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            D2DBS.mysql.Execute("INSERT DELAYED INTO performance (`date`,`gs_addr`,`busy_pool`, `idle_pool`, `thread_num`, `handle_num`, `ge_num`) VALUES (UNIX_TIMESTAMP(), '" + Conn.RemoteAddr + "','" + packet.BusyPool.ToString() + "','" + packet.IdlePool.ToString() + "','" + packet.ThreadNum.ToString() + "','" + packet.HandleNum.ToString() + "','" + packet.GENum.ToString() + "')");
            return(0);
        }
예제 #2
0
        private int HandleSaveCharSave(ConnInfo Conn, List <byte> buf)
        {
            TGSSaveCharSaveRequest packet = new TGSSaveCharSaveRequest();
            int pos = Marshal.SizeOf(packet);

            packet = (TGSSaveCharSaveRequest)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            string[] Names       = BytesToString(buf.GetRange(pos, buf.Count - pos - packet.datalen)).Split('\0');
            string   AccountName = Names[0];
            string   CharName    = Names[1];
            string   GameName    = Names[2];
            string   IPAddr      = Names[3];
            string   ItemLog     = Names[4];
            string   CharVersion = D2DBS.config["char_version"];
            byte     result      = 1;

            byte[] data = buf.GetRange(buf.Count - packet.datalen, packet.datalen).ToArray();

            if (data[0] != 0x55 || data[1] != 0xAA)
            {
                D2DBS.log.Write("error", "Invaild charsave `" + CharName + "`(*" + AccountName + ")@" + GameName + " for gs " + Conn.GSId.ToString());
            }
            else
            {
                if (D2DBS.charfile.SetCharSave(AccountName, CharName, data) == true)
                {
                    D2DBS.mysql.Execute("UPDATE LOW_PRIORITY charstat SET `ist` = '" + packet.ist.ToString() + "' WHERE version = '" + CharVersion + "' AND charname = '" + CharName + "'");

                    if (ItemLog.Length > 0)
                    {
                        D2DBS.mysql.Execute("INSERT DELAYED INTO itemrecord (`date`,`version`,`game`,`charname`,`accname`,`ipaddr`,`itemchange`,`istchange`) VALUES (UNIX_TIMESTAMP(), '" + CharVersion + "', '" + D2DBS.mysql.Escape(GameName) + "', '" + CharName + "', '" + AccountName + "', '" + IPAddr + "', '" + D2DBS.mysql.Escape(ItemLog) + "','" + packet.changedist.ToString() + "')");
                    }

                    result = 0;
                    D2DBS.log.Write("info", "Saved charsave `" + CharName + "`(*" + AccountName + ") for gs " + Conn.GSId.ToString());
                }
                else
                {
                    D2DBS.log.Write("info", "Failed to saved charsave `" + CharName + "`(*" + AccountName + ") for gs " + Conn.GSId.ToString());
                }
            }

            TDBSSaveDataReply rpacket = new TDBSSaveDataReply();

            byte[] rawcharname = StringToChars(CharName);
            rpacket.h.seqno  = packet.h.seqno;
            rpacket.h.type   = (byte)EPacketType.DBSSaveDataReply;
            rpacket.h.size   = (short)(Marshal.SizeOf(rpacket) + rawcharname.Length);
            rpacket.datatype = 1;
            rpacket.result   = result;
            lock (Conn.StreamLocker)
            {
                Conn.NetWriter.Write(D2DBS.core.StructToBytes(rpacket));
                Conn.NetWriter.Write(rawcharname);
                Conn.NetWriter.Flush();
            }
            return(0);
        }
예제 #3
0
        private int HandleEmergency(ConnInfo Conn, List <byte> buf)
        {
            TGSEmergency packet = new TGSEmergency();
            int          pos    = Marshal.SizeOf(packet);

            packet = (TGSEmergency)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            D2DBS.mysql.Execute("INSERT DELAYED INTO emergency (`date`,`gs_addr`,`type`, `param`) VALUES (UNIX_TIMESTAMP(), '" + Conn.RemoteAddr + "','" + packet.EmergencyType.ToString() + "','" + packet.Param.ToString() + "')");
            return(0);
        }
예제 #4
0
        private int HandleRateExceeded(ConnInfo Conn, List <byte> buf)
        {
            TGSRateExceeded packet = new TGSRateExceeded();
            int             pos    = Marshal.SizeOf(packet);

            string[] Names = BytesToString(buf.GetRange(pos, buf.Count - pos)).Split('\0');
            packet = (TGSRateExceeded)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            D2DBS.mysql.Execute("INSERT DELAYED INTO rate_exceeded (`date`,`gs_addr`,`charname`, `accname`, `ipaddr`, `rate`) VALUES (UNIX_TIMESTAMP(), '" + Conn.RemoteAddr + "','" + Names[0] + "','" + Names[1] + "','" + Names[2] + "','" + packet.RequestRate.ToString() + "')");
            return(0);
        }
예제 #5
0
        public int HandlePacket(ConnInfo Conn, List <byte> buf)
        {
            THeader h = new THeader();

            if (buf.Count < Marshal.SizeOf(h))
            {
                return(-1);
            }
            h = (THeader)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(h), h.GetType());
            if (buf.Count != h.size)
            {
                return(-1);
            }
            switch ((EPacketType)h.type)
            {
            case EPacketType.GSGetDataRequest:
                return(HandleGetDataRequest(Conn, buf));

            case EPacketType.GSCloseSignal:
                return(HandleCloseSignal(Conn, buf));

            case EPacketType.GSCharLock:
                return(HandleCharLock(Conn, buf));

            case EPacketType.GSKickReply:
                return(HandleKickReply(Conn, buf));

            case EPacketType.GSSaveCharInfoRequest:
                return(HandleSaveCharInfo(Conn, buf));

            case EPacketType.GSSaveCharSaveRequest:
                return(HandleSaveCharSave(Conn, buf));

            case EPacketType.GSUpdateLadder:
                return(HandleUpdateLadder(Conn, buf));

            case EPacketType.GSPerformanceCounter:
                return(HandlePerformanceCounter(Conn, buf));

            case EPacketType.GSRateExceeded:
                return(HandleRateExceeded(Conn, buf));

            case EPacketType.GSEmergency:
                return(HandleEmergency(Conn, buf));

            case EPacketType.GSSOJCounterUpdate:
                return(HandleSOJCounterUpdate(Conn, buf));

            case EPacketType.GSEchoReply:
                return(0);

            default:
                return(-1);
            }
        }
예제 #6
0
 public int DBSHandlePacket(ConnInfo Conn, List<byte> buf)
 {
     try
     {
         return D2DBS.packet.HandlePacket(Conn, buf);
     }
     catch (Exception e)
     {
         D2DBS.log.Write("error", "Error occured while handling packet: " + e.ToString());
         return -1;
     }
 }
예제 #7
0
 public int DBSHandlePacket(ConnInfo Conn, List <byte> buf)
 {
     try
     {
         return(D2DBS.packet.HandlePacket(Conn, buf));
     }
     catch (Exception e)
     {
         D2DBS.log.Write("error", "Error occured while handling packet: " + e.ToString());
         return(-1);
     }
 }
예제 #8
0
        private int HandleUpdateLadder(ConnInfo Conn, List <byte> buf)
        {
            TGSUpdateLadder packet = new TGSUpdateLadder();
            int             pos    = Marshal.SizeOf(packet);

            packet = (TGSUpdateLadder)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            string[] Names    = BytesToString(buf.GetRange(pos, buf.Count - pos)).Split('\0');
            string   CharName = Names[0];

            D2DBS.ladder.UpdateLadder(packet.charexplow, packet.charstatus, packet.charlevel, packet.charclass, CharName);
            D2DBS.log.Write("info", "Ladder of `" + CharName + "`(L=" + packet.charlevel.ToString() + ",C=" + packet.charclass.ToString() + ",S=" + packet.charstatus.ToString() + ") updated for gs " + Conn.GSId.ToString());
            return(0);
        }
예제 #9
0
        private int HandleKickReply(ConnInfo Conn, List <byte> buf)
        {
            TGSKickReply packet = new TGSKickReply();
            int          pos    = Marshal.SizeOf(packet);

            packet = (TGSKickReply)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            string[] Names    = BytesToString(buf.GetRange(pos, buf.Count - pos)).Split('\0');
            string   CharName = Names[0];

            if (packet.result == 1)
            {
                D2DBS.charlock.UnlockChar(CharName);
                D2DBS.log.Write("info", "Char `" + CharName + "` kicked from gs " + Conn.GSId.ToString());
            }
            return(0);
        }
예제 #10
0
        private int HandleCharLock(ConnInfo Conn, List <byte> buf)
        {
            TGSCharLock packet = new TGSCharLock();
            int         pos    = Marshal.SizeOf(packet);

            packet = (TGSCharLock)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            string[] Names    = BytesToString(buf.GetRange(pos, buf.Count - pos)).Split('\0');
            string   CharName = Names[0];

            D2DBS.log.Write("info", "Charlock `" + CharName + "` set to " + packet.lockstatus.ToString() + " for gs " + Conn.GSId);
            if (packet.lockstatus == 0)
            {
                D2DBS.charlock.UnlockChar(CharName);
            }
            else
            {
                D2DBS.charlock.SetCharLock(CharName, Conn.GSId);
            }
            return(0);
        }
예제 #11
0
        public void KickPlayer(ConnInfo Conn, string CharName)
        {
            if (Conn.Disposed)
            {
                return;
            }
            D2DBS.log.Write("info", "Kicking `" + CharName + "`");
            TDBSKickRequest kpacket = new TDBSKickRequest();

            byte[] RAWCharName = StringToChars(CharName);
            kpacket.h.seqno = 0;
            kpacket.h.type  = (byte)EPacketType.DBSKickRequest;
            kpacket.h.size  = (short)(Marshal.SizeOf(kpacket.GetType()) + RAWCharName.Length);
            lock (Conn.StreamLocker)
            {
                Conn.NetWriter.Write(D2DBS.core.StructToBytes(kpacket));
                Conn.NetWriter.Write(RAWCharName);
                Conn.NetWriter.Flush();
            }
        }
예제 #12
0
        private int HandleSaveCharInfo(ConnInfo Conn, List <byte> buf)
        {
            TGSSaveCharInfoRequest packet = new TGSSaveCharInfoRequest();
            int pos = Marshal.SizeOf(packet);

            packet = (TGSSaveCharInfoRequest)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            string[] Names       = BytesToString(buf.GetRange(pos, buf.Count - pos - packet.datalen - 1)).Split('\0');
            string   AccountName = Names[0];
            string   CharName    = Names[1];
            string   CharVersion = D2DBS.config["char_version"];

            byte[]    data     = buf.GetRange(buf.Count - packet.datalen, packet.datalen).ToArray();
            TCharInfo CharInfo = (TCharInfo)D2DBS.core.BytesToStruct(data, typeof(TCharInfo));

            TDBSSaveDataReply rpacket = new TDBSSaveDataReply();

            byte[] rawcharname = StringToChars(CharName);
            rpacket.h.seqno  = packet.h.seqno;
            rpacket.h.type   = (byte)EPacketType.DBSSaveDataReply;
            rpacket.h.size   = (short)(Marshal.SizeOf(rpacket) + rawcharname.Length);
            rpacket.datatype = 2;
            if (D2DBS.charfile.SetCharInfo(AccountName, CharName, CharInfo) == true)
            {
                D2DBS.mysql.Execute("INSERT DELAYED INTO `charstat` (`version`, `charname`, `accname`, `charclass`, `level`, `ist`, `lastupdate`) SELECT '" + CharVersion + "', '" + CharName + "', '" + AccountName + "', '" + CharInfo.summary.charclass.ToString() + "', '" + CharInfo.summary.charlevel.ToString() + "', '0', UNIX_TIMESTAMP() FROM `charstat` WHERE NOT EXISTS (SELECT `charname` FROM `charstat` WHERE `version` = '" + CharVersion + "' `charname` = '" + CharName + "') LIMIT 1");
                D2DBS.mysql.Execute("UPDATE LOW_PRIORITY `charstat` SET `accname` = '" + AccountName + "', `charclass` = '" + CharInfo.summary.charclass.ToString() + "', `level` = '" + CharInfo.summary.charlevel.ToString() + "', `lastupdate` = UNIX_TIMESTAMP() WHERE version = '" + CharVersion + "' AND charname = '" + CharName + "'");
                rpacket.result = 0;
                D2DBS.log.Write("info", "Saved charinfo `" + CharName + "`(*" + AccountName + ") for gs " + Conn.GSId.ToString());
            }
            else
            {
                rpacket.result = 1;
                D2DBS.log.Write("info", "Failed to saved charinfo `" + CharName + "`(*" + AccountName + ") for gs " + Conn.GSId.ToString());
            }
            lock (Conn.StreamLocker)
            {
                Conn.NetWriter.Write(D2DBS.core.StructToBytes(rpacket));
                Conn.NetWriter.Write(rawcharname);
                Conn.NetWriter.Flush();
            }
            return(0);
        }
예제 #13
0
        private int HandleCloseSignal(ConnInfo Conn, List <byte> buf)
        {
            TGSCloseSignal packet = new TGSCloseSignal();
            int            pos    = Marshal.SizeOf(packet);

            packet = (TGSCloseSignal)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            string[] Names       = BytesToString(buf.GetRange(pos, buf.Count - pos)).Split('\0');
            string   GameName    = Names[0];
            string   CharVersion = D2DBS.config["char_version"];

            if (packet.ifclose == 0)
            {
                D2DBS.mysql.Execute("INSERT DELAYED INTO game (`version`, `name`,`startdate`,`enddate`) VALUES ('" + CharVersion + "', '" + D2DBS.mysql.Escape(GameName) + "', UNIX_TIMESTAMP(), '0')");
                D2DBS.log.Write("info", "Game `" + GameName + "` closed on gs " + Conn.GSId.ToString());
            }
            else
            {
                D2DBS.mysql.Execute("UPDATE LOW_PRIORITY `game` SET `enddate` = UNIX_TIMESTAMP() WHERE `version` = '" + CharVersion + " AND `name` = '" + D2DBS.mysql.Escape(GameName) + "' ORDER BY startdate DESC LIMIT 1");
                D2DBS.log.Write("info", "Game `" + GameName + "` started on gs " + Conn.GSId.ToString());
            }
            return(0);
        }
예제 #14
0
        private int HandleSOJCounterUpdate(ConnInfo Conn, List <byte> buf)
        {
            TGSSOJCounterUpdate packet = new TGSSOJCounterUpdate();
            int pos = Marshal.SizeOf(packet);

            string[] Names = BytesToString(buf.GetRange(pos, buf.Count - pos)).Split('\0');
            packet = (TGSSOJCounterUpdate)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            D2DBS.diabloClone.Increment(packet.increment, Names[0]);

            TDBSSOJCounterUpdate rpacket = new TDBSSOJCounterUpdate();

            rpacket.h.seqno     = packet.h.seqno;
            rpacket.h.type      = (byte)EPacketType.DBSSOJCounterUpdate;
            rpacket.h.size      = (short)(Marshal.SizeOf(rpacket));
            rpacket.soj_counter = D2DBS.diabloClone.Get();
            lock (Conn.StreamLocker)
            {
                Conn.NetWriter.Write(D2DBS.core.StructToBytes(rpacket));
                Conn.NetWriter.Flush();
            }
            return(0);
        }
예제 #15
0
        private int HandleGetDataRequest(ConnInfo Conn, List <byte> buf)
        {
            TGSGetDataRequest packet = new TGSGetDataRequest();
            int pos = Marshal.SizeOf(packet);

            packet = (TGSGetDataRequest)D2DBS.core.BytesToStruct(buf.ToArray(), Marshal.SizeOf(packet), packet.GetType());
            string[]  Names       = BytesToString(buf.GetRange(pos, buf.Count - pos)).Split('\0');
            string    AccountName = Names[0];
            string    CharName    = Names[1];
            TCharInfo CharInfo    = new TCharInfo();
            byte      result      = 1;

            byte[] data = null;
            if (packet.datatype == 1)
            {
                if (D2DBS.charlock.SetCharLock(CharName, Conn.GSId))
                {
                    data = D2DBS.charfile.GetCharSave(AccountName, CharName);
                    if (data == null)
                    {
                        result = 1;
                        D2DBS.log.Write("error", "Failed to load charsave `" + CharName + "`(*" + AccountName + ") for gs " + Conn.GSId.ToString());
                        D2DBS.charlock.UnlockChar(CharName);
                    }
                    else
                    {
                        result = 0;
                        D2DBS.log.Write("info", "Loaded charsave `" + CharName + "`(*" + AccountName + ") for gs " + Conn.GSId.ToString());
                    }
                }
                else
                {
                    int LockGSId = D2DBS.charlock.GetGSIdByLock(CharName);
                    result = 1;
                    D2DBS.log.Write("warn", "Char `" + CharName + "`(*" + AccountName + ") already locked on gs " + LockGSId.ToString() + " for gs " + Conn.GSId.ToString());
                    //KickPlayer(D2DBS.net.GetConnByGSId(LockGSId), CharName);
                }
            }
            else
            {
                data = D2DBS.charfile.GetCharInfoRaw(AccountName, CharName);
                D2DBS.log.Write("info", "Loaded charinfo `" + CharName + "`(*" + AccountName + ") for gs " + Conn.GSId.ToString());
            }
            if (result == 0)
            {
                byte[] RAWCharInfo = D2DBS.charfile.GetCharInfoRaw(AccountName, CharName);
                if (RAWCharInfo == null)
                {
                    D2DBS.log.Write("error", "Failed to load charinfo `" + CharName + "`(*" + AccountName + ") for gs " + Conn.GSId.ToString());
                    D2DBS.charlock.UnlockChar(CharName);
                    result = 1;
                }
                else
                {
                    CharInfo = (TCharInfo)D2DBS.core.BytesToStruct(RAWCharInfo, typeof(TCharInfo));
                }
            }
            TDBSGetDataReply rpacket = new TDBSGetDataReply();

            if (result == 0)
            {
                int ladder_time = int.Parse(D2DBS.config["ladderinit_time"]);
                if (D2DBS.charfile.GetLadder((ushort)CharInfo.summary.charstatus) == 1)
                {
                    if (CharInfo.header.create_time < ladder_time)
                    {
                        rpacket.allowladder = 0;
                        D2DBS.log.Write("info", "Char `" + CharName + "`(*" + AccountName + ") expired for ladder, converting to non-ladder");
                    }
                    else
                    {
                        rpacket.allowladder = 1;
                    }
                }
                else
                {
                    rpacket.allowladder = 0;
                }
                rpacket.charcreatetime = CharInfo.header.create_time;
                rpacket.datalen        = (short)data.Length;
            }
            else
            {
                rpacket.allowladder    = 0;
                rpacket.charcreatetime = 0;
                rpacket.datalen        = 0;
            }
            byte[] rawcharname = StringToChars(CharName);
            rpacket.h.seqno  = packet.h.seqno;
            rpacket.h.type   = (byte)EPacketType.DBSGetDataReply;
            rpacket.h.size   = (short)(Marshal.SizeOf(rpacket) + rawcharname.Length + rpacket.datalen);
            rpacket.datatype = packet.datatype;
            rpacket.result   = result;
            lock (Conn.StreamLocker)
            {
                Conn.NetWriter.Write(D2DBS.core.StructToBytes(rpacket));
                Conn.NetWriter.Write(rawcharname);
                if (rpacket.datalen > 0)
                {
                    Conn.NetWriter.Write(data);
                }
                Conn.NetWriter.Flush();
            }
            return(0);
        }
예제 #16
0
파일: DBSNet.cs 프로젝트: pvpgn/D2DBSDotNet
 private void ClientLoop(object Param)
 {
     ConnInfo Conn = new ConnInfo((TcpClient)Param);
     TcpClient Client = Conn.Client;
     string RemoteAddr = Conn.RemoteAddr;
     NetworkStream NetStream = Conn.NetStream;
     BinaryReader NetReader = Conn.NetReader;
     BinaryWriter NetWriter = Conn.NetWriter;
     try
     {
         Client.ReceiveBufferSize = 65535;
         Client.SendBufferSize = 65535;
         int ConnState = 0;
         while (Conn.Disposed == false && Client.Connected == true)
         {
             if (ConnState == 0)
             {
                 byte ConnClass = NetReader.ReadByte();
                 if (ConnClass == 0x88)
                 {
                     for (int i = 0; i < GSAddr.Count; i++)
                     {
                         if (GSAddr[i] == RemoteAddr)
                         {
                             if (GSConn.ContainsKey(i))
                             {
                                 D2DBS.log.Write("warn", "Previous D2GS connection found, dispose.");
                                 GSConn[i].Dispose();
                             }
                             if (GSConn.ContainsKey(i) == false)
                                 GSConn.Add(i, Conn);
                             else
                                 GSConn[i] = Conn;
                             ConnState = 1;
                             Conn.GSId = i;
                             D2DBS.log.Write("info", "D2GS connection from " + RemoteAddr + " accepted (GSId: " + i.ToString() + ")");
                             break;
                         }
                     }
                     if (ConnState == 0)
                     {
                         throw new Exception("D2GS connection from " + RemoteAddr + " not authorized");
                     }
                 }
                 else
                 {
                     throw new Exception("Unknown connection class 0x" + ConnClass.ToString("X"));
                 }
             }
             else
             {
                 int size;
                 while ((size = NetReader.ReadInt16()) > 0)
                 {
                     byte[] buf = new byte[size];
                     int leftsize = size;
                     int pos = 0;
                     buf[0] = (byte)(size & 0xFF);
                     buf[1] = (byte)((size >> 8) & 0xFF);
                     pos += 2;
                     leftsize -= 2;
                     while (Conn.Disposed == false && Client.Connected == true && leftsize > 0)
                     {
                         int readlen = NetReader.Read(buf, pos, leftsize);
                         leftsize -= readlen;
                         pos += readlen;
                     }
                     if (leftsize == 0)
                     {
                         List<byte> packetbuf = new List<byte>(buf);
                         int Code = D2DBS.core.DBSHandlePacket(Conn, packetbuf);
                         if (Code == -1)
                         {
                             throw new Exception("Failed to handle packet");
                         }
                     }
                     else
                     {
                         throw new Exception("Error occured while receiving packet");
                     }
                 }
             }
         }
     }
     catch (Exception e)
     {
         D2DBS.log.Write("error", "Connection from " + RemoteAddr + " closed: " + e.Message + " (GSId: " + Conn.GSId.ToString() + ")");
     }
     D2DBS.log.Write("error", "D2GS Connection from " + RemoteAddr + " closed (GSId: " + Conn.GSId.ToString() + ")");
     Conn.Dispose();
 }
예제 #17
0
        private void ClientLoop(object Param)
        {
            ConnInfo      Conn       = new ConnInfo((TcpClient)Param);
            TcpClient     Client     = Conn.Client;
            string        RemoteAddr = Conn.RemoteAddr;
            NetworkStream NetStream  = Conn.NetStream;
            BinaryReader  NetReader  = Conn.NetReader;
            BinaryWriter  NetWriter  = Conn.NetWriter;

            try
            {
                Client.ReceiveBufferSize = 65535;
                Client.SendBufferSize    = 65535;
                int ConnState = 0;
                while (Conn.Disposed == false && Client.Connected == true)
                {
                    if (ConnState == 0)
                    {
                        byte ConnClass = NetReader.ReadByte();
                        if (ConnClass == 0x88)
                        {
                            for (int i = 0; i < GSAddr.Count; i++)
                            {
                                if (GSAddr[i] == RemoteAddr)
                                {
                                    if (GSConn.ContainsKey(i))
                                    {
                                        D2DBS.log.Write("warn", "Previous D2GS connection found, dispose.");
                                        GSConn[i].Dispose();
                                    }
                                    if (GSConn.ContainsKey(i) == false)
                                    {
                                        GSConn.Add(i, Conn);
                                    }
                                    else
                                    {
                                        GSConn[i] = Conn;
                                    }
                                    ConnState = 1;
                                    Conn.GSId = i;
                                    D2DBS.log.Write("info", "D2GS connection from " + RemoteAddr + " accepted (GSId: " + i.ToString() + ")");
                                    break;
                                }
                            }
                            if (ConnState == 0)
                            {
                                throw new Exception("D2GS connection from " + RemoteAddr + " not authorized");
                            }
                        }
                        else
                        {
                            throw new Exception("Unknown connection class 0x" + ConnClass.ToString("X"));
                        }
                    }
                    else
                    {
                        int size;
                        while ((size = NetReader.ReadInt16()) > 0)
                        {
                            byte[] buf      = new byte[size];
                            int    leftsize = size;
                            int    pos      = 0;
                            buf[0]    = (byte)(size & 0xFF);
                            buf[1]    = (byte)((size >> 8) & 0xFF);
                            pos      += 2;
                            leftsize -= 2;
                            while (Conn.Disposed == false && Client.Connected == true && leftsize > 0)
                            {
                                int readlen = NetReader.Read(buf, pos, leftsize);
                                leftsize -= readlen;
                                pos      += readlen;
                            }
                            if (leftsize == 0)
                            {
                                List <byte> packetbuf = new List <byte>(buf);
                                int         Code      = D2DBS.core.DBSHandlePacket(Conn, packetbuf);
                                if (Code == -1)
                                {
                                    throw new Exception("Failed to handle packet");
                                }
                            }
                            else
                            {
                                throw new Exception("Error occured while receiving packet");
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                D2DBS.log.Write("error", "Connection from " + RemoteAddr + " closed: " + e.Message + " (GSId: " + Conn.GSId.ToString() + ")");
            }
            D2DBS.log.Write("error", "D2GS Connection from " + RemoteAddr + " closed (GSId: " + Conn.GSId.ToString() + ")");
            Conn.Dispose();
        }