source: trunk/CrypPlugins/KeySearcher/KeySearcher.cs @ 2671

Last change on this file since 2671 was 2671, checked in by Sven Rech, 11 years ago

Fixed some stuff in KeySearcher statstics presentation which can lead to XAML crashes.
Also, inserted a lot of try-catch blocks, just to make sure.

File size: 73.0 KB
Line 
1/*                             
2   Copyright 2009 Sven Rech, Nils Kopal, Uni 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.Diagnostics;
19using System.IO;
20using System.Linq;
21using System.Net;
22using System.Text;
23using Cryptool.P2P;
24using Cryptool.P2P.Internal;
25using Cryptool.PluginBase.Analysis;
26using Cryptool.PluginBase;
27using System.Windows.Controls;
28using System.ComponentModel;
29using Cryptool.PluginBase.Control;
30using System.Collections;
31using System.Collections.Generic;
32using System.Threading;
33using System.Windows.Threading;
34using Cryptool.PluginBase.IO;
35using System.Numerics;
36using KeySearcher.Helper;
37using KeySearcher.KeyPattern;
38using KeySearcher.P2P;
39using KeySearcher.P2P.Exceptions;
40using KeySearcherPresentation;
41using KeySearcherPresentation.Controls;
42using KeySearcher.Properties;
43using OpenCLNet;
44
45namespace KeySearcher
46{
47    [Author("Sven Rech, Nils Kopal, Raoul Falk, Dennis Nolte", "rech@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-due.de")]
48    [PluginInfo("KeySearcher.Properties.Resources", false, "pluginName", "pluginToolTip", "KeySearcher/DetailedDescription/Description.xaml", "KeySearcher/Images/icon.png")]
49    public class KeySearcher : IAnalysisMisc
50    {
51        /// <summary>
52        /// used for creating the UserStatistics
53        /// </summary>
54        private Dictionary<string, Dictionary<long, Information>> statistic;
55        private Dictionary<long, Maschinfo> maschinehierarchie;
56        private bool initialized;
57        /// <summary>
58        /// used for creating the TopList
59        /// </summary>
60        private Queue valuequeue;
61        private double value_threshold;
62        /// <summary>
63        /// the thread with the most keys left
64        /// </summary>
65        private int maxThread;
66        private readonly Mutex maxThreadMutex = new Mutex();
67        private ArrayList threadsStopEvents;
68
69        public bool IsKeySearcherRunning;
70        private KeyQualityHelper keyQualityHelper;
71        private readonly P2PQuickWatchPresentation p2PQuickWatchPresentation;
72        private readonly LocalQuickWatchPresentation localQuickWatchPresentation;
73
74        private OpenCLManager oclManager = null;
75        private Mutex openCLPresentationMutex = new Mutex();
76
77        private readonly Stopwatch localBruteForceStopwatch;
78
79        private KeyPattern.KeyPattern pattern;
80        public KeyPattern.KeyPattern Pattern
81        {
82            get
83            {
84                return pattern;
85            }
86            set
87            {
88                pattern = value;
89                if ((settings.Key == null) || ((settings.Key != null) && !pattern.testWildcardKey(settings.Key)))
90                    settings.Key = pattern.giveInputPattern();
91            }
92        }
93
94        internal bool stop;
95
96        internal bool update;
97
98        #region IControlEncryption + IControlCost + InputFields
99
100        #region IControlEncryption Members
101
102        private IControlEncryption controlMaster;
103        [PropertyInfo(Direction.ControlMaster, "Control_Master", "ControlMasterDesc", "")]
104        public IControlEncryption ControlMaster
105        {
106            get { return controlMaster; }
107            set
108            {
109                if (controlMaster != null)
110                {
111                    controlMaster.keyPatternChanged -= keyPatternChanged;
112                }
113                if (value != null)
114                {
115                    Pattern = new KeyPattern.KeyPattern(value.getKeyPattern());
116                    value.keyPatternChanged += keyPatternChanged;
117                    controlMaster = value;
118                    OnPropertyChanged("ControlMaster");
119
120                }
121                else
122                    controlMaster = null;
123            }
124        }
125
126        #endregion
127
128        #region IControlCost Members
129
130        private IControlCost costMaster;
131        [PropertyInfo(Direction.ControlMaster, "Cost_Master", "CostMasterDesc", "")]
132        public IControlCost CostMaster
133        {
134            get { return costMaster; }
135            set
136            {
137                costMaster = value;
138                keyQualityHelper = new KeyQualityHelper(costMaster);
139            }
140        }
141
142        #endregion
143
144        /* BEGIN: following lines are from Arnie - 2010.01.12 */
145        ICryptoolStream csEncryptedData;
146        [PropertyInfo(Direction.InputData, "CS_Encrypted_Data", "csEncryptedDataDesc", "", false, false, QuickWatchFormat.Hex, "")]
147        public virtual ICryptoolStream CSEncryptedData
148        {
149            get { return this.csEncryptedData; }
150            set
151            {
152                if (value != this.csEncryptedData)
153                {
154                    this.csEncryptedData = value;
155                    this.encryptedData = GetByteFromCryptoolStream(value);
156                    OnPropertyChanged("CSEncryptedData");
157                }
158            }
159        }
160
161        byte[] encryptedData;
162        [PropertyInfo(Direction.InputData,"Encrypted_Data","EcryptedDataDesc","",false,false,QuickWatchFormat.Hex,"")]
163        public virtual byte[] EncryptedData
164        {
165            get { return this.encryptedData; }
166            set
167            {
168                if (value != this.encryptedData)
169                {
170                    this.encryptedData = value;
171                    OnPropertyChanged("EncryptedData");
172                }
173            }
174        }
175
176        /// <summary>
177        /// When the Input-Slot changed, set this variable to true, so the new Stream will be transformed to byte[]
178        /// </summary>
179        private byte[] GetByteFromCryptoolStream(ICryptoolStream cryptoolStream)
180        {
181            byte[] encryptedByteData = null;
182
183            if (cryptoolStream != null)
184            {
185                using (CStreamReader reader = cryptoolStream.CreateReader())
186                {
187                    if (reader.Length > Int32.MaxValue)
188                    throw(new Exception("CryptoolStream length is longer than the Int32.MaxValue"));
189
190                    encryptedByteData = reader.ReadFully();
191            }
192            }
193            return encryptedByteData;
194        }
195
196        byte[] initVector;
197        [PropertyInfo(Direction.InputData, "Initialization_Vector", "InitVecDesc", "")]
198        public virtual byte[] InitVector
199        {
200            get { return this.initVector; }
201            set
202            {
203                if (value != this.initVector)
204                {
205                    this.initVector = value;
206                    OnPropertyChanged("InitVector");
207                }
208            }
209        }
210        /* END: Lines above are from Arnie - 2010.01.12 */
211
212        private ValueKey top1ValueKey;
213        public virtual ValueKey Top1
214        {
215            set { top1ValueKey = value; OnPropertyChanged("Top1Message"); OnPropertyChanged("Top1Key"); }
216        }
217
218        [PropertyInfo(Direction.OutputData, "Top1_Message", "top1MesDesc", "")]
219        public virtual byte[] Top1Message
220        {
221            get { return top1ValueKey.decryption; }
222        }
223        [PropertyInfo(Direction.OutputData, "Top1_Key", "Top1KeyDesc", "")]
224        public virtual byte[] Top1Key
225        {
226            get
227            {
228                if (top1ValueKey.key != null)
229                {
230                    return top1ValueKey.keya;
231                }
232                else
233                    return null;
234            }
235        }
236
237        #endregion
238
239        #region IPlugin Members
240
241        public event StatusChangedEventHandler OnPluginStatusChanged;
242
243        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
244
245        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
246
247        private KeySearcherSettings settings;
248        private AutoResetEvent connectResetEvent;
249
250        #region external client variables
251        private CryptoolServer cryptoolServer;
252        private KeySearcherOpenCLCode externalKeySearcherOpenCLCode;
253        private IKeyTranslator externalKeyTranslator;
254        private BigInteger externalKeysProcessed;
255        /// <summary>
256        /// List of clients which connected while there was no job available. Will receive
257        /// a job a soon as one is available.
258        /// </summary>
259        private List<EndPoint> waitingExternalClients = new List<EndPoint>();
260        private Guid currentExternalJobGuid = Guid.NewGuid();
261        private AutoResetEvent waitForExternalClientToFinish = new AutoResetEvent(false);
262        private DateTime assignTime;
263        private bool externalClientJobsAvailable = false;
264        /// <summary>
265        /// id of the client which calculated the last pattern
266        /// </summary>
267        public Int64 ExternaClientId { get; private set; }
268        /// <summary>
269        /// Hostname of the client which calculated the last pattern
270        /// </summary>
271        public String ExternalClientHostname { get; private set; }
272        #endregion
273
274        public KeySearcher()
275        {
276            IsKeySearcherRunning = false;
277           
278            if (OpenCL.NumberOfPlatforms > 0)
279            {
280                oclManager = new OpenCLManager();
281                oclManager.AttemptUseBinaries = false;
282                oclManager.AttemptUseSource = true;
283                oclManager.RequireImageSupport = false;
284                var directoryName = Path.Combine(DirectoryHelper.DirectoryLocalTemp, "KeySearcher");
285                oclManager.BinaryPath = Path.Combine(directoryName, "openclbin");
286                oclManager.BuildOptions = "";
287                oclManager.CreateDefaultContext(0, DeviceType.ALL);
288            }
289
290            settings = new KeySearcherSettings(this, oclManager);
291           
292            QuickWatchPresentation = new QuickWatch();
293            localQuickWatchPresentation = ((QuickWatch) QuickWatchPresentation).LocalQuickWatchPresentation;
294            p2PQuickWatchPresentation = ((QuickWatch)QuickWatchPresentation).P2PQuickWatchPresentation;
295            p2PQuickWatchPresentation.UpdateSettings(this, settings);
296
297            settings.PropertyChanged += SettingsPropertyChanged;
298            ((QuickWatch)QuickWatchPresentation).IsOpenCLEnabled = (settings.DeviceSettings.Count(x => x.useDevice) > 0);
299
300            localBruteForceStopwatch = new Stopwatch();
301        }
302
303        void SettingsPropertyChanged(object sender, PropertyChangedEventArgs e)
304        {
305            p2PQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
306                                                             new Action(UpdateQuickwatchSettings));
307        }
308
309        void UpdateQuickwatchSettings()
310        {
311            ((QuickWatch)QuickWatchPresentation).IsP2PEnabled = settings.UsePeerToPeer;
312            ((QuickWatch)QuickWatchPresentation).IsOpenCLEnabled = (settings.DeviceSettings.Count(x => x.useDevice) > 0);
313            p2PQuickWatchPresentation.UpdateSettings(this, settings);
314        }
315
316        public ISettings Settings
317        {
318            get { return settings; }
319        }
320
321        public UserControl Presentation
322        {
323            get { return QuickWatchPresentation; }
324        }
325
326        public UserControl QuickWatchPresentation
327        {
328            get;
329            private set;
330        }
331
332        public void PreExecution()
333        {
334            update = false;
335        }
336
337        // because Encryption PlugIns were changed radical, the new StartPoint is here - Arnie 2010.01.12
338        public virtual void Execute()
339        {
340            IsKeySearcherRunning = true;
341            localBruteForceStopwatch.Reset();
342
343            //either byte[] CStream input or CryptoolStream Object input
344            if (encryptedData != null || csEncryptedData != null) //to prevent execution on initialization
345            {
346                if (ControlMaster != null)
347                    process(ControlMaster);
348                else
349                {
350                    GuiLogMessage(Resources.You_have_to_connect_the_KeySearcher_with_the_Decryption_Control_, NotificationLevel.Warning);
351                }
352            }
353        }
354
355        public void PostExecution()
356        {
357        }
358
359        public void Pause()
360        {
361        }
362
363        public void Stop()
364        {
365            IsKeySearcherRunning = false;
366            stop = true;
367            waitForExternalClientToFinish.Set();
368        }
369
370        public void Initialize()
371        {
372            settings.Initialize();
373        }
374
375        public void Dispose()
376        {
377        }
378
379        #endregion
380
381        #region INotifyPropertyChanged Members
382
383        public event PropertyChangedEventHandler PropertyChanged;
384
385        public void OnPropertyChanged(string name)
386        {
387            if (PropertyChanged != null)
388            {
389                PropertyChanged(this, new PropertyChangedEventArgs(name));
390            }
391        }
392
393        #endregion
394
395        #region whole KeySearcher functionality
396
397        private class ThreadStackElement
398        {
399            public AutoResetEvent ev;
400            public int threadid;
401        }
402
403        #region code for the worker threads
404
405        private void KeySearcherJob(object param)
406        {
407            AutoResetEvent stopEvent = new AutoResetEvent(false);
408            threadsStopEvents.Add(stopEvent);
409
410            object[] parameters = (object[])param;
411            KeyPattern.KeyPattern[] patterns = (KeyPattern.KeyPattern[])parameters[0];
412            int threadid = (int)parameters[1];
413            BigInteger[] doneKeysArray = (BigInteger[])parameters[2];
414            BigInteger[] openCLDoneKeysArray = (BigInteger[])parameters[3];
415            BigInteger[] keycounterArray = (BigInteger[])parameters[4];
416            BigInteger[] keysLeft = (BigInteger[])parameters[5];
417            IControlEncryption sender = (IControlEncryption)parameters[6];
418            int bytesToUse = (int)parameters[7];
419            Stack threadStack = (Stack)parameters[8];
420            var openCLDeviceSettings = (KeySearcherSettings.OpenCLDeviceSettings)parameters[9];
421
422            KeySearcherOpenCLCode keySearcherOpenCLCode = null;
423            KeySearcherOpenCLSubbatchOptimizer keySearcherOpenCLSubbatchOptimizer = null;
424            if (openCLDeviceSettings != null)
425            {
426                keySearcherOpenCLCode = new KeySearcherOpenCLCode(this, encryptedData, sender, CostMaster, 256 * 256 * 256 * 16);
427                keySearcherOpenCLSubbatchOptimizer = new KeySearcherOpenCLSubbatchOptimizer(openCLDeviceSettings.mode, 
428                        oclManager.CQ[openCLDeviceSettings.index].Device.MaxWorkItemSizes.Aggregate(1, (x, y) => (x * (int)y)) / 8);
429
430                ((QuickWatch)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
431                {
432                    openCLPresentationMutex.WaitOne();
433                    ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.AmountOfDevices++;
434                    openCLPresentationMutex.ReleaseMutex();
435                }, null);
436                Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
437            }
438
439            try
440            {
441                while (patterns[threadid] != null)
442                {
443                    BigInteger size = patterns[threadid].size();
444                    keysLeft[threadid] = size;
445                   
446                    IKeyTranslator keyTranslator = ControlMaster.getKeyTranslator();
447                    keyTranslator.SetKeys(patterns[threadid]);
448
449                    bool finish = false;
450
451                    do
452                    {
453                        //if we are the thread with most keys left, we have to share them:
454                        keyTranslator = ShareKeys(patterns, threadid, keysLeft, keyTranslator, threadStack);
455
456                        if (openCLDeviceSettings == null || !openCLDeviceSettings.useDevice)         //CPU
457                        {
458                            finish = BruteforceCPU(keyTranslator, sender, bytesToUse);
459                        }
460                        else                    //OpenCL
461                        {
462                            try
463                            {
464                                finish = BruteforceOpenCL(keySearcherOpenCLCode, keySearcherOpenCLSubbatchOptimizer, keyTranslator, sender, bytesToUse, parameters);
465                            }
466                            catch (Exception)
467                            {
468                                openCLDeviceSettings.useDevice = false;
469                                ((QuickWatch)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
470                                {
471                                    openCLPresentationMutex.WaitOne();
472                                    ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.AmountOfDevices--;
473                                    openCLPresentationMutex.ReleaseMutex();
474                                }, null);
475                                continue;
476                            }
477                        }
478                       
479                        int progress = keyTranslator.GetProgress();
480
481                        if (openCLDeviceSettings == null)
482                        {
483                            doneKeysArray[threadid] += progress;
484                            keycounterArray[threadid] += progress;
485                            keysLeft[threadid] -= progress;
486                        }
487
488                    } while (!finish && !stop);
489
490                    if (stop)
491                        return;
492
493                    //Let's wait until another thread is willing to share with us:
494                    WaitForNewPattern(patterns, threadid, threadStack);
495                }
496            }
497            finally
498            {
499                sender.Dispose();
500                stopEvent.Set();
501            }
502        }
503
504        private unsafe bool BruteforceOpenCL(KeySearcherOpenCLCode keySearcherOpenCLCode, KeySearcherOpenCLSubbatchOptimizer keySearcherOpenCLSubbatchOptimizer, IKeyTranslator keyTranslator, IControlEncryption sender, int bytesToUse, object[] parameters)
505        {
506            int threadid = (int)parameters[1];
507            BigInteger[] doneKeysArray = (BigInteger[])parameters[2];
508            BigInteger[] openCLDoneKeysArray = (BigInteger[])parameters[3];
509            BigInteger[] keycounterArray = (BigInteger[])parameters[4];
510            BigInteger[] keysLeft = (BigInteger[])parameters[5];
511            var openCLDeviceSettings = (KeySearcherSettings.OpenCLDeviceSettings)parameters[9];
512            try
513            {
514                Kernel bruteforceKernel = keySearcherOpenCLCode.GetBruteforceKernel(oclManager, keyTranslator);
515
516                int deviceIndex = openCLDeviceSettings.index;
517               
518                Mem userKey;
519                var key = keyTranslator.GetKey();
520                fixed (byte* ukp = key)
521                    userKey = oclManager.Context.CreateBuffer(MemFlags.USE_HOST_PTR, key.Length, new IntPtr((void*)ukp));
522
523                int subbatches = keySearcherOpenCLSubbatchOptimizer.GetAmountOfSubbatches(keyTranslator);
524                int subbatchSize = keyTranslator.GetOpenCLBatchSize() / subbatches;
525                ((QuickWatch) QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback) delegate
526                                                                    {
527                                                                        ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.workItems.Content = subbatchSize;
528                                                                    }, null);
529                //GuiLogMessage(string.Format("Now using {0} subbatches", subbatches), NotificationLevel.Info);
530               
531                float[] costArray = new float[subbatchSize];
532                Mem costs = oclManager.Context.CreateBuffer(MemFlags.READ_WRITE, costArray.Length * 4);
533
534                IntPtr[] globalWorkSize = { (IntPtr)subbatchSize, (IntPtr)1, (IntPtr)1 };
535
536                keySearcherOpenCLSubbatchOptimizer.BeginMeasurement();
537
538                try
539                {
540                    for (int i = 0; i < subbatches; i++)
541                    {
542                        bruteforceKernel.SetArg(0, userKey);
543                        bruteforceKernel.SetArg(1, costs);
544                        bruteforceKernel.SetArg(2, i * subbatchSize);
545                        oclManager.CQ[deviceIndex].EnqueueNDRangeKernel(bruteforceKernel, 3, null, globalWorkSize, null);
546                        oclManager.CQ[deviceIndex].EnqueueBarrier();
547
548                        Event e;
549                        fixed (float* costa = costArray)
550                            oclManager.CQ[deviceIndex].EnqueueReadBuffer(costs, true, 0, costArray.Length * 4, new IntPtr((void*)costa), 0, null, out e);
551
552                        e.Wait();
553
554                        checkOpenCLResults(keyTranslator, costArray, sender, bytesToUse, i * subbatchSize);
555
556                        doneKeysArray[threadid] += subbatchSize;
557                        openCLDoneKeysArray[threadid] += subbatchSize;
558                        keycounterArray[threadid] += subbatchSize;
559                        keysLeft[threadid] -= subbatchSize;
560
561                        if (stop)
562                            return false;
563                    }
564
565                    keySearcherOpenCLSubbatchOptimizer.EndMeasurement();
566                }
567                finally
568                {
569                    costs.Dispose();
570                }
571            }
572            catch (Exception ex)
573            {
574                GuiLogMessage(ex.Message, NotificationLevel.Error);
575                GuiLogMessage("Bruteforcing with OpenCL failed! Using CPU instead.", NotificationLevel.Error);
576                throw new Exception("Bruteforcing with OpenCL failed!");
577            }
578
579            return !keyTranslator.NextOpenCLBatch();
580        }
581
582        private void checkOpenCLResults(IKeyTranslator keyTranslator, float[] costArray, IControlEncryption sender, int bytesToUse, int add)
583        {
584            var op = this.costMaster.getRelationOperator();
585            for (int i = 0; i < costArray.Length; i++)
586            {
587                float cost = costArray[i];
588                if (((op == RelationOperator.LargerThen) && (cost > value_threshold))
589                    || (op == RelationOperator.LessThen) && (cost < value_threshold))
590                {
591                    ValueKey valueKey = new ValueKey { value = cost, key = keyTranslator.GetKeyRepresentation(i + add) };
592                    valueKey.keya = keyTranslator.GetKeyFromRepresentation(valueKey.key);
593                    valueKey.decryption = sender.Decrypt(this.encryptedData, valueKey.keya, InitVector, bytesToUse);
594                    EnhanceUserName(ref valueKey);
595                    valuequeue.Enqueue(valueKey);
596                }
597            }
598        }
599
600        private bool BruteforceCPU(IKeyTranslator keyTranslator, IControlEncryption sender, int bytesToUse)
601        {
602            bool finish = false;
603            for (int count = 0; count < 256 * 256; count++)
604            {
605                byte[] keya = keyTranslator.GetKey();
606
607                if (!decryptAndCalculate(sender, bytesToUse, keya, keyTranslator))
608                    throw new Exception("Bruteforcing not possible!");
609
610                finish = !keyTranslator.NextKey();
611                if (finish)
612                    break;
613            }
614            return finish;
615        }
616
617        private IKeyTranslator ShareKeys(KeyPattern.KeyPattern[] patterns, int threadid, BigInteger[] keysLeft, IKeyTranslator keyTranslator, Stack threadStack)
618        {
619            BigInteger size;
620            if (maxThread == threadid && threadStack.Count != 0)
621            {
622                try
623                {
624                    maxThreadMutex.WaitOne();
625                    if (maxThread == threadid && threadStack.Count != 0)
626                    {
627                        KeyPattern.KeyPattern[] split = patterns[threadid].split();
628                        if (split != null)
629                        {
630                            patterns[threadid] = split[0];
631                            keyTranslator = ControlMaster.getKeyTranslator();
632                            keyTranslator.SetKeys(patterns[threadid]);
633
634                            ThreadStackElement elem = (ThreadStackElement)threadStack.Pop();
635                            patterns[elem.threadid] = split[1];
636                            elem.ev.Set();    //wake the other thread up                                   
637                            size = patterns[threadid].size();
638                            keysLeft[threadid] = size;
639                        }
640                        maxThread = -1;
641                    }
642                }
643                finally
644                {
645                    maxThreadMutex.ReleaseMutex();
646                }
647            }
648            return keyTranslator;
649        }
650
651        private void WaitForNewPattern(KeyPattern.KeyPattern[] patterns, int threadid, Stack threadStack)
652        {
653            ThreadStackElement el = new ThreadStackElement();
654            el.ev = new AutoResetEvent(false);
655            el.threadid = threadid;
656            patterns[threadid] = null;
657            threadStack.Push(el);
658            GuiLogMessage("Thread waiting for new keys.", NotificationLevel.Debug);
659            el.ev.WaitOne();
660            if (!stop)
661            {
662                GuiLogMessage("Thread waking up with new keys.", NotificationLevel.Debug);
663            }
664        }
665
666        #region bruteforce methods
667
668        private bool decryptAndCalculate(IControlEncryption sender, int bytesToUse, byte[] keya, IKeyTranslator keyTranslator)
669        {
670            ValueKey valueKey = new ValueKey();
671
672            try
673            {
674                if (this.encryptedData != null && this.encryptedData.Length > 0)
675                {
676                    valueKey.decryption = sender.Decrypt(this.encryptedData, keya, InitVector, bytesToUse);
677                }
678                else
679                {
680                    GuiLogMessage("Can't bruteforce empty input!", NotificationLevel.Error);
681                    return false;
682                }
683            }
684            catch (Exception ex)
685            {
686                GuiLogMessage("Decryption is not possible: " + ex.Message, NotificationLevel.Error);
687                GuiLogMessage("Stack Trace: " + ex.StackTrace, NotificationLevel.Error);
688                return false;
689            }
690
691            try
692            {
693                valueKey.value = CostMaster.calculateCost(valueKey.decryption);
694            }
695            catch (Exception ex)
696            {
697                GuiLogMessage("Cost calculation is not possible: " + ex.Message, NotificationLevel.Error);
698                return false;
699            }
700
701            if (this.costMaster.getRelationOperator() == RelationOperator.LargerThen)
702            {
703                if (valueKey.value > value_threshold)
704                {
705                    valueKey.key = keyTranslator.GetKeyRepresentation();
706                    valueKey.keya = (byte[])keya.Clone();
707                    EnhanceUserName(ref valueKey);
708                    valuequeue.Enqueue(valueKey);
709                }
710            }
711            else
712            {
713                if (valueKey.value < value_threshold)
714                {
715                    valueKey.key = keyTranslator.GetKeyRepresentation();
716                    valueKey.keya = (byte[])keya.Clone();
717                    EnhanceUserName(ref valueKey);
718                    valuequeue.Enqueue(valueKey);
719                }
720            }
721            return true;
722        }
723
724        #endregion
725
726        #endregion
727
728        public void process(IControlEncryption sender)
729        {
730            if (sender == null || costMaster == null)
731                return;
732            if (!Pattern.testWildcardKey(settings.Key))
733            {
734                GuiLogMessage("Wrong key pattern!", NotificationLevel.Error);
735                return;
736            }
737            Pattern.WildcardKey = settings.Key;
738            this.sender = sender;
739
740            bruteforcePattern(Pattern);
741        }
742
743        internal LinkedList<ValueKey> costList = new LinkedList<ValueKey>();
744        private int bytesToUse;
745        private IControlEncryption sender;
746        private DateTime beginBruteforcing;
747        private DistributedBruteForceManager distributedBruteForceManager;
748        private BigInteger keysInThisChunk;
749
750        // main entry point to the KeySearcher
751        private LinkedList<ValueKey> bruteforcePattern(KeyPattern.KeyPattern pattern)
752        {
753            beginBruteforcing = DateTime.Now;
754            GuiLogMessage(Resources.Start_bruteforcing_pattern__ + pattern.getKey() + "'", NotificationLevel.Debug);
755                       
756            int maxInList = 10;
757            costList = new LinkedList<ValueKey>();
758            FillListWithDummies(maxInList, costList);
759            valuequeue = Queue.Synchronized(new Queue());
760
761            statistic = new Dictionary<string, Dictionary<long, Information>>();
762            maschinehierarchie = new Dictionary<long, Maschinfo>();
763            initialized = false;
764
765            stop = false;
766            if (!pattern.testWildcardKey(settings.Key))
767            {
768                GuiLogMessage(Resources.Wrong_key_pattern_, NotificationLevel.Error);
769                return null;
770            }
771
772            // bytesToUse = 0;
773
774            try
775            {
776                bytesToUse = CostMaster.getBytesToUse();
777            }
778            catch (Exception ex)
779            {
780                GuiLogMessage(Resources.Bytes_used_not_valid__ + ex.Message, NotificationLevel.Error);
781                return null;
782            }
783
784            Thread serverThread = null;
785            try
786            {
787                if (settings.UseExternalClient)
788                {
789                    GuiLogMessage(Resources.Waiting_for_external_client_, NotificationLevel.Info);
790                    if (cryptoolServer != null)
791                    {
792
793                    }
794                    cryptoolServer = new CryptoolServer();
795                    waitingExternalClients.Clear();
796                    cryptoolServer.Port = settings.Port;
797                    cryptoolServer.OnJobCompleted += cryptoolServer_OnJobCompleted;
798                    cryptoolServer.OnClientAuth = cryptoolServer_OnClientAuth;
799                    cryptoolServer.OnClientDisconnected += cryptoolServer_OnClientDisconnected;
800                    cryptoolServer.OnClientRequestedJob += cryptoolServer_OnClientRequestedJob;
801                    cryptoolServer.OnErrorLog += cryptoolServer_OnErrorLog;
802                    serverThread = new Thread(new ThreadStart(delegate
803                                                                      {
804                                                                          cryptoolServer.Run();
805                                                                      }));
806                    serverThread.Start();
807                }
808
809                if (settings.UsePeerToPeer)
810                {
811                    BruteForceWithPeerToPeerSystem();
812                    return null;
813                }
814
815                return BruteForceWithLocalSystem(pattern);
816            }
817            finally
818            {
819                if (serverThread != null)
820                {
821                    //stop server here!
822                    cryptoolServer.Shutdown();
823                    cryptoolServer.OnJobCompleted -= cryptoolServer_OnJobCompleted;
824                    cryptoolServer.OnClientAuth = null;
825                    cryptoolServer.OnClientDisconnected -= cryptoolServer_OnClientDisconnected;
826                    cryptoolServer.OnClientRequestedJob -= cryptoolServer_OnClientRequestedJob;
827                    cryptoolServer.OnErrorLog -= cryptoolServer_OnErrorLog;
828                }
829            }
830        }
831
832        private void BruteForceWithPeerToPeerSystem()
833        {
834            if (!update)
835            {
836                GuiLogMessage(Resources.Launching_p2p_based_bruteforce_logic___, NotificationLevel.Info);
837
838                try
839                {
840                    distributedBruteForceManager = new DistributedBruteForceManager(this, pattern, settings,
841                                                                                    keyQualityHelper,
842                                                                                    p2PQuickWatchPresentation);
843                    distributedBruteForceManager.Execute();
844                }
845                catch (NotConnectedException)
846                {
847                    GuiLogMessage(Resources.P2P_not_connected_, NotificationLevel.Error);
848                }
849                catch (KeySearcherStopException)
850                {
851                    update = true;
852                    return;
853                }
854            }
855            else
856            {
857                GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Error);
858                Thread.Sleep(3000);
859            }
860        }
861
862        internal LinkedList<ValueKey> BruteForceWithLocalSystem(KeyPattern.KeyPattern pattern, bool redirectResultsToStatisticsGenerator = false)
863        {
864            ((QuickWatch)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
865            {
866                openCLPresentationMutex.WaitOne();
867                ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.AmountOfDevices = 0;
868                openCLPresentationMutex.ReleaseMutex();
869            }, null);
870
871            if (!redirectResultsToStatisticsGenerator)
872            {
873                localQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(SetStartDate));
874                localBruteForceStopwatch.Start();
875            }
876
877            keysInThisChunk = pattern.size();
878
879            if (settings.UseExternalClient)
880            {
881                GuiLogMessage(Resources.Only_using_external_client_to_bruteforce_, NotificationLevel.Info);
882                lock (this)
883                {
884                    externalKeySearcherOpenCLCode = new KeySearcherOpenCLCode(this, encryptedData, sender, CostMaster,
885                                                                              256*256*256*64);
886                    externalKeysProcessed = 0;
887                    externalKeyTranslator = ControlMaster.getKeyTranslator();
888                    externalKeyTranslator.SetKeys(pattern);
889                    currentExternalJobGuid = Guid.NewGuid();
890                    foreach (var client in waitingExternalClients)
891                    {
892                        AssignJobToClient(client, externalKeySearcherOpenCLCode.CreateOpenCLBruteForceCode(externalKeyTranslator));
893                    }
894                    waitingExternalClients.Clear();
895                    externalClientJobsAvailable = true;
896                }
897                waitForExternalClientToFinish.Reset();
898                waitForExternalClientToFinish.WaitOne();
899                lock (this)
900                {
901                    externalClientJobsAvailable = false;
902                }
903            }
904            else
905            {
906                KeyPattern.KeyPattern[] patterns = splitPatternForThreads(pattern);
907                if (patterns == null || patterns.Length == 0)
908                {
909                    GuiLogMessage(Resources.No_ressources_to_BruteForce_available__Check_the_KeySearcher_settings_, NotificationLevel.Error);
910                    throw new Exception("No ressources to BruteForce available. Check the KeySearcher settings!");
911                }
912
913                BigInteger[] doneKeysA = new BigInteger[patterns.Length];
914                BigInteger[] openCLDoneKeysA = new BigInteger[patterns.Length];
915                BigInteger[] keycounters = new BigInteger[patterns.Length];
916                BigInteger[] keysleft = new BigInteger[patterns.Length];
917                Stack threadStack = Stack.Synchronized(new Stack());
918                threadsStopEvents = ArrayList.Synchronized(new ArrayList());
919                StartThreads(sender, bytesToUse, patterns, doneKeysA, openCLDoneKeysA, keycounters, keysleft, threadStack);
920
921                DateTime lastTime = DateTime.Now;
922
923                //update message:
924                while (!stop)
925                {
926                    Thread.Sleep(2000);
927
928                    updateToplist();
929
930                    #region calculate global counters from local counters
931                    BigInteger keycounter = 0;
932                    BigInteger doneKeys = 0;
933                    BigInteger openCLdoneKeys = 0;
934                    foreach (BigInteger dk in doneKeysA)
935                        doneKeys += dk;
936                    foreach (BigInteger dk in openCLDoneKeysA)
937                        openCLdoneKeys += dk;
938                    foreach (BigInteger kc in keycounters)
939                        keycounter += kc;
940                    #endregion
941
942                    if (keycounter > keysInThisChunk)
943                        GuiLogMessage(Resources.There_must_be_an_error__because_we_bruteforced_too_much_keys___, NotificationLevel.Error);
944
945                    #region determination of the thread with most keys
946                    if (keysInThisChunk - keycounter > 1000)
947                    {
948                        try
949                        {
950                            maxThreadMutex.WaitOne();
951                            BigInteger max = 0;
952                            int id = -1;
953                            for (int i = 0; i < patterns.Length; i++)
954                                if (keysleft[i] != null && keysleft[i] > max)
955                                {
956                                    max = keysleft[i];
957                                    id = i;
958                                }
959                            maxThread = id;
960                        }
961                        finally
962                        {
963                            maxThreadMutex.ReleaseMutex();
964                        }
965                    }
966                    #endregion
967
968                    long keysPerSecond = (long)((long)doneKeys / (DateTime.Now - lastTime).TotalSeconds);
969                    long openCLKeysPerSecond = (long)((long)openCLdoneKeys / (DateTime.Now - lastTime).TotalSeconds);
970                    lastTime = DateTime.Now;
971                    if (redirectResultsToStatisticsGenerator)
972                    {
973                        distributedBruteForceManager.StatisticsGenerator.ShowProgress(costList, keysInThisChunk, keycounter, keysPerSecond);
974                    }
975                    else
976                    {
977                        showProgress(costList, keysInThisChunk, keycounter, keysPerSecond);
978                    }
979
980                    //show OpenCL keys/sec:
981                    var ratio = (double)openCLdoneKeys / (double)doneKeys;
982                    ((QuickWatch)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
983                    {
984                        ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.keysPerSecondOpenCL.Content = String.Format("{0:N}", openCLKeysPerSecond);
985                        ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.keysPerSecondCPU.Content = String.Format("{0:N}", (keysPerSecond - openCLKeysPerSecond));
986                        ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.ratio.Content = String.Format("{0:P}", ratio);
987                    }, null);
988
989
990                    #region set doneKeys to 0
991                    doneKeys = 0;
992                    for (int i = 0; i < doneKeysA.Length; i++)
993                        doneKeysA[i] = 0;
994                    openCLdoneKeys = 0;
995                    for (int i = 0; i < openCLDoneKeysA.Length; i++)
996                        openCLDoneKeysA[i] = 0;
997                    #endregion
998
999                    if (keycounter >= keysInThisChunk)
1000                        break;
1001                }//end while
1002
1003                showProgress(costList, 1, 1, 1);
1004
1005                //wake up all sleeping threads, so they can stop:
1006                while (threadStack.Count != 0)
1007                    ((ThreadStackElement)threadStack.Pop()).ev.Set();
1008
1009                //wait until all threads finished:
1010                foreach (AutoResetEvent stopEvent in threadsStopEvents)
1011                {
1012                    stopEvent.WaitOne();
1013                }
1014
1015                if (!stop && !redirectResultsToStatisticsGenerator)
1016                    ProgressChanged(1, 1);
1017
1018            }
1019
1020            /* BEGIN: For evaluation issues - added by Arnold 2010.03.17 */
1021            TimeSpan bruteforcingTime = DateTime.Now.Subtract(beginBruteforcing);
1022            StringBuilder sbBFTime = new StringBuilder();
1023            if (bruteforcingTime.Days > 0)
1024                sbBFTime.Append(bruteforcingTime.Days.ToString() + Resources._days_);
1025            if (bruteforcingTime.Hours > 0)
1026            {
1027                if (bruteforcingTime.Hours <= 9)
1028                    sbBFTime.Append("0");
1029                sbBFTime.Append(bruteforcingTime.Hours.ToString() + ":");
1030            }
1031            if (bruteforcingTime.Minutes <= 9)
1032                sbBFTime.Append("0");
1033            sbBFTime.Append(bruteforcingTime.Minutes.ToString() + ":");
1034            if (bruteforcingTime.Seconds <= 9)
1035                sbBFTime.Append("0");
1036            sbBFTime.Append(bruteforcingTime.Seconds.ToString() + "-");
1037            if (bruteforcingTime.Milliseconds <= 9)
1038                sbBFTime.Append("00");
1039            if (bruteforcingTime.Milliseconds <= 99)
1040                sbBFTime.Append("0");
1041            sbBFTime.Append(bruteforcingTime.Milliseconds.ToString());
1042
1043            GuiLogMessage(Resources.Ended_bruteforcing_pattern__ + pattern.getKey() + Resources.___Bruteforcing_TimeSpan__ + sbBFTime.ToString(), NotificationLevel.Debug);
1044            /* END: For evaluation issues - added by Arnold 2010.03.17 */
1045
1046            return costList;
1047        }
1048
1049        #region External Client
1050
1051        void cryptoolServer_OnClientDisconnected(EndPoint client)
1052        {
1053            GuiLogMessage(Resources.Client_disconnected_, NotificationLevel.Info);
1054            lock (this)
1055            {
1056                waitingExternalClients.Remove(client);
1057            }
1058        }
1059
1060        bool cryptoolServer_OnClientAuth(System.Net.EndPoint client, string name, string password)
1061        {
1062            if(settings.ExternalClientPassword.Length == 0 ||
1063                settings.ExternalClientPassword == password)
1064            {
1065                GuiLogMessage(string.Format(Resources.Client__0__connected_, name), NotificationLevel.Info);
1066                return true;
1067            }
1068            GuiLogMessage(string.Format(Resources.Client__0__tried_to_auth_with_invalid_password, name), NotificationLevel.Info);
1069            return false;
1070        }
1071
1072        private void AssignJobToClient(EndPoint client, string src)
1073        {
1074            JobInput j = new JobInput();
1075            j.Guid = currentExternalJobGuid.ToString();
1076            j.Src = src;
1077            var key = externalKeyTranslator.GetKey();
1078            j.Key = key;
1079            j.LargerThen = (costMaster.getRelationOperator() == RelationOperator.LargerThen);
1080            j.Size = externalKeyTranslator.GetOpenCLBatchSize();
1081            j.ResultSize = 10;
1082            GuiLogMessage(string.Format(Resources.Assigning_new_job_with_Guid__0__to_client_, j.Guid), NotificationLevel.Info);
1083            cryptoolServer.SendJob(j, client);
1084            assignTime = DateTime.Now;
1085        }
1086
1087        void cryptoolServer_OnJobCompleted(System.Net.EndPoint client, JobResult jr, String clientName)
1088        {
1089            GuiLogMessage(string.Format(Resources.Client_returned_result_of_job_with_Guid__0__, jr.Guid), NotificationLevel.Info);
1090            lock (this)
1091            {
1092                if (!jr.Guid.Equals(currentExternalJobGuid.ToString()))
1093                {
1094                    GuiLogMessage(string.Format(Resources.Received_late_job_result_0_from_client_1, jr.Guid, client), NotificationLevel.Warning);
1095                    return;
1096                }
1097
1098                // Set new guid. Will prevent concurrent clients
1099                // from supplying old results for new chunks.
1100                currentExternalJobGuid = Guid.NewGuid();
1101            }
1102
1103            Int64 id = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID(clientName);
1104            String hostname = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetHostName() + "/" + clientName;
1105
1106            ExternalClientHostname = hostname;
1107            ExternaClientId = id;
1108
1109            //check:
1110            var op = this.costMaster.getRelationOperator();
1111            foreach (var res in jr.ResultList)
1112            {
1113                float cost = res.Key;
1114                if (((op == RelationOperator.LargerThen) && (cost > value_threshold))
1115                    || (op == RelationOperator.LessThen) && (cost < value_threshold))
1116                {
1117                    ValueKey valueKey = new ValueKey { value = cost, key = externalKeyTranslator.GetKeyRepresentation(res.Value) };
1118                    valueKey.keya = externalKeyTranslator.GetKeyFromRepresentation(valueKey.key);
1119                    valueKey.decryption = sender.Decrypt(this.encryptedData, valueKey.keya, InitVector, bytesToUse);
1120
1121                    EnhanceUserName(ref valueKey);
1122
1123                    // special treatment for external client
1124                    valueKey.maschid = id;
1125                    valueKey.maschname = hostname;
1126
1127                    valuequeue.Enqueue(valueKey);
1128                }
1129            }
1130            updateToplist();
1131
1132            //progress:
1133            externalKeyTranslator.NextOpenCLBatch();
1134            int progress = externalKeyTranslator.GetProgress();
1135            externalKeysProcessed += progress;
1136            int keysPerSec = (int)(progress / (DateTime.Now - assignTime).TotalSeconds);
1137
1138            QuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1139                                                                                    {
1140                                                                                        if (!((QuickWatch)QuickWatchPresentation).IsP2PEnabled)
1141                                                                                            showProgress(costList, keysInThisChunk, externalKeysProcessed, keysPerSec);
1142                                                                                        else
1143                                                                                            distributedBruteForceManager.StatisticsGenerator.ShowProgress(costList,
1144                                                                                                             keysInThisChunk, externalKeysProcessed, keysPerSec);
1145                                                                                    }, null);
1146
1147            if (externalKeysProcessed == keysInThisChunk)
1148            {
1149                waitForExternalClientToFinish.Set();
1150                lock (this)
1151                {
1152                    externalClientJobsAvailable = false;
1153                }
1154            }
1155        }
1156
1157        void cryptoolServer_OnErrorLog(string str)
1158        {
1159            GuiLogMessage(str, NotificationLevel.Error);
1160        }
1161
1162        void cryptoolServer_OnClientRequestedJob(EndPoint ipep)
1163        {
1164            lock (this)
1165            {
1166                if(externalClientJobsAvailable)
1167                {
1168                    AssignJobToClient(ipep, externalKeySearcherOpenCLCode.CreateOpenCLBruteForceCode(externalKeyTranslator));
1169                }
1170                else
1171                {
1172                    waitingExternalClients.Add(ipep);
1173                }
1174            }
1175       
1176        }
1177
1178        #endregion
1179
1180        private void SetStartDate()
1181        {
1182            localQuickWatchPresentation.startTime.Content = DateTime.Now.ToString("g", Thread.CurrentThread.CurrentCulture); ;
1183        }
1184
1185        internal void showProgress(LinkedList<ValueKey> costList, BigInteger size, BigInteger keycounter, long keysPerSecond)
1186        {
1187            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
1188
1189            LinkedListNode<ValueKey> linkedListNode;
1190            ProgressChanged((double)keycounter / (double)size, 1.0);
1191
1192            if (localQuickWatchPresentation.IsVisible && keysPerSecond != 0 && !stop)
1193            {
1194                double time = (Math.Pow(10, BigInteger.Log((size - keycounter), 10) - Math.Log10(keysPerSecond)));
1195                TimeSpan timeleft = new TimeSpan(-1);
1196
1197                try
1198                {
1199                    if (time / (24 * 60 * 60) <= int.MaxValue)
1200                    {
1201                        int days = (int)(time / (24 * 60 * 60));
1202                        time = time - (days * 24 * 60 * 60);
1203                        int hours = (int)(time / (60 * 60));
1204                        time = time - (hours * 60 * 60);
1205                        int minutes = (int)(time / 60);
1206                        time = time - (minutes * 60);
1207                        int seconds = (int)time;
1208
1209                        timeleft = new TimeSpan(days, hours, minutes, (int)seconds, 0);
1210                    }
1211                }
1212                catch
1213                {
1214                    //can not calculate time span
1215                }
1216
1217                localQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1218                {
1219                    localQuickWatchPresentation.elapsedTime.Content = localBruteForceStopwatch.Elapsed;
1220                    localQuickWatchPresentation.keysPerSecond.Content = String.Format("{0:0,0}", keysPerSecond);
1221                    if (timeleft != new TimeSpan(-1))
1222                    {
1223                        localQuickWatchPresentation.timeLeft.Content = "" + timeleft;
1224                        try
1225                        {
1226                            localQuickWatchPresentation.endTime.Content = "" + DateTime.Now.Add(timeleft);
1227                        }
1228                        catch
1229                        {
1230                            localQuickWatchPresentation.endTime.Content = Resources.in_a_galaxy_far__far_away___;
1231                        }
1232                    }
1233                    else
1234                    {
1235                        localQuickWatchPresentation.timeLeft.Content = Resources.incalculable____;
1236                        localQuickWatchPresentation.endTime.Content = Resources.in_a_galaxy_far__far_away___;
1237                    }
1238
1239                    localQuickWatchPresentation.entries.Clear();
1240                    linkedListNode = costList.First;
1241
1242                    int i = 0;
1243                    while (linkedListNode != null)
1244                    {
1245                        i++;
1246
1247                        ResultEntry entry = new ResultEntry();
1248                        entry.Ranking = "" + i;
1249                        entry.Value = "" + Math.Round(linkedListNode.Value.value, 3);
1250                        entry.Key = linkedListNode.Value.key;
1251                        entry.Text = enc.GetString(linkedListNode.Value.decryption);
1252
1253                        localQuickWatchPresentation.entries.Add(entry);
1254                        linkedListNode = linkedListNode.Next;
1255                    }
1256                }
1257                , null);
1258            }//end if
1259            else if (!stop && localQuickWatchPresentation.IsVisible)
1260            {
1261
1262                localQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
1263                {
1264                    localQuickWatchPresentation.entries.Clear();
1265                    linkedListNode = costList.First;
1266                    int i = 0;
1267
1268                    while (linkedListNode != null)
1269                    {
1270                        i++;
1271
1272                        ResultEntry entry = new ResultEntry();
1273                        entry.Ranking = "" + i;
1274                        entry.Value = "" + Math.Round(linkedListNode.Value.value, 3);
1275                        entry.Key = linkedListNode.Value.key;
1276                        entry.Text = enc.GetString(linkedListNode.Value.decryption);
1277
1278                        localQuickWatchPresentation.entries.Add(entry);
1279                        linkedListNode = linkedListNode.Next;
1280                    }
1281                }
1282                , null);
1283            }
1284        }
1285
1286        #region For TopList
1287
1288        private void FillListWithDummies(int maxInList, LinkedList<ValueKey> costList)
1289        {
1290            ValueKey valueKey = new ValueKey();
1291            if (this.costMaster.getRelationOperator() == RelationOperator.LessThen)
1292                valueKey.value = double.MaxValue;
1293            else
1294                valueKey.value = double.MinValue;
1295            valueKey.key = Resources.dummykey;
1296            valueKey.decryption = new byte[0];
1297            value_threshold = valueKey.value;
1298            LinkedListNode<ValueKey> node = costList.AddFirst(valueKey);
1299            for (int i = 1; i < maxInList; i++)
1300            {
1301                node = costList.AddAfter(node, valueKey);
1302            }
1303        }
1304
1305        public void SetInitialized(bool ini)
1306        {
1307            this.initialized = ini;
1308        }
1309
1310        public Dictionary<string, Dictionary<long, Information>> GetStatistics()
1311        {
1312            return statistic;
1313        }
1314
1315        private DateTime startDate;
1316        public void SetBeginningDate(DateTime sd)
1317        {
1318            startDate = sd;
1319        }
1320
1321        public void ResetStatistics()
1322        {
1323            statistic = null;
1324            statistic = new Dictionary<string, Dictionary<long, Information>>();
1325            maschinehierarchie = null;
1326            maschinehierarchie = new Dictionary<long, Maschinfo>();
1327        }
1328
1329        public void InitialiseInformationQuickwatch()
1330        {
1331            if (Pattern == null || !Pattern.testWildcardKey(settings.Key) || settings.ChunkSize == 0)
1332            {
1333                return;
1334            }
1335
1336            var keyPattern = Pattern;
1337            var keysPerChunk = Math.Pow(2, settings.ChunkSize);
1338            var keyPatternPool = new KeyPatternPool(keyPattern, new BigInteger(keysPerChunk));
1339
1340            ((QuickWatch) QuickWatchPresentation).StatisticsPresentation.TotalBlocks = keyPatternPool.Length;
1341            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.TotalKeys = new BigInteger(keysPerChunk) * keyPatternPool.Length;   
1342            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Days = DateTime.UtcNow.Subtract(startDate).Days + " Days";
1343            UpdateStatisticsPresentation();
1344        }
1345
1346        internal void IntegrateNewResults(LinkedList<ValueKey> updatedCostList, Dictionary<string, Dictionary<long, Information>> updatedStatistics, string dataIdentifier)
1347        {
1348            foreach (var valueKey in updatedCostList)
1349            {
1350                if (keyQualityHelper.IsBetter(valueKey.value, value_threshold))
1351                {
1352                    valuequeue.Enqueue(valueKey);
1353                }
1354            }
1355
1356            foreach (string avname in updatedStatistics.Keys)
1357            {
1358                //taking the dictionary in this avatarname
1359                Dictionary<long, Information> MaschCount = updatedStatistics[avname];
1360               
1361                //if the avatarname already exists in the statistics
1362                if (statistic.ContainsKey(avname))
1363                {
1364                    foreach (long id in MaschCount.Keys)
1365                    {
1366                        //get the statistic maschcount for this avatarname
1367                        Dictionary<long, Information> statMaschCount = statistic[avname];
1368
1369                        //if the id of the Maschine already exists for this avatarname
1370                        if (statMaschCount.ContainsKey(id))
1371                        {
1372                            if (!initialized || ((MaschCount[id].Count == 1) && (MaschCount.Keys.Count == 1)))
1373                            {
1374                                statMaschCount[id].Count = statMaschCount[id].Count + MaschCount[id].Count;
1375                                statMaschCount[id].Hostname = MaschCount[id].Hostname;
1376                                statMaschCount[id].Date = MaschCount[id].Date;
1377                                statistic[avname] = statMaschCount;
1378                            }
1379                        }
1380                        else
1381                        {
1382                            //add a new id,information value for this avatarname
1383                            statistic[avname].Add(id, MaschCount[id]);
1384                        }
1385                    }
1386                }
1387                else
1388                {
1389                    //add the maschinecount dictionary to this avatarname
1390                    statistic[avname] = MaschCount;
1391                }
1392                statistic[avname] = statistic[avname].OrderByDescending((x) => x.Value.Count).ToDictionary(x => x.Key, y => y.Value);
1393            }
1394            statistic = statistic.OrderByDescending((x) => x.Value.Sum((z) => z.Value.Count)).ToDictionary(x => x.Key,y => y.Value);
1395
1396            GenerateMaschineStats();
1397            //The following Method can be used to write a local csv file with the User/Maschine Statistics.
1398            WriteStatistics(dataIdentifier);
1399            UpdateStatisticsPresentation();
1400           
1401            updateToplist();
1402        }
1403
1404        //Update the Statistic Presentation
1405        internal void UpdateStatisticsPresentation()
1406        {
1407            try
1408            {
1409                var calcChunks = calculatedChunks();
1410                ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Statistics = statistic;
1411                ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.MachineHierarchy = maschinehierarchie;
1412                ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Days = DateTime.UtcNow.Subtract(startDate).Days + " Days";
1413                ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.CalculatedBlocks = calcChunks;
1414                ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.CalculatedKeys = calcChunks * (BigInteger)Math.Pow(2, settings.ChunkSize);
1415                ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Percent = (double)calcChunks;
1416                ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Users = statistic.Keys.Count;
1417                ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Machines = maschinehierarchie.Keys.Count;
1418                if (statistic.Count > 0)
1419                {
1420                    ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.BeeUsers = statistic.Keys.First();
1421                    ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.BeeMachines = maschinehierarchie[maschinehierarchie.Keys.First()].Hostname;
1422                }
1423            }
1424            catch (Exception ex)
1425            {
1426                GuiLogMessage(string.Format("Error when trying to update statistic: {0}", ex.Message), NotificationLevel.Error);
1427            }
1428        }
1429
1430        //Write the User Statistics to an external csv-document
1431        internal void WriteStatistics(String dataIdentifier)
1432        {
1433            //using the chosen csv file
1434            String path = settings.CsvPath;
1435
1436            if (path == "")
1437            {
1438                //using the default save folder %APPDATA%\Local\Cryptool2
1439                path = string.Format("{0}\\UserRanking{1}.csv", DirectoryHelper.DirectoryLocal, dataIdentifier);
1440            }
1441
1442            try
1443            {
1444                using (StreamWriter sw = new StreamWriter(path))
1445                {
1446                    sw.WriteLine("Avatarname" + ";" + "MaschineID" + ";" + "Hostname" + ";" + "Pattern Count" + ";" + "Last Update");
1447                    foreach (string avatar in statistic.Keys)
1448                    {
1449                        foreach (long mID in statistic[avatar].Keys)
1450                        {
1451                            sw.WriteLine(avatar + ";" + mID.ToString() + ";" + statistic[avatar][mID].Hostname + ";" + statistic[avatar][mID].Count + ";" + statistic[avatar][mID].Date);
1452                        }
1453                    }
1454                }
1455            }
1456            catch (Exception)
1457            {
1458                GuiLogMessage(string.Format("Failed to write Userstatistics to {0}", path), NotificationLevel.Error);
1459            }
1460
1461            //For testing purpose. This writes the Maschinestatistics to the main folder if no different path was chosen
1462            if (settings.CsvPath == "")
1463            {
1464                try
1465                {
1466                    //using the default save folder %APPDATA%\Local\Cryptool2
1467                    using (StreamWriter sw = new StreamWriter(string.Format("{0}\\Maschine{1}.csv", DirectoryHelper.DirectoryLocal, dataIdentifier)))
1468                    {
1469                        sw.WriteLine("Maschineid" + ";" + "Name" + ";" + "Sum" + ";" + "Users");
1470                        foreach (long mID in maschinehierarchie.Keys)
1471                        {
1472                            sw.WriteLine(mID + ";" + maschinehierarchie[mID].Hostname + ";" + maschinehierarchie[mID].Sum + ";" + maschinehierarchie[mID].Users);
1473                        }
1474                    }
1475                }
1476                catch (Exception)
1477                {
1478                    GuiLogMessage(string.Format("Failed to write Maschinestatistics to {0}", path), NotificationLevel.Error);
1479                }
1480            }             
1481        }
1482
1483        internal void GenerateMaschineStats()
1484        {
1485            maschinehierarchie = null;
1486            maschinehierarchie = new Dictionary<long, Maschinfo>();
1487
1488            foreach (string avatar in statistic.Keys)
1489            {
1490                Dictionary<long, Information> Maschines = statistic[avatar];
1491
1492                //add the maschine count to the maschinestatistics
1493                foreach (long mid in Maschines.Keys)
1494                {
1495                    //if the maschine exists in maschinestatistic add it to the sum
1496                    if (maschinehierarchie.ContainsKey(mid))
1497                    {
1498
1499                        maschinehierarchie[mid].Sum = maschinehierarchie[mid].Sum + Maschines[mid].Count;
1500                        maschinehierarchie[mid].Hostname = Maschines[mid].Hostname;
1501                        maschinehierarchie[mid].Users = maschinehierarchie[mid].Users + avatar + " | ";
1502                    }
1503                    else
1504                    {
1505                        //else make a new entry
1506                        maschinehierarchie.Add(mid, new Maschinfo() { Sum = Maschines[mid].Count , Hostname = Maschines[mid].Hostname , Users = "| " + avatar + " | "});
1507                    }
1508                }
1509            }
1510
1511            maschinehierarchie = maschinehierarchie.OrderByDescending((x) => x.Value.Sum).ToDictionary(x => x.Key, y => y.Value);
1512        }
1513
1514        internal BigInteger calculatedChunks()
1515        {
1516            return maschinehierarchie.Keys.Aggregate<long, BigInteger>(0, (current, mid) => current + maschinehierarchie[mid].Sum);
1517        }
1518
1519        private static DateTime defaultstart = DateTime.MinValue;
1520        private static string username = P2PSettings.Default.PeerName;
1521        private static long maschineid = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
1522        private static string maschinename = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetHostName();
1523
1524        private static void EnhanceUserName(ref ValueKey vk)
1525        {
1526            DateTime chunkstart = DateTime.UtcNow;
1527            username = P2PSettings.Default.PeerName;
1528
1529            //enhance our userdata:
1530            if ((username != null) && (!username.Equals("")))
1531            {
1532                vk.user = username;
1533                vk.time = chunkstart;
1534                vk.maschid = maschineid;
1535                vk.maschname = maschinename;
1536            }
1537            else
1538            {
1539                vk.user = "Unknown";
1540                vk.time = defaultstart;
1541                vk.maschid = 666;
1542                vk.maschname = "Devil";
1543            }
1544        }
1545
1546        internal void updateToplist()
1547        {
1548            LinkedListNode<ValueKey> node;
1549            while (valuequeue.Count != 0)
1550            {
1551                ValueKey vk = (ValueKey)valuequeue.Dequeue();
1552
1553                //if (costList.Contains(vk)) continue;
1554                var result = costList.Where(valueKey => valueKey.key == vk.key);
1555                if (result.Count() > 0)
1556                {
1557                    continue;
1558                }
1559
1560                if (this.costMaster.getRelationOperator() == RelationOperator.LargerThen)
1561                {
1562                    if (vk.value > costList.Last().value)
1563                    {
1564                        node = costList.First;
1565                        while (node != null)
1566                        {
1567                            if (vk.value > node.Value.value)
1568                            {
1569                                if (node == costList.First)
1570                                    Top1 = vk;
1571                                costList.AddBefore(node, vk);
1572                                costList.RemoveLast();
1573                                value_threshold = costList.Last.Value.value;
1574                                break;
1575                            }
1576                            node = node.Next;
1577                        }//end while
1578                    }//end if
1579                }
1580                else
1581                {
1582                    if (vk.value < costList.Last().value)
1583                    {
1584                        node = costList.First;
1585                        while (node != null)
1586                        {
1587                            if (vk.value < node.Value.value)
1588                            {
1589                                if (node == costList.First)
1590                                    Top1 = vk;
1591                                costList.AddBefore(node, vk);
1592                                costList.RemoveLast();
1593                                value_threshold = costList.Last.Value.value;
1594                                break;
1595                            }
1596                            node = node.Next;
1597                        }//end while
1598                    }//end if
1599                }
1600            }
1601        }
1602
1603        #endregion
1604
1605        private void StartThreads(IControlEncryption sender, int bytesToUse, KeyPattern.KeyPattern[] patterns, BigInteger[] doneKeysA, BigInteger[] openCLDoneKeysA, BigInteger[] keycounters, BigInteger[] keysleft, Stack threadStack)
1606        {
1607            //First start the opencl threads:
1608            int i = 0;
1609            foreach (var ds in settings.DeviceSettings)
1610            {
1611                if (ds.useDevice)
1612                {
1613                    WaitCallback worker = new WaitCallback(KeySearcherJob);
1614                    doneKeysA[i] = new BigInteger();
1615                    openCLDoneKeysA[i] = new BigInteger();
1616                    keycounters[i] = new BigInteger();
1617
1618                    ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, openCLDoneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack, ds });
1619                    i++;
1620                }
1621            }
1622
1623            //Then the CPU threads:
1624            for (; i < patterns.Length; i++)
1625            {
1626                WaitCallback worker = new WaitCallback(KeySearcherJob);
1627                doneKeysA[i] = new BigInteger();
1628                openCLDoneKeysA[i] = new BigInteger();
1629                keycounters[i] = new BigInteger();
1630
1631                ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, openCLDoneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack, null });
1632            }
1633        }
1634
1635        private KeyPattern.KeyPattern[] splitPatternForThreads(KeyPattern.KeyPattern pattern)
1636        {
1637            int threads = settings.CoresUsed;
1638            threads += settings.DeviceSettings.Count(x => x.useDevice); 
1639
1640            if (threads < 1)
1641                return null;
1642
1643            KeyPattern.KeyPattern[] patterns = new KeyPattern.KeyPattern[threads];
1644            if (threads > 1)
1645            {
1646                KeyPattern.KeyPattern[] patterns2 = pattern.split();
1647                if (patterns2 == null)
1648                {
1649                    patterns2 = new KeyPattern.KeyPattern[1];
1650                    patterns2[0] = pattern;
1651                    return patterns2;
1652                }
1653                patterns[0] = patterns2[0];
1654                patterns[1] = patterns2[1];
1655                int p = 1;
1656                threads -= 2;
1657
1658                while (threads > 0)
1659                {
1660                    int maxPattern = -1;
1661                    BigInteger max = 0;
1662                    for (int i = 0; i <= p; i++)
1663                        if (patterns[i].size() > max)
1664                        {
1665                            max = patterns[i].size();
1666                            maxPattern = i;
1667                        }
1668                    KeyPattern.KeyPattern[] patterns3 = patterns[maxPattern].split();
1669                    if (patterns3 == null)
1670                    {
1671                        patterns3 = new KeyPattern.KeyPattern[p+1];
1672                        for (int i = 0; i <= p; i++)
1673                            patterns3[i] = patterns[i];
1674                        return patterns3;
1675                    }
1676                    patterns[maxPattern] = patterns3[0];
1677                    patterns[++p] = patterns3[1];
1678                    threads--;
1679                }
1680            }
1681            else
1682                patterns[0] = pattern;
1683            return patterns;
1684        }
1685
1686        private void keyPatternChanged()
1687        {
1688            Pattern = new KeyPattern.KeyPattern(controlMaster.getKeyPattern());
1689        }
1690
1691        #endregion
1692
1693        public void GuiLogMessage(string message, NotificationLevel loglevel)
1694        {
1695            if (OnGuiLogNotificationOccured != null)
1696                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(message, this, loglevel));
1697        }
1698
1699        public void ProgressChanged(double value, double max)
1700        {
1701            if (OnPluginProgressChanged != null)
1702            {
1703                OnPluginProgressChanged(this, new PluginProgressEventArgs(value, max));
1704
1705            }
1706        }
1707
1708        /// <summary>
1709        /// used for delivering the results from the worker threads to the main thread:
1710        /// </summary>
1711        public struct ValueKey
1712        {
1713            public override bool Equals(object obj)
1714            {
1715                if (obj != null && obj is ValueKey && keya != null && ((ValueKey)obj).keya != null)
1716                    return (keya.SequenceEqual(((ValueKey)obj).keya));
1717                else
1718                    return false;
1719            }
1720
1721            public double value;
1722            public String key;
1723            public byte[] decryption;
1724            public byte[] keya;
1725            //---------------------
1726            public string user { get; set; }
1727            public DateTime time { get; set; }
1728            public long maschid { get; set; }
1729            public string maschname { get; set; }
1730            //---------------------
1731        };
1732    }
1733
1734    /// <summary>
1735    /// Represents one entry in our result list
1736    /// </summary>
1737    public class ResultEntry
1738    {
1739        public string Ranking { get; set; }
1740        public string Value { get; set; }
1741        public string Key { get; set; }
1742        public string Text { get; set; }
1743        //-------
1744        public string User { get; set; }
1745        public DateTime Time { get; set; }
1746        public long Maschid { get; set; }
1747        public string Maschname { get; set; }
1748        //-------
1749    }
1750    /// <summary>
1751    /// Represents one entry in our statistic list
1752    /// </summary>
1753    public class Information
1754    {
1755        public int Count { get; set; }
1756        public string Hostname { get; set; }
1757        public DateTime Date { get; set; }
1758    }
1759    /// <summary>
1760    /// Represents one entry in our maschine statistic list
1761    /// </summary>
1762    public class Maschinfo
1763    {
1764        public int Sum { get; set; }
1765        public string Hostname { get; set; }
1766        public string Users { get; set; }
1767    } 
1768}
Note: See TracBrowser for help on using the repository browser.