Any kind of proper acknowledgement constitutes an alive connection for 30 seconds.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
package com.github.manevolent.ts3j.event;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* TeamSpeak 3 Java API
|
||||
* %%
|
||||
* Copyright (C) 2014 Bert De Geyter
|
||||
* %%
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class DisconnectedEvent extends BaseEvent {
|
||||
|
||||
public DisconnectedEvent(Map<String, String> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
public int getReasonId() {
|
||||
return getInt("reasonid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fire(TS3Listener listener) {
|
||||
listener.onDisconnected(this);
|
||||
}
|
||||
}
|
||||
@@ -63,4 +63,6 @@ public interface TS3Listener {
|
||||
void onClientChannelGroupChanged(ClientChannelGroupChangedEvent e);
|
||||
|
||||
void onClientChanged(ClientUpdatedEvent e);
|
||||
|
||||
void onDisconnected(DisconnectedEvent e);
|
||||
}
|
||||
|
||||
+30
-9
@@ -37,6 +37,8 @@ import java.util.concurrent.*;
|
||||
public abstract class AbstractTeamspeakClientSocket
|
||||
extends AbstractTeamspeakSocket
|
||||
implements TeamspeakClientSocket {
|
||||
public static long TIMEOUT = 30000L;
|
||||
|
||||
private static final byte[] INIT1_MAC = new byte[] {
|
||||
0x54, 0x53, 0x33, 0x49, 0x4E, 0x49, 0x54, 0x31
|
||||
};
|
||||
@@ -66,6 +68,7 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
private int clientId = 0;
|
||||
private int packetId = 0;
|
||||
|
||||
private long lastResponse;
|
||||
private long lastPing;
|
||||
|
||||
private final NetworkReader networkReader = new NetworkReader();
|
||||
@@ -396,7 +399,7 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
response = new PacketResponse(
|
||||
networkPacket,
|
||||
sendQueue,
|
||||
networkPacket.getHeader().getType().canResend() ? 10 : 0
|
||||
networkPacket.getHeader().getType().canResend() ? 30 : 0
|
||||
)
|
||||
);
|
||||
} else
|
||||
@@ -408,13 +411,14 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
|
||||
// If necessary, fulfill promise for the packet acknowledgement or throw TimeoutException
|
||||
if (response != null) {
|
||||
while (response.getRetries() < response.getMaxTries()) {
|
||||
while (response.getRetries() < response.getMaxTries() &&
|
||||
getState() != ClientConnectionState.DISCONNECTED) {
|
||||
try {
|
||||
if (getState() == ClientConnectionState.DISCONNECTED)
|
||||
throw new IllegalStateException("no longer connected");
|
||||
|
||||
// Wait one cycle for an ACK
|
||||
response.waitForAcknowledgement(1000);
|
||||
response.waitForAcknowledgement(1000L);
|
||||
break;
|
||||
} catch (TimeoutException e) {
|
||||
if (response.willResend())
|
||||
@@ -530,8 +534,13 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
networkPacket = readNetworkPacket((int) timeout);
|
||||
} catch (SocketTimeoutException e) {
|
||||
if (getState() == ClientConnectionState.CONNECTED) {
|
||||
writePacket(new PacketBody4Ping(getRole().getOut()));
|
||||
lastPing = System.currentTimeMillis();
|
||||
if (System.currentTimeMillis() - lastResponse >= TIMEOUT) {
|
||||
Ts3Debugging.debug("Connection timed out.");
|
||||
setState(ClientConnectionState.DISCONNECTED); // Timeout
|
||||
} else {
|
||||
writePacket(new PacketBody4Ping(getRole().getOut()));
|
||||
lastPing = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -593,16 +602,28 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
switch (packet.getHeader().getType()) {
|
||||
case ACK:
|
||||
response = sendQueue.get(((PacketBody6Ack)packet.getBody()).getPacketId());
|
||||
if (response == null)
|
||||
Ts3Debugging.debug("Unrecognized ACK: " + ((PacketBody6Ack)packet.getBody()).getPacketId());
|
||||
if (response == null) {
|
||||
Ts3Debugging.debug("Unrecognized ACK: " + ((PacketBody6Ack) packet.getBody()).getPacketId());
|
||||
} else {
|
||||
lastResponse = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
handle = false;
|
||||
break;
|
||||
case ACK_LOW:
|
||||
lastResponse = System.currentTimeMillis();
|
||||
|
||||
response = sendQueueLow.get(((PacketBody7AckLow)packet.getBody()).getPacketId());
|
||||
if (response == null)
|
||||
Ts3Debugging.debug("Unrecognized ACK_LOW: " + ((PacketBody6Ack)packet.getBody()).getPacketId());
|
||||
if (response == null) {
|
||||
Ts3Debugging.debug("Unrecognized ACK_LOW: " + ((PacketBody6Ack) packet.getBody()).getPacketId());
|
||||
} else {
|
||||
lastResponse = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
handle = false;
|
||||
break;
|
||||
case PONG:
|
||||
lastResponse = System.currentTimeMillis();
|
||||
default:
|
||||
handle = true;
|
||||
response = null;
|
||||
|
||||
+46
-4
@@ -9,9 +9,7 @@ import com.github.manevolent.ts3j.command.*;
|
||||
import com.github.manevolent.ts3j.command.parameter.CommandSingleParameter;
|
||||
import com.github.manevolent.ts3j.command.response.AbstractCommandResponse;
|
||||
import com.github.manevolent.ts3j.command.response.CommandResponse;
|
||||
import com.github.manevolent.ts3j.event.ChannelListEvent;
|
||||
import com.github.manevolent.ts3j.event.TS3Event;
|
||||
import com.github.manevolent.ts3j.event.TS3Listener;
|
||||
import com.github.manevolent.ts3j.event.*;
|
||||
import com.github.manevolent.ts3j.identity.LocalIdentity;
|
||||
import com.github.manevolent.ts3j.identity.Uid;
|
||||
import com.github.manevolent.ts3j.protocol.NetworkPacket;
|
||||
@@ -58,7 +56,7 @@ public class LocalTeamspeakClientSocket
|
||||
|
||||
private List<TS3Listener> listeners = new LinkedList<>();
|
||||
|
||||
private int acceptingReturnCode = 0;
|
||||
private int acceptingReturnCode = Integer.MAX_VALUE;
|
||||
private int lastReturnCode = 0;
|
||||
|
||||
private Integer serverId = null;
|
||||
@@ -80,6 +78,27 @@ public class LocalTeamspeakClientSocket
|
||||
});
|
||||
|
||||
namedProcessors.put("channellistfinished", new ChannelListFinishedHandler());
|
||||
|
||||
namedProcessors.put("notifyclientleftview", new CommandProcessor() {
|
||||
@Override
|
||||
public void process(AbstractTeamspeakClientSocket client, SingleCommand command)
|
||||
throws CommandProcessException {
|
||||
int clientId = Integer.parseInt(command.get("clid").getValue());
|
||||
if (clientId == getClientId()) {
|
||||
try {
|
||||
setState(ClientConnectionState.DISCONNECTED);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
for (TS3Listener listener : listeners)
|
||||
listener.onDisconnected(new DisconnectedEvent(command.toMap()));
|
||||
} else {
|
||||
for (TS3Listener listener : listeners)
|
||||
listener.onClientLeave(new ClientLeaveEvent(command.toMap()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addListener(TS3Listener listener) {
|
||||
@@ -164,6 +183,9 @@ public class LocalTeamspeakClientSocket
|
||||
setClientId(0);
|
||||
setPacketId(0);
|
||||
setGenerationId(0);
|
||||
serverId = null;
|
||||
awaitingCommands.clear();
|
||||
acceptingReturnCode = lastReturnCode = 0;
|
||||
|
||||
setOption("client.hostname", remote.getHostString());
|
||||
|
||||
@@ -745,4 +767,24 @@ public class LocalTeamspeakClientSocket
|
||||
|
||||
executeCommand(command).complete();
|
||||
}
|
||||
|
||||
public void disconnect()
|
||||
throws
|
||||
IOException, TimeoutException,
|
||||
ExecutionException, InterruptedException {
|
||||
switch (getState()) {
|
||||
case CONNECTING:
|
||||
case RETRIEVING_DATA:
|
||||
waitForState(ClientConnectionState.CONNECTED, 10000L);
|
||||
case CONNECTED:
|
||||
writePacket(new PacketBody2Command(
|
||||
ProtocolRole.CLIENT,
|
||||
new SingleCommand("clientdisconnect", ProtocolRole.CLIENT))
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -40,16 +40,9 @@ public class ServerConnectionTest {
|
||||
|
||||
assertEquals(client.getState(), ClientConnectionState.CONNECTED);
|
||||
|
||||
client.sendServerMessage("Heyyyy");
|
||||
client.disconnect();
|
||||
|
||||
while (true) {
|
||||
Thread.sleep(1000L);
|
||||
|
||||
for (Channel channel : client.listChannels()) {
|
||||
Ts3Debugging.debug(channel.getName());
|
||||
}
|
||||
|
||||
}
|
||||
client.waitForState(ClientConnectionState.DISCONNECTED, 10000L);
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user