Exemplo n.º 1
0
        protected virtual TransportSendStats WriteMessageToBody(string formDataBoundary, Stream requestStream, IList <ITransportPacketInfo> packetInfos, IList <ConfigurationRequestDataItem> configurationsToDownloadInfos, SendIterationContext context)
        {
            var packetsSendStats = new Dictionary <ITransportPacketInfo, SendStats>();

            using (var nonClosingStream = new NonClosingStreamWrapper(requestStream))
                using (var sr = new StreamWriter(nonClosingStream, this.encoding ?? DefaultEncoding))
                    using (var formDataWriter = new FormDataWriter(nonClosingStream, formDataBoundary, this.encoding ?? DefaultEncoding))
                    {
                        var maxMessageSizeReached = false;

                        if (context.RequestConfigurations)
                        {
                            // записываем данные по конфигурациям
                            for (int i = 0; i < configurationsToDownloadInfos.Count; i++)
                            {
                                var configurationsToDownloadInfo = configurationsToDownloadInfos[i];

                                // == confs[0].
                                var itemPrefix = string.Concat(TransportConstants.FormDataConfigurationProp, "[", i, "].");

                                // == confs[0].ProviderKey
                                formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(ConfigurationRequestDataItem.ProviderKey)), configurationsToDownloadInfo.ProviderKey);
                                formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(ConfigurationRequestDataItem.Token)), configurationsToDownloadInfo.Token);
                                if (configurationsToDownloadInfo.StartPosition != null)
                                {
                                    formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(ConfigurationRequestDataItem.StartPosition)), configurationsToDownloadInfo.StartPosition);
                                }
                                formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(ConfigurationRequestDataItem.IsCompleted)), configurationsToDownloadInfo.IsCompleted);
                            }
                        }

                        if (context.SendPackets)
                        {
                            formDataWriter.ResetSize();

                            // записываем данные по пакетам
                            for (int i = 0; i < packetInfos.Count; i++)
                            {
                                var packetInfo = packetInfos[i];

                                var sendStats = this.packetManager.ReadSendStats(packetInfo.ProviderKey, packetInfo.Id);
                                if (sendStats?.TransferCompleted == true)
                                {
                                    continue;
                                }

                                int    packetBytesSended       = sendStats?.TransferedBytes ?? 0;
                                int    bufferSize              = 4096;
                                bool   packetTransferCompleted = false;
                                string packetBlockHashStr;
                                // == packets[0].
                                var itemPrefix = string.Concat(TransportConstants.FormDataPacketsProp, "[", i, "].");
                                // записываем данные пакета
                                using (var packetStream = packetInfo.GetReadOnlyStreamOrDefault())
                                {
                                    // пакет был удалён
                                    if (packetStream == null)
                                    {
                                        continue;
                                    }

                                    // записываем метаданные о пакете
                                    // == packets[0].ProviderKey
                                    formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.ProviderKey)), packetInfo.ProviderKey);
                                    formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.PacketId)), packetInfo.Id);
                                    formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.StartPosition)), packetBytesSended);

                                    packetStream.Seek(packetBytesSended, SeekOrigin.Begin);

                                    using (var hashAlgorithm = this.hashAlgorithmFunc())
                                    {
                                        var packetIdStr = packetInfo.Id.ToString();
                                        formDataWriter.WriteFileHeader(string.Concat(itemPrefix, nameof(PacketFormDataItem.FileKey)), packetIdStr);

                                        byte[] buffer = new byte[bufferSize];
                                        int    read   = 0;
                                        while (!maxMessageSizeReached && (read = packetStream.Read(buffer, 0, buffer.Length)) > 0)
                                        {
                                            if (formDataWriter.GetWrittenSize() + read > this.settings.PacketSizeLimits.Max)
                                            {
                                                // записываем только до максимального размера
                                                read = this.settings.PacketSizeLimits.Max - formDataWriter.GetWrittenSize();
                                                maxMessageSizeReached = true;
                                            }

                                            formDataWriter.Write(buffer, 0, read);

                                            if (hashAlgorithm != null)
                                            {
                                                // hash contents
                                                hashAlgorithm.TransformBlock(buffer, 0, read, null, 0);
                                            }

                                            packetBytesSended = packetBytesSended + read;
                                        }

                                        if (read <= 0)
                                        {
                                            packetTransferCompleted = true;
                                        }

                                        if (hashAlgorithm != null)
                                        {
                                            hashAlgorithm.TransformFinalBlock(new byte[0], 0, 0);
                                            packetBlockHashStr = hashAlgorithm.GetHashString();
                                        }
                                    }
                                }

                                formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.EndPosition)), packetBytesSended);

                                //// записываем хеш данные блока пакета
                                //formDataWriter.WriteValue(nameof(PacketFormDataItem.Hash) + suffix, packetBlockHashStr);
                                formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.IsFinal)), packetTransferCompleted);

                                packetsSendStats.Add(packetInfo, new SendStats
                                {
                                    TransferedBytes   = packetBytesSended,
                                    TransferCompleted = packetTransferCompleted,
                                });

                                if (maxMessageSizeReached)
                                {
                                    break;
                                }
                            }
                        }
                    }

            return(new TransportSendStats
            {
                SendedPacketsStats = packetsSendStats,
                ConfigurationsInfos = configurationsToDownloadInfos,
            });
        }
Exemplo n.º 2
0
        protected virtual TransportSendStats WriteMessageToBody(string formDataBoundary, Stream requestStream, IList <ITransportPacketInfo> packetInfos, IList <ConfigurationRequestDataItem> configurationsToDownloadInfos, SendIterationContext context, Func <bool> cancelSendFunc)
        {
            var packetsSendStats = new Dictionary <ITransportPacketInfo, SendStats>();
            var completedPackets = new List <ITransportPacketInfo>();

            using (var nonClosingStream = new NonClosingStreamWrapper(requestStream))
                using (var sr = new StreamWriter(nonClosingStream, this.encoding ?? DefaultEncoding))
                    using (var formDataWriter = new FormDataWriter(nonClosingStream, formDataBoundary, this.encoding ?? DefaultEncoding))
                    {
                        var messageCapacityReached = false;

                        if (context.RequestConfigurations)
                        {
                            // записываем данные по конфигурациям
                            for (int i = 0; i < configurationsToDownloadInfos.Count; i++)
                            {
                                if (cancelSendFunc())
                                {
                                    break;
                                }

                                var configurationsToDownloadInfo = configurationsToDownloadInfos[i];

                                // == confs[0].
                                var itemPrefix = string.Concat(TransportConstants.FormDataConfigurationProp, "[", i, "].");

                                // == confs[0].ProviderKey
                                formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(ConfigurationRequestDataItem.ProviderKey)), configurationsToDownloadInfo.ProviderKey);
                                formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(ConfigurationRequestDataItem.Token)), configurationsToDownloadInfo.Token);
                                if (configurationsToDownloadInfo.StartPosition != null)
                                {
                                    formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(ConfigurationRequestDataItem.StartPosition)), configurationsToDownloadInfo.StartPosition);
                                }
                                formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(ConfigurationRequestDataItem.IsCompleted)), configurationsToDownloadInfo.IsCompleted);
                            }
                        }

                        if (context.SendPackets)
                        {
                            //formDataWriter.ResetSize();

                            bool hasWrittenPackagePartToRequest = false;
                            // записываем данные по пакетам
                            for (int i = 0; i < packetInfos.Count; i++)
                            {
                                if (cancelSendFunc())
                                {
                                    break;
                                }

                                var packetInfo = packetInfos[i];

                                var sendStats = this.packetManager.ReadSendStats(packetInfo.ProviderKey, packetInfo.Identity);
                                if (sendStats?.TransferCompleted == true)
                                {
                                    completedPackets.Add(packetInfo);
                                    continue;
                                }

                                int packetBytesSended = sendStats?.TransferedBytes ?? 0;
                                // буфер ~16 kb (довольно много можно уместить)
                                int    bufferSize = 4 * 4096;
                                bool   packetTransferCompleted = false;
                                string packetBlockHashStr;
                                // == packets[0].
                                var itemPrefix = string.Concat(TransportConstants.FormDataPacketsProp, "[", i, "].");
                                // записываем данные пакета
                                using (var packetStream = packetInfo.GetReadOnlyStreamOrDefault())
                                {
                                    // пакет был удалён
                                    if (packetStream == null)
                                    {
                                        completedPackets.Add(packetInfo);
                                        continue;
                                    }

                                    // записываем метаданные о пакете
                                    // == packets[0].ProviderKey
                                    formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.ProviderKey)), packetInfo.ProviderKey);
                                    formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.PacketId)), packetInfo.Identity.PacketId);
                                    formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.StartPosition)), packetBytesSended);

                                    packetStream.Seek(packetBytesSended, SeekOrigin.Begin);

                                    using (var hashAlgorithm = this.hashAlgorithmFunc())
                                    {
                                        var packetIdStr = packetInfo.Identity.PacketId.ToString();
                                        formDataWriter.WriteFileHeader(string.Concat(itemPrefix, nameof(PacketFormDataItem.FileKey)), packetIdStr);

                                        byte[] buffer       = new byte[bufferSize];
                                        int    read         = 0;
                                        bool   writtenToEnd = false;
                                        while (!messageCapacityReached && (read = packetStream.Read(buffer, 0, buffer.Length)) > 0)
                                        {
                                            // подумать над реализацией которая будет делать меньшую фрагментацию пакетови не будет записывать "лишние"
                                            if (formDataWriter.GetWrittenSize() + read > context.TransportSettings.PacketSizeLimits.Max)
                                            {
                                                // записываем только до максимального размера
                                                var toWrite = context.TransportSettings.PacketSizeLimits.Max - formDataWriter.GetWrittenSize();

                                                if (toWrite < 0)
                                                {
                                                    var originalReadFromPacket = read;
                                                    if (hasWrittenPackagePartToRequest)
                                                    {
                                                        read = Math.Min(context.TransportSettings.PacketSizeLimits.Min, Math.Min(read, 4096));
                                                    }
                                                    else
                                                    {
                                                        read = read < context.TransportSettings.PacketSizeLimits.Max ? read : context.TransportSettings.PacketSizeLimits.Max;
                                                    }

                                                    writtenToEnd = originalReadFromPacket <= read && packetStream.ReadByte() == -1;
                                                }
                                                else
                                                {
                                                    read = toWrite;
                                                }

                                                messageCapacityReached = true;
                                            }

                                            formDataWriter.Write(buffer, 0, read);
                                            hasWrittenPackagePartToRequest = true;

                                            if (hashAlgorithm != null)
                                            {
                                                // hash contents
                                                hashAlgorithm.TransformBlock(buffer, 0, read, null, 0);
                                            }

                                            packetBytesSended = packetBytesSended + read;
                                        }

                                        if (read <= 0 || writtenToEnd)
                                        {
                                            packetTransferCompleted = true;
                                        }

                                        if (hashAlgorithm != null)
                                        {
                                            hashAlgorithm.TransformFinalBlock(new byte[0], 0, 0);
                                            packetBlockHashStr = hashAlgorithm.GetHashString();
                                        }
                                    }
                                }

                                formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.EndPosition)), packetBytesSended);

                                //// записываем хеш данные блока пакета
                                //formDataWriter.WriteValue(nameof(PacketFormDataItem.Hash) + suffix, packetBlockHashStr);
                                formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.IsFinal)), packetTransferCompleted);

                                // данные о предыдущей части
                                if (sendStats?.PreviousPartIdentity != null)
                                {
                                    formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.PreviousPartId)), sendStats.PreviousPartIdentity.Id);
                                    formDataWriter.WriteValue(string.Concat(itemPrefix, nameof(PacketFormDataItem.PreviousPartStorageToken)), sendStats.PreviousPartIdentity.StorageToken);
                                }

                                packetsSendStats.Add(packetInfo, new SendStats
                                {
                                    TransferedBytes   = packetBytesSended,
                                    TransferCompleted = packetTransferCompleted,
                                });

                                if (messageCapacityReached)
                                {
                                    break;
                                }
                            }
                        }
                    }

            return(new TransportSendStats
            {
                IgnoredPackets = completedPackets,
                SendedPacketsStats = packetsSendStats,
                ConfigurationsInfos = configurationsToDownloadInfos,
            });
        }