FtpWebRequest is always 2.0, remove unnecessary ifdefs
[mono.git] / mcs / class / System / System.Net / RequestStream.cs
index a89f98e0b67ef790880ded562c9624aaa827da93..a1ebb40795ed39d862cef27523b8ab5fd8e110c5 100644 (file)
@@ -30,19 +30,27 @@ using System.IO;
 using System.Net.Sockets;
 using System.Runtime.InteropServices;
 namespace System.Net {
-       class RequestStream : NetworkStream
+       class RequestStream : Stream
        {
                byte [] buffer;
                int offset;
                int length;
+               long remaining_body;
                bool disposed;
+               Stream stream;
 
-               internal RequestStream (Socket sock, byte [] buffer, int offset, int length) :
-                                       base (sock, false)
+               internal RequestStream (Stream stream, byte [] buffer, int offset, int length)
+                       : this (stream, buffer, offset, length, -1)
                {
+               }
+
+               internal RequestStream (Stream stream, byte [] buffer, int offset, int length, long contentlength)
+               {
+                       this.stream = stream;
                        this.buffer = buffer;
                        this.offset = offset;
                        this.length = length;
+                       this.remaining_body = contentlength;
                }
 
                public override bool CanRead {
@@ -76,13 +84,12 @@ namespace System.Net {
                {
                }
 
-               // true if the we have >= count bytes in this.buffer
+               
+               // Returns 0 if we can keep reading from the base stream,
+               // > 0 if we read something from the buffer.
+               // -1 if we had a content length set and we finished reading that many bytes.
                int FillFromBuffer (byte [] buffer, int off, int count)
                {
-                       int size = this.length - this.offset;
-                       if (size <= 0)
-                               return 0;
-
                        if (buffer == null)
                                throw new ArgumentNullException ("buffer");
                        if (off < 0)
@@ -95,9 +102,27 @@ namespace System.Net {
                        if (off > len - count)
                                throw new ArgumentException ("Reading would overrun buffer");
 
-                       size = Math.Min (size, count);
+                       if (this.remaining_body == 0)
+                               return -1;
+
+                       if (this.length == 0)
+                               return 0;
+
+                       int size = Math.Min (this.length, count);
+                       if (this.remaining_body > 0)
+                               size = (int) Math.Min (size, this.remaining_body);
+
+                       if (this.offset > this.buffer.Length - size) {
+                               size = Math.Min (size, this.buffer.Length - this.offset);
+                       }
+                       if (size == 0)
+                               return 0;
+
                        Buffer.BlockCopy (this.buffer, this.offset, buffer, off, size);
                        this.offset += size;
+                       this.length -= size;
+                       if (this.remaining_body > 0)
+                               remaining_body -= size;
                        return size;
                }
 
@@ -106,11 +131,18 @@ namespace System.Net {
                        if (disposed)
                                throw new ObjectDisposedException (typeof (RequestStream).ToString ());
 
+                       // Call FillFromBuffer to check for buffer boundaries even when remaining_body is 0
                        int nread = FillFromBuffer (buffer, offset, count);
-                       if (nread > 0)
+                       if (nread == -1) { // No more bytes available (Content-Length)
+                               return 0;
+                       } else if (nread > 0) {
                                return nread;
+                       }
 
-                       return base.Read (buffer, offset, count);
+                       nread = stream.Read (buffer, offset, count);
+                       if (nread > 0 && remaining_body > 0)
+                               remaining_body -= nread;
+                       return nread;
                }
 
                public override IAsyncResult BeginRead (byte [] buffer, int offset, int count,
@@ -120,7 +152,7 @@ namespace System.Net {
                                throw new ObjectDisposedException (typeof (RequestStream).ToString ());
 
                        int nread = FillFromBuffer (buffer, offset, count);
-                       if (nread > 0) {
+                       if (nread > 0 || nread == -1) {
                                HttpStreamAsyncResult ares = new HttpStreamAsyncResult ();
                                ares.Buffer = buffer;
                                ares.Offset = offset;
@@ -132,7 +164,11 @@ namespace System.Net {
                                return ares;
                        }
 
-                       return base.BeginRead (buffer, offset, count, cback, state);
+                       // Avoid reading past the end of the request to allow
+                       // for HTTP pipelining
+                       if (remaining_body >= 0 && count > remaining_body)
+                               count = (int) Math.Min (Int32.MaxValue, remaining_body);
+                       return stream.BeginRead (buffer, offset, count, cback, state);
                }
 
                public override int EndRead (IAsyncResult ares)
@@ -151,7 +187,10 @@ namespace System.Net {
                        }
 
                        // Close on exception?
-                       return base.EndRead (ares);
+                       int nread = stream.EndRead (ares);
+                       if (remaining_body > 0 && nread > 0)
+                               remaining_body -= nread;
+                       return nread;
                }
 
                public override long Seek (long offset, SeekOrigin origin)