예제 #1
0
        private Stream ReadFileImpl(string virtualFilePath)
        {
            //get a token - this creates a new transfer and validates the request
            DownloadToken token = RequestDownloadToken(virtualFilePath, false);

            //forward the token
            return(DownloadFileImpl(token.TransferId));
        }
예제 #2
0
        /// <summary>
        /// Requests a download token based on an older one. This allows to resume a paused
        /// or expired download if the service already discarded the token.
        /// </summary>
        /// <param name="oldToken">The previously used token.</param>
        /// <param name="includeFileHash">Whether a file hash for the
        /// requested resource should be calculated and assigned to the
        /// <see cref="DownloadToken.Md5FileHash"/> property of the returned
        /// <see cref="DownloadToken"/>. Can be used to verify file integrity, and also
        /// indicates whether the file was changed if the old token contained a file hash.</param>
        /// <returns>An updated token with a new expiration time, which reflects the
        /// status updates of the submitted token, including the <see cref="TransferToken.LastTransmittedBlockInfo"/></returns>
        public DownloadToken RenewToken(DownloadToken oldToken, bool includeFileHash)
        {
            //just create a new token - no adjustments needed with this service implementation
            var token = RequestDownloadToken(oldToken.ResourceIdentifier, includeFileHash);

            token.LastTransmittedBlockInfo  = oldToken.LastTransmittedBlockInfo;
            token.LastBlockTransmissionTime = oldToken.LastBlockTransmissionTime;
            return(token);
        }
    public void Init()
    {
      store = new InMemoryTransferStore<DownloadTransfer<FileItem>>();

      transfers = new List<DownloadTransfer<FileItem>>();
      for (int i = 0; i < 10; i++)
      {
        FileItem item = new FileItem {LocalFile = new FileInfo(i.ToString())};        
        var token = new DownloadToken {TransferId = i.ToString()};
        transfers.Add(new DownloadTransfer<FileItem>(token, item));
      }
    }
예제 #4
0
        /// <summary>
        /// Requests a download token for a given resource.
        /// </summary>
        /// <param name="resourceIdentifier"></param>
        /// <param name="includeFileHash">Whether a file hash for the
        /// requested resource should be calculated and assigned to the
        /// <see cref="DownloadToken.Md5FileHash"/> property of the returned
        /// <see cref="DownloadToken"/>.</param>
        /// <returns></returns>
        public DownloadToken RequestDownloadToken(string resourceIdentifier, bool includeFileHash)
        {
            FileInfo fileInfo = FileResolveFunc(resourceIdentifier);

            if (!fileInfo.Exists)
            {
                string msg = String.Format("Resource [{0}] not found.", resourceIdentifier);
                throw new VirtualResourceNotFoundException(msg);
            }

            string transferId = Guid.NewGuid().ToString();

            DownloadToken dt = new DownloadToken
            {
                TransferId         = transferId,
                ResourceIdentifier = resourceIdentifier,
                CreationTime       = SystemTime.Now(),
                ContentType        = ContentUtil.ResolveContentType(fileInfo.Extension),
                DownloadBlockSize  = 512 * 1024,           //TODO configure block size and expiration
                ResourceName       = fileInfo.Name,
                ResourceLength     = fileInfo.Length,
                ExpirationTime     = SystemTime.Now().AddHours(24),
                Status             = TransferStatus.Starting
            };

            //calculate number of blocks
            long count = dt.ResourceLength / dt.DownloadBlockSize.Value;

            if (dt.ResourceLength % dt.DownloadBlockSize != null)
            {
                count++;
            }
            dt.TotalBlockCount = count;

            if (includeFileHash)
            {
                dt.Md5FileHash = fileInfo.CalculateMd5Hash();
            }

            var transfer = new DownloadTransfer(dt)
            {
                File = fileInfo
            };

            Transfers.Add(transferId, transfer);
            return(dt);
        }
예제 #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 public DownloadManager(IDownloadTransferService transferService, string resourceId, DownloadToken token)
 {
   TransferService = transferService;
   ResourceId = resourceId;
   Token = token;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 protected OutboundTransferManager(DownloadToken token)
 {
   Token = token;
 }
예제 #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 protected OutboundTransferManager(DownloadToken token)
 {
     Token = token;
 }
예제 #8
0
 /// <summary>
 /// Creates a transfer object for a given requested resource.
 /// </summary>
 /// <param name="submittedResourceFilePath">The resource identifier as submitted.</param>
 /// <param name="fileItem">Represents the requested file resource.</param>
 /// <param name="token">The token that is being issued for the transfer.</param>
 /// <param name="claims">The access rights for the resource.</param>
 /// <param name="lockGuard">File locks, if necessary. Can be a null reference
 /// if no locking takes place.</param>
 /// <param name="expirationJob">A scheduled job that invokes the
 /// <see cref="TransferHandlerBase{TFile,TToken,TTransfer}.OnTransferExpiration"/>
 /// method once the transfer expires. May be null if the token does not expire.</param>
 /// <returns>A transfer object which encapsulates the information required to perform
 /// the transfer.</returns>
 protected abstract TTransfer CreateTransfer(string submittedResourceFilePath, TFile fileItem, DownloadToken token,
                                             FileClaims claims, ResourceLockGuard lockGuard,
                                             Job <DownloadToken> expirationJob);
예제 #9
0
        private TTransfer InitTransferImpl(string submittedResourceFilePath, int?clientMaxBlockSize, bool includeFileHash)
        {
            const FileSystemTask context = FileSystemTask.DownloadTokenRequest;
            TFile fileItem = CreateFileItemImpl(submittedResourceFilePath, false, context);

            if (!fileItem.Exists)
            {
                Auditor.AuditRequestedFileNotFound(fileItem, context);

                string msg = String.Format("Resource [{0}] not found.", submittedResourceFilePath);
                throw new VirtualResourceNotFoundException(msg)
                      {
                          IsAudited = true
                      };
            }

            //get authorization
            FileClaims claims = GetFileClaims(fileItem);

            if (!claims.AllowReadData)
            {
                Auditor.AuditDeniedOperation(context, AuditEvent.FileDataDownloadDenied, fileItem);

                string msg = "Read request for file [{0}] was denied - you are not authorized to read the resource.";
                msg = String.Format(msg, submittedResourceFilePath);
                throw new ResourceAccessException(msg)
                      {
                          IsAudited = true
                      };
            }

            //try to get lock
            ResourceLockGuard readLock = LockResourceForDownload(fileItem, claims);

            if (readLock != null && !readLock.IsLockEnabled)
            {
                Auditor.AuditDeniedOperation(context, AuditEvent.FileReadLockDenied, fileItem);

                string msg = "The requested file [{0}] is currently locked and thus cannot be accessed.";
                msg = String.Format(msg, submittedResourceFilePath);
                throw new ResourceLockedException(msg)
                      {
                          IsAudited = true
                      };
            }

            //create download token
            DownloadToken token = CreateDownloadToken(submittedResourceFilePath, fileItem, clientMaxBlockSize, includeFileHash);

            //create expiration job if we have an expiration time
            Job <DownloadToken> job = null;

            if (token.ExpirationTime.HasValue)
            {
                job = ScheduleExpiration(token);
            }

            //create transfer instance
            TTransfer transfer = CreateTransfer(submittedResourceFilePath, fileItem, token, claims, readLock, job);

            //cache transfer
            TransferStore.AddTransfer(transfer);

            //audit issued token
            Auditor.AuditResourceOperation(context, AuditEvent.DownloadTokenIssued, fileItem);

            return(transfer);
        }
예제 #10
0
        /// <summary>
        /// Handles locking, validation and stream preparation of a given transfer in order to read
        /// a given block of data. The actual reading (either into a buffer, or a returned
        /// stream) is being delegated via the <paramref name="dataReaderFunc"/>.
        /// </summary>
        /// <typeparam name="T">The type of <see cref="IDataBlockInfo"/> that is being returned.</typeparam>
        /// <param name="transferId">The transfer token ID.</param>
        /// <param name="blockNumber">The block number to be read.</param>
        /// <param name="dataReaderFunc">A function that receives the <see cref="DownloadTransfer"/> and
        /// the designated stream offset, and returns the required <see cref="IDataBlockInfo"/> that
        /// provides the block's data.</param>
        /// <returns>The <see cref="IDataBlockInfo"/> that is being created by the <paramref name="dataReaderFunc"/>.</returns>
        private T PrepareBlockReading <T>(string transferId, long blockNumber, Func <DownloadTransfer, long, T> dataReaderFunc) where T : IDataBlockInfo
        {
            DownloadTransfer transfer = GetCachedTransfer(transferId, true);
            DownloadToken    token    = transfer.Token;

            if (!File.Exists(transfer.File.FullName))
            {
                string msg = "Resource [{0}] of transfer [{1}] was not found.";
                msg = String.Format(msg, transfer.Token.ResourceName, transferId);
                throw new VirtualResourceNotFoundException(msg);
            }

            lock (transfer.SyncRoot)
            {
                //make sure the transfer is active
                if (!transfer.Status.Is(TransferStatus.Starting, TransferStatus.Running, TransferStatus.Paused))
                {
                    string msg = String.Format("Transfer is not active anymore - status is [{0}].", transfer.Status);
                    throw new TransferStatusException(msg);
                }

                long position = blockNumber * token.DownloadBlockSize.Value;

                //in case of an invalid position, throw error
                if (position > token.ResourceLength)
                {
                    string msg = "Cannot deliver block {0} - invalid block number.";
                    msg = String.Format(msg, blockNumber);
                    throw new DataBlockException(msg);
                }


                if (transfer.Stream == null)
                {
                    //open stream, share read access
                    transfer.Stream = transfer.File.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
                }

                //reposition stream if necessary
                if (position != transfer.Stream.Position)
                {
                    transfer.Stream.Seek(position, SeekOrigin.Begin);
                }

                T dataBlock = dataReaderFunc(transfer, position);

                if (dataBlock.IsLastBlock)
                {
                    //assume the last block will be processed successfully and
                    //already close the stream (don't wait for the transfer to be
                    //close by client)
                    transfer.Stream.Close();
                    transfer.Stream.Dispose();
                    transfer.Stream = null;
                }

                //update status
                transfer.Token.Status = TransferStatus.Running;

                //maintain local (unshared) copy of the block info without the data
                transfer.Token.LastTransmittedBlockInfo = DataBlockInfo.FromDataBlock(dataBlock);
                return(dataBlock);
            }
        }
예제 #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 public DownloadTransfer(DownloadToken token)
 {
     Token    = token;
     SyncRoot = new object();
 }
예제 #12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 public DownloadTransfer(DownloadToken token)
 {
   Token = token;
   SyncRoot = new object();
 }
예제 #13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 public DownloadManager(IDownloadTransferService transferService, string resourceId, DownloadToken token)
 {
     TransferService = transferService;
     ResourceId      = resourceId;
     Token           = token;
 }