95 lines
2.3 KiB
Dart
95 lines
2.3 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
class RCONPacket {
|
|
int id;
|
|
int type;
|
|
String body;
|
|
|
|
RCONPacket(this.id, this.type, this.body);
|
|
|
|
List<int> toBytes() {
|
|
List<int> bodyBytes = utf8.encode(body);
|
|
int size = 10 + bodyBytes.length;
|
|
List<int> packet = [];
|
|
packet.addAll(_intToBytes(size));
|
|
packet.addAll(_intToBytes(id));
|
|
packet.addAll(_intToBytes(type));
|
|
packet.addAll(bodyBytes);
|
|
packet.addAll([0, 0]);
|
|
return packet;
|
|
}
|
|
|
|
static RCONPacket fromBytes(List<int> bytes) {
|
|
int size = _bytesToInt(bytes.sublist(0, 4));
|
|
int id = _bytesToInt(bytes.sublist(4, 8));
|
|
int type = _bytesToInt(bytes.sublist(8, 12));
|
|
String body =
|
|
utf8.decode(bytes.sublist(12, size + 2).sublist(0, size - 10));
|
|
return RCONPacket(id, type, body);
|
|
}
|
|
|
|
static List<int> _intToBytes(int value) {
|
|
return [
|
|
value & 0xFF,
|
|
(value >> 8) & 0xFF,
|
|
(value >> 16) & 0xFF,
|
|
(value >> 24) & 0xFF
|
|
];
|
|
}
|
|
|
|
static int _bytesToInt(List<int> bytes) {
|
|
return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
|
|
}
|
|
}
|
|
|
|
class RCONClient {
|
|
String host;
|
|
int port;
|
|
String password;
|
|
late Socket _socket;
|
|
late int _requestId;
|
|
|
|
RCONClient(this.host, this.port, this.password) {
|
|
_requestId = 0;
|
|
}
|
|
|
|
Future<void> connect() async {
|
|
_socket = await Socket.connect(host, port);
|
|
if (await _authenticate()) {
|
|
print('Authenticated successfully');
|
|
} else {
|
|
print('Authentication failed');
|
|
}
|
|
}
|
|
|
|
Future<bool> _authenticate() async {
|
|
RCONPacket packet = RCONPacket(_requestId++, 3, password);
|
|
_socket.add(packet.toBytes());
|
|
await _socket.flush();
|
|
RCONPacket response = await _readPacket();
|
|
return response.id == packet.id && response.type == 2;
|
|
}
|
|
|
|
Future<RCONPacket> _readPacket() async {
|
|
List<int> sizeBytes = await _socket.first;
|
|
int size = RCONPacket._bytesToInt(sizeBytes);
|
|
List<int> dataBytes = [];
|
|
while (dataBytes.length < size) {
|
|
dataBytes.addAll(await _socket.first);
|
|
}
|
|
return RCONPacket.fromBytes(sizeBytes + dataBytes);
|
|
}
|
|
|
|
Future<String> sendCommand(String command) async {
|
|
RCONPacket packet = RCONPacket(_requestId++, 2, command);
|
|
_socket.add(packet.toBytes());
|
|
await _socket.flush();
|
|
RCONPacket response = await _readPacket();
|
|
return response.body;
|
|
}
|
|
|
|
void close() {
|
|
_socket.close();
|
|
}
|
|
}
|