Created
November 19, 2018 09:55
-
-
Save Lachee/fecafd7a3e12ee5714b682e0cfbccb85 to your computer and use it in GitHub Desktop.
C# Dotnet Steam RCON Client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Packet | |
{ | |
public int ID { get; set; } | |
public string Body { get; set; } | |
public PacketType Type { get; set; } | |
public enum PacketType | |
{ | |
ServerdataAuth = 3, | |
ServerdataAuthResponse = 2, | |
ServerdataExecuteCommand = 2, | |
ServerdataResponseValue = 0 | |
} | |
public static async Task<Packet> FromStream(Stream stream, int count) | |
{ | |
int id, type; | |
string body; | |
byte[] intbuff = new byte[sizeof(int)]; | |
byte[] stringbuff = new byte[count - 10]; | |
byte[] nullbuff = new byte[2]; | |
await stream.ReadAsync(intbuff, 0, intbuff.Length); | |
id = BitConverter.ToInt32(intbuff, 0); | |
await stream.ReadAsync(intbuff, 0, intbuff.Length); | |
type = BitConverter.ToInt32(intbuff, 0); | |
await stream.ReadAsync(stringbuff, 0, stringbuff.Length); | |
body = System.Text.Encoding.ASCII.GetString(stringbuff); | |
await stream.ReadAsync(nullbuff, 0, nullbuff.Length); | |
return new Packet() | |
{ | |
ID = id, | |
Type = type == 2 ? PacketType.ServerdataAuthResponse : (PacketType)type, | |
Body = body | |
}; | |
} | |
public async Task ToStream(Stream stream) | |
{ | |
byte[] bodyBuffer = System.Text.Encoding.ASCII.GetBytes(Body); | |
int size = bodyBuffer.Length + 10; | |
await stream.WriteAsync(BitConverter.GetBytes(size), 0, sizeof(int)); | |
await stream.WriteAsync(BitConverter.GetBytes(ID), 0, sizeof(int)); | |
await stream.WriteAsync(BitConverter.GetBytes((int) Type), 0, sizeof(int)); | |
await stream.WriteAsync(bodyBuffer, 0, bodyBuffer.Length); | |
await stream.WriteAsync(new byte[2], 0, 2); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class RconClient | |
{ | |
public string Address { get; } | |
public int Port { get; } | |
private string _password; | |
public RconClient(string address, int port, string password = null) | |
{ | |
Address = address; | |
Port = port; | |
_password = password; | |
} | |
public async Task<RconResponse> Execute(string command) | |
{ | |
try | |
{ | |
int sequence = 10; | |
using (var tcp = new TcpClient()) | |
{ | |
//Connect to the TCP and prepare the stream | |
await tcp.ConnectAsync(Address, Port); | |
using (var stream = tcp.GetStream()) | |
{ | |
//Write the authentication packet | |
int authID = sequence++; | |
await new Packet() | |
{ | |
ID = authID, | |
Type = Packet.PacketType.ServerdataAuth, | |
Body = _password | |
}.ToStream(stream); | |
//Make sure its all valid | |
bool receivedAuthPacket = false; | |
bool isAuthenticated = false; | |
//Prepare a buffer and read all the authorization packets. | |
byte[] sizebuff = new byte[sizeof(int)]; | |
while (!receivedAuthPacket) | |
{ | |
await stream.ReadAsync(sizebuff, 0, sizebuff.Length); | |
var authResponsePacket = await Packet.FromStream(stream, BitConverter.ToInt32(sizebuff, 0)); | |
if (authResponsePacket.Type == Packet.PacketType.ServerdataAuthResponse) | |
{ | |
receivedAuthPacket = true; | |
isAuthenticated = authResponsePacket.ID == authID; | |
} | |
} | |
//Make sure we are authorized | |
if (!isAuthenticated) | |
{ | |
return new RconResponse() | |
{ | |
Message = "Invalid Authorization", | |
Successful = false | |
}; | |
} | |
//Write the command packet | |
await new Packet() | |
{ | |
ID = sequence++, | |
Type = Packet.PacketType.ServerdataExecuteCommand, | |
Body = command | |
}.ToStream(stream); | |
//Read its response. | |
await stream.ReadAsync(sizebuff, 0, sizebuff.Length); | |
var responsePacket = await Packet.FromStream(stream, BitConverter.ToInt32(sizebuff, 0)); | |
return new RconResponse() | |
{ | |
Response = responsePacket.Body, | |
Successful = true | |
}; | |
} | |
} | |
} | |
catch (Exception e) | |
{ | |
return new RconResponse() | |
{ | |
Message = e.Message, | |
Successful = false | |
}; | |
} | |
} | |
} | |
public struct RconResponse | |
{ | |
public string Response { get; set; } | |
public string Message { get; set; } | |
public bool Successful { get; set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment