/// <summary>
 /// Обработка исходящих сообщений (Отправка)
 /// </summary>
 private static void ShipmentMessages()
 {
     while (IsMakedUp || OutgoingMessageQueue.Any())
     {
         if (!OutgoingMessageQueue.TryDequeue(out var message))
         {
             continue;
         }
         try
         {
             var json = JsonSerializer.Serialize(message);
             json = Regex.Replace(json, @"\\u([0-9A-Fa-f]{4})", m => "" + (char)Convert.ToInt32(m.Groups[1].Value, 16));
             var bytes     = Encoding.UTF8.GetBytes(json);
             var recipient = Users.FirstOrDefault(x => x.NickName == message.RecipientNickName);
             if (recipient?.Handler?.Connected == true)
             {
                 recipient.Handler.SendAsync(bytes, SocketFlags.None);
                 ServerMessage(message.Sender.Id == ServerData.Id ? $"Ответ Сервера клиенту [{recipient.NickName}] отправлен." : $"Сообщение от [{message.Sender.NickName}] получателю [{recipient.NickName}] отправлено.");
                 continue;
             }
             ServerMessage($"Попытка отправить сообщение пользователю {message.RecipientNickName} который уже покинул нас");
         }
         catch (Exception ex)
         {
             ServerMessage($"При отправке сообщения возникло исключение: {ex.Message}");
         }
     }
 }
        //todo deactivated as it crashed the test framework [TestMethod]
        public void OutgoingMessageIsResetOnSocketReset()
        {
            const string hostname             = "127.0.0.1";
            const int    port                 = 10100;
            const string connectionIdentifier = "1";

            var server = new SingleConnectionServer();

            server.StartListening();

            var engine = ExecutionEngineFactory.StartNew(new InMemoryStorageEngine());

            engine.Schedule(() =>
            {
                var unackedMessageQueue = new OutgoingMessageQueue();
                var deliverer           = new OutgoingMessageDeliverer(hostname, port, connectionIdentifier, unackedMessageQueue);

                Roots.Entangle(deliverer);
                Roots.Entangle(unackedMessageQueue);
                deliverer.Send("HELLO WORLD".GetUtf8Bytes());
            });

            Thread.Sleep(1_000);

            server.DisposeConnectedSocket();

            Thread.Sleep(1_000);

            server.GetNodeIdentifier().ShouldBe("1");
            server.GetReceivedMessages().Count.ShouldBe(2);
        }
示例#3
0
 public void Start()
 {
     outgoingMessageQueue = CreateOutgoingMessageQueue();
     outgoingMessageQueue.WaitForFirstMessage();
     incomingMessageQueue = CreateIncomingMessageQueue(outgoingMessageQueue);
     incomingMessageQueue.MessageReceived += OnMessageReceived;
     incomingMessageQueue.WaitForFirstMessage();
 }
示例#4
0
 private void StartCommunication(PipeStream readStream, PipeStream writeStream)
 {
     outgoingMessageQueue = CreateOutgoingMessageQueue(writeStream);
     outgoingMessageQueue.WaitForFirstMessage();
     incomingMessageQueue = CreateIncomingMessageQueue(readStream);
     incomingMessageQueue.MessageReceived += OnMessageReceived;
     incomingMessageQueue.WaitForFirstMessage();
 }
示例#5
0
 public IncomingMessageQueue(StreamFactory streamFactory, ILog log, PipeStream readStream,
                             NamedPipeCommunicationProtocol communicationProtocol,
                             OutgoingMessageQueue outgoingMessageQueue, CancellationToken cancellationToken)
 {
     this.streamFactory         = streamFactory;
     this.log                   = log;
     this.readStream            = readStream;
     this.communicationProtocol = communicationProtocol;
     this.cancellationToken     = cancellationToken;
     this.outgoingMessageQueue  = outgoingMessageQueue;
 }
示例#6
0
        /// <inheritdoc />
        public override async Task <SendResult> SendMessage <TPayloadType>(TPayloadType payload, DeliveryMethod method)
        {
            if (payload == null)
            {
                throw new ArgumentNullException(nameof(payload));
            }

            //we just add the message to the queue and let the other threads/tasks deal with everything else.
            await OutgoingMessageQueue.EnqueueAsync(payload)
            .ConfigureAwait(false);

            return(SendResult.Enqueued);
        }
        public void OutgoingConnectionSendsMessageSuccessfully()
        {
            const string hostname             = "127.0.0.1";
            const int    port                 = 10100;
            const string connectionIdentifier = "1";

            var server = new SingleConnectionServer();

            server.StartListening();

            var engine = ExecutionEngineFactory.StartNew(new InMemoryStorageEngine());

            engine.Schedule(() =>
            {
                var unackedMessageQueue = new OutgoingMessageQueue();
                var deliverer           = new OutgoingMessageDeliverer(hostname, port, connectionIdentifier, unackedMessageQueue);

                Roots.Entangle(deliverer);
                Roots.Entangle(unackedMessageQueue);
                deliverer.Send("HELLO WORLD".GetUtf8Bytes());
            });

            Thread.Sleep(1_000);

            server.GetNodeIdentifier().ShouldBe("1");
            server.GetReceivedMessages()[0].Item2.ShouldBe("HELLO WORLD");

            var unackeds = engine.Schedule(() =>
            {
                var q = Roots.Resolve <OutgoingMessageQueue>();
                return(q.GetSyncedUnackedMessages().ToArray());
            }).Result;

            unackeds.Length.ShouldBe(1);
            unackeds[0].Item1.ShouldBe(0);
            unackeds[0].Item2.Array.ToUtf8String().ShouldBe("HELLO WORLD");

            server.AckUntil(0);

            Thread.Sleep(1_000);

            unackeds = engine.Schedule(() =>
            {
                var q = Roots.Resolve <OutgoingMessageQueue>();
                return(q.GetSyncedUnackedMessages().ToArray());
            }).Result;

            unackeds.Length.ShouldBe(0);
        }
示例#8
0
        /// <summary>
        /// Dispatches the outgoing messages scheduled to be send
        /// over the network.
        /// </summary>
        /// <returns>A future which will complete when the client disconnects.</returns>
        private async Task DispatchOutgoingMessages()
        {
            try
            {
                //We need a token for canceling this task when a user disconnects
                CancellationToken dispatchCancelation = CreateNewManagedCancellationTokenSource().Token;

                while (!dispatchCancelation.IsCancellationRequested)
                {
                    TPayloadWriteType payload = await OutgoingMessageQueue.DequeueAsync(dispatchCancelation)
                                                .ConfigureAwait(false);

                    await UnmanagedClient.WriteAsync(payload)
                    .ConfigureAwait(false);
                }
            }
            catch (TaskCanceledException e)
            {
                //Supress this exception. We don't care about it. It's expected.
                //We cannot rethrow because this can cause application instability on threadpools
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Error: {e.Message}\n\n Stack: {e.StackTrace}");
                }

                //We cannot rethrow because this can cause application instability on threadpools
            }
            finally
            {
                try
                {
                    await DisconnectAsync(0);
                }
                catch (Exception)
                {
                }
            }

            //TODO: Should we do anything after the dispatch has stopped?
        }
 public SimulatorIncomingMessageQueue(StreamFactory streamFactory, ILog log, PipeStream readStream, NamedPipeCommunicationProtocolSimulator communicationProtocol, CancellationToken cancellationToken, OutgoingMessageQueue outgoingMessageQueue) : base(streamFactory, log, readStream, communicationProtocol, outgoingMessageQueue, cancellationToken)
 {
     this.communicationProtocol = communicationProtocol;
 }
 protected override IncomingMessageQueue CreateIncomingMessageQueue(OutgoingMessageQueue outgoingQueue)
 {
     return(new SimulatorIncomingMessageQueue(streamFactory, log, readStream, this, CancellationToken,
                                              outgoingQueue));
 }
示例#11
0
 protected virtual IncomingMessageQueue CreateIncomingMessageQueue(OutgoingMessageQueue outgoingQueue)
 {
     return(new IncomingMessageQueue(streamFactory, log, readStream,
                                     this, outgoingQueue, CancellationToken));
 }
        /// <summary>
        /// Обработка входящих сообщений
        /// </summary>
        private static void ProcessingIncomingMessage()
        {
            while (IsMakedUp || IncomingMessagesQueue.Any())
            {
                try
                {
                    if (!IncomingMessagesQueue.TryDequeue(out var message))
                    {
                        continue;
                    }
                    if (message.Type != MessageType.Authorization && !Users.Any(x => x.Id == message.Sender.Id && x.NickName == message.Sender.NickName && x.Handler.Connected))
                    {
                        OutgoingMessageQueue.Enqueue(message.ServerResponse($"Простите, {message.Sender.NickName}, но вас нет!"));
                        continue;
                    }
                    switch (message.Type)
                    {
                    case MessageType.Authorization:
                        if (Users.Any(x => x.NickName.Equals(message.Sender.NickName) || x.Id.Equals(message.Sender.Id)))
                        {
                            OutgoingMessageQueue.Enqueue(message.ServerResponse($"No/Пользователь с аналогичными регистрационными данными уже в чате", MessageType.Authorization));
                            break;
                        }
                        lock (Users)
                        {
                            Users.Add(message.Sender);
                        }
                        ServerMessage($"В чат вошел [{message.Sender.NickName}] ({message.Sender.Handler.RemoteEndPoint})");
                        var responceContent = $"Ok/Поздравляю {message.Sender.NickName}, Вы в чате. Список доступных команд:";
                        responceContent += AllCommandsString;
                        responceContent += $"\n{Datas.ExitCommand.ComKey} --> {Datas.ExitCommand.Comment}";
                        OutgoingMessageQueue.Enqueue(message.ServerResponse(responceContent, MessageType.Authorization));
                        break;

                    case MessageType.Server:
                        if (message.Content.Equals(Datas.ExitCommand.ComKey))
                        {
                            GoodByClient(message.Sender);
                            break;
                        }
                        var com = AllCommands.FirstOrDefault(x => x.ComKey.Equals(message.Content));
                        OutgoingMessageQueue.Enqueue(message.ServerResponse(com != null
                                ? com.Function?.Invoke("")
                                : "Мой юнный мозг не выдержал перегрузки, вызванной Вашим вопросом, и сдулся.")
                                                     );
                        break;

                    case MessageType.Private:
                        if (Users.Any(x => x.NickName == message.RecipientNickName))
                        {
                            OutgoingMessageQueue.Enqueue(message);
                            break;
                        }
                        OutgoingMessageQueue.Enqueue(message.ServerResponse($"Получатель сообщения [{message.RecipientNickName}] отсутствует в списке зарегистрированных пользователей"));
                        break;

                    case MessageType.All:
                        foreach (var recipient in Users)
                        {
                            var answer = message.CloneExcept("RecipientNickName");
                            answer.RecipientNickName = recipient.NickName;
                            OutgoingMessageQueue.Enqueue(answer);
                        }
                        break;
                    }
                }
                catch (Exception ex)
                {
                    ServerMessage($"При обработке сообщения возникло исключение: {ex.Message}");
                }
            }
        }