Example #1
0
        public async Task DispatchPacket(LoginStart packet)
        {
            if (_useAuthentication)
            {
                throw new NotImplementedException();
            }
            else
            {
                var user = await GrainFactory.GetGrain <INonAuthenticatedUser>(packet.Name).GetUser();

                if (await user.GetProtocolVersion() > MineCase.Protocol.Protocol.Version)
                {
                    await SendLoginDisconnect("{\"text\":\"Outdated server!I'm still on 1.12\"}");
                }
                else if (await user.GetProtocolVersion() < MineCase.Protocol.Protocol.Version)
                {
                    await SendLoginDisconnect("{\"text\":\"Outdated client!Please use 1.12\"}");
                }
                else
                {
                    var uuid = user.GetPrimaryKey();
                    await SendLoginSuccess(packet.Name, uuid);

                    await user.SetClientPacketSink(GrainFactory.GetGrain <IClientboundPacketSink>(this.GetPrimaryKey()));

                    await GrainFactory.GetGrain <IPacketRouter>(this.GetPrimaryKey()).BindToUser(user);

                    var world = await user.GetWorld();

                    var game = GrainFactory.GetGrain <IGameSession>(world.GetPrimaryKeyString());
                    await game.JoinGame(user);
                }
            }
        }
Example #2
0
        private Task DispatchLoginPackets(UncompressedPacket packet)
        {
            var  br = new SpanReader(packet.Data);
            Task task;

            switch (packet.PacketId)
            {
            // Login Start
            case 0x00:
                task = DispatchPacket(LoginStart.Deserialize(ref br));
                break;

            // Encryption Response
            case 0x01:
                task = DispatchPacket(EncryptionResponse.Deserialize(ref br));
                break;

            default:
                throw new InvalidDataException($"Unrecognizable packet id: 0x{packet.PacketId:X2}.");
            }

            if (!br.IsCosumed)
            {
                throw new InvalidDataException($"Packet data is not fully consumed.");
            }
            return(task);
        }
Example #3
0
        private async Task DispatchPacket(LoginStart packet)
        {
            _userName = packet.Name;
            var user = GrainFactory.GetGrain <INonAuthenticatedUser>(packet.Name);
            await user.SetProtocolVersion(_protocolVersion);

            var requestGrain = GrainFactory.GetGrain <ILoginFlow>(this.GetPrimaryKey());

            requestGrain.DispatchPacket(packet).Ignore();
        }
Example #4
0
        public static void Invoke(ClientConnection client)
        {
            client.RegisterPacketHandler(typeof(StatusResponse), (connection, packet) =>
            {
                Debug.Log("Handler");
                var login = new LoginStart(connection.Session.SelectedProfile.Name);
                connection.SendPacket(login);
            });

            client.RegisterPacketHandler(typeof(KeepAlive), (connection, packet) =>
            {
                if (packet is KeepAlive sender)
                {
                    Debug.Log("Bip bop");

                    connection.SendPacket(sender);
                }
            });
        }
        public void Connect(string address, int port)
        {
            Connection = new TcpClient();
            Connection.Connect(address, port);
            NetworkStream       = Connection.GetStream();
            NetworkManager      = new NetworkManager(NetworkStream);
            NetworkingReset     = new ManualResetEvent(true);
            NetworkWorkerThread = new Thread(NetworkWorker);
            NetworkWorkerThread.Start();
            var handshake = new Handshaking(NetworkManager.Protocol, address, (ushort)port, NetworkState.Login);

            SendPacket(handshake);
            //var queue = new StatusRequest();
            //SendPacket(queue);
            var login = new LoginStart(Session.SelectedProfile.Name);

            SendPacket(login);

            Debug.Log("Hello");
        }
Example #6
0
        private object DeserializeLoginPacket(UncompressedPacket packet)
        {
            var    br = new SpanReader(packet.Data);
            object innerPacket;

            switch (packet.PacketId)
            {
            // Login Start
            case 0x00:
                innerPacket = LoginStart.Deserialize(ref br);
                break;

            default:
                throw new InvalidDataException($"Unrecognizable packet id: 0x{packet.PacketId:X2}.");
            }

            if (!br.IsCosumed)
            {
                throw new InvalidDataException($"Packet data is not fully consumed.");
            }
            return(innerPacket);
        }
        private object DeserializeLoginPacket(ref UncompressedPacket packet)
        {
            using (var br = new BinaryReader(new MemoryStream(packet.Data)))
            {
                object innerPacket;
                switch (packet.PacketId)
                {
                // Login Start
                case 0x00:
                    innerPacket = LoginStart.Deserialize(br);
                    break;

                default:
                    throw new InvalidDataException($"Unrecognizable packet id: 0x{packet.PacketId:X}.");
                }

                if (br.BaseStream.Position != br.BaseStream.Length)
                {
                    throw new InvalidDataException($"Packet data is not fully consumed.");
                }
                return(innerPacket);
            }
        }
