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

Last change on this file since 2500 was 2500, checked in by nolte, 11 years ago

Excluded the write process of the csv file from the key searcher (Not in use right now)

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