Beispiel #1
0
        private static void MultipartWriteSegmentAsyncComplete(IAsyncResult result)
        {
            Contract.Assert(result != null, "result cannot be null.");
            MultipartAsyncContext context = (MultipartAsyncContext)result.AsyncState;

            Contract.Assert(context != null, "context cannot be null");

            MimeBodyPart part = context.PartsEnumerator.Current;

            try
            {
                Stream output = context.PartsEnumerator.Current.GetOutputStream();
                output.EndWrite(result);
            }
            catch (Exception e)
            {
                part.Dispose();
                context.TaskCompletionSource.TrySetException(new IOException(Properties.Resources.ReadAsMimeMultipartErrorWriting, e));
            }

            if (!MoveNextSegment(context))
            {
                MoveNextPart(context);
            }
        }
        private static async Task <bool> MoveToNextSegmentAsync(MultipartAsyncContext context)
        {
            Contract.Assert(context != null, "context cannot be null");
            if (context.SegmentsEnumerator.MoveNext())
            {
                Stream output = context.PartsEnumerator.Current.GetOutputStream(context.Parent);
                try
                {
                    ArraySegment <byte> segment = (ArraySegment <byte>)context.SegmentsEnumerator.Current;
                    await output.WriteAsync(segment.Array, segment.Offset, segment.Count);

                    if (!await MoveToNextSegmentAsync(context))
                    {
                        await MoveToNextPartAsync(context);
                    }

                    return(true);
                }
                catch (Exception e)
                {
                    context.PartsEnumerator.Current.Dispose();
                    throw new IOException(Properties.Resources.ReadAsMimeMultipartErrorWriting, e);
                }
            }

            return(CheckIsFinalPart(context.PartsEnumerator.Current, context.Result));
        }
Beispiel #3
0
        public static Task <IEnumerable <HttpContent> > ReadAsMultipartAsync(this HttpContent content, IMultipartStreamProvider streamProvider, int bufferSize)
        {
            if (content == null)
            {
                throw new ArgumentNullException("content");
            }

            if (streamProvider == null)
            {
                throw new ArgumentNullException("streamProvider");
            }

            if (bufferSize < MinBufferSize)
            {
                throw new ArgumentOutOfRangeException("bufferSize", bufferSize, RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, MinBufferSize));
            }

            return(content.ReadAsStreamAsync().Then(stream =>
            {
                TaskCompletionSource <IEnumerable <HttpContent> > taskCompletionSource = new TaskCompletionSource <IEnumerable <HttpContent> >();
                MimeMultipartBodyPartParser parser = new MimeMultipartBodyPartParser(content, streamProvider);
                byte[] data = new byte[bufferSize];
                MultipartAsyncContext context = new MultipartAsyncContext(stream, taskCompletionSource, parser, data);

                // Start async read/write loop
                MultipartReadAsync(context);

                // Return task and complete later
                return taskCompletionSource.Task;
            }));
        }
        private static bool MoveNextSegment(MultipartAsyncContext context)
        {
            Contract.Assert(context != null, "context cannot be null");
            try
            {
                if (context.SegmentsEnumerator.MoveNext())
                {
                    MultipartWriteSegmentAsync(context);
                    return(true);
                }
                else if (CheckPartCompletion(context.PartsEnumerator.Current, context.Result))
                {
                    // We are done parsing
                    context.TaskCompletionSource.TrySetResult(true);
                    return(true);
                }
            }
            catch (Exception e)
            {
                context.TaskCompletionSource.TrySetException(e);
                return(true);
            }

            return(false);
        }
