Пример #1
0
 public static void SetupConfig()
 {
     try
     {
         if (File.Exists(ConfigPath))
         {
             StarryboundServer.serverConfig = ServerFile.Read(ConfigPath);
         }
         StarryboundServer.serverConfig.gamePort        = StarryboundServer.config.serverPort;
         StarryboundServer.privatePassword              = Utils.GenerateSecureSalt();
         StarryboundServer.serverConfig.serverPasswords = new string[] { StarryboundServer.privatePassword };
         StarryboundServer.serverConfig.maxPlayers      = StarryboundServer.config.maxClients + 10;
         StarryboundServer.serverConfig.bind            = StarryboundServer.config.proxyIP;
         if (StarryboundServer.serverConfig.useDefaultWorldCoordinate)
         {
             string[] spawnPlanet = StarryboundServer.serverConfig.defaultWorldCoordinate.Split(':');
             if (spawnPlanet.Length == 5)
             {
                 StarryboundServer.spawnPlanet = new WorldCoordinate(spawnPlanet[0], Convert.ToInt32(spawnPlanet[1]), Convert.ToInt32(spawnPlanet[2]), Convert.ToInt32(spawnPlanet[3]), Convert.ToInt32(spawnPlanet[4]), 0);
             }
             else
             {
                 StarryboundServer.spawnPlanet = new WorldCoordinate(spawnPlanet[0], Convert.ToInt32(spawnPlanet[1]), Convert.ToInt32(spawnPlanet[2]), Convert.ToInt32(spawnPlanet[3]), Convert.ToInt32(spawnPlanet[4]), Convert.ToInt32(spawnPlanet[5]));
             }
         }
         StarryboundServer.serverConfig.Write(ConfigPath);
     }
     catch (Exception e)
     {
         StarryboundServer.logFatal("Failed to parse starbound.config: " + e.ToString());
         Thread.Sleep(5000);
         Environment.Exit(8);
     }
 }
Пример #2
0
        public void run()
        {
            var executableName = "starbound_server" + (StarryboundServer.IsMono ? "" : ".exe");

            try
            {
                ProcessStartInfo startInfo = new ProcessStartInfo(executableName)
                {
                    WindowStyle            = ProcessWindowStyle.Hidden,
                    UseShellExecute        = false,
                    RedirectStandardOutput = true,
                    CreateNoWindow         = true
                };
                process = Process.Start(startInfo);
                StarryboundServer.parentProcessId = process.Id;
                File.WriteAllText("starbound_server.pid", process.Id.ToString());
                process.OutputDataReceived += (sender, e) => parseOutput(e.Data);
                process.ErrorDataReceived  += (sender, e) => logStarboundError("ErrorDataReceived from starbound_server.exe: " + e.Data);
                process.BeginOutputReadLine();
                process.WaitForExit();

                StarryboundServer.changeState(ServerState.Crashed, "ServerThread::run", "starbound_server.exe process has exited.");
            }
            catch (ThreadAbortException) { }
            catch (Exception e)
            {
                StarryboundServer.changeState(ServerState.Crashed, "ServerThread::run::Exception", e.ToString());
            }
        }
Пример #3
0
        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());
            }
        }
Пример #4
0
        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));
            }
        }
Пример #5
0
        public static void LoadClaims()
        {
            try
            {
                String claimPath = Path.Combine(StarryboundServer.SavePath, "claims.json");
                StarryboundServer.logInfo("Loading players claims from file " + claimPath);
                if (File.Exists(claimPath))
                {
                    String serializedData = String.Empty;
                    using (StreamReader rdr = new StreamReader(claimPath))
                    {
                        serializedData = rdr.ReadLine();
                    }
                    if (!String.IsNullOrEmpty(serializedData))
                    {
                        _playerToSystem = Newtonsoft.Json.JsonConvert.DeserializeObject <Dictionary <String, List <Extensions.WorldCoordinate> > >(serializedData);
                    }

                    foreach (String plyUUID in _playerToSystem.Keys)
                    {
                        foreach (Extensions.WorldCoordinate coord in _playerToSystem[plyUUID])
                        {
                            _SystemToPlayer.Add(coord, plyUUID);
                        }
                    }
                }
            } catch (Exception e)
            {
                StarryboundServer.logException("Unable to load claims from claims.json: {0}", e.Message);
            }
        }
Пример #6
0
 public static bool ReleaseClaim(PlayerData player, Extensions.WorldCoordinate loc)
 {
     try
     {
         stakeClaimMutex.WaitOne();
         if (_SystemToPlayer.ContainsKey(loc))
         {
             if (_SystemToPlayer[loc] == player.name)
             {
                 _SystemToPlayer.Remove(loc);
                 _playerToSystem[player.name].Remove(loc);
                 SaveClaims();
                 stakeClaimMutex.ReleaseMutex();
                 return(true);
             }
         }
     }
     catch (Exception e)
     {
         StarryboundServer.logException("Could not release claim to location {0} for player {1}", loc, player.uuid);
         stakeClaimMutex.ReleaseMutex();
         return(false);
     }
     return(false);
 }
