WebRequest web_request;
- // FIXME: supply maxSizeOfHeaders.
- int max_headers = 0x10000;
-
// Constructor
public HttpRequestChannel (HttpChannelFactory<IRequestChannel> factory,
this.source = factory;
}
- public int MaxSizeOfHeaders {
- get { return max_headers; }
- }
-
public MessageEncoder Encoder {
get { return source.MessageEncoder; }
}
// 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;
web_request.Method = "POST";
web_request.ContentType = Encoder.ContentType;
+#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.Transport;
+ string authType = null;
+ switch (httpbe.AuthenticationScheme) {
+ // AuthenticationSchemes.Anonymous is the default, ignored.
+ case AuthenticationSchemes.Basic:
+ authType = "Basic";
+ break;
+ case AuthenticationSchemes.Digest:
+ authType = "Digest";
+ break;
+ case AuthenticationSchemes.Ntlm:
+ authType = "Ntlm";
+ break;
+ case AuthenticationSchemes.Negotiate:
+ authType = "Negotiate";
+ break;
+ }
+ if (authType != null) {
+ var cred = source.ClientCredentials;
+ string user = cred != null ? cred.UserName.UserName : null;
+ string pwd = cred != null ? cred.UserName.Password : null;
+ if (String.IsNullOrEmpty (user))
+ throw new InvalidOperationException (String.Format ("Use ClientCredentials to specify a user name for required HTTP {0} authentication.", authType));
+ var nc = new NetworkCredential (user, pwd);
+ web_request.Credentials = nc;
+ // FIXME: it is said required in SL4, but it blocks full WCF.
+ //web_request.UseDefaultCredentials = false;
+ }
+#endif
+
#if !NET_2_1 // FIXME: implement this to not depend on Timeout property
web_request.Timeout = (int) timeout.TotalMilliseconds;
#endif
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 ?
}
#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);
resstr = res.GetResponseStream ();
} catch (WebException we) {
res = we.Response;
-#if NET_2_1 // debug
- Console.WriteLine (we);
-#endif
+ if (res == null) {
+ channelResult.Complete (we);
+ return;
+ }
try {
// The response might contain SOAP fault. It might not.
resstr = res.GetResponseStream ();
} catch (WebException we2) {
-#if NET_2_1 // debug
- Console.WriteLine (we2);
-#endif
-
channelResult.Complete (we2);
return;
}
}
-
+
+ var hrr = (HttpWebResponse) res;
+ 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)));
+ }
+
try {
using (var responseStream = resstr) {
MemoryStream ms = new MemoryStream ();
}
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 ();
buf.CreateMessage ().WriteMessage (w);
w.Close ();
*/
+ channelResult.Response = ret;
channelResult.Complete ();
}
} catch (Exception ex) {
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 {
}
public WaitHandle AsyncWaitHandle {
- get { return wait; }
+ get {
+ lock (locker) {
+ if (wait == null)
+ wait = new ManualResetEvent (is_completed);
+ }
+ return wait;
+ }
}
public object AsyncState {
error = error ?? ex;
IsCompleted = true;
- wait.Set ();
if (callback != null)
callback (this);
}
}
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 ()
{
if (!IsCompleted) {
-
- const bool exit_context =
-#if MONOTOUCH
- false; // MonoTouch doesn't support any remoting feature
-#else
- true;
-#endif
-
// 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 (!wait.WaitOne (Timeout, exit_context))
+#if NET_2_1
+ // neither Moonlight nor MonoTouch supports contexts (WaitOne default to false)
+ bool result = AsyncWaitHandle.WaitOne (Timeout);
+#else
+ bool result = AsyncWaitHandle.WaitOne (Timeout, true);
+#endif
+ if (!result)
throw new TimeoutException ();
}
if (error != null)