Beispiel #5
0
        /// <summary>
        /// Reads all body parts within a MIME multipart message using the provided <see cref="MultipartStreamProvider"/> instance
        /// to determine where the contents of each body part is written and <paramref name="bufferSize"/> as read buffer size.
        /// </summary>
        /// <typeparam name="T">The <see cref="MultipartStreamProvider"/> with which to process the data.</typeparam>
        /// <param name="content">An existing <see cref="HttpContent"/> instance to use for the object's content.</param>
        /// <param name="streamProvider">A stream provider providing output streams for where to write body parts as they are parsed.</param>
        /// <param name="bufferSize">Size of the buffer used to read the contents.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        /// <returns>A <see cref="Task{T}"/> representing the tasks of getting the result of reading the MIME content.</returns>
        public static async Task <T> ReadAsMultipartAsync <T>(
            this HttpContent content,
            T streamProvider,
            int bufferSize,
            CancellationToken cancellationToken
            ) where T : MultipartStreamProvider
        {
            if (content == null)
            {
                throw Error.ArgumentNull("content");
            }

            if (streamProvider == null)
            {
                throw Error.ArgumentNull("streamProvider");
            }

            if (bufferSize < MinBufferSize)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo(
                          "bufferSize",
                          bufferSize,
                          MinBufferSize
                          );
            }

            Stream stream;

            try
            {
                stream = await content.ReadAsStreamAsync();
            }
            catch (Exception e)
            {
                throw new IOException(Properties.Resources.ReadAsMimeMultipartErrorReading, e);
            }

            using (var parser = new MimeMultipartBodyPartParser(content, streamProvider))
            {
                byte[] data = new byte[bufferSize];
                MultipartAsyncContext context = new MultipartAsyncContext(
                    stream,
                    parser,
                    data,
                    streamProvider.Contents
                    );

                // Start async read/write loop
                await MultipartReadAsync(context, cancellationToken);

                // Let the stream provider post-process when everything is complete
                await streamProvider.ExecutePostProcessingAsync(cancellationToken);

                return(streamProvider);
            }
        }
Beispiel #6
0
        private static async Task MultipartReadAsync(
            MultipartAsyncContext context,
            CancellationToken cancellationToken
            )
        {
            Contract.Assert(context != null, "context cannot be null");
            while (true)
            {
                int bytesRead;
                try
                {
                    bytesRead = await context.ContentStream.ReadAsync(
                        context.Data,
                        0,
                        context.Data.Length,
                        cancellationToken
                        );
                }
                catch (Exception e)
                {
                    throw new IOException(Properties.Resources.ReadAsMimeMultipartErrorReading, e);
                }

                IEnumerable <MimeBodyPart> parts = context.MimeParser.ParseBuffer(
                    context.Data,
                    bytesRead
                    );

                foreach (MimeBodyPart part in parts)
                {
                    foreach (ArraySegment <byte> segment in part.Segments)
                    {
                        try
                        {
                            await part.WriteSegment(segment, cancellationToken);
                        }
                        catch (Exception e)
                        {
                            part.Dispose();
                            throw new IOException(
                                      Properties.Resources.ReadAsMimeMultipartErrorWriting,
                                      e
                                      );
                        }
                    }

                    if (CheckIsFinalPart(part, context.Result))
                    {
                        return;
                    }
                }
            }
        }
        private static async Task MoveToNextPartAsync(MultipartAsyncContext context)
        {
            Contract.Assert(context != null, "context cannot be null");
            while (context.PartsEnumerator.MoveNext())
            {
                context.SegmentsEnumerator = context.PartsEnumerator.Current.Segments.GetEnumerator();
                if (await MoveToNextSegmentAsync(context))
                {
                    return;
                }
            }

            await MultipartReadAsync(context);
        }
Beispiel #8
0
        private static void MoveNextPart(MultipartAsyncContext context)
        {
            Contract.Assert(context != null, "context cannot be null");
            while (context.PartsEnumerator.MoveNext())
            {
                context.SegmentsEnumerator = context.PartsEnumerator.Current.Segments.GetEnumerator();
                if (MoveNextSegment(context))
                {
                    return;
                }
            }

            // Read some more
            MultipartReadAsync(context);
        }
Beispiel #9
0
        private static void OnMultipartReadAsyncComplete(IAsyncResult result)
        {
            if (result.CompletedSynchronously)
            {
                return;
            }

            MultipartAsyncContext context = (MultipartAsyncContext)result.AsyncState;

            Contract.Assert(context != null, "context cannot be null");
            try
            {
                MultipartReadAsyncComplete(result);
            }
            catch (Exception e)
            {
                context.TaskCompletionSource.TrySetException(e);
            }
        }
Beispiel #10
0
        private static void MultipartReadAsync(MultipartAsyncContext context)
        {
            Contract.Assert(context != null, "context cannot be null");
            IAsyncResult result = null;

            try
            {
                result = context.ContentStream.BeginRead(context.Data, 0, context.Data.Length, _onMultipartReadAsyncComplete, context);
                if (result.CompletedSynchronously)
                {
                    MultipartReadAsyncComplete(result);
                }
            }
            catch (Exception e)
            {
                Exception exception = (result != null && result.CompletedSynchronously) ? e : new IOException(Properties.Resources.ReadAsMimeMultipartErrorReading, e);
                context.TaskCompletionSource.TrySetException(exception);
            }
        }
        private static async Task MultipartReadAsync(MultipartAsyncContext context)
        {
            Contract.Assert(context != null, "context cannot be null");
            int bytesRead = 0;

            try
            {
                bytesRead = await context.ContentStream.ReadAsync(context.Data, 0, context.Data.Length);
            }
            catch (Exception e)
            {
                throw new IOException(Properties.Resources.ReadAsMimeMultipartErrorReading, e);
            }

            IEnumerable <MimeBodyPart> parts = context.MimeParser.ParseBuffer(context.Data, bytesRead);

            context.PartsEnumerator = parts.GetEnumerator();
            await MoveToNextPartAsync(context);
        }
Beispiel #12
0
        private static void MultipartReadAsyncComplete(IAsyncResult result)
        {
            Contract.Assert(result != null, "result cannot be null");
            MultipartAsyncContext context = (MultipartAsyncContext)result.AsyncState;
            int bytesRead = 0;

            try
            {
                bytesRead = context.ContentStream.EndRead(result);
            }
            catch (Exception e)
            {
                context.TaskCompletionSource.TrySetException(new IOException(Properties.Resources.ReadAsMimeMultipartErrorReading, e));
            }

            IEnumerable <MimeBodyPart> parts = context.MimeParser.ParseBuffer(context.Data, bytesRead);

            context.PartsEnumerator = parts.GetEnumerator();
            MoveNextPart(context);
        }
Beispiel #13
0
        private static void MultipartWriteSegmentAsync(MultipartAsyncContext context)
        {
            Contract.Assert(context != null, "context cannot be null.");
            Stream output = context.PartsEnumerator.Current.GetOutputStream();
            ArraySegment <byte> segment = (ArraySegment <byte>)context.SegmentsEnumerator.Current;

            try
            {
                IAsyncResult result = output.BeginWrite(segment.Array, segment.Offset, segment.Count, _onMultipartWriteSegmentAsyncComplete, context);
                if (result.CompletedSynchronously)
                {
                    MultipartWriteSegmentAsyncComplete(result);
                }
            }
            catch (Exception e)
            {
                context.PartsEnumerator.Current.Dispose();
                context.TaskCompletionSource.TrySetException(new IOException(Properties.Resources.ReadAsMimeMultipartErrorWriting, e));
            }
        }
        public static Task <T> ReadAsMultipartAsync <T>(this HttpContent content, T streamProvider, int bufferSize) where T : MultipartStreamProvider
        {
            if (content == null)
            {
                throw Error.ArgumentNull("content");
            }

            if (streamProvider == null)
            {
                throw Error.ArgumentNull("streamProvider");
            }

            if (bufferSize < MinBufferSize)
            {
                throw Error.ArgumentMustBeGreaterThanOrEqualTo("bufferSize", bufferSize, MinBufferSize);
            }

            MimeMultipartBodyPartParser parser = null;

            return(content.ReadAsStreamAsync().Then(stream =>
            {
                TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>();
                parser = new MimeMultipartBodyPartParser(content, streamProvider);
                byte[] data = new byte[bufferSize];
                MultipartAsyncContext context = new MultipartAsyncContext(content, stream, taskCompletionSource, parser, data, streamProvider.Contents);

                // Start async read/write loop
                MultipartReadAsync(context);

                // Return task and complete when we have run the post processing step.
                return taskCompletionSource.Task.Then(() => streamProvider.ExecutePostProcessingAsync().ToTask <T>(result: streamProvider));
            }).Finally(() =>
            {
                if (parser != null)
                {
                    parser.Dispose();
                }
            }, runSynchronously: true));
        }
        private static void MoveNextPart(MultipartAsyncContext context)
        {
            Contract.Assert(context != null, "context cannot be null");
            try
            {
                while (context.PartsEnumerator.MoveNext())
                {
                    context.SegmentsEnumerator = context.PartsEnumerator.Current.Segments.GetEnumerator();
                    if (MoveNextSegment(context))
                    {
                        return;
                    }
                }
            }
            catch (Exception e)
            {
                context.TaskCompletionSource.TrySetException(e);
                return;
            }

            // Read some more
            MultipartReadAsync(context);
        }
        private static bool MoveNextSegment(MultipartAsyncContext context)
        {
            Contract.Assert(context != null, "context cannot be null");
            if (context.SegmentsEnumerator.MoveNext())
            {
                MultipartWriteSegmentAsync(context);
                return true;
            }
            else if (CheckPartCompletion(context.PartsEnumerator.Current, context.Result))
            {
                // We are done parsing
                context.TaskCompletionSource.TrySetResult(context.Result);
                return true;
            }

            return false;
        }
        private static void MoveNextPart(MultipartAsyncContext context)
        {
            Contract.Assert(context != null, "context cannot be null");
            while (context.PartsEnumerator.MoveNext())
            {
                context.SegmentsEnumerator = context.PartsEnumerator.Current.Segments.GetEnumerator();
                if (MoveNextSegment(context))
                {
                    return;
                }
            }

            // Read some more
            MultipartReadAsync(context);
        }
 private static void MultipartWriteSegmentAsync(MultipartAsyncContext context)
 {
     Contract.Assert(context != null, "context cannot be null.");
     Stream output = context.PartsEnumerator.Current.GetOutputStream();
     ArraySegment<byte> segment = (ArraySegment<byte>)context.SegmentsEnumerator.Current;
     try
     {
         IAsyncResult result = output.BeginWrite(segment.Array, segment.Offset, segment.Count, _onMultipartWriteSegmentAsyncComplete, context);
         if (result.CompletedSynchronously)
         {
             MultipartWriteSegmentAsyncComplete(result);
         }
     }
     catch (Exception e)
     {
         context.PartsEnumerator.Current.Dispose();
         context.TaskCompletionSource.TrySetException(new IOException(Properties.Resources.ReadAsMimeMultipartErrorWriting, e));
     }
 }
 private static void MultipartReadAsync(MultipartAsyncContext context)
 {
     Contract.Assert(context != null, "context cannot be null");
     IAsyncResult result = null;
     try
     {
         result = context.ContentStream.BeginRead(context.Data, 0, context.Data.Length, _onMultipartReadAsyncComplete, context);
         if (result.CompletedSynchronously)
         {
             MultipartReadAsyncComplete(result);
         }
     }
     catch (Exception e)
     {
         Exception exception = (result != null && result.CompletedSynchronously) ? e : new IOException(Properties.Resources.ReadAsMimeMultipartErrorReading, e);
         context.TaskCompletionSource.TrySetException(exception);
     }
 }
        public static Task<IEnumerable<HttpContent>> ReadAsMultipartAsync(this HttpContent content, IMultipartStreamProvider streamProvider, int bufferSize)
        {
            if (content == null)
            {
                throw new ArgumentNullException("content");
            }

            if (streamProvider == null)
            {
                throw new ArgumentNullException("streamProvider");
            }

            if (bufferSize < MinBufferSize)
            {
                throw new ArgumentOutOfRangeException("bufferSize", bufferSize, RS.Format(Properties.Resources.ArgumentMustBeGreaterThanOrEqualTo, MinBufferSize));
            }

            return content.ReadAsStreamAsync().Then(stream =>
            {
                TaskCompletionSource<IEnumerable<HttpContent>> taskCompletionSource = new TaskCompletionSource<IEnumerable<HttpContent>>();
                MimeMultipartBodyPartParser parser = new MimeMultipartBodyPartParser(content, streamProvider);
                byte[] data = new byte[bufferSize];
                MultipartAsyncContext context = new MultipartAsyncContext(stream, taskCompletionSource, parser, data);

                // Start async read/write loop
                MultipartReadAsync(context);

                // Return task and complete later
                return taskCompletionSource.Task;
            });
        }