/// <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); }
public void Start() { outgoingMessageQueue = CreateOutgoingMessageQueue(); outgoingMessageQueue.WaitForFirstMessage(); incomingMessageQueue = CreateIncomingMessageQueue(outgoingMessageQueue); incomingMessageQueue.MessageReceived += OnMessageReceived; incomingMessageQueue.WaitForFirstMessage(); }
private void StartCommunication(PipeStream readStream, PipeStream writeStream) { outgoingMessageQueue = CreateOutgoingMessageQueue(writeStream); outgoingMessageQueue.WaitForFirstMessage(); incomingMessageQueue = CreateIncomingMessageQueue(readStream); incomingMessageQueue.MessageReceived += OnMessageReceived; incomingMessageQueue.WaitForFirstMessage(); }
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; }
/// <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); }
/// <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)); }
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}"); } } }