Example #1
0
        public void HandleMessage(VMNetClient client, VMNetMessage message)
        {
            var cmd = new VMNetCommand();

            try {
                using (var reader = new BinaryReader(new MemoryStream(message.Data))) {
                    if (!cmd.TryDeserialize(reader, false))
                    {
                        return;                                     //ignore things that should never be sent to the server
                    }
                }
            }
            catch (Exception e)
            {
                //corrupt commands are currently a death sentence for the client. nothing should be corrupt over TCP except in rare cases.
                client.FatalDCMessage = "RECEIVED BAD COMMAND: " + e.ToString();
                ClientsToDC.Add(client);
                return;
            }

            if (cmd.Type == VMCommandType.SimJoin)
            {
                //note: currently avatars no longer send sim join commands, the server does when it gets the database info.
                if (SandboxBans.Contains(client.RemoteIP))
                {
                    SendGenericMessage(client, "Banned", "You have been banned from this sandbox server!");
                    ClientsToDC.Add(client);
                    return;
                }
                else if (((VMNetSimJoinCmd)cmd.Command).Version != VMNetSimJoinCmd.CurVer)
                {
                    SendGenericMessage(client, "Version Mismatch", "Your game version does not match the server's. Please update your game.");
                    ClientsToDC.Add(client);
                    return;
                }
                SendCommand(cmd.Command); //just go for it. will start the avatar retrieval process.
                return;
            }
            else if (cmd.Type == VMCommandType.RequestResync)
            {
                lock (ClientsToSync)
                {
                    //todo: throttle
                    ProblemTick = ((VMRequestResyncCmd)cmd.Command).TickID;
                    ResyncClients.Add(client); //under clientstosync lock
                }
            }
            else if (cmd.Type != VMCommandType.ChatParameters)
            {
                client.InactivityTicks = 0;
            }

            cmd.Command.ActorUID = client.PersistID;
            SendCommand(cmd.Command);
        }
Example #2
0
        public override void OnPacket(NetworkClient client, ProcessedPacket packet)
        {
            var cmd = new VMNetCommand();

            try {
                using (var reader = new BinaryReader(packet)) {
                    cmd.Deserialize(reader);
                }
            } catch (Exception)
            {
                ClientsToDC.Add(client);
                return;
            }

            if (cmd.Type == VMCommandType.SimJoin)
            {
                if (SandboxBans.Contains(client.RemoteIP))
                {
                    SendGenericMessage(client, "Banned", "You have been banned from this sandbox server!");
                    ClientsToDC.Add(client);
                    return;
                }
                else if (((VMNetSimJoinCmd)cmd.Command).Version != VMNetSimJoinCmd.CurVer)
                {
                    SendGenericMessage(client, "Version Mismatch", "Your game version does not match the server's. Please update your game.");
                    ClientsToDC.Add(client);
                    return;
                }

                ((VMNetSimJoinCmd)cmd.Command).Ticket = client.RemoteIP + ":" + ((VMNetSimJoinCmd)cmd.Command).Name;
                ((VMNetSimJoinCmd)cmd.Command).Client = client; //remember client so we can bind it to persist id later
                SendCommand(cmd.Command);                       //just go for it. will start the avatar retrieval process.
                return;
            }
            else if (cmd.Type == VMCommandType.RequestResync)
            {
                lock (ClientsToSync)
                {
                    //todo: throttle
                    ClientsToSync.Add(client);
                }
            }

            lock (ClientToUID)
            {
                if (!ClientToUID.ContainsKey(client))
                {
                    return;                                   //client hasn't registered yet
                }
                cmd.Command.ActorUID = ClientToUID[client];
            }
            SendCommand(cmd.Command);
        }
