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

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

ProgressChunk stuff for P2PManager QuickWatchPresentation

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