public void runUdp() { try { IPAddress localAdd = IPAddress.Parse(StarryboundServer.config.proxyIP); udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint ipEndPoint = new IPEndPoint(localAdd, StarryboundServer.config.proxyPort); udpSocket.Bind(ipEndPoint); IPEndPoint ipeSender = new IPEndPoint(IPAddress.Any, 0); //The epSender identifies the incoming clients EndPoint epSender = (EndPoint)ipeSender; StarryboundServer.logInfo("RCON listener has been started on UDP " + localAdd.ToString() + ":" + StarryboundServer.config.proxyPort); while (true) { int bytesRead = udpSocket.ReceiveFrom(udpByteData, ref epSender); StarryboundServer.logInfo("Receiving RCON Data..."); OnReceive(udpByteData, bytesRead, epSender); } } catch (Exception e) { StarryboundServer.logError("Something went wrong while trying to setup the UDP listener. " + e.ToString()); } }
private void OnReceive(byte[] dataBuffer, int bytesRead, EndPoint remote) { byte[] data = new byte[bytesRead]; try { Buffer.BlockCopy(dataBuffer, 0, data, 0, bytesRead); /* * Source Query packets begin with 0xFF (x4) */ if (bytesRead > 4) { byte[] sourceCheck = new byte[] { data[0], data[1], data[2], data[3] }; if (sourceCheck.SequenceEqual(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF })) { SourceRequest(data, remote); return; } } string text = Encoding.UTF8.GetString(data, 0, bytesRead); StarryboundServer.logInfo(String.Format("RCON: Received non-source request of {0} bytes from {1}: {2}", bytesRead, remote, text)); } catch (Exception e) { StarryboundServer.logError("Bad RCON request received. " + e.ToString()); StarryboundServer.logError("RCON: Binary data: " + Utils.ByteArrayToString(data)); } }
public static int[] GetSpamSettings() { if (!StarryboundServer.config.enableSpamProtection) { return new int[] { 0, 0 } } ; string[] spamSplit = StarryboundServer.config.spamInterval.Split(':'); try { int numMessages = int.Parse(spamSplit[0]); int numSeconds = int.Parse(spamSplit[1]); return(new int[] { numMessages, numSeconds }); } catch (Exception) { StarryboundServer.logError("Unable to read settings for anti-spam system - Is it in numMessages:numSeconds format?"); return(new int[] { 0, 0 }); } }
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; } }