104aef3173deb13bf077c8f3c0fed5135b2ecc2f
[mono.git] / mcs / class / System / System.Net / ResponseStream.cs
1 //
2 // System.Net.ResponseStream
3 //
4 // Author:
5 //      Gonzalo Paniagua Javier (gonzalo@novell.com)
6 //
7 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 #if NET_2_0
29 using System.IO;
30 using System.Net.Sockets;
31 using System.Text;
32 using System.Runtime.InteropServices;
33 namespace System.Net {
34         // FIXME: Does this buffer the response until Close?
35         // What happens when we set content-length to X and write X-1 bytes then close?
36         // what if we don't set content-length at all?
37         class ResponseStream : NetworkStream
38         {
39                 HttpListenerResponse response;
40                 bool ignore_errors;
41                 bool disposed;
42                 bool trailer_sent;
43
44                 internal ResponseStream (Socket sock, HttpListenerResponse response, bool ignore_errors) :
45                                         base (sock, false)
46                 {
47                         this.response = response;
48                         this.ignore_errors = ignore_errors;
49                 }
50
51                 public override bool CanRead {
52                         get { return false; }
53                 }
54
55                 public override bool CanSeek {
56                         get { return false; }
57                 }
58
59                 public override bool CanWrite {
60                         get { return true; }
61                 }
62
63                 public override long Length {
64                         get { throw new NotSupportedException (); }
65                 }
66
67                 public override long Position {
68                         get { throw new NotSupportedException (); }
69                         set { throw new NotSupportedException (); }
70                 }
71
72
73                 public override void Close ()
74                 {
75                         if (disposed == false) {
76                                 disposed = true;
77                                 if (response.HeadersSent == false)
78                                         response.SendHeaders (true);
79
80                                 if (response.SendChunked && !trailer_sent) {
81                                         WriteChunkSize (0, true);
82                                         trailer_sent = true;
83                                 }
84                                 response.Close ();
85                         }
86                 }
87
88                 public override void Flush ()
89                 {
90                 }
91
92                 static byte [] crlf = new byte [] { 13, 10 };
93                 void WriteChunkSize (int size, bool final)
94                 {
95                         string str = String.Format ("{0:x}\r\n{1}", size, final ? "\r\n" : "");
96                         byte [] b = Encoding.ASCII.GetBytes (str);
97                         base.Write (b, 0, b.Length);
98                 }
99
100                 internal void InternalWrite (byte [] buffer, int offset, int count)
101                 {
102                         if (ignore_errors) {
103                                 try {
104                                         base.Write (buffer, offset, count);
105                                 } catch { }
106                         } else {
107                                 base.Write (buffer, offset, count);
108                         }
109                 }
110
111                 public override void Write (byte [] buffer, int offset, int count)
112                 {
113                         if (disposed)
114                                 throw new ObjectDisposedException (GetType ().ToString ());
115
116                         if (response.HeadersSent == false)
117                                 response.SendHeaders (false);
118
119                         bool chunked = response.SendChunked;
120                         try {
121                                 if (chunked)
122                                         WriteChunkSize (count, false);
123                         } catch { }
124                         InternalWrite (buffer, offset, count);
125                         try {
126                                 if (chunked)
127                                         base.Write (crlf, 0, 2);
128                         } catch { }
129                 }
130
131                 public override IAsyncResult BeginWrite (byte [] buffer, int offset, int count,
132                                                         AsyncCallback cback, object state)
133                 {
134                         if (disposed)
135                                 throw new ObjectDisposedException (GetType ().ToString ());
136
137                         if (response.HeadersSent == false)
138                                 response.SendHeaders (false);
139
140                         try {
141                                 if (response.SendChunked)
142                                         WriteChunkSize (count, false);
143                         } catch { }
144                         return base.BeginWrite (buffer, offset, count, cback, state);
145                 }
146
147                 public override void EndWrite (IAsyncResult ares)
148                 {
149                         if (disposed)
150                                 throw new ObjectDisposedException (GetType ().ToString ());
151
152                         if (ignore_errors) {
153                                 try {
154                                         base.EndWrite (ares);
155                                         if (response.SendChunked)
156                                                 base.Write (crlf, 0, 2);
157                                 } catch { }
158                         } else {
159                                 base.EndWrite (ares);
160                                 if (response.SendChunked)
161                                         base.Write (crlf, 0, 2);
162                         }
163                 }
164
165                 public override int Read ([In,Out] byte[] buffer, int offset, int count)
166                 {
167                         throw new NotSupportedException ();
168                 }
169
170                 public override IAsyncResult BeginRead (byte [] buffer, int offset, int count,
171                                                         AsyncCallback cback, object state)
172                 {
173                         throw new NotSupportedException ();
174                 }
175
176                 public override int EndRead (IAsyncResult ares)
177                 {
178                         throw new NotSupportedException ();
179                 }
180
181                 public override long Seek (long offset, SeekOrigin origin)
182                 {
183                         throw new NotSupportedException ();
184                 }
185
186                 public override void SetLength (long value)
187                 {
188                         throw new NotSupportedException ();
189                 }
190         }
191 }
192 #endif
193