@@ -21,15 +21,15 @@ namespace Discord.API | |||||
=> _http.Get<APIResponses.Gateway>(Endpoints.Gateway); | => _http.Get<APIResponses.Gateway>(Endpoints.Gateway); | ||||
public async Task<APIResponses.AuthRegister> LoginAnonymous(string username) | public async Task<APIResponses.AuthRegister> LoginAnonymous(string username) | ||||
{ | { | ||||
var fingerprintResponse = await _http.Post<APIResponses.AuthFingerprint>(Endpoints.AuthFingerprint); | |||||
var fingerprintResponse = await _http.Post<APIResponses.AuthFingerprint>(Endpoints.AuthFingerprint).ConfigureAwait(false); | |||||
var registerRequest = new APIRequests.AuthRegisterRequest { Fingerprint = fingerprintResponse.Fingerprint, Username = username }; | var registerRequest = new APIRequests.AuthRegisterRequest { Fingerprint = fingerprintResponse.Fingerprint, Username = username }; | ||||
var registerResponse = await _http.Post<APIResponses.AuthRegister>(Endpoints.AuthRegister, registerRequest); | |||||
var registerResponse = await _http.Post<APIResponses.AuthRegister>(Endpoints.AuthRegister, registerRequest).ConfigureAwait(false); | |||||
return registerResponse; | return registerResponse; | ||||
} | } | ||||
public async Task<APIResponses.AuthLogin> Login(string email, string password) | public async Task<APIResponses.AuthLogin> Login(string email, string password) | ||||
{ | { | ||||
var request = new APIRequests.AuthLogin { Email = email, Password = password }; | var request = new APIRequests.AuthLogin { Email = email, Password = password }; | ||||
var response = await _http.Post<APIResponses.AuthLogin>(Endpoints.AuthLogin, request); | |||||
var response = await _http.Post<APIResponses.AuthLogin>(Endpoints.AuthLogin, request).ConfigureAwait(false); | |||||
return response; | return response; | ||||
} | } | ||||
public Task Logout() | public Task Logout() | ||||
@@ -24,7 +24,7 @@ namespace Discord | |||||
if (name == null) throw new ArgumentNullException(nameof(name)); | if (name == null) throw new ArgumentNullException(nameof(name)); | ||||
if (region == null) throw new ArgumentNullException(nameof(region)); | if (region == null) throw new ArgumentNullException(nameof(region)); | ||||
var response = await _api.CreateServer(name, region); | |||||
var response = await _api.CreateServer(name, region).ConfigureAwait(false); | |||||
return _servers.Update(response.Id, response); | return _servers.Update(response.Id, response); | ||||
} | } | ||||
@@ -37,7 +37,7 @@ namespace Discord | |||||
CheckReady(); | CheckReady(); | ||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | ||||
try { await _api.LeaveServer(serverId); } | |||||
try { await _api.LeaveServer(serverId).ConfigureAwait(false); } | |||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | ||||
return _servers.Remove(serverId); | return _servers.Remove(serverId); | ||||
} | } | ||||
@@ -54,7 +54,7 @@ namespace Discord | |||||
if (name == null) throw new ArgumentNullException(nameof(name)); | if (name == null) throw new ArgumentNullException(nameof(name)); | ||||
if (type == null) throw new ArgumentNullException(nameof(type)); | if (type == null) throw new ArgumentNullException(nameof(type)); | ||||
var response = await _api.CreateChannel(serverId, name, type); | |||||
var response = await _api.CreateChannel(serverId, name, type).ConfigureAwait(false); | |||||
return _channels.Update(response.Id, serverId, response); | return _channels.Update(response.Id, serverId, response); | ||||
} | } | ||||
@@ -67,7 +67,7 @@ namespace Discord | |||||
CheckReady(); | CheckReady(); | ||||
if (channelId == null) throw new ArgumentNullException(nameof(channelId)); | if (channelId == null) throw new ArgumentNullException(nameof(channelId)); | ||||
try { await _api.DestroyChannel(channelId); } | |||||
try { await _api.DestroyChannel(channelId).ConfigureAwait(false); } | |||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | ||||
return _channels.Remove(channelId); | return _channels.Remove(channelId); | ||||
} | } | ||||
@@ -108,7 +108,7 @@ namespace Discord | |||||
if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | ||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | if (userId == null) throw new ArgumentNullException(nameof(userId)); | ||||
try { await _api.Unban(serverId, userId); } | |||||
try { await _api.Unban(serverId, userId).ConfigureAwait(false); } | |||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | ||||
} | } | ||||
@@ -139,7 +139,7 @@ namespace Discord | |||||
if (maxAge <= 0) throw new ArgumentOutOfRangeException(nameof(maxAge)); | if (maxAge <= 0) throw new ArgumentOutOfRangeException(nameof(maxAge)); | ||||
if (maxUses <= 0) throw new ArgumentOutOfRangeException(nameof(maxUses)); | if (maxUses <= 0) throw new ArgumentOutOfRangeException(nameof(maxUses)); | ||||
var response = await _api.CreateInvite(channelId, maxAge, maxUses, isTemporary, hasXkcdPass); | |||||
var response = await _api.CreateInvite(channelId, maxAge, maxUses, isTemporary, hasXkcdPass).ConfigureAwait(false); | |||||
_channels.Update(response.Channel.Id, response.Server.Id, response.Channel); | _channels.Update(response.Channel.Id, response.Server.Id, response.Channel); | ||||
_servers.Update(response.Server.Id, response.Server); | _servers.Update(response.Server.Id, response.Server); | ||||
_users.Update(response.Inviter.Id, response.Inviter); | _users.Update(response.Inviter.Id, response.Inviter); | ||||
@@ -163,7 +163,7 @@ namespace Discord | |||||
CheckReady(); | CheckReady(); | ||||
if (id == null) throw new ArgumentNullException(nameof(id)); | if (id == null) throw new ArgumentNullException(nameof(id)); | ||||
var response = await _api.GetInvite(id); | |||||
var response = await _api.GetInvite(id).ConfigureAwait(false); | |||||
return new Invite(response.Code, response.XkcdPass, this) | return new Invite(response.Code, response.XkcdPass, this) | ||||
{ | { | ||||
ChannelId = response.Channel.Id, | ChannelId = response.Channel.Id, | ||||
@@ -195,8 +195,8 @@ namespace Discord | |||||
id = id.Substring(0, id.Length - 1); | id = id.Substring(0, id.Length - 1); | ||||
//Check if this is a human-readable link and get its ID | //Check if this is a human-readable link and get its ID | ||||
var response = await _api.GetInvite(id); | |||||
await _api.AcceptInvite(response.Code); | |||||
var response = await _api.GetInvite(id).ConfigureAwait(false); | |||||
await _api.AcceptInvite(response.Code).ConfigureAwait(false); | |||||
} | } | ||||
/// <summary> Deletes the provided invite. </summary> | /// <summary> Deletes the provided invite. </summary> | ||||
@@ -208,8 +208,8 @@ namespace Discord | |||||
try | try | ||||
{ | { | ||||
//Check if this is a human-readable link and get its ID | //Check if this is a human-readable link and get its ID | ||||
var response = await _api.GetInvite(id); | |||||
await _api.DeleteInvite(response.Code); | |||||
var response = await _api.GetInvite(id).ConfigureAwait(false); | |||||
await _api.DeleteInvite(response.Code).ConfigureAwait(false); | |||||
} | } | ||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | ||||
} | } | ||||
@@ -257,31 +257,28 @@ namespace Discord | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
var msg = await _api.SendMessage(channelId, blockText, mentions, nonce); | |||||
var msg = await _api.SendMessage(channelId, blockText, mentions, nonce).ConfigureAwait(false); | |||||
result[i] = _messages.Update(msg.Id, channelId, msg); | result[i] = _messages.Update(msg.Id, channelId, msg); | ||||
result[i].Nonce = nonce; | result[i].Nonce = nonce; | ||||
try { RaiseMessageSent(result[i]); } catch { } | try { RaiseMessageSent(result[i]); } catch { } | ||||
} | } | ||||
await Task.Delay(1000); | |||||
await Task.Delay(1000).ConfigureAwait(false); | |||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
/// <summary> Sends a private message to the provided channel. </summary> | /// <summary> Sends a private message to the provided channel. </summary> | ||||
public async Task<Message[]> SendPrivateMessage(User user, string text) | public async Task<Message[]> SendPrivateMessage(User user, string text) | ||||
=> await SendMessage(await GetPMChannel(user), text, new string[0]); | |||||
{ | |||||
var channel = await GetPMChannel(user).ConfigureAwait(false); | |||||
return await SendMessage(channel, text, new string[0]).ConfigureAwait(false); | |||||
} | |||||
/// <summary> Sends a private message to the provided channel. </summary> | /// <summary> Sends a private message to the provided channel. </summary> | ||||
public async Task<Message[]> SendPrivateMessage(string userId, string text) | public async Task<Message[]> SendPrivateMessage(string userId, string text) | ||||
=> await SendMessage(await GetPMChannel(userId), text, new string[0]); | |||||
/*/// <summary> Sends a private message to the provided user, mentioning certain users. </summary> | |||||
/// <remarks> While not required, it is recommended to include a mention reference in the text (see User.Mention). </remarks> | |||||
public async Task<Message[]> SendPrivateMessage(User user, string text, string[] mentions) | |||||
=> SendMessage(await GetOrCreatePMChannel(user), text, mentions); | |||||
/// <summary> Sends a private message to the provided user, mentioning certain users. </summary> | |||||
/// <remarks> While not required, it is recommended to include a mention reference in the text (see User.Mention). </remarks> | |||||
public async Task<Message[]> SendPrivateMessage(string userId, string text, string[] mentions) | |||||
=> SendMessage(await GetOrCreatePMChannel(userId), text, mentions);*/ | |||||
{ | |||||
var channel = await GetPMChannel(userId).ConfigureAwait(false); | |||||
return await SendMessage(channel, text, new string[0]).ConfigureAwait(false); | |||||
} | |||||
/// <summary> Edits a message the provided message. </summary> | /// <summary> Edits a message the provided message. </summary> | ||||
public Task EditMessage(Message message, string text) | public Task EditMessage(Message message, string text) | ||||
@@ -313,7 +310,7 @@ namespace Discord | |||||
if (text.Length > DiscordAPI.MaxMessageSize) | if (text.Length > DiscordAPI.MaxMessageSize) | ||||
text = text.Substring(0, DiscordAPI.MaxMessageSize); | text = text.Substring(0, DiscordAPI.MaxMessageSize); | ||||
var msg = await _api.EditMessage(channelId, messageId, text, mentions); | |||||
var msg = await _api.EditMessage(channelId, messageId, text, mentions).ConfigureAwait(false); | |||||
_messages.Update(msg.Id, channelId, msg); | _messages.Update(msg.Id, channelId, msg); | ||||
} | } | ||||
@@ -329,7 +326,7 @@ namespace Discord | |||||
try | try | ||||
{ | { | ||||
await _api.DeleteMessage(channelId, msgId); | |||||
await _api.DeleteMessage(channelId, msgId).ConfigureAwait(false); | |||||
_messages.Remove(msgId); | _messages.Remove(msgId); | ||||
} | } | ||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | ||||
@@ -343,7 +340,7 @@ namespace Discord | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
await _api.DeleteMessage(msg.ChannelId, msg.Id); | |||||
await _api.DeleteMessage(msg.ChannelId, msg.Id).ConfigureAwait(false); | |||||
} | } | ||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | ||||
} | } | ||||
@@ -357,7 +354,7 @@ namespace Discord | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
await _api.DeleteMessage(channelId, msgId); | |||||
await _api.DeleteMessage(channelId, msgId).ConfigureAwait(false); | |||||
} | } | ||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } | ||||
} | } | ||||
@@ -404,7 +401,7 @@ namespace Discord | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
var msgs = await _api.GetMessages(channel.Id, count); | |||||
var msgs = await _api.GetMessages(channel.Id, count).ConfigureAwait(false); | |||||
return msgs.OrderBy(x => x.Timestamp) | return msgs.OrderBy(x => x.Timestamp) | ||||
.Select(x => | .Select(x => | ||||
{ | { | ||||
@@ -503,21 +500,21 @@ namespace Discord | |||||
public async Task ChangeUsername(string newName, string currentEmail, string currentPassword) | public async Task ChangeUsername(string newName, string currentEmail, string currentPassword) | ||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
var response = await _api.ChangeUsername(newName, currentEmail, currentPassword); | |||||
var response = await _api.ChangeUsername(newName, currentEmail, currentPassword).ConfigureAwait(false); | |||||
_users.Update(response.Id, response); | _users.Update(response.Id, response); | ||||
} | } | ||||
/// <summary> Changes your email to newEmail. </summary> | /// <summary> Changes your email to newEmail. </summary> | ||||
public async Task ChangeEmail(string newEmail, string currentPassword) | public async Task ChangeEmail(string newEmail, string currentPassword) | ||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
var response = await _api.ChangeEmail(newEmail, currentPassword); | |||||
var response = await _api.ChangeEmail(newEmail, currentPassword).ConfigureAwait(false); | |||||
_users.Update(response.Id, response); | _users.Update(response.Id, response); | ||||
} | } | ||||
/// <summary> Changes your password to newPassword. </summary> | /// <summary> Changes your password to newPassword. </summary> | ||||
public async Task ChangePassword(string newPassword, string currentEmail, string currentPassword) | public async Task ChangePassword(string newPassword, string currentEmail, string currentPassword) | ||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
var response = await _api.ChangePassword(newPassword, currentEmail, currentPassword); | |||||
var response = await _api.ChangePassword(newPassword, currentEmail, currentPassword).ConfigureAwait(false); | |||||
_users.Update(response.Id, response); | _users.Update(response.Id, response); | ||||
} | } | ||||
@@ -526,7 +523,7 @@ namespace Discord | |||||
public async Task ChangeAvatar(AvatarImageType imageType, byte[] bytes, string currentEmail, string currentPassword) | public async Task ChangeAvatar(AvatarImageType imageType, byte[] bytes, string currentEmail, string currentPassword) | ||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
var response = await _api.ChangeAvatar(imageType, bytes, currentEmail, currentPassword); | |||||
var response = await _api.ChangeAvatar(imageType, bytes, currentEmail, currentPassword).ConfigureAwait(false); | |||||
_users.Update(response.Id, response); | _users.Update(response.Id, response); | ||||
} | } | ||||
} | } | ||||
@@ -403,14 +403,14 @@ namespace Discord | |||||
var channel = user.PrivateChannel; | var channel = user.PrivateChannel; | ||||
if (channel != null) | if (channel != null) | ||||
return channel; | return channel; | ||||
return await CreatePMChannel(user?.Id); | |||||
return await CreatePMChannel(user?.Id).ConfigureAwait(false); | |||||
} | } | ||||
private async Task<Channel> CreatePMChannel(string userId) | private async Task<Channel> CreatePMChannel(string userId) | ||||
{ | { | ||||
CheckReady(); | CheckReady(); | ||||
if (userId == null) throw new ArgumentNullException(nameof(userId)); | if (userId == null) throw new ArgumentNullException(nameof(userId)); | ||||
var response = await _api.CreatePMChannel(_myId, userId); | |||||
var response = await _api.CreatePMChannel(_myId, userId).ConfigureAwait(false); | |||||
return _channels.Update(response.Id, response); | return _channels.Update(response.Id, response); | ||||
} | } | ||||
@@ -107,21 +107,21 @@ namespace Discord | |||||
//Reconnect if we didn't cause the disconnect | //Reconnect if we didn't cause the disconnect | ||||
if (e.WasUnexpected) | if (e.WasUnexpected) | ||||
{ | { | ||||
await Task.Delay(_config.ReconnectDelay); | |||||
await Task.Delay(_config.ReconnectDelay).ConfigureAwait(false); | |||||
while (!_disconnectToken.IsCancellationRequested) | while (!_disconnectToken.IsCancellationRequested) | ||||
{ | { | ||||
try | try | ||||
{ | { | ||||
await _webSocket.ReconnectAsync(); | |||||
await _webSocket.ReconnectAsync().ConfigureAwait(false); | |||||
if (_http.Token != null) | if (_http.Token != null) | ||||
await _webSocket.Login(_http.Token); | |||||
await _webSocket.Login(_http.Token).ConfigureAwait(false); | |||||
break; | break; | ||||
} | } | ||||
catch (Exception ex) | catch (Exception ex) | ||||
{ | { | ||||
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket reconnect failed: {ex.Message}"); | RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket reconnect failed: {ex.Message}"); | ||||
//Net is down? We can keep trying to reconnect until the user runs Disconnect() | //Net is down? We can keep trying to reconnect until the user runs Disconnect() | ||||
await Task.Delay(_config.FailedReconnectDelay); | |||||
await Task.Delay(_config.FailedReconnectDelay).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -141,12 +141,12 @@ namespace Discord | |||||
//Reconnect if we didn't cause the disconnect | //Reconnect if we didn't cause the disconnect | ||||
if (e.WasUnexpected) | if (e.WasUnexpected) | ||||
{ | { | ||||
await Task.Delay(_config.ReconnectDelay); | |||||
await Task.Delay(_config.ReconnectDelay).ConfigureAwait(false); | |||||
while (!_disconnectToken.IsCancellationRequested) | while (!_disconnectToken.IsCancellationRequested) | ||||
{ | { | ||||
try | try | ||||
{ | { | ||||
await _voiceWebSocket.ReconnectAsync(); | |||||
await _voiceWebSocket.ReconnectAsync().ConfigureAwait(false); | |||||
break; | break; | ||||
} | } | ||||
catch (Exception ex) | catch (Exception ex) | ||||
@@ -154,7 +154,7 @@ namespace Discord | |||||
if (_isDebugMode) | if (_isDebugMode) | ||||
RaiseOnDebugMessage(DebugMessageType.Connection, $"VoiceSocket reconnect failed: {ex.Message}"); | RaiseOnDebugMessage(DebugMessageType.Connection, $"VoiceSocket reconnect failed: {ex.Message}"); | ||||
//Net is down? We can keep trying to reconnect until the user runs Disconnect() | //Net is down? We can keep trying to reconnect until the user runs Disconnect() | ||||
await Task.Delay(_config.FailedReconnectDelay); | |||||
await Task.Delay(_config.FailedReconnectDelay).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -426,7 +426,7 @@ namespace Discord | |||||
if (_config.EnableVoice) | if (_config.EnableVoice) | ||||
{ | { | ||||
_voiceWebSocket.SetSessionData(data.ServerId, _myId, _sessionId, data.Token); | _voiceWebSocket.SetSessionData(data.ServerId, _myId, _sessionId, data.Token); | ||||
await _voiceWebSocket.ConnectAsync("wss://" + data.Endpoint.Split(':')[0]); | |||||
await _voiceWebSocket.ConnectAsync("wss://" + data.Endpoint.Split(':')[0]).ConfigureAwait(false); | |||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
@@ -469,7 +469,7 @@ namespace Discord | |||||
APIResponses.SendMessage apiMsg = null; | APIResponses.SendMessage apiMsg = null; | ||||
try | try | ||||
{ | { | ||||
apiMsg = await _api.SendMessage(msg.ChannelId, msg.RawText, msg.MentionIds, msg.Nonce); | |||||
apiMsg = await _api.SendMessage(msg.ChannelId, msg.RawText, msg.MentionIds, msg.Nonce).ConfigureAwait(false); | |||||
} | } | ||||
catch (WebException) { break; } | catch (WebException) { break; } | ||||
catch (HttpException) { hasFailed = true; } | catch (HttpException) { hasFailed = true; } | ||||
@@ -483,7 +483,7 @@ namespace Discord | |||||
msg.HasFailed = hasFailed; | msg.HasFailed = hasFailed; | ||||
try { RaiseMessageSent(msg); } catch { } | try { RaiseMessageSent(msg); } catch { } | ||||
} | } | ||||
await Task.Delay(_config.MessageQueueInterval); | |||||
await Task.Delay(_config.MessageQueueInterval).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
catch { } | catch { } | ||||
@@ -499,49 +499,36 @@ namespace Discord | |||||
/// <summary> Connects to the Discord server with the provided token. </summary> | /// <summary> Connects to the Discord server with the provided token. </summary> | ||||
public async Task Connect(string token) | public async Task Connect(string token) | ||||
{ | { | ||||
await Disconnect(); | |||||
await Disconnect().ConfigureAwait(false); | |||||
if (_isDebugMode) | if (_isDebugMode) | ||||
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket is using cached token."); | RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket is using cached token."); | ||||
await ConnectInternal(token); | |||||
await ConnectInternal(token).ConfigureAwait(false); | |||||
} | } | ||||
/// <summary> Connects to the Discord server with the provided email and password. </summary> | /// <summary> Connects to the Discord server with the provided email and password. </summary> | ||||
/// <returns> Returns a token for future connections. </returns> | /// <returns> Returns a token for future connections. </returns> | ||||
public async Task<string> Connect(string email, string password) | public async Task<string> Connect(string email, string password) | ||||
{ | { | ||||
await Disconnect(); | |||||
await Disconnect().ConfigureAwait(false); | |||||
var response = await _api.Login(email, password); | |||||
var response = await _api.Login(email, password).ConfigureAwait(false); | |||||
if (_isDebugMode) | if (_isDebugMode) | ||||
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket got token."); | RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket got token."); | ||||
return await ConnectInternal(response.Token); | |||||
return await ConnectInternal(response.Token).ConfigureAwait(false); | |||||
} | } | ||||
/// <summary> Connects to the Discord server as an anonymous user with the provided username. </summary> | |||||
/// <returns> Returns a token for future connections. </returns> | |||||
/*public async Task<string> ConnectAnonymous(string username) | |||||
{ | |||||
await Disconnect(); | |||||
var response = await _api.LoginAnonymous(username); | |||||
if (_isDebugMode) | |||||
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket got anonymous token."); | |||||
_http.Token = response.Token; | |||||
return await ConnectInternal(response.Token); | |||||
}*/ | |||||
private async Task<string> ConnectInternal(string token) | private async Task<string> ConnectInternal(string token) | ||||
{ | { | ||||
_blockEvent.Reset(); | _blockEvent.Reset(); | ||||
_http.Token = token; | _http.Token = token; | ||||
string url = (await _api.GetWebSocketEndpoint()).Url; | |||||
string url = (await _api.GetWebSocketEndpoint().ConfigureAwait(false)).Url; | |||||
if (_isDebugMode) | if (_isDebugMode) | ||||
RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket got endpoint."); | RaiseOnDebugMessage(DebugMessageType.Connection, $"DataSocket got endpoint."); | ||||
await _webSocket.ConnectAsync(url); | |||||
await _webSocket.Login(token); | |||||
await _webSocket.ConnectAsync(url).ConfigureAwait(false); | |||||
await _webSocket.Login(token).ConfigureAwait(false); | |||||
_disconnectToken = new CancellationTokenSource(); | _disconnectToken = new CancellationTokenSource(); | ||||
if (_config.UseMessageQueue) | if (_config.UseMessageQueue) | ||||
@@ -550,10 +537,10 @@ namespace Discord | |||||
_mainTask = _disconnectToken.Wait(); | _mainTask = _disconnectToken.Wait(); | ||||
_mainTask = _mainTask.ContinueWith(async x => | _mainTask = _mainTask.ContinueWith(async x => | ||||
{ | { | ||||
await _webSocket.DisconnectAsync(); | |||||
await _webSocket.DisconnectAsync().ConfigureAwait(false); | |||||
#if !DNXCORE50 | #if !DNXCORE50 | ||||
if (_config.EnableVoice) | if (_config.EnableVoice) | ||||
await _voiceWebSocket.DisconnectAsync(); | |||||
await _voiceWebSocket.DisconnectAsync().ConfigureAwait(false); | |||||
#endif | #endif | ||||
//Clear send queue | //Clear send queue | ||||
@@ -569,7 +556,7 @@ namespace Discord | |||||
_blockEvent.Set(); | _blockEvent.Set(); | ||||
_mainTask = null; | _mainTask = null; | ||||
}).Unwrap(); | }).Unwrap(); | ||||
_isConnected = true; | |||||
_isConnected = true; | |||||
return token; | return token; | ||||
} | } | ||||
/// <summary> Disconnects from the Discord server, canceling any pending requests. </summary> | /// <summary> Disconnects from the Discord server, canceling any pending requests. </summary> | ||||
@@ -578,7 +565,7 @@ namespace Discord | |||||
if (_mainTask != null) | if (_mainTask != null) | ||||
{ | { | ||||
try { _disconnectToken.Cancel(); } catch (NullReferenceException) { } | try { _disconnectToken.Cancel(); } catch (NullReferenceException) { } | ||||
try { await _mainTask; } catch (NullReferenceException) { } | |||||
try { await _mainTask.ConfigureAwait(false); } catch (NullReferenceException) { } | |||||
} | } | ||||
} | } | ||||
@@ -591,13 +578,13 @@ namespace Discord | |||||
CheckVoice(); | CheckVoice(); | ||||
if (channel == null) throw new ArgumentNullException(nameof(channel)); | if (channel == null) throw new ArgumentNullException(nameof(channel)); | ||||
await LeaveVoiceServer(); | |||||
await LeaveVoiceServer().ConfigureAwait(false); | |||||
//_currentVoiceServerId = channel.ServerId; | //_currentVoiceServerId = channel.ServerId; | ||||
_webSocket.JoinVoice(channel); | _webSocket.JoinVoice(channel); | ||||
#if !DNXCORE50 | #if !DNXCORE50 | ||||
await _voiceWebSocket.BeginConnect(); | |||||
await _voiceWebSocket.BeginConnect().ConfigureAwait(false); | |||||
#else | #else | ||||
await Task.CompletedTask; | |||||
await Task.CompletedTask.ConfigureAwait(false); | |||||
#endif | #endif | ||||
} | } | ||||
@@ -607,9 +594,9 @@ namespace Discord | |||||
CheckVoice(); | CheckVoice(); | ||||
#if !DNXCORE50 | #if !DNXCORE50 | ||||
await _voiceWebSocket.DisconnectAsync(); | |||||
await _voiceWebSocket.DisconnectAsync().ConfigureAwait(false); | |||||
#else | #else | ||||
await Task.CompletedTask; | |||||
await Task.CompletedTask.ConfigureAwait(false); | |||||
#endif | #endif | ||||
//if (_voiceWebSocket.CurrentVoiceServerId != null) | //if (_voiceWebSocket.CurrentVoiceServerId != null) | ||||
_webSocket.LeaveVoice(); | _webSocket.LeaveVoice(); | ||||
@@ -654,7 +641,7 @@ namespace Discord | |||||
#if !DNXCORE50 | #if !DNXCORE50 | ||||
_voiceWebSocket.Wait(); | _voiceWebSocket.Wait(); | ||||
#endif | #endif | ||||
await TaskHelper.CompletedTask; | |||||
await TaskHelper.CompletedTask.ConfigureAwait(false); | |||||
} | } | ||||
//Helpers | //Helpers | ||||
@@ -27,8 +27,8 @@ namespace Discord | |||||
_lastSeq = 0; | _lastSeq = 0; | ||||
_lastSession = null; | _lastSession = null; | ||||
_redirectServer = null; | _redirectServer = null; | ||||
await BeginConnect(); | |||||
await base.ConnectAsync(url); | |||||
await BeginConnect().ConfigureAwait(false); | |||||
await base.ConnectAsync(url).ConfigureAwait(false); | |||||
} | } | ||||
public async Task Login(string token) | public async Task Login(string token) | ||||
{ | { | ||||
@@ -44,7 +44,7 @@ namespace Discord | |||||
msg.Payload.Properties["$device"] = "Discord.Net"; | msg.Payload.Properties["$device"] = "Discord.Net"; | ||||
msg.Payload.Properties["$referrer"] = ""; | msg.Payload.Properties["$referrer"] = ""; | ||||
msg.Payload.Properties["$referring_domain"] = ""; | msg.Payload.Properties["$referring_domain"] = ""; | ||||
await SendMessage(msg, cancelToken); | |||||
await SendMessage(msg, cancelToken).ConfigureAwait(false); | |||||
try | try | ||||
{ | { | ||||
@@ -14,6 +14,7 @@ using System.Threading; | |||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using System.Text; | using System.Text; | ||||
using WebSocketMessage = Discord.API.Models.VoiceWebSocketCommands.WebSocketMessage; | using WebSocketMessage = Discord.API.Models.VoiceWebSocketCommands.WebSocketMessage; | ||||
using Discord.Helpers; | |||||
namespace Discord | namespace Discord | ||||
{ | { | ||||
@@ -65,29 +66,26 @@ namespace Discord | |||||
_isClearing = false; | _isClearing = false; | ||||
var cancelToken = _disconnectToken.Token; | var cancelToken = _disconnectToken.Token; | ||||
Task.Factory.StartNew(async () => | |||||
Task.Run(async () => | |||||
{ | { | ||||
_connectWaitOnLogin.Reset(); | |||||
VoiceWebSocketCommands.Login msg = new VoiceWebSocketCommands.Login(); | |||||
msg.Payload.ServerId = _serverId; | |||||
msg.Payload.SessionId = _sessionId; | |||||
msg.Payload.Token = _token; | |||||
msg.Payload.UserId = _userId; | |||||
await SendMessage(msg, cancelToken); | |||||
try | try | ||||
{ | { | ||||
_connectWaitOnLogin.Reset(); | |||||
VoiceWebSocketCommands.Login msg = new VoiceWebSocketCommands.Login(); | |||||
msg.Payload.ServerId = _serverId; | |||||
msg.Payload.SessionId = _sessionId; | |||||
msg.Payload.Token = _token; | |||||
msg.Payload.UserId = _userId; | |||||
await SendMessage(msg, cancelToken).ConfigureAwait(false); | |||||
if (!_connectWaitOnLogin.Wait(_timeout, cancelToken)) | if (!_connectWaitOnLogin.Wait(_timeout, cancelToken)) | ||||
return; | return; | ||||
} | |||||
catch (OperationCanceledException) | |||||
{ | |||||
return; | |||||
} | |||||
SetConnected(); | |||||
}); | |||||
SetConnected(); | |||||
} | |||||
catch (OperationCanceledException) { } | |||||
}, _disconnectToken.Token); | |||||
} | } | ||||
protected override void OnDisconnect() | protected override void OnDisconnect() | ||||
{ | { | ||||
@@ -128,41 +126,45 @@ namespace Discord | |||||
public new async Task BeginConnect() | public new async Task BeginConnect() | ||||
{ | { | ||||
await base.BeginConnect(); | |||||
await base.BeginConnect().ConfigureAwait(false); | |||||
var cancelToken = _disconnectToken.Token; | var cancelToken = _disconnectToken.Token; | ||||
await Task.Yield(); | |||||
try | |||||
{ | |||||
if (!_connectWaitOnLogin.Wait(_timeout, cancelToken)) //Waiting on JoinServer message | |||||
throw new Exception("No reply from Discord server"); | |||||
} | |||||
catch (OperationCanceledException) | |||||
await Task.Factory.StartNew(() => | |||||
{ | { | ||||
if (_disconnectReason == null) | |||||
throw new Exception("An unknown websocket error occurred."); | |||||
else | |||||
_disconnectReason.Throw(); | |||||
} | |||||
try | |||||
{ | |||||
if (!_connectWaitOnLogin.Wait(_timeout, cancelToken)) //Waiting on JoinServer message | |||||
throw new Exception("No reply from Discord server"); | |||||
} | |||||
catch (OperationCanceledException) | |||||
{ | |||||
if (_disconnectReason == null) | |||||
throw new Exception("An unknown websocket error occurred."); | |||||
else | |||||
_disconnectReason.Throw(); | |||||
} | |||||
}).ConfigureAwait(false); | |||||
} | } | ||||
private async Task ReceiveVoiceAsync() | private async Task ReceiveVoiceAsync() | ||||
{ | { | ||||
var cancelSource = _disconnectToken; | var cancelSource = _disconnectToken; | ||||
var cancelToken = cancelSource.Token; | var cancelToken = cancelSource.Token; | ||||
await Task.Yield(); | |||||
try | |||||
await Task.Run(async () => | |||||
{ | { | ||||
while (!cancelToken.IsCancellationRequested) | |||||
try | |||||
{ | { | ||||
var result = await _udp.ReceiveAsync(); | |||||
ProcessUdpMessage(result); | |||||
while (!cancelToken.IsCancellationRequested) | |||||
{ | |||||
var result = await _udp.ReceiveAsync().ConfigureAwait(false); | |||||
ProcessUdpMessage(result); | |||||
} | |||||
} | } | ||||
} | |||||
catch (OperationCanceledException) { } | |||||
catch (ObjectDisposedException) { } | |||||
catch (Exception ex) { DisconnectInternal(ex); } | |||||
catch (OperationCanceledException) { } | |||||
catch (ObjectDisposedException) { } | |||||
catch (Exception ex) { DisconnectInternal(ex); } | |||||
}).ConfigureAwait(false); | |||||
} | } | ||||
#if USE_THREAD | #if USE_THREAD | ||||
@@ -170,11 +172,12 @@ namespace Discord | |||||
{ | { | ||||
var cancelToken = cancelSource.Token; | var cancelToken = cancelSource.Token; | ||||
#else | #else | ||||
private async Task SendVoiceAsync() | |||||
private Task SendVoiceAsync() | |||||
{ | { | ||||
var cancelSource = _disconnectToken; | var cancelSource = _disconnectToken; | ||||
var cancelToken = cancelSource.Token; | var cancelToken = cancelSource.Token; | ||||
await Task.Yield(); | |||||
return Task.Run(() => | |||||
{ | |||||
#endif | #endif | ||||
byte[] packet; | byte[] packet; | ||||
@@ -224,7 +227,7 @@ namespace Discord | |||||
#if USE_THREAD | #if USE_THREAD | ||||
_udp.Send(rtpPacket, packet.Length + 12); | _udp.Send(rtpPacket, packet.Length + 12); | ||||
#else | #else | ||||
await _udp.SendAsync(rtpPacket, packet.Length + 12); | |||||
await _udp.SendAsync(rtpPacket, packet.Length + 12).ConfigureAwait(false); | |||||
#endif | #endif | ||||
} | } | ||||
timestamp = unchecked(timestamp + samplesPerFrame); | timestamp = unchecked(timestamp + samplesPerFrame); | ||||
@@ -247,24 +250,23 @@ namespace Discord | |||||
#if USE_THREAD | #if USE_THREAD | ||||
Thread.Sleep(1); | Thread.Sleep(1); | ||||
#else | #else | ||||
await Task.Delay(1); | |||||
await Task.Delay(1).ConfigureAwait(false); | |||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
catch (OperationCanceledException) { } | catch (OperationCanceledException) { } | ||||
catch (ObjectDisposedException) { } | catch (ObjectDisposedException) { } | ||||
catch (Exception ex) { DisconnectInternal(ex); } | catch (Exception ex) { DisconnectInternal(ex); } | ||||
} | |||||
//Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken | |||||
private async Task WatcherAsync() | |||||
#if !USE_THREAD | |||||
}).ConfigureAwait(false); | |||||
#endif | |||||
} | |||||
//Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken | |||||
private Task WatcherAsync() | |||||
{ | { | ||||
var cancelToken = _disconnectToken.Token; | var cancelToken = _disconnectToken.Token; | ||||
try | |||||
{ | |||||
await Task.Delay(-1, cancelToken); | |||||
} | |||||
catch (OperationCanceledException) { } | |||||
finally { _udp.Close(); } | |||||
return cancelToken.Wait() | |||||
.ContinueWith(_ => _udp.Close()); | |||||
} | } | ||||
protected override async Task ProcessMessage(string json) | protected override async Task ProcessMessage(string json) | ||||
@@ -279,7 +281,7 @@ namespace Discord | |||||
var payload = (msg.Payload as JToken).ToObject<VoiceWebSocketEvents.Ready>(); | var payload = (msg.Payload as JToken).ToObject<VoiceWebSocketEvents.Ready>(); | ||||
_heartbeatInterval = payload.HeartbeatInterval; | _heartbeatInterval = payload.HeartbeatInterval; | ||||
_ssrc = payload.SSRC; | _ssrc = payload.SSRC; | ||||
_endpoint = new IPEndPoint((await Dns.GetHostAddressesAsync(_host.Replace("wss://", ""))).FirstOrDefault(), payload.Port); | |||||
_endpoint = new IPEndPoint((await Dns.GetHostAddressesAsync(_host.Replace("wss://", "")).ConfigureAwait(false)).FirstOrDefault(), payload.Port); | |||||
//_mode = payload.Modes.LastOrDefault(); | //_mode = payload.Modes.LastOrDefault(); | ||||
_mode = "plain"; | _mode = "plain"; | ||||
_udp.Connect(_endpoint); | _udp.Connect(_endpoint); | ||||
@@ -295,7 +297,7 @@ namespace Discord | |||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | ||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | ||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | ||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, 70); | |||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, 70).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
@@ -42,19 +42,17 @@ namespace Discord | |||||
protected virtual async Task BeginConnect() | protected virtual async Task BeginConnect() | ||||
{ | { | ||||
await DisconnectAsync(); | |||||
await DisconnectAsync().ConfigureAwait(false); | |||||
_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(); | |||||
var cancelToken = _disconnectToken.Token; | var cancelToken = _disconnectToken.Token; | ||||
_webSocket = new ClientWebSocket(); | _webSocket = new ClientWebSocket(); | ||||
_webSocket.Options.KeepAliveInterval = TimeSpan.Zero; | _webSocket.Options.KeepAliveInterval = TimeSpan.Zero; | ||||
await _webSocket.ConnectAsync(new Uri(url), cancelToken); | |||||
await _webSocket.ConnectAsync(new Uri(url), cancelToken).ConfigureAwait(false); | |||||
_host = url; | _host = url; | ||||
if (_isDebug) | if (_isDebug) | ||||
@@ -99,7 +97,7 @@ namespace Discord | |||||
if (_task != null) | if (_task != null) | ||||
{ | { | ||||
try { DisconnectInternal(new Exception("Disconnect requested by user."), false); } catch (NullReferenceException) { } | try { DisconnectInternal(new Exception("Disconnect requested by user."), false); } catch (NullReferenceException) { } | ||||
try { await _task; } catch (NullReferenceException) { } | |||||
try { await _task.ConfigureAwait(false); } catch (NullReferenceException) { } | |||||
} | } | ||||
} | } | ||||
@@ -131,90 +129,94 @@ namespace Discord | |||||
}; | }; | ||||
} | } | ||||
private async Task ReceiveAsync() | |||||
private Task ReceiveAsync() | |||||
{ | { | ||||
var cancelSource = _disconnectToken; | var cancelSource = _disconnectToken; | ||||
var cancelToken = cancelSource.Token; | var cancelToken = cancelSource.Token; | ||||
await Task.Yield(); | |||||
var buffer = new byte[ReceiveChunkSize]; | |||||
var builder = new StringBuilder(); | |||||
try | |||||
return Task.Run(async () => | |||||
{ | { | ||||
while (_webSocket.State == WebSocketState.Open && !cancelToken.IsCancellationRequested) | |||||
var buffer = new byte[ReceiveChunkSize]; | |||||
var builder = new StringBuilder(); | |||||
try | |||||
{ | { | ||||
WebSocketReceiveResult result = null; | |||||
do | |||||
while (_webSocket.State == WebSocketState.Open && !cancelToken.IsCancellationRequested) | |||||
{ | { | ||||
if (_webSocket.State != WebSocketState.Open || cancelToken.IsCancellationRequested) | |||||
return; | |||||
try | |||||
WebSocketReceiveResult result = null; | |||||
do | |||||
{ | { | ||||
result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), cancelToken); | |||||
} | |||||
catch (Win32Exception ex) | |||||
when (ex.HResult == HR_TIMEOUT) | |||||
{ | |||||
string msg = $"Connection timed out."; | |||||
RaiseOnDebugMessage(DebugMessageType.Connection, msg); | |||||
DisconnectInternal(new Exception(msg)); | |||||
return; | |||||
} | |||||
if (_webSocket.State != WebSocketState.Open || cancelToken.IsCancellationRequested) | |||||
return; | |||||
try | |||||
{ | |||||
result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), cancelToken).ConfigureAwait(false); | |||||
} | |||||
catch (Win32Exception ex) | |||||
when (ex.HResult == HR_TIMEOUT) | |||||
{ | |||||
string msg = $"Connection timed out."; | |||||
RaiseOnDebugMessage(DebugMessageType.Connection, msg); | |||||
DisconnectInternal(new Exception(msg)); | |||||
return; | |||||
} | |||||
if (result.MessageType == WebSocketMessageType.Close) | |||||
{ | |||||
string msg = $"Got Close Message ({result.CloseStatus?.ToString() ?? "Unexpected"}, {result.CloseStatusDescription ?? "No Reason"})"; | |||||
RaiseOnDebugMessage(DebugMessageType.Connection, msg); | |||||
DisconnectInternal(new Exception(msg)); | |||||
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).ConfigureAwait(false); | |||||
return; | |||||
} | |||||
else | |||||
builder.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); | |||||
if (result.MessageType == WebSocketMessageType.Close) | |||||
{ | |||||
string msg = $"Got Close Message ({result.CloseStatus?.ToString() ?? "Unexpected"}, {result.CloseStatusDescription ?? "No Reason"})"; | |||||
RaiseOnDebugMessage(DebugMessageType.Connection, msg); | |||||
DisconnectInternal(new Exception(msg)); | |||||
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); | |||||
return; | |||||
} | } | ||||
else | |||||
builder.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); | |||||
} | |||||
while (result == null || !result.EndOfMessage); | |||||
while (result == null || !result.EndOfMessage); | |||||
#if DEBUG | #if DEBUG | ||||
System.Diagnostics.Debug.WriteLine(">>> " + builder.ToString()); | |||||
System.Diagnostics.Debug.WriteLine(">>> " + builder.ToString()); | |||||
#endif | #endif | ||||
await ProcessMessage(builder.ToString()); | |||||
await ProcessMessage(builder.ToString()).ConfigureAwait(false); | |||||
builder.Clear(); | |||||
builder.Clear(); | |||||
} | |||||
} | } | ||||
} | |||||
catch (OperationCanceledException) { } | |||||
catch (Exception ex) { DisconnectInternal(ex); } | |||||
} | |||||
private async Task SendAsync() | |||||
catch (OperationCanceledException) { } | |||||
catch (Exception ex) { DisconnectInternal(ex); } | |||||
}); | |||||
} | |||||
private Task SendAsync() | |||||
{ | { | ||||
var cancelSource = _disconnectToken; | var cancelSource = _disconnectToken; | ||||
var cancelToken = cancelSource.Token; | var cancelToken = cancelSource.Token; | ||||
await Task.Yield(); | |||||
try | |||||
return Task.Run(async () => | |||||
{ | { | ||||
byte[] bytes; | |||||
while (_webSocket.State == WebSocketState.Open && !cancelToken.IsCancellationRequested) | |||||
try | |||||
{ | { | ||||
if (_heartbeatInterval > 0) | |||||
byte[] bytes; | |||||
while (_webSocket.State == WebSocketState.Open && !cancelToken.IsCancellationRequested) | |||||
{ | { | ||||
DateTime now = DateTime.UtcNow; | |||||
if ((now - _lastHeartbeat).TotalMilliseconds > _heartbeatInterval) | |||||
if (_heartbeatInterval > 0) | |||||
{ | { | ||||
await SendMessage(GetKeepAlive(), cancelToken); | |||||
_lastHeartbeat = now; | |||||
DateTime now = DateTime.UtcNow; | |||||
if ((now - _lastHeartbeat).TotalMilliseconds > _heartbeatInterval) | |||||
{ | |||||
await SendMessage(GetKeepAlive(), cancelToken).ConfigureAwait(false); | |||||
_lastHeartbeat = now; | |||||
} | |||||
} | } | ||||
while (_sendQueue.TryDequeue(out bytes)) | |||||
await SendMessage(bytes, cancelToken).ConfigureAwait(false); | |||||
await Task.Delay(_sendInterval, cancelToken).ConfigureAwait(false); | |||||
} | } | ||||
while (_sendQueue.TryDequeue(out bytes)) | |||||
await SendMessage(bytes, cancelToken); | |||||
await Task.Delay(_sendInterval, cancelToken); | |||||
} | } | ||||
} | |||||
catch (OperationCanceledException) { } | |||||
catch (Exception ex) { DisconnectInternal(ex); } | |||||
catch (OperationCanceledException) { } | |||||
catch (Exception ex) { DisconnectInternal(ex); } | |||||
}); | |||||
} | } | ||||
protected abstract Task ProcessMessage(string json); | protected abstract Task ProcessMessage(string json); | ||||
@@ -252,7 +254,7 @@ namespace Discord | |||||
try | try | ||||
{ | { | ||||
await _webSocket.SendAsync(new ArraySegment<byte>(message, offset, count), WebSocketMessageType.Text, isLast, cancelToken); | |||||
await _webSocket.SendAsync(new ArraySegment<byte>(message, offset, count), WebSocketMessageType.Text, isLast, cancelToken).ConfigureAwait(false); | |||||
} | } | ||||
catch (Win32Exception ex) | catch (Win32Exception ex) | ||||
when (ex.HResult == HR_TIMEOUT) | when (ex.HResult == HR_TIMEOUT) | ||||
@@ -9,12 +9,12 @@ namespace Discord.Helpers | |||||
public static async Task Wait(this CancellationTokenSource tokenSource) | public static async Task Wait(this CancellationTokenSource tokenSource) | ||||
{ | { | ||||
var token = tokenSource.Token; | var token = tokenSource.Token; | ||||
try { await Task.Delay(-1, token); } | |||||
try { await Task.Delay(-1, token).ConfigureAwait(false); } | |||||
catch (OperationCanceledException) { } | catch (OperationCanceledException) { } | ||||
} | } | ||||
public static async Task Wait(this CancellationToken token) | public static async Task Wait(this CancellationToken token) | ||||
{ | { | ||||
try { await Task.Delay(-1, token); } | |||||
try { await Task.Delay(-1, token).ConfigureAwait(false); } | |||||
catch (OperationCanceledException) { } | catch (OperationCanceledException) { } | ||||
} | } | ||||
} | } | ||||
@@ -117,7 +117,7 @@ namespace Discord.Helpers | |||||
private async Task<ResponseT> Send<ResponseT>(HttpMethod method, string path, HttpContent content) | private async Task<ResponseT> Send<ResponseT>(HttpMethod method, string path, HttpContent content) | ||||
where ResponseT : class | where ResponseT : class | ||||
{ | { | ||||
string responseJson = await SendRequest(method, path, content, true); | |||||
string responseJson = await SendRequest(method, path, content, true).ConfigureAwait(false); | |||||
#if TEST_RESPONSES | #if TEST_RESPONSES | ||||
if (path.StartsWith(Endpoints.BaseApi)) | if (path.StartsWith(Endpoints.BaseApi)) | ||||
return JsonConvert.DeserializeObject<ResponseT>(responseJson, _settings); | return JsonConvert.DeserializeObject<ResponseT>(responseJson, _settings); | ||||
@@ -127,7 +127,7 @@ namespace Discord.Helpers | |||||
#if TEST_RESPONSES | #if TEST_RESPONSES | ||||
private async Task<string> Send(HttpMethod method, string path, HttpContent content) | private async Task<string> Send(HttpMethod method, string path, HttpContent content) | ||||
{ | { | ||||
string responseJson = await SendRequest(method, path, content, true); | |||||
string responseJson = await SendRequest(method, path, content, true).ConfigureAwait(false); | |||||
if (path.StartsWith(Endpoints.BaseApi) && !string.IsNullOrEmpty(responseJson)) | if (path.StartsWith(Endpoints.BaseApi) && !string.IsNullOrEmpty(responseJson)) | ||||
throw new Exception("API check failed: Response is not empty."); | throw new Exception("API check failed: Response is not empty."); | ||||
return responseJson; | return responseJson; | ||||
@@ -146,12 +146,12 @@ namespace Discord.Helpers | |||||
{ | { | ||||
if (content is StringContent) | if (content is StringContent) | ||||
{ | { | ||||
string json = await (content as StringContent).ReadAsStringAsync(); | |||||
string json = await (content as StringContent).ReadAsStringAsync().ConfigureAwait(false); | |||||
RaiseOnDebugMessage(DebugMessageType.XHRRawOutput, $"{method} {path}: {json}"); | RaiseOnDebugMessage(DebugMessageType.XHRRawOutput, $"{method} {path}: {json}"); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
byte[] bytes = await content.ReadAsByteArrayAsync(); | |||||
byte[] bytes = await content.ReadAsByteArrayAsync().ConfigureAwait(false); | |||||
RaiseOnDebugMessage(DebugMessageType.XHRRawOutput, $"{method} {path}: {bytes.Length} bytes"); | RaiseOnDebugMessage(DebugMessageType.XHRRawOutput, $"{method} {path}: {bytes.Length} bytes"); | ||||
} | } | ||||
} | } | ||||
@@ -167,14 +167,14 @@ namespace Discord.Helpers | |||||
HttpResponseMessage response; | HttpResponseMessage response; | ||||
if (hasResponse) | if (hasResponse) | ||||
{ | { | ||||
response = await _client.SendAsync(msg, HttpCompletionOption.ResponseContentRead); | |||||
response = await _client.SendAsync(msg, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false); | |||||
if (!response.IsSuccessStatusCode) | if (!response.IsSuccessStatusCode) | ||||
throw new HttpException(response.StatusCode); | throw new HttpException(response.StatusCode); | ||||
result = await response.Content.ReadAsStringAsync(); | |||||
result = await response.Content.ReadAsStringAsync().ConfigureAwait(false); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
response = await _client.SendAsync(msg, HttpCompletionOption.ResponseHeadersRead); | |||||
response = await _client.SendAsync(msg, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); | |||||
if (!response.IsSuccessStatusCode) | if (!response.IsSuccessStatusCode) | ||||
throw new HttpException(response.StatusCode); | throw new HttpException(response.StatusCode); | ||||
result = null; | result = null; | ||||