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

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

Fixed Top-User logic

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