2009-07-10 Atsushi Enomoto <atsushi@ximian.com>
authorAtsushi Eno <atsushieno@gmail.com>
Fri, 10 Jul 2009 03:34:07 +0000 (03:34 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Fri, 10 Jul 2009 03:34:07 +0000 (03:34 -0000)
* PeerNode.cs : significant refactoring. It does not call resolver
  to manage the node itself but rather hold its state.

* PeerDuplexChannel.cs : now it implements some of node management
  functionality and Send operation. The receiver part is not yet.

svn path=/trunk/mcs/; revision=137671

mcs/class/System.ServiceModel/System.ServiceModel.Channels/ChangeLog
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PeerDuplexChannel.cs
mcs/class/System.ServiceModel/System.ServiceModel/ChangeLog
mcs/class/System.ServiceModel/System.ServiceModel/PeerNode.cs

index 6694db63e306f8e0d2abf8727a8e7061ea2754d1..6b7a7fc910e6c4f4bddc237e06e439be472b588d 100755 (executable)
@@ -1,3 +1,8 @@
+2009-07-10  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * PeerDuplexChannel.cs : now it implements some of node management
+         functionality and Send operation. The receiver part is not yet.
+
 2009-07-10  Atsushi Enomoto  <atsushi@ximian.com>
 
        * TcpChannelListener.cs, TcpDuplexSessionChannel.cs : do not pass
index ef647b861029284a703752967fa0ad7628103321..2bc8f030659a3b0c8fe00738bce74b458809c489 100755 (executable)
 //
 using System;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.IO;
 using System.Net;
 using System.Net.Security;
+using System.Net.Sockets;
 using System.ServiceModel;
 using System.ServiceModel.Description;
 using System.ServiceModel.Security;
@@ -51,16 +53,20 @@ namespace System.ServiceModel.Channels
                EndpointAddress local_address;
                PeerResolver resolver;
                PeerNode node;
+               TcpListener listener;
+               TcpChannelInfo info;
+               List<PeerNodeAddress> peers = new List<PeerNodeAddress> ();
 
                public PeerDuplexChannel (IPeerChannelManager factory, EndpointAddress address, Uri via, PeerResolver resolver)
                        : base ((ChannelFactoryBase) factory, address, via)
                {
                        binding = factory.Source;
                        this.resolver = factory.Resolver;
+                       info = new TcpChannelInfo (binding, factory.MessageEncoder, null); // FIXME: fill properties correctly.
 
                        // It could be opened even with empty list of PeerNodeAddresses.
                        // So, do not create PeerNode per PeerNodeAddress, but do it with PeerNodeAddress[].
-                       node = new PeerNodeImpl (resolver, RemoteAddress, factory.Source.ListenIPAddress, factory.Source.Port);
+                       node = new PeerNodeImpl (RemoteAddress, factory.Source.ListenIPAddress, factory.Source.Port);
                }
 
                // FIXME: receive local_address too
@@ -69,9 +75,9 @@ namespace System.ServiceModel.Channels
                {
                        binding = listener.Source;
                        this.resolver = listener.Resolver;
-                       // FIXME: set resolver and node.
+                       info = new TcpChannelInfo (binding, listener.MessageEncoder, null); // FIXME: fill properties correctly.
 
-                       node = new PeerNodeImpl (resolver, null, listener.Source.ListenIPAddress, listener.Source.Port);
+                       node = new PeerNodeImpl (null, listener.Source.ListenIPAddress, listener.Source.Port);
                }
 
                public override EndpointAddress LocalAddress {
@@ -87,38 +93,77 @@ namespace System.ServiceModel.Channels
 
                // DuplexChannelBase
 
+               TcpDuplexSessionChannel CreateInnerChannel (PeerNodeAddress pna)
+               {
+                       var cfb = Manager as ChannelFactoryBase;
+                       if (cfb != null)
+                               return new TcpDuplexSessionChannel (cfb, info, pna.EndpointAddress, Via);
+                       else
+                               return new TcpDuplexSessionChannel ((ChannelListenerBase) Manager, info, listener.AcceptTcpClient ());
+               }
+
                public override void Send (Message message, TimeSpan timeout)
                {
-                       throw new NotImplementedException ();
+                       ThrowIfDisposedOrNotOpen ();
+
+                       DateTime start = DateTime.Now;
+
+                       foreach (var pna in peers) {
+                               var inner = CreateInnerChannel (pna);
+                               inner.Open (timeout - (DateTime.Now - start));
+                               inner.Send (message, timeout);
+                       }
                }
 
                public override Message Receive (TimeSpan timeout)
                {
+                       ThrowIfDisposedOrNotOpen ();
+
                        throw new NotImplementedException ();
                }
 
                public override bool WaitForMessage (TimeSpan timeout)
                {
+                       ThrowIfDisposedOrNotOpen ();
+
                        throw new NotImplementedException ();
                }
                
                // CommunicationObject
                
-               [MonoTODO]
                protected override void OnAbort ()
                {
-                       throw new NotImplementedException ();
+                       OnClose (TimeSpan.Zero);
                }
 
                protected override void OnClose (TimeSpan timeout)
                {
-                       node.Close (timeout);
+                       DateTime start = DateTime.Now;
+                       peers.Clear ();
+                       resolver.Unregister (node.RegisteredId, timeout - (DateTime.Now - start));
+                       node.SetOffline ();
+                       if (listener != null)
+                               listener.Stop ();
+                       node.RegisteredId = null;
                }
 
-               // At some stage I should unify this class with PeerOutputChannel (and probably PeerInputChannel). Too much duplicate.
                protected override void OnOpen (TimeSpan timeout)
                {
-                       node.Open (timeout);
+                       DateTime start = DateTime.Now;
+
+                       // FIXME: supply maxAddresses
+                       peers.AddRange (resolver.Resolve (node.MeshId, 3, timeout));
+
+                       listener = node.GetTcpListener ();
+                       var ep = (IPEndPoint) listener.LocalEndpoint;
+                       string name = Dns.GetHostName ();
+                       var nid = new Random ().Next (0, int.MaxValue);
+                       var ea = new EndpointAddress ("net.tcp://" + name + ":" + ep.Port + "/PeerChannelEndpoints/" + Guid.NewGuid ());
+                       var pna = new PeerNodeAddress (ea, new ReadOnlyCollection<IPAddress> (Dns.GetHostEntry (ep.Address).AddressList));
+                       node.RegisteredId = resolver.Register (node.MeshId, pna, timeout - (DateTime.Now - start));
+                       node.NodeId = nid;
+
+                       node.SetOnline ();
                }
        }
 }
