Skip to content

Commit e71723e

Browse files
authored
Improve gateway connection/resume logic (#3099)
This commit refactors how the gateway connection being closed gets handled, and also reworks how resuming is performed. If a resume fails, or if the session id is invalid/doesn't exist, the shard will fall back to restart + reidentify after a 1 second delay. This behavior was only present in some circumstances before. Also, cleaned up the loop in `ShardRunner::run` by adding a `ShardAction::Dispatch` variant, since event dispatch was already mutually exclusive to hearbeating, identifying, and restarting. The overall effect is less interleaving of control flow. Plus, removed the `Shard::{reconnect, reset}` functions as they were unused. A notable change is that 4006 is no longer considered a valid close code as it is undocumented, and neither is 1000, which tungstenite assigns as `Normal` or "clean". We should stick to the [table of close codes](https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-close-event-codes) provided by Discord.
1 parent 31025c0 commit e71723e

File tree

5 files changed

+262
-364
lines changed

5 files changed

+262
-364
lines changed

src/constants.rs

Lines changed: 39 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub const USER_AGENT: &str = concat!(
3636
);
3737

3838
enum_number! {
39-
/// An enum representing the [gateway opcodes].
39+
/// An enum representing the gateway opcodes.
4040
///
4141
/// [Discord docs](https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-opcodes).
4242
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
@@ -70,53 +70,43 @@ enum_number! {
7070
}
7171
}
7272

73-
pub mod close_codes {
74-
/// Unknown error; try reconnecting?
75-
///
76-
/// Can reconnect.
77-
pub const UNKNOWN_ERROR: u16 = 4000;
78-
/// Invalid Gateway OP Code.
79-
///
80-
/// Can resume.
81-
pub const UNKNOWN_OPCODE: u16 = 4001;
82-
/// An invalid payload was sent.
83-
///
84-
/// Can resume.
85-
pub const DECODE_ERROR: u16 = 4002;
86-
/// A payload was sent prior to identifying.
87-
///
88-
/// Cannot reconnect.
89-
pub const NOT_AUTHENTICATED: u16 = 4003;
90-
/// The account token sent with the identify payload was incorrect.
91-
///
92-
/// Cannot reconnect.
93-
pub const AUTHENTICATION_FAILED: u16 = 4004;
94-
/// More than one identify payload was sent.
95-
///
96-
/// Can reconnect.
97-
pub const ALREADY_AUTHENTICATED: u16 = 4005;
98-
/// The sequence sent when resuming the session was invalid.
99-
///
100-
/// Can reconnect.
101-
pub const INVALID_SEQUENCE: u16 = 4007;
102-
/// Payloads were being sent too quickly.
103-
///
104-
/// Can resume.
105-
pub const RATE_LIMITED: u16 = 4008;
106-
/// A session timed out.
107-
///
108-
/// Can reconnect.
109-
pub const SESSION_TIMEOUT: u16 = 4009;
110-
/// An invalid shard when identifying was sent.
111-
///
112-
/// Cannot reconnect.
113-
pub const INVALID_SHARD: u16 = 4010;
114-
/// The session would have handled too many guilds.
73+
enum_number! {
74+
/// An enum representing the gateway close codes.
11575
///
116-
/// Cannot reconnect.
117-
pub const SHARDING_REQUIRED: u16 = 4011;
118-
/// Undocumented gateway intents have been provided.
119-
pub const INVALID_GATEWAY_INTENTS: u16 = 4013;
120-
/// Disallowed gateway intents have been provided.
121-
pub const DISALLOWED_GATEWAY_INTENTS: u16 = 4014;
76+
/// [Discord docs](https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-close-event-codes)
77+
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
78+
#[non_exhaustive]
79+
pub enum CloseCode {
80+
/// Unknown error; try reconnecting.
81+
UnknownError = 4000,
82+
/// Invalid gateway opcode.
83+
UnknownOpcode = 4001,
84+
/// An invalid payload was sent.
85+
DecodeError = 4002,
86+
/// A payload was sent prior to identifying, or the session was invalidated.
87+
NotAuthenticated = 4003,
88+
/// The account token sent with the identify payload was incorrect.
89+
AuthenticationFailed = 4004,
90+
/// More than one identify payload was sent.
91+
AlreadyAuthenticated = 4005,
92+
/// The sequence sent when resuming the session was invalid.
93+
InvalidSequence = 4007,
94+
/// Payloads were being sent too quickly.
95+
RateLimited = 4008,
96+
/// The gateway session timed out, and a new one must be started.
97+
SessionTimeout = 4009,
98+
/// An invalid shard was sent when identifying.
99+
InvalidShard = 4010,
100+
/// The session would have handled too many guilds; you must use sharding to connect.
101+
ShardingRequired = 4011,
102+
/// An invalid gateway API version was sent.
103+
InvalidApiVersion = 4012,
104+
/// An invalid gateway intent was sent.
105+
InvalidGatewayIntents = 4013,
106+
/// A disallowed gateway intent was sent; you may have it disabled or may not be approved
107+
/// to use it.
108+
DisallowedGatewayIntents = 4014,
109+
110+
_ => Unknown(u16),
111+
}
122112
}

src/gateway/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ pub enum Error {
2020
HeartbeatFailed,
2121
/// When invalid authentication (a bad token) was sent in the IDENTIFY.
2222
InvalidAuthentication,
23+
/// When an invalid API version was sent to the gateway.
24+
InvalidApiVersion,
2325
/// Expected a Ready or an InvalidateSession
2426
InvalidHandshake,
2527
/// When invalid sharding data was sent in the IDENTIFY.
@@ -71,6 +73,7 @@ impl fmt::Display for Error {
7173
Self::ExpectedHello => f.write_str("Expected a Hello"),
7274
Self::HeartbeatFailed => f.write_str("Failed sending a heartbeat"),
7375
Self::InvalidAuthentication => f.write_str("Sent invalid authentication"),
76+
Self::InvalidApiVersion => f.write_str("Sent invalid API version"),
7477
Self::InvalidHandshake => f.write_str("Expected a valid Handshake"),
7578
Self::InvalidShardData => f.write_str("Sent invalid shard data"),
7679
Self::NoAuthentication => f.write_str("Sent no authentication"),

0 commit comments

Comments
 (0)