TryCatch tail functions
This commit is contained in:
parent
2a5774bd6d
commit
d885485684
5 changed files with 22 additions and 192 deletions
|
@ -16,12 +16,12 @@ class PacketServer {
|
|||
print("Server now listening on port ${port}");
|
||||
|
||||
await for (var sock in socket!) {
|
||||
S2CResponse response = S2CResponse();
|
||||
print(
|
||||
"New connection from ${sock.remoteAddress.address}:${sock.remotePort}");
|
||||
|
||||
try {
|
||||
sock.listen((data) async {
|
||||
S2CResponse response = S2CResponse();
|
||||
try {
|
||||
CompoundTag tag = await NbtIo.readFromStream(data);
|
||||
StringBuilder builder = StringBuilder();
|
||||
|
@ -33,8 +33,8 @@ class PacketServer {
|
|||
request.decodeTag(tag);
|
||||
|
||||
PacketResponse reply = await request.handleServerPacket();
|
||||
// Server uses NBT to communicate
|
||||
|
||||
// Server uses NBT to communicate
|
||||
builder = StringBuilder();
|
||||
Tag.writeStringifiedNamedTag(reply.replyDataTag, builder, 0);
|
||||
|
||||
|
@ -45,17 +45,10 @@ class PacketServer {
|
|||
.put("error", StringTag.valueOf("Malformed request packet"));
|
||||
|
||||
print(
|
||||
"Something went wrong, sending malformed request response\n${stack}\n\n${E}\n\n");
|
||||
|
||||
sock.add(
|
||||
await NbtIo.writeToStream(response.encodeTag() as CompoundTag));
|
||||
"Something went wrong. Malformed request? \n\n${E}\n\n${stack}\n\n\n\n");
|
||||
} finally {
|
||||
await sock.flush();
|
||||
sock.close();
|
||||
|
||||
if (!shouldRestart) {
|
||||
await socket!.close();
|
||||
}
|
||||
}
|
||||
}, onDone: () {
|
||||
sock.close();
|
||||
|
|
|
@ -85,10 +85,12 @@ Stream<List<int>> tail(final File file) async* {
|
|||
|
||||
Stream<Uint8List> _read() async* {
|
||||
while (pos < len) {
|
||||
final bytesRead = await randomAccess.readInto(buf);
|
||||
pos += bytesRead;
|
||||
try {
|
||||
final bytesRead = await randomAccess.readInto(buf);
|
||||
pos += bytesRead;
|
||||
|
||||
yield buf.sublist(0, bytesRead);
|
||||
yield buf.sublist(0, bytesRead);
|
||||
} catch (E) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,15 +100,22 @@ Stream<List<int>> tail(final File file) async* {
|
|||
// Step 2: wait for modify events and read more bytes from file
|
||||
await for (final event in file.watch(events: FileSystemEvent.modify)) {
|
||||
if ((event as FileSystemModifyEvent).contentChanged) {
|
||||
len = await (randomAccess.length());
|
||||
yield* _read();
|
||||
try {
|
||||
len = await (randomAccess.length());
|
||||
yield* _read();
|
||||
} catch (E) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tailAndPrint(File file) {
|
||||
tail(file).transform(utf8.decoder).transform(LineSplitter()).forEach((line) {
|
||||
// Do something with the line that has been read, e.g. print it out...
|
||||
print(line);
|
||||
});
|
||||
try {
|
||||
tail(file)
|
||||
.transform(utf8.decoder)
|
||||
.transform(LineSplitter())
|
||||
.forEach((line) {
|
||||
// Do something with the line that has been read, e.g. print it out...
|
||||
print(line);
|
||||
});
|
||||
} catch (E) {}
|
||||
}
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'RconDecoder.dart';
|
||||
|
||||
abstract class RconClient {
|
||||
void exit();
|
||||
|
||||
void send(String cmd);
|
||||
|
||||
factory RconClient() => RconClientImpl();
|
||||
|
||||
Stream<String> connect(String host, int port, String password);
|
||||
}
|
||||
|
||||
class RconType {
|
||||
/// RCON Packet Type 0: Server response
|
||||
static const int SERVERDATA_RESPONSE_VALUE = 0;
|
||||
|
||||
/// RCON Packet Type 2: Server auth response
|
||||
static const int SERVERDATA_AUTH_RESPONSE = 2;
|
||||
|
||||
/// RCON Packet Type 2: Client execute command
|
||||
static const int SERVERDATA_EXECCOMMAND = 2;
|
||||
|
||||
/// RCON Packet Type 3: Client send authentication data
|
||||
static const int SERVERDATA_AUTH = 3;
|
||||
}
|
||||
|
||||
/// Client for the rcon protocol
|
||||
class RconClientImpl implements RconClient {
|
||||
/// Socket used to write and read TCP packets.
|
||||
late Socket _socket;
|
||||
|
||||
/// Disconnect from the a RCON server.
|
||||
///
|
||||
/// Usage:
|
||||
///
|
||||
/// ```dart
|
||||
/// RconClient client = RconClient.connect(print, 'localhost', '25575', 'password');
|
||||
/// client.exit();
|
||||
/// ```
|
||||
@override
|
||||
void exit() => _socket.destroy();
|
||||
|
||||
/// Send commands
|
||||
@override
|
||||
void send(String cmd) => _send(RconType.SERVERDATA_EXECCOMMAND, cmd);
|
||||
|
||||
/// Authenticate to the server
|
||||
void _authenticate(String password) =>
|
||||
_send(RconType.SERVERDATA_AUTH, password);
|
||||
|
||||
/// Build and send a packet to the rcon server
|
||||
///
|
||||
/// | Field | Type | Value |
|
||||
/// |--------------|-------------------------------------|-------|
|
||||
/// | Size | 32-bit little-endian Signed Integer | |
|
||||
/// | ID | 32-bit little-endian Signed Integer | |
|
||||
/// | Type | 32-bit little-endian Signed Integer | |
|
||||
/// | Body | Null-terminated ASCII String | |
|
||||
/// | Empty String | Null-terminated ASCII String | 0x00 |
|
||||
void _send(int type, String payload) {
|
||||
final Uint8List outSize = Uint8List(4);
|
||||
final Uint8List outId = Uint8List(4); // Empty: 00 00 00 00
|
||||
final Uint8List outType = Uint8List(4);
|
||||
|
||||
// Write type in the Type field
|
||||
final ByteData typeData = ByteData.view(outType.buffer);
|
||||
typeData.setInt32(0, type, Endian.little);
|
||||
|
||||
// Build the body
|
||||
final List<int> outBody = utf8.encode(payload);
|
||||
|
||||
// Build ID + Type + Body + Empty String
|
||||
final Uint8List outPacketBody =
|
||||
Uint8List.fromList(outId + outType + outBody + Uint8List(2));
|
||||
|
||||
// Calculate the Size field
|
||||
final ByteData sizeData = ByteData.view(outSize.buffer);
|
||||
sizeData.setInt32(0, outPacketBody.length, Endian.little);
|
||||
|
||||
// Build the packet
|
||||
final Uint8List packet = Uint8List.fromList(outSize + outPacketBody);
|
||||
|
||||
// View packet
|
||||
// print(packet);
|
||||
// print(packet.map((int i) => i.toRadixString(16)).toList());
|
||||
// print(utf8.decode(packet));
|
||||
|
||||
// Send the packet
|
||||
_socket.add(packet);
|
||||
}
|
||||
|
||||
/// Connect to the a RCON server.
|
||||
///
|
||||
/// Usage:
|
||||
///
|
||||
/// ```dart
|
||||
/// final RconClient client = RconClient();
|
||||
/// final Stream<String> response = client.connect(
|
||||
/// 'localhost',
|
||||
/// 25575,
|
||||
/// 'password',
|
||||
/// );
|
||||
/// ```
|
||||
@override
|
||||
Stream<String> connect(String host, int port, String password) async* {
|
||||
print("Trying to connect...");
|
||||
|
||||
_socket = await Socket.connect(host, port);
|
||||
|
||||
print("Connected.");
|
||||
|
||||
final Stream<String> stream = _socket.transform(RconDecoder());
|
||||
|
||||
print("Trying to authenticate");
|
||||
|
||||
_authenticate(password);
|
||||
|
||||
yield* stream;
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'Rcon.dart';
|
||||
|
||||
class RconDecoder extends Converter<Uint8List, String> {
|
||||
/// Transform packets into a String.
|
||||
///
|
||||
/// | Field | Type | Value |
|
||||
/// |--------------|-------------------------------------|-------|
|
||||
/// | Size | 32-bit little-endian Signed Integer | |
|
||||
/// | ID | 32-bit little-endian Signed Integer | |
|
||||
/// | Type | 32-bit little-endian Signed Integer | |
|
||||
/// | Body | Null-terminated ASCII String | |
|
||||
/// | Empty String | Null-terminated ASCII String | 0x00 |
|
||||
@override
|
||||
String convert(Uint8List data) {
|
||||
final byteData = ByteData.sublistView(data);
|
||||
// final inLength = byteData.getInt32(0, Endian.little);
|
||||
final inId = byteData.getInt32(4, Endian.little);
|
||||
final inType = byteData.getInt32(8, Endian.little);
|
||||
final inBody = data.sublist(12);
|
||||
|
||||
if (inType == RconType.SERVERDATA_AUTH_RESPONSE) {
|
||||
if (inId == -1) {
|
||||
throw const SocketException('Bad login.');
|
||||
} else if (inId == 0) {
|
||||
return 'Authentication successful. You can now write commands.';
|
||||
}
|
||||
}
|
||||
|
||||
return utf8.decode(inBody);
|
||||
}
|
||||
|
||||
@override
|
||||
Sink<Uint8List> startChunkedConversion(Sink<String> sink) {
|
||||
return ChunkedConversionSink.withCallback((chunk) {
|
||||
for (final data in chunk) {
|
||||
sink.add(convert(data));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Override the base class's bind, to provide a better type.
|
||||
@override
|
||||
Stream<String> bind(Stream<Uint8List> stream) => super.bind(stream);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
name: libac_dart
|
||||
description: "Aria's Creations code library"
|
||||
version: 1.0.29
|
||||
version: 1.0.31
|
||||
homepage: "https://zontreck.com"
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue