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

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

added thousands separator for high values in Statistic Information

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