Esempio n. 1
0
 /// <summary>
 /// Constructs a new <see cref="BaseSocketClientAbstraction"/> around an existing <see cref="WebSocket.BaseSocketClient"/>.
 /// </summary>
 /// <param name="baseSocketClient">The value to use for <see cref="WebSocket.BaseSocketClient"/>.</param>
 /// <exception cref="ArgumentNullException">Throws for <paramref name="baseSocketClient"/>.</exception>
 protected BaseSocketClientAbstraction(BaseSocketClient baseSocketClient)
     : base(baseSocketClient)
 {
     baseSocketClient.ChannelCreated         += x => ChannelCreated?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.ChannelDestroyed       += x => ChannelDestroyed?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.ChannelUpdated         += (x, y) => ChannelUpdated?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.CurrentUserUpdated     += (x, y) => CurrentUserUpdated?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.GuildAvailable         += x => GuildAvailable?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.GuildMembersDownloaded += x => GuildMembersDownloaded?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.GuildMemberUpdated     += (x, y) => GuildMemberUpdated?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.GuildUnavailable       += x => GuildUnavailable?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.GuildUpdated           += (x, y) => GuildUpdated?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.JoinedGuild            += x => JoinedGuild?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.LeftGuild             += x => LeftGuild?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.MessageReceived       += x => MessageReceived?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.MessageUpdated        += (x, y, z) => MessageUpdated?.InvokeAsync(x.Abstract(), y.Abstract(), z.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.MessageDeleted        += (x, y) => MessageDeleted?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.ReactionAdded         += (x, y, z) => ReactionAdded?.InvokeAsync(x.Abstract(), y.Abstract(), z.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.ReactionRemoved       += (x, y, z) => ReactionRemoved?.InvokeAsync(x.Abstract(), y.Abstract(), z.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.ReactionsCleared      += (x, y) => ReactionsCleared?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.RecipientAdded        += x => RecipientAdded?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.RecipientRemoved      += x => RecipientRemoved?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.RoleCreated           += x => RoleCreated?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.RoleDeleted           += x => RoleDeleted?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.RoleUpdated           += (x, y) => RoleUpdated?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.UserBanned            += (x, y) => UserBanned?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.UserIsTyping          += (x, y) => UserIsTyping?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.UserJoined            += x => UserJoined?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.UserLeft              += x => UserLeft?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.UserUnbanned          += (x, y) => UserUnbanned?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.UserUpdated           += (x, y) => UserUpdated?.InvokeAsync(x.Abstract(), y.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.UserVoiceStateUpdated += (x, y, z) => UserVoiceStateUpdated?.InvokeAsync(x.Abstract(), y.Abstract(), z.Abstract()) ?? Task.CompletedTask;
     baseSocketClient.VoiceServerUpdated    += x => VoiceServerUpdated?.InvokeAsync(x.Abstract()) ?? Task.CompletedTask;
 }
Esempio n. 2
0
        private async Task RequestReceivedHandler(object sender, RequestReceivedEventArgs e)
        {
            try
            {
                var sw = Stopwatch.StartNew();
                if (MessageReceived != null)
                {
                    await MessageReceived.InvokeAsync(this, new MessageEventArgs(e.Request)).ConfigureAwait(false);
                }
                if (e.Request?.Body is null)
                {
                    return;
                }
                var body = e.Request.Body.GetValue();
                if (EnableCompleteMessageCache)
                {
                    RequestMessageCache.Add(body, e.Request);
                }
                object result;
                Status.IncrementCurrentMessagesBeingProcessed();
                try
                {
                    result = await Processor.ProcessAsync(body, e.ProcessResponseTimeoutCancellationToken).ConfigureAwait(false);

                    e.SetResponseBody(result);
                }
                catch (Exception ex)
                {
                    Core.Log.Write(ex);
                    Status.IncrementTotalExceptions();
                }
                sw.Stop();
                Status.ReportProcessingTime(sw.Elapsed.TotalMilliseconds);
                Status.DecrementCurrentMessagesBeingProcessed();
                Status.IncrementTotalMessagesProccesed();
                if (EnableCompleteMessageCache)
                {
                    RequestMessageCache.Remove(body);
                }
            }
            catch (Exception ex)
            {
                Core.Log.Write(ex);
                Status.IncrementTotalExceptions();
            }
        }
Esempio n. 3
0
        private async Task ReceiveAsync(CancellationToken cancellationToken)
        {
            Task _sentData = Task.CompletedTask;

            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    if (!_networkStream.CanRead)
                    {
                        continue;
                    }

                    if (!_client.Connected)
                    {
                        throw new SocketException((int)SocketError.ConnectionReset);
                    }

                    byte[] bytes = new byte[8];
                    if ((await _networkStream.ReadAsync(bytes, 0, bytes.Length).ConfigureAwait(false)) == 0)
                    {
                        throw new SocketException((int)SocketError.ConnectionReset);
                    }

                    uint length = BitConverter.ToUInt32(bytes, 0);
                    uint magic  = BitConverter.ToUInt32(bytes, 4);

                    if (magic != _tcpMagic)
                    {
                        throw new InvalidDataException("The provided packet does not have the correct magic value");
                    }

                    bytes = new byte[length];
                    await ReceiveDataAsync(bytes, bytes.Length).ConfigureAwait(false);

                    await _sentData.ConfigureAwait(false);

                    _sentData = MessageReceived.InvokeAsync(this, new DataReceivedEventArgs(bytes));
                }
            }
            catch (Exception ex)
            {
                var _ = OnClosed(ex);
            }
        }
Esempio n. 4
0
        /// <inheritdoc />
        /// <summary>
        /// On Service Start method
        /// </summary>
        /// <param name="args">Start arguments</param>
        public void OnStart(string[] args)
        {
            try
            {
                Core.Log.InfoBasic("Starting messaging service");
                _cTokenSource = new CancellationTokenSource();
                OnInit(args);
                QueueServer = GetQueueServer();
                if (QueueServer is null)
                {
                    throw new Exception("The queue server is null, please check the configuration file and ensure the Types assemblies are on the assembly folder.");
                }
                Processor = GetMessageProcessorAsync(QueueServer);
                if (Processor is null)
                {
                    throw new Exception("The message processor is null, please check your GetMessageProcessor method implementation.");
                }
                if (QueueServer.ResponseServer)
                {
                    QueueServer.ResponseReceived += async(s, e) =>
                    {
                        if (MessageReceived != null)
                        {
                            await MessageReceived.InvokeAsync(this, new RawMessageEventArgs(e.Message, e.CorrelationId)).ConfigureAwait(false);
                        }
                        await Processor.ProcessAsync(e, _cTokenSource.Token).ConfigureAwait(false);
                    };
                }
                else
                {
                    QueueServer.RequestReceived += async(s, e) =>
                    {
                        if (MessageReceived != null)
                        {
                            await MessageReceived.InvokeAsync(this, new RawMessageEventArgs(e.Request, e.CorrelationId)).ConfigureAwait(false);
                        }
                        var result = await Processor.ProcessAsync(e, _cTokenSource.Token).ConfigureAwait(false);

                        if (result != ResponseMessage.NoResponse && result != null)
                        {
                            if (result is byte[] rBytes)
                            {
                                e.Response = rBytes;
                            }
                            else if (result is MultiArray <byte> mBytes)
                            {
                                e.Response = mBytes;
                            }
                            else
                            {
                                e.Response = QueueServer.SenderSerializer.Serialize(result);
                            }
                        }
                    };
                    QueueServer.BeforeSendResponse += async(s, e) =>
                    {
                        if (BeforeSendMessage != null)
                        {
                            await BeforeSendMessage.InvokeAsync(this, new RawMessageEventArgs(e.Message, e.CorrelationId)).ConfigureAwait(false);
                        }
                    };
                    QueueServer.ResponseSent += async(s, e) =>
                    {
                        if (MessageSent != null)
                        {
                            await MessageSent.InvokeAsync(this, new RawMessageEventArgs(e.Message, e.CorrelationId)).ConfigureAwait(false);
                        }
                    };
                }

                Processor.Init();
                QueueServer.StartListeners();
                Core.Log.InfoBasic("Messaging service started.");

                Core.Status.Attach(collection =>
                {
                    Core.Status.AttachChild(Processor, this);
                    Core.Status.AttachChild(QueueServer, this);
                });
            }
            catch (Exception ex)
            {
                Core.Log.Write(ex);
                throw;
            }
        }
        private async Task RunAsync(CancellationToken cancelToken)
        {
            var buffer = new ArraySegment <byte>(new byte[ReceiveChunkSize]);

            try
            {
                while (!cancelToken.IsCancellationRequested)
                {
                    WebSocketReceiveResult socketResult = await _client.ReceiveAsync(buffer, cancelToken).ConfigureAwait(false);

                    byte[] result;
                    int    resultCount;

                    if (socketResult.MessageType == WebSocketMessageType.Close)
                    {
                        throw new WebSocketClosedException((int)socketResult.CloseStatus, socketResult.CloseStatusDescription);
                    }

                    if (!socketResult.EndOfMessage)
                    {
                        //This is a large message (likely just READY), lets create a temporary expandable stream
                        using (var stream = new MemoryStream())
                        {
                            stream.Write(buffer.Array, 0, socketResult.Count);
                            do
                            {
                                if (cancelToken.IsCancellationRequested)
                                {
                                    return;
                                }
                                socketResult = await _client.ReceiveAsync(buffer, cancelToken).ConfigureAwait(false);

                                stream.Write(buffer.Array, 0, socketResult.Count);
                            }while (socketResult == null || !socketResult.EndOfMessage);

                            //Use the internal buffer if we can get it
                            resultCount = (int)stream.Length;
#if MSTRYBUFFER
                            if (stream.TryGetBuffer(out var streamBuffer))
                            {
                                result = streamBuffer.Array;
                            }
                            else
                            {
                                result = stream.ToArray();
                            }
#else
                            result = stream.GetBuffer();
#endif
                        }
                    }
                    else
                    {
                        //Small message
                        result = new byte[socketResult.Count];
                        Buffer.BlockCopy(buffer.Array, 0, result, 0, socketResult.Count);
                    }

                    if (socketResult.MessageType == WebSocketMessageType.Text)
                    {
                        throw new NotSupportedException();
                    }
                    else
                    {
                        await MessageReceived.InvokeAsync(this, new DataReceivedEventArgs(result)).ConfigureAwait(false);
                    }
                }
            }
            catch (Win32Exception ex) when(ex.HResult == HR_TIMEOUT)
            {
                var _ = OnClosed(new Exception("Connection timed out.", ex));
            }
            catch (OperationCanceledException) { }
            catch (Exception ex)
            {
                //This cannot be awaited otherwise we'll deadlock when DiscordApiClient waits for this task to complete.
                var _ = OnClosed(ex);
            }
        }
Esempio n. 6
0
        /// <inheritdoc />
        /// <summary>
        /// On Service Start method
        /// </summary>
        /// <param name="args">Start arguments</param>
        public void OnStart(string[] args)
        {
            try
            {
                Core.Log.InfoBasic("Starting messaging service");
                _cTokenSource = new CancellationTokenSource();
                OnInit(args);
                Status      = new MessagingServiceStatus(this);
                QueueServer = GetQueueServer();
                if (QueueServer == null)
                {
                    throw new Exception("The queue server is null, please check the configuration file and ensure the Types assemblies are on the assembly folder.");
                }
                Processor = GetMessageProcessorAsync(QueueServer);
                if (Processor == null)
                {
                    throw new Exception("The message processor is null, please check your GetMessageProcessor method implementation.");
                }
                if (QueueServer.ResponseServer)
                {
                    QueueServer.ResponseReceived += async(s, e) =>
                    {
                        if (MessageReceived != null)
                        {
                            await MessageReceived.InvokeAsync(this, new MessageEventArgs(e.Message)).ConfigureAwait(false);
                        }
                        if (e.Message?.Body == null)
                        {
                            return;
                        }

                        ReceivedMessagesCache.TryAdd(e.Message.Body, e.Message);
                        Status.IncrementCurrentMessagesBeingProcessed();
                        var sw = Stopwatch.StartNew();
                        try
                        {
                            await Processor.ProcessAsync(e.Message.Body, _cTokenSource.Token).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            Core.Log.Write(ex);
                            Status.IncrementTotalExceptions();
                        }
                        sw.Stop();
                        Status.ReportProcessingTime(sw.Elapsed.TotalMilliseconds);
                        Status.DecrementCurrentMessagesBeingProcessed();
                        Status.IncrementTotalMessagesProccesed();
                        ReceivedMessagesCache.TryRemove(e.Message.Body, out object _);
                    };
                }
                else
                {
                    QueueServer.RequestReceived += async(s, e) =>
                    {
                        if (MessageReceived != null)
                        {
                            await MessageReceived.InvokeAsync(this, new MessageEventArgs(e.Request)).ConfigureAwait(false);
                        }
                        if (e.Request?.Body == null)
                        {
                            return;
                        }

                        ReceivedMessagesCache.TryAdd(e.Request.Body, e.Request);
                        object result = null;
                        Status.IncrementCurrentMessagesBeingProcessed();
                        var sw = Stopwatch.StartNew();
                        try
                        {
                            result = await Processor.ProcessAsync(e.Request.Body, e.ProcessResponseTimeoutCancellationToken).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            Core.Log.Write(ex);
                            Status.IncrementTotalExceptions();
                        }
                        sw.Stop();
                        Status.ReportProcessingTime(sw.Elapsed.TotalMilliseconds);
                        Status.DecrementCurrentMessagesBeingProcessed();
                        Status.IncrementTotalMessagesProccesed();
                        e.Response.Body = result;
                        ReceivedMessagesCache.TryRemove(e.Request.Body, out object _);
                    };
                    QueueServer.BeforeSendResponse += async(s, e) =>
                    {
                        if (BeforeSendMessage != null)
                        {
                            await BeforeSendMessage.InvokeAsync(this, new MessageEventArgs(e.Message)).ConfigureAwait(false);
                        }
                    };
                    QueueServer.ResponseSent += async(s, e) =>
                    {
                        if (MessageSent != null)
                        {
                            await MessageSent.InvokeAsync(this, new MessageEventArgs(e.Message)).ConfigureAwait(false);
                        }
                    };
                }

                Processor.Init();
                QueueServer.StartListeners();
                Core.Log.InfoBasic("Messaging service started.");
            }
            catch (Exception ex)
            {
                Core.Log.Write(ex);
                throw;
            }
        }