New tests.
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / HttpRequestChannel.cs
index cd1af9faa39b9221f20924fa379a732a81a90d0c..4bae6026237252bad1bf95b9c5ccf720bea05541 100644 (file)
@@ -43,9 +43,6 @@ namespace System.ServiceModel.Channels
 
                WebRequest web_request;
 
-               // FIXME: supply maxSizeOfHeaders.
-               int max_headers = 0x10000;
-
                // Constructor
 
                public HttpRequestChannel (HttpChannelFactory<IRequestChannel> factory,
@@ -55,10 +52,6 @@ namespace System.ServiceModel.Channels
                        this.source = factory;
                }
 
-               public int MaxSizeOfHeaders {
-                       get { return max_headers; }
-               }
-
                public MessageEncoder Encoder {
                        get { return source.MessageEncoder; }
                }
@@ -77,7 +70,7 @@ namespace System.ServiceModel.Channels
                        // FIXME: is distination really like this?
                        Uri destination = message.Headers.To;
                        if (destination == null) {
-                               if (source.Source.ManualAddressing)
+                               if (source.Transport.ManualAddressing)
                                        throw new InvalidOperationException ("When manual addressing is enabled on the transport, every request messages must be set its destination address.");
                                 else
                                        destination = Via ?? RemoteAddress.Uri;
@@ -87,9 +80,15 @@ namespace System.ServiceModel.Channels
                        web_request.Method = "POST";
                        web_request.ContentType = Encoder.ContentType;
 
-#if !NET_2_1 // until we support NetworkCredential like SL4 will do.
+#if NET_2_1
+                       var cmgr = source.GetProperty<IHttpCookieContainerManager> ();
+                       if (cmgr != null)
+                               ((HttpWebRequest) web_request).CookieContainer = cmgr.CookieContainer;
+#endif
+
+#if !MOONLIGHT // until we support NetworkCredential like SL4 will do.
                        // client authentication (while SL3 has NetworkCredential class, it is not implemented yet. So, it is non-SL only.)
-                       var httpbe = (HttpTransportBindingElement) source.Source;
+                       var httpbe = (HttpTransportBindingElement) source.Transport;
                        string authType = null;
                        switch (httpbe.AuthenticationScheme) {
                        // AuthenticationSchemes.Anonymous is the default, ignored.
@@ -138,6 +137,7 @@ namespace System.ServiceModel.Channels
                        string pname = HttpRequestMessageProperty.Name;
                        if (message.Properties.ContainsKey (pname)) {
                                HttpRequestMessageProperty hp = (HttpRequestMessageProperty) message.Properties [pname];
+                               web_request.Headers.Clear ();
                                web_request.Headers.Add (hp.Headers);
                                web_request.Method = hp.Method;
                                // FIXME: do we have to handle hp.QueryString ?
@@ -146,6 +146,13 @@ namespace System.ServiceModel.Channels
                        }
 #endif
 
+/*
+// FIXME: this causes invalid message security.
+var mb = message.CreateBufferedCopy (0x10000);
+message = mb.CreateMessage ();
+Console.WriteLine (mb.CreateMessage ());
+*/
+
                        if (!suppressEntityBody && String.Compare (web_request.Method, "GET", StringComparison.OrdinalIgnoreCase) != 0) {
                                MemoryStream buffer = new MemoryStream ();
                                Encoder.WriteMessage (message, buffer);
@@ -198,7 +205,7 @@ namespace System.ServiceModel.Channels
                        }
 
                        var hrr = (HttpWebResponse) res;
-                       if ((int) hrr.StatusCode >= 400) {
+                       if ((int) hrr.StatusCode >= 400 && (int) hrr.StatusCode < 500) {
                                channelResult.Complete (new WebException (String.Format ("There was an error on processing web request: Status code {0}({1}): {2}", (int) hrr.StatusCode, hrr.StatusCode, hrr.StatusDescription)));
                        }
 
@@ -216,9 +223,12 @@ namespace System.ServiceModel.Channels
                                        }
                                        ms.Seek (0, SeekOrigin.Begin);
 
-                                       channelResult.Response = Encoder.ReadMessage (
-                                               //responseStream, MaxSizeOfHeaders);
-                                               ms, MaxSizeOfHeaders, res.ContentType);
+                                       Message ret = Encoder.ReadMessage (
+                                               ms, (int) source.Transport.MaxReceivedMessageSize, res.ContentType);
+                                       var rp = new HttpResponseMessageProperty () { StatusCode = hrr.StatusCode, StatusDescription = hrr.StatusDescription };
+                                       foreach (var key in hrr.Headers.AllKeys)
+                                               rp.Headers [key] = hrr.Headers [key];
+                                       ret.Properties.Add (HttpResponseMessageProperty.Name, rp);
 /*
 MessageBuffer buf = ret.CreateBufferedCopy (0x10000);
 ret = buf.CreateMessage ();
@@ -227,6 +237,7 @@ w.Formatting = System.Xml.Formatting.Indented;
 buf.CreateMessage ().WriteMessage (w);
 w.Close ();
 */
+                                       channelResult.Response = ret;
                                        channelResult.Complete ();
                                }
                        } catch (Exception ex) {
@@ -313,16 +324,15 @@ w.Close ();
                        AsyncCallback callback;
                        ManualResetEvent wait;
                        Exception error;
+                       object locker = new object ();
+                       bool is_completed;
 
                        public HttpChannelRequestAsyncResult (Message message, TimeSpan timeout, AsyncCallback callback, object state)
                        {
-                               CompletedSynchronously = true;
                                Message = message;
                                Timeout = timeout;
                                this.callback = callback;
                                AsyncState = state;
-
-                               wait = new ManualResetEvent (false);
                        }
 
                        public Message Response {
@@ -330,7 +340,13 @@ w.Close ();
                        }
 
                        public WaitHandle AsyncWaitHandle {
-                               get { return wait; }
+                               get {
+                                       lock (locker) {
+                                               if (wait == null)
+                                                       wait = new ManualResetEvent (is_completed);
+                                       }
+                                       return wait;
+                               }
                        }
 
                        public object AsyncState {
@@ -351,7 +367,6 @@ w.Close ();
                                error = error ?? ex;
 
                                IsCompleted = true;
-                               wait.Set ();
                                if (callback != null)
                                        callback (this);
                        }
@@ -361,7 +376,14 @@ w.Close ();
                        }
 
                        public bool IsCompleted {
-                               get; private set;
+                               get { return is_completed; }
+                               set {
+                                       is_completed = value;
+                                       lock (locker) {
+                                               if (is_completed && wait != null)
+                                                       wait.Set ();
+                                       }
+                               }
                        }
 
                        public void WaitEnd ()
@@ -370,11 +392,11 @@ w.Close ();
                                        // FIXME: Do we need to use the timeout? If so, what happens when the timeout is reached.
                                        // Is the current request cancelled and an exception thrown? If so we need to pass the
                                        // exception to the Complete () method and allow the result to complete 'normally'.
-#if NET_2_1 || MONOTOUCH
+#if NET_2_1
                                        // neither Moonlight nor MonoTouch supports contexts (WaitOne default to false)
-                                       bool result = wait.WaitOne (Timeout);
+                                       bool result = AsyncWaitHandle.WaitOne (Timeout);
 #else
-                                       bool result = wait.WaitOne (Timeout, true);
+                                       bool result = AsyncWaitHandle.WaitOne (Timeout, true);
 #endif
                                        if (!result)
                                                throw new TimeoutException ();