TeamSpeak: auf Channel-Liste warten, kein doppelter Neuversuch

This commit is contained in:
MineTec committed 2026-10-18 13:14:43 +02:00
1 parent 5787c0cc68
commit 3c3a9dd836
1 file changed
+24 -2
@@ -81,7 +81,7 @@ public final class TeamspeakSide implements TS3Listener {
if (!ready || socket == null || rooms.stream().allMatch(room -> roomChannels.containsKey(room.key()))) return; if (!ready || socket == null || rooms.stream().allMatch(room -> roomChannels.containsKey(room.key()))) return;
try { try {
resolveChannels(socket); resolveChannels(socket);
if (parentChannel > 0) socket.joinChannel(parentChannel, null); joinParent(socket);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} catch (Exception e) { } catch (Exception e) {
@@ -151,11 +151,12 @@ public final class TeamspeakSide implements TS3Listener {
socket.addListener(this); socket.addListener(this);
observer = socket; observer = socket;
socket.connect(new InetSocketAddress(config.host(), config.port()), emptyToNull(config.password()), 15000L); socket.connect(new InetSocketAddress(config.host(), config.port()), emptyToNull(config.password()), 15000L);
awaitInitialState();
LOG.info("TeamSpeak verbunden mit {}:{} ({} Channels, {} Clients sichtbar)", LOG.info("TeamSpeak verbunden mit {}:{} ({} Channels, {} Clients sichtbar)",
config.host(), config.port(), channels.size(), clients.size()); config.host(), config.port(), channels.size(), clients.size());
parentChannel = resolveParent(); parentChannel = resolveParent();
resolveChannels(socket); resolveChannels(socket);
if (parentChannel > 0) socket.joinChannel(parentChannel, null); joinParent(socket);
ready = true; ready = true;
} catch (Exception e) { } catch (Exception e) {
LOG.warn("TeamSpeak-Verbindung fehlgeschlagen ({}), neuer Versuch in {} s", e.toString(), RECONNECT_SECONDS); LOG.warn("TeamSpeak-Verbindung fehlgeschlagen ({}), neuer Versuch in {} s", e.toString(), RECONNECT_SECONDS);
@@ -164,6 +165,17 @@ public final class TeamspeakSide implements TS3Listener {
} }
} }
/** ts3j liefert die Channel- und Client-Liste asynchron aus; warten, bis sie sich nicht mehr ändert. */
private void awaitInitialState() throws InterruptedException {
int last = -1;
for (int i = 0; i < 50; i++) {
int now = channels.size() + clients.size();
if (now == last && now > 0) return;
last = now;
Thread.sleep(200);
}
}
private void resolveChannels(LocalTeamspeakClientSocket socket) throws InterruptedException { private void resolveChannels(LocalTeamspeakClientSocket socket) throws InterruptedException {
for (Room room : rooms) { for (Room room : rooms) {
if (roomChannels.containsKey(room.key())) continue; if (roomChannels.containsKey(room.key())) continue;
@@ -202,6 +214,12 @@ public final class TeamspeakSide implements TS3Listener {
} }
} }
/** Der Beobachter wartet im Eltern-Channel; wer einen Channel anlegt, kann dorthin verschoben werden. */
private void joinParent(LocalTeamspeakClientSocket socket) throws Exception {
TsClient self = clients.get(socket.getClientId());
if (parentChannel > 0 && (self == null || self.channel() != parentChannel)) socket.joinChannel(parentChannel, null);
}
/** {@code parentChannel} ist eine Channel-ID oder der Name eines Channels auf oberster Ebene. */ /** {@code parentChannel} ist eine Channel-ID oder der Name eines Channels auf oberster Ebene. */
private int resolveParent() throws IOException { private int resolveParent() throws IOException {
String configured = config.parentChannel(); String configured = config.parentChannel();
@@ -230,6 +248,7 @@ public final class TeamspeakSide implements TS3Listener {
LocalTeamspeakClientSocket socket = observer; LocalTeamspeakClientSocket socket = observer;
observer = null; observer = null;
if (socket != null) { if (socket != null) {
socket.removeListener(this);
try { try {
socket.disconnect(); socket.disconnect();
} catch (Exception ignored) { } catch (Exception ignored) {
@@ -321,6 +340,9 @@ public final class TeamspeakSide implements TS3Listener {
@Override @Override
public void onDisconnected(DisconnectedEvent e) { public void onDisconnected(DisconnectedEvent e) {
// Beim fehlgeschlagenen Verbinden plant connectObserver den Neuversuch selbst
if (!ready) return;
ready = false;
LOG.warn("TeamSpeak-Beobachter getrennt, neuer Versuch in {} s", RECONNECT_SECONDS); LOG.warn("TeamSpeak-Beobachter getrennt, neuer Versuch in {} s", RECONNECT_SECONDS);
executor.execute(this::disconnectObserver); executor.execute(this::disconnectObserver);
executor.schedule(this::connectObserver, RECONNECT_SECONDS, TimeUnit.SECONDS); executor.schedule(this::connectObserver, RECONNECT_SECONDS, TimeUnit.SECONDS);