Browse Source

Fixed pings, incoming message debugging and joining channels

tags/docs-0.9
RogueException 9 years ago
parent
commit
3fa6ba8d50
5 changed files with 106 additions and 35 deletions
  1. +83
    -0
      src/Discord.Net.Sessions/SessionsService.cs
  2. +2
    -20
      src/Discord.Net/API/Voice.cs
  3. +1
    -1
      src/Discord.Net/DiscordClient.Voice.cs
  4. +1
    -1
      src/Discord.Net/DiscordWSClient.cs
  5. +19
    -13
      src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs

+ 83
- 0
src/Discord.Net.Sessions/SessionsService.cs View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Discord.Sessions
{
public class SessionsService : IService
{
private static readonly DualChannelPermissions _ownerPerm = new DualChannelPermissions() { ReadMessages = true, ManageChannel = true };
private static readonly DualChannelPermissions _memberPerm = new DualChannelPermissions() { ReadMessages = true };
private static readonly DualChannelPermissions _everyonePerm = new DualChannelPermissions() { ReadMessages = false };

private DiscordClient _client;

public void Install(DiscordClient client)
{
_client = client;
}

public IEnumerable<Channel> GetSessions(Server server)
=> server.TextChannels.Where(x => x.Name != "" && x.Name[0] == '!');

public async Task<Channel> CreateSession(Server server, string name, bool includeVoice, User owner)
{
name = '!' + name;
Channel textChannel = await _client.CreateChannel(server, name, ChannelType.Text);
Channel voiceChannel = includeVoice ? await _client.CreateChannel(server, name, ChannelType.Voice) : null;

//Take away read from everyone
await _client.SetChannelPermissions(textChannel, server.EveryoneRole, _everyonePerm);
await _client.SetChannelPermissions(textChannel, owner, _ownerPerm);

return textChannel;
}
public async Task DestroySession(Channel channel)
{
if (channel == null) throw new ArgumentNullException(nameof(channel));
CheckSession(channel);

await _client.DeleteChannel(channel);
}
public Task JoinSession(Channel channel, User user)
{
if (channel == null) throw new ArgumentNullException(nameof(channel));
if (user == null) throw new ArgumentNullException(nameof(user));
CheckSession(channel);

return _client.SetChannelPermissions(channel, user, _memberPerm);
}
public async Task LeaveSession(Channel channel, User user)
{
if (channel == null) throw new ArgumentNullException(nameof(channel));
if (user == null) throw new ArgumentNullException(nameof(user));
CheckSession(channel);

if (IsOwner(channel, user))
await DestroySession(channel);
else
await _client.RemoveChannelPermissions(channel, user);
}

private bool IsSession(Channel channel)
=> channel.Name == "" && channel.Name[0] == '!';
private void CheckSession(Channel channel)
{
if (!IsSession(channel))
throw new InvalidOperationException("The provided channel is not a session.");
}
private bool IsOwner(Channel channel, User user)
=> _client.GetChannelPermissions(channel, user).ManageMessages == true;
/*private IEnumerable<string> GetPermissionUsers(Channel channel)
{
return channel.PermissionOverwrites
.Where(x => x.TargetType == PermissionTarget.User && x.Allow.Text_ReadMessages)
.Select(x => x.TargetId);
}*/
}
}

+ 2
- 20
src/Discord.Net/API/Voice.cs View File

@@ -23,24 +23,6 @@ namespace Discord.API
}
}

/*public class GetIceResponse
{
[JsonProperty("ttl")]
public string TTL;
[JsonProperty("servers")]
public ServerData[] Servers;

public sealed class ServerData
{
[JsonProperty("url")]
public string URL;
[JsonProperty("username")]
public string Username;
[JsonProperty("credential")]
public string Credential;
}
}*/

//Commands
internal sealed class JoinVoiceCommand : WebSocketMessage<JoinVoiceCommand.Data>
{
@@ -110,9 +92,9 @@ namespace Discord.API
public SocketInfo SocketData = new SocketInfo();
}
}
internal sealed class VoiceKeepAliveCommand : WebSocketMessage<object>
internal sealed class VoiceKeepAliveCommand : WebSocketMessage<ulong>
{
public VoiceKeepAliveCommand() : base(3, null) { }
public VoiceKeepAliveCommand() : base(3, EpochTime.GetMilliseconds()) { }
}
internal sealed class IsTalkingCommand : WebSocketMessage<IsTalkingCommand.Data>
{


+ 1
- 1
src/Discord.Net/DiscordClient.Voice.cs View File

@@ -48,7 +48,7 @@ namespace Discord
public async Task<IDiscordVoiceClient> JoinVoiceServer(Channel channel)
{
if (channel == null) throw new ArgumentNullException(nameof(channel));
CheckReady(); //checkVoice is done inside the voice client
CheckReady(true); //checkVoice is done inside the voice client

var client = await CreateVoiceClient(channel.Server).ConfigureAwait(false);
await client.JoinChannel(channel.Id).ConfigureAwait(false);


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

@@ -282,7 +282,7 @@ namespace Discord
throw new InvalidOperationException("The client is connecting.");
}
if (checkVoice && !_config.EnableVoice)
if (checkVoice && _config.VoiceMode == DiscordVoiceMode.Disabled)
throw new InvalidOperationException("Voice is not enabled for this client.");
}
protected void RaiseEvent(string name, Action action)


