Roll my own rcon implementation due to problems with other implementation
This commit is contained in:
parent
74fe37d7d8
commit
15aae5c3d7
5 changed files with 96 additions and 412 deletions
95
lib/utils/rcon/Rcon.dart
Normal file
95
lib/utils/rcon/Rcon.dart
Normal file
|
@ -0,0 +1,95 @@
|
|||
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();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue