public void delayDisconnect(string reason) { if (kickTargetTimestamp != 0) { return; } sendChatMessage("^#f75d5d;" + reason); flushChatQueue(); kickTargetTimestamp = Utils.getTimestamp() + 6; sendServerPacket(Packet.ClientDisconnect, new byte[1]); StarryboundServer.logInfo("[" + playerData.client + "] is being kicked for " + reason); }
public static ServerFile Read(string path) { if (!File.Exists(path)) { return(new ServerFile()); } using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { ServerFile file = Read(fs); StarryboundServer.logInfo("Starbound server config loaded successfully."); return(file); } }
private void doDisconnect(string logMessage) { if (this.state == ClientState.Disposing) { return; } this.state = ClientState.Disposing; StarryboundServer.logInfo("[" + playerData.client + "] " + logMessage); try { if (this.playerData.name != null) { Client target = StarryboundServer.getClient(this.playerData.name); if (target != null) { Users.SaveUser(this.playerData); StarryboundServer.removeClient(this); if (this.kickTargetTimestamp == 0) { StarryboundServer.sendGlobalMessage(this.playerData.name + " has left the server."); } } } } catch (Exception e) { StarryboundServer.logException("Failed to remove client from clients: " + e.ToString()); } try { this.sendServerPacket(Packet.ClientDisconnect, new byte[1]); } catch (Exception) { } try { this.cSocket.Close(); this.sSocket.Close(); } catch (Exception) { } try { this.ClientForwarder.Abort(); this.ServerForwarder.Abort(); } catch (Exception) { } }
public void runTcp() { try { IPAddress localAdd = IPAddress.Parse(StarryboundServer.config.proxyIP); tcpSocket = new TcpListener(localAdd, StarryboundServer.config.proxyPort); tcpSocket.Start(); StarryboundServer.logInfo("Proxy server has been started on " + localAdd.ToString() + ":" + StarryboundServer.config.proxyPort); StarryboundServer.changeState(ServerState.ListenerReady, "ListenerThread::runTcp"); try { while (true) { TcpClient clientSocket = tcpSocket.AcceptTcpClient(); clientSocket.ReceiveTimeout = StarryboundServer.config.clientSocketTimeout * 1000; clientSocket.SendTimeout = StarryboundServer.config.internalSocketTimeout * 1000; new Thread(new ThreadStart(new Client(clientSocket).run)).Start(); } } catch (ThreadAbortException) { StarryboundServer.changeState(ServerState.Crashed, "ListenerThread::runTcp", "Thread has been aborted"); } catch (Exception e) { if ((int)StarryboundServer.serverState > 3) { return; } StarryboundServer.logException("ListenerThread Exception: " + e.ToString()); StarryboundServer.changeState(ServerState.Crashed, "ListenerThread::runTcp", e.ToString()); } tcpSocket.Stop(); StarryboundServer.logFatal("ListenerThread has failed - No new connections will be possible."); } catch (ThreadAbortException) { } catch (SocketException e) { StarryboundServer.logFatal("TcpListener has failed to start: " + e.Message); StarryboundServer.serverState = ServerState.Crashed; } }
private void SourceRequest(byte[] data, EndPoint remote) { byte headerByte = data[4]; byte[] dataArray; switch (headerByte) { case 0x54: dataArray = new byte[data.Length - 6]; Buffer.BlockCopy(data, 5, dataArray, 0, dataArray.Length); string text = Encoding.UTF8.GetString(dataArray); string needle = "Source Engine Query"; if (text != needle) { StarryboundServer.logError("RCON: Received invalid A2S_INFO request: " + text + " is invalid."); return; } else { StarryboundServer.logDebug("ListenerThread::SourceRequest", "RCON: Matched A2S_INFO request!"); } try { byte header = 0x49; byte protocol = 0x02; byte[] name = encodeString(StarryboundServer.config.serverName); byte[] map = encodeString("Starbound"); byte[] folder = encodeString("na"); byte[] game = encodeString("Starbound"); byte[] appID = BitConverter.GetBytes(Convert.ToUInt16(1337)); byte players = Convert.ToByte((uint)StarryboundServer.clientCount); byte maxplayers = Convert.ToByte((uint)StarryboundServer.config.maxClients); byte bots = Convert.ToByte((uint)0); byte servertype = Convert.ToByte('d'); byte environment = Convert.ToByte((StarryboundServer.IsMono ? 'l' : 'w')); byte visibility = Convert.ToByte((uint)(StarryboundServer.config.proxyPass == "" ? 0 : 1)); byte vac = Convert.ToByte((uint)0); byte[] version = encodeString(StarryboundServer.starboundVersion.Name); var s = new MemoryStream(); s.Write(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }, 0, 4); s.WriteByte(header); s.WriteByte(protocol); s.Write(name, 0, name.Length); s.Write(map, 0, map.Length); s.Write(folder, 0, folder.Length); s.Write(game, 0, game.Length); s.Write(appID, 0, appID.Length); s.WriteByte(players); s.WriteByte(maxplayers); s.WriteByte(bots); s.WriteByte(servertype); s.WriteByte(environment); s.WriteByte(visibility); s.WriteByte(vac); s.Write(version, 0, version.Length); StarryboundServer.logInfo("RCON: Sending A2S_INFO Response packet to " + remote); udpSocket.SendTo(s.ToArray(), remote); } catch (Exception e) { StarryboundServer.logError("RCON: Unable to send data to stream! An error occurred."); StarryboundServer.logError("RCON: " + e.ToString()); } break; case 0x55: StarryboundServer.logDebug("ListenerThread::SourceRequest", "RCON: Received A2S_PLAYER request from " + remote); dataArray = new byte[4]; Buffer.BlockCopy(data, 5, dataArray, 0, dataArray.Length); if (dataArray.SequenceEqual(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF })) { var buffer = new byte[4]; new Random().NextBytes(buffer); if (challengeData.ContainsKey(remote)) { challengeData.Remove(remote); } challengeData.Add(remote, buffer); var s = new MemoryStream(); s.Write(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }, 0, 4); s.WriteByte(0x41); s.Write(buffer, 0, 4); StarryboundServer.logInfo("RCON: Sending A2S_PLAYER Challenge Response packet to " + remote); udpSocket.SendTo(s.ToArray(), remote); } else { if (!challengeData.ContainsKey(remote)) { StarryboundServer.logError("RCON: Illegal A2S_PLAYER request received from " + remote + ". No challenge number has been issued to this address."); } else { var s = new MemoryStream(); s.Write(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }, 0, 4); s.WriteByte(0x44); s.WriteByte(Convert.ToByte((uint)StarryboundServer.clientCount)); List <Client> clientList = StarryboundServer.getClients(); for (var i = 0; i < clientList.Count; i++) { Client client = clientList[i]; s.WriteByte(Convert.ToByte((uint)i)); byte[] name = encodeString(client.playerData.name); s.Write(name, 0, name.Length); byte[] score = new byte[4]; score = BitConverter.GetBytes((int)0); s.Write(score, 0, score.Length); float seconds = Utils.getTimestamp() - client.connectedTime; byte[] connected = new byte[4]; connected = BitConverter.GetBytes(seconds); s.Write(connected, 0, connected.Length); //StarryboundServer.logDebug("ListenerThread::SourceA2SPlayer", "Client ID #" + i + ": " + Utils.ByteArrayToString(new byte[] { Convert.ToByte((uint)i) }) + Utils.ByteArrayToString(name) + Utils.ByteArrayToString(score) + Utils.ByteArrayToString(connected)); } StarryboundServer.logInfo("RCON: Sending A2S_PLAYER Response packet for " + StarryboundServer.clientCount + " player(s) to " + remote); //StarryboundServer.logDebug("ListenerThread::SourceA2SPlayer", "RCON: Dump packet: " + Utils.ByteArrayToString(s.ToArray())); udpSocket.SendTo(s.ToArray(), remote); } } break; default: StarryboundServer.logError("RCON: Received unknown or unsupported header byte - " + headerByte); break; } }
public void run() { try { this.cIn = new BinaryReader(this.cSocket.GetStream()); this.cOut = new BinaryWriter(this.cSocket.GetStream()); IPEndPoint ipep = (IPEndPoint)this.cSocket.Client.RemoteEndPoint; IPAddress ipa = ipep.Address; this.playerData.ip = ipep.Address.ToString(); StarryboundServer.logInfo("[" + playerData.client + "] Accepting new connection."); if ((int)StarryboundServer.serverState < 3) { MemoryStream packet = new MemoryStream(); BinaryWriter packetWrite = new BinaryWriter(packet); packetWrite.WriteBE(StarryboundServer.ProtocolVersion); this.sendClientPacket(Packet.ProtocolVersion, packet.ToArray()); rejectPreConnected("Connection Failed: The server is not ready yet."); return; } else if ((int)StarryboundServer.serverState > 3) { MemoryStream packet = new MemoryStream(); BinaryWriter packetWrite = new BinaryWriter(packet); packetWrite.WriteBE(StarryboundServer.ProtocolVersion); this.sendClientPacket(Packet.ProtocolVersion, packet.ToArray()); rejectPreConnected("Connection Failed: The server is shutting down."); return; } else if (StarryboundServer.restartTime != 0) { MemoryStream packet = new MemoryStream(); BinaryWriter packetWrite = new BinaryWriter(packet); packetWrite.WriteBE(StarryboundServer.ProtocolVersion); this.sendClientPacket(Packet.ProtocolVersion, packet.ToArray()); rejectPreConnected("Connection Failed: The server is restarting."); return; } sSocket = new TcpClient(); sSocket.ReceiveTimeout = StarryboundServer.config.internalSocketTimeout * 1000; sSocket.SendTimeout = StarryboundServer.config.internalSocketTimeout * 1000; IAsyncResult result = sSocket.BeginConnect((StarryboundServer.config.proxyIP.Equals("0.0.0.0") ? IPAddress.Loopback : IPAddress.Parse(StarryboundServer.config.proxyIP)), StarryboundServer.config.serverPort, null, null); bool success = result.AsyncWaitHandle.WaitOne(3000, true); if (!success || !sSocket.Connected) { StarryboundServer.failedConnections++; if (StarryboundServer.failedConnections >= StarryboundServer.config.maxFailedConnections) { StarryboundServer.logFatal(StarryboundServer.failedConnections + " clients failed to connect in a row. Restarting..."); StarryboundServer.serverState = ServerState.Crashed; } MemoryStream packet = new MemoryStream(); BinaryWriter packetWrite = new BinaryWriter(packet); packetWrite.WriteBE(StarryboundServer.ProtocolVersion); this.sendClientPacket(Packet.ProtocolVersion, packet.ToArray()); rejectPreConnected("Connection Failed: Unable to connect to the parent server."); return; } this.sIn = new BinaryReader(this.sSocket.GetStream()); this.sOut = new BinaryWriter(this.sSocket.GetStream()); this.connectedTime = Utils.getTimestamp(); // Forwarding for data from SERVER (sIn) to CLIENT (cOut) this.ServerForwarder = new Thread(new ThreadStart(new ForwardThread(this, this.sIn, this.cOut, Direction.Server).run)); ServerForwarder.Start(); // Forwarding for data from CLIENT (cIn) to SERVER (sOut) this.ClientForwarder = new Thread(new ThreadStart(new ForwardThread(this, this.cIn, this.sOut, Direction.Client).run)); ClientForwarder.Start(); StarryboundServer.failedConnections = 0; } catch (Exception e) { StarryboundServer.logException("ClientThread Exception: " + e.ToString()); StarryboundServer.failedConnections++; MemoryStream packet = new MemoryStream(); BinaryWriter packetWrite = new BinaryWriter(packet); packetWrite.WriteBE(StarryboundServer.ProtocolVersion); this.sendClientPacket(Packet.ProtocolVersion, packet.ToArray()); rejectPreConnected("Connection Failed: A internal server error occurred (1)"); } }
void parseOutput(string consoleLine) { try { foreach (string line in filterConsole) { if (consoleLine.Contains(line)) { return; } } if (consoleLine.StartsWith("Error: ") || consoleLine.StartsWith("AssetException:")) { this.parseError = true; } else if ((consoleLine.StartsWith("Warn:") || consoleLine.StartsWith("Info:") || consoleLine.StartsWith("Debug:")) && this.parseError) { logStarboundError(" "); this.parseError = false; } else if (String.IsNullOrWhiteSpace(consoleLine) && this.parseError) { logStarboundError(" "); this.parseError = false; return; } if (consoleLine.StartsWith("Warn: Perf: ")) { string[] perf = consoleLine.Remove(0, 12).Split(' '); string function = perf[0]; float millis = Convert.ToSingle(perf[2]); if (millis > 5000) { StarryboundServer.logWarn("Parent Server [" + function + "] lagged for " + (millis / 1000) + " seconds"); } return; } else if (consoleLine.Contains("Info: Server version")) { string[] versionString = consoleLine.Split('\''); string versionName = versionString[1]; int protocolVersion = int.Parse(versionString[3]); StarryboundServer.starboundVersion.Protocol = protocolVersion; StarryboundServer.starboundVersion.Name = versionName; if (protocolVersion != StarryboundServer.ProtocolVersion) { StarryboundServer.logFatal("Detected protcol version [" + protocolVersion + "] != [" + StarryboundServer.ProtocolVersion + "] to expected protocol version!"); Thread.Sleep(5000); Environment.Exit(4); } StarryboundServer.logInfo("Parent Server Version: [" + versionName + "] Protocol: [" + protocolVersion + "]"); return; } else if (consoleLine.Contains("TcpServer will close, listener thread caught exception")) { StarryboundServer.logFatal("Parent Server TcpServer listener thread caught exception, Forcing a restart."); StarryboundServer.changeState(ServerState.Crashed, "ServerThread::parseOutput", "Starbound Tcp listener has crashed"); } else if (consoleLine.Contains("TcpServer listening on: ")) { StarryboundServer.changeState(ServerState.StarboundReady, "ServerThread::parseOutput"); ServerConfig.RemovePrivateConfig(); } else if (consoleLine.StartsWith("Info: Kicking client ")) { string[] kick = consoleLine.Remove(0, 21).Split(' '); string user = kick[0]; string id = kick[1]; string ip = kick[2]; StarryboundServer.logWarn("Parent Server disconnected " + user + " " + ip + " for inactivity."); return; } if (!this.parseError) { Console.WriteLine("[STAR] " + consoleLine); } else { logStarboundError(consoleLine); } } catch (Exception) { } }