Example #3
0
        private void SendState(VM vm)
        {
            if (ClientsToSync.Count == 0)
            {
                return;
            }

            var watch = new Stopwatch();

            watch.Start();

            var state    = vm.Save();
            var statecmd = new VMStateSyncCmd {
                State = state
            };

#if VM_DESYNC_DEBUG
            statecmd.Trace = vm.Trace.GetTick(ProblemTick);
#endif
            var cmd = new VMNetCommand(statecmd);

            //currently just hack this on the tick system. might switch later
            var ticks = new VMNetTickList {
                Ticks = new List <VMNetTick> {
                    new VMNetTick {
                        Commands = new List <VMNetCommand> {
                            cmd
                        },
                        RandomSeed = 0, //will be restored by client from cmd
                        TickID     = TickID
                    }
                }
            };

            byte[] data;
            using (var stream = new MemoryStream())
            {
                using (var writer = new BinaryWriter(stream))
                {
                    ticks.SerializeInto(writer);
                }
                data = stream.ToArray();
            }

            foreach (var client in ClientsToSync)
            {
                Send(client, new VMNetMessage(VMNetMessageType.BroadcastTick, data));
            }

            ClientsToSync.Clear();

            watch.Stop();
        }
Example #4
0
        private void SendState(VM vm)
        {
            if (ClientsToSync.Count == 0)
            {
                return;
            }
            var state = vm.Save();
            var cmd   = new VMNetCommand(new VMStateSyncCmd {
                State = state
            });

            //currently just hack this on the tick system. will change when we switch to not gonzonet
            var ticks = new VMNetTickList {
                Ticks = new List <VMNetTick> {
                    new VMNetTick {
                        Commands = new List <VMNetCommand> {
                            cmd
                        },
                        RandomSeed = 0, //will be restored by client from cmd
                        TickID     = TickID
                    }
                }
            };

            byte[] data;
            using (var stream = new MemoryStream())
            {
                using (var writer = new BinaryWriter(stream))
                {
                    ticks.SerializeInto(writer);
                }

                data = stream.ToArray();
            }

            byte[] packet;

            using (var stream = new PacketStream((byte)PacketType.VM_PACKET, 0))
            {
                stream.WriteHeader();
                stream.WriteInt32(data.Length + (int)PacketHeaders.UNENCRYPTED);
                stream.WriteBytes(data);

                packet = stream.ToArray();
            }
            foreach (var client in ClientsToSync)
            {
                client.Send(packet);
            }
            ClientsToSync.Clear();
        }
Example #5
0
        public void SendDirectCommand(VMNetClient client, VMNetCommandBodyAbstract acmd)
        {
            var cmd = new VMNetCommand(acmd);

            byte[] data;
            using (var stream = new MemoryStream())
            {
                using (var writer = new BinaryWriter(stream))
                {
                    cmd.SerializeInto(writer);
                }

                data = stream.ToArray();
            }

            Send(client, new VMNetMessage(VMNetMessageType.Direct, data));
        }
        private void HandleServerMessage(VMNetMessage message)
        {
            if (message.Type == VMNetMessageType.Direct)
            {
                var cmd = new VMNetCommand();
                try
                {
                    using (var reader = new BinaryReader(new MemoryStream(message.Data)))
                    {
                        cmd.Deserialize(reader);
                    }
                    cmd.Command.Execute(VMHook, VMHook.GetAvatarByPersist(cmd.Command.ActorUID));
                }
                catch (Exception e)
                {
                    CloseReason = VMCloseNetReason.NetExceptionDirect;
                    CloseString = "An exception occurred while running a direct tick from the server, so the lot connection was terminated: \n\n" + e.ToString();
                    Shutdown();
                    return;
                }
            }
            else
            {
                var tick = new VMNetTickList();
                try
                {
                    using (var reader = new BinaryReader(new MemoryStream(message.Data)))
                    {
                        tick.Deserialize(reader);
                    }
                }
                catch (Exception e)
                {
                    CloseReason = VMCloseNetReason.NetException;
                    CloseString = "An exception occurred while running a broadcast tick from the server, so the lot connection was terminated: \n\n" + e.ToString();
                    Shutdown();
                    return;
                }

                for (int i = 0; i < tick.Ticks.Count; i++)
                {
                    tick.Ticks[i].ImmediateMode = tick.ImmediateMode;
                    TickBuffer.Enqueue(tick.Ticks[i]);
                }
            }
        }
