* docs.make, Makefile.am: Build mono-file-formats{.tree,.zip},
[mono.git] / mcs / class / System / System.Net / HttpConnection.cs
index 706979771950010f13a8d3115d679a4c3f3b32fe..6a57e3a6dcc5a2a05e241918a5dc9f9d43a78203 100644 (file)
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-#if NET_2_0
+
+#if NET_2_0 && SECURITY_DEP
+
 using System.IO;
 using System.Net.Sockets;
+using System.Reflection;
 using System.Text;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using Mono.Security.Protocol.Tls;
+
 namespace System.Net {
        sealed class HttpConnection
        {
                const int BufferSize = 8192;
                Socket sock;
-               NetworkStream stream;
+               Stream stream;
                EndPointListener epl;
                MemoryStream ms;
                byte [] buffer;
                HttpListenerContext context;
-               bool secure;
                StringBuilder current_line;
                ListenerPrefix prefix;
                RequestStream i_stream;
@@ -47,16 +53,35 @@ namespace System.Net {
                bool chunked;
                int chunked_uses;
                bool context_bound;
+               bool secure;
+               AsymmetricAlgorithm key;
 
-               public HttpConnection (Socket sock, EndPointListener epl, bool secure)
+               public HttpConnection (Socket sock, EndPointListener epl, bool secure, X509Certificate2 cert, AsymmetricAlgorithm key)
                {
                        this.sock = sock;
-                       stream = new NetworkStream (sock, false);
                        this.epl = epl;
                        this.secure = secure;
+                       this.key = key;
+                       if (secure == false) {
+                               stream = new NetworkStream (sock, false);
+                       } else {
+#if EMBEDDED_IN_1_0
+                               throw new NotImplementedException ();
+#else
+                               SslServerStream ssl_stream = new SslServerStream (new NetworkStream (sock, false), cert, false, false);
+                               ssl_stream.PrivateKeyCertSelectionDelegate += OnPVKSelection;
+                               stream = ssl_stream;
+#endif
+                       }
                        Init ();
                }
 
+               AsymmetricAlgorithm OnPVKSelection (X509Certificate certificate, string targetHost)
+               {
+                       return key;
+               }
+
+
                void Init ()
                {
                        context_bound = false;
@@ -96,7 +121,11 @@ namespace System.Net {
                {
                        if (buffer == null)
                                buffer = new byte [BufferSize];
-                       stream.BeginRead (buffer, 0, BufferSize, OnRead, this);
+                       try {
+                               stream.BeginRead (buffer, 0, BufferSize, OnRead, this);
+                       } catch {
+                               sock.Close (); // stream disposed
+                       }
                }
 
                public RequestStream GetRequestStream (bool chunked, long contentlength)
@@ -108,9 +137,9 @@ namespace System.Net {
                                if (chunked) {
                                        this.chunked = true;
                                        context.Response.SendChunked = true;
-                                       i_stream = new ChunkedInputStream (context, sock, buffer, position, length);
+                                       i_stream = new ChunkedInputStream (context, stream, buffer, position, length - position);
                                } else {
-                                       i_stream = new RequestStream (sock, buffer, position, length, contentlength);
+                                       i_stream = new RequestStream (stream, buffer, position, length - position, contentlength);
                                }
                        }
                        return i_stream;
@@ -122,7 +151,7 @@ namespace System.Net {
                        if (o_stream == null) {
                                HttpListener listener = context.Listener;
                                bool ign = (listener == null) ? true : listener.IgnoreWriteExceptions;
-                               o_stream = new ResponseStream (sock, context.Response, ign);
+                               o_stream = new ResponseStream (stream, context.Response, ign);
                        }
                        return o_stream;
                }
@@ -135,7 +164,8 @@ namespace System.Net {
                        try {
                                nread = stream.EndRead (ares);
                                ms.Write (buffer, 0, nread);
-                       } catch {
+                       } catch (Exception e) {
+                               //Console.WriteLine (e);
                                if (ms.Length > 0)
                                        SendError ();
                                sock.Close ();
@@ -289,10 +319,20 @@ namespace System.Net {
                                        return;
                                }
 
-                               Socket s = sock;
-                               sock = null;
-                               s.Shutdown (SocketShutdown.Both);
-                               s.Close ();
+                               if (context.Response.Headers ["connection"] == "close") {
+                                       Socket s = sock;
+                                       sock = null;
+                                       try {
+                                               s.Shutdown (SocketShutdown.Both);
+                                       } finally {
+                                               s.Close ();
+                                       }
+                               } else {
+                                       Init ();
+                                       BeginReadRequest ();
+                                       return;
+                               }
+
                                if (context_bound)
                                        epl.UnbindContext (context);
                        }