You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			338 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			338 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //
 | |
| // HttpClientChannel.cs
 | |
| // 
 | |
| // Author:
 | |
| //   Michael Hutchinson <mhutchinson@novell.com>
 | |
| // 
 | |
| // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
 | |
| // 
 | |
| // 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.Net;
 | |
| using System.Collections;
 | |
| using System.Globalization;
 | |
| using System.Runtime.Remoting.Messaging;
 | |
| 
 | |
| namespace System.Runtime.Remoting.Channels.Http
 | |
| {
 | |
| 
 | |
| 	public class HttpClientChannel : BaseChannelWithProperties,
 | |
| 		IChannel, IChannelSender
 | |
| 		, ISecurableChannel
 | |
| 	{
 | |
| 		string name = "http client";
 | |
| 		int priority = 1;
 | |
| 
 | |
| 
 | |
| 		// names and (some) default values fromhttp://msdn.microsoft.com/en-us/library/bb187435(VS.85).aspx
 | |
| 		// other values guessed from defaults of HttpWebResponse
 | |
| 		string machineName = null;
 | |
| 		bool allowAutoRedirect = true; //FIXME: what's the default? true/false?
 | |
| 		int clientConnectionLimit = 2;
 | |
| 		string connectionGroupName = null;
 | |
| 		ICredentials credentials = null;
 | |
| 		string domain = null;
 | |
| 		string password = null;
 | |
| 		string proxyName = null;
 | |
| 		int proxyPort = -1;
 | |
| 		Uri proxyUri = null;
 | |
| 		string servicePrincipalName = null;
 | |
| 		int timeout = -1;
 | |
| 		bool unsafeAuthenticatedConnectionSharing = false;
 | |
| 		// according to docs, should be true if useDefaultCredentials true or 
 | |
| 		// credentials is CredentialCache.DefaultCredentials
 | |
| 		bool useAuthenticatedConnectionSharing = false;
 | |
| 		bool useDefaultCredentials = false;
 | |
| 		string username = null;
 | |
| 		
 | |
| 		bool isSecured = false;
 | |
| 
 | |
| 		IClientChannelSinkProvider sinkProvider;
 | |
| 
 | |
| 		#region Constructors
 | |
| 
 | |
| 		public HttpClientChannel ()
 | |
| 		{
 | |
| 			BuildSink (null);
 | |
| 		}
 | |
| 		
 | |
| 		[MonoTODO ("Handle the machineName, proxyName, proxyPort, servicePrincipalName, " + 
 | |
| 			"useAuthenticatedConnectionSharing properties")]
 | |
| 		public HttpClientChannel (IDictionary properties, IClientChannelSinkProvider sinkProvider)
 | |
| 		{
 | |
| 			if (properties != null) {
 | |
| 				foreach (DictionaryEntry property in properties) {
 | |
| 					switch ((string)property.Key) {
 | |
| 					case "name":
 | |
| 						//NOTE: matching MS behaviour: throws InvalidCastException, allows null
 | |
| 						this.name = (string)property.Value;
 | |
| 						break;
 | |
| 					case "priority":
 | |
| 						this.priority = Convert.ToInt32 (property.Value);
 | |
| 						break;
 | |
| 					case "machineName":
 | |
| 						this.machineName = (string)property.Value;
 | |
| 						break;
 | |
| 					case "allowAutoRedirect":
 | |
| 						this.allowAutoRedirect = Convert.ToBoolean (property.Value);
 | |
| 						break;
 | |
| 					case "clientConnectionLimit":
 | |
| 						this.clientConnectionLimit = Convert.ToInt32 (property.Value);
 | |
| 						break;
 | |
| 					case "connectionGroupName":
 | |
| 						this.connectionGroupName = (string)property.Value;
 | |
| 						break;
 | |
| 					case "credentials":
 | |
| 						this.credentials = (ICredentials)property.Value;
 | |
| 						if (this.credentials == CredentialCache.DefaultCredentials)
 | |
| 							useAuthenticatedConnectionSharing = true;
 | |
| 						break;
 | |
| 					case "domain":
 | |
| 						this.domain = (string)property.Value;
 | |
| 						break;
 | |
| 					case "password":
 | |
| 						this.password = (string)property.Value;
 | |
| 						break;
 | |
| 					case "proxyName":
 | |
| 						this.proxyName = (string)property.Value;
 | |
| 						break;
 | |
| 					case "proxyPort":
 | |
| 						this.proxyPort = Convert.ToInt32 (property.Value);
 | |
| 						break;
 | |
| 					case "servicePrincipalName":
 | |
| 						this.servicePrincipalName = (string)property.Value;
 | |
| 						break;
 | |
| 					case "timeout":
 | |
| 						this.timeout = Convert.ToInt32 (property.Value);
 | |
| 						break;
 | |
| 					case "unsafeAuthenticatedConnectionSharing":
 | |
| 						this.unsafeAuthenticatedConnectionSharing = Convert.ToBoolean (property.Value);
 | |
| 						break;
 | |
| 					case "useAuthenticatedConnectionSharing":
 | |
| 						this.useAuthenticatedConnectionSharing = Convert.ToBoolean (property.Value);
 | |
| 						break;
 | |
| 					case "useDefaultCredentials":
 | |
| 						this.useDefaultCredentials = Convert.ToBoolean (property.Value);
 | |
| 						if (useDefaultCredentials)
 | |
| 							useAuthenticatedConnectionSharing = true;
 | |
| 						break;
 | |
| 					case "username":
 | |
| 						this.username = (string)property.Value;
 | |
| 						break;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			BuildSink (sinkProvider);
 | |
| 		}
 | |
| 
 | |
| 		public HttpClientChannel (string name, IClientChannelSinkProvider sinkProvider)
 | |
| 		{
 | |
| 			this.name = name;
 | |
| 			BuildSink (sinkProvider);
 | |
| 		}
 | |
| 
 | |
| 		void BuildSink (IClientChannelSinkProvider sinkProvider)
 | |
| 		{
 | |
| 			if (sinkProvider == null) {
 | |
| 				//according to docs, defaults to SOAP if no other sink provided
 | |
| 				sinkProvider = new SoapClientFormatterSinkProvider ();
 | |
| 			}
 | |
| 
 | |
| 			this.sinkProvider = sinkProvider;
 | |
| 
 | |
| 			//add HTTP sink at the end of the chain
 | |
| 			while (sinkProvider.Next != null) sinkProvider = sinkProvider.Next;
 | |
| 			sinkProvider.Next = new HttpClientTransportSinkProvider ();
 | |
| 
 | |
| 			// LAMESPEC: BaseChannelWithProperties wants SinksWithProperties to be set with the sink chain
 | |
| 			// BUT MS' HttpClientChannel does not set it (inspected from HttpClientChannel subclass)
 | |
| 		}
 | |
| 
 | |
| 		#endregion
 | |
| 
 | |
| 		#region BaseChannelWithProperties overrides
 | |
| 
 | |
| 		public override object this[object key]
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				switch (key as string) {
 | |
| 				case "proxyport":
 | |
| 					return proxyPort;
 | |
| 				case "proxyname":
 | |
| 					return proxyName;
 | |
| 				}
 | |
| 				return null;
 | |
| 			}
 | |
| 			set
 | |
| 			{
 | |
| 				switch (key as string) {
 | |
| 				case "proxyport":
 | |
| 					proxyPort = Convert.ToInt32 (value);
 | |
| 					ConstructProxy ();
 | |
| 					return;
 | |
| 				case "proxyname":
 | |
| 					proxyName = (string)value;
 | |
| 					ConstructProxy ();
 | |
| 					return;
 | |
| 				}
 | |
| 				//ignore other values, MS does so
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public override ICollection Keys
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				return new string[] {
 | |
| 					"proxyname",
 | |
| 					"proxyport"
 | |
| 				};
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		void ConstructProxy ()
 | |
| 		{
 | |
| 			if (proxyName != null && proxyPort > 0)
 | |
| 				proxyUri = new Uri (proxyName + ":" + proxyPort);
 | |
| 		}
 | |
| 
 | |
| 		#endregion
 | |
| 
 | |
| 		#region IChannel
 | |
| 
 | |
| 		public string ChannelName
 | |
| 		{
 | |
| 			get { return name; }
 | |
| 		}
 | |
| 
 | |
| 		public int ChannelPriority
 | |
| 		{
 | |
| 			get { return priority; }
 | |
| 		}
 | |
| 
 | |
| 		public string Parse (string url, out string objectURI)
 | |
| 		{
 | |
| 			return HttpChannel.ParseInternal (url, out objectURI);
 | |
| 		}
 | |
| 
 | |
| 		#endregion
 | |
| 
 | |
| 		#region IChannelSender (: IChannel)
 | |
| 
 | |
| 		public virtual IMessageSink CreateMessageSink (string url, object remoteChannelData, out string objectURI)
 | |
| 		{
 | |
| 			//Mostly copied from TcpClientChannel
 | |
| 			if (url == null || Parse (url, out objectURI) == null) {
 | |
| 				if (remoteChannelData != null) {
 | |
| 					IChannelDataStore ds = remoteChannelData as IChannelDataStore;
 | |
| 					if (ds != null && ds.ChannelUris.Length > 0)
 | |
| 						url = ds.ChannelUris[0];
 | |
| 					else {
 | |
| 						objectURI = null;
 | |
| 						return null;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				if (Parse (url, out objectURI) == null)
 | |
| 					return null;
 | |
| 			}
 | |
| 			
 | |
| 			object newSink = sinkProvider.CreateSink (this, url, remoteChannelData);
 | |
| 			if (newSink is IMessageSink) {
 | |
| 				return (IMessageSink) newSink;
 | |
| 			} else {
 | |
| 				throw new RemotingException ("First channel sink must implement IMessageSink");
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		#endregion
 | |
| 		
 | |
| 		#region ISecurableChannel
 | |
| 		
 | |
| 		public bool IsSecured
 | |
| 		{
 | |
| 			get { return isSecured; }
 | |
| 			set {
 | |
| 				throw new NotImplementedException ("Unable to determine expected behaviour yet.");
 | |
| 			}
 | |
| 		}
 | |
| 		
 | |
| 		#endregion
 | |
| 		
 | |
| 		#region Internal properties
 | |
| 		
 | |
| 		internal string MachineName {
 | |
| 			get { return machineName; }
 | |
| 		}
 | |
| 		internal bool AllowAutoRedirect {
 | |
| 			get { return allowAutoRedirect; }
 | |
| 		}
 | |
| 		internal int ClientConnectionLimit {
 | |
| 			get { return clientConnectionLimit; }
 | |
| 		}
 | |
| 		internal string ConnectionGroupName {
 | |
| 			get { return connectionGroupName; }
 | |
| 		}
 | |
| 		internal ICredentials Credentials {
 | |
| 			get { return credentials; }
 | |
| 		}
 | |
| 		internal string Domain {
 | |
| 			get { return domain; }
 | |
| 		}
 | |
| 		internal string Password {
 | |
| 			get { return password; }
 | |
| 		}
 | |
| 		internal string Username {
 | |
| 			get { return username; }
 | |
| 		}
 | |
| 		internal string ProxyName {
 | |
| 			get { return proxyName; }
 | |
| 		}
 | |
| 		internal int ProxyPort {
 | |
| 			get { return proxyPort; }
 | |
| 		}
 | |
| 		internal Uri ProxyUri {
 | |
| 			get { return proxyUri; }
 | |
| 		}
 | |
| 		internal string ServicePrincipalName {
 | |
| 			get { return servicePrincipalName; }
 | |
| 		}
 | |
| 		internal int Timeout {
 | |
| 			get { return timeout; }
 | |
| 		}
 | |
| 		internal bool UnsafeAuthenticatedConnectionSharing {
 | |
| 			get { return unsafeAuthenticatedConnectionSharing; }
 | |
| 		}
 | |
| 		internal bool UseAuthenticatedConnectionSharing {
 | |
| 			get { return useAuthenticatedConnectionSharing; }
 | |
| 		}
 | |
| 		internal bool UseDefaultCredentials {
 | |
| 			get { return useDefaultCredentials; }
 | |
| 		}
 | |
| 		
 | |
| 		#endregion
 | |
| 
 | |
| 	}
 | |
| }
 |