Example #7
0
        private void SendToServer(VMNetCommandBodyAbstract cmd)
        {
            byte[] data;
            using (var stream = new MemoryStream())
            {
                var cmd2 = new VMNetCommand(cmd);
                using (var writer = new BinaryWriter(stream))
                {
                    cmd2.SerializeInto(writer);
                }
                data = stream.ToArray();
            }

            if (OnClientCommand != null)
            {
                OnClientCommand(data);
            }
        }
Example #8
0
        private void HandleServerMessage(VMNetMessage message)
        {
            if (message.Type == VMNetMessageType.Direct)
            {
                var cmd = new VMNetCommand();
                try
                {
                    using (var reader = new BinaryReader(new MemoryStream(message.Data)))
                    {
                        cmd.Deserialize(reader);
                    }
                    cmd.Command.Execute(VMHook);
                }
                catch (Exception e)
                {
                    Shutdown();
                    return;
                }
            }
            else
            {
                var tick = new VMNetTickList();
                try
                {
                    using (var reader = new BinaryReader(new MemoryStream(message.Data)))
                    {
                        tick.Deserialize(reader);
                    }
                }
                catch (Exception e)
                {
                    Shutdown();
                    return;
                }

                for (int i = 0; i < tick.Ticks.Count; i++)
                {
                    tick.Ticks[i].ImmediateMode = tick.ImmediateMode;
                    TickBuffer.Enqueue(tick.Ticks[i]);
                }
            }
        }
Example #9
0
 private void SendToServer(VMNetCommandBodyAbstract cmd)
 {
     byte[] data;
     using (var stream = new MemoryStream())
     {
         var cmd2 = new VMNetCommand(cmd);
         using (var writer = new BinaryWriter(stream))
         {
             cmd2.SerializeInto(writer);
         }
         data = stream.ToArray();
     }
     using (var stream = new PacketStream((byte)PacketType.VM_PACKET, 0))
     {
         stream.WriteHeader();
         stream.WriteInt32(data.Length + (int)PacketHeaders.UNENCRYPTED);
         stream.WriteBytes(data);
         Client.Send(stream.ToArray());
     }
 }
Example #10
0
        public override void OnPacket(NetworkClient client, ProcessedPacket packet)
        {
            var cmd = new VMNetCommand();

            try {
                using (var reader = new BinaryReader(packet)) {
                    cmd.Deserialize(reader);
                }
            } catch (Exception)
            {
                ClientsToDC.Add(client);
                return;
            }

            if (cmd.Type == VMCommandType.SimJoin)
            {
                if (((VMNetSimJoinCmd)cmd.Command).Version != VMNetSimJoinCmd.CurVer)
                {
                    ClientsToDC.Add(client);
                    return;
                }
                lock (UIDs)
                {
                    UIDs.Add(client, ((VMNetSimJoinCmd)cmd.Command).SimID);
                }
            }
            else if (cmd.Type == VMCommandType.RequestResync)
            {
                lock (ClientsToSync)
                {
                    //todo: throttle
                    ClientsToSync.Add(client);
                }
            }

            SendCommand(cmd.Command);
        }
Example #11
0
        public void SendDirectCommand(VMNetClient client, VMNetCommandBodyAbstract acmd)
        {
            if (client.RemoteIP == "local")
            {
                //just breaking sandbox a little
                SendCommand(acmd);
                return;
            }

            var cmd = new VMNetCommand(acmd);

            byte[] data;
            using (var stream = new MemoryStream())
            {
                using (var writer = new BinaryWriter(stream))
                {
                    cmd.SerializeInto(writer);
                }

                data = stream.ToArray();
            }

            Send(client, new VMNetMessage(VMNetMessageType.Direct, data));
        }