Пример #7
0
        public static void ProcessBans()
        {
            readLegacyBans();
            List <Ban> bans = Read(Path.Combine(StarryboundServer.SavePath, "bans.json"));

            foreach (Ban ban in bans)
            {
                allBans.Add(ban.banID, ban);
                nextBanID = ban.banID + 1;
            }

            foreach (Ban lBan in legacyBans.Values)
            {
                if (!allBans.ContainsKey(lBan.banID))
                {
                    allBans.Add(lBan.banID, lBan);
                }
            }

            int removedCount = 0;

            foreach (Ban ban in allBans.Values)
            {
                if (ban.hasExpired())
                {
                    ban.remove(); removedCount++;
                }
            }

            Write(Path.Combine(StarryboundServer.SavePath, "bans.json"));

            StarryboundServer.logInfo(allBans.Count + " ban(s) have been loaded from file. " + removedCount + " ban(s) have expired and been removed.");
        }
Пример #8
0
        public static void SetupConfig()
        {
            CreateIfNot(RulesPath, "1) Respect all players 2) No griefing/hacking 3) Have fun!");
            CreateIfNot(MotdPath, "This server is running Starrybound Server v%versionNum%. Type /help for a list of commands. There are currently %players% player(s) online.");

            StarryboundServer.motdData  = ReadConfigFile(MotdPath);
            StarryboundServer.rulesData = ReadConfigFile(RulesPath);

            if (File.Exists(ConfigPath))
            {
                StarryboundServer.config = ConfigFile.Read(ConfigPath);
            }

            if (StarryboundServer.IsMono && StarryboundServer.config == null)
            {
                StarryboundServer.config = new ConfigFile();
            }

            StarryboundServer.config.Write(ConfigPath);

#if DEBUG
            StarryboundServer.config.logLevel = LogType.Debug;
            StarryboundServer.logDebug("SetupConfig", "This was compiled in DEBUG, forcing debug logging!");
#endif
        }
Пример #9
0
        public bool checkTrigger(int count, Client client)
        {
            if (count == countToTrigger)
            {
                PlayerData player = client.playerData;

                switch (actionName)
                {
                case "mute":
                    player.isMuted = true;
                    StarryboundServer.sendGlobalMessage("^#f75d5d;" + player.name + " has been muted automatically for spamming.");
                    break;

                case "kick":
                    client.kickClient(reason);
                    break;

                case "ban":
                    if (length != 0)
                    {
                        length = Utils.getTimestamp() + (length * 60);
                    }

                    Bans.addNewBan(player.name, player.uuid, player.ip, Utils.getTimestamp(), "[SYSTEM]", length, reason);

                    client.banClient(reason);
                    break;
                }

                return(true);
            }

            return(false);
        }
Пример #10
0
        public static bool addNewBan(string username, string uuid, string ipaddress, int timeBanned, string admin, int expiry, string reason)
        {
            string[] args = new string[8];

            args[0] = nextBanID.ToString();
            args[1] = username;
            args[2] = uuid;
            args[3] = ipaddress;
            args[4] = timeBanned.ToString();
            args[5] = admin;
            args[6] = expiry.ToString();
            args[7] = reason;

            try
            {
                Ban ban = new Ban(nextBanID, username, uuid, ipaddress, timeBanned, admin, expiry, reason);

                allBans.Add(nextBanID, ban);

                Write(Path.Combine(StarryboundServer.SavePath, "bans.json"));

                nextBanID++;
            }
            catch (Exception e) {
                StarryboundServer.logException("Unable to write ban to banned-players.txt: " + e.Message);
                return(false);
            }

            return(true);
        }
Пример #11
0
 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);
 }
Пример #12
0
 public static ServerFile Read(Stream stream)
 {
     try
     {
         DataContractJsonSerializer str = new DataContractJsonSerializer(StarryboundServer.serverConfig.GetType());
         return(str.ReadObject(stream) as ServerFile);
     }
     catch (Exception)
     {
         StarryboundServer.logException("Starbound server config is unreadable - Re-creating config with default values");
         return(new ServerFile());
     }
 }
Пример #13
0
        public static void SaveClaims()
        {
            try
            {
                using (StreamWriter wtr = new StreamWriter(Path.Combine(StarryboundServer.SavePath, "claims.json")))
                    wtr.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(_playerToSystem));
            }catch (Exception e)
            {
                StarryboundServer.logException("Unable to write claims to claims.json: {0}", e.Message);
            }

            return;
        }
