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

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

fixed IntegrateResultsIntoParent in Distributed KeySearcher.
Untestet, but you shouldn't use it anyway at the moment.

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