Example #12
0
        private void SendState(VM vm)
        {
            if (ResyncClients.Count != 0 && LastSync == null && !SyncSerializing)
            {
                //only add resync clients when we can give them a (near) clean sync.
                if (TickID - LastDesyncTick > DESYNC_LOOP_FREQ)
                {
                    LastDesyncPcts.Clear();
                }
                LastDesyncTick = TickID;
                LastDesyncPcts.Add(ResyncClients.Count / (float)vm.Context.ObjectQueries.AvatarsByPersist.Count);

                foreach (var cli in ResyncClients) //under clientstosync lock
                {
                    ClientsToSync.Add(cli);
                }
                ResyncClients.Clear();
            }
            if (ClientsToSync.Count == 0)
            {
                return;
            }

            if (LastSync == null && !SyncSerializing)
            {
                SyncSerializing = true;
                TicksSinceSync  = new List <byte[]>(); //start saving a history.

                var state    = vm.Save();              //must be saved on lot thread. we can serialize elsewhere tho.
                var statecmd = new VMStateSyncCmd {
                    State = state
                };
                if (vm.Trace != null)
                {
                    statecmd.Traces = vm.Trace.History;
                }
                var cmd = new VMNetCommand(statecmd);

                //currently just hack this on the tick system. might switch later
                var ticks = new VMNetTickList
                {
                    Ticks = new List <VMNetTick> {
                        new VMNetTick {
                            Commands = new List <VMNetCommand> {
                                cmd
                            },
                            RandomSeed = 0, //will be restored by client from cmd
                            TickID     = TickID
                        }
                    }
                };

                Task.Run(() =>
                {
                    byte[] data;
                    using (var stream = new MemoryStream())
                    {
                        using (var writer = new BinaryWriter(stream))
                        {
                            ticks.SerializeInto(writer);
                        }
                        data = stream.ToArray();
                    }
                    LastSync        = data;
                    SyncSerializing = false;
                });
            }
            else if (LastSync != null)
            {
                foreach (var client in ClientsToSync)
                {
                    Send(client, new VMNetMessage(VMNetMessageType.BroadcastTick, LastSync));
                    foreach (var tick in TicksSinceSync) //catch this client up with what happened since the last state was created.
                    {
                        Send(client, new VMNetMessage(VMNetMessageType.BroadcastTick, tick));
                    }
                }
                ClientsToSync.Clear();
                NewClients.Clear(); //note that the lock for clientstosync is valid for newclients too.

                //don't clear last sync and history, since it can be used again if someone wants to join soon.
            }
            //if neither of the above happen, we're waiting for the serialization to complete (in the task)
        }
Example #13
0
        private void SendState(VM vm)
        {
            if (ClientsToSync.Count == 0)
            {
                return;
            }
            //Console.WriteLine("== SERIAL: Sending State to Client... ==");

            var watch = new Stopwatch();

            watch.Start();

            var state = vm.Save();
            //Console.WriteLine("== STATE: Intermediate - after save... " + watch.ElapsedMilliseconds + " ms. ==");
            var cmd = new VMNetCommand(new VMStateSyncCmd {
                State = state
            });

            //currently just hack this on the tick system. will change when we switch to not gonzonet
            var ticks = new VMNetTickList {
                Ticks = new List <VMNetTick> {
                    new VMNetTick {
                        Commands = new List <VMNetCommand> {
                            cmd
                        },
                        RandomSeed = 0, //will be restored by client from cmd
                        TickID     = TickID
                    }
                }
            };

            byte[] data;
            using (var stream = new MemoryStream())
            {
                //Console.WriteLine("== STATE: Intermediate - before serialize... " + watch.ElapsedMilliseconds + " ms. ==");
                using (var writer = new BinaryWriter(stream))
                {
                    ticks.SerializeInto(writer);
                }

                //Console.WriteLine("== STATE: Intermediate - before toArray... " + watch.ElapsedMilliseconds + " ms. ==");
                data = stream.ToArray();
            }
            //Console.WriteLine("== STATE: Intermediate - before send... " + watch.ElapsedMilliseconds + " ms. ==");

            byte[] packet;

            using (var stream = new PacketStream((byte)ProtocolAbstractionLibraryD.PacketType.VM_PACKET, 0))
            {
                stream.WriteHeader();
                stream.WriteInt32(data.Length + (int)PacketHeaders.UNENCRYPTED);
                stream.WriteBytes(data);

                packet = stream.ToArray();
            }
            foreach (var client in ClientsToSync)
            {
                client.Send(packet);
            }
            ClientsToSync.Clear();

            watch.Stop();
            //Console.WriteLine("== SERIAL: DONE! State send took "+watch.ElapsedMilliseconds+" ms. ==");
        }
