source: trunk/CrypP2P/P2PManager.cs @ 1579

Last change on this file since 1579 was 1579, checked in by Paul Lelgemann, 12 years ago

+ P2PEditor: Timer-based refresh of the job list (configurable in seconds)
o CrypP2P: Restored bootstrapper to V2
+ P2PManager: Added asynchronous DHT message calls for completeness

File size: 10.8 KB
Line 
1/*
2   Copyright 2010 Paul Lelgemann, University of Duisburg-Essen
3
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15*/
16
17using System;
18using System.Windows.Forms;
19using Cryptool.P2P.Internal;
20using Cryptool.P2P.Worker;
21using Cryptool.PluginBase;
22using Cryptool.PluginBase.Miscellaneous;
23using Cryptool.Plugins.PeerToPeer.Internal;
24using PeersAtPlay;
25using PeersAtPlay.P2PStorage.DHT;
26using PeersAtPlay.Util.Threading;
27
28namespace Cryptool.P2P
29{
30    public sealed class P2PManager
31    {
32        #region Singleton
33
34        public static readonly P2PManager Instance = new P2PManager();
35
36        private P2PManager()
37        {
38            P2PBase = new P2PBase();
39
40            // Register events
41
42            // to forward event from overlay/dht MessageReceived-Event from P2PBase
43            P2PBase.OnP2PMessageReceived += OnP2PMessageReceived;
44
45            // Register exit event to terminate P2P connection without loosing data
46            // TODO check if this is correct, should be - but handler is not called (and application does not shut down), probably unrelated to this problem
47            Application.ApplicationExit += HandleDisconnectByApplicationShutdown;
48        }
49
50        #endregion
51
52        #region Variables
53
54        public P2PBase P2PBase { get; private set; }
55        public bool IsP2PConnecting { get; internal set; }
56
57        #endregion
58
59        #region Events
60
61        public static event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
62
63        public delegate void P2PConnectionStateChangeEventHandler(object sender, bool newState);
64        public static event P2PConnectionStateChangeEventHandler OnP2PConnectionStateChangeOccurred;
65
66        public event P2PBase.P2PMessageReceived OnPeerMessageReceived;
67
68        #endregion Events
69
70        internal void FireConnectionStatusChange()
71        {
72            if (OnP2PConnectionStateChangeOccurred != null)
73            {
74                OnP2PConnectionStateChangeOccurred(this, IsP2PConnected());
75            }
76        }
77
78        public bool IsP2PConnected()
79        {
80            return P2PBase.Started;
81        }
82
83        public string UserInfo()
84        {
85            if (!IsP2PConnected())
86            {
87                return null;
88            }
89
90            string userName;
91            var userInfo = P2PBase.GetPeerId(out userName);
92            return userInfo + " (" + userName + ")";
93        }
94
95        public void HandleConnectOnStartup()
96        {
97            if (P2PSettings.Default.ConnectOnStartup && IsReadyToConnect())
98            {
99                GuiLogMessage("Connect on startup enabled. Establishing connection...", NotificationLevel.Info);
100                new ConnectionWorker(P2PBase).Start();
101            }
102        }
103
104        private bool IsReadyToConnect()
105        {
106            if (String.IsNullOrEmpty(P2PSettings.Default.PeerName))
107            {
108                GuiLogMessage("Peer-to-peer not fully configured: username missing.", NotificationLevel.Error);
109                return false;
110            }
111
112            if (String.IsNullOrEmpty(P2PSettings.Default.PeerName))
113            {
114                GuiLogMessage("Peer-to-peer not fully configured: world name missing.", NotificationLevel.Error);
115                return false;
116            }
117
118            return true;
119        }
120
121        public PeerId GetPeerId(out string userName)
122        {
123            return P2PBase.GetPeerId(out userName);
124        }
125
126        // to forward event from overlay/dht MessageReceived-Event from P2PBase
127        private void OnP2PMessageReceived(PeerId sourceAddr, byte[] data)
128        {
129            if (OnPeerMessageReceived != null)
130                OnPeerMessageReceived(sourceAddr, data);
131        }
132
133        #region Framework methods
134
135        private void HandleDisconnectByApplicationShutdown(object sender, EventArgs e)
136        {
137            if (IsP2PConnected())
138            {
139                new ConnectionWorker(P2PBase).Start();
140            }
141        }
142
143        public void GuiLogMessage(string message, NotificationLevel logLevel)
144        {
145            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, null, new GuiLogEventArgs(message, null, logLevel));
146        }
147
148        #endregion Framework methods
149
150        #region DHT operations (blocking)
151
152        /// <summary>
153        /// Stores the given data in the DHT. This method will block until a response has been received.
154        ///
155        /// The underlying DHT is versionend. Store attempts will fail, if the latest version has not been retrieved before.
156        /// </summary>
157        /// <param name="key">key to write</param>
158        /// <param name="data">data to write</param>
159        /// <exception cref="NotConnectedException">Will be thrown if the P2P system is not connected</exception>
160        /// <returns>true if the store attempt was successful, false otherwise</returns>
161        public static bool Store(string key, byte[] data)
162        {
163            if (!Instance.IsP2PConnected())
164                throw new NotConnectedException();
165
166            return Instance.P2PBase.SynchStore(key, data);
167        }
168
169        /// <summary>
170        /// Stores the given data in the DHT. This method will block until a response has been received.
171        ///
172        /// The underlying DHT is versionend. Store attempts will fail, if the latest version has not been retrieved before.
173        /// </summary>
174        /// <param name="key">key to write</param>
175        /// <param name="data">data to write</param>
176        /// <exception cref="NotConnectedException">Will be thrown if the P2P system is not connected</exception>
177        /// <returns>true if the store attempt was successful, false otherwise</returns>
178        public static bool Store(string key, string data)
179        {
180            if (!Instance.IsP2PConnected())
181                throw new NotConnectedException();
182           
183            return Instance.P2PBase.SynchStore(key, data);
184        }
185
186        /// <summary>
187        /// Retrieves the latest version of a given in key from the DHT. This method will block until a response has been received.
188        /// </summary>
189        /// <param name="key">key to retrieve</param>
190        /// <exception cref="NotConnectedException">Will be thrown if the P2P system is not connected</exception>
191        /// <returns>byte array containing the data</returns>
192        public static byte[] Retrieve(string key)
193        {
194            if (!Instance.IsP2PConnected())
195                throw new NotConnectedException();
196           
197            return Instance.P2PBase.SynchRetrieve(key);
198        }
199
200        /// <summary>
201        /// Removes a key and its data from the DHT. This method will block until a response has been received.
202        ///
203        /// The underlying DHT is versionend. Remove attempts will fail, if the latest version has not been retrieved before.
204        /// </summary>
205        /// <param name="key">key to remove</param>
206        /// <exception cref="NotConnectedException">Will be thrown if the P2P system is not connected</exception>
207        /// <returns>bool determining wether the attempt was successful</returns>
208        public static bool Remove(string key)
209        {
210            if (!Instance.IsP2PConnected())
211                throw new NotConnectedException();
212
213            return Instance.P2PBase.SynchRemove(key);
214        }
215
216        #endregion DHT operations (blocking)
217
218        #region DHT operations (non-blocking)
219
220        /// <summary>
221        /// Stores the given data in the DHT.
222        ///
223        /// The underlying DHT is versionend. Store attempts will fail, if the latest version has not been retrieved before.
224        /// </summary>
225        /// <param name="callback">Callback for asynchronous call</param>
226        /// <param name="key">key to write</param>
227        /// <param name="data">data to write</param>
228        /// <param name="asyncState">Arbitrary data, which will be included in the callback parameter</param>
229        /// <exception cref="NotConnectedException">Will be thrown if the P2P system is not connected</exception>
230        /// <returns>Guid identifying the request</returns>
231        public static Guid Store(AsyncCallback<StoreResult> callback, string key, byte[] data, object asyncState)
232        {
233            if (!Instance.IsP2PConnected())
234                throw new NotConnectedException();
235
236            return Instance.P2PBase.VersionedDht.Store(callback, key, data, asyncState);
237        }
238
239        /// <summary>
240        /// Retrieves the latest version of a given in key from the DHT.
241        /// </summary>
242        /// <param name="callback">Callback for asynchronous call</param>
243        /// <param name="key">key to retrieve</param>
244        /// <param name="asyncState">Arbitrary data, which will be included in the callback parameter</param>
245        /// <exception cref="NotConnectedException">Will be thrown if the P2P system is not connected</exception>
246        /// <returns>Guid identifying the request</returns>
247        public static Guid Retrieve(AsyncCallback<RetrieveResult> callback, string key, object asyncState)
248        {
249            if (!Instance.IsP2PConnected())
250                throw new NotConnectedException();
251
252            return Instance.P2PBase.Dht.Retrieve(callback, key, asyncState);
253        }
254
255        /// <summary>
256        /// Removes a key and its data from the DHT.
257        ///
258        /// The underlying DHT is versionend. Remove attempts will fail, if the latest version has not been retrieved before.
259        /// </summary>
260        /// <param name="callback">Callback for asynchronous call</param>
261        /// <param name="key">key to remove</param>
262        /// <param name="asyncState">Arbitrary data, which will be included in the callback parameter</param>
263        /// <exception cref="NotConnectedException">Will be thrown if the P2P system is not connected</exception>
264        /// <returns>Guid identifying the request</returns>
265        public static Guid Remove(AsyncCallback<RemoveResult> callback, string key, object asyncState)
266        {
267            if (!Instance.IsP2PConnected())
268                throw new NotConnectedException();
269
270            return Instance.P2PBase.VersionedDht.Remove(callback, key, asyncState);
271        }
272
273        #endregion DHT operations (non-blocking)
274    }
275
276   
277}
Note: See TracBrowser for help on using the repository browser.