コード例 #1
0
ファイル: CoflnetSocket.cs プロジェクト: Coflnet/cloud
    protected override void OnOpen()
    {
        var protocols = Context.SecWebSocketProtocols;


        foreach (var item in protocols)
        {
            if (item == "dev")
            {
                this.Encoder = CoflnetJsonEncoder.Instance;
                Send("runing on dev, Format");
                Send(MessagePackSerializer.SerializeToJson(
                         new CoflnetJsonEncoder.DevCommandData(ServerCommandData.SerializeServerCommandData
                                                                   (new KeyValuePair <string, string>("exampleKey", "This is an example of a valid command"),
                                                                   "setValue",
                                                                   this.Encoder))));
                //	CommandData.SerializeCommandData("hi", "setValue")))));
            }
        }


        if (this.Encoder == null)
        {
            this.Encoder = CoflnetEncoder.Instance;
        }

        System.Timers.Timer timer = new System.Timers.Timer();
        timer.AutoReset = true;

        timer.Elapsed += t_Elapsed;

        timer.Start();
    }
コード例 #2
0
        private bool VerifyVersionData(ServerCommandData data)
        {
            CoreLog.Log(CoreLogLevel.Debug, $"Received {data.Command} while waiting for server announcement.");
            if (data.Command == ServerCommand.Announce)
            {
                var protocolVersion = ValueConverter.ToUInt32(data.Data, 0);
                var pluginVersion   = ValueConverter.ToVersion(data.Data, 4);

                if (protocolVersion != CoreVersion.ProtocolVersion)
                {
                    var updatee = protocolVersion > CoreVersion.ProtocolVersion ? "game mode" : "server";
                    CoreLog.Log(CoreLogLevel.Error,
                                $"Protocol version mismatch! The server is running protocol {protocolVersion} but the game mode is running {CoreVersion.ProtocolVersion}");
                    CoreLog.Log(CoreLogLevel.Error, $"Please update your {updatee}.");
                    return(false);
                }
                CoreLog.Log(CoreLogLevel.Info, $"Connected to version {pluginVersion.ToString(3)} via protocol {protocolVersion}");

                ServerPath = ValueConverter.ToString(data.Data, 8, Encoding.ASCII);

                return(true);
            }
            CoreLog.Log(CoreLogLevel.Error, $"Received command {data.Command.ToString().ToLower()} instead of announce.");
            return(false);
        }
コード例 #3
0
            public bool Process(ServerCommandData command, bool force)
            {
                if (_condition != command.Command && !force)
                {
                    return(false);
                }

                _result = command;

                _semaphore.Release();

                return(true);
            }
コード例 #4
0
ファイル: MessagePersistence.cs プロジェクト: Coflnet/cloud
        /// <summary>
        /// Save the specified data. Will drop the data if the receiver and sender are the same.
        /// </summary>
        /// <param name="commandData">Data to save.</param>
        public override void SaveMessage(CommandData commandData)
        {
            // messages to oneself won't be saved
            if (commandData.SenderId == commandData.Recipient)
            {
                return;
            }
            var serverData = commandData as ServerCommandData;

            if (serverData == null)
            {
                serverData = new ServerCommandData(commandData);
            }
            FileController.AppendLineAs <ServerCommandData>(PathToSource(commandData.Recipient), serverData);
        }
コード例 #5
0
            public ServerCommandData Wait()
            {
                _semaphore.Wait();

                var result = _result;

                _result = default(ServerCommandData);

                // If we're not waiting for this command, don't recycle this handle.
                if (result.Command == _condition)
                {
                    _owner.Recycle(this);
                }

                return(result);
            }