Example #8
0
        public async Task DispatchPacket(LoginStart packet)
        {
            var settingsGrain = GrainFactory.GetGrain <IServerSettings>(0);
            var settings      = await settingsGrain.GetSettings();

            if (settings.OnlineMode)
            {
                // TODO auth and compression
                var user = GrainFactory.GetGrain <INonAuthenticatedUser>(packet.Name);

                if (await user.GetProtocolVersion() > MineCase.Protocol.Protocol.Version)
                {
                    await SendLoginDisconnect($"{{\"text\":\"Outdated server!I'm still on {Protocol.Protocol.VersionName}\"}}");
                }
                else if (await user.GetProtocolVersion() < MineCase.Protocol.Protocol.Version)
                {
                    await SendLoginDisconnect($"{{\"text\":\"Outdated client!Please use {Protocol.Protocol.VersionName}\"}}");
                }
                else
                {
                    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                    Random verifyRandom          = new Random();
                    Byte[] verifyToken           = new byte[64];

                    verifyRandom.NextBytes(verifyToken);
                    var keys = rsa.ExportParameters(false);

                    await SendEncryptionRequest("", keys.Exponent, verifyToken);
                }
            }
            else
            {
                var nonAuthenticatedUser = GrainFactory.GetGrain <INonAuthenticatedUser>(packet.Name);

                if (await nonAuthenticatedUser.GetProtocolVersion() > MineCase.Protocol.Protocol.Version)
                {
                    await SendLoginDisconnect($"{{\"text\":\"Outdated server!I'm still on {Protocol.Protocol.VersionName}\"}}");
                }
                else if (await nonAuthenticatedUser.GetProtocolVersion() < MineCase.Protocol.Protocol.Version)
                {
                    await SendLoginDisconnect($"{{\"text\":\"Outdated client!Please use {Protocol.Protocol.VersionName}\"}}");
                }
                else
                {
                    // TODO refuse him if server is full
                    var user = await nonAuthenticatedUser.GetUser();

                    var world = await user.GetWorld();

                    var gameSession = GrainFactory.GetGrain <IGameSession>(world.GetPrimaryKeyString());

                    await SendSetCompression();

                    var uuid = user.GetPrimaryKey();
                    await SendLoginSuccess(packet.Name, uuid);

                    await user.SetClientPacketSink(GrainFactory.GetGrain <IClientboundPacketSink>(this.GetPrimaryKey()));

                    var packetRouter = GrainFactory.GetGrain <IPacketRouter>(this.GetPrimaryKey());
                    await user.SetPacketRouter(packetRouter);

                    await packetRouter.BindToUser(user);

                    var game = GrainFactory.GetGrain <IGameSession>(world.GetPrimaryKeyString());
                    await game.JoinGame(user);
                }
            }
        }
        /// <summary>
        /// Return false if disconnect/finished
        /// </summary>
        void RunClientHandshake()
        {
            clientThread.WatchdogTick = DateTime.Now;

            //Read Handshake
            var hs = PacketReader.ReadFirstPackage(clientStream);

            if (hs == null)
            {
                //Old status packet
                LegacyStatus.SendStatus(clientStream);
                Phase = Phases.FinalClose;
                return;
            }
            var h = new Handshake(hs);

            Debug.FromClient(this, h);
            clientThread.State = "Handshake Received " + h;
            ClientVersion      = h.Version;
            if (h.State == HandshakeState.Status)
            {
                RunStatusPing(h);
                return;
            }
            if (h.State == HandshakeState.None)
            {
                Close("Invalid handshake state: " + h.State);
                return;
            }
            if (h.State != HandshakeState.Login)
            {
                Close("Invalid handshake state: " + h.State);
                return;
            }
            #if DEBUG
            if (h.Version >= ProtocolVersion.next)
            {
                throw new InvalidDataException("new version: " + h.Version);
            }
            #endif
            if (h.Version > MinecraftServer.BackendVersion)
            {
                clientThread.State = "Handshake too high version";
                Close("We are still running " + MinecraftServer.BackendVersion.ToText() + " we are so very sorry about that");
                return;
            }
            if (h.Version < MinecraftServer.FrontendVersion)
            {
                clientThread.State = "Handshake too low version";
                Close("Upgrade your client to " + MinecraftServer.FrontendVersion.ToText());
                return;
            }

            //Login
            var l = new LoginStart(PacketReader.ReadHandshake(clientStream));

            clientThread.State = "LoginStart Received " + l.Name;
            unverifiedUsername = l.Name;
            #if DEBUGx
            var names = new string[] { "travelcraft2012", "nuxas", "drjanitor" };
            unverifiedUsername = names[logincount++ % names.Length];
            #endif
            if (unverifiedUsername.Length == 0 || unverifiedUsername.Length > 16)
            {
                clientThread.State = "Handshake wrong username length";
                Close("Bad username");
                Console.WriteLine("Wrong username length: " + unverifiedUsername.Length);
                return;
            }

            //Set Compression
            var compression = new SetCompression();
            SendToClientInternal(compression);
            maxUncompressed = compression.MaxSize;

            //Send encryption request
            clientThread.State = "Handshake: Sending encryption request";
            //Initiate ID
            var r = new Random();
            ID = new byte[8];
            r.NextBytes(ID);
            SendToClientInternal(new EncryptionRequest(Authentication.McHex(ID), MinecraftServer.RsaBytes));
            clientThread.State = "Handshake: Sent encryption request, reading response";

            //Read enc response
            int erSize;
            var erBuffer = PacketReader.Read(clientStream, out erSize);
            if (erSize != 0)
            {
                erBuffer = Compression.Decompress(erBuffer, erSize);
            }
            var er = new EncryptionResponse(erBuffer);

            clientThread.State = "Handshake: Got enc resp";
            CryptoMC cryptoStream = new CryptoMC(clientStream, er);

            //Verify user
            clientThread.WatchdogTick = DateTime.Now;

            clientThread.State = "Handshake: loading proxy data";
            Settings           = LoadProxyPlayer(unverifiedUsername);

            if (IPAddress.IsLoopback(RemoteEndPoint.Address))
            {
                MinecraftUsername = unverifiedUsername;
                Log.WritePlayer(this, "Succesful login from (local) " + RemoteEndPoint);
            }
            else
            {
                clientThread.State = "Handshake: Verifying login credentials";
                string error = Authentication.VerifyUserLogin(unverifiedUsername, cryptoStream.SharedKey, ID);
                if (error != null)
                {
                    //Unauthorized
                    Log.WriteAuthFail(unverifiedUsername, RemoteEndPoint, error);
                    Close("Mojang says " + error);
                    return;
                }
                else
                {
                    MinecraftUsername = unverifiedUsername;
                    Log.WritePlayer(this, "Login from " + RemoteEndPoint + " " + Country);
                }
            }
            clientThread.State = "Handshake: Logged in";

            //Get UUID
            try
            {
                Settings.UUID = UsernameUUID.GetUUID(MinecraftUsername);
                //Saved further down
                Debug.WriteLine("Real UUID for " + MinecraftUsername + " is " + Settings.UUID);
            }
            catch (Exception)
            {
                Debug.WriteLine("Failed to get UUID for MinecraftName " + MinecraftUsername);
            }

            clientThread.WatchdogTick = DateTime.Now;

            MineProxy.Inbox.Status(this);

            //start encryption
            clientStream = cryptoStream;

            SendToClientInternal(new LoginSuccess(Settings.UUID, MinecraftUsername));

            clientThread.User  = MinecraftUsername;
            clientThread.State = "Logged in";

            EntityID = freeEID;

            //Math.Abs(unverifiedUsername.GetHashCode());
            freeEID += 5000;

            //Login reply to client
            JoinGame lr = new JoinGame();
            lr.ClientVersion = 0;
            lr.Difficulty    = 0;
            lr.Dimension     = 0;
            lr.EntityID      = EntityID;
            lr.MaxPlayers    = (byte)MinecraftServer.PlayerListSlots;
            lr.GameMode      = 0;
            SendToClient(lr);

            Phase = Phases.Gaming;
            Queue = new SendQueue(this);

            PlayerList.LoginPlayer(this);

            SaveProxyPlayer();

            string name = h.Host.ToLowerInvariant().Split('.')[0];
            if (name == "con")
            {
                SetWorld(World.Construct);
            }
            else
            {
                SetWorld(World.Main);
            }
            //Handshake complete
        }