index c5ab682d73c5c1a59d44dd82076c7a6c0f398149..cf4c20fa6a13e0220fc8b7d33413259b349cc0df 100755 (executable)
@@ -1,3 +1,8 @@
+2009-07-10  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * PeerNode.cs : significant refactoring. It does not call resolver
+         to manage the node itself but rather hold its state.
+
 2009-07-09  Atsushi Enomoto  <atsushi@ximian.com>
 
        * PeerNode.cs : some implementation cleanup before significant
index 2e19f741ef680da5c80456fb634194b7082703a5..f7fa41335f5773ef43933b3b6d7b2a1d23ba7b34 100644 (file)
@@ -51,14 +51,17 @@ namespace System.ServiceModel
 
                internal int NodeId { get; set; }
 
-               internal abstract bool IsOpen { get; }
+               internal bool IsOpen {
+                       get { return RegisteredId != null; }
+               }
+
+               internal object RegisteredId { get; set; }
 
                public int Port { get; private set; }
 
                public abstract PeerMessagePropagationFilter MessagePropagationFilter { get; set; }
 
-               internal abstract void Open (TimeSpan timeout);
-               internal abstract void Close (TimeSpan timeout);
+               internal abstract TcpListener GetTcpListener ();
 
                public void RefreshConnection ()
                {
@@ -92,33 +95,24 @@ namespace System.ServiceModel
                        public PeerNodeAddress Address { get; set; }
                }
 
-               internal PeerNodeImpl (PeerResolver resolver, EndpointAddress remoteAddress, IPAddress fixedListenAddress, int port)
+               internal PeerNodeImpl (EndpointAddress remoteAddress, IPAddress fixedListenAddress, int port)
                        : base (remoteAddress.Uri.Host, port)
                {
-                       this.resolver = resolver;
                        this.listen_address = fixedListenAddress ?? IPAddress.Any;
                        this.remote_address = remoteAddress;
                }
 
-               PeerResolver resolver;
                EndpointAddress remote_address;
                IPAddress listen_address;
-               object registered_id;
-               TcpListener listener;
 
                // FIXME: implement
                public override PeerMessagePropagationFilter MessagePropagationFilter { get; set; }
 
-               internal override bool IsOpen {
-                       get { return registered_id != null; }
-               }
-
-               internal override void Open (TimeSpan timeout)
+               internal override TcpListener GetTcpListener ()
                {
-                       DateTime startTime = DateTime.Now;
-
                        int p = Port;
                        var rnd = Port != 0 ? null : new Random ();
+                       TcpListener listener = null;
                        while (p < 51000) {
                                if (rnd != null)
                                        p = rnd.Next (50000, 51000); // This range is picked up sorta randomly.
@@ -134,22 +128,7 @@ namespace System.ServiceModel
                        }
                        if (listener == null)
                                throw new InvalidOperationException (String.Format ("The specified endpoint is available for a peer node to listen. IP address: {0}, Port {1}", listen_address, Port));
-                       var ep = (IPEndPoint) listener.LocalEndpoint;
-                       string name = Dns.GetHostName ();
-                       var nid = new Random ().Next (0, int.MaxValue);
-                       var pna = new PeerNodeAddress (new EndpointAddress ("net.tcp://" + name + ":" + ep.Port + "/PeerChannelEndpoints/" + Guid.NewGuid ()), new ReadOnlyCollection<IPAddress> (Dns.GetHostEntry (listen_address).AddressList));
-                       registered_id = resolver.Register (MeshId, pna, timeout - (DateTime.Now - startTime));
-                       NodeId = nid;
-                       SetOnline ();
-               }
-
-               internal override void Close (TimeSpan timeout)
-               {
-                       resolver.Unregister (registered_id, timeout);
-                       SetOffline ();
-                       if (listener != null)
-                               listener.Stop ();
-                       registered_id = null;
+                       return listener;
                }
        }
 }