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; } }