Example #10
0
 private void btnLogin_Click(object sender, EventArgs e)
 {
     LoginStart?.Invoke(sender, e);
 }
Example #11
0
        /// <summary>
        /// Return false if disconnect/finished
        /// </summary>
        void RunClientHandshake()
        {
            clientThread.WatchdogTick = DateTime.Now;

            //Read Handshake
            var hs = PacketReader.ReadFirstPackage(clientStream);

            if (hs == null)
            {
                //Old status packet
                LegacyStatus.SendStatus(clientStream);
                Phase = Phases.FinalClose;
                return;
            }
            var h = new Handshake(hs);

            Debug.FromClient(this, h);
            clientThread.State = "Handshake Received " + h;
            ClientVersion      = h.Version;
            if (h.State == HandshakeState.Status)
            {
                RunStatusPing(h);
                return;
            }
            if (h.State == HandshakeState.None)
            {
                Close("Invalid handshake state: " + h.State);
                return;
            }
            if (h.State != HandshakeState.Login)
            {
                Close("Invalid handshake state: " + h.State);
                return;
            }

            #if DEBUG
            if (h.Version >= ProtocolVersion.next)
            {
                throw new InvalidDataException("new version: " + h.Version);
            }
            #endif
            if (h.Version > MinecraftServer.BackendVersion)
            {
                clientThread.State = "Handshake too high version";
                Close("We are still running " + MinecraftServer.BackendVersion.ToText() + " we are so very sorry about that");
                return;
            }
            if (h.Version < MinecraftServer.FrontendVersion)
            {
                clientThread.State = "Handshake too low version";
                Close("Upgrade your client to " + MinecraftServer.FrontendVersion.ToText());
                return;
            }

            clientThread.WatchdogTick = DateTime.Now;

            //Login
            var l = new LoginStart(PacketReader.ReadHandshake(clientStream));
            Debug.FromClient(this, l);

            clientThread.State = "LoginStart Received " + l.Name;
            unverifiedUsername = l.Name;
            if (unverifiedUsername.Length == 0 || unverifiedUsername.Length > 16)
            {
                clientThread.State = "Handshake wrong username length";
                Close("Bad username");
                Console.WriteLine("Wrong username length: " + unverifiedUsername.Length);
                return;
            }

            //Set Compression
            var compression = new SetCompression();
            SendToClientInternal(compression);
            maxUncompressed = compression.MaxSize;

            //Send encryption request
            clientThread.State = "Handshake: Sending encryption request";
            //Initiate ID
            var r = new Random();
            ID = new byte[8];
            r.NextBytes(ID);
            SendToClientInternal(new EncryptionRequest(Authentication.McHex(ID), MinecraftServer.RsaBytes));
            clientThread.State = "Handshake: Sent encryption request, reading response";

            //Read enc response
            int erSize;
            var erBuffer = PacketReader.Read(clientStream, out erSize);
            if (erSize != 0)
            {
                erBuffer = Compression.Decompress(erBuffer, erSize);
            }
            var er = new EncryptionResponse(erBuffer);
            Debug.FromClient(this, er);

            clientThread.State = "Handshake: Got enc resp";
            CryptoMC cryptoStream = new CryptoMC(clientStream, er);

            //Verify user
            clientThread.State = "Handshake: loading proxy data";
            Settings           = LoadProxyPlayer(unverifiedUsername);

            clientThread.State = "Handshake: Verifying login credentials";
            var auth = Authentication.VerifyUserLogin(unverifiedUsername, cryptoStream.SharedKey, ID);
            #warning From here we now need to take care of the id in the response.
            if (auth == null)
            {
                //Unauthorized
                Log.WriteAuthFail(unverifiedUsername, RemoteEndPoint, "");
                Close("Mojang says no");
                return;
            }
            else
            {
                MinecraftUsername = unverifiedUsername;
                Log.WritePlayer(this, "Login from " + RemoteEndPoint + " " + Country);
            }
            clientThread.State = "Handshake: Logged in";

            //Get UUID
            Settings.UUID = auth.id;

            clientThread.WatchdogTick = DateTime.Now;

            MineProxy.Inbox.Status(this);

            //start encryption
            clientStream = cryptoStream;

            SendToClientInternal(new LoginSuccess(Settings.UUID, MinecraftUsername));

            clientThread.User  = MinecraftUsername;
            clientThread.State = "Logged in";

            EntityID = freeEID;

            //Math.Abs(unverifiedUsername.GetHashCode());
            freeEID += 5000;

            //Login reply to client
            //No longer, send the vanilla server Login reply instead.

            Phase = Phases.Gaming;
            Queue = new SendQueue(this);

            PlayerList.LoginPlayer(this);

            SaveProxyPlayer();

            string name = h.Host.ToLowerInvariant().Split('.')[0];
            if (World.VanillaWorlds.ContainsKey(name))
            {
                SetWorld(World.VanillaWorlds[name]);
            }
            else
            {
                SetWorld(World.Main);
            }
            //Handshake complete
        }
Example #12
0
 public virtual void OnLoginStart(LoginStart packet)
 {
 }
 private void InvokeLoginStart(LoginStart packet)
 {
     packetListener.OnLoginStart(packet);
 }