forked from OpenGamers/abaddon
handle opcode 9 invalid session and improve handling socket closure
This commit is contained in:
parent
092cd3291b
commit
e13a6eab81
@ -38,6 +38,7 @@ Abaddon::Abaddon()
|
|||||||
m_discord.signal_guild_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildUpdate));
|
m_discord.signal_guild_update().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnGuildUpdate));
|
||||||
m_discord.signal_reaction_add().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnReactionAdd));
|
m_discord.signal_reaction_add().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnReactionAdd));
|
||||||
m_discord.signal_reaction_remove().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnReactionRemove));
|
m_discord.signal_reaction_remove().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnReactionRemove));
|
||||||
|
m_discord.signal_disconnected().connect(sigc::mem_fun(*this, &Abaddon::DiscordOnDisconnect));
|
||||||
if (m_settings.GetPrefetch())
|
if (m_settings.GetPrefetch())
|
||||||
m_discord.signal_message_create().connect([this](Snowflake id) {
|
m_discord.signal_message_create().connect([this](Snowflake id) {
|
||||||
const auto msg = m_discord.GetMessage(id);
|
const auto msg = m_discord.GetMessage(id);
|
||||||
@ -233,6 +234,14 @@ void Abaddon::DiscordOnReactionRemove(Snowflake message_id, const Glib::ustring
|
|||||||
m_main_window->UpdateChatReactionAdd(message_id, param);
|
m_main_window->UpdateChatReactionAdd(message_id, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Abaddon::DiscordOnDisconnect(bool is_reconnecting, GatewayCloseCode close_code) {
|
||||||
|
m_main_window->UpdateComponents();
|
||||||
|
if (close_code == GatewayCloseCode::AuthenticationFailed) {
|
||||||
|
Gtk::MessageDialog dlg(*m_main_window, "Discord rejected your token", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||||
|
dlg.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const SettingsManager &Abaddon::GetSettings() const {
|
const SettingsManager &Abaddon::GetSettings() const {
|
||||||
return m_settings;
|
return m_settings;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ public:
|
|||||||
void DiscordOnGuildUpdate(Snowflake guild_id);
|
void DiscordOnGuildUpdate(Snowflake guild_id);
|
||||||
void DiscordOnReactionAdd(Snowflake message_id, const Glib::ustring ¶m);
|
void DiscordOnReactionAdd(Snowflake message_id, const Glib::ustring ¶m);
|
||||||
void DiscordOnReactionRemove(Snowflake message_id, const Glib::ustring ¶m);
|
void DiscordOnReactionRemove(Snowflake message_id, const Glib::ustring ¶m);
|
||||||
|
void DiscordOnDisconnect(bool is_reconnecting, GatewayCloseCode close_code);
|
||||||
|
|
||||||
const SettingsManager &GetSettings() const;
|
const SettingsManager &GetSettings() const;
|
||||||
|
|
||||||
|
@ -7,6 +7,14 @@ DiscordClient::DiscordClient(bool mem_store)
|
|||||||
, m_decompress_buf(InflateChunkSize)
|
, m_decompress_buf(InflateChunkSize)
|
||||||
, m_store(mem_store) {
|
, m_store(mem_store) {
|
||||||
m_msg_dispatch.connect(sigc::mem_fun(*this, &DiscordClient::MessageDispatch));
|
m_msg_dispatch.connect(sigc::mem_fun(*this, &DiscordClient::MessageDispatch));
|
||||||
|
auto dispatch_cb = [this]() {
|
||||||
|
m_generic_mutex.lock();
|
||||||
|
auto func = m_generic_queue.front();
|
||||||
|
m_generic_queue.pop();
|
||||||
|
m_generic_mutex.unlock();
|
||||||
|
func();
|
||||||
|
};
|
||||||
|
m_generic_dispatch.connect(dispatch_cb);
|
||||||
|
|
||||||
m_websocket.signal_message().connect(sigc::mem_fun(*this, &DiscordClient::HandleGatewayMessageRaw));
|
m_websocket.signal_message().connect(sigc::mem_fun(*this, &DiscordClient::HandleGatewayMessageRaw));
|
||||||
m_websocket.signal_open().connect(sigc::mem_fun(*this, &DiscordClient::HandleSocketOpen));
|
m_websocket.signal_open().connect(sigc::mem_fun(*this, &DiscordClient::HandleSocketOpen));
|
||||||
@ -41,7 +49,7 @@ void DiscordClient::Stop() {
|
|||||||
|
|
||||||
m_websocket.Stop();
|
m_websocket.Stop();
|
||||||
|
|
||||||
m_signal_disconnected.emit(false);
|
m_signal_disconnected.emit(false, GatewayCloseCode::UserDisconnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DiscordClient::IsStarted() const {
|
bool DiscordClient::IsStarted() const {
|
||||||
@ -652,6 +660,9 @@ void DiscordClient::HandleGatewayMessage(std::string str) {
|
|||||||
case GatewayOp::Reconnect: {
|
case GatewayOp::Reconnect: {
|
||||||
HandleGatewayReconnect(m);
|
HandleGatewayReconnect(m);
|
||||||
} break;
|
} break;
|
||||||
|
case GatewayOp::InvalidSession: {
|
||||||
|
HandleGatewayInvalidSession(m);
|
||||||
|
} break;
|
||||||
case GatewayOp::Event: {
|
case GatewayOp::Event: {
|
||||||
auto iter = m_event_map.find(m.Type);
|
auto iter = m_event_map.find(m.Type);
|
||||||
if (iter == m_event_map.end()) {
|
if (iter == m_event_map.end()) {
|
||||||
@ -1100,7 +1111,8 @@ void DiscordClient::HandleGatewayInviteDelete(const GatewayMessage &msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DiscordClient::HandleGatewayReconnect(const GatewayMessage &msg) {
|
void DiscordClient::HandleGatewayReconnect(const GatewayMessage &msg) {
|
||||||
m_signal_disconnected.emit(true);
|
printf("received reconnect\n");
|
||||||
|
m_signal_disconnected.emit(true, GatewayCloseCode::Reconnecting);
|
||||||
inflateEnd(&m_zstream);
|
inflateEnd(&m_zstream);
|
||||||
m_compressed_buf.clear();
|
m_compressed_buf.clear();
|
||||||
|
|
||||||
@ -1117,6 +1129,27 @@ void DiscordClient::HandleGatewayReconnect(const GatewayMessage &msg) {
|
|||||||
m_websocket.StartConnection(DiscordGateway);
|
m_websocket.StartConnection(DiscordGateway);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiscordClient::HandleGatewayInvalidSession(const GatewayMessage &msg) {
|
||||||
|
printf("invalid session! re-identifying\n");
|
||||||
|
|
||||||
|
m_signal_disconnected.emit(true, GatewayCloseCode::Reconnecting);
|
||||||
|
inflateEnd(&m_zstream);
|
||||||
|
m_compressed_buf.clear();
|
||||||
|
|
||||||
|
std::memset(&m_zstream, 0, sizeof(m_zstream));
|
||||||
|
inflateInit2(&m_zstream, MAX_WBITS + 32);
|
||||||
|
|
||||||
|
m_heartbeat_acked = true;
|
||||||
|
m_wants_resume = false;
|
||||||
|
|
||||||
|
m_heartbeat_waiter.kill();
|
||||||
|
if (m_heartbeat_thread.joinable()) m_heartbeat_thread.join();
|
||||||
|
|
||||||
|
m_websocket.Stop(1000);
|
||||||
|
|
||||||
|
m_websocket.StartConnection(DiscordGateway);
|
||||||
|
}
|
||||||
|
|
||||||
void DiscordClient::HandleGatewayMessageUpdate(const GatewayMessage &msg) {
|
void DiscordClient::HandleGatewayMessageUpdate(const GatewayMessage &msg) {
|
||||||
Snowflake id = msg.Data.at("id");
|
Snowflake id = msg.Data.at("id");
|
||||||
|
|
||||||
@ -1263,6 +1296,28 @@ void DiscordClient::HandleSocketOpen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DiscordClient::HandleSocketClose(uint16_t code) {
|
void DiscordClient::HandleSocketClose(uint16_t code) {
|
||||||
|
printf("got socket close code: %d\n", code);
|
||||||
|
auto close_code = static_cast<GatewayCloseCode>(code);
|
||||||
|
auto cb = [this, close_code]() {
|
||||||
|
inflateEnd(&m_zstream);
|
||||||
|
m_compressed_buf.clear();
|
||||||
|
|
||||||
|
m_heartbeat_waiter.kill();
|
||||||
|
if (m_heartbeat_thread.joinable()) m_heartbeat_thread.join();
|
||||||
|
m_client_connected = false;
|
||||||
|
|
||||||
|
m_store.ClearAll();
|
||||||
|
m_chan_to_message_map.clear();
|
||||||
|
m_guild_to_users.clear();
|
||||||
|
|
||||||
|
m_websocket.Stop();
|
||||||
|
|
||||||
|
m_signal_disconnected.emit(false, close_code);
|
||||||
|
};
|
||||||
|
m_generic_mutex.lock();
|
||||||
|
m_generic_queue.push(cb);
|
||||||
|
m_generic_dispatch.emit();
|
||||||
|
m_generic_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DiscordClient::CheckCode(const http::response_type &r) {
|
bool DiscordClient::CheckCode(const http::response_type &r) {
|
||||||
|
@ -170,6 +170,7 @@ private:
|
|||||||
void HandleGatewayInviteCreate(const GatewayMessage &msg);
|
void HandleGatewayInviteCreate(const GatewayMessage &msg);
|
||||||
void HandleGatewayInviteDelete(const GatewayMessage &msg);
|
void HandleGatewayInviteDelete(const GatewayMessage &msg);
|
||||||
void HandleGatewayReconnect(const GatewayMessage &msg);
|
void HandleGatewayReconnect(const GatewayMessage &msg);
|
||||||
|
void HandleGatewayInvalidSession(const GatewayMessage &msg);
|
||||||
void HeartbeatThread();
|
void HeartbeatThread();
|
||||||
void SendIdentify();
|
void SendIdentify();
|
||||||
void SendResume();
|
void SendResume();
|
||||||
@ -217,6 +218,10 @@ private:
|
|||||||
std::queue<std::string> m_msg_queue;
|
std::queue<std::string> m_msg_queue;
|
||||||
void MessageDispatch();
|
void MessageDispatch();
|
||||||
|
|
||||||
|
mutable std::mutex m_generic_mutex;
|
||||||
|
Glib::Dispatcher m_generic_dispatch;
|
||||||
|
std::queue<std::function<void()>> m_generic_queue;
|
||||||
|
|
||||||
// signals
|
// signals
|
||||||
public:
|
public:
|
||||||
typedef sigc::signal<void> type_signal_gateway_ready;
|
typedef sigc::signal<void> type_signal_gateway_ready;
|
||||||
@ -241,7 +246,7 @@ public:
|
|||||||
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_guild_ban_add; // guild id, user id
|
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_guild_ban_add; // guild id, user id
|
||||||
typedef sigc::signal<void, InviteData> type_signal_invite_create;
|
typedef sigc::signal<void, InviteData> type_signal_invite_create;
|
||||||
typedef sigc::signal<void, InviteDeleteObject> type_signal_invite_delete;
|
typedef sigc::signal<void, InviteDeleteObject> type_signal_invite_delete;
|
||||||
typedef sigc::signal<void, bool> type_signal_disconnected; // bool true if reconnecting
|
typedef sigc::signal<void, bool, GatewayCloseCode> type_signal_disconnected; // bool true if reconnecting
|
||||||
typedef sigc::signal<void> type_signal_connected;
|
typedef sigc::signal<void> type_signal_connected;
|
||||||
|
|
||||||
type_signal_gateway_ready signal_gateway_ready();
|
type_signal_gateway_ready signal_gateway_ready();
|
||||||
|
@ -28,6 +28,7 @@ enum class GatewayOp : int {
|
|||||||
UpdateStatus = 3,
|
UpdateStatus = 3,
|
||||||
Resume = 6,
|
Resume = 6,
|
||||||
Reconnect = 7,
|
Reconnect = 7,
|
||||||
|
InvalidSession = 9,
|
||||||
Hello = 10,
|
Hello = 10,
|
||||||
HeartbeatAck = 11,
|
HeartbeatAck = 11,
|
||||||
LazyLoadRequest = 14,
|
LazyLoadRequest = 14,
|
||||||
@ -62,6 +63,28 @@ enum class GatewayEvent : int {
|
|||||||
INVITE_DELETE,
|
INVITE_DELETE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class GatewayCloseCode : uint16_t {
|
||||||
|
// discord
|
||||||
|
UnknownError = 4000,
|
||||||
|
UnknownOpcode = 4001,
|
||||||
|
DecodeError = 4002,
|
||||||
|
NotAuthenticated = 4003,
|
||||||
|
AuthenticationFailed = 4004,
|
||||||
|
AlreadyAuthenticated = 4005,
|
||||||
|
InvalidSequence = 4007,
|
||||||
|
RateLimited = 4008,
|
||||||
|
SessionTimedOut = 4009,
|
||||||
|
InvalidShard = 4010,
|
||||||
|
ShardingRequired = 4011,
|
||||||
|
InvalidAPIVersion = 4012,
|
||||||
|
InvalidIntents = 4013,
|
||||||
|
DisallowedIntents = 4014,
|
||||||
|
|
||||||
|
// internal
|
||||||
|
UserDisconnect = 4091,
|
||||||
|
Reconnecting = 4092,
|
||||||
|
};
|
||||||
|
|
||||||
struct GatewayMessage {
|
struct GatewayMessage {
|
||||||
GatewayOp Opcode;
|
GatewayOp Opcode;
|
||||||
nlohmann::json Data;
|
nlohmann::json Data;
|
||||||
|
Loading…
Reference in New Issue
Block a user