コード例 #6
0
ファイル: CoflnetSocket.cs プロジェクト: Coflnet/cloud
    protected override void OnMessage(MessageEventArgs e)
    {
        // try to parse and execute the command sent
        try
        {
            ServerCommandData commandData = Encoder.Deserialize(e);
            // if connection information is needed
            commandData.Connection = this;


            if (commandData.Recipient.ServerId == 0)
            {
                throw new CoflnetException("unknown_server", "this server is unknown (There is no server with the id 0)");
            }


            // prevent id spoofing
            if (commandData.SenderId != new EntityId() && !AuthenticatedIds.Contains(commandData.SenderId))
            {
                throw new NotAuthenticatedAsException(commandData.SenderId);
            }


            EntityManager.Instance.ExecuteForReference(commandData);
            //	var controllerForObject = ReferenceManager.Instance.GetResource(commandData.rId)
            //					.GetCommandController();

            //	controllerForObject.ExecuteCommand(commandData);
        }
        catch (CoflnetException ex)
        {
            Encoder.Send(new CoflnetExceptionTransmit(ex), this);
            Track.instance.Error(ex.Message, e.Data, ex.StackTrace);
        }

        /*
         * catch (Exception ex)
         * {
         *      Track.instance.Error(ex.Message, e.Data, ex.StackTrace);
         * }*/
        //Logger.Log(ID);
        //Logger.Log("Got some data :)");
    }
コード例 #7
0
        public void Release(ServerCommandData command)
        {
            // Find wait handle waiting for this command.
            lock (_waitHandles)
            {
                // Process the command in REVERSE order (stack) because of natives calling callbacks
                // calling natives calling callbacks... The deepest native should first receive a response.
                // When forcing an unhandled command down some wait handle (next while loop), the order does
                // not matter.
                var current = _waitHandles.Last;
                while (current != null)
                {
                    if (current.Value.Process(command, false))
                    {
                        _waitHandles.Remove(current);
                        return;
                    }

                    current = current.Previous;
                }

                // Force it down some wait handle... Can't let asyncQueue handle it because at this point
                // the main thread might be waiting for the response of a native, while the server might be
                // waiting for the response to a callback invoked by the native. Deadlocks, yay! If no wait
                // handles are available, the async queue should be able to handle this because the main thread
                // is likely idle.
                current = _waitHandles.First;
                while (current != null)
                {
                    if (current.Value.Process(command, true))
                    {
                        return;
                    }

                    current = current.Next;
                }
            }

            // If no wait handles are able to process this command, put it on the queue for when the main thread
            // is idle.
            _asyncQueue.Enqueue(command);
            _semaphore.Release();
        }
