// (C) 2003 Martin Willemoes Hansen
//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using System;
using System.Collections;
using System.IO;
namespace System.Runtime.Remoting.Channels.Http
{
- public class HttpClientChannel : IChannelSender,IChannel
+ public class HttpClientChannel : BaseChannelWithProperties, IChannelSender,IChannel
{
// Property Keys (purposely all lower-case)
private const String ProxyNameKey = "proxyname";
private int _clientConnectionLimit = 0; // bump connection limit to at least this number (only meaningful if > 0)
private bool _bUseDefaultCredentials = false; // should default credentials be used?
- private IClientChannelSinkProvider _sinkProvider = null; // sink chain provider
-
- private IMessageSink _msgSink;
-
-
+ private IClientChannelSinkProvider _sinkProvider = null; // sink chain provider
public HttpClientChannel()
{
-
- SetupProvider(_sinkProvider);
+ SetupProvider (null,null);
}
-
-
public HttpClientChannel(String name, IClientChannelSinkProvider sinkProvider)
{
if(name != null)
_channelName = name;
- SetupProvider(sinkProvider);
+ SetupProvider (sinkProvider, null);
}
-
// constructor used by config file
public HttpClientChannel(IDictionary properties, IClientChannelSinkProvider sinkProvider)
}
}
- SetupProvider (sinkProvider);
-
+ SetupProvider (sinkProvider, properties);
}
-
public int ChannelPriority
{
get { return _channelPriority; }
public virtual IMessageSink CreateMessageSink(String url, Object remoteChannelData, out String objectURI)
{
- if (url == null && remoteChannelData != null && remoteChannelData as IChannelDataStore != null )
+ if ((url == null || !HttpHelper.StartsWithHttp (url)) && remoteChannelData != null && remoteChannelData as IChannelDataStore != null )
{
IChannelDataStore ds = (IChannelDataStore) remoteChannelData;
url = ds.ChannelUris[0];
if(url != null && HttpHelper.StartsWithHttp(url))
{
HttpHelper.Parse(url, out objectURI);
- _msgSink = (IMessageSink) _sinkProvider.CreateSink(this,url,remoteChannelData);
+ IMessageSink msgSink = (IMessageSink) _sinkProvider.CreateSink(this,url,remoteChannelData);
- if(_msgSink !=null )
+ if(msgSink !=null )
SetServicePoint(url);
- return _msgSink;
+ return msgSink;
}
else
{
objectURI = null;
return null;
}
-
}
private void UpdateProxy()
internal IWebProxy ProxyObject { get { return _proxyObject; } }
internal bool UseDefaultCredentials { get { return _bUseDefaultCredentials; } }
- private void SetupProvider(IClientChannelSinkProvider sinkProvider)
+ private void SetupProvider (IClientChannelSinkProvider sinkProvider, IDictionary properties)
{
+ if (properties == null) properties = new Hashtable ();
+ HttpClientTransportSinkProvider httpSink = new HttpClientTransportSinkProvider (properties);
+ SinksWithProperties = httpSink;
+
if(sinkProvider == null)
{
_sinkProvider = new SoapClientFormatterSinkProvider();
- _sinkProvider.Next = new HttpClientTransportSinkProvider();
+ _sinkProvider.Next = httpSink;
}
else
{
dummySinkProvider = dummySinkProvider.Next;
}
- dummySinkProvider.Next = new HttpClientTransportSinkProvider();
+ dummySinkProvider.Next = httpSink;
}
-
+ }
+
+ public override object this [object key]
+ {
+ get { return Properties[key]; }
+ set { Properties[key] = value; }
+ }
+
+ public override ICollection Keys
+ {
+ get { return Properties.Keys; }
}
}
- internal class HttpClientTransportSinkProvider : IClientChannelSinkProvider
+ internal class HttpClientTransportSinkProvider : IClientChannelSinkProvider, IChannelSinkBase
{
- internal HttpClientTransportSinkProvider()
+ IDictionary _properties;
+
+ internal HttpClientTransportSinkProvider (IDictionary properties)
{
+ _properties = properties;
}
public IClientChannelSink CreateSink(IChannelSender channel, String url,
get { return null; }
set { throw new NotSupportedException(); }
}
+
+ public IDictionary Properties
+ {
+ get { return _properties; }
+ }
+
} // class HttpClientTransportSinkProvider
out ITransportHeaders responseHeaders, out Stream responseStream)
{
string url = null;
- string uri = (string)requestHeaders[CommonTransportKeys.RequestUri];
+ string uri = ((IMethodCallMessage)msg).Uri;
+ requestHeaders [CommonTransportKeys.RequestUri] = uri;
CreateUrl(uri,out url);
- HttpWebRequest httpWebRequest = CreateWebRequest(url,requestHeaders,requestStream);
+ HttpWebRequest httpWebRequest = CreateWebRequest (url,requestHeaders,requestStream);
- SendAndRecieve(httpWebRequest,out responseHeaders,out responseStream);
+ SendAndRecieve (httpWebRequest,out responseHeaders,out responseStream);
}
ITransportHeaders headers, Stream stream)
{
string url = null;
- string uri = (string)headers[CommonTransportKeys.RequestUri];
+ string uri = ((IMethodCallMessage)msg).Uri;
+ headers [CommonTransportKeys.RequestUri] = uri;
CreateUrl(uri,out url);
HttpWebRequest httpWebRequest = CreateWebRequest(url,headers,stream);
}
Stream reqStream = request.GetRequestStream();
- if (requestStream is MemoryStream)
- {
- MemoryStream memStream = (MemoryStream)requestStream;
- reqStream.Write (memStream.GetBuffer(), 0, (int)memStream.Length);
- }
- else
+ try {
HttpHelper.CopyStream(requestStream, reqStream);
-
- reqStream.Close();
+ } finally {
+ reqStream.Close();
+ }
return request;
}
catch (WebException ex)
{
httpWebResponse = ex.Response as HttpWebResponse;
- if (httpWebResponse == null) throw ex;
+ if (httpWebResponse == null || httpWebResponse.StatusCode == HttpStatusCode.InternalServerError) throw ex;
}
ReceiveResponse (httpWebResponse, out responseHeaders, out responseStream);
private void ReceiveResponse (HttpWebResponse httpWebResponse, out ITransportHeaders responseHeaders, out Stream responseStream)
{
responseHeaders = new TransportHeaders();
+ Stream webStream = httpWebResponse.GetResponseStream();
try
{
- Stream webStream = httpWebResponse.GetResponseStream();
-
if (httpWebResponse.ContentLength != -1)
{
byte[] buffer = new byte [httpWebResponse.ContentLength];
int nr = 0;
- while (nr < buffer.Length)
- nr += webStream.Read (buffer, nr, buffer.Length - nr);
+ while (nr < buffer.Length) {
+ int pr = webStream.Read (buffer, nr, buffer.Length - nr);
+ if (pr == 0) throw new RemotingException ("Connection closed");
+ nr += pr;
+ }
responseStream = new MemoryStream (buffer);
}
else
}
finally
{
- if(httpWebResponse!=null)
- httpWebResponse.Close();
+ webStream.Close ();
+ httpWebResponse.Close();
}
}