Example #14
0
        public bool AsyncBreak; //if

        protected void InternalTick(VM vm, VMNetTick tick)
        {
            CurrentTick = tick.TickID;
            if (CurrentTick > GreatestTick)
            {
                GreatestTick = CurrentTick;
            }
            if (!tick.ImmediateMode && (tick.Commands.Count == 0 || !(tick.Commands[0].Command is VMStateSyncCmd)) && vm.Context.RandomSeed != tick.RandomSeed)
            {
                if (DesyncCooldown == 0)
                {
                    System.Console.WriteLine("DESYNC - Requested state from host");
                    if (DesyncTick == 0)
                    {
                        DesyncTick = CurrentTick - 1;
                    }
                    vm.SendCommand(new VMRequestResyncCmd());
                    DesyncCooldown = 30 * 30;
                }
                else
                {
                    System.Console.WriteLine("WARN - DESYNC - Expected " + tick.RandomSeed + ", was at " + vm.Context.RandomSeed);
                }
            }

            if (RecordStream != null)
            {
                RecordTick(tick);
            }
            vm.Context.RandomSeed = tick.RandomSeed;
            AsyncBreak            = false;
            bool doTick = !tick.ImmediateMode;

            foreach (var cmd in tick.Commands)
            {
                if (cmd.Command is VMStateSyncCmd && ((VMStateSyncCmd)cmd.Command).Run)
                {
                    if (LastTick + 1 != tick.TickID)
                    {
                        System.Console.WriteLine("Jump to tick " + tick.TickID);
                    }
                    if (!(this is VMFSORDriver))
                    {
                        doTick = false;                          //something weird here. this can break loading from saves casually - but must not be active for resyncs.
                    }
                    //disable just for fsor playback
                }

                var caller = vm.GetAvatarByPersist(cmd.Command.ActorUID);
                Executing = cmd;
                cmd.Command.Execute(vm, caller);
                Executing = null;
                if (vm.FSOVAsyncLoading)
                {
                    tick.Commands.Remove(cmd); //don't worry about modifying an enumerated collection - we are exiting anyways.
                    AsyncBreak = true;
                    return;
                }
            }

            if (tick.TickID < LastTick)
            {
                System.Console.WriteLine("Tick wrong! Got " + tick.TickID + ", Missed " + ((int)tick.TickID - (LastTick + 1)));
            }
            else if (doTick && vm.Context.Ready)
            {
                if (tick.TickID > LastTick + 1)
                {
                    System.Console.WriteLine("Tick wrong! Got " + tick.TickID + ", Missed " + ((int)tick.TickID - (LastTick + 1)));
                }
                vm.Trace?.NewTick(tick.TickID);
                vm.InternalTick(tick.TickID);
                if (DesyncCooldown > 0)
                {
                    DesyncCooldown--;
                }
            }
            LastTick = tick.TickID;
        }