コード例 #8
0
        private void ProcessCommand(ServerCommandData data)
        {
            switch (data.Command)
            {
            case ServerCommand.Nop:
                break;

            case ServerCommand.Tick:
                // The server expects at least a message every 5 seconds or else the debug pause
                // detector kicks in. Send one at least every 3 to be safe.
                if (DateTime.UtcNow - _lastSend > TimeSpan.FromSeconds(3))
                {
                    Send(ServerCommand.Alive, null);
                }

                if (!_canTick)
                {
                    break;
                }

                try
                {
                    _gameModeProvider.Tick();
                }
                catch (Exception e)
                {
                    OnUnhandledException(new UnhandledExceptionEventArgs("Tick", e));
                }

                break;

            case ServerCommand.Pong:
                if (_pongs.Count == 0)
                {
                    CoreLog.Log(CoreLogLevel.Error, "Received a random pong");
                    CoreLog.Log(CoreLogLevel.Debug, Environment.StackTrace);
                }
                else
                {
                    _pongs.Dequeue().Pong();
                }
                break;

            case ServerCommand.Announce:
                CoreLog.Log(CoreLogLevel.Error, "Received a random server announcement");
                CoreLog.Log(CoreLogLevel.Debug, Environment.StackTrace);
                break;

            case ServerCommand.PublicCall:
                var name   = ValueConverter.ToString(data.Data, 0, Encoding);
                var isInit = name == "OnGameModeInit";

                if (CoreLog.DoesLog(CoreLogLevel.Verbose))
                {
                    CoreLog.LogVerbose("Incoming public call: {0}", name);
                }

                if ((_startBehaviour == GameModeStartBehaviour.Gmx || _startBehaviour == GameModeStartBehaviour.FakeGmx) && !_initReceived &&
                    !isInit)
                {
                    CoreLog.Log(CoreLogLevel.Debug, $"Skipping callback {name} because OnGameModeInit has not yet been called");
                    Send(ServerCommand.Response, AZero);
                    break;
                }

                var isFirstInit = isInit && !_initReceived;
                if (isFirstInit)
                {
                    _initReceived = true;
                }

                if (_callbacks.TryGetValue(name, out var callback))
                {
                    int?result = null;
                    try
                    {
                        result = callback.Invoke(data.Data, name.Length + 1);

                        CoreLog.LogVerbose("Public call response for {0}: {1}", name, result);
                    }
                    catch (Exception e)
                    {
                        OnUnhandledException(new UnhandledExceptionEventArgs(name, e));
                    }

                    Send(ServerCommand.Response,
                         result != null
                                ? AOne.Concat(ValueConverter.GetBytes(result.Value))
                                : AZero);
                }
                else
                {
                    CoreLog.Log(CoreLogLevel.Error, "Received unknown callback " + name);
                    CoreLog.Log(CoreLogLevel.Debug, Environment.StackTrace);
                }

                if (isFirstInit)
                {
                    if (_startBehaviour == GameModeStartBehaviour.FakeGmx)
                    {
                        FakeGmxRotate();
                    }

                    _canTick = true;
                }
                else if (_initReceived && name == "OnGameModeExit")
                {
                    CoreLog.Log(CoreLogLevel.Info, "OnGameModeExit received, sending reconnect signal...");
                    Send(ServerCommand.Reconnect, null);

                    // Give the server time to receive the reconnect signal.
                    Thread.Sleep(100);

                    CleanUp();
                }
                break;

            default:
                CoreLog.Log(CoreLogLevel.Error, $"Unknown command {data.Command} received with {data.Data?.Length.ToString() ?? "NULL"} data");
                CoreLog.Log(CoreLogLevel.Debug, Environment.StackTrace);
                break;
            }
        }
