2 // LocalPeerResolverService.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System
.Collections
.Generic
;
33 using System
.Runtime
.Serialization
;
34 using System
.ServiceModel
;
35 using System
.ServiceModel
.PeerResolvers
;
37 namespace System
.ServiceModel
.PeerResolvers
39 // This implementation of peer resolver should open up node
40 // registration to some extent, say, valid within the same machine.
42 // A correct implementation should be using something like zeroconf
43 // to register the local machine as a peer node.
45 class LocalPeerResolverService
: ICustomPeerResolverContract
47 public LocalPeerResolverService (TextWriter log
)
49 this.log
= log
?? TextWriter
.Null
;
53 Dictionary
<string,Mesh
> mesh_map
= new Dictionary
<string,Mesh
> ();
55 // CustomPeerResolverService delegation
57 // Open(), Close(), ControlShape, RefreshInterval, CleanupInterval
59 public bool ControlShape { get; set; }
60 public TimeSpan RefreshInterval { get; set; }
61 public TimeSpan CleanupInterval { get; set; }
63 // (internal) ICustomPeerResolverContract implementation
65 public PeerServiceSettingsInfo
GetCustomServiceSettings ()
67 log
.WriteLine ("REQUEST: GetCustomServiceSettings");
68 return new PeerServiceSettingsInfo () {
69 ControlMeshShape
= this.ControlShape
,
70 RefreshInterval
= this.RefreshInterval
,
71 CleanupInterval
= this.CleanupInterval
};
74 public void SetCustomServiceSettings (PeerServiceSettingsInfo info
)
76 log
.WriteLine ("REQUEST: SetCustomServiceSettings(ControlMeshShape:{0}, RefreshInterval:{1}, CleanupInterval:{2}", info
.ControlMeshShape
, info
.RefreshInterval
, info
.CleanupInterval
);
77 ControlShape
= info
.ControlMeshShape
;
78 RefreshInterval
= info
.RefreshInterval
;
79 CleanupInterval
= info
.CleanupInterval
;
82 // IPeerResolverContract implementation
84 public ServiceSettingsResponseInfo
GetServiceSettings ()
86 return new ServiceSettingsResponseInfo () { ControlMeshShape = this.ControlShape }
;
89 public RefreshResponseInfo
Refresh (RefreshInfo refreshInfo
)
92 log
.WriteLine ("REQUEST: Refresh (Mesh: {0}, Registraion: {1})", r
.MeshId
, r
.RegistrationId
);
93 var mesh
= GetExistingMesh (r
.MeshId
);
94 var node
= mesh
.FirstOrDefault (n
=> n
.RegistrationId
== r
.RegistrationId
);
96 return new RefreshResponseInfo () { Result = RefreshResult.RegistrationNotFound }
;
98 return new RefreshResponseInfo () { Result = RefreshResult.Success, RegistrationLifetime = RefreshInterval - (DateTime.Now - node.LastRefreshTime) }
;
101 public RegisterResponseInfo
Register (RegisterInfo registerInfo
)
103 var r
= registerInfo
;
104 log
.WriteLine ("REQUEST: Register (Mesh: {0}, Client: {1}, NodeAddress: endpoint {2})", r
.MeshId
, r
.ClientId
, r
.NodeAddress
.EndpointAddress
);
106 if (!mesh_map
.TryGetValue (r
.MeshId
, out mesh
)) {
107 mesh
= new Mesh (r
.MeshId
);
108 mesh_map
.Add (r
.MeshId
, mesh
);
110 var node
= RegisterNode (mesh
, r
.ClientId
, r
.NodeAddress
);
111 return new RegisterResponseInfo () { RegistrationId = node.RegistrationId }
;
114 public ResolveResponseInfo
Resolve (ResolveInfo resolveInfo
)
117 log
.WriteLine ("REQUEST: Resolve (Mesh: {0}, Client: {1}, MaxAddresses: {2})", r
.MeshId
, r
.ClientId
, r
.MaxAddresses
);
119 var rr
= new ResolveResponseInfo ();
120 if (!mesh_map
.TryGetValue (r
.MeshId
, out mesh
))
122 // FIXME: find out how to use the argument ClientId.
123 // So far, it is used to filter out the registered node from the same ClientId.
124 foreach (var node
in mesh
.TakeWhile (n
=> n
.ClientId
!= r
.ClientId
)) {
125 rr
.Addresses
.Add (node
.Address
);
126 if (rr
.Addresses
.Count
== r
.MaxAddresses
)
132 public void Unregister (UnregisterInfo unregisterInfo
)
134 var u
= unregisterInfo
;
135 log
.WriteLine ("REQUEST: Unregister (Mesh: {0}, Registration: {1})", u
.MeshId
, u
.RegistrationId
);
136 Mesh mesh
= GetExistingMesh (u
.MeshId
);
138 var node
= mesh
.GetRegisteredNode (u
.RegistrationId
);
143 public RegisterResponseInfo
Update (UpdateInfo updateInfo
)
146 log
.WriteLine ("REQUEST: Update (Mesh: {0}, Registration: {1}, NodeAddress:)", u
.MeshId
, u
.RegistrationId
, u
.NodeAddress
);
147 var mesh
= GetExistingMesh (u
.MeshId
);
148 var node
= mesh
.GetRegisteredNode (u
.RegistrationId
);
149 node
.Update (u
.NodeAddress
);
150 return new RegisterResponseInfo () { RegistrationId = node.RegistrationId }
;
153 Mesh
GetExistingMesh (string meshId
)
156 if (!mesh_map
.TryGetValue (meshId
, out mesh
))
157 throw new InvalidOperationException (String
.Format ("Specified mesh {0} does not exist", meshId
));
161 Node
RegisterNode (Mesh mesh
, Guid clientId
, PeerNodeAddress addr
)
164 var node
= new Node () { ClientId = clientId, Address = addr }
;
166 node
.LastRefreshTime
= DateTime
.Now
;
172 class Mesh
: List
<Node
>
174 public Mesh (string id
)
179 public string Id { get; private set; }
181 public Node
GetRegisteredNode (Guid registrationId
)
183 var node
= this.FirstOrDefault (n
=> n
.RegistrationId
== registrationId
);
185 throw new InvalidOperationException (String
.Format ("Node with registration Id {0} does not exist in the specified mesh {0}", registrationId
, Id
));
194 RegistrationId
= Guid
.NewGuid ();
197 public Guid RegistrationId { get; private set; }
198 public Guid ClientId { get; set; }
199 public PeerNodeAddress Address { get; set; }
200 public DateTime LastRefreshTime { get; set; }
202 public void Refresh ()
204 LastRefreshTime
= DateTime
.Now
;
207 public void Update (PeerNodeAddress addr
)
210 LastRefreshTime
= DateTime
.Now
;