source: trunk/CrypPlugins/PeerToPeerManager_NEW/P2PManager_KeyPattern.cs @ 1178

Last change on this file since 1178 was 1178, checked in by arnold, 12 years ago

P2PManager: Added a job distribution Expander in the QuickWatchPresentation
Bug fixes: Cyclic Register-Message-Sending, Allocating more than one job to each worker

File size: 24.0 KB
Line 
1/* Copyright 2010 Team CrypTool (Christian Arnold), Uni Duisburg-Essen
2
3   Licensed under the Apache License, Version 2.0 (the "License");
4   you may not use this file except in compliance with the License.
5   You may obtain a copy of the License at
6
7       http://www.apache.org/licenses/LICENSE-2.0
8
9   Unless required by applicable law or agreed to in writing, software
10   distributed under the License is distributed on an "AS IS" BASIS,
11   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   See the License for the specific language governing permissions and
13   limitations under the License.
14*/
15
16using System;
17using System.Collections.Generic;
18using System.Linq;
19using System.Text;
20using System.Threading;
21using Cryptool.PluginBase;
22using Cryptool.PluginBase.IO;
23using Cryptool.PluginBase.Control;
24using Cryptool.PluginBase.Miscellaneous;
25using System.ComponentModel;
26using KeySearcher;
27using System.Windows.Controls;
28using System.Windows.Threading;
29using Cryptool.Plugins.PeerToPeer.Jobs;
30
31/*TODO:
32 * - Execute: If InitVector is null, try to create a fitting InitVector with the format 0...0
33 * - No linebreaks in the global result list
34 * - 2 Output values (Top1-Key and Top1-Decryption)
35 * - Display the job stati in a kind of a defragmentation list
36 */
37
38namespace Cryptool.Plugins.PeerToPeer
39{
40    /// <summary>
41    /// This PlugIn only works, when its connected with a P2P_Peer object.
42    /// </summary>
43    [Author("Christian Arnold", "arnold@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-due.de")]
44    [PluginInfo(false, "P2P_Manager_KeyPattern", "Creates a new Manager-Peer for distributable KeyPattern-Jobs", "", "PeerToPeerManager_NEW/manager_medium_neutral.png", "PeerToPeerManager_NEW/manager_medium_working.png", "PeerToPeerManager_NEW/manager_medium_finished.png")]
45    public class P2PManager_KeyPattern : IInput
46    {
47        private P2PManagerBase_NEW p2pManager;
48        private P2PManager_KeyPatternSettings settings;
49        // IInput
50        private CryptoolStream decryptedData;
51        private byte[] initVector;
52        // IControls       
53        private IControlEncryption encryptionControl;
54        private IP2PControl p2pControl;
55
56        private KeyPattern pattern = null;
57        public KeyPattern Pattern
58        {
59            get
60            {
61                return pattern;
62            }
63            set
64            {
65                pattern = value;
66                if ((settings.Key == null) || ((settings.Key != null) && !pattern.testWildcardKey(settings.Key)))
67                    settings.Key = pattern.giveInputPattern();
68            }
69        }
70
71        /// <summary>
72        /// after starting the execution, set this value, so after receiving
73        /// a Job result, the WPF UpdateQuickWatch can use this value, without
74        /// accessing the Settings every time.
75        /// </summary>
76        private int bytesToUseForDecryption = 0;
77
78        #region In and Output
79
80        [PropertyInfo(Direction.InputData, "Encrypted Data", "Encrypted data out of an Encryption PlugIn", "", true, false, DisplayLevel.Beginner, QuickWatchFormat.Hex, "")]
81        public CryptoolStream DecryptedData
82        {
83            get { return this.decryptedData; }
84            set
85            {
86                if (value != this.decryptedData)
87                {
88                    this.decryptedData = value;
89                }
90            }
91        }
92
93        [PropertyInfo(Direction.InputData, "Initialization Vector", "Initialization vector with which the data were encrypted", "", DisplayLevel.Beginner)]
94        public byte[] InitVector
95        {
96            get { return this.initVector; }
97            set
98            {
99                if (value != this.initVector)
100                    this.initVector = value;
101            }
102        }
103
104        [PropertyInfo(Direction.ControlMaster, "Control Master", "Used for bruteforcing", "", DisplayLevel.Beginner)]
105        public IControlEncryption EncryptionControl
106        {
107            get { return this.encryptionControl; }
108            set
109            {
110                if (this.encryptionControl != null)
111                {
112                    this.encryptionControl.keyPatternChanged -= encryptionControl_keyPatternChanged;
113                    this.encryptionControl.OnStatusChanged -= encryptionControl_onStatusChanged;
114                }
115                if (value != null)
116                {
117                    Pattern = new KeyPattern(value.getKeyPattern());
118                    value.keyPatternChanged += encryptionControl_keyPatternChanged;
119                    value.OnStatusChanged += encryptionControl_onStatusChanged;
120                    this.encryptionControl = value;
121                    OnPropertyChanged("ControlMaster");
122
123                }
124                else
125                    this.encryptionControl = null;
126            }
127        }
128
129        private void encryptionControl_keyPatternChanged()
130        {
131            Pattern = new KeyPattern(this.encryptionControl.getKeyPattern());
132        }
133        private void encryptionControl_onStatusChanged(IControl sender, bool readyForExecution)
134        {
135            // obsolete stuff
136            if (readyForExecution)
137            {
138                this.process((IControlEncryption)sender);
139            }
140        }
141
142        /// <summary>
143        /// Catches the completely configurated, initialized and joined P2P object from the P2PPeer-Slave-PlugIn.
144        /// </summary>
145        [PropertyInfo(Direction.ControlMaster, "P2P Slave", "Input the P2P-Peer-PlugIn", "", true, false, DisplayLevel.Beginner, QuickWatchFormat.Text, null)]
146        public IP2PControl P2PControl
147        {
148            get
149            {
150                return this.p2pControl;
151            }
152            set
153            {
154                if (this.p2pControl != null)
155                {
156                    this.p2pControl.OnStatusChanged -= P2PControl_OnStatusChanged;
157                }
158                if (value != null)
159                {
160                    this.p2pControl = (P2PPeerMaster)value;
161                    this.p2pControl.OnStatusChanged += new IControlStatusChangedEventHandler(P2PControl_OnStatusChanged);
162                    OnPropertyChanged("P2PMaster");
163                }
164                else
165                {
166                    this.p2pControl = null;
167                }
168            }
169        }
170
171        private void P2PControl_OnStatusChanged(IControl sender, bool readyForExecution)
172        {
173            //throw new NotImplementedException();
174        }
175
176        #endregion
177
178        #region Events
179
180        public event StatusChangedEventHandler OnPluginStatusChanged;
181
182        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
183
184        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
185
186        #endregion
187
188        #region Standard PlugIn-Functionality
189
190        public P2PManager_KeyPattern()
191        {
192            this.settings = new P2PManager_KeyPatternSettings();
193            this.settings.PropertyChanged += new PropertyChangedEventHandler(settings_PropertyChanged);
194            this.settings.TaskPaneAttributeChanged += new TaskPaneAttributeChangedHandler(settings_TaskPaneAttributeChanged);
195            this.settings.OnPluginStatusChanged += new StatusChangedEventHandler(settings_OnPluginStatusChanged);
196
197            QuickWatchPresentation = new P2PManagerPresentation();
198        }
199
200        #region QuickWatchPresentation Stuff
201
202        public UserControl QuickWatchPresentation
203        {
204            get;
205            private set;
206        }
207
208        public UserControl Presentation
209        {
210            get { return QuickWatchPresentation; }
211        }
212
213        private void UpdateQuickWatch(double progressInPercent)
214        {
215            UpdateQuickWatch(this.distributableKeyPatternJob.GlobalResultList, this.distributableKeyPatternJob.TotalAmount,
216                this.distributableKeyPatternJob.AllocatedAmount, this.distributableKeyPatternJob.FinishedAmount, 
217                progressInPercent, this.p2pManager.FreeWorkers(), this.p2pManager.BusyWorkers());
218        }
219
220        private void UpdateQuickWatch(LinkedList<KeySearcher.KeySearcher.ValueKey> globalTop10List,
221            BigInteger jobsTotalAmount, BigInteger jobsInProgress, BigInteger jobsFinished, double progressInPercent,
222            int freeWorkers, int busyWorkers)
223        {
224            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
225            LinkedListNode<KeySearcher.KeySearcher.ValueKey> listNode;
226
227            if (QuickWatchPresentation.IsVisible)
228            {
229                ((P2PManagerPresentation)QuickWatchPresentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
230                {
231                    ((P2PManagerPresentation)QuickWatchPresentation).txtProgressInPercent.Text = "" + Math.Round(progressInPercent, 2) + "%";
232                    ((P2PManagerPresentation)QuickWatchPresentation).txtTotal.Text = "" + jobsTotalAmount.ToString();
233                    ((P2PManagerPresentation)QuickWatchPresentation).txtInProgress.Text = "" + jobsInProgress.ToString();
234                    ((P2PManagerPresentation)QuickWatchPresentation).txtLeft.Text = "" + new BigInteger((jobsTotalAmount - jobsInProgress - jobsFinished)).ToString();
235                    ((P2PManagerPresentation)QuickWatchPresentation).txtFinished.Text = "" + jobsFinished.ToString();
236
237                    ((P2PManagerPresentation)QuickWatchPresentation).txtTotalWorker.Text = "" + (freeWorkers + busyWorkers);
238                    ((P2PManagerPresentation)QuickWatchPresentation).txtFreeWorker.Text = "" + freeWorkers;
239                    ((P2PManagerPresentation)QuickWatchPresentation).txtBusyWorker.Text = "" + busyWorkers;
240
241                    /* START approximation of end time */
242                    // this value is MinValue until the first job is allocated to a worker
243                    DateTime estimatedDateTime = this.p2pManager.EstimatedEndTime();
244                    if(estimatedDateTime != DateTime.MaxValue)
245                    {
246                        ((P2PManagerPresentation)QuickWatchPresentation).txtEstimatedEndTime.Text = estimatedDateTime.ToString();
247                    }
248                    /* END approximation of end time */
249
250                    ((P2PManagerPresentation)QuickWatchPresentation).entries.Clear();
251                    listNode = globalTop10List.First;
252
253                    int i = 0;
254                    while (listNode != null)
255                    {
256                        i++;
257
258                        ResultEntry entry = new ResultEntry();
259                        entry.Ranking = "" + i;
260                        entry.Value = "" + Math.Round(listNode.Value.value, 3);
261                        entry.Key = listNode.Value.key;
262                        // remove all linebreaks, tabs and so on
263                        string decryptText = enc.GetString(listNode.Value.decryption, 0, this.bytesToUseForDecryption);
264                        decryptText = decryptText.Replace("\n", String.Empty);
265                        decryptText = decryptText.Replace("\t", String.Empty);
266                        decryptText = decryptText.Replace("\r", String.Empty);
267                        entry.Text = decryptText;//enc.GetString(listNode.Value.decryption, 0, this.bytesToUseForDecryption);
268
269                        ((P2PManagerPresentation)QuickWatchPresentation).entries.Add(entry);
270                        listNode = listNode.Next;
271                    }
272                    // to resize the WPF Presentation, so it will fit in the PlugIn-Borders
273                    ((P2PManagerPresentation)QuickWatchPresentation).P2PManagerPresentation_SizeChanged(null, null);
274                }, null);
275            }
276        }
277
278        private void UpdateProgressChunk(BigInteger jobId, System.Windows.Media.Brush color)
279        {
280            // new Progress Chunk - Arnold 2010.02.23
281            if (jobId.LongValue() <= Int32.MaxValue)
282            {
283                int iJobId = (int)jobId.LongValue();
284                if (QuickWatchPresentation.IsVisible)
285                {
286                    ((P2PManagerPresentation)QuickWatchPresentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
287                    {
288                        if (((P2PManagerPresentation)QuickWatchPresentation).PrgChunks[iJobId] != null)
289                            ((P2PManagerPresentation)QuickWatchPresentation).PrgChunks[iJobId] = color;
290                    }, null);
291                }
292            }
293        }
294
295        private void SetProgressChunkJobCount(BigInteger bigInteger)
296        {
297            if (bigInteger.LongValue() <= Int32.MaxValue)
298            {
299                int count = (int)bigInteger.LongValue();
300                if (QuickWatchPresentation.IsVisible)
301                {
302                    ((P2PManagerPresentation)QuickWatchPresentation).Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
303                    {
304                        ((P2PManagerPresentation)QuickWatchPresentation).PrgChunks.JobCount = count;
305                    }, null);
306                }
307            }
308        }
309
310        #endregion
311
312        void settings_OnPluginStatusChanged(IPlugin sender, StatusEventArgs args)
313        {
314            if (OnPluginStatusChanged != null)
315                OnPluginStatusChanged(this, args);
316        }
317
318        void settings_TaskPaneAttributeChanged(ISettings settings, TaskPaneAttributeChangedEventArgs args)
319        {
320            //throw new NotImplementedException();
321        }
322
323        void settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
324        {
325            if (e.PropertyName == "Key")
326            {
327                if (this.EncryptionControl != null)
328                {
329                    KeyPattern checkPattern = new KeyPattern(this.EncryptionControl.getKeyPattern());
330                    if (!checkPattern.testWildcardKey(this.settings.Key))
331                    {
332                        GuiLogMessage("The set Pattern doesn't fit to the encryption plugin connected with this manager!", NotificationLevel.Warning);
333                    }
334                    else
335                        GuiLogMessage("Successfully changed the KeyPattern in the settings.", NotificationLevel.Info);
336                }
337            }
338
339            if (this.p2pControl == null)
340                return;
341            if (e.PropertyName == "BtnUnregister")
342            {
343                if (this.p2pManager != null && this.p2pManager.Started)
344                {
345                    Stop();
346                    //this.p2pManager.Stop(PubSubMessageType.Unregister);
347                    GuiLogMessage("Unregister button pressed, Publisher has stopped!", NotificationLevel.Info);
348                }
349            }
350            if (e.PropertyName == "BtnRegister")
351            {
352                if (this.p2pManager == null || !this.p2pManager.Started)
353                {
354                    this.process(this.EncryptionControl);
355                    GuiLogMessage("Register button pressed, Publisher has been started!", NotificationLevel.Info);
356                }
357            }
358            if (e.PropertyName == "BtnSolutionFound")
359            {
360                if (this.p2pManager != null && this.p2pManager.Started)
361                {
362                    Stop();
363                    //this.p2pManager.Stop(PubSubMessageType.Solution);
364                    GuiLogMessage("TEST: Emulate Solution-Found-message", NotificationLevel.Info);
365                }
366            }
367        }
368
369        public ISettings Settings
370        {
371            set { this.settings = (P2PManager_KeyPatternSettings)value; }
372            get { return this.settings; }
373        }
374
375        // Pre-Execute Method is below this region
376
377        // Execute-Method is below this region
378
379        public void PostExecution()
380        {
381            //throw new NotImplementedException();
382        }
383
384        public void Pause()
385        {
386            //throw new NotImplementedException();
387        }
388
389        public void Stop()
390        {
391
392            if (this.p2pManager != null && this.p2pManager.Started)
393            {
394                this.p2pManager.Stop(PubSubMessageType.Unregister);
395                this.settings.MngStatusChanged(P2PManager_KeyPatternSettings.MngStatus.Neutral);
396                this.p2pManager.OnGuiMessage -= p2pManager_OnGuiMessage;
397                this.p2pManager.OnProcessProgress -= p2pManager_OnProcessProgress;
398                this.p2pManager.OnNewJobAllocated -= p2pManager_OnNewJobAllocated;
399                this.p2pManager.OnNoMoreJobsLeft -= p2pManager_OnNoMoreJobsLeft;
400                this.p2pManager.OnResultReceived -= p2pManager_OnResultReceived;
401                // set Manager to null, so after restarting the Workspace,
402                // a new Distributable stop will be initialized with (maybe)
403                // changed settings
404                this.p2pManager = null;
405            }
406        }
407
408        public void Initialize()
409        {
410        }
411
412        public void Dispose()
413        {
414        }
415
416        #endregion
417
418        public void PreExecution()
419        {
420            // if no P2P Slave PlugIn is connected with this PlugIn --> No execution!
421            if (P2PControl == null)
422            {
423                GuiLogMessage("No P2P_Peer connected with this PlugIn!", NotificationLevel.Error);
424                return;
425            }
426        }
427
428        void p2pManager_OnProcessProgress(double progressInPercent)
429        {
430            ProgressChanged(progressInPercent, 100.0);
431            UpdateQuickWatch(progressInPercent);
432        }
433
434        void p2pManager_OnGuiMessage(string sData, NotificationLevel notificationLevel)
435        {
436            GuiLogMessage(sData, notificationLevel);
437        }
438
439        DistributableKeyPatternJob distributableKeyPatternJob;
440        public void Execute()
441        {
442            if (this.DecryptedData != null)
443            {
444                // TODO: dirty hack because of a missing Initialization vector
445                // it can't be null, because serialization will throw an exception in this case
446                if (this.InitVector == null)
447                {
448                    this.InitVector = new byte[8]{0,0,0,0,0,0,0,0};
449                    GuiLogMessage("Initialization vector not set, so set a standard value - dirty hack!", NotificationLevel.Info);
450                }
451                this.process(this.EncryptionControl);
452            }               
453        }
454
455        private void process(IControlEncryption iControlEncryption)
456        {
457            // if no P2P Slave PlugIn is connected with this PlugIn --> No execution!
458            if (P2PControl == null)
459            {
460                GuiLogMessage("No P2P_Peer connected with this PlugIn!", NotificationLevel.Error);
461                return;
462            }
463            if (iControlEncryption == null)
464            {
465                GuiLogMessage("No Encryption Control connected with this PlugIn", NotificationLevel.Error);
466                return;
467            }
468
469            if (this.p2pManager == null)
470            {
471                byte[] byteEncryptedData = null;
472                CryptoolStream newEncryptedData = new CryptoolStream();
473                try
474                {
475                    newEncryptedData.OpenRead(this.DecryptedData.FileName);
476                    // Convert CryptoolStream to an byte Array and store it in the DHT
477                    if (newEncryptedData.Length > Int32.MaxValue)
478                        throw (new Exception("Encrypted Data are too long for this PlugIn. The maximum size of Data is " + Int32.MaxValue + "!"));
479                    byteEncryptedData = new byte[newEncryptedData.Length];
480                    int k = newEncryptedData.Read(byteEncryptedData, 0, byteEncryptedData.Length);
481                    if (k < byteEncryptedData.Length)
482                        throw (new Exception("Read Data are shorter than byteArrayLen"));
483                }
484                catch (Exception ex)
485                {
486                    throw (new Exception("Fatal error while reading the CryptoolStream. Exception: " + ex.ToString()));
487                }
488                finally
489                {
490                    newEncryptedData.Close();
491                    newEncryptedData.Dispose();
492                }
493                             
494                string pattern = this.encryptionControl.getKeyPattern();
495                KeyPattern kp = new KeyPattern(pattern);
496                if (kp.testWildcardKey(this.settings.Key))
497                {
498                    kp.WildcardKey = this.settings.Key;
499                }
500                else
501                {
502                    GuiLogMessage("The Key Pattern in the settings isn't valid for the given Encryption!", NotificationLevel.Error);
503                    return;
504                }
505
506                // create a new DistributableJob instance
507                distributableKeyPatternJob = new DistributableKeyPatternJob
508                    (kp, this.settings.KeyPatternSize * 10000, byteEncryptedData, this.InitVector);
509
510                //set progress chunk job count
511                SetProgressChunkJobCount(this.distributableKeyPatternJob.TotalAmount);
512
513                this.p2pManager = new P2PManagerBase_NEW(this.P2PControl, distributableKeyPatternJob);
514                this.p2pManager.OnGuiMessage += new P2PPublisherBase.GuiMessage(p2pManager_OnGuiMessage);
515                this.p2pManager.OnProcessProgress += new P2PManagerBase_NEW.ProcessProgress(p2pManager_OnProcessProgress);
516                this.p2pManager.OnNewJobAllocated += new P2PManagerBase_NEW.NewJobAllocated(p2pManager_OnNewJobAllocated);
517                this.p2pManager.OnNoMoreJobsLeft += new P2PManagerBase_NEW.NoMoreJobsLeft(p2pManager_OnNoMoreJobsLeft);
518                this.p2pManager.OnResultReceived += new P2PManagerBase_NEW.ResultReceived(p2pManager_OnResultReceived);
519                this.p2pManager.OnJobCanceled += new P2PManagerBase_NEW.JobCanceled(p2pManager_OnJobCanceled);
520            }
521
522            this.bytesToUseForDecryption = this.settings.BytesToUse;
523
524            this.p2pManager.StartManager(this.settings.TopicName, this.settings.SendAliveMessageInterval * 1000);
525
526            this.settings.MngStatusChanged(P2PManager_KeyPatternSettings.MngStatus.Working);
527        }
528
529        void p2pManager_OnJobCanceled(BigInteger jobId)
530        {
531            UpdateProgressChunk(jobId, System.Windows.Media.Brushes.Red);
532        }
533
534        void p2pManager_OnResultReceived(BigInteger jobId)
535        {
536            UpdateProgressChunk(jobId, System.Windows.Media.Brushes.Green);
537
538            this.settings.MngStatusChanged(P2PManager_KeyPatternSettings.MngStatus.Finished);
539        }
540
541        void p2pManager_OnNoMoreJobsLeft()
542        {
543            this.settings.MngStatusChanged(P2PManager_KeyPatternSettings.MngStatus.Finished);
544        }
545
546        void p2pManager_OnNewJobAllocated(BigInteger jobId)
547        {
548            UpdateProgressChunk(jobId, System.Windows.Media.Brushes.Yellow);
549
550            this.settings.MngStatusChanged(P2PManager_KeyPatternSettings.MngStatus.Working);
551        }
552
553        #region INotifyPropertyChanged Members
554
555        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
556
557        public void OnPropertyChanged(string name)
558        {
559            EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
560        }
561
562        public event PluginProgressChangedEventHandler OnPluginProcessChanged;
563
564        private void ProgressChanged(double value, double max)
565        {
566            EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
567        }
568
569        private void GuiLogMessage(string p, NotificationLevel notificationLevel)
570        {
571            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(p, this, notificationLevel));
572        }
573
574        #endregion
575    }
576
577}
Note: See TracBrowser for help on using the repository browser.