/// <summary> /// Create a server instance from this configuration /// </summary> public KRPC.Server.Server Create() { KRPC.Server.Message.RPCServer rpcServer = null; KRPC.Server.Message.StreamServer streamServer = null; var serverProtocol = Protocol; if (serverProtocol == Protocol.ProtocolBuffersOverTCP || serverProtocol == Protocol.ProtocolBuffersOverWebsockets) { var serverAddress = IPAddress.Loopback; IPAddress.TryParse(Settings.GetValueOrDefault("address", IPAddress.Loopback.ToString()), out serverAddress); ushort rpcPort = 0; ushort streamPort = 0; ushort.TryParse(Settings.GetValueOrDefault("rpc_port", "0"), out rpcPort); ushort.TryParse(Settings.GetValueOrDefault("stream_port", "0"), out streamPort); var rpcTcpServer = new TCPServer(serverAddress, rpcPort); var streamTcpServer = new TCPServer(serverAddress, streamPort); if (serverProtocol == Protocol.ProtocolBuffersOverTCP) { rpcServer = new KRPC.Server.ProtocolBuffers.RPCServer(rpcTcpServer); streamServer = new KRPC.Server.ProtocolBuffers.StreamServer(streamTcpServer); } else { rpcServer = new KRPC.Server.WebSockets.RPCServer(rpcTcpServer); streamServer = new KRPC.Server.WebSockets.StreamServer(streamTcpServer); } } else { uint baudRate = 0; ushort dataBits = 0; KRPC.IO.Ports.Parity parity; KRPC.IO.Ports.StopBits stopBits; uint.TryParse(Settings.GetValueOrDefault("baud_rate", "9600"), out baudRate); ushort.TryParse(Settings.GetValueOrDefault("data_bits", "8"), out dataBits); // TODO: add helper method for Enum.TryParse (only available in .NET 4) try { parity = (KRPC.IO.Ports.Parity)Enum.Parse( typeof(KRPC.IO.Ports.Parity), Settings.GetValueOrDefault("parity", "None")); } catch (ArgumentException) { parity = KRPC.IO.Ports.Parity.None; } try { stopBits = (KRPC.IO.Ports.StopBits)Enum.Parse( typeof(KRPC.IO.Ports.StopBits), Settings.GetValueOrDefault("stop_bits", "One")); } catch (ArgumentException) { stopBits = KRPC.IO.Ports.StopBits.None; } var serialServer = new KRPC.Server.SerialIO.ByteServer( Settings.GetValueOrDefault("port", string.Empty), baudRate, dataBits, parity, stopBits); rpcServer = new KRPC.Server.SerialIO.RPCServer(serialServer); streamServer = new KRPC.Server.SerialIO.StreamServer(); } return(new KRPC.Server.Server(Id, serverProtocol, Name, rpcServer, streamServer)); }
public static void Main(string[] args) { bool showHelp = false; bool showVersion = false; Logger.Format = "{0:G} - {1} - {2}"; Logger.Enabled = true; Logger.Level = Logger.Severity.Info; bool serverDebug = false; string type = "protobuf"; string bind = "127.0.0.1"; ushort rpcPort = 0; ushort streamPort = 0; string portName = string.Empty; uint baudRate = 9600; ushort dataBits = 8; KRPC.IO.Ports.Parity parity = KRPC.IO.Ports.Parity.None; KRPC.IO.Ports.StopBits stopBits = KRPC.IO.Ports.StopBits.One; var options = new OptionSet { { "h|help", "show this help message and exit", v => showHelp = v != null }, { "v|version", "show program's version number and exit", v => showVersion = v != null }, { "type=", "Type of server to run. Either protobuf, websockets, websockets-echo, or serialio.", v => type = v }, { "bind=", "For TCP based protocols, the address to bind the server to. If unspecified, the loopback address is used (127.0.0.1).", v => bind = v }, { "rpc-port=", "For TCP based protocols, the port number to use for the RPC server. If unspecified, use an ephemeral port.", (ushort v) => rpcPort = v }, { "stream-port=", "For TCP based protocols, the port number to use for the stream server. If unspecified, use an ephemeral port.", (ushort v) => streamPort = v }, { "port=", "For SerialIO based protocols, the port name to communicate on.", v => portName = v }, { "baud-rate=", "For SerialIO based protocols, the baud rate.", (uint v) => baudRate = v }, { "data-bits=", "For SerialIO based protocols, the number of data bits.", (ushort v) => dataBits = v }, { "parity=", "For SerialIO based protocols, the parity.", (KRPC.IO.Ports.Parity v) => parity = v }, { "stop-bits=", "For SerialIO based protocols, the number of stop bits.", (KRPC.IO.Ports.StopBits v) => stopBits = v }, { "debug", "Set log level to 'debug', defaults to 'info'", v => { if (v != null) { Logger.Enabled = true; Logger.Level = Logger.Severity.Debug; } } }, { "quiet", "Set log level to 'warning'", v => { if (v != null) { Logger.Enabled = true; Logger.Level = Logger.Severity.Warning; } } }, { "server-debug", "Output debug information about the server", v => serverDebug = v != null } }; options.Parse(args); if (showHelp) { Help(options); return; } if (showVersion) { var assembly = Assembly.GetEntryAssembly(); var info = FileVersionInfo.GetVersionInfo(assembly.Location); var version = string.Format("{0}.{1}.{2}", info.FileMajorPart, info.FileMinorPart, info.FileBuildPart); Console.WriteLine("TestServer.exe version " + version); return; } KRPC.Service.Scanner.Scanner.GetServices(); var core = Core.Instance; CallContext.SetGameScene(GameScene.SpaceCenter); core.OnClientRequestingConnection += (s, e) => e.Request.Allow(); IPAddress bindAddress; if (!IPAddress.TryParse(bind, out bindAddress)) { Console.WriteLine("Failed to parse bind address."); return; } TCPServer rpcTcpServer = null; TCPServer streamTcpServer = null; KRPC.Server.SerialIO.ByteServer serialServer = null; if (type == "protobuf" || type == "websockets" || type == "websockets-echo") { rpcTcpServer = new TCPServer(bindAddress, rpcPort); streamTcpServer = new TCPServer(bindAddress, streamPort); } if (type == "serialio") { serialServer = new KRPC.Server.SerialIO.ByteServer( portName, baudRate, dataBits, parity, stopBits); } Server server; if (type == "protobuf") { var rpcServer = new KRPC.Server.ProtocolBuffers.RPCServer(rpcTcpServer); var streamServer = new KRPC.Server.ProtocolBuffers.StreamServer(streamTcpServer); server = new Server(Guid.NewGuid(), Protocol.ProtocolBuffersOverTCP, "TestServer", rpcServer, streamServer); } else if (type == "websockets") { var rpcServer = new KRPC.Server.WebSockets.RPCServer(rpcTcpServer); var streamServer = new KRPC.Server.WebSockets.StreamServer(streamTcpServer); server = new Server(Guid.NewGuid(), Protocol.ProtocolBuffersOverWebsockets, "TestServer", rpcServer, streamServer); } else if (type == "websockets-echo") { var rpcServer = new KRPC.Server.WebSockets.RPCServer(rpcTcpServer, true); var streamServer = new KRPC.Server.WebSockets.StreamServer(streamTcpServer); server = new Server(Guid.NewGuid(), Protocol.ProtocolBuffersOverWebsockets, "TestServer", rpcServer, streamServer); } else if (type == "serialio") { var rpcServer = new KRPC.Server.SerialIO.RPCServer(serialServer); var streamServer = new KRPC.Server.SerialIO.StreamServer(); server = new Server(Guid.NewGuid(), Protocol.ProtocolBuffersOverSerialIO, "TestServer", rpcServer, streamServer); } else { Logger.WriteLine("Server type '" + type + "' not supported", Logger.Severity.Error); return; } core.Add(server); Logger.WriteLine("Starting server..."); core.StartAll(); Logger.WriteLine("type = " + type); if (rpcTcpServer != null) { Logger.WriteLine("bind = " + bindAddress); Logger.WriteLine("rpc_port = " + rpcTcpServer.ActualPort); if (streamTcpServer != null) { Logger.WriteLine("stream_port = " + streamTcpServer.ActualPort); } } if (serialServer != null) { Logger.WriteLine("port = " + serialServer.Address); } Logger.WriteLine("Server started successfully"); const long targetFPS = 60; long update = 0; long ticksPerUpdate = Stopwatch.Frequency / targetFPS; var timer = new Stopwatch(); while (server.Running) { timer.Reset(); timer.Start(); core.Update(); if (serverDebug && update % targetFPS == 0) { // Output details about whether server.Update() took too little or too long to execute var elapsed = timer.ElapsedTicks; var diffTicks = Math.Abs(ticksPerUpdate - elapsed); var diffTime = Math.Round(diffTicks / (double)Stopwatch.Frequency * 1000d, 2); if (elapsed > ticksPerUpdate) { Console.WriteLine("Slow by " + diffTime + " ms (" + diffTicks + " ticks)"); } else { Console.WriteLine("Fast by " + diffTime + " ms (" + diffTicks + " ticks)"); } } // Wait, to force 60 FPS while (timer.ElapsedTicks < ticksPerUpdate) { } update++; } }