コード例 #9
0
        private void ProcessCommand(ServerCommandData data)
        {
            switch (data.Command)
            {
            case ServerCommand.Tick:
                if (!_canTick)
                {
                    break;
                }

                _gameModeProvider.Tick();

                // The server expects at least a message every 5 seconds or else the debug pause
                // detector kicks in. Send one at least every 3 to be safe.
                if (DateTime.UtcNow - _lastSend > TimeSpan.FromSeconds(3))
                {
                    Send(ServerCommand.Alive, null);
                }

                break;

            case ServerCommand.Pong:
                if (_pongs.Count == 0)
                {
                    CoreLog.Log(CoreLogLevel.Error, "Received a random pong");
                    CoreLog.Log(CoreLogLevel.Debug, Environment.StackTrace);
                }
                else
                {
                    _pongs.Dequeue().Pong();
                }
                break;

            case ServerCommand.Announce:
                CoreLog.Log(CoreLogLevel.Error, "Received a random server announcement");
                CoreLog.Log(CoreLogLevel.Debug, Environment.StackTrace);
                break;

            case ServerCommand.PublicCall:
                var name   = ValueConverter.ToString(data.Data, 0, Encoding);
                var isInit = name == "OnGameModeInit";

                if (CoreLog.DoesLog(CoreLogLevel.Verbose))
                {
                    CoreLog.LogVerbose("Incoming public call: {0}", name);
                }

                if ((_startBehaviour == GameModeStartBehaviour.Gmx || _startBehaviour == GameModeStartBehaviour.FakeGmx) && !_initReceived &&
                    !isInit)
                {
                    CoreLog.Log(CoreLogLevel.Debug, $"Skipping callback {name} because OnGameModeInit has not yet been called");
                    Send(ServerCommand.Response, AZero);
                    break;
                }

                var isFirstInit = isInit && !_initReceived;
                if (isFirstInit)
                {
                    _initReceived = true;
                }

                if (_callbacks.TryGetValue(name, out var callback))
                {
                    int?result = null;
                    try
                    {
                        result = callback.Invoke(data.Data, name.Length + 1);

                        CoreLog.LogVerbose("Public call response for {0}: {1}", name, result);
                    }
                    catch (Exception e)
                    {
                        OnUnhandledException(new UnhandledExceptionEventArgs(e));
                    }

                    Send(ServerCommand.Response,
                         result != null
                                ? AOne.Concat(ValueConverter.GetBytes(result.Value))
                                : AZero);
                }
                else
                {
                    CoreLog.Log(CoreLogLevel.Error, "Received unknown callback " + name);
                    CoreLog.Log(CoreLogLevel.Debug, Environment.StackTrace);
                }

                if (isFirstInit)
                {
                    if (_startBehaviour == GameModeStartBehaviour.FakeGmx)
                    {
                        _callbacks.TryGetValue("OnIncomingConnection", out var onIncomingConnection);
                        _callbacks.TryGetValue("OnPlayerConnect", out var onPlayerConnect);
                        _callbacks.TryGetValue("OnPlayerRequestClass", out var onPlayerRequestClass);

                        var natIsPlayerConnected = NativeLoader.Load("IsPlayerConnected", new[]
                        {
                            NativeParameterInfo.ForType(typeof(int))
                        });
                        var natGetPlayerPoolSize   = NativeLoader.Load("GetPlayerPoolSize", new NativeParameterInfo[0]);
                        var natForceClassSelection =
                            NativeLoader.Load("ForceClassSelection", new[]
                        {
                            NativeParameterInfo.ForType(typeof(int))
                        });
                        var natTogglePlayerSpectating = NativeLoader.Load("TogglePlayerSpectating",
                                                                          new[]
                        {
                            NativeParameterInfo.ForType(typeof(int)),
                            NativeParameterInfo.ForType(typeof(int))
                        });
                        var natGetPlayerIp = NativeLoader.Load("GetPlayerIp",
                                                               new[]
                        {
                            NativeParameterInfo.ForType(typeof(int)),
                            new NativeParameterInfo(NativeParameterType.StringReference, 2),
                            NativeParameterInfo.ForType(typeof(int)),
                        });

                        var poolSize = natGetPlayerPoolSize.Invoke();
                        for (var i = 0; i <= poolSize; i++)
                        {
                            var isConnected = natIsPlayerConnected.Invoke(i);

                            if (isConnected == 0)
                            {
                                continue;
                            }

                            var args = new object[] { i, null, 16 };
                            natGetPlayerIp.Invoke(args);

                            if (args[1] is string ip)
                            {
                                onIncomingConnection?.Invoke(
                                    ValueConverter.GetBytes(i)
                                    .Concat(ValueConverter.GetBytes(ip, Encoding.ASCII))
                                    .Concat(ValueConverter.GetBytes(9999999))
                                    .ToArray(), 0);
                            }

                            onPlayerConnect?.Invoke(ValueConverter.GetBytes(i), 0);

                            natForceClassSelection.Invoke(i);
                            natTogglePlayerSpectating.Invoke(i, 1);
                            natTogglePlayerSpectating.Invoke(i, 0);

                            onPlayerRequestClass?.Invoke(
                                ValueConverter.GetBytes(i)
                                .Concat(ValueConverter.GetBytes(0))
                                .ToArray(), 0);
                        }
                    }

                    _canTick = true;
                }
                else if (_initReceived && name == "OnGameModeExit")
                {
                    CoreLog.Log(CoreLogLevel.Info, "OnGameModeExit received, sending reconnect signal...");
                    Send(ServerCommand.Reconnect, null);

                    // Give the server time to receive the reconnect signal.
                    // TODO: This is an ugly freeze/comms-deadlock fix.
                    Thread.Sleep(100);

                    CleanUp();
                }
                break;

            default:
                CoreLog.Log(CoreLogLevel.Error, $"Unknown command {data.Command} recieved with {data.Data?.Length.ToString() ?? "NULL"} data");
                CoreLog.Log(CoreLogLevel.Debug, Environment.StackTrace);
                break;
            }
        }
コード例 #10
0
 public void Release(ServerCommandData command)
 {
     _asyncQueue.Enqueue(command);
     _semaphore.Release();
 }