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

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

Added more Information to the Information-Tag of the
StatisticPresentation.

File size: 72.3 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        private DateTime startDate;
1315        public void SetBeginningDate(DateTime sd)
1316        {
1317            startDate = sd;
1318        }
1319
1320        public void ResetStatistics()
1321        {
1322            statistic = null;
1323            statistic = new Dictionary<string, Dictionary<long, Information>>();
1324            maschinehierarchie = null;
1325            maschinehierarchie = new Dictionary<long, Maschinfo>();
1326        }
1327
1328        public void InitialiseInformationQuickwatch()
1329        {
1330            if (Pattern == null || !Pattern.testWildcardKey(settings.Key) || settings.ChunkSize == 0)
1331            {
1332                return;
1333            }
1334
1335            var keyPattern = Pattern;
1336            var keysPerChunk = Math.Pow(2, settings.ChunkSize);
1337            var keyPatternPool = new KeyPatternPool(keyPattern, new BigInteger(keysPerChunk));
1338
1339            ((QuickWatch) QuickWatchPresentation).StatisticsPresentation.TotalBlocks = keyPatternPool.Length;
1340            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.TotalKeys = new BigInteger(keysPerChunk) * keyPatternPool.Length;   
1341            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Days = DateTime.UtcNow.Subtract(startDate).Days + " Days";
1342            UpdateStatisticsPresentation();
1343        }
1344
1345        internal void IntegrateNewResults(LinkedList<ValueKey> updatedCostList, Dictionary<string, Dictionary<long, Information>> updatedStatistics, string dataIdentifier)
1346        {
1347            foreach (var valueKey in updatedCostList)
1348            {
1349                if (keyQualityHelper.IsBetter(valueKey.value, value_threshold))
1350                {
1351                    valuequeue.Enqueue(valueKey);
1352                }
1353            }
1354
1355            foreach (string avname in updatedStatistics.Keys)
1356            {
1357                //taking the dictionary in this avatarname
1358                Dictionary<long, Information> MaschCount = updatedStatistics[avname];
1359               
1360                //if the avatarname already exists in the statistics
1361                if (statistic.ContainsKey(avname))
1362                {
1363                    foreach (long id in MaschCount.Keys)
1364                    {
1365                        //get the statistic maschcount for this avatarname
1366                        Dictionary<long, Information> statMaschCount = statistic[avname];
1367
1368                        //if the id of the Maschine already exists for this avatarname
1369                        if (statMaschCount.ContainsKey(id))
1370                        {
1371                            if (!initialized || ((MaschCount[id].Count == 1) && (MaschCount.Keys.Count == 1)))
1372                            {
1373                                statMaschCount[id].Count = statMaschCount[id].Count + MaschCount[id].Count;
1374                                statMaschCount[id].Hostname = MaschCount[id].Hostname;
1375                                statMaschCount[id].Date = MaschCount[id].Date;
1376                                statistic[avname] = statMaschCount;
1377                            }
1378                        }
1379                        else
1380                        {
1381                            //add a new id,information value for this avatarname
1382                            statistic[avname].Add(id, MaschCount[id]);
1383                        }
1384                    }
1385                }
1386                else
1387                {
1388                    //add the maschinecount dictionary to this avatarname
1389                    statistic[avname] = MaschCount;
1390                }
1391                statistic[avname] = statistic[avname].OrderByDescending((x) => x.Value.Count).ToDictionary(x => x.Key, y => y.Value);
1392            }
1393            GenerateMaschineStats();
1394            //The following Method can be used to write a local csv file with the User/Maschine Statistics.
1395            //WriteStatistics(dataIdentifier);
1396            UpdateStatisticsPresentation();
1397           
1398            updateToplist();
1399        }
1400
1401        //Update the Statistic Presentation
1402        internal void UpdateStatisticsPresentation()
1403        {
1404            var calcChunks = calculatedChunks();
1405            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Statistics = statistic;
1406            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.MachineHierarchy = maschinehierarchie;
1407            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Days = DateTime.UtcNow.Subtract(startDate).Days + " Days";
1408            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.CalculatedBlocks = calcChunks;
1409            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.CalculatedKeys = calcChunks * (BigInteger)Math.Pow(2, settings.ChunkSize);
1410            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Percent = (double)calcChunks;
1411            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Users = statistic.Keys.Count;
1412            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Machines = maschinehierarchie.Keys.Count;
1413        }
1414
1415        //Write the User Statistics to an external csv-document
1416        internal void WriteStatistics(String dataIdentifier)
1417        {
1418            //using the chosen csv file
1419            String path = settings.CsvPath;
1420
1421            if (path == "")
1422            {
1423                //using the default save folder %APPDATA%\Local\Cryptool2
1424                path = string.Format("{0}\\UserRanking{1}.csv", DirectoryHelper.DirectoryLocal, dataIdentifier);
1425            }
1426
1427            try
1428            {
1429                using (StreamWriter sw = new StreamWriter(path))
1430                {
1431                    sw.WriteLine("Avatarname" + ";" + "MaschineID" + ";" + "Hostname" + ";" + "Pattern Count" + ";" + "Last Update");
1432                    foreach (string avatar in statistic.Keys)
1433                    {
1434                        foreach (long mID in statistic[avatar].Keys)
1435                        {
1436                            sw.WriteLine(avatar + ";" + mID.ToString() + ";" + statistic[avatar][mID].Hostname + ";" + statistic[avatar][mID].Count + ";" + statistic[avatar][mID].Date);
1437                        }
1438                    }
1439                }
1440            }
1441            catch (Exception)
1442            {
1443                GuiLogMessage(string.Format("Failed to write Userstatistics to {0}", path), NotificationLevel.Error);
1444            }
1445
1446            //For testing purpose. This writes the Maschinestatistics to the main folder if no different path was chosen
1447            if (settings.CsvPath == "")
1448            {
1449                try
1450                {
1451                    //using the default save folder %APPDATA%\Local\Cryptool2
1452                    using (StreamWriter sw = new StreamWriter(string.Format("{0}\\Maschine{1}.csv", DirectoryHelper.DirectoryLocal, dataIdentifier)))
1453                    {
1454                        sw.WriteLine("Maschineid" + ";" + "Name" + ";" + "Sum" + ";" + "Users");
1455                        foreach (long mID in maschinehierarchie.Keys)
1456                        {
1457                            sw.WriteLine(mID + ";" + maschinehierarchie[mID].Hostname + ";" + maschinehierarchie[mID].Sum + ";" + maschinehierarchie[mID].Users);
1458                        }
1459                    }
1460                }
1461                catch (Exception)
1462                {
1463                    GuiLogMessage(string.Format("Failed to write Maschinestatistics to {0}", path), NotificationLevel.Error);
1464                }
1465            }             
1466        }
1467
1468        internal void GenerateMaschineStats()
1469        {
1470            maschinehierarchie = null;
1471            maschinehierarchie = new Dictionary<long, Maschinfo>();
1472
1473            foreach (string avatar in statistic.Keys)
1474            {
1475                Dictionary<long, Information> Maschines = statistic[avatar];
1476
1477                //add the maschine count to the maschinestatistics
1478                foreach (long mid in Maschines.Keys)
1479                {
1480                    //if the maschine exists in maschinestatistic add it to the sum
1481                    if (maschinehierarchie.ContainsKey(mid))
1482                    {
1483
1484                        maschinehierarchie[mid].Sum = maschinehierarchie[mid].Sum + Maschines[mid].Count;
1485                        maschinehierarchie[mid].Hostname = Maschines[mid].Hostname;
1486                        maschinehierarchie[mid].Users = maschinehierarchie[mid].Users + avatar + " | ";
1487                    }
1488                    else
1489                    {
1490                        //else make a new entry
1491                        maschinehierarchie.Add(mid, new Maschinfo() { Sum = Maschines[mid].Count , Hostname = Maschines[mid].Hostname , Users = "| " + avatar + " | "});
1492                    }
1493                }
1494            }
1495
1496            maschinehierarchie = maschinehierarchie.OrderByDescending((x) => x.Value.Sum).ToDictionary(x => x.Key, y => y.Value);
1497        }
1498
1499        internal BigInteger calculatedChunks()
1500        {
1501            return maschinehierarchie.Keys.Aggregate<long, BigInteger>(0, (current, mid) => current + maschinehierarchie[mid].Sum);
1502        }
1503
1504        private static DateTime defaultstart = DateTime.MinValue;
1505        private static string username = P2PSettings.Default.PeerName;
1506        private static long maschineid = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
1507        private static string maschinename = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetHostName();
1508
1509        private static void EnhanceUserName(ref ValueKey vk)
1510        {
1511            DateTime chunkstart = DateTime.UtcNow;
1512            username = P2PSettings.Default.PeerName;
1513
1514            //enhance our userdata:
1515            if ((username != null) && (!username.Equals("")))
1516            {
1517                vk.user = username;
1518                vk.time = chunkstart;
1519                vk.maschid = maschineid;
1520                vk.maschname = maschinename;
1521            }
1522            else
1523            {
1524                vk.user = "Unknown";
1525                vk.time = defaultstart;
1526                vk.maschid = 666;
1527                vk.maschname = "Devil";
1528            }
1529        }
1530
1531        internal void updateToplist()
1532        {
1533            LinkedListNode<ValueKey> node;
1534            while (valuequeue.Count != 0)
1535            {
1536                ValueKey vk = (ValueKey)valuequeue.Dequeue();
1537
1538                //if (costList.Contains(vk)) continue;
1539                var result = costList.Where(valueKey => valueKey.key == vk.key);
1540                if (result.Count() > 0)
1541                {
1542                    continue;
1543                }
1544
1545                if (this.costMaster.getRelationOperator() == RelationOperator.LargerThen)
1546                {
1547                    if (vk.value > costList.Last().value)
1548                    {
1549                        node = costList.First;
1550                        while (node != null)
1551                        {
1552                            if (vk.value > node.Value.value)
1553                            {
1554                                if (node == costList.First)
1555                                    Top1 = vk;
1556                                costList.AddBefore(node, vk);
1557                                costList.RemoveLast();
1558                                value_threshold = costList.Last.Value.value;
1559                                break;
1560                            }
1561                            node = node.Next;
1562                        }//end while
1563                    }//end if
1564                }
1565                else
1566                {
1567                    if (vk.value < costList.Last().value)
1568                    {
1569                        node = costList.First;
1570                        while (node != null)
1571                        {
1572                            if (vk.value < node.Value.value)
1573                            {
1574                                if (node == costList.First)
1575                                    Top1 = vk;
1576                                costList.AddBefore(node, vk);
1577                                costList.RemoveLast();
1578                                value_threshold = costList.Last.Value.value;
1579                                break;
1580                            }
1581                            node = node.Next;
1582                        }//end while
1583                    }//end if
1584                }
1585            }
1586        }
1587
1588        #endregion
1589
1590        private void StartThreads(IControlEncryption sender, int bytesToUse, KeyPattern.KeyPattern[] patterns, BigInteger[] doneKeysA, BigInteger[] openCLDoneKeysA, BigInteger[] keycounters, BigInteger[] keysleft, Stack threadStack)
1591        {
1592            //First start the opencl threads:
1593            int i = 0;
1594            foreach (var ds in settings.DeviceSettings)
1595            {
1596                if (ds.useDevice)
1597                {
1598                    WaitCallback worker = new WaitCallback(KeySearcherJob);
1599                    doneKeysA[i] = new BigInteger();
1600                    openCLDoneKeysA[i] = new BigInteger();
1601                    keycounters[i] = new BigInteger();
1602
1603                    ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, openCLDoneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack, ds });
1604                    i++;
1605                }
1606            }
1607
1608            //Then the CPU threads:
1609            for (; i < patterns.Length; i++)
1610            {
1611                WaitCallback worker = new WaitCallback(KeySearcherJob);
1612                doneKeysA[i] = new BigInteger();
1613                openCLDoneKeysA[i] = new BigInteger();
1614                keycounters[i] = new BigInteger();
1615
1616                ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, openCLDoneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack, null });
1617            }
1618        }
1619
1620        private KeyPattern.KeyPattern[] splitPatternForThreads(KeyPattern.KeyPattern pattern)
1621        {
1622            int threads = settings.CoresUsed;
1623            threads += settings.DeviceSettings.Count(x => x.useDevice); 
1624
1625            if (threads < 1)
1626                return null;
1627
1628            KeyPattern.KeyPattern[] patterns = new KeyPattern.KeyPattern[threads];
1629            if (threads > 1)
1630            {
1631                KeyPattern.KeyPattern[] patterns2 = pattern.split();
1632                if (patterns2 == null)
1633                {
1634                    patterns2 = new KeyPattern.KeyPattern[1];
1635                    patterns2[0] = pattern;
1636                    return patterns2;
1637                }
1638                patterns[0] = patterns2[0];
1639                patterns[1] = patterns2[1];
1640                int p = 1;
1641                threads -= 2;
1642
1643                while (threads > 0)
1644                {
1645                    int maxPattern = -1;
1646                    BigInteger max = 0;
1647                    for (int i = 0; i <= p; i++)
1648                        if (patterns[i].size() > max)
1649                        {
1650                            max = patterns[i].size();
1651                            maxPattern = i;
1652                        }
1653                    KeyPattern.KeyPattern[] patterns3 = patterns[maxPattern].split();
1654                    if (patterns3 == null)
1655                    {
1656                        patterns3 = new KeyPattern.KeyPattern[p+1];
1657                        for (int i = 0; i <= p; i++)
1658                            patterns3[i] = patterns[i];
1659                        return patterns3;
1660                    }
1661                    patterns[maxPattern] = patterns3[0];
1662                    patterns[++p] = patterns3[1];
1663                    threads--;
1664                }
1665            }
1666            else
1667                patterns[0] = pattern;
1668            return patterns;
1669        }
1670
1671        private void keyPatternChanged()
1672        {
1673            Pattern = new KeyPattern.KeyPattern(controlMaster.getKeyPattern());
1674        }
1675
1676        #endregion
1677
1678        public void GuiLogMessage(string message, NotificationLevel loglevel)
1679        {
1680            if (OnGuiLogNotificationOccured != null)
1681                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(message, this, loglevel));
1682        }
1683
1684        public void ProgressChanged(double value, double max)
1685        {
1686            if (OnPluginProgressChanged != null)
1687            {
1688                OnPluginProgressChanged(this, new PluginProgressEventArgs(value, max));
1689
1690            }
1691        }
1692
1693        /// <summary>
1694        /// used for delivering the results from the worker threads to the main thread:
1695        /// </summary>
1696        public struct ValueKey
1697        {
1698            public override bool Equals(object obj)
1699            {
1700                if (obj != null && obj is ValueKey && keya != null && ((ValueKey)obj).keya != null)
1701                    return (keya.SequenceEqual(((ValueKey)obj).keya));
1702                else
1703                    return false;
1704            }
1705
1706            public double value;
1707            public String key;
1708            public byte[] decryption;
1709            public byte[] keya;
1710            //---------------------
1711            public string user { get; set; }
1712            public DateTime time { get; set; }
1713            public long maschid { get; set; }
1714            public string maschname { get; set; }
1715            //---------------------
1716        };
1717    }
1718
1719    /// <summary>
1720    /// Represents one entry in our result list
1721    /// </summary>
1722    public class ResultEntry
1723    {
1724        public string Ranking { get; set; }
1725        public string Value { get; set; }
1726        public string Key { get; set; }
1727        public string Text { get; set; }
1728        //-------
1729        public string User { get; set; }
1730        public DateTime Time { get; set; }
1731        public long Maschid { get; set; }
1732        public string Maschname { get; set; }
1733        //-------
1734    }
1735    /// <summary>
1736    /// Represents one entry in our statistic list
1737    /// </summary>
1738    public class Information
1739    {
1740        public int Count { get; set; }
1741        public string Hostname { get; set; }
1742        public DateTime Date { get; set; }
1743    }
1744    /// <summary>
1745    /// Represents one entry in our maschine statistic list
1746    /// </summary>
1747    public class Maschinfo
1748    {
1749        public int Sum { get; set; }
1750        public string Hostname { get; set; }
1751        public string Users { get; set; }
1752    } 
1753}
Note: See TracBrowser for help on using the repository browser.