Пример #14
0
        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);
            }
        }
Пример #15
0
 public static ConfigFile Read(Stream stream)
 {
     try
     {
         using (var sr = new StreamReader(stream))
         {
             return(JsonConvert.DeserializeObject <ConfigFile>(sr.ReadToEnd()));
         }
     }
     catch (Exception)
     {
         StarryboundServer.logException("Starrybound config is unreadable - Re-creating config with default values");
         return(new ConfigFile());
     }
 }
Пример #16
0
 public static List <Ban> Read(Stream stream)
 {
     try
     {
         using (var sr = new StreamReader(stream))
         {
             return(JsonConvert.DeserializeObject <List <Ban> >(sr.ReadToEnd()));
         }
     }
     catch (Exception)
     {
         StarryboundServer.logException("Server ban file is not readable - Bans WILL NOT operate until this issue is fixed.");
         writeBans = false;
         return(new List <Ban>());
     }
 }
Пример #17
0
 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) { }
 }
Пример #18
0
        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;
            }
        }
Пример #19
0
        public bool canIBuild()
        {
            if (StarryboundServer.serverConfig.useDefaultWorldCoordinate && StarryboundServer.config.spawnWorldProtection)
            {
                if (loc != null)
                {
                    if ((StarryboundServer.spawnPlanet.Equals(loc)) && !group.hasPermission("admin.spawnbuild") && !inPlayerShip)
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
            }
            else if (!hasPermission("world.build"))
            {
                return(false);
            }
            else if (!canBuild)
            {
                return(false);
            }
            if (this.hasPermission("admin.ignoreshipaccess"))
            {
                return(true);                                              //Admins can ignore claims
            }
            var player = Claims.GetStakeOwner(loc);

            if (player == this.name)
            {
                return(true);
            }
            if (player != null)
            {
                List <String> whiteList = StarryboundServer.getClientWhitelist(player);

                if (!whiteList.Contains(this.name))
                {
                    return(false);                                //Players need to specificly whitelist players to ignore claims
                }
            }
            return(true);
        }
Пример #20
0
        public static BootstrapFile Read(Stream stream)
        {
            try
            {
                using (var sr = new StreamReader(stream))
                {
                    return(JsonConvert.DeserializeObject <BootstrapFile>(sr.ReadToEnd()));
                }
            }
            catch (Exception)
            {
                StarryboundServer.logFatal("bootstrap.config file is unreadable. The server start cannot continue.");
                Thread.Sleep(5000);
                Environment.Exit(6);
            }

            return(null);
        }
Пример #21
0
        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 });
            }
        }
Пример #22
0
        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) { }
        }
Пример #23
0
        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)");
            }
        }
Пример #24
0
        public static void readLegacyBans()
        {
            try
            {
                StreamReader reader = File.OpenText(Path.Combine(StarryboundServer.SavePath, "banned-players.txt"));
                string       line;
                int          banCount = 0;
                while ((line = reader.ReadLine()) != null)
                {
                    string[] args = line.Split('|');

                    /*
                     * Ban format:
                     * int          ID
                     * string       Username
                     * string       UUID
                     * string       IP Address
                     * timestamp    UnixTimestamp (Time of Addition)
                     * string       Admin
                     * timestamp    Expiry
                     * string       Reason
                     *
                     * Example:
                     * 2|User|133bfef193364620513ea1980ba39dc3|127.0.0.1|1387767903|Crashdoom|0|Griefing the spawn
                     *
                     */

                    if (args.Length != 8)
                    {
                        continue;
                    }

                    try
                    {
                        int    banID      = int.Parse(args[0]);
                        string username   = args[1];
                        string uuid       = args[2];
                        string ipaddress  = args[3];
                        int    timeBanned = int.Parse(args[4]);
                        string admin      = args[5];
                        int    expiry     = int.Parse(args[6]);
                        string reason     = args[7];

                        Ban ban = new Ban(banID, username, uuid, ipaddress, timeBanned, admin, expiry, reason);

                        legacyBans.Add(banID, ban);

                        nextBanID = banID + 1;

                        banCount++;
                    }
                    catch (Exception) { banCount--; StarryboundServer.logWarn("Invalid ban detected in banned-players.txt"); }
                }

                reader.Close();
            }
            catch (Exception e)
            {
                StarryboundServer.logWarn("Unable to read bans from legacy banned-players.txt: " + e.Message);
            }
        }
Пример #25
0
        public void run()
        {
            try
            {
                for (;;)
                {
                    if (!this.client.connectionAlive)
                    {
                        this.client.forceDisconnect(direction, "Connection no longer alive");
                        return;
                    }


                    if (this.client.kickTargetTimestamp != 0)
                    {
                        if (this.client.kickTargetTimestamp < Utils.getTimestamp())
                        {
                            this.client.closeConnection();
                            return;
                        }
                        continue;
                    }

                    #region Process Packet
                    //Packet ID and Vaildity Check.
                    uint temp = this.incoming.ReadVarUInt32();
                    if (temp < 0 || temp > 48)
                    {
                        this.client.forceDisconnect(direction, "Sent invalid packet ID [" + temp + "].");
                        return;
                    }
                    Packet packetID = (Packet)temp;

                    //Packet Size and Compression Check.
                    bool compressed = false;
                    int  packetSize = this.incoming.ReadVarInt32();
                    if (packetSize < 0)
                    {
                        packetSize = -packetSize;
                        compressed = true;
                    }

                    //Create buffer for forwarding
                    byte[] dataBuffer = this.incoming.ReadFully(packetSize);

                    //Do decompression
                    MemoryStream ms = new MemoryStream();
                    if (compressed)
                    {
                        ZlibStream compressedStream = new ZlibStream(new MemoryStream(dataBuffer), CompressionMode.Decompress);
                        byte[]     buffer           = new byte[32768];
                        for (;;)
                        {
                            int read = compressedStream.Read(buffer, 0, buffer.Length);
                            if (read <= 0)
                            {
                                break;
                            }
                            ms.Write(buffer, 0, read);
                        }
                        ms.Seek(0, SeekOrigin.Begin);
                    }
                    else
                    {
                        ms = new MemoryStream(dataBuffer);
                    }

                    //Create packet parser
                    BinaryReader packetData = new BinaryReader(ms);
                    #endregion

                    //Return data for packet processor
                    object returnData = true;

                    if (packetID != Packet.Heartbeat && packetID != Packet.UniverseTimeUpdate)
                    {
                        if (direction == Direction.Client)
                        #region Handle Client Packets
                        {
                            #region Protocol State Security
                            ClientState curState = this.client.state;
                            if (curState != ClientState.Connected)
                            {
                                if (curState == ClientState.PendingConnect && packetID != Packet.ClientConnect)
                                {
                                    this.client.rejectPreConnected("Violated PendingConnect protocol state with " + packetID);
                                    return;
                                }
                                else if (curState == ClientState.PendingAuthentication && packetID != Packet.HandshakeResponse)
                                {
                                    this.client.rejectPreConnected("Violated PendingAuthentication protocol state with " + packetID);
                                    return;
                                }
                                else if (curState == ClientState.PendingConnectResponse)
                                {
                                    int startTime = Utils.getTimestamp();
                                    while (true)
                                    {
                                        if (this.client.state == ClientState.Connected)
                                        {
                                            break;
                                        }
                                        if (Utils.getTimestamp() > startTime + StarryboundServer.config.connectTimeout)
                                        {
                                            this.client.rejectPreConnected("Connection Failed: Server did not respond in time.");
                                            return;
                                        }
                                    }
                                }
                            }
                            #endregion

                            if (packetID == Packet.ChatSend)
                            {
                                returnData = new Packet11ChatSend(this.client, packetData, this.direction).onReceive();
                            }
                            else if (packetID == Packet.ClientConnect)
                            {
                                this.client.state = ClientState.PendingAuthentication;
                                returnData        = new Packet7ClientConnect(this.client, packetData, this.direction).onReceive();
                                MemoryStream packet      = new MemoryStream();
                                BinaryWriter packetWrite = new BinaryWriter(packet);

                                passwordSalt = Utils.GenerateSecureSalt();
                                packetWrite.WriteStarString("");
                                packetWrite.WriteStarString(passwordSalt);
                                packetWrite.WriteBE(StarryboundServer.config.passwordRounds);
                                this.client.sendClientPacket(Packet.HandshakeChallenge, packet.ToArray());
                            }
                            else if (packetID == Packet.HandshakeResponse)
                            {
                                string claimResponse = packetData.ReadStarString();
                                string passwordHash  = packetData.ReadStarString();

                                string verifyHash = Utils.StarHashPassword(StarryboundServer.config.proxyPass, this.client.playerData.account + passwordSalt, StarryboundServer.config.passwordRounds);
                                if (passwordHash != verifyHash)
                                {
                                    this.client.rejectPreConnected("Your password was incorrect.");
                                    return;
                                }

                                this.client.state = ClientState.PendingConnectResponse;
                                returnData        = false;
                            }
                            else if (packetID == Packet.WarpCommand)
                            {
                                WarpType        cmd    = (WarpType)packetData.ReadUInt32BE();
                                WorldCoordinate coord  = packetData.ReadStarWorldCoordinate();
                                string          player = packetData.ReadStarString();
                                if (cmd == WarpType.WarpToPlayerShip)
                                {
                                    Client target = StarryboundServer.getClient(player);
                                    if (target != null)
                                    {
                                        if (!this.client.playerData.canAccessShip(target.playerData))
                                        {
                                            this.client.sendChatMessage("^#5dc4f4;You cannot access this player's ship due to their ship access settings.");
                                            StarryboundServer.logDebug("ShipAccess", "Preventing " + this.client.playerData.name + " from accessing " + target.playerData.name + "'s ship.");
                                            MemoryStream packetWarp  = new MemoryStream();
                                            BinaryWriter packetWrite = new BinaryWriter(packetWarp);
                                            packetWrite.WriteBE((uint)WarpType.WarpToOwnShip);
                                            packetWrite.Write(new WorldCoordinate());
                                            packetWrite.WriteStarString("");
                                            client.sendServerPacket(Packet.WarpCommand, packetWarp.ToArray());
                                            returnData = false;
                                        }
                                        else
                                        {
                                            this.client.playerData.inPlayerShip = true;
                                        }
                                    }
                                }
                                else if (cmd == WarpType.WarpToOwnShip)
                                {
                                    this.client.playerData.inPlayerShip = true;
                                }
                                else
                                {
                                    this.client.playerData.inPlayerShip = false;
                                }
                                StarryboundServer.logDebug("WarpCommand", "[" + this.client.playerData.client + "][" + cmd + "]" + (coord != null ? "[" + coord.ToString() + "]" : "") + "[" + player + "] inPlayerShip:" + this.client.playerData.inPlayerShip);
                            }
                            else if (packetID == Packet.ModifyTileList || packetID == Packet.DamageTileGroup || packetID == Packet.DamageTile || packetID == Packet.ConnectWire || packetID == Packet.DisconnectAllWires)
                            {
                                if (!this.client.playerData.canIBuild())
                                {
                                    returnData = false;
                                }
                            }
                            else if (packetID == Packet.EntityCreate)
                            {
                                while (true)
                                {
                                    EntityType type = (EntityType)packetData.Read();
                                    if (type == EntityType.EOF)
                                    {
                                        break;
                                    }
                                    byte[] entityData = packetData.ReadStarByteArray();
                                    int    entityId   = packetData.ReadVarInt32();
                                    if (type == EntityType.Projectile)
                                    {
                                        BinaryReader entity        = new BinaryReader(new MemoryStream(entityData));
                                        string       projectileKey = entity.ReadStarString();
                                        object       projParams    = entity.ReadStarVariant();
                                        if (StarryboundServer.config.projectileBlacklist.Contains(projectileKey))
                                        {
                                            MemoryStream packet      = new MemoryStream();
                                            BinaryWriter packetWrite = new BinaryWriter(packet);
                                            packetWrite.WriteVarInt32(entityId);
                                            packetWrite.Write(false);
                                            this.client.sendClientPacket(Packet.EntityDestroy, packet.ToArray());
                                            returnData = false;
                                        }
                                        if (StarryboundServer.serverConfig.useDefaultWorldCoordinate && StarryboundServer.config.spawnWorldProtection)
                                        {
                                            if (this.client.playerData.loc != null)
                                            {
                                                if (StarryboundServer.config.projectileBlacklistSpawn.Contains(projectileKey) ^ StarryboundServer.config.projectileSpawnListIsWhitelist)
                                                {
                                                    if (StarryboundServer.spawnPlanet.Equals(this.client.playerData.loc) && !this.client.playerData.group.hasPermission("admin.spawnbuild") && !this.client.playerData.inPlayerShip)
                                                    {
                                                        MemoryStream packet      = new MemoryStream();
                                                        BinaryWriter packetWrite = new BinaryWriter(packet);
                                                        packetWrite.WriteVarInt32(entityId);
                                                        packetWrite.Write(false);
                                                        this.client.sendClientPacket(Packet.EntityDestroy, packet.ToArray());
                                                        returnData = false;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                MemoryStream packet      = new MemoryStream();
                                                BinaryWriter packetWrite = new BinaryWriter(packet);
                                                packetWrite.WriteVarInt32(entityId);
                                                packetWrite.Write(false);
                                                this.client.sendClientPacket(Packet.EntityDestroy, packet.ToArray());
                                                returnData = false;
                                            }
                                        }
                                    }
                                    else if (type == EntityType.Object || type == EntityType.Plant || type == EntityType.PlantDrop || type == EntityType.Monster)
                                    {
                                        if (!this.client.playerData.canIBuild())
                                        {
                                            MemoryStream packet      = new MemoryStream();
                                            BinaryWriter packetWrite = new BinaryWriter(packet);
                                            packetWrite.WriteVarInt32(entityId);
                                            packetWrite.Write(false);
                                            this.client.sendClientPacket(Packet.EntityDestroy, packet.ToArray());
                                            returnData = false;
                                        }
                                    }
                                }
                            }
                            else if (packetID == Packet.SpawnEntity)
                            {
                                while (true)
                                {
                                    EntityType type = (EntityType)packetData.Read();
                                    if (type == EntityType.EOF)
                                    {
                                        break;
                                    }
                                    byte[] entityData = packetData.ReadStarByteArray();
                                    if (type == EntityType.Projectile)
                                    {
                                        BinaryReader entity        = new BinaryReader(new MemoryStream(entityData));
                                        string       projectileKey = entity.ReadStarString();
                                        object       projParams    = entity.ReadStarVariant();
                                        if (StarryboundServer.config.projectileBlacklist.Contains(projectileKey))
                                        {
                                            returnData = false;
                                        }
                                        if (StarryboundServer.serverConfig.useDefaultWorldCoordinate && StarryboundServer.config.spawnWorldProtection)
                                        {
                                            if (this.client.playerData.loc != null)
                                            {
                                                if (StarryboundServer.config.projectileBlacklistSpawn.Contains(projectileKey) ^ StarryboundServer.config.projectileSpawnListIsWhitelist)
                                                {
                                                    if (StarryboundServer.spawnPlanet.Equals(this.client.playerData.loc) && !this.client.playerData.group.hasPermission("admin.spawnbuild") && !this.client.playerData.inPlayerShip)
                                                    {
                                                        returnData = false;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                returnData = false;
                                            }
                                        }
                                    }
                                    else if (type == EntityType.Object || type == EntityType.Plant || type == EntityType.PlantDrop || type == EntityType.Monster)
                                    {
                                        if (!this.client.playerData.canIBuild())
                                        {
                                            returnData = false;
                                        }
                                    }
                                }
                            }
                        }
                        #endregion
                        else
                        #region Handle Server Packets
                        {
                            if (packetID == Packet.ChatReceive)
                            {
                                returnData = new Packet5ChatReceive(this.client, packetData, this.direction).onReceive();
                            }
                            else if (packetID == Packet.ProtocolVersion)
                            {
                                uint protocolVersion = packetData.ReadUInt32BE();
                                if (protocolVersion != StarryboundServer.ProtocolVersion)
                                {
                                    MemoryStream packet      = new MemoryStream();
                                    BinaryWriter packetWrite = new BinaryWriter(packet);
                                    packetWrite.WriteBE(protocolVersion);
                                    this.client.sendClientPacket(Packet.ProtocolVersion, packet.ToArray());

                                    this.client.rejectPreConnected("Connection Failed: Unable to handle parent server protocol version.");
                                    return;
                                }
                            }
                            else if (packetID == Packet.HandshakeChallenge)
                            {
                                string claimMessage   = packetData.ReadString();
                                string passwordSalt   = packetData.ReadStarString();
                                int    passwordRounds = packetData.ReadInt32BE();

                                MemoryStream packet       = new MemoryStream();
                                BinaryWriter packetWrite  = new BinaryWriter(packet);
                                string       passwordHash = Utils.StarHashPassword(StarryboundServer.privatePassword, passwordSalt, passwordRounds);
                                packetWrite.WriteStarString("");
                                packetWrite.WriteStarString(passwordHash);
                                this.client.sendServerPacket(Packet.HandshakeResponse, packet.ToArray());

                                returnData = false;
                            }
                            else if (packetID == Packet.ConnectResponse)
                            {
                                int startTime = Utils.getTimestamp();
                                while (true)
                                {
                                    if (this.client.state == ClientState.PendingConnectResponse)
                                    {
                                        break;
                                    }
                                    if (Utils.getTimestamp() > startTime + StarryboundServer.config.connectTimeout)
                                    {
                                        this.client.rejectPreConnected("Connection Failed: Client did not respond with handshake.");
                                        return;
                                    }
                                }
                                returnData = new Packet2ConnectResponse(this.client, packetData, this.direction).onReceive();
                            }
                            else if (packetID == Packet.WorldStart)
                            {
                                if (!this.client.playerData.sentMotd)
                                {
                                    this.client.sendChatMessage(Config.GetMotd());

                                    if (!this.client.playerData.group.hasPermission("world.build"))
                                    {
                                        this.client.sendChatMessage("^#f75d5d;" + StarryboundServer.config.buildErrorMessage);
                                    }

                                    this.client.playerData.sentMotd = true;
                                }

                                var    unk4          = packetData.ReadStarVariant();
                                var    unk3          = packetData.ReadStarVariant();
                                byte[] unk1          = packetData.ReadStarByteArray();
                                byte[] unk2          = packetData.ReadStarByteArray();
                                float  spawnX        = packetData.ReadSingleBE();
                                float  spawnY        = packetData.ReadSingleBE();
                                var    mapParamsSize = packetData.ReadStarVariant();

                                /*
                                 * for (int i = 0; i < mapParamsSize; i++)
                                 * {
                                 *  string key = packetData.ReadStarString();
                                 *  var value = packetData.ReadStarVariant();
                                 *  mapParams.Add(key, value);
                                 *  if(key == "fuel.level")
                                 *  {
                                 *      isPlayerShip++;
                                 *  }
                                 *  else if(key == "fuel.max")
                                 *  {
                                 *      isPlayerShip++;
                                 *  }
                                 * }
                                 * this.client.playerData.inPlayerShip = (isPlayerShip == 2);
                                 */
                                uint            clientID      = packetData.ReadUInt32BE();
                                bool            interpolation = packetData.ReadBoolean();
                                WorldCoordinate coords        = Utils.findGlobalCoords(unk1);
                                if (coords != null)
                                {
                                    this.client.playerData.loc = coords;
                                    StarryboundServer.logDebug("WorldStart", "[" + this.client.playerData.client + "][" + interpolation + ":" + clientID + "] CurLoc:[" + this.client.playerData.loc.ToString() + "][" + this.client.playerData.inPlayerShip + "]");
                                }
                                else
                                {
                                    StarryboundServer.logDebug("WorldStart", "[" + this.client.playerData.client + "][" + interpolation + ":" + clientID + "] InPlayerShip:[" + this.client.playerData.inPlayerShip + "]");
                                }
                            }
                            else if (packetID == Packet.WorldStop)
                            {
                                string status = packetData.ReadStarString();
                            }
                            else if (packetID == Packet.GiveItem)
                            {
                                string name     = packetData.ReadStarString();
                                uint   count    = packetData.ReadVarUInt32();
                                var    itemDesc = packetData.ReadStarVariant();
                            }
                            else if (packetID == Packet.EnvironmentUpdate)
                            {
                                byte[] sky           = packetData.ReadStarByteArray();
                                byte[] serverWeather = packetData.ReadStarByteArray();
                                if (this.client.playerData.loc == null)
                                {
                                    WorldCoordinate coords = Utils.findGlobalCoords(sky);
                                    if (coords != null)
                                    {
                                        this.client.playerData.loc = coords;
                                        StarryboundServer.logDebug("EnvUpdate", "[" + this.client.playerData.client + "] CurLoc:[" + this.client.playerData.loc.ToString() + "]");
                                    }
                                }
                            }
                            else if (packetID == Packet.ClientContextUpdate)
                            {
                                try
                                {
                                    byte[] clientContextData = packetData.ReadStarByteArray();
                                    if (clientContextData.Length != 0)
                                    {
                                        BinaryReader clientContextReader = new BinaryReader(new MemoryStream(clientContextData));
                                        byte[]       data = clientContextReader.ReadStarByteArray();
                                        if (data.Length > 8) //Should at least be more than 8 bytes for it to contain the data we want.
                                        {
                                            BinaryReader dataReader       = new BinaryReader(new MemoryStream(data));
                                            byte         dataBufferLength = dataReader.ReadByte();
                                            if (dataBufferLength == 2)
                                            {
                                                byte arrayLength = dataReader.ReadByte();
                                                if (arrayLength == 2 || arrayLength == 4)  //Only observed these being used so far for what we want.
                                                {
                                                    byte dataType = dataReader.ReadByte(); //04 = String, 0E = CelestialLog
                                                    if (dataType == 4)
                                                    {
                                                        string string1 = dataReader.ReadStarString();
                                                        if (dataReader.BaseStream.Position != dataReader.BaseStream.Length)
                                                        {
                                                            if (string1 == "null")
                                                            {
                                                                byte[] worldHeader = dataReader.ReadStarByteArray(); //0008020A000C
                                                                byte[] worldData   = dataReader.ReadStarByteArray();
                                                                byte   typeByte    = dataReader.ReadByte();          //0E = CelestialLog
                                                                if (typeByte == 14)
                                                                {
                                                                    Dictionary <string, WorldCoordinate> log = dataReader.ReadStarCelestialLog();
                                                                    log.TryGetValue("loc", out this.client.playerData.loc);
                                                                    if (!log.TryGetValue("home", out this.client.playerData.home))
                                                                    {
                                                                        this.client.playerData.home = this.client.playerData.loc;
                                                                    }
                                                                    StarryboundServer.logDebug("ClientContext", "[" + this.client.playerData.client + "] CurLoc:[" + this.client.playerData.loc.ToString() + "][" + this.client.playerData.inPlayerShip + "]");
                                                                    StarryboundServer.logDebug("ClientContext", "[" + this.client.playerData.client + "] CurHome:[" + this.client.playerData.home.ToString() + "]");
                                                                }
                                                            }
                                                        }
                                                    }
                                                    else if (dataType == 14)
                                                    {
                                                        Dictionary <string, WorldCoordinate> log = dataReader.ReadStarCelestialLog();
                                                        log.TryGetValue("loc", out this.client.playerData.loc);
                                                        if (!log.TryGetValue("home", out this.client.playerData.home))
                                                        {
                                                            this.client.playerData.home = this.client.playerData.loc;
                                                        }
                                                        StarryboundServer.logDebug("ClientContext", "[" + this.client.playerData.client + "] CurLoc:[" + this.client.playerData.loc.ToString() + "][" + this.client.playerData.inPlayerShip + "]");
                                                        StarryboundServer.logDebug("ClientContext", "[" + this.client.playerData.client + "] CurHome:[" + this.client.playerData.home.ToString() + "]");
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    StarryboundServer.logDebug("ClientContext", "[" + this.client.playerData.client + "] Failed to parse ClientContextUpdate from Server: " + e.ToString());
                                }
                            }
                            else if (packetID == Packet.EntityCreate)
                            {
                                MemoryStream sendStream = new MemoryStream();
                                BinaryWriter sendWriter = new BinaryWriter(sendStream);
                                bool         test       = true;
                                while (true)
                                {
                                    EntityType type = (EntityType)packetData.Read();
                                    if (type == EntityType.EOF)
                                    {
                                        break;
                                    }
                                    byte[] entityData = packetData.ReadStarByteArray();
                                    int    entityId   = packetData.ReadVarInt32();
                                    if (type == EntityType.Player)
                                    {
                                        byte[] buffer = new byte[16];
                                        Buffer.BlockCopy(entityData, 0, buffer, 0, 16);
                                        buffer = Utils.HashUUID(buffer);
                                        Buffer.BlockCopy(buffer, 0, entityData, 0, 16);
                                        returnData = test = false;
                                    }
                                    sendWriter.Write((byte)type);
                                    sendWriter.WriteVarUInt64((ulong)entityData.Length);
                                    sendWriter.Write(entityData);
                                    sendWriter.WriteVarInt32(entityId);
                                }
                                if (test == false)
                                {
                                    this.outgoing.WriteVarUInt32((uint)packetID);
                                    this.outgoing.WriteVarInt32((int)sendStream.Length);
                                    this.outgoing.Write(sendStream.ToArray());
                                    this.outgoing.Flush();
                                }
                            }
                        }
                        #endregion
                    }

                    //Check return data
                    if (returnData is Boolean)
                    {
                        if ((Boolean)returnData == false)
                        {
                            continue;
                        }
                    }
                    else if (returnData is int)
                    {
                        if ((int)returnData == -1)
                        {
                            this.client.forceDisconnect(direction, "Command processor requested to drop client");
                            return;
                        }
                    }

                    #region Forward Packet
                    //Write data to dest
                    this.outgoing.WriteVarUInt32((uint)packetID);
                    if (compressed)
                    {
                        this.outgoing.WriteVarInt32(-packetSize);
                        this.outgoing.Write(dataBuffer, 0, packetSize);
                    }
                    else
                    {
                        this.outgoing.WriteVarInt32(packetSize);
                        this.outgoing.Write(dataBuffer, 0, packetSize);
                    }
                    this.outgoing.Flush();
                    #endregion

                    #region Inject from Packet Queue
                    var chatbuffer = this.client.packetQueue;
                    foreach (Packet11ChatSend chatPacket in chatbuffer)
                    {
                        chatPacket.onSend();
                    }

                    this.client.packetQueue = new List <Packet11ChatSend>();
                    #endregion

                    //If disconnect was forwarded to client, lets disconnect.
                    if (packetID == Packet.ServerDisconnect && direction == Direction.Server)
                    {
                        this.client.closeConnection();
                    }
                }
            }
            catch (ThreadAbortException) { }
            catch (EndOfStreamException)
            {
                this.client.forceDisconnect(direction, "End of stream");
            }
            catch (Exception e)
            {
                if (e.InnerException != null)
                {
                    if (e.InnerException is System.Net.Sockets.SocketException)
                    {
                        this.client.forceDisconnect(direction, e.InnerException.Message);
                        return;
                    }
                }
                this.client.forceDisconnect(direction, "ForwardThread Exception: " + e.ToString());
            }
        }
Пример #26
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;
            }
        }