use of org.javacord.api.event.connection.ReconnectEvent in project Javacord by BtoBastian.
the class DiscordWebSocketAdapter method onTextMessage.
@Override
public void onTextMessage(WebSocket websocket, String text) throws Exception {
ObjectMapper mapper = api.getObjectMapper();
JsonNode packet = mapper.readTree(text);
heart.handlePacket(packet);
int op = packet.get("op").asInt();
Optional<GatewayOpcode> opcode = GatewayOpcode.fromCode(op);
if (!opcode.isPresent()) {
logger.debug("Received unknown packet (op: {}, content: {})", op, packet);
return;
}
switch(opcode.get()) {
case DISPATCH:
lastSeq = packet.get("s").asInt();
String type = packet.get("t").asText();
PacketHandler handler = handlers.get(type);
if (handler != null) {
handler.handlePacket(packet.get("d"));
} else {
logger.debug("Received unknown packet of type {} (packet: {})", type, packet);
}
if (type.equals("GUILD_MEMBERS_CHUNK")) {
lastGuildMembersChunkReceived = System.currentTimeMillis();
}
if (type.equals("RESUMED")) {
reconnectingOrResumingLock.lock();
try {
reconnectAttempt.set(0);
finishedReconnectingOrResumingCondition.signalAll();
} finally {
reconnectingOrResumingLock.unlock();
}
logger.debug("Received RESUMED packet");
ResumeEvent resumeEvent = new ResumeEventImpl(api);
api.getEventDispatcher().dispatchResumeEvent(null, resumeEvent);
}
if (type.equals("READY")) {
reconnectingOrResumingLock.lock();
try {
reconnectAttempt.set(0);
finishedReconnectingOrResumingCondition.signalAll();
} finally {
reconnectingOrResumingLock.unlock();
}
sessionId = packet.get("d").get("session_id").asText();
// Discord sends us GUILD_CREATE packets after logging in. We will wait for them.
api.getThreadPool().getSingleThreadExecutorService("Startup Servers Wait Thread").submit(() -> {
boolean allUsersLoaded = false;
boolean allServersLoaded = false;
int lastUnavailableServerAmount = 0;
int sameUnavailableServerCounter = 0;
while (api.isWaitingForServersOnStartup() && (!allServersLoaded || !allUsersLoaded)) {
if (api.getUnavailableServers().size() == lastUnavailableServerAmount) {
sameUnavailableServerCounter++;
} else {
lastUnavailableServerAmount = api.getUnavailableServers().size();
sameUnavailableServerCounter = 0;
}
allServersLoaded = api.getUnavailableServers().isEmpty();
if (allServersLoaded) {
allUsersLoaded = !api.hasUserCacheEnabled() || !api.isWaitingForUsersOnStartup() || api.getAllServers().stream().map(ServerImpl.class::cast).noneMatch(server -> server.getMemberCount() != server.getRealMembers().size());
}
if (sameUnavailableServerCounter > 1000 && lastGuildMembersChunkReceived + 5000 < System.currentTimeMillis()) {
// itself has some issues. Let's break the loop!
break;
}
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
}
ReconnectEvent reconnectEvent = new ReconnectEventImpl(api);
api.getEventDispatcher().dispatchReconnectEvent(null, reconnectEvent);
ready.complete(true);
});
logger.debug("Received READY packet");
}
break;
case HEARTBEAT:
heart.beat();
break;
case RECONNECT:
sendCloseFrame(websocket, WebSocketCloseReason.COMMANDED_RECONNECT.getNumericCloseCode(), WebSocketCloseReason.COMMANDED_RECONNECT.getCloseReason());
break;
case INVALID_SESSION:
if (lastSentFrameWasIdentify.isMarked()) {
logger.info("Hit identifying rate limit. Retrying in 5 seconds...");
} else {
// Invalid session :(
int oneToFiveSeconds = 1000 + (int) (Math.random() * 4000);
logger.info("Could not resume session. Reconnecting in {}.{} seconds...", () -> oneToFiveSeconds / 1000, () -> oneToFiveSeconds / 100 % 10);
try {
Thread.sleep(oneToFiveSeconds);
} catch (InterruptedException e) {
logger.error("Interrupted while delaying reconnect!");
return;
}
}
api.getGatewayIdentifyRatelimiter().requestQuota();
sendIdentify(websocket);
break;
case HELLO:
logger.debug("Received HELLO packet");
JsonNode data = packet.get("d");
int heartbeatInterval = data.get("heartbeat_interval").asInt();
// calculate reserved places for heartbeats
webSocketFrameSendingLimit.set(WEB_SOCKET_FRAME_SENDING_RATELIMIT - 1 - (60_000 / heartbeatInterval));
heart.startBeating(heartbeatInterval);
if (sessionId == null) {
sendIdentify(websocket);
} else {
sendResume(websocket);
}
break;
case HEARTBEAT_ACK:
// Handled by the heart
break;
default:
logger.debug("Received unknown packet (op: {}, content: {})", op, packet);
break;
}
}
Aggregations