LibAC-dart/lib/utils/rcon/Rcon.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();
}
}