Exemple #1
0
            public void SendMessage(CancellationToken cancellationToken)
            {
                sendCounter++;
                if (sendCounter > MaxRetrySendingCount)
                {
                    communicationProtocol.Disconnect();
                    return;
                }

                Log.LogInformation($"Start sending message {Id.ToByteString()}. Attempt nr. {sendCounter}.");

                Data.Seek(0, SeekOrigin.Begin);
                SendMessageInChunks(cancellationToken);
            }
Exemple #2
0
            private void StartReading()
            {
                try
                {
                    while (!cancellationToken.IsCancellationRequested)
                    {
                        log.LogInformation("Start message reader");
                        byte[] header       = new byte[HeaderSize];
                        int    headerResult = readStream.Read(header, 0, header.Length);
                        try
                        {
                            if (headerResult == 0)
                            {
                                throw new ClientDisconnectedException();
                            }

                            (int messageLength, bool isSplit, Guid messageGuid, byte confirmation) = ParseHeader(header);

                            if (messageLength > 0)
                            {
                                ReadMessage(messageLength, isSplit, messageGuid, confirmation);
                            }
                            else
                            {
                                ProcessConfirmationFlag(confirmation, messageGuid);
                            }
                        }
                        catch (ClientDisconnectedException)
                        {
                            communicationProtocol.Disconnect();
                        }
                    }
                    log.LogInformation("Shutdown reader thread.");
                }
                catch (Exception)
                {
                    //Do not log anything as any log will lead to another exception
                }

                void ReadMessage(int messageLength, bool isSplit, Guid messageGuid, byte confirmation)
                {
                    Stream messageStream = streamFactory.Create(messageLength);
                    int    intervals     = messageLength / BufferSize;
                    int    remaining     = messageLength % BufferSize;

                    byte[]          buffer  = new byte[BufferSize];
                    IncomingMessage message = new IncomingMessage(messageGuid, messageStream, log);

                    try
                    {
                        ReadIntervals();
                        int result = Extensions.ExecutesWithTimeout(() => readStream.Read(buffer, 0, remaining),
                                                                    MaxConfirmationResponseTime);

                        if (result == 0)
                        {
                            throw new ClientDisconnectedException();
                        }

                        if (result != remaining)
                        {
                            throw new PartialMessageException(messageGuid);
                        }

                        AppendBuffer(messageStream, buffer, remaining);
                        messageStream.Seek(0, SeekOrigin.Begin);

                        if (splitMessages.ContainsKey(messageGuid) &&
                            splitMessages.TryGetValue(messageGuid, out IncomingMessage splitMessage))
                        {
                            MergeWithSplitMessage(splitMessage, messageStream);
                            message.Dispose();
                            message = splitMessage;
                        }

                        if (isSplit)
                        {
                            EnqueueSplitMessage(messageGuid, message);
                        }

                        if (!isSplit)
                        {
                            splitMessages.TryRemove(messageGuid, out _);

                            CompleteMessage(message, messageGuid, confirmation);
                        }
                    }
                    catch (ClientDisconnectedException disconnectedException)
                    {
                        log.LogError($"Client disconnected during communication.{Environment.NewLine}" +
                                     $"{disconnectedException}");
                        messageStream?.Dispose();
                        message?.Dispose();
                        throw;
                    }
                    catch (TaskCanceledException c)
                    {
                        log.LogError($"Exception during message read.{Environment.NewLine}" +
                                     $"{new MessageTimeoutException(messageGuid.GetHashCode(), MaxConfirmationResponseTime, c)}");
                    }
                    catch (OperationCanceledException oc)
                    {
                        log.LogError($"Exception during message read.{Environment.NewLine}" +
                                     $"{new MessageTimeoutException(messageGuid.GetHashCode(), MaxConfirmationResponseTime, oc)}");
                    }
                    catch (PartialMessageException)
                    {
                        messageStream?.Dispose();
                        message?.Dispose();
                        outgoingMessageQueue.SendMessageConfirmation(messageGuid, false);
                    }
                    catch (Exception e)
                    {
                        log.LogError($"Exception during message read.{Environment.NewLine}" +
                                     $"{e}");
                        messageStream?.Dispose();
                        message?.Dispose();
                        throw new ClientDisconnectedException(e);
                    }

                    log.LogVerbose("Finished reading message.");

                    void ReadIntervals()
                    {
                        while (intervals > 0)
                        {
                            intervals--;
                            ReadInterval();
                        }

                        void ReadInterval()
                        {
                            int result = Extensions.ExecutesWithTimeout(() => readStream.Read(buffer, 0, BufferSize),
                                                                        MaxConfirmationResponseTime);

                            if (result == 0)
                            {
                                throw new ClientDisconnectedException();
                            }

                            if (result != BufferSize)
                            {
                                throw new PartialMessageException(messageGuid);
                            }

                            AppendBuffer(messageStream, buffer, BufferSize);
                        }
                    }
                }
            }