Browse Source

Add basic websocket redirect support

tags/docs-0.9
Brandon Smith 9 years ago
parent
commit
43e54f0042
5 changed files with 58 additions and 9 deletions
  1. +15
    -2
      src/Discord.Net/API/Models/TextWebSocketCommands.cs
  2. +6
    -0
      src/Discord.Net/API/Models/TextWebSocketEvents.cs
  3. +32
    -3
      src/Discord.Net/DiscordDataSocket.cs
  4. +1
    -1
      src/Discord.Net/DiscordVoiceSocket.cs
  5. +4
    -3
      src/Discord.Net/DiscordWebSocket.cs

+ 15
- 2
src/Discord.Net/API/Models/TextWebSocketCommands.cs View File

@@ -15,9 +15,11 @@ namespace Discord.API.Models
{ {
[JsonProperty(PropertyName = "op")] [JsonProperty(PropertyName = "op")]
public int Operation; public int Operation;
[JsonProperty(PropertyName = "t")]
[JsonProperty(PropertyName = "t", NullValueHandling = NullValueHandling.Ignore)]
public string Type; public string Type;
[JsonProperty(PropertyName = "d")]
[JsonProperty(PropertyName = "s", NullValueHandling = NullValueHandling.Ignore)]
public int? Sequence;
[JsonProperty(PropertyName = "d", NullValueHandling = NullValueHandling.Ignore)]
public object Payload; public object Payload;
} }
internal abstract class WebSocketMessage<T> : WebSocketMessage internal abstract class WebSocketMessage<T> : WebSocketMessage
@@ -78,5 +80,16 @@ namespace Discord.API.Models
public string SelfDeaf; public string SelfDeaf;
} }
} }
public sealed class Resume : WebSocketMessage<Resume.Data>
{
public Resume() : base(6) { }
public class Data
{
[JsonProperty(PropertyName = "session_id")]
public string SessionId;
[JsonProperty(PropertyName = "seq")]
public int Sequence;
}
}
} }
} }

+ 6
- 0
src/Discord.Net/API/Models/TextWebSocketEvents.cs View File

@@ -36,6 +36,12 @@ namespace Discord.API.Models
public int HeartbeatInterval; public int HeartbeatInterval;
} }


public sealed class Redirect
{
[JsonProperty(PropertyName = "url")]
public string Url;
}

//Servers //Servers
public sealed class GuildCreate : ExtendedServerInfo { } public sealed class GuildCreate : ExtendedServerInfo { }
public sealed class GuildUpdate : ServerInfo { } public sealed class GuildUpdate : ServerInfo { }


+ 32
- 3
src/Discord.Net/DiscordDataSocket.cs View File

@@ -12,6 +12,8 @@ namespace Discord
internal sealed partial class DiscordDataSocket : DiscordWebSocket internal sealed partial class DiscordDataSocket : DiscordWebSocket
{ {
private readonly ManualResetEventSlim _connectWaitOnLogin, _connectWaitOnLogin2; private readonly ManualResetEventSlim _connectWaitOnLogin, _connectWaitOnLogin2;
private string _lastSession, _redirectServer;
private int _lastSeq;


public DiscordDataSocket(DiscordClient client, int timeout, int interval, bool isDebug) public DiscordDataSocket(DiscordClient client, int timeout, int interval, bool isDebug)
: base(client, timeout, interval, isDebug) : base(client, timeout, interval, isDebug)
@@ -20,10 +22,13 @@ namespace Discord
_connectWaitOnLogin2 = new ManualResetEventSlim(false); _connectWaitOnLogin2 = new ManualResetEventSlim(false);
} }