+ 19
- 13
src/Discord.Net/Net/WebSockets/VoiceWebSocket.cs View File

@@ -36,12 +36,14 @@ namespace Discord.Net.WebSockets
private ushort _sequence;
private long? _serverId, _channelId, _userId;
private string _sessionId, _token, _encryptionMode;
private ulong _ping;
private Thread _sendThread, _receiveThread;

public long? CurrentServerId => _serverId;
public long? CurrentChannelId => _channelId;
public VoiceBuffer OutputBuffer => _sendBuffer;
public int Ping => (int)_ping;

public VoiceWebSocket(DiscordWSClient client)
: base(client)
@@ -312,29 +314,30 @@ namespace Discord.Net.WebSockets
}
else
voicePacket = new byte[MaxOpusSize + 12];
pingPacket = new byte[8];
pingPacket[0] = 0x80; //Flags;
pingPacket[1] = 0x78; //Payload Type
pingPacket[3] = 0x00; //Length
pingPacket[4] = 0x01; //Length (1*8 bytes)
pingPacket[5] = (byte)((_ssrc >> 24) & 0xFF);
pingPacket[6] = (byte)((_ssrc >> 16) & 0xFF);
pingPacket[7] = (byte)((_ssrc >> 8) & 0xFF);
pingPacket[8] = (byte)((_ssrc >> 0) & 0xFF);
pingPacket[1] = 0xC9; //Payload Type
pingPacket[2] = 0x00; //Length
pingPacket[3] = 0x01; //Length (1*8 bytes)
pingPacket[4] = (byte)((_ssrc >> 24) & 0xFF);
pingPacket[5] = (byte)((_ssrc >> 16) & 0xFF);
pingPacket[6] = (byte)((_ssrc >> 8) & 0xFF);
pingPacket[7] = (byte)((_ssrc >> 0) & 0xFF);
if (_isEncrypted)
{
Buffer.BlockCopy(pingPacket, 0, nonce, 0, 8);
int ret = Sodium.Encrypt(pingPacket, 8, encodedFrame, 0, nonce, _secretKey);
if (ret != 0)
throw new InvalidOperationException("Failed to encrypt ping packet");
pingPacket = new byte[ret];
Buffer.BlockCopy(encodedFrame, 0, pingPacket, 0, ret);
pingPacket = new byte[pingPacket.Length + 16];
Buffer.BlockCopy(encodedFrame, 0, pingPacket, 0, pingPacket.Length);
Array.Clear(nonce, 0, nonce.Length);
}

int rtpPacketLength = 0;
voicePacket[0] = 0x80; //Flags;
voicePacket[1] = 0xC9; //Payload Type
voicePacket[1] = 0x78; //Payload Type
voicePacket[8] = (byte)((_ssrc >> 24) & 0xFF);
voicePacket[9] = (byte)((_ssrc >> 16) & 0xFF);
voicePacket[10] = (byte)((_ssrc >> 8) & 0xFF);
@@ -385,7 +388,7 @@ namespace Discord.Net.WebSockets
}
if (currentTicks > nextPingTicks)
{
_udp.Send(pingPacket, pingPacket.Length);
//_udp.Send(pingPacket, pingPacket.Length);
nextPingTicks = currentTicks + 5 * Stopwatch.Frequency;
}
}
@@ -412,6 +415,7 @@ namespace Discord.Net.WebSockets

protected override async Task ProcessMessage(string json)
{
await base.ProcessMessage(json).ConfigureAwait(false);
var msg = JsonConvert.DeserializeObject<WebSocketMessage>(json);
switch (msg.Operation)
{
@@ -454,7 +458,9 @@ namespace Discord.Net.WebSockets
break;
case 3: //PONG
{
//var payload = (msg.Payload as JToken).ToObject<VoiceKeepAliveCommand>();
ulong time = EpochTime.GetMilliseconds();
var payload = (ulong)(long)msg.Payload;
_ping = payload - time;
//TODO: Use this to estimate latency
}
break;


Loading…
Cancel
Save