Преглед изворни кода

ongoing PeerTransportBindingElement implementation.

svn path=/trunk/mcs/; revision=132146
Atsushi Eno пре 16 година
родитељ
комит
1f9a2160f1
28 измењених фајлова са 1297 додато и 148 уклоњено
  1. 7 0
      mcs/class/System.ServiceModel/ChangeLog
  2. 13 0
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
  3. 47 17
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/DuplexSessionChannelBase.cs
  4. 12 3
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/InputChannelBase.cs
  5. 1 14
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/MsmqOutputChannel.cs
  6. 9 4
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/OutputChannelBase.cs
  7. 93 0
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerChannelFactory.cs
  8. 165 0
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerChannelListener.cs
  9. 105 0
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerCustomResolverBindingElement.cs
  10. 155 0
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerDuplexChannel.cs
  11. 132 0
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerInputChannel.cs
  12. 108 0
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerOutputChannel.cs
  13. 3 1
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerResolverBindingElement.cs
  14. 64 24
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerTransportBindingElement.cs
  15. 34 5
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/PnrpPeerResolverBindingElement.cs
  16. 1 13
      mcs/class/System.ServiceModel/System.ServiceModel.Channels/TcpDuplexSessionChannel.cs
  17. 7 18
      mcs/class/System.ServiceModel/System.ServiceModel.PeerResolvers/PeerCustomResolverSettings.cs
  18. 15 13
      mcs/class/System.ServiceModel/System.ServiceModel.PeerResolvers/PeerResolverSettings.cs
  19. 6 0
      mcs/class/System.ServiceModel/System.ServiceModel.dll.sources
  20. 6 0
      mcs/class/System.ServiceModel/System.ServiceModel/ChangeLog
  21. 0 1
      mcs/class/System.ServiceModel/System.ServiceModel/Dummy.cs
  22. 33 35
      mcs/class/System.ServiceModel/System.ServiceModel/NetPeerTcpBinding.cs
  23. 6 0
      mcs/class/System.ServiceModel/System.ServiceModel/PeerSecuritySettings.cs
  24. 2 0
      mcs/class/System.ServiceModel/System.ServiceModel_test.dll.sources
  25. 4 0
      mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/ChangeLog
  26. 152 0
      mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/PeerTransportBindingElementTest.cs
  27. 4 0
      mcs/class/System.ServiceModel/Test/System.ServiceModel/ChangeLog
  28. 113 0
      mcs/class/System.ServiceModel/Test/System.ServiceModel/NetPeerTcpBindingTest.cs

+ 7 - 0
mcs/class/System.ServiceModel/ChangeLog

@@ -1,3 +1,10 @@
+2009-04-20  Astushi Enomoto  <[email protected]>
+
+	* System.ServiceModel.dll.sources:
+	  added several Peer transport support files.
+	* System.ServiceModel.dll_test.sources: added
+	  NetPeerTcpBindingTest.cs and PeerTransportBindingElementTest.cs.
+
 2009-04-08  Astushi Enomoto  <[email protected]>
 
 	* System.ServiceModel.dll.sources:

+ 13 - 0
mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog

@@ -1,3 +1,16 @@
+2009-04-20  Atsushi Enomoto  <[email protected]>
+
+	* PeerChannelFactory.cs, PeerChannelListener.cs,
+	  PeerCustomResolverBindingElement.cs, PeerDuplexChannel.cs
+	  PeerInputChannel.cs, PeerOutputChannel.cs :
+	  new; ongoing peer transport implementation.
+	* DuplexSessionChannelBase.cs, InputChannelBase.cs
+	  MsmqOutputChannel.cs, OutputChannelBase.cs,
+	  PeerResolverBindingElement.cs, PeerTransportBindingElement.cs,
+	  PnrpPeerResolverBindingElement.cs, TcpDuplexSessionChannel.cs :
+	  several internal changes (either required or for simplification)
+	  for ongoing peer transport implementation.
+
 2009-04-08  Atsushi Enomoto  <[email protected]>
 
 	* PeerTransportBindingElement.cs : ListenIPAddress is IPAddress.

+ 47 - 17
mcs/class/System.ServiceModel/System.ServiceModel.Channels/DuplexSessionChannelBase.cs

@@ -20,9 +20,11 @@ namespace System.ServiceModel.Channels
 		EndpointAddress remote_address;
 		Uri via;
 		
-		public DuplexChannelBase (ChannelFactoryBase factory) : base (factory)
+		public DuplexChannelBase (ChannelFactoryBase factory, EndpointAddress remoteAddress, Uri via) : base (factory)
 		{
 			channel_factory_base = factory;
+			remote_address = remoteAddress;
+			this.via = via;
 		}
 		
 		public DuplexChannelBase (ChannelListenerBase listener) : base (listener)
@@ -32,22 +34,38 @@ namespace System.ServiceModel.Channels
 
 		public abstract EndpointAddress LocalAddress { get; }
 		
-		public abstract EndpointAddress RemoteAddress { get; }
-		
-		public abstract Uri Via { get; }
+		public EndpointAddress RemoteAddress {
+			get { return remote_address; }
+		}
+
+		public Uri Via {
+			get { return via; }
+		}
 		
-		public abstract IAsyncResult BeginSend (Message message, AsyncCallback callback, object state);
+		public virtual IAsyncResult BeginSend (Message message, AsyncCallback callback, object state)
+		{
+			return BeginSend (message, this.DefaultSendTimeout, callback, state);
+		}
 		
 		public abstract IAsyncResult BeginSend (Message message, TimeSpan timeout, AsyncCallback callback, object state);
 		
 		public abstract void EndSend (IAsyncResult result);
 		
-		public abstract void Send (Message message);
-		
-		public abstract void Send (Message message, TimeSpan timeout);
-		
-		public abstract IAsyncResult BeginReceive (AsyncCallback callback, object state);
-		
+		public virtual void Send (Message message)
+		{
+			Send (message, this.DefaultSendTimeout);
+		}
+
+		public virtual void Send (Message message, TimeSpan timeout)
+		{
+			EndSend (BeginSend (message, timeout, null, null));
+		}
+
+		public virtual IAsyncResult BeginReceive (AsyncCallback callback, object state)
+		{
+			return BeginReceive (this.DefaultReceiveTimeout, callback, state);
+		}
+
 		public abstract IAsyncResult BeginReceive (TimeSpan timeout, AsyncCallback callback, object state);
 		
 		public abstract IAsyncResult BeginTryReceive (TimeSpan timeout, AsyncCallback callback, object state);
@@ -60,12 +78,24 @@ namespace System.ServiceModel.Channels
 		
 		public abstract bool EndWaitForMessage (IAsyncResult result);
 		
-		public abstract Message Receive ();
-		
-		public abstract Message Receive (TimeSpan timeout);
-		
-		public abstract bool TryReceive (TimeSpan timeout, out Message message);
+		public virtual Message Receive ()
+		{
+			return Receive (this.DefaultReceiveTimeout);
+		}
+
+		public virtual Message Receive (TimeSpan timeout)
+		{
+			return EndReceive (BeginReceive (timeout, null, null));
+		}
 		
-		public abstract bool WaitForMessage (TimeSpan timeout);
+		public virtual bool TryReceive (TimeSpan timeout, out Message message)
+		{
+			return EndTryReceive (BeginTryReceive (timeout, null, null), out message);
+		}
+
+		public virtual bool WaitForMessage (TimeSpan timeout)
+		{
+			return EndWaitForMessage (BeginWaitForMessage (timeout, null, null));
+		}
 	}
 }

+ 12 - 3
mcs/class/System.ServiceModel/System.ServiceModel.Channels/InputChannelBase.cs

@@ -63,10 +63,19 @@ namespace System.ServiceModel.Channels
 			return Receive (DefaultReceiveTimeout);
 		}
 
-		public abstract Message Receive (TimeSpan timeout);
+		public virtual Message Receive (TimeSpan timeout)
+		{
+			return EndReceive (BeginReceive (timeout, null, null));
+		}
 
-		public abstract bool TryReceive (TimeSpan timeout, out Message message);
+		public virtual bool TryReceive (TimeSpan timeout, out Message message)
+		{
+			return EndTryReceive (BeginTryReceive (timeout, null, null), out message);
+		}
 
-		public abstract bool WaitForMessage (TimeSpan timeout);
+		public virtual bool WaitForMessage (TimeSpan timeout)
+		{
+			return EndWaitForMessage (BeginWaitForMessage (timeout, null, null));
+		}
 	}
 }

+ 1 - 14
mcs/class/System.ServiceModel/System.ServiceModel.Channels/MsmqOutputChannel.cs

@@ -35,26 +35,13 @@ namespace System.ServiceModel.Channels
 	internal class MsmqOutputChannel : OutputChannelBase
 	{
 		MsmqChannelFactory<IOutputChannel> source;
-		EndpointAddress address;
-		Uri via;
 		MessageQueue queue;
 
 		public MsmqOutputChannel (MsmqChannelFactory<IOutputChannel> factory,
 			EndpointAddress address, Uri via)
-			: base (factory)
+			: base (factory, address, via)
 		{
 			this.source = factory;
-			this.address = address;
-			this.via = via;
-		}
-
-		// IOutputChannel
-		public override EndpointAddress RemoteAddress {
-			get { return address; }
-		}
-
-		public override Uri Via {
-			get { return via; }
 		}
 
 		// Send

+ 9 - 4
mcs/class/System.ServiceModel/System.ServiceModel.Channels/OutputChannelBase.cs

@@ -33,10 +33,12 @@ namespace System.ServiceModel.Channels
 	{
 		ChannelFactoryBase channel_factory;
 
-		public OutputChannelBase (ChannelFactoryBase factory)
+		public OutputChannelBase (ChannelFactoryBase factory, EndpointAddress remoteAddress, Uri via)
 			: base (factory)
 		{
 			this.channel_factory = factory;
+			RemoteAddress = remoteAddress;
+			Via = via;
 		}
 
 		protected internal override TimeSpan DefaultCloseTimeout {
@@ -48,9 +50,9 @@ namespace System.ServiceModel.Channels
 		}
 
 		// IOutputChannel
-		public abstract EndpointAddress RemoteAddress { get; }
+		public EndpointAddress RemoteAddress { get; private set; }
 
-		public abstract Uri Via { get; }
+		public Uri Via { get; private set; }
 
 		public IAsyncResult BeginSend (Message message, AsyncCallback callback, object state)
 		{
@@ -66,6 +68,9 @@ namespace System.ServiceModel.Channels
 			Send (message, channel_factory.DefaultSendTimeout);
 		}
 
-		public abstract void Send (Message message, TimeSpan timeout);
+		public virtual void Send (Message message, TimeSpan timeout)
+		{
+			EndSend (BeginSend (message, timeout, null, null));
+		}
 	}
 }

+ 93 - 0
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerChannelFactory.cs

@@ -0,0 +1,93 @@
+//
+// PeerChannelFactory.cs
+//
+// Author:
+//	Atsushi Enomoto <[email protected]>
+//
+// Copyright (C) 2009 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.Collections.Generic;
+using System.Net;
+using System.Net.Security;
+using System.ServiceModel;
+using System.ServiceModel.Description;
+using System.ServiceModel.Security;
+using System.Text;
+
+namespace System.ServiceModel.Channels
+{
+	internal class PeerChannelFactory<TChannel> : ChannelFactoryBase<TChannel>
+	{
+		PeerTransportBindingElement source;
+		MessageEncoder encoder;
+
+		public PeerChannelFactory (PeerTransportBindingElement source, BindingContext ctx)
+		{
+			this.source = source;
+			foreach (BindingElement be in ctx.RemainingBindingElements) {
+				MessageEncodingBindingElement mbe = be as MessageEncodingBindingElement;
+				if (mbe != null) {
+					encoder = mbe.CreateMessageEncoderFactory ().Encoder;
+					break;
+				}
+			}
+			if (encoder == null)
+				encoder = new TextMessageEncoder (MessageVersion.Default, Encoding.UTF8);
+		}
+
+		public MessageEncoder MessageEncoder {
+			get { return encoder; }
+		}
+
+		protected override TChannel OnCreateChannel (
+			EndpointAddress address, Uri via)
+		{
+			ThrowIfDisposedOrNotOpen ();
+
+			if (source.Scheme != address.Uri.Scheme)
+				throw new ArgumentException (String.Format ("Argument EndpointAddress has unsupported URI scheme: {0}", address.Uri.Scheme));
+
+			Type t = typeof (TChannel);
+			if (t == typeof (IOutputChannel))
+				return (TChannel) (object) new PeerOutputChannel ((PeerChannelFactory<IOutputChannel>) (object) this, address, via);
+			if (t == typeof (IDuplexChannel))
+				return (TChannel) (object) new PeerDuplexChannel ((PeerChannelFactory<IDuplexChannel>) (object) this, address, via);
+			throw new InvalidOperationException (String.Format ("channel type {0} is not supported.", typeof (TChannel).Name));
+		}
+
+		protected override IAsyncResult OnBeginOpen (TimeSpan timeout,
+			AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override void OnEndOpen (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override void OnOpen (TimeSpan timeout)
+		{
+		}
+	}
+}

+ 165 - 0
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerChannelListener.cs

@@ -0,0 +1,165 @@
+//
+// PeerChannelListener.cs
+//
+// Author:
+//	Atsushi Enomoto <[email protected]>
+//
+// Copyright (C) 2009 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.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Net;
+using System.Net.Security;
+using System.ServiceModel;
+using System.ServiceModel.Description;
+using System.ServiceModel.Security;
+using System.Text;
+
+namespace System.ServiceModel.Channels
+{
+	internal class PeerChannelListener<TChannel> : ChannelListenerBase<TChannel>
+		where TChannel : class, IChannel
+	{
+		PeerTransportBindingElement source;
+		BindingContext context;
+		Uri listen_uri;
+		List<IChannel> channels = new List<IChannel> ();
+		MessageEncoder encoder;
+
+		public PeerChannelListener (PeerTransportBindingElement source,
+			BindingContext context)
+			: base (context.Binding)
+		{
+			// FIXME: consider ListenUriMode
+			// FIXME: there should be some way to post-provide Uri in case of null listenerUri in context.
+			listen_uri = context.ListenUriBaseAddress != null ?
+				new Uri (context.ListenUriBaseAddress, context.ListenUriRelativeAddress) : null;
+			foreach (BindingElement be in context.RemainingBindingElements) {
+				MessageEncodingBindingElement mbe = be as MessageEncodingBindingElement;
+				if (mbe != null) {
+					encoder = mbe.CreateMessageEncoderFactory ().Encoder;
+					break;
+				}
+			}
+			if (encoder == null)
+				encoder = new TextMessageEncoder (MessageVersion.Default, Encoding.UTF8);
+		}
+
+		public MessageEncoder MessageEncoder {
+			get { return encoder; }
+		}
+
+		public override Uri Uri {
+			get { return listen_uri; }
+		}
+
+		protected override TChannel OnAcceptChannel (TimeSpan timeout)
+		{
+			TChannel ch = PopulateChannel (timeout);
+			channels.Add (ch);
+			return ch;
+		}
+
+		TChannel PopulateChannel (TimeSpan timeout)
+		{
+			if (typeof (TChannel) == typeof (IInputChannel))
+				return (TChannel) (object) new PeerInputChannel ((PeerChannelListener<IInputChannel>) (object) this, timeout);
+			// FIXME: handle timeout somehow.
+			if (typeof (TChannel) == typeof (IDuplexChannel))
+				return (TChannel) (object) new PeerDuplexChannel ((PeerChannelListener<IDuplexChannel>) (object) this);
+
+			throw new InvalidOperationException (String.Format ("Not supported channel '{0}' (mono bug; it is incorrectly allowed at construction time)", typeof (TChannel)));
+		}
+
+		protected override IAsyncResult OnBeginAcceptChannel (
+			TimeSpan timeout, AsyncCallback callback,
+			object asyncState)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override TChannel OnEndAcceptChannel (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override IAsyncResult OnBeginWaitForChannel (
+			TimeSpan timeout, AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override bool OnEndWaitForChannel (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override bool OnWaitForChannel (TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override void OnOpen (TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override IAsyncResult OnBeginOpen (TimeSpan timeout,
+			AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override void OnEndOpen (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override void OnClose (TimeSpan timeout)
+		{
+			if (ServiceHostingEnvironment.InAspNet)
+				return;
+
+			foreach (TChannel ch in channels)
+				ch.Close(timeout);
+		}
+
+		[MonoTODO]
+		protected override IAsyncResult OnBeginClose (TimeSpan timeout,
+			AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		protected override void OnEndClose (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO ("find out what to do here.")]
+		protected override void OnAbort ()
+		{
+		}
+	}
+}

+ 105 - 0
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerCustomResolverBindingElement.cs

@@ -0,0 +1,105 @@
+//
+// PeerCustomResolverBindingElement.cs
+//
+// Author:
+//	Atsushi Enomoto <[email protected]>
+//
+// Copyright (C) 2009 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.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Net.Security;
+using System.ServiceModel;
+using System.ServiceModel.Description;
+using System.ServiceModel.PeerResolvers;
+using System.Text;
+using System.Xml;
+
+namespace System.ServiceModel.Channels
+{
+	public class PeerCustomResolverBindingElement : PeerResolverBindingElement
+	{
+		public PeerCustomResolverBindingElement ()
+		{
+		}
+
+		private PeerCustomResolverBindingElement (
+			PeerCustomResolverBindingElement other)
+			: base (other)
+		{
+			ReferralPolicy = other.ReferralPolicy;
+		}
+
+		public PeerCustomResolverBindingElement (BindingContext context, PeerCustomResolverSettings settings)
+			: this (settings)
+		{
+			this.context = context;
+		}
+
+		public PeerCustomResolverBindingElement (PeerCustomResolverSettings settings)
+		{
+			this.settings = settings;
+		}
+
+		BindingContext context;
+		PeerCustomResolverSettings settings;
+
+		public override PeerReferralPolicy ReferralPolicy { get; set; }
+
+		[MonoTODO]
+		public override IChannelFactory<TChannel> BuildChannelFactory<TChannel> (
+			BindingContext context)
+		{
+			return context.BuildInnerChannelFactory<TChannel> ();
+		}
+
+		[MonoTODO]
+		public override IChannelListener<TChannel>
+			BuildChannelListener<TChannel> (
+			BindingContext context)
+		{
+			return context.BuildInnerChannelListener<TChannel> ();
+		}
+
+		public override BindingElement Clone ()
+		{
+			return new PeerCustomResolverBindingElement (this);
+		}
+
+		[MonoTODO]
+		public override PeerResolver CreatePeerResolver ()
+		{
+			if (settings != null)
+				return settings.Resolver;
+
+			// FIXME: create from configuration
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		public override T GetProperty<T> (BindingContext context)
+		{
+			throw new NotImplementedException ();
+		}
+	}
+}

+ 155 - 0
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerDuplexChannel.cs

@@ -0,0 +1,155 @@
+//
+// PeerDuplexChannel.cs
+//
+// Author:
+//	Atsushi Enomoto <[email protected]>
+//
+// Copyright (C) 2009 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.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Net.Security;
+using System.ServiceModel;
+using System.ServiceModel.Description;
+using System.ServiceModel.Security;
+using System.Threading;
+
+namespace System.ServiceModel.Channels
+{
+	internal class PeerDuplexChannel : DuplexChannelBase
+	{
+		PeerChannelFactory<IDuplexChannel> factory;
+		PeerChannelListener<IDuplexChannel> listener;
+		EndpointAddress remote_address;
+		EndpointAddress local_address;
+		Uri via;
+
+		public PeerDuplexChannel (PeerChannelFactory<IDuplexChannel> factory, EndpointAddress address, Uri via)
+			: base (factory, address, via)
+		{
+			this.factory = factory;
+			this.remote_address = address;
+			this.via = via;
+		}
+
+		// FIXME: receive local_address too
+		public PeerDuplexChannel (PeerChannelListener<IDuplexChannel> listener)
+			: base (listener)
+		{
+			this.listener = listener;
+		}
+
+		public override EndpointAddress LocalAddress {
+			get { return local_address; }
+		}
+
+		// DuplexChannelBase
+
+		public override IAsyncResult BeginSend (Message message, TimeSpan timeout, AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override void EndSend (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override IAsyncResult BeginReceive (TimeSpan timeout, AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override IAsyncResult BeginTryReceive (TimeSpan timeout, AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override IAsyncResult BeginWaitForMessage (TimeSpan timeout, AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override Message EndReceive (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override bool EndTryReceive (IAsyncResult result, out Message message)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override bool EndWaitForMessage (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+		
+		// CommunicationObject
+		
+		[MonoTODO]
+		protected override void OnAbort ()
+		{
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		protected override IAsyncResult OnBeginClose (TimeSpan timeout,
+			AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		protected override IAsyncResult OnBeginOpen (TimeSpan timeout,
+			AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		protected override void OnClose (TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+		
+		[MonoTODO]
+		protected override void OnEndClose (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		protected override void OnEndOpen (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+		
+		[MonoTODO]
+		protected override void OnOpen (TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+	}
+}

+ 132 - 0
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerInputChannel.cs

@@ -0,0 +1,132 @@
+//
+// PeerInputChannel.cs
+//
+// Author: Atsushi Enomoto ([email protected])
+//
+// Copyright (C) 2009 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.Messaging;
+using System.ServiceModel;
+
+namespace System.ServiceModel.Channels
+{
+	internal class PeerInputChannel : InputChannelBase
+	{
+		PeerChannelListener<IInputChannel> listener;
+		EndpointAddress local_address;
+
+		// FIXME: handle timeout
+		public PeerInputChannel (PeerChannelListener<IInputChannel> listener, TimeSpan timeout)
+			: base (listener)
+		{
+			this.listener = listener;
+		}
+
+		// FIXME: how is it set?
+		public override EndpointAddress LocalAddress {
+			get { return local_address; }
+		}
+
+		public override IAsyncResult BeginReceive (TimeSpan timeout, AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override IAsyncResult BeginTryReceive (TimeSpan timeout, AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override IAsyncResult BeginWaitForMessage (TimeSpan timeout, AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override Message EndReceive (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override bool EndTryReceive (IAsyncResult result, out Message message)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override bool EndWaitForMessage (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override Message Receive (TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override bool TryReceive (TimeSpan timeout, out Message message)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override bool WaitForMessage (TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		// ChannelBase
+
+		protected override void OnAbort ()
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override void OnClose (TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override void OnOpen (TimeSpan timeout)
+		{
+			// nothing to do
+		}
+
+		protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object sender)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override void OnEndOpen (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object sender)
+		{
+			throw new NotImplementedException ();
+		}
+
+		protected override void OnEndClose (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+	}
+}

+ 108 - 0
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerOutputChannel.cs

@@ -0,0 +1,108 @@
+//
+// PeerOutputChannel.cs
+//
+// Author:
+//	Atsushi Enomoto <[email protected]>
+//
+// Copyright (C) 2006 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.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Net.Security;
+using System.ServiceModel;
+using System.ServiceModel.Description;
+using System.ServiceModel.Security;
+using System.Threading;
+
+namespace System.ServiceModel.Channels
+{
+	internal class PeerOutputChannel : OutputChannelBase
+	{
+		PeerChannelFactory<IOutputChannel> factory;
+
+		public PeerOutputChannel (PeerChannelFactory<IOutputChannel> factory, EndpointAddress address, Uri via)
+			: base (factory, address, via)
+		{
+			this.factory = factory;
+		}
+
+		// OutputChannelBase
+
+		public override IAsyncResult BeginSend (Message message, TimeSpan timeout, AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override void EndSend (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		// CommunicationObject
+		
+		[MonoTODO]
+		protected override void OnAbort ()
+		{
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		protected override IAsyncResult OnBeginClose (TimeSpan timeout,
+			AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		protected override IAsyncResult OnBeginOpen (TimeSpan timeout,
+			AsyncCallback callback, object state)
+		{
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		protected override void OnClose (TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+		
+		[MonoTODO]
+		protected override void OnEndClose (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+
+		[MonoTODO]
+		protected override void OnEndOpen (IAsyncResult result)
+		{
+			throw new NotImplementedException ();
+		}
+		
+		[MonoTODO]
+		protected override void OnOpen (TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+	}
+}

+ 3 - 1
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerResolverBindingElement.cs

@@ -28,8 +28,8 @@
 using System;
 using System.Collections.Generic;
 using System.Net.Security;
-using System.ServiceModel.Channels;
 using System.ServiceModel.Description;
+using System.ServiceModel.PeerResolvers;
 using System.Text;
 using System.Xml;
 
@@ -47,6 +47,8 @@ namespace System.ServiceModel.Channels
 		{
 		}
 
+		public abstract PeerReferralPolicy ReferralPolicy { get; set; }
+
 		public abstract PeerResolver CreatePeerResolver ();
 	}
 }

+ 64 - 24
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerTransportBindingElement.cs

@@ -36,21 +36,23 @@ namespace System.ServiceModel.Channels
 {
 	[MonoTODO]
 	public sealed class PeerTransportBindingElement
-		: TransportBindingElement, ISecurityCapabilities
+		: TransportBindingElement, IPolicyExportExtension, IWsdlExportExtension
 	{
-		long max_recv_message_size;
-		bool auth_msg;
+		long max_recv_message_size = 0x10000;
 		int port;
+		PeerSecuritySettings security = new PeerSecuritySettings ();
 
 		public PeerTransportBindingElement ()
 		{
-			throw new NotImplementedException ();
 		}
 
 		private PeerTransportBindingElement (
 			PeerTransportBindingElement other)
 			: base (other)
 		{
+			max_recv_message_size = other.max_recv_message_size;
+			port = other.port;
+			other.security.CopyTo (security);
 		}
 
 		public IPAddress ListenIPAddress { get; set; }
@@ -60,11 +62,6 @@ namespace System.ServiceModel.Channels
 			set { max_recv_message_size = value; }
 		}
 
-		public bool MessageAuthentication {
-			get { return auth_msg; }
-			set { auth_msg = value; }
-		}
-
 		public int Port {
 			get { return port; }
 			set { port = value; }
@@ -74,10 +71,45 @@ namespace System.ServiceModel.Channels
 			get { return "net.p2p"; }
 		}
 
+		public override bool CanBuildChannelFactory<TChannel> (
+			BindingContext context)
+		{
+			return  typeof (TChannel) == typeof (IOutputChannel) ||
+				typeof (TChannel) == typeof (IDuplexChannel);
+		}
+
+		public override bool CanBuildChannelListener<TChannel> (
+			BindingContext context)
+		{
+			return  typeof (TChannel) == typeof (IInputChannel) ||
+				typeof (TChannel) == typeof (IDuplexChannel);
+		}
+
 		public override IChannelFactory<TChannel> BuildChannelFactory<TChannel> (
 			BindingContext context)
 		{
-			throw new NotImplementedException ();
+			if (!CanBuildChannelFactory<TChannel> (context))
+				throw new ArgumentException (String.Format ("Not supported channel type '{0}'", typeof (TChannel)));
+			if (typeof (TChannel) == typeof (IOutputChannel))
+				return (IChannelFactory<TChannel>) (object) new PeerChannelFactory<IOutputChannel> (this, context);
+			else if (typeof (TChannel) == typeof (IDuplexChannel))
+				return (IChannelFactory<TChannel>) (object) new PeerChannelFactory<IDuplexChannel> (this, context);
+			throw new InvalidOperationException (String.Format ("Not supported channel '{0}' (is incorrectly allowed at construction time)", typeof (TChannel)));
+		}
+
+		public override IChannelListener<TChannel> BuildChannelListener<TChannel> (
+			BindingContext context)
+		{
+			if (!CanBuildChannelListener<TChannel> (context))
+				throw new ArgumentException (String.Format ("Not supported channel type '{0}'", typeof (TChannel)));
+
+			// FIXME: check LocalIPAddress.
+
+			if (typeof (TChannel) == typeof (IInputChannel))
+				return (IChannelListener<TChannel>) (object) new PeerChannelListener<IInputChannel> (this, context);
+			else if (typeof (TChannel) == typeof (IDuplexChannel))
+				return (IChannelListener<TChannel>) (object) new PeerChannelListener<IDuplexChannel> (this, context);
+			throw new InvalidOperationException (String.Format ("Not supported channel '{0}' (is incorrectly allowed at construction time)", typeof (TChannel)));
 		}
 
 		public override BindingElement Clone ()
@@ -85,30 +117,38 @@ namespace System.ServiceModel.Channels
 			return new PeerTransportBindingElement (this);
 		}
 
-		[MonoTODO]
 		public override T GetProperty<T> (BindingContext context)
 		{
-			throw new NotImplementedException ();
+			if (typeof (T) == typeof (IBindingMulticastCapabilities))
+				return (T) (object) this;
+			if (typeof (T) == typeof (ISecurityCapabilities))
+				return (T) (object) this;
+			if (typeof (T) == typeof (IBindingDeliveryCapabilities))
+				return (T) (object) this;
+
+			return default (T);
 		}
 
-		ProtectionLevel ISecurityCapabilities.SupportedRequestProtectionLevel {
-			get { throw new NotImplementedException (); }
+		public PeerSecuritySettings Security {
+			get { return security; }
 		}
 
-		ProtectionLevel ISecurityCapabilities.SupportedResponseProtectionLevel {
-			get { throw new NotImplementedException (); }
-		}
-
-		bool ISecurityCapabilities.SupportsClientAuthentication {
-			get { throw new NotImplementedException (); }
+		[MonoTODO]
+		void IPolicyExportExtension.ExportPolicy (MetadataExporter exporter, PolicyConversionContext contxt)
+		{
+			throw new NotImplementedException ();
 		}
 
-		bool ISecurityCapabilities.SupportsClientWindowsIdentity {
-			get { throw new NotImplementedException (); }
+		[MonoTODO]
+		void IWsdlExportExtension.ExportEndpoint (WsdlExporter exporter, WsdlEndpointConversionContext context)
+		{
+			throw new NotImplementedException ();
 		}
 
-		bool ISecurityCapabilities.SupportsServerAuthentication {
-			get { throw new NotImplementedException (); }
+		[MonoTODO]
+		void IWsdlExportExtension.ExportContract (WsdlExporter exporter, WsdlContractConversionContext context)
+		{
+			throw new NotImplementedException ();
 		}
 	}
 }

+ 34 - 5
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PnrpPeerResolverBindingElement.cs

@@ -27,16 +27,16 @@
 //
 using System;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.Net.Security;
-using System.ServiceModel.Channels;
 using System.ServiceModel.Description;
-using System.ServiceModel.Security;
+using System.ServiceModel.PeerResolvers;
 using System.Text;
 using System.Xml;
 
 namespace System.ServiceModel.Channels
 {
-	[MonoTODO]
+	[MonoTODO ("We aren't actually going to implement this windows-only protocol")]
 	public class PnrpPeerResolverBindingElement : PeerResolverBindingElement
 	{
 		public PnrpPeerResolverBindingElement ()
@@ -47,8 +47,11 @@ namespace System.ServiceModel.Channels
 			PnrpPeerResolverBindingElement other)
 			: base (other)
 		{
+			ReferralPolicy = other.ReferralPolicy;
 		}
 
+		public override PeerReferralPolicy ReferralPolicy { get; set; }
+
 		[MonoTODO]
 		public override IChannelFactory<TChannel> BuildChannelFactory<TChannel> (
 			BindingContext context)
@@ -64,7 +67,6 @@ namespace System.ServiceModel.Channels
 			throw new NotImplementedException ();
 		}
 
-		[MonoTODO]
 		public override BindingElement Clone ()
 		{
 			return new PnrpPeerResolverBindingElement (this);
@@ -73,7 +75,7 @@ namespace System.ServiceModel.Channels
 		[MonoTODO]
 		public override PeerResolver CreatePeerResolver ()
 		{
-			throw new NotImplementedException ();
+			return new PnrpPeerResolver (this);
 		}
 
 		[MonoTODO]
@@ -82,4 +84,31 @@ namespace System.ServiceModel.Channels
 			throw new NotImplementedException ();
 		}
 	}
+
+	class PnrpPeerResolver : PeerResolver
+	{
+		public PnrpPeerResolver (PnrpPeerResolverBindingElement binding)
+		{
+		}
+
+		public override object Register (string meshId, PeerNodeAddress nodeAddress, TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override ReadOnlyCollection<PeerNodeAddress> Resolve (string meshId, int maxAddresses, TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override void Unregister (object registrationId, TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override void Update (object registrationId, PeerNodeAddress updatedNodeAddress, TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+	}
 }

+ 1 - 13
mcs/class/System.ServiceModel/System.ServiceModel.Channels/TcpDuplexSessionChannel.cs

@@ -25,18 +25,14 @@ namespace System.ServiceModel.Channels
 		TcpClient client;
 		bool is_service_side;
 		EndpointAddress local_address;
-		EndpointAddress remote_address;
 		TcpListener tcp_listener;
 		TimeSpan timeout;
-		Uri via;
 		
 		public TcpDuplexSessionChannel (ChannelFactoryBase factory, TcpChannelInfo info, EndpointAddress address, Uri via)
-			: base (factory)
+			: base (factory, address, via)
 		{
 			is_service_side = false;
 			this.info = info;
-			remote_address = address;
-			this.via = via;
 		}
 		
 		public TcpDuplexSessionChannel (ChannelListenerBase listener, TcpChannelInfo info, TcpClient acceptedRequest, TimeSpan timeout)
@@ -74,19 +70,11 @@ namespace System.ServiceModel.Channels
 			get { return local_address; }
 		}
 		
-		public override EndpointAddress RemoteAddress {
-			get { return remote_address; }
-		}
-		
 		// FIXME: implement
 		public IDuplexSession Session {
 			get { throw new NotImplementedException (); }
 		}
 		
-		public override Uri Via {
-			get { return via; }
-		}
-		
 		[MonoTODO]
 		public override IAsyncResult BeginSend (Message message, AsyncCallback callback, object state)
 		{

+ 7 - 18
mcs/class/System.ServiceModel/System.ServiceModel.PeerResolvers/PeerCustomResolverSettings.cs

@@ -14,34 +14,23 @@ namespace System.ServiceModel.PeerResolvers
 {
 	public class PeerCustomResolverSettings
 	{
-		EndpointAddress address;
-		Binding binding;
-		PeerResolver resolver;
-		
 		public PeerCustomResolverSettings()
 		{
 		}
 		
-		[MonoTODO]
-		public EndpointAddress Address {
-			get { return address; }
-			set { address = value; }
-		}
+		public EndpointAddress Address { get; set; }
 		
-		[MonoTODO]
-		public Binding Binding {
-			get { return binding; }
-			set { binding = value; }
-		}
+		public Binding Binding { get; set; }
 		
 		public bool IsBindingSpecified {
 			get { return Binding != null; }
 		}
 		
-		[MonoTODO]
-		public PeerResolver Resolver {
-			get { return resolver; }
-			set { resolver = value; }
+		public PeerResolver Resolver { get; set; }
+
+		internal PeerCustomResolverBindingElement CreateBinding ()
+		{
+			return new PeerCustomResolverBindingElement (this);
 		}
 	}
 }

+ 15 - 13
mcs/class/System.ServiceModel/System.ServiceModel.PeerResolvers/PeerResolverSettings.cs

@@ -8,7 +8,7 @@
 // 
 
 using System;
-using System.ServiceModel.PeerResolvers;
+using System.ServiceModel.Channels;
 
 namespace System.ServiceModel.PeerResolvers
 {
@@ -17,27 +17,29 @@ namespace System.ServiceModel.PeerResolvers
 		PeerCustomResolverSettings custom = new PeerCustomResolverSettings ();
 		// FIXME: Is it really by default Auto?
 		PeerResolverMode mode = PeerResolverMode.Auto;
-		PeerReferralPolicy referral_policy;
 		
 		public PeerResolverSettings ()
 		{
 		}
-		
-		[MonoTODO]
+
 		public PeerCustomResolverSettings Custom {
 			get { return custom; }
 		}
 		
-		[MonoTODO]
-		public PeerResolverMode Mode {
-			get { return mode; }
-			set { mode = value; }
-		}
+		public PeerResolverMode Mode { get; set; }
 		
-		[MonoTODO]
-		public PeerReferralPolicy ReferralPolicy {
-			get { return referral_policy; }
-			set { referral_policy = value; }
+		public PeerReferralPolicy ReferralPolicy { get; set; }
+
+		internal BindingElement CreateBinding ()
+		{
+			switch (Mode) {
+			case PeerResolverMode.Pnrp:
+				return new PnrpPeerResolverBindingElement () { ReferralPolicy = this.ReferralPolicy };
+			default:
+				var be = Custom.CreateBinding ();
+				be.ReferralPolicy = this.ReferralPolicy;
+				return be;
+			}
 		}
 	}
 }

+ 6 - 0
mcs/class/System.ServiceModel/System.ServiceModel.dll.sources

@@ -243,6 +243,12 @@ System.ServiceModel.Channels/OneWayBindingElement.cs
 System.ServiceModel.Channels/OneWayBindingElementImporter.cs
 System.ServiceModel.Channels/OutputChannelBase.cs
 System.ServiceModel.Channels/PeerResolverBindingElement.cs
+System.ServiceModel.Channels/PeerChannelFactory.cs
+System.ServiceModel.Channels/PeerChannelListener.cs
+System.ServiceModel.Channels/PeerCustomResolverBindingElement.cs
+System.ServiceModel.Channels/PeerDuplexChannel.cs
+System.ServiceModel.Channels/PeerInputChannel.cs
+System.ServiceModel.Channels/PeerOutputChannel.cs
 System.ServiceModel.Channels/PeerTransportBindingElement.cs
 System.ServiceModel.Channels/PnrpPeerResolverBindingElement.cs
 System.ServiceModel.Channels/ReliableSessionBindingElementImporter.cs

+ 6 - 0
mcs/class/System.ServiceModel/System.ServiceModel/ChangeLog

@@ -1,3 +1,9 @@
+2009-04-20  Atsushi Enomoto  <[email protected]>
+
+	* Dummy.cs : remove some peer transport stuff.
+	* NetPeerTcpBinding.cs : implemented some members.
+	* PeerSecuritySettings.cs : added copy utility method.
+
 2009-04-17  Geoff Norton  <[email protected]>
 
 	* ChannelFactory.cs: Ensure we create and open a factory here,

+ 0 - 1
mcs/class/System.ServiceModel/System.ServiceModel/Dummy.cs

@@ -21,7 +21,6 @@ namespace System.ServiceModel.Activation.Configuration
 
 namespace System.ServiceModel.Channels
 {
-	public class PeerCustomResolverBindingElement { }
 	public class PrivacyNoticeBindingElement { }
 	public class PrivacyNoticeBindingElementImporter { }
 	public class ReliableSessionBindingElement { }

+ 33 - 35
mcs/class/System.ServiceModel/System.ServiceModel/NetPeerTcpBinding.cs

@@ -43,14 +43,15 @@ namespace System.ServiceModel
 		IBindingDeliveryCapabilities, IBindingMulticastCapabilities,
 		ISecurityCapabilities, IBindingRuntimePreferences
 	{
-		long max_buffer_pool_size = 0x80000;
-		long max_recv_message_size = 0x10000;
-		bool msg_auth;
-		int port;
-		XmlDictionaryReaderQuotas reader_quotas;
-//		PeerResolver resolver = new PeerResolverImpl ();
+		// We don't support PNRP
+		public static bool IsPnrpAvailable {
+			get { return false; }
+		}
+
+		XmlDictionaryReaderQuotas reader_quotas = new XmlDictionaryReaderQuotas ();
 		PeerResolverSettings resolver = new PeerResolverSettings ();
 		PeerSecuritySettings security = new PeerSecuritySettings ();
+		PeerTransportBindingElement transport = new PeerTransportBindingElement ();
 
 		public NetPeerTcpBinding ()
 		{
@@ -62,38 +63,40 @@ namespace System.ServiceModel
 			throw new NotImplementedException ();
 		}
 
-		public IPAddress ListenIPAddress { get; set; }
-
-		public long MaxBufferPoolSize {
-			get { return max_buffer_pool_size; }
-			set { max_buffer_pool_size = value; }
+		[MonoTODO]
+		public IPAddress ListenIPAddress {
+			get { return transport.ListenIPAddress; }
+			set { transport.ListenIPAddress = value; }
 		}
 
-		public bool MessageAuthentication {
-			get { return msg_auth; }
-			set { msg_auth = value; }
+		[MonoTODO]
+		public new long MaxBufferPoolSize {
+			get { return transport.MaxBufferPoolSize; }
+			set { transport.MaxBufferPoolSize = value; }
 		}
 
+		[MonoTODO]
 		public long MaxReceivedMessageSize {
-			get { return max_recv_message_size; }
-			set { max_recv_message_size = value; }
+			get { return transport.MaxReceivedMessageSize; }
+			set { transport.MaxReceivedMessageSize = value; }
 		}
 
-		[MonoTODO]
 		public int Port {
-			get { return port; }
-			set { port = value; }
+			get { return transport.Port; }
+			set { transport.Port = value; }
 		}
 
-		[MonoTODO]
 		public PeerResolverSettings Resolver {
 			get { return resolver; }
-			set { resolver = value; }
 		}
 
 		public XmlDictionaryReaderQuotas ReaderQuotas {
 			get { return reader_quotas; }
-			set { reader_quotas = value; }
+			set {
+				if (value == null)
+					throw new ArgumentNullException ("value");
+				reader_quotas = value;
+			}
 		}
 
 		public override string Scheme {
@@ -104,25 +107,20 @@ namespace System.ServiceModel
 			get { return security; }
 		}
 
-		public EnvelopeVersion SoapVersion {
+		public EnvelopeVersion EnvelopeVersion {
 			get { return EnvelopeVersion.Soap12; }
 		}
 
 		public override BindingElementCollection
 			CreateBindingElements ()
 		{
-			BinaryMessageEncodingBindingElement mbe = 
-				new BinaryMessageEncodingBindingElement ();
-			ReaderQuotas.CopyTo (mbe.ReaderQuotas);
-
-			PeerTransportBindingElement tbe =
-				new PeerTransportBindingElement ();
-			tbe.ListenIPAddress = ListenIPAddress;
-			tbe.MaxBufferPoolSize = MaxBufferPoolSize;
-			tbe.MaxReceivedMessageSize = MaxReceivedMessageSize;
-			tbe.MessageAuthentication = MessageAuthentication;
-
-			return new BindingElementCollection (new BindingElement [] { mbe, tbe });
+			var mbe = new BinaryMessageEncodingBindingElement ();
+			if (ReaderQuotas != null)
+				ReaderQuotas.CopyTo (mbe.ReaderQuotas);
+
+			var prbe = Resolver.CreateBinding ();
+
+			return new BindingElementCollection (new BindingElement [] { mbe, prbe, transport.Clone () });
 		}
 
 		// explicit interface implementations

+ 6 - 0
mcs/class/System.ServiceModel/System.ServiceModel/PeerSecuritySettings.cs

@@ -26,5 +26,11 @@ namespace System.ServiceModel
 		}
 
 		public PeerTransportSecuritySettings Transport { get; private set; }
+
+		internal void CopyTo (PeerSecuritySettings other)
+		{
+			other.mode = mode;
+			other.Transport.CredentialType = Transport.CredentialType;
+		}
 	}
 }

+ 2 - 0
mcs/class/System.ServiceModel/System.ServiceModel_test.dll.sources

@@ -29,6 +29,7 @@ System.ServiceModel.Channels/MsmqTransportBindingElementTest.cs
 System.ServiceModel.Channels/NamedPipeTransportBindingElementTest.cs
 System.ServiceModel.Channels/OneWayBindingElementTest.cs
 System.ServiceModel.Channels/OutputChannelBase.cs
+System.ServiceModel.Channels/PeerTransportBindingElementTest.cs
 System.ServiceModel.Channels/ReplyChannelBase.cs
 System.ServiceModel.Channels/RequestChannelBase.cs
 System.ServiceModel.Channels/SecurityAssert.cs
@@ -123,6 +124,7 @@ System.ServiceModel/IntegratedConnectionTest.cs
 System.ServiceModel/MessageSecurityVersionTest.cs
 System.ServiceModel/NetMsmqBindingTest.cs
 System.ServiceModel/NetTcpBindingTest.cs
+System.ServiceModel/NetPeerTcpBindingTest.cs
 System.ServiceModel/ServiceAssert.cs
 System.ServiceModel/ServiceEndpointCollectionTest.cs
 System.ServiceModel/ServiceEndpointTest.cs

+ 4 - 0
mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/ChangeLog

@@ -1,3 +1,7 @@
+2009-04-20  Atsushi Enomoto  <[email protected]>
+
+	* PeerTransportBindingElementTest.cs : new.
+
 2009-04-07  Atsushi Enomoto  <[email protected]>
 
 	* TcpTransportBindingElementTest.cs : more can-build tests.

+ 152 - 0
mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/PeerTransportBindingElementTest.cs

@@ -0,0 +1,152 @@
+//
+// PeerTransportBindingElementTest.cs
+//
+// Author:
+//	Atsushi Enomoto <[email protected]>
+//
+// Copyright (C) 2009 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.Collections.ObjectModel;
+using System.Net;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.ServiceModel.Description;
+using System.Text;
+using NUnit.Framework;
+
+namespace MonoTests.System.ServiceModel.Channels
+{
+	[TestFixture]
+	public class PeerTransportBindingElementTest
+	{
+		[Test]
+		public void CanBuildChannelFactoryListener ()
+		{
+			var be = new PeerTransportBindingElement ();
+			var binding = new CustomBinding (new HandlerTransportBindingElement (null));
+			var ctx = new BindingContext (binding, new BindingParameterCollection ());
+			Assert.IsFalse (be.CanBuildChannelFactory<IRequestChannel> (ctx), "#1");
+			Assert.IsTrue (be.CanBuildChannelFactory<IOutputChannel> (ctx), "#2");
+			Assert.IsTrue  (be.CanBuildChannelFactory<IDuplexChannel> (ctx), "#3");
+			Assert.IsFalse (be.CanBuildChannelFactory<IRequestSessionChannel> (ctx), "#4");
+			Assert.IsFalse (be.CanBuildChannelFactory<IOutputSessionChannel> (ctx), "#5"); // oh?
+			Assert.IsFalse (be.CanBuildChannelFactory<IDuplexSessionChannel> (ctx), "#6"); // really?
+
+			Assert.IsFalse (be.CanBuildChannelListener<IReplyChannel> (ctx), "#7");
+			Assert.IsTrue (be.CanBuildChannelListener<IInputChannel> (ctx), "#8");
+			Assert.IsTrue (be.CanBuildChannelListener<IDuplexChannel> (ctx), "#9");
+			Assert.IsFalse (be.CanBuildChannelListener<IReplySessionChannel> (ctx), "#10");
+			Assert.IsFalse (be.CanBuildChannelListener<IInputSessionChannel> (ctx), "#11"); // hrm...
+			Assert.IsFalse (be.CanBuildChannelListener<IDuplexSessionChannel> (ctx), "#12"); // ...k.
+		}
+
+		[Test]
+		[ExpectedException (typeof (ArgumentException))]
+		public void BuildRequestChannelFactory ()
+		{
+			// IRequestChannel is invalid
+			PeerTransportBindingElement be =
+				new PeerTransportBindingElement ();
+			be.Security.Mode = SecurityMode.None;
+			CustomBinding binding = new CustomBinding (
+				new HandlerTransportBindingElement (null));
+			BindingContext ctx = new BindingContext (
+				binding, new BindingParameterCollection ());
+			be.BuildChannelFactory<IRequestChannel> (ctx);
+		}
+
+		[Test]
+		public void BuildOutputChannelFactory ()
+		{
+			PeerTransportBindingElement be =
+				new PeerTransportBindingElement ();
+			be.Security.Mode = SecurityMode.None;
+			CustomBinding binding = new CustomBinding (
+				new HandlerTransportBindingElement (null));
+			BindingContext ctx = new BindingContext (
+				binding, new BindingParameterCollection ());
+			be.BuildChannelFactory<IOutputChannel> (ctx);
+		}
+		[Test]
+		[ExpectedException (typeof (ArgumentException))]
+		public void BuildReplyChannelListener ()
+		{
+			// IReplyChannel is invalid
+			PeerTransportBindingElement be =
+				new PeerTransportBindingElement ();
+			be.Security.Mode = SecurityMode.None;
+			CustomBinding binding = new CustomBinding (
+				new HandlerTransportBindingElement (null));
+			BindingContext ctx = new BindingContext (
+				binding, new BindingParameterCollection ());
+			be.BuildChannelListener<IReplyChannel> (ctx);
+		}
+
+		[Test]
+		public void BuildInputChannelListener ()
+		{
+			PeerTransportBindingElement be =
+				new PeerTransportBindingElement ();
+			be.Security.Mode = SecurityMode.None;
+			CustomBinding binding = new CustomBinding (
+				new HandlerTransportBindingElement (null));
+			BindingContext ctx = new BindingContext (
+				binding, new BindingParameterCollection ());
+			ctx.ListenUriBaseAddress = new Uri ("net.p2p:foobar");
+			be.BuildChannelListener<IInputChannel> (ctx);
+		}
+
+		[Test]
+		[ExpectedException (typeof (ArgumentException))]
+		[Category ("NotWorking")]
+		public void InvalidListenIPAddress ()
+		{
+			PeerTransportBindingElement be =
+				new PeerTransportBindingElement ();
+			be.Security.Mode = SecurityMode.None;
+			be.ListenIPAddress = IPAddress.Parse ("127.0.0.1");
+			CustomBinding binding = new CustomBinding (
+				new HandlerTransportBindingElement (null));
+			BindingContext ctx = new BindingContext (
+				binding, new BindingParameterCollection ());
+			ctx.ListenUriBaseAddress = new Uri ("net.p2p:foobar");
+			be.BuildChannelListener<IInputChannel> (ctx);
+		}
+
+		[Test]
+		[Ignore ("It is documented that MaxBufferPoolSize must be greater than MaxReceivedMessageSize, but not really checked (at least here)")]
+		public void MaxBufferPoolSizeTooSmall ()
+		{
+			PeerTransportBindingElement be =
+				new PeerTransportBindingElement ();
+			be.MaxBufferPoolSize = 0x1000;
+			be.Security.Mode = SecurityMode.None;
+			CustomBinding binding = new CustomBinding (
+				new HandlerTransportBindingElement (null));
+			BindingContext ctx = new BindingContext (
+				binding, new BindingParameterCollection ());
+			ctx.ListenUriBaseAddress = new Uri ("net.p2p:foobar");
+			be.BuildChannelListener<IInputChannel> (ctx);
+		}
+	}
+}

+ 4 - 0
mcs/class/System.ServiceModel/Test/System.ServiceModel/ChangeLog

@@ -1,3 +1,7 @@
+2009-04-20  Atsushi Enomoto  <[email protected]>
+
+	* NetPeerTcpBindingTest.cs : new test.
+
 2009-04-08  Atsushi Enomoto  <[email protected]>
 
 	* NetTcpBindingTest.cs : fix wrong value expectation.

+ 113 - 0
mcs/class/System.ServiceModel/Test/System.ServiceModel/NetPeerTcpBindingTest.cs

@@ -0,0 +1,113 @@
+//
+// NetPeerTcpBindingTest.cs
+//
+// Author:
+//	Atsushi Enomoto <[email protected]>
+//
+// Copyright (C) 2009 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.Collections.ObjectModel;
+using System.Net.Security;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.ServiceModel.PeerResolvers;
+using System.ServiceModel.Security;
+using NUnit.Framework;
+
+namespace MonoTests.System.ServiceModel
+{
+	[TestFixture]
+	public class NetPeerTcpBindingTest
+	{
+		[Test]
+		public void DefaultValues ()
+		{
+			if (!NetPeerTcpBinding.IsPnrpAvailable)
+				return; // yes, we actually don't test it.
+
+			var n = new NetPeerTcpBinding ();
+			Assert.AreEqual (EnvelopeVersion.Soap12, n.EnvelopeVersion, "#1");
+			Assert.IsNull (n.ListenIPAddress, "#2");
+			Assert.AreEqual (0x10000, n.MaxReceivedMessageSize, "#3");
+			Assert.AreEqual (0, n.Port, "#4");
+			Assert.IsNotNull (n.ReaderQuotas, "#5");
+
+			var bec = n.CreateBindingElements ();
+			Assert.IsNotNull (bec.Find<PnrpPeerResolverBindingElement> (), "#bec0");
+			Assert.IsNotNull (bec.Find<BinaryMessageEncodingBindingElement> (), "#bec1");
+			Assert.AreEqual (3, bec.Count, "#bec2");
+
+			var tr = bec.Find<PeerTransportBindingElement> ();
+			Assert.IsNotNull (tr, "#tr1");
+		}
+
+		[Test]
+		public void DefaultValuesForCustom ()
+		{
+			var n = new NetPeerTcpBinding ();
+			n.Resolver.Mode = PeerResolverMode.Custom;
+			n.Resolver.Custom.Resolver = new DummyResolver ();
+
+			Assert.AreEqual (EnvelopeVersion.Soap12, n.EnvelopeVersion, "#1");
+			Assert.IsNull (n.ListenIPAddress, "#2");
+			Assert.AreEqual (0x10000, n.MaxReceivedMessageSize, "#3");
+			Assert.AreEqual (0, n.Port, "#4");
+			Assert.IsNotNull (n.ReaderQuotas, "#5");
+
+			var bec = n.CreateBindingElements ();
+			Assert.IsNotNull (bec.Find<PeerCustomResolverBindingElement> (), "#bec0");
+			Assert.IsNotNull (bec.Find<BinaryMessageEncodingBindingElement> (), "#bec1");
+			Assert.AreEqual (3, bec.Count, "#bec2");
+
+			var tr = bec.Find<PeerTransportBindingElement> ();
+			Assert.IsNotNull (tr, "#tr1");
+		}
+	}
+
+	class DummyResolver : PeerResolver
+	{
+		public override object Register (string meshId,
+			PeerNodeAddress nodeAddress, TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override ReadOnlyCollection<PeerNodeAddress> Resolve (
+			string meshId, int maxAddresses, TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override void Unregister (object registrationId,
+			TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override void Update (object registrationId,
+			PeerNodeAddress updatedNodeAddress, TimeSpan timeout)
+		{
+			throw new NotImplementedException ();
+		}
+	}
+}