static void Main(string[] args) { // Initialise connection Rcon rcon = new Rcon("rust.yourserver.com", 26101, "your rcon passphrase"); // Single command rcon.Send("say \"Thank [color#FF0000]you [color#FFFFFF]for choosing this RCON class.\""); // Command with (multipart) reply Package command = new Package("banlistex"); command.RegisterCallback((Package result) => { rcon.Send(String.Format("say \"There are {0} entries on your ban list.\"", result.Response.Split('\n').Length)); }); // Note that result and command are the same object. rcon.SendPackage(command); // Handle passive traffic (eg. chat, join and quit messages, ...) Task passive = new Task(() => { while (true) { Package package = rcon.ReadPackage(); if (Regex.IsMatch(package.Response, "^\\[CHAT\\] \\\".*\\\":\\\".*\\\"$")) Console.WriteLine("Chat message received."); else if (Regex.IsMatch(package.Response, "^User Connected: .* \\(\\d+\\)$")) Console.WriteLine("User connected."); } }); passive.Start(); Task.WaitAll(new Task[] { passive }); }
// Request /// <summary> /// Create a new request to send to the server. The content will be sent to the server. /// </summary> /// <param name="content">Message to send to the server</param> /// <param name="type">Message type, Normal, Auth or Validation</param> public Package(string content, PackageType type = PackageType.Normal) { this.id = Package.id_counter++; this.content = content; this.type = 2; if (type == PackageType.Auth) this.type = 3; if (type != PackageType.Validation) this.validationPackage = new Package("", PackageType.Validation); this.callbacks = new List<Action<Package>>(); }
/// <summary> /// Prepare the byte array to send to the server. /// </summary> /// <param name="package">Package to be sent</param> /// <returns>Byte array to be sent</returns> private byte[] getBytes(Package package) { byte[] id = BitConverter.GetBytes(package.ID); byte[] type = BitConverter.GetBytes(package.Type); byte[] content = Encoding.UTF8.GetBytes(package.Content); int size = id.Length + type.Length + content.Length + 2; // 2x "0x00" on content byte[] bsize = BitConverter.GetBytes(size); byte[] send = new byte[size + 4]; if (!BitConverter.IsLittleEndian) { Array.Reverse(id); Array.Reverse(type); Array.Reverse(content); Array.Reverse(bsize); } int position = 0; foreach (byte b in bsize) send[position++] = b; foreach (byte b in id) send[position++] = b; foreach (byte b in type) send[position++] = b; foreach (byte b in content) send[position++] = b; send[position++] = 0; send[position++] = 0; return send; }
/// <summary> /// Process received packages from server /// </summary> /// <param name="package">Package from the server</param> public void UpdatePackage(Package package) { if (package.ID == 1) return; if (package.ID > 1) { // Validating package? Package validator = this.packages.Where(match => match.ValidationPackage != null && match.ValidationPackage.ID == package.ID).FirstOrDefault(); if (validator != null) // Validator received, completing package { if (validator.Complete) throw new IllegalProtocolException(); validator.Complete = true; return; } // Matching package? Package matched = this.packages.Where(match => match.ID == package.ID).FirstOrDefault(); if (matched != null) // Found a matching package { matched.Response += package.Response; // Append response to original return; } // It's either with an ID > 1 throw new IllegalProtocolException(); } // Passive traffic this.packages.Add(package); }
/// <summary> /// Send a package to the server. /// </summary> /// <param name="package">Package to send to the server.</param> /// <returns>ID of the command</returns> public int SendPackage(Package package) { byte[] send = getBytes(package); this.stream.Write(send, 0, send.Length); if (package.ValidationPackage != null) { send = getBytes(package.ValidationPackage); this.stream.Write(send, 0, send.Length); } this.stream.Flush(); this.packages.Add(package); return package.ID; }