public override Task ConnectAsync(string url)
public override async Task ConnectAsync(string url)
{ {
BeginConnect();
return base.ConnectAsync(url);
_lastSeq = 0;
_lastSession = null;
_redirectServer = null;
await BeginConnect();
await base.ConnectAsync(url);
} }
public async Task Login(string token) public async Task Login(string token)
{ {
@@ -65,6 +70,8 @@ namespace Discord
protected override Task ProcessMessage(string json) protected override Task ProcessMessage(string json)
{ {
var msg = JsonConvert.DeserializeObject<WebSocketMessage>(json); var msg = JsonConvert.DeserializeObject<WebSocketMessage>(json);
if (msg.Sequence.HasValue)
_lastSeq = msg.Sequence.Value;
switch (msg.Operation) switch (msg.Operation)
{ {
case 0: case 0:
@@ -72,6 +79,7 @@ namespace Discord
if (msg.Type == "READY") if (msg.Type == "READY")
{ {
var payload = (msg.Payload as JToken).ToObject<TextWebSocketEvents.Ready>(); var payload = (msg.Payload as JToken).ToObject<TextWebSocketEvents.Ready>();
_lastSession = payload.SessionId;
_heartbeatInterval = payload.HeartbeatInterval; _heartbeatInterval = payload.HeartbeatInterval;
QueueMessage(new TextWebSocketCommands.UpdateStatus()); QueueMessage(new TextWebSocketCommands.UpdateStatus());
//QueueMessage(GetKeepAlive()); //QueueMessage(GetKeepAlive());
@@ -82,6 +90,15 @@ namespace Discord
_connectWaitOnLogin2.Set(); //Post-Event _connectWaitOnLogin2.Set(); //Post-Event
} }
break; break;
case 7:
{
var payload = (msg.Payload as JToken).ToObject<TextWebSocketEvents.Redirect>();
if (_isDebug)
RaiseOnDebugMessage(DebugMessageType.Connection, $"Redirected to {payload.Url}.");
_host = payload.Url;
DisconnectInternal(new Exception("Server is redirecting."), true);
}
break;
default: default:
if (_isDebug) if (_isDebug)
RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownOpCode, "Unknown Opcode: " + msg.Operation); RaiseOnDebugMessage(DebugMessageType.WebSocketUnknownOpCode, "Unknown Opcode: " + msg.Operation);
@@ -107,5 +124,17 @@ namespace Discord
var joinVoice = new TextWebSocketCommands.JoinVoice(); var joinVoice = new TextWebSocketCommands.JoinVoice();
QueueMessage(joinVoice); QueueMessage(joinVoice);
} }

protected override void OnConnect()
{
if (_redirectServer != null)
{
var resumeMsg = new TextWebSocketCommands.Resume();
resumeMsg.Payload.SessionId = _lastSession;
resumeMsg.Payload.Sequence = _lastSeq;
SendMessage(resumeMsg, _disconnectToken.Token);
}
_redirectServer = null;
}
} }
} }

+ 1
- 1
src/Discord.Net/DiscordVoiceSocket.cs View File

@@ -128,7 +128,7 @@ namespace Discord


public new async Task BeginConnect() public new async Task BeginConnect()
{ {
base.BeginConnect();
await base.BeginConnect();
var cancelToken = _disconnectToken.Token; var cancelToken = _disconnectToken.Token;


await Task.Yield(); await Task.Yield();


+ 4
- 3
src/Discord.Net/DiscordWebSocket.cs View File

@@ -40,14 +40,15 @@ namespace Discord
_sendQueue = new ConcurrentQueue<byte[]>(); _sendQueue = new ConcurrentQueue<byte[]>();
} }


protected void BeginConnect()
protected virtual async Task BeginConnect()
{ {
await DisconnectAsync();
_disconnectToken = new CancellationTokenSource(); _disconnectToken = new CancellationTokenSource();
_disconnectReason = null; _disconnectReason = null;
} }
public virtual async Task ConnectAsync(string url) public virtual async Task ConnectAsync(string url)
{ {
await DisconnectAsync();
//await DisconnectAsync();


var cancelToken = _disconnectToken.Token; var cancelToken = _disconnectToken.Token;


@@ -152,7 +153,7 @@ namespace Discord
try try
{ {
result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), cancelToken); result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), cancelToken);
}
}
catch (Win32Exception ex) catch (Win32Exception ex)
when (ex.HResult == HR_TIMEOUT) when (ex.HResult == HR_TIMEOUT)
{ {


Loading…
Cancel
Save