2009-01-19 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System / System.Net / RequestStream.cs
index bc80f676a0d650ff4b32a47e39430ee0db9a15bd..748808f4be0db973ce300b4045dfbe6a61826e84 100644 (file)
@@ -30,30 +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 available;
+               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)
                {
-                       this.buffer = buffer;
-                       this.offset = offset;
-                       this.length = length;
-                       this.available = -1;
                }
 
-               internal RequestStream (Socket sock, byte [] buffer, int offset, int length, long contentlength) :
-                                       base (sock, false)
+               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.available = contentlength;
+                       this.remaining_body = contentlength;
                }
 
                public override bool CanRead {
@@ -80,20 +77,19 @@ namespace System.Net {
 
                public override void Close ()
                {
-                       // TODO: What do we close?
+                       disposed = true;
                }
 
                public override void Flush ()
                {
                }
 
-               // 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)
@@ -106,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;
                }
 
@@ -117,21 +131,17 @@ namespace System.Net {
                        if (disposed)
                                throw new ObjectDisposedException (typeof (RequestStream).ToString ());
 
-                       if (available == 0)
-                               return 0;
-
+                       // 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;
+                       }
 
-                       // Avoid reading past the end of the request to allow
-                       // for HTTP pipelining
-                       if (available != -1 && count > available)
-                               count = (int) available;
-
-                       nread = base.Read (buffer, offset, count);
-                       if (available != -1)
-                               available -= nread;
+                       nread = stream.Read (buffer, offset, count);
+                       if (nread > 0 && remaining_body > 0)
+                               remaining_body -= nread;
                        return nread;
                }
 
@@ -142,7 +152,7 @@ namespace System.Net {
                                throw new ObjectDisposedException (typeof (RequestStream).ToString ());
 
                        int nread = FillFromBuffer (buffer, offset, count);
-                       if (nread > 0 || available == 0) {
+                       if (nread > 0 || nread == -1) {
                                HttpStreamAsyncResult ares = new HttpStreamAsyncResult ();
                                ares.Buffer = buffer;
                                ares.Offset = offset;
@@ -156,9 +166,9 @@ namespace System.Net {
 
                        // Avoid reading past the end of the request to allow
                        // for HTTP pipelining
-                       if (available != -1 && count > available)
-                               count = (int) Math.Min (Int32.MaxValue, available);
-                       return base.BeginRead (buffer, offset, count, cback, state);
+                       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)
@@ -177,9 +187,9 @@ namespace System.Net {
                        }
 
                        // Close on exception?
-                       int nread = base.EndRead (ares);
-                       if (available != -1)
-                               available -= nread;
+                       int nread = stream.EndRead (ares);
+                       if (remaining_body > 0 && nread > 0)
+                               remaining_body -= nread;
                        return nread;
                }