/// <summary>
        /// Packet Type: 1052. This packet is sent as a response to the account server's authentication reply to
        /// complete the authentication process. This packet contains the client's identification data and the client's
        /// region and patch number. The client should be authenticated by the message server and connected with the
        /// map server.
        /// </summary>
        /// <param name="pClient">The client requesting access to the server.</param>
        /// <param name="pMsg">The authentication packet requesting processing.</param>
        public static void HandleConnect(Client pClient, MsgConnect pMsg)
        {
            if (pClient.Identity == 0)                // not authenticated
            {
                if (ServerKernel.LoginServer == null) // if login server is down, no login allowed
                {
                    pClient.Disconnect();
                    return;
                }

                // Decrypt important client data from the Account Server:
                var pCipher    = new PhoenixTransferCipher(ServerKernel.TransferKey, ServerKernel.TransferSalt, pClient.IpAddress);
                var pDecrypted = pCipher.Decrypt(new[] { pMsg.Identity, pMsg.Authentication });

                // let's check if the player has really requested the login into the account server
                LoginRequest pRequest;
                if (ServerKernel.LoginQueue.TryRemove(pDecrypted[0], out pRequest))
                {
                    // user found
                    if (!pRequest.IsValid(pDecrypted[0], pDecrypted[1], pClient.IpAddress))
                    {
                        // something is not right, disconnect.
                        pClient.Disconnect();
                        return;
                    }
                }
                else
                {
                    Client trash;
                    if (!ServerKernel.CharacterCreation.TryRemove(pDecrypted[0], out trash))
                    {
                        // user did not request a login token on the account server
                        pClient.Disconnect();
                        return;
                    }
                }

                // Assign authentication data to the client:
                pClient.AccountIdentity = pMsg.Identity = pDecrypted[0];
                pClient.Language        = pMsg.Language;
                //pClient.VipLevel = pRequest.VipLevel;
                //pClient.Authority = pRequest.Authority;


                InitializeCharacter(pClient, pMsg);
            }
            else
            {
                InitializeCharacter(pClient, pMsg);
            }
        }
예제 #2
0
파일: NatResolver.cs 프로젝트: jimu/ZunTzu
        private static unsafe void notificationLoop(object natTraversalSession)
        {
            NatTraversalSession session = (NatTraversalSession)natTraversalSession;
            Timer keepAliveTimer        = null;

            try {
                IPEndPoint serviceEndPoint = null;

                // connect to service to open a port on the NAT devices
                using (Socket notificationSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) {
                    notificationSocket.Connect(natTraversalServiceUrl, natTraversalServicePort);
                    serviceEndPoint       = (IPEndPoint)notificationSocket.RemoteEndPoint;
                    session.LocalEndPoint = (IPEndPoint)notificationSocket.LocalEndPoint;
                }

                // create a new socket in listening mode using the port just opened
                using (Socket notificationSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) {
                    notificationSocket.ReceiveTimeout = 1000;
                    notificationSocket.Bind(session.LocalEndPoint);

                    // send "open notification channel" message
                    {
                        MsgOpenNotificationChannel msg = new MsgOpenNotificationChannel(session.SessionId);
                        byte[] datagram = new byte[sizeof(MsgOpenNotificationChannel)];
                        for (int i = 0; i < datagram.Length; ++i)
                        {
                            datagram[i] = ((byte *)&msg)[i];
                        }
                        notificationSocket.SendTo(datagram, serviceEndPoint);
                    }

                    while (true)
                    {
                        // block until a message is received or 1 second has elapsed
                        EndPoint   any                 = new IPEndPoint(IPAddress.Any, 0);
                        byte[]     bytesReceived       = new byte[1024];
                        int        bytesReceivedLength = notificationSocket.ReceiveFrom(bytesReceived, ref any);
                        IPEndPoint remoteEndPoint      = (IPEndPoint)any;

                        // test for stop condition: a message send from this local endpoint to itself
                        if (remoteEndPoint.Equals(session.LocalEndPoint))
                        {
                            break;
                        }
                        else if (remoteEndPoint.Equals(serviceEndPoint))
                        {
                            // handle the message
                            if (bytesReceivedLength >= 3 && bytesReceived[0] == 'z' && bytesReceived[1] == 't')
                            {
                                switch (bytesReceived[2])
                                {
                                case (byte)MessageType.AckOpenNotificationChannel:
                                    if (bytesReceivedLength == sizeof(MsgAckOpenNotificationChannel))
                                    {
                                        MsgAckOpenNotificationChannel msg = new MsgAckOpenNotificationChannel();
                                        for (int i = 0; i < sizeof(MsgAckOpenNotificationChannel); ++i)
                                        {
                                            ((byte *)&msg)[i] = bytesReceived[i];
                                        }

                                        // handle MsgAckOpenNotificationChannel
                                        // send "host" message, from the same port as DirectPlay (spoofed)
                                        IPEndPoint spoofedEndPoint = new IPEndPoint(session.LocalEndPoint.Address, session.PrivatePort);
                                        MsgHost    msgHost         = new MsgHost(session.SessionId, session.LocalEndPoint.Address, (ushort)session.PrivatePort);
                                        byte[]     datagram        = new byte[sizeof(MsgHost)];
                                        for (int i = 0; i < datagram.Length; ++i)
                                        {
                                            datagram[i] = ((byte *)&msgHost)[i];
                                        }
                                        PortSpoofing.Send(spoofedEndPoint, serviceEndPoint, datagram);
                                    }
                                    break;

                                case (byte)MessageType.AckHost:
                                    if (bytesReceivedLength == sizeof(MsgAckHost))
                                    {
                                        if (keepAliveTimer == null)                                                     // ignore if already handled
                                        {
                                            MsgAckHost msg = new MsgAckHost();
                                            for (int i = 0; i < sizeof(MsgAckHost); ++i)
                                            {
                                                ((byte *)&msg)[i] = bytesReceived[i];
                                            }

                                            // handle MsgAckHost
                                            // record public address/port
                                            session.PublicIpAddress = new IPAddress((uint)IPAddress.HostToNetworkOrder((int)msg.HostPublicIp)).ToString();
                                            session.PublicPort      = msg.HostPublicPort;

                                            // notify main thread that NAT traversal is enabled
                                            session.Enabled = true;
                                            if (session.NatTraversalEnabled != null)
                                            {
                                                session.NatTraversalEnabled.Set();
                                            }

                                            // set reception so it can't time-out
                                            notificationSocket.ReceiveTimeout = 0;

                                            // send a keep alive message every 19 seconds
                                            KeepAliveSettings settings = new KeepAliveSettings();
                                            settings.SpoofedLocalEndPoint = session.LocalEndPoint;
                                            settings.ServiceEndPoint      = serviceEndPoint;
                                            MsgKeepAlive msgKeepAlive = new MsgKeepAlive(session.SessionId);
                                            settings.Datagram = new byte[sizeof(MsgKeepAlive)];
                                            for (int i = 0; i < settings.Datagram.Length; ++i)
                                            {
                                                settings.Datagram[i] = ((byte *)&msgKeepAlive)[i];
                                            }

                                            keepAliveTimer = new Timer(new TimerCallback(keepAlive), settings, 19000, 19000);
                                        }
                                    }
                                    break;

                                case (byte)MessageType.Connect:
                                    if (bytesReceivedLength == sizeof(MsgConnect))
                                    {
                                        MsgConnect msg = new MsgConnect();
                                        for (int i = 0; i < sizeof(MsgConnect); ++i)
                                        {
                                            ((byte *)&msg)[i] = bytesReceived[i];
                                        }

                                        // handle MsgConnect
                                        // punch hole targeting client's public and private addresses
                                        IPAddress publicClientAddress  = new IPAddress((uint)IPAddress.HostToNetworkOrder((int)msg.ClientPublicIp));
                                        IPAddress privateClientAddress = new IPAddress((uint)IPAddress.HostToNetworkOrder((int)msg.ClientPrivateIp));

                                        IPEndPoint spoofedEndPoint = new IPEndPoint(session.LocalEndPoint.Address, session.PrivatePort);
                                        byte[]     emptyDatagram   = new byte[0];

                                        PortSpoofing.Send(spoofedEndPoint, new IPEndPoint(publicClientAddress, msg.ClientPublicPort), emptyDatagram);
                                        PortSpoofing.Send(spoofedEndPoint, new IPEndPoint(privateClientAddress, msg.ClientPrivatePort), emptyDatagram);

                                        // send acknowledgement through notification channel
                                        MsgAckConnect msgAckConnect = new MsgAckConnect(session.SessionId, publicClientAddress, msg.ClientPublicPort);
                                        byte[]        datagram      = new byte[sizeof(MsgAckConnect)];
                                        for (int i = 0; i < datagram.Length; ++i)
                                        {
                                            datagram[i] = ((byte *)&msgAckConnect)[i];
                                        }
                                        notificationSocket.SendTo(datagram, serviceEndPoint);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            } catch {
                if (!session.Enabled && session.NatTraversalEnabled != null)
                {
                    session.NatTraversalEnabled.Set();
                }
            } finally {
                if (keepAliveTimer != null)
                {
                    keepAliveTimer.Change(Timeout.Infinite, Timeout.Infinite);
                    keepAliveTimer.Dispose();
                }
            }
        }
예제 #3
0
        public static ClientBasePacket HandlePacket(byte[] data, int offset, GameSession client)
        {
            // Calculate message size
            var size = (short)((data[offset + 1] << 8) + data[offset]);

            // Copy the packet to a new byte array
            // Skipping the header
            var packet = new byte[size];

            Array.Copy(data, offset, packet, 0, size);

            ClientBasePacket msg;

            // Get the id
            var id = packet[2];

            // Handle the packet
            // TODO: Can we group these into login / game / etc?
            switch (id)
            {
            case 0x00:
                msg = new ProtocolVersion(packet, client);
                break;

            case 0x01:
                msg = new ValidateClient(packet, client);
                break;

            case 0x03:
                msg = new ConnectClient(packet, client);
                break;

            case 0x04:
                msg = new ConnectSwitch(packet, client);
                break;

            case 0x05:
                msg = new SwitchServer(packet, client);
                break;

            case 0x06:
                msg = new ServerTime(packet, client);
                break;

            case 0x07:
                msg = new Message(packet, client);
                break;

            case 0x0d:
                msg = new Log(packet, client);
                break;

            case 0x0c:
                msg = new SyncMoney(packet, client);
                break;

            case 0x11:
                msg = new FactoryModifyUnit(packet, client);
                break;

            case 0x12:
                msg = new FactoryModifyEnd(packet, client);
                break;

            case 0x16:
                msg = new IsValidName(packet, client);
                break;

            case 0x17:
                msg = new FactoryChangeUnitName(packet, client);
                break;

            case 0x18:
                msg = new RequestInventory(packet, client);
                break;

            case 0x19:
                msg = new RequestSearchGame(packet, client);
                break;

            case 0x1b:
                msg = new CreateGame(packet, client);
                break;

            case 0x1c:
                msg = new EnterGame(packet, client);
                break;

            case 0x1f:
                msg = new ListUser(packet, client);
                break;

            case 0x20:
                msg = new Ready(packet, client);
                break;

            case 0x21:
                msg = new Exit(packet, client);
                break;

            case 0x22:
                msg = new StartGame(packet, client);
                break;

            case 0x2b:
                msg = new SelectBase(packet, client);
                break;

            case 0x2c:
                msg = new ReadyGame(packet, client);
                break;

            case 0x2e:
                msg = new RequestPalette(packet, client);
                break;

            case 0x2f:
                msg = new MoveUnit(packet, client);
                break;

            case 0x30:
                msg = new AimUnit(packet, client);
                break;

            case 0x31:
                msg = new StartAttack(packet, client);
                break;

            case 0x32:
                msg = new StopAttack(packet, client);
                break;

            case 0x35:
                msg = new RequestRegain(packet, client);
                break;

            case 0x38:
                msg = new ModeSniper(packet, client);
                break;

            case 0x3a:
                msg = new RequestChangeWeaponset(packet, client);
                break;

            case 0x3b:
                msg = new RequestQuitBattle(packet, client);
                break;

            case 0x3f:
                msg = new BuyList(packet, client);
                break;

            case 0x40:
                msg = new RequestGoodsData(packet, client);
                break;

            case 0x46:
                msg = new RequestAvatarInfo(packet, client);
                break;

            case 0x47:
            case 0x48:
            case 0x49:
            case 0x4a:
            case 0x4b:
            case 0x4c:
            case 0x4d:
                msg = new RequestStatsInfo(packet, client);
                break;

            case 0x4e:
                msg = new RequestBestInfo(packet, client);
                break;

            case 0x57:
                msg = new TutorialSelect(packet, client);
                break;

            case 0x5a:
                msg = new UnAimUnit(packet, client);
                break;

            case 0x63:
                msg = new MsgConnect(packet, client);
                break;

            case 0x64:
                msg = new MsgUserStateInfo(packet, client);
                break;

            case 0x66:
                msg = new MsgUserClanInfo(packet, client);
                break;

            case 0x67:
                msg = new MsgGetBuddyList(packet, client);
                break;

            case 0x69:
                msg = new MsgGetChannelList(packet, client);
                break;

            case 0x6a:
                msg = new MsgJoinChannel(packet, client);
                break;

            case 0x6b:
                msg = new MsgLeaveChannel(packet, client);
                break;

            case 0x6c:
                msg = new MsgChannelChatting(packet, client);
                break;

            case 0x71:
                msg = new RequestOperator(packet, client);
                break;

            case 0x72:
                msg = new SelectOperator(packet, client);
                break;

            default:
                msg = new UnknownPacket(packet, client);
                //Console.WriteLine("Unknown packet id [{0}] from user {1}", id, client.GetUserName());
                break;
            }

            return(msg);
        }
예제 #4
0
 public void HandleAuthenticationComplete(Client pClient, byte[] pBuffer)
 {
     MsgConnect pMsg = new MsgConnect(pBuffer);
 }
        /// <summary>
        /// This function is called once the client has been authenticated. If the character for the client
        /// does not exist in the database, then this function will open the character creation screen; else,
        /// it will load character data and send the client information needed to log into the world. It will
        /// also connect the player to the map server.
        /// </summary>
        /// <param name="pClient">The client being processed.</param>
        /// <param name="pPacket">The authentication packet to be sent to the map server.</param>
        private static void InitializeCharacter(Client pClient, MsgConnect pPacket, bool bCreate = false)
        {
            // check if the server is full
            if (ServerKernel.Players.Count >= ServerKernel.MaxOnlinePlayer)
            {
                pClient.Send(ServerMessages.Login.ServerFull);
                pClient.Disconnect();
                return;
            }

            DbAccount pAccount = new AccountRepository().SearchByIdentity(pClient.AccountIdentity);
            DbUser    pUser    = new CharacterRepository().SearchByAccount(pClient.AccountIdentity);

            if (pAccount != null && pUser != null)
            {
                if (pUser.Life <= 0)
                {
                    pUser.Life = 1;
                }

                pClient.VipLevel        = pAccount.Vip;
                pClient.Identity        = pUser.Identity;
                pClient.AccountIdentity = pAccount.Identity;

                if (CheckGamePool(pClient, pClient.Identity) &&
                    ServerKernel.Players.TryAdd(pClient.Identity, pClient))
                {
                    // The client is ready and authorized for login. Prepare the client for the game world: load
                    // spawn information and send it to the map server, and initialize game structures necessary
                    // to log into the server.
                    if (!bCreate)
                    {
                        pClient.Send(ServerMessages.Login.AnswerOk);
                    }

                    pClient.Send(new MsgUserIpInfo());
                    pClient.Send(new MsgServerInfo()
                    {
                        ClassicMode = 0, PotencyMode = 0
                    });

                    if (pUser.Lookface < 10000)
                    {
                        ushort body     = (ushort)(pUser.Lookface % 10000);
                        uint   lookface = 0;
                        if (body == (ushort)BodyType.THIN_MALE || body == (ushort)BodyType.HEAVY_MALE)
                        {
                            if ((pUser.Profession / 10) == 5)
                            {
                                lookface = (uint)(new Random().Next(103, 107));
                            }
                            else if ((pUser.Profession / 10) == 6)
                            {
                                lookface = (uint)(new Random().Next(109, 113));
                            }
                            else
                            {
                                lookface = (uint)(new Random().Next(1, 102));
                            }
                        }
                        else
                        {
                            if ((pUser.Profession / 10) == 5)
                            {
                                lookface = (uint)(new Random().Next(291, 295));
                            }
                            else if ((pUser.Profession / 10) == 6)
                            {
                                lookface = (uint)(new Random().Next(300, 304));
                            }
                            else
                            {
                                lookface = (uint)(new Random().Next(201, 290));
                            }
                        }
                        pUser.Lookface = lookface * 10000 + pUser.Lookface;
                    }

                    var pInfo = new MsgUserInfo(pUser.Name, string.Empty, pUser.Mate)
                    {
                        Agility            = pUser.Agility,
                        AncestorProfession = (byte)pUser.FirstProfession,
                        Attributes         = pUser.AdditionalPoints,
                        BoundEmoney        = pUser.BoundEmoney,
                        ConquerPoints      = pUser.Emoney,
                        Enlighten          = pUser.EnlightPoints,
                        EnlightenExp       = 0,
                        Experience         = pUser.Experience,
                        Hairstyle          = pUser.Hair,
                        Health             = pUser.Life,
                        Mana               = pUser.Mana,
                        Identity           = pUser.Identity,
                        Level              = pUser.Level,
                        Mesh               = pUser.Lookface,
                        Vitality           = pUser.Vitality,
                        Spirit             = pUser.Spirit,
                        Metempsychosis     = pUser.Metempsychosis,
                        Strength           = pUser.Strength,
                        QuizPoints         = pUser.StudentPoints,
                        Silver             = pUser.Money,
                        PreviousProfession = (byte)pUser.LastProfession,
                        Profession         = (byte)pUser.Profession,
                        PlayerTitle        = pUser.SelectedTitle,
                        PkPoints           = pUser.PkPoints
                    };

                    pClient.Character = new Character(pInfo, pUser, pClient);

                    pClient.Send(pInfo);
                    pClient.Send(new MsgData());
                    pClient.Screen = new Screen(pClient.Character);

                    if (ServerKernel.Players.Count > ServerKernel.OnlineRecord)
                    {
                        ServerKernel.OnlineRecord = (ushort)ServerKernel.Players.Count;
                    }

                    ServerKernel.Log.SaveLog(string.Format("User [{0}] has logged in.", pClient.Character.Name), true, LogType.MESSAGE);
                    ServerKernel.LoginServer.Send(new MsgLoginSvPlayerAmount((ushort)ServerKernel.Players.Count, LoginPlayerAmountRequest.REPLY_ONLINE_AMOUNT));

                    pUser.LastLogin = (uint)UnixTimestamp.Timestamp();
                    Database.Characters.SaveOrUpdate(pUser);
                }
            }
            else if (pAccount != null &&
                     CheckGamePool(pClient, 0) &&
                     ServerKernel.CharacterCreation.TryAdd(pClient.AccountIdentity, pClient))
            {
                pClient.Send(ServerMessages.Login.NewRole);
            }
            else
            {
                pClient.Send(ServerMessages.Login.TransferFailed);
                pClient.Disconnect();
            }
        }