Browse Source

2004-02-12 Gonzalo Paniagua Javier <[email protected]>

	* ChunkStream.cs: use an array of buffers instead of a MemoryStream for
	storing the chunks. This way, we won't miss traling data from the
	previous chunk when a new one is received before the other is fully
	read.

svn path=/trunk/mcs/; revision=23004
Gonzalo Paniagua Javier 22 years ago
parent
commit
c48e993d10
2 changed files with 56 additions and 20 deletions
  1. 7 0
      mcs/class/System/System.Net/ChangeLog
  2. 49 20
      mcs/class/System/System.Net/ChunkStream.cs

+ 7 - 0
mcs/class/System/System.Net/ChangeLog

@@ -1,3 +1,10 @@
+2004-02-12  Gonzalo Paniagua Javier <[email protected]>
+
+	* ChunkStream.cs: use an array of buffers instead of a MemoryStream for
+	storing the chunks. This way, we won't miss traling data from the
+	previous chunk when a new one is received before the other is fully
+	read.
+
 2004-01-27  Nick Drochak <[email protected]>
 
 	* DigestClient.cs:

+ 49 - 20
mcs/class/System/System.Net/ChunkStream.cs

@@ -7,6 +7,7 @@
 // (C) 2003 Ximian, Inc (http://www.ximian.com)
 //
 
+using System.Collections;
 using System.Globalization;
 using System.IO;
 using System.Text;
@@ -22,7 +23,24 @@ namespace System.Net
 			Trailer
 		}
 
-		MemoryStream ms;
+		class Chunk {
+			public byte [] Bytes;
+			public int Offset;
+
+			public Chunk (byte [] chunk)
+			{
+				this.Bytes = chunk;
+			}
+
+			public int Read (byte [] buffer, int offset, int size)
+			{
+				int nread = (size > Bytes.Length - Offset) ? Bytes.Length - Offset : size;
+				Buffer.BlockCopy (Bytes, Offset, buffer, offset, nread);
+				Offset += nread;
+				return nread;
+			}
+		}
+
 		WebHeaderCollection headers;
 		int chunkSize;
 		int chunkRead;
@@ -31,24 +49,22 @@ namespace System.Net
 		StringBuilder saved;
 		bool sawCR;
 		bool gotit;
-		long readPosition;
+		ArrayList chunks;
 		
 		public ChunkStream (byte [] buffer, int offset, int size, WebHeaderCollection headers)
 		{
 			this.headers = headers;
-			ms = new MemoryStream ();
 			saved = new StringBuilder ();
+			chunks = new ArrayList ();
 			chunkSize = -1;
-			if (offset < size)
-				Write (buffer, offset, size);
+			Write (buffer, offset, size);
 		}
 
 		public void ResetBuffer ()
 		{
-			ms.SetLength (0);
-			readPosition = 0;
 			chunkSize = -1;
 			chunkRead = 0;
+			chunks.Clear ();
 		}
 		
 		public void WriteAndReadBack (byte [] buffer, int offset, int size, ref int read)
@@ -59,14 +75,31 @@ namespace System.Net
 
 		public int Read (byte [] buffer, int offset, int size)
 		{
-			long prevPosition = ms.Position;
-			ms.Position = readPosition;
-			int r = ms.Read (buffer, offset, size);
-			readPosition += r;
-			ms.Position = prevPosition;
-			return r;
+			return ReadFromChunks (buffer, offset, size);
 		}
 
+		int ReadFromChunks (byte [] buffer, int offset, int size)
+		{
+			int count = chunks.Count;
+			int nread = 0;
+			for (int i = 0; i < count; i++) {
+				Chunk chunk = (Chunk) chunks [i];
+				if (chunk == null)
+					continue;
+
+				if (chunk.Offset == chunk.Bytes.Length) {
+					chunks [i] = null;
+					continue;
+				}
+				
+				nread += chunk.Read (buffer, offset + nread, size - nread);
+				if (nread == size)
+					break;
+			}
+
+			return nread;
+		}
+		
 		public void Write (byte [] buffer, int offset, int size)
 		{
 			InternalWrite (buffer, ref offset, size);
@@ -75,16 +108,10 @@ namespace System.Net
 		void InternalWrite (byte [] buffer, ref int offset, int size)
 		{
 			if (state == State.None) {
-				ms.Position = 0;
-				readPosition = 0;
 				state = GetChunkSize (buffer, ref offset, size);
 				if (state == State.None)
 					return;
 				
-				ms.SetLength (0);
-				if (ms.Capacity < chunkSize)
-					ms.Capacity = chunkSize;
-
 				saved.Length = 0;
 				sawCR = false;
 				gotit = false;
@@ -131,7 +158,9 @@ namespace System.Net
 			if (diff + chunkRead > chunkSize)
 				diff = chunkSize - chunkRead;
 
-			ms.Write (buffer, offset, diff);
+			byte [] chunk = new byte [diff];
+			Buffer.BlockCopy (buffer, offset, chunk, 0, diff);
+			chunks.Add (new Chunk (chunk));
 			offset += diff;
 			chunkRead += diff;
 			return (chunkRead == chunkSize) ? State.BodyFinished : State.Body;