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

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

Fixed Top-User logic

File size: 72.7 KB
RevLine 
[2010]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;
[1705]18using System.Diagnostics;
[2086]19using System.IO;
[409]20using System.Linq;
[2202]21using System.Net;
[409]22using System.Text;
[1634]23using Cryptool.P2P;
[1698]24using Cryptool.P2P.Internal;
[409]25using Cryptool.PluginBase.Analysis;
26using Cryptool.PluginBase;
27using System.Windows.Controls;
28using System.ComponentModel;
29using Cryptool.PluginBase.Control;
[676]30using System.Collections;
[702]31using System.Collections.Generic;
[744]32using System.Threading;
33using System.Windows.Threading;
[1083]34using Cryptool.PluginBase.IO;
[1448]35using System.Numerics;
[1634]36using KeySearcher.Helper;
[2202]37using KeySearcher.KeyPattern;
[1634]38using KeySearcher.P2P;
[2152]39using KeySearcher.P2P.Exceptions;
[1682]40using KeySearcherPresentation;
41using KeySearcherPresentation.Controls;
[2295]42using KeySearcher.Properties;
[2040]43using OpenCLNet;
[409]44
45namespace KeySearcher
[2233]46{
[1027]47    [Author("Sven Rech, Nils Kopal, Raoul Falk, Dennis Nolte", "rech@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-due.de")]
[2301]48    [PluginInfo("KeySearcher.Properties.Resources", false, "pluginName", "pluginToolTip", "KeySearcher/DetailedDescription/Description.xaml", "KeySearcher/Images/icon.png")]
[676]49    public class KeySearcher : IAnalysisMisc
[409]50    {
[939]51        /// <summary>
[2217]52        /// used for creating the UserStatistics
53        /// </summary>
[2233]54        private Dictionary<string, Dictionary<long, Information>> statistic;
[2292]55        private Dictionary<long, Maschinfo> maschinehierarchie;
[2217]56        private bool initialized;
57        /// <summary>
[939]58        /// used for creating the TopList
59        /// </summary>
[819]60        private Queue valuequeue;
61        private double value_threshold;
[939]62        /// <summary>
63        /// the thread with the most keys left
64        /// </summary>
65        private int maxThread;
[1698]66        private readonly Mutex maxThreadMutex = new Mutex();
[2115]67        private ArrayList threadsStopEvents;
[819]68
[1727]69        public bool IsKeySearcherRunning;
[1682]70        private KeyQualityHelper keyQualityHelper;
[1698]71        private readonly P2PQuickWatchPresentation p2PQuickWatchPresentation;
72        private readonly LocalQuickWatchPresentation localQuickWatchPresentation;
[1634]73
[2040]74        private OpenCLManager oclManager = null;
[2146]75        private Mutex openCLPresentationMutex = new Mutex();
[2040]76
[1705]77        private readonly Stopwatch localBruteForceStopwatch;
78
[1698]79        private KeyPattern.KeyPattern pattern;
[1674]80        public KeyPattern.KeyPattern Pattern
[682]81        {
82            get
83            {
84                return pattern;
85            }
86            set
87            {
88                pattern = value;
[952]89                if ((settings.Key == null) || ((settings.Key != null) && !pattern.testWildcardKey(settings.Key)))
90                    settings.Key = pattern.giveInputPattern();
[682]91            }
92        }
93
[1634]94        internal bool stop;
[409]95
[2152]96        internal bool update;
97
[1083]98        #region IControlEncryption + IControlCost + InputFields
99
[939]100        #region IControlEncryption Members
101
102        private IControlEncryption controlMaster;
[2334]103        [PropertyInfo(Direction.ControlMaster, "Control_Master", "ControlMasterDesc", "")]
[939]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                {
[1674]115                    Pattern = new KeyPattern.KeyPattern(value.getKeyPattern());
[939]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;
[2334]131        [PropertyInfo(Direction.ControlMaster, "Cost_Master", "CostMasterDesc", "")]
[939]132        public IControlCost CostMaster
133        {
134            get { return costMaster; }
135            set
136            {
137                costMaster = value;
[1682]138                keyQualityHelper = new KeyQualityHelper(costMaster);
[939]139            }
140        }
141
142        #endregion
143
[1083]144        /* BEGIN: following lines are from Arnie - 2010.01.12 */
[2529]145        ICryptoolStream csEncryptedData;
[2334]146        [PropertyInfo(Direction.InputData, "CS_Encrypted_Data", "csEncryptedDataDesc", "", false, false, QuickWatchFormat.Hex, "")]
[2529]147        public virtual ICryptoolStream CSEncryptedData
[1083]148        {
[1089]149            get { return this.csEncryptedData; }
[1083]150            set
151            {
[1089]152                if (value != this.csEncryptedData)
[1083]153                {
[1089]154                    this.csEncryptedData = value;
[1162]155                    this.encryptedData = GetByteFromCryptoolStream(value);
[1089]156                    OnPropertyChanged("CSEncryptedData");
157                }
158            }
159        }
160
161        byte[] encryptedData;
[2334]162        [PropertyInfo(Direction.InputData,"Encrypted_Data","EcryptedDataDesc","",false,false,QuickWatchFormat.Hex,"")]
[1089]163        public virtual byte[] EncryptedData
164        {
165            get { return this.encryptedData; }
166            set
167            {
168                if (value != this.encryptedData)
169                {
170                    this.encryptedData = value;
[1083]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>
[2529]179        private byte[] GetByteFromCryptoolStream(ICryptoolStream cryptoolStream)
[1083]180        {
[1162]181            byte[] encryptedByteData = null;
182
183            if (cryptoolStream != null)
[1083]184            {
[2529]185                using (CStreamReader reader = cryptoolStream.CreateReader())
186                {
187                    if (reader.Length > Int32.MaxValue)
[1083]188                    throw(new Exception("CryptoolStream length is longer than the Int32.MaxValue"));
[2529]189
190                    encryptedByteData = reader.ReadFully();
[1083]191            }
[2529]192            }
[1089]193            return encryptedByteData;
[1083]194        }
195
196        byte[] initVector;
[2334]197        [PropertyInfo(Direction.InputData, "Initialization_Vector", "InitVecDesc", "")]
[1089]198        public virtual byte[] InitVector
[1083]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
[1159]212        private ValueKey top1ValueKey;
213        public virtual ValueKey Top1
214        {
215            set { top1ValueKey = value; OnPropertyChanged("Top1Message"); OnPropertyChanged("Top1Key"); }
216        }
217
[2334]218        [PropertyInfo(Direction.OutputData, "Top1_Message", "top1MesDesc", "")]
[1159]219        public virtual byte[] Top1Message
220        {
221            get { return top1ValueKey.decryption; }
222        }
[2334]223        [PropertyInfo(Direction.OutputData, "Top1_Key", "Top1KeyDesc", "")]
[1160]224        public virtual byte[] Top1Key
[1159]225        {
[1160]226            get
227            {
[2010]228                if (top1ValueKey.key != null)
[1166]229                {
[2010]230                    return top1ValueKey.keya;
[1166]231                }
232                else
233                    return null;
[1160]234            }
[1159]235        }
236
[1083]237        #endregion
238
[676]239        #region IPlugin Members
[409]240
[676]241        public event StatusChangedEventHandler OnPluginStatusChanged;
[409]242
[676]243        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
[409]244
[676]245        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
[409]246
[819]247        private KeySearcherSettings settings;
[1682]248        private AutoResetEvent connectResetEvent;
[409]249
[2202]250        #region external client variables
251        private CryptoolServer cryptoolServer;
252        private KeySearcherOpenCLCode externalKeySearcherOpenCLCode;
253        private IKeyTranslator externalKeyTranslator;
[2257]254        private BigInteger externalKeysProcessed;
[2417]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();
[2202]261        private AutoResetEvent waitForExternalClientToFinish = new AutoResetEvent(false);
[2214]262        private DateTime assignTime;
[2417]263        private bool externalClientJobsAvailable = false;
[2495]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; }
[2202]272        #endregion
273
[676]274        public KeySearcher()
275        {
[1727]276            IsKeySearcherRunning = false;
[2183]277           
[2040]278            if (OpenCL.NumberOfPlatforms > 0)
279            {
280                oclManager = new OpenCLManager();
[2086]281                oclManager.AttemptUseBinaries = false;
282                oclManager.AttemptUseSource = true;
283                oclManager.RequireImageSupport = false;
[2092]284                var directoryName = Path.Combine(DirectoryHelper.DirectoryLocalTemp, "KeySearcher");
285                oclManager.BinaryPath = Path.Combine(directoryName, "openclbin");
[2086]286                oclManager.BuildOptions = "";
[2040]287                oclManager.CreateDefaultContext(0, DeviceType.ALL);
288            }
[2183]289
290            settings = new KeySearcherSettings(this, oclManager);
[2171]291           
[1682]292            QuickWatchPresentation = new QuickWatch();
293            localQuickWatchPresentation = ((QuickWatch) QuickWatchPresentation).LocalQuickWatchPresentation;
294            p2PQuickWatchPresentation = ((QuickWatch)QuickWatchPresentation).P2PQuickWatchPresentation;
295            p2PQuickWatchPresentation.UpdateSettings(this, settings);
296
297            settings.PropertyChanged += SettingsPropertyChanged;
[2194]298            ((QuickWatch)QuickWatchPresentation).IsOpenCLEnabled = (settings.DeviceSettings.Count(x => x.useDevice) > 0);
[1705]299
300            localBruteForceStopwatch = new Stopwatch();
[676]301        }
[409]302
[1682]303        void SettingsPropertyChanged(object sender, PropertyChangedEventArgs e)
304        {
305            p2PQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
[2158]306                                                             new Action(UpdateQuickwatchSettings));
[1682]307        }
308
[2158]309        void UpdateQuickwatchSettings()
[1682]310        {
311            ((QuickWatch)QuickWatchPresentation).IsP2PEnabled = settings.UsePeerToPeer;
[2194]312            ((QuickWatch)QuickWatchPresentation).IsOpenCLEnabled = (settings.DeviceSettings.Count(x => x.useDevice) > 0);
[1682]313            p2PQuickWatchPresentation.UpdateSettings(this, settings);
314        }
315
[676]316        public ISettings Settings
317        {
318            get { return settings; }
319        }
[409]320
[676]321        public UserControl Presentation
[415]322        {
[1036]323            get { return QuickWatchPresentation; }
[676]324        }
[409]325
[676]326        public UserControl QuickWatchPresentation
327        {
[744]328            get;
329            private set;
[676]330        }
[409]331
[676]332        public void PreExecution()
333        {
[2152]334            update = false;
[676]335        }
[415]336
[1083]337        // because Encryption PlugIns were changed radical, the new StartPoint is here - Arnie 2010.01.12
[1089]338        public virtual void Execute()
[716]339        {
[1727]340            IsKeySearcherRunning = true;
[2161]341            localBruteForceStopwatch.Reset();
[1727]342
[1089]343            //either byte[] CStream input or CryptoolStream Object input
[1634]344            if (encryptedData != null || csEncryptedData != null) //to prevent execution on initialization
[1083]345            {
[1634]346                if (ControlMaster != null)
347                    process(ControlMaster);
[1083]348                else
349                {
[2295]350                    GuiLogMessage(Resources.You_have_to_connect_the_KeySearcher_with_the_Decryption_Control_, NotificationLevel.Warning);
[1083]351                }
352            }
[715]353        }
354
[939]355        public void PostExecution()
356        {
357        }
358
359        public void Pause()
360        {
361        }
362
363        public void Stop()
364        {
[1727]365            IsKeySearcherRunning = false;
[939]366            stop = true;
[2202]367            waitForExternalClientToFinish.Set();
[939]368        }
369
370        public void Initialize()
371        {
[2040]372            settings.Initialize();
[939]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
[843]397        private class ThreadStackElement
398        {
399            public AutoResetEvent ev;
400            public int threadid;
401        }
402
[908]403        #region code for the worker threads
[939]404
[819]405        private void KeySearcherJob(object param)
406        {
[2115]407            AutoResetEvent stopEvent = new AutoResetEvent(false);
408            threadsStopEvents.Add(stopEvent);
409
[819]410            object[] parameters = (object[])param;
[1674]411            KeyPattern.KeyPattern[] patterns = (KeyPattern.KeyPattern[])parameters[0];
[819]412            int threadid = (int)parameters[1];
[866]413            BigInteger[] doneKeysArray = (BigInteger[])parameters[2];
[2146]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];
[2194]420            var openCLDeviceSettings = (KeySearcherSettings.OpenCLDeviceSettings)parameters[9];
[744]421
[2086]422            KeySearcherOpenCLCode keySearcherOpenCLCode = null;
[2143]423            KeySearcherOpenCLSubbatchOptimizer keySearcherOpenCLSubbatchOptimizer = null;
[2194]424            if (openCLDeviceSettings != null)
[2143]425            {
426                keySearcherOpenCLCode = new KeySearcherOpenCLCode(this, encryptedData, sender, CostMaster, 256 * 256 * 256 * 16);
[2194]427                keySearcherOpenCLSubbatchOptimizer = new KeySearcherOpenCLSubbatchOptimizer(openCLDeviceSettings.mode, 
428                        oclManager.CQ[openCLDeviceSettings.index].Device.MaxWorkItemSizes.Aggregate(1, (x, y) => (x * (int)y)) / 8);
429
[2146]430                ((QuickWatch)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
431                {
432                    openCLPresentationMutex.WaitOne();
433                    ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.AmountOfDevices++;
434                    openCLPresentationMutex.ReleaseMutex();
435                }, null);
[2166]436                Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
[2143]437            }
[2086]438
[819]439            try
[676]440            {
[2086]441                while (patterns[threadid] != null)
[785]442                {
[2086]443                    BigInteger size = patterns[threadid].size();
[843]444                    keysLeft[threadid] = size;
[2086]445                   
[2061]446                    IKeyTranslator keyTranslator = ControlMaster.getKeyTranslator();
[2086]447                    keyTranslator.SetKeys(patterns[threadid]);
[2010]448
449                    bool finish = false;
450
[843]451                    do
[785]452                    {
[865]453                        //if we are the thread with most keys left, we have to share them:
[2086]454                        keyTranslator = ShareKeys(patterns, threadid, keysLeft, keyTranslator, threadStack);
455
[2554]456                        if (openCLDeviceSettings == null || !openCLDeviceSettings.useDevice)         //CPU
[843]457                        {
[2086]458                            finish = BruteforceCPU(keyTranslator, sender, bytesToUse);
459                        }
460                        else                    //OpenCL
461                        {
[1172]462                            try
463                            {
[2143]464                                finish = BruteforceOpenCL(keySearcherOpenCLCode, keySearcherOpenCLSubbatchOptimizer, keyTranslator, sender, bytesToUse, parameters);
[865]465                            }
[2086]466                            catch (Exception)
[1172]467                            {
[2194]468                                openCLDeviceSettings.useDevice = false;
[2146]469                                ((QuickWatch)QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
470                                {
471                                    openCLPresentationMutex.WaitOne();
472                                    ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.AmountOfDevices--;
473                                    openCLPresentationMutex.ReleaseMutex();
474                                }, null);
[2086]475                                continue;
[1172]476                            }
[843]477                        }
[2086]478                       
[2010]479                        int progress = keyTranslator.GetProgress();
[838]480
[2194]481                        if (openCLDeviceSettings == null)
[2143]482                        {
483                            doneKeysArray[threadid] += progress;
484                            keycounterArray[threadid] += progress;
485                            keysLeft[threadid] -= progress;
486                        }
[1932]487
[2010]488                    } while (!finish && !stop);
[1932]489
[865]490                    if (stop)
491                        return;
[838]492
[843]493                    //Let's wait until another thread is willing to share with us:
[2086]494                    WaitForNewPattern(patterns, threadid, threadStack);
[843]495                }
[819]496            }
497            finally
498            {
499                sender.Dispose();
[2115]500                stopEvent.Set();
[819]501            }
502        }
[939]503
[2143]504        private unsafe bool BruteforceOpenCL(KeySearcherOpenCLCode keySearcherOpenCLCode, KeySearcherOpenCLSubbatchOptimizer keySearcherOpenCLSubbatchOptimizer, IKeyTranslator keyTranslator, IControlEncryption sender, int bytesToUse, object[] parameters)
[2086]505        {
[2143]506            int threadid = (int)parameters[1];
507            BigInteger[] doneKeysArray = (BigInteger[])parameters[2];
[2146]508            BigInteger[] openCLDoneKeysArray = (BigInteger[])parameters[3];
509            BigInteger[] keycounterArray = (BigInteger[])parameters[4];
510            BigInteger[] keysLeft = (BigInteger[])parameters[5];
[2194]511            var openCLDeviceSettings = (KeySearcherSettings.OpenCLDeviceSettings)parameters[9];
[2086]512            try
513            {
514                Kernel bruteforceKernel = keySearcherOpenCLCode.GetBruteforceKernel(oclManager, keyTranslator);
[2194]515
516                int deviceIndex = openCLDeviceSettings.index;
[2143]517               
[2086]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
[2143]523                int subbatches = keySearcherOpenCLSubbatchOptimizer.GetAmountOfSubbatches(keyTranslator);
[2146]524                int subbatchSize = keyTranslator.GetOpenCLBatchSize() / subbatches;
525                ((QuickWatch) QuickWatchPresentation).Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback) delegate
526                                                                    {
[2158]527                                                                        ((QuickWatch)QuickWatchPresentation).OpenCLPresentation.workItems.Content = subbatchSize;
[2146]528                                                                    }, null);
[2161]529                //GuiLogMessage(string.Format("Now using {0} subbatches", subbatches), NotificationLevel.Info);
[2146]530               
[2143]531                float[] costArray = new float[subbatchSize];
532                Mem costs = oclManager.Context.CreateBuffer(MemFlags.READ_WRITE, costArray.Length * 4);
[2086]533
[2220]534                IntPtr[] globalWorkSize = { (IntPtr)subbatchSize, (IntPtr)1, (IntPtr)1 };
[2086]535
[2143]536                keySearcherOpenCLSubbatchOptimizer.BeginMeasurement();
[2086]537
[2162]538                try
[2143]539                {
[2162]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);
[2220]545                        oclManager.CQ[deviceIndex].EnqueueNDRangeKernel(bruteforceKernel, 3, null, globalWorkSize, null);
[2162]546                        oclManager.CQ[deviceIndex].EnqueueBarrier();
[2143]547
[2162]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);
[2143]551
[2162]552                        e.Wait();
[2143]553
[2162]554                        checkOpenCLResults(keyTranslator, costArray, sender, bytesToUse, i * subbatchSize);
[2143]555
[2162]556                        doneKeysArray[threadid] += subbatchSize;
557                        openCLDoneKeysArray[threadid] += subbatchSize;
558                        keycounterArray[threadid] += subbatchSize;
559                        keysLeft[threadid] -= subbatchSize;
[2143]560
[2162]561                        if (stop)
562                            return false;
563                    }
[2143]564
[2162]565                    keySearcherOpenCLSubbatchOptimizer.EndMeasurement();
566                }
567                finally
568                {
569                    costs.Dispose();
570                }
[2086]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
[2143]579            return !keyTranslator.NextOpenCLBatch();
580        }
581
582        private void checkOpenCLResults(IKeyTranslator keyTranslator, float[] costArray, IControlEncryption sender, int bytesToUse, int add)
583        {
[2086]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                {
[2143]591                    ValueKey valueKey = new ValueKey { value = cost, key = keyTranslator.GetKeyRepresentation(i + add) };
[2086]592                    valueKey.keya = keyTranslator.GetKeyFromRepresentation(valueKey.key);
593                    valueKey.decryption = sender.Decrypt(this.encryptedData, valueKey.keya, InitVector, bytesToUse);
[2484]594                    EnhanceUserName(ref valueKey);
[2086]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
[939]666        #region bruteforce methods
667
[2061]668        private bool decryptAndCalculate(IControlEncryption sender, int bytesToUse, byte[] keya, IKeyTranslator keyTranslator)
[865]669        {
[2359]670            ValueKey valueKey = new ValueKey();
[2010]671
[865]672            try
673            {
[1162]674                if (this.encryptedData != null && this.encryptedData.Length > 0)
[1089]675                {
[1194]676                    valueKey.decryption = sender.Decrypt(this.encryptedData, keya, InitVector, bytesToUse);
[1089]677                }
678                else
679                {
[1162]680                    GuiLogMessage("Can't bruteforce empty input!", NotificationLevel.Error);
681                    return false;
[1089]682                }
[865]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                {
[2010]705                    valueKey.key = keyTranslator.GetKeyRepresentation();
706                    valueKey.keya = (byte[])keya.Clone();
[2484]707                    EnhanceUserName(ref valueKey);
[2467]708                    valuequeue.Enqueue(valueKey);
[865]709                }
710            }
711            else
712            {
713                if (valueKey.value < value_threshold)
714                {
[2010]715                    valueKey.key = keyTranslator.GetKeyRepresentation();
[2359]716                    valueKey.keya = (byte[])keya.Clone();
[2484]717                    EnhanceUserName(ref valueKey);
[865]718                    valuequeue.Enqueue(valueKey);
719                }
720            }
721            return true;
722        }
723
[908]724        #endregion
725
[939]726        #endregion
727
[819]728        public void process(IControlEncryption sender)
729        {
[908]730            if (sender == null || costMaster == null)
731                return;
[971]732            if (!Pattern.testWildcardKey(settings.Key))
733            {
734                GuiLogMessage("Wrong key pattern!", NotificationLevel.Error);
735                return;
736            }
737            Pattern.WildcardKey = settings.Key;
[1634]738            this.sender = sender;
739
740            bruteforcePattern(Pattern);
[908]741        }
742
[1634]743        internal LinkedList<ValueKey> costList = new LinkedList<ValueKey>();
744        private int bytesToUse;
745        private IControlEncryption sender;
746        private DateTime beginBruteforcing;
[1682]747        private DistributedBruteForceManager distributedBruteForceManager;
[2257]748        private BigInteger keysInThisChunk;
[1634]749
[939]750        // main entry point to the KeySearcher
[1674]751        private LinkedList<ValueKey> bruteforcePattern(KeyPattern.KeyPattern pattern)
[908]752        {
[1634]753            beginBruteforcing = DateTime.Now;
[2295]754            GuiLogMessage(Resources.Start_bruteforcing_pattern__ + pattern.getKey() + "'", NotificationLevel.Debug);
[1244]755                       
[908]756            int maxInList = 10;
[1634]757            costList = new LinkedList<ValueKey>();
[2524]758            FillListWithDummies(maxInList, costList);
[1634]759            valuequeue = Queue.Synchronized(new Queue());
[908]760
[2233]761            statistic = new Dictionary<string, Dictionary<long, Information>>();
[2292]762            maschinehierarchie = new Dictionary<long, Maschinfo>();
[2217]763            initialized = false;
764
[908]765            stop = false;
[952]766            if (!pattern.testWildcardKey(settings.Key))
[819]767            {
[2295]768                GuiLogMessage(Resources.Wrong_key_pattern_, NotificationLevel.Error);
[971]769                return null;
[908]770            }
[819]771
[1682]772            // bytesToUse = 0;
[819]773
[908]774            try
775            {
776                bytesToUse = CostMaster.getBytesToUse();
777            }
778            catch (Exception ex)
779            {
[2295]780                GuiLogMessage(Resources.Bytes_used_not_valid__ + ex.Message, NotificationLevel.Error);
[971]781                return null;
[908]782            }
[819]783
[2202]784            Thread serverThread = null;
785            try
[1634]786            {
[2202]787                if (settings.UseExternalClient)
788                {
[2295]789                    GuiLogMessage(Resources.Waiting_for_external_client_, NotificationLevel.Info);
[2417]790                    if (cryptoolServer != null)
791                    {
792
793                    }
[2202]794                    cryptoolServer = new CryptoolServer();
[2417]795                    waitingExternalClients.Clear();
[2202]796                    cryptoolServer.Port = settings.Port;
[2417]797                    cryptoolServer.OnJobCompleted += cryptoolServer_OnJobCompleted;
798                    cryptoolServer.OnClientAuth = cryptoolServer_OnClientAuth;
[2214]799                    cryptoolServer.OnClientDisconnected += cryptoolServer_OnClientDisconnected;
[2417]800                    cryptoolServer.OnClientRequestedJob += cryptoolServer_OnClientRequestedJob;
801                    cryptoolServer.OnErrorLog += cryptoolServer_OnErrorLog;
[2202]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);
[1634]816            }
[2202]817            finally
818            {
[2445]819                if (serverThread != null)
[2202]820                {
821                    //stop server here!
[2411]822                    cryptoolServer.Shutdown();
[2417]823                    cryptoolServer.OnJobCompleted -= cryptoolServer_OnJobCompleted;
824                    cryptoolServer.OnClientAuth = null;
[2214]825                    cryptoolServer.OnClientDisconnected -= cryptoolServer_OnClientDisconnected;
[2417]826                    cryptoolServer.OnClientRequestedJob -= cryptoolServer_OnClientRequestedJob;
827                    cryptoolServer.OnErrorLog -= cryptoolServer_OnErrorLog;
[2202]828                }
829            }
[1634]830        }
831
832        private void BruteForceWithPeerToPeerSystem()
833        {
[2152]834            if (!update)
835            {
[2295]836                GuiLogMessage(Resources.Launching_p2p_based_bruteforce_logic___, NotificationLevel.Info);
[1698]837
[2152]838                try
839                {
840                    distributedBruteForceManager = new DistributedBruteForceManager(this, pattern, settings,
841                                                                                    keyQualityHelper,
842                                                                                    p2PQuickWatchPresentation);
843                    distributedBruteForceManager.Execute();
844                }
845                catch (NotConnectedException)
846                {
[2295]847                    GuiLogMessage(Resources.P2P_not_connected_, NotificationLevel.Error);
[2152]848                }
849                catch (KeySearcherStopException)
850                {
851                    update = true;
852                    return;
853                }
[1698]854            }
[2152]855            else
[1698]856            {
[2295]857                GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Error);
[2152]858                Thread.Sleep(3000);
[1698]859            }
[1634]860        }
861
[1682]862        internal LinkedList<ValueKey> BruteForceWithLocalSystem(KeyPattern.KeyPattern pattern, bool redirectResultsToStatisticsGenerator = false)
[1634]863        {
[2149]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
[1705]871            if (!redirectResultsToStatisticsGenerator)
872            {
873                localQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(SetStartDate));
874                localBruteForceStopwatch.Start();
875            }
876
[2257]877            keysInThisChunk = pattern.size();
878
[2202]879            if (settings.UseExternalClient)
[2086]880            {
[2295]881                GuiLogMessage(Resources.Only_using_external_client_to_bruteforce_, NotificationLevel.Info);
[2202]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);
[2417]889                    currentExternalJobGuid = Guid.NewGuid();
890                    foreach (var client in waitingExternalClients)
891                    {
892                        AssignJobToClient(client, externalKeySearcherOpenCLCode.CreateOpenCLBruteForceCode(externalKeyTranslator));
893                    }
894                    waitingExternalClients.Clear();
895                    externalClientJobsAvailable = true;
[2202]896                }
897                waitForExternalClientToFinish.Reset();
898                waitForExternalClientToFinish.WaitOne();
[2417]899                lock (this)
900                {
901                    externalClientJobsAvailable = false;
902                }
[2086]903            }
[2202]904            else
905            {
906                KeyPattern.KeyPattern[] patterns = splitPatternForThreads(pattern);
907                if (patterns == null || patterns.Length == 0)
908                {
[2295]909                    GuiLogMessage(Resources.No_ressources_to_BruteForce_available__Check_the_KeySearcher_settings_, NotificationLevel.Error);
[2202]910                    throw new Exception("No ressources to BruteForce available. Check the KeySearcher settings!");
911                }
[908]912
[2202]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);
[908]920
[2202]921                DateTime lastTime = DateTime.Now;
[2009]922
[2202]923                //update message:
924                while (!stop)
925                {
926                    Thread.Sleep(2000);
[908]927
[2202]928                    updateToplist();
[908]929
[2202]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
[908]941
[2257]942                    if (keycounter > keysInThisChunk)
[2295]943                        GuiLogMessage(Resources.There_must_be_an_error__because_we_bruteforced_too_much_keys___, NotificationLevel.Error);
[908]944
[2202]945                    #region determination of the thread with most keys
[2257]946                    if (keysInThisChunk - keycounter > 1000)
[1172]947                    {
[2202]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                        }
[1172]965                    }
[2202]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)
[1172]972                    {
[2257]973                        distributedBruteForceManager.StatisticsGenerator.ShowProgress(costList, keysInThisChunk, keycounter, keysPerSecond);
[1172]974                    }
[2202]975                    else
976                    {
[2257]977                        showProgress(costList, keysInThisChunk, keycounter, keysPerSecond);
[2202]978                    }
[819]979
[2202]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);
[2150]988
[819]989
[2202]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
[908]998
[2257]999                    if (keycounter >= keysInThisChunk)
[2202]1000                        break;
1001                }//end while
[908]1002
[2202]1003                showProgress(costList, 1, 1, 1);
[2042]1004
[2202]1005                //wake up all sleeping threads, so they can stop:
1006                while (threadStack.Count != 0)
1007                    ((ThreadStackElement)threadStack.Pop()).ev.Set();
[908]1008
[2202]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
[2115]1018            }
1019
[1244]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)
[2295]1024                sbBFTime.Append(bruteforcingTime.Days.ToString() + Resources._days_);
[1244]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
[2295]1043            GuiLogMessage(Resources.Ended_bruteforcing_pattern__ + pattern.getKey() + Resources.___Bruteforcing_TimeSpan__ + sbBFTime.ToString(), NotificationLevel.Debug);
[1244]1044            /* END: For evaluation issues - added by Arnold 2010.03.17 */
1045
[971]1046            return costList;
[908]1047        }
1048
[2202]1049        #region External Client
[2061]1050
[2202]1051        void cryptoolServer_OnClientDisconnected(EndPoint client)
1052        {
[2295]1053            GuiLogMessage(Resources.Client_disconnected_, NotificationLevel.Info);
[2417]1054            lock (this)
1055            {
1056                waitingExternalClients.Remove(client);
1057            }
[2202]1058        }
[2061]1059
[2417]1060        bool cryptoolServer_OnClientAuth(System.Net.EndPoint client, string name, string password)
[2202]1061        {
[2417]1062            if(settings.ExternalClientPassword.Length == 0 ||
1063                settings.ExternalClientPassword == password)
[2202]1064            {
[2417]1065                GuiLogMessage(string.Format(Resources.Client__0__connected_, name), NotificationLevel.Info);
1066                return true;
[2202]1067            }
[2417]1068            GuiLogMessage(string.Format(Resources.Client__0__tried_to_auth_with_invalid_password, name), NotificationLevel.Info);
1069            return false;
[2202]1070        }
1071
1072        private void AssignJobToClient(EndPoint client, string src)
1073        {
1074            JobInput j = new JobInput();
[2417]1075            j.Guid = currentExternalJobGuid.ToString();
[2202]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;
[2295]1082            GuiLogMessage(string.Format(Resources.Assigning_new_job_with_Guid__0__to_client_, j.Guid), NotificationLevel.Info);
[2202]1083            cryptoolServer.SendJob(j, client);
[2214]1084            assignTime = DateTime.Now;
[2202]1085        }
1086
[2495]1087        void cryptoolServer_OnJobCompleted(System.Net.EndPoint client, JobResult jr, String clientName)
[2202]1088        {
[2295]1089            GuiLogMessage(string.Format(Resources.Client_returned_result_of_job_with_Guid__0__, jr.Guid), NotificationLevel.Info);
[2417]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            }
[2495]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
[2202]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);
[2428]1120
[2484]1121                    EnhanceUserName(ref valueKey);
[2495]1122
1123                    // special treatment for external client
1124                    valueKey.maschid = id;
1125                    valueKey.maschname = hostname;
1126
[2202]1127                    valuequeue.Enqueue(valueKey);
1128                }
1129            }
1130            updateToplist();
1131
1132            //progress:
[2214]1133            externalKeyTranslator.NextOpenCLBatch();
1134            int progress = externalKeyTranslator.GetProgress();
1135            externalKeysProcessed += progress;
1136            int keysPerSec = (int)(progress / (DateTime.Now - assignTime).TotalSeconds);
[2202]1137
[2257]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
[2417]1147            if (externalKeysProcessed == keysInThisChunk)
[2202]1148            {
[2417]1149                waitForExternalClientToFinish.Set();
1150                lock (this)
1151                {
1152                    externalClientJobsAvailable = false;
1153                }
[2202]1154            }
[2417]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)
[2202]1165            {
[2417]1166                if(externalClientJobsAvailable)
1167                {
1168                    AssignJobToClient(ipep, externalKeySearcherOpenCLCode.CreateOpenCLBruteForceCode(externalKeyTranslator));
1169                }
1170                else
1171                {
1172                    waitingExternalClients.Add(ipep);
1173                }
[2202]1174            }
[2417]1175       
[2202]1176        }
1177
1178        #endregion
1179
[1705]1180        private void SetStartDate()
1181        {
1182            localQuickWatchPresentation.startTime.Content = DateTime.Now.ToString("g", Thread.CurrentThread.CurrentCulture); ;
1183        }
1184
[2150]1185        internal void showProgress(LinkedList<ValueKey> costList, BigInteger size, BigInteger keycounter, long keysPerSecond)
[908]1186        {
[1030]1187            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
1188
[908]1189            LinkedListNode<ValueKey> linkedListNode;
[2146]1190            ProgressChanged((double)keycounter / (double)size, 1.0);
[908]1191
[2009]1192            if (localQuickWatchPresentation.IsVisible && keysPerSecond != 0 && !stop)
[908]1193            {
[2009]1194                double time = (Math.Pow(10, BigInteger.Log((size - keycounter), 10) - Math.Log10(keysPerSecond)));
[908]1195                TimeSpan timeleft = new TimeSpan(-1);
1196
1197                try
[843]1198                {
[908]1199                    if (time / (24 * 60 * 60) <= int.MaxValue)
[843]1200                    {
[908]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);
[843]1210                    }
1211                }
[908]1212                catch
[819]1213                {
[908]1214                    //can not calculate time span
[819]1215                }
[908]1216
[1682]1217                localQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
[819]1218                {
[1705]1219                    localQuickWatchPresentation.elapsedTime.Content = localBruteForceStopwatch.Elapsed;
[2189]1220                    localQuickWatchPresentation.keysPerSecond.Content = String.Format("{0:0,0}", keysPerSecond);
[908]1221                    if (timeleft != new TimeSpan(-1))
[819]1222                    {
[1705]1223                        localQuickWatchPresentation.timeLeft.Content = "" + timeleft;
[908]1224                        try
[702]1225                        {
[1705]1226                            localQuickWatchPresentation.endTime.Content = "" + DateTime.Now.Add(timeleft);
[819]1227                        }
[908]1228                        catch
[819]1229                        {
[2295]1230                            localQuickWatchPresentation.endTime.Content = Resources.in_a_galaxy_far__far_away___;
[819]1231                        }
[702]1232                    }
[908]1233                    else
1234                    {
[2295]1235                        localQuickWatchPresentation.timeLeft.Content = Resources.incalculable____;
1236                        localQuickWatchPresentation.endTime.Content = Resources.in_a_galaxy_far__far_away___;
[908]1237                    }
[819]1238
[1682]1239                    localQuickWatchPresentation.entries.Clear();
[908]1240                    linkedListNode = costList.First;
[2146]1241
[908]1242                    int i = 0;
1243                    while (linkedListNode != null)
1244                    {
1245                        i++;
[1030]1246
1247                        ResultEntry entry = new ResultEntry();
1248                        entry.Ranking = "" + i;
[2146]1249                        entry.Value = "" + Math.Round(linkedListNode.Value.value, 3);
[1030]1250                        entry.Key = linkedListNode.Value.key;
1251                        entry.Text = enc.GetString(linkedListNode.Value.decryption);
1252
[1682]1253                        localQuickWatchPresentation.entries.Add(entry);
[908]1254                        linkedListNode = linkedListNode.Next;
1255                    }
1256                }
1257                , null);
1258            }//end if
[1682]1259            else if (!stop && localQuickWatchPresentation.IsVisible)
[908]1260            {
1261
[1682]1262                localQuickWatchPresentation.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
[908]1263                {
[1682]1264                    localQuickWatchPresentation.entries.Clear();
[2146]1265                    linkedListNode = costList.First;
[908]1266                    int i = 0;
[1030]1267
[908]1268                    while (linkedListNode != null)
[843]1269                    {
[908]1270                        i++;
[1030]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
[1682]1278                        localQuickWatchPresentation.entries.Add(entry);
[908]1279                        linkedListNode = linkedListNode.Next;
[843]1280                    }
[908]1281                }
1282                , null);
1283            }
1284        }
[843]1285
[939]1286        #region For TopList
1287
[2524]1288        private void FillListWithDummies(int maxInList, LinkedList<ValueKey> costList)
[939]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;
[2295]1295            valueKey.key = Resources.dummykey;
[939]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
[2217]1305        public void SetInitialized(bool ini)
[908]1306        {
[2217]1307            this.initialized = ini;
1308        }
[2292]1309
[2262]1310        public Dictionary<string, Dictionary<long, Information>> GetStatistics()
1311        {
1312            return statistic;
1313        }
[2292]1314
[2527]1315        private DateTime startDate;
1316        public void SetBeginningDate(DateTime sd)
1317        {
1318            startDate = sd;
1319        }
1320
[2283]1321        public void ResetStatistics()
1322        {
1323            statistic = null;
1324            statistic = new Dictionary<string, Dictionary<long, Information>>();
[2292]1325            maschinehierarchie = null;
1326            maschinehierarchie = new Dictionary<long, Maschinfo>();
[2283]1327        }
[2217]1328
[2527]1329        public void InitialiseInformationQuickwatch()
1330        {
1331            if (Pattern == null || !Pattern.testWildcardKey(settings.Key) || settings.ChunkSize == 0)
1332            {
1333                return;
1334            }
1335
1336            var keyPattern = Pattern;
1337            var keysPerChunk = Math.Pow(2, settings.ChunkSize);
1338            var keyPatternPool = new KeyPatternPool(keyPattern, new BigInteger(keysPerChunk));
1339
1340            ((QuickWatch) QuickWatchPresentation).StatisticsPresentation.TotalBlocks = keyPatternPool.Length;
1341            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.TotalKeys = new BigInteger(keysPerChunk) * keyPatternPool.Length;   
1342            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Days = DateTime.UtcNow.Subtract(startDate).Days + " Days";
1343            UpdateStatisticsPresentation();
1344        }
1345
[2233]1346        internal void IntegrateNewResults(LinkedList<ValueKey> updatedCostList, Dictionary<string, Dictionary<long, Information>> updatedStatistics, string dataIdentifier)
[2217]1347        {
[1682]1348            foreach (var valueKey in updatedCostList)
[1634]1349            {
[1682]1350                if (keyQualityHelper.IsBetter(valueKey.value, value_threshold))
[1634]1351                {
1352                    valuequeue.Enqueue(valueKey);
1353                }
1354            }
1355
[2217]1356            foreach (string avname in updatedStatistics.Keys)
1357            {
1358                //taking the dictionary in this avatarname
[2233]1359                Dictionary<long, Information> MaschCount = updatedStatistics[avname];
[2285]1360               
[2217]1361                //if the avatarname already exists in the statistics
1362                if (statistic.ContainsKey(avname))
1363                {
1364                    foreach (long id in MaschCount.Keys)
1365                    {
1366                        //get the statistic maschcount for this avatarname
[2233]1367                        Dictionary<long, Information> statMaschCount = statistic[avname];
[2246]1368
[2217]1369                        //if the id of the Maschine already exists for this avatarname
[2244]1370                        if (statMaschCount.ContainsKey(id))
[2217]1371                        {
[2233]1372                            if (!initialized || ((MaschCount[id].Count == 1) && (MaschCount.Keys.Count == 1)))
[2217]1373                            {
[2246]1374                                statMaschCount[id].Count = statMaschCount[id].Count + MaschCount[id].Count;
1375                                statMaschCount[id].Hostname = MaschCount[id].Hostname;
1376                                statMaschCount[id].Date = MaschCount[id].Date;
[2217]1377                                statistic[avname] = statMaschCount;
1378                            }
1379                        }
1380                        else
1381                        {
[2242]1382                            //add a new id,information value for this avatarname
[2246]1383                            statistic[avname].Add(id, MaschCount[id]);
[2217]1384                        }
1385                    }
1386                }
1387                else
1388                {
1389                    //add the maschinecount dictionary to this avatarname
1390                    statistic[avname] = MaschCount;
1391                }
[2285]1392                statistic[avname] = statistic[avname].OrderByDescending((x) => x.Value.Count).ToDictionary(x => x.Key, y => y.Value);
[2292]1393            }
[2612]1394            statistic = statistic.OrderByDescending((x) => x.Value.Sum((z) => z.Value.Count)).ToDictionary(x => x.Key,y => y.Value);
1395
[2292]1396            GenerateMaschineStats();
[2500]1397            //The following Method can be used to write a local csv file with the User/Maschine Statistics.
[2612]1398            WriteStatistics(dataIdentifier);
[2527]1399            UpdateStatisticsPresentation();
[2500]1400           
[2527]1401            updateToplist();
1402        }
1403
1404        //Update the Statistic Presentation
1405        internal void UpdateStatisticsPresentation()
1406        {
1407            var calcChunks = calculatedChunks();
[2293]1408            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Statistics = statistic;
1409            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.MachineHierarchy = maschinehierarchie;
[2527]1410            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Days = DateTime.UtcNow.Subtract(startDate).Days + " Days";
1411            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.CalculatedBlocks = calcChunks;
1412            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.CalculatedKeys = calcChunks * (BigInteger)Math.Pow(2, settings.ChunkSize);
1413            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Percent = (double)calcChunks;
1414            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Users = statistic.Keys.Count;
1415            ((QuickWatch)QuickWatchPresentation).StatisticsPresentation.Machines = maschinehierarchie.Keys.Count;
[2556]1416            if (statistic.Count > 0)
1417            {
1418                ((QuickWatch) QuickWatchPresentation).StatisticsPresentation.BeeUsers = statistic.Keys.First();
1419                ((QuickWatch) QuickWatchPresentation).StatisticsPresentation.BeeMachines = maschinehierarchie[maschinehierarchie.Keys.First()].Hostname;
1420            }
[1634]1421        }
1422
[2217]1423        //Write the User Statistics to an external csv-document
1424        internal void WriteStatistics(String dataIdentifier)
1425        {
[2411]1426            //using the chosen csv file
1427            String path = settings.CsvPath;
1428
1429            if (path == "")
[2217]1430            {
[2263]1431                //using the default save folder %APPDATA%\Local\Cryptool2
[2411]1432                path = string.Format("{0}\\UserRanking{1}.csv", DirectoryHelper.DirectoryLocal, dataIdentifier);
[2217]1433            }
[2411]1434
1435            try
[2263]1436            {
[2411]1437                using (StreamWriter sw = new StreamWriter(path))
[2263]1438                {
1439                    sw.WriteLine("Avatarname" + ";" + "MaschineID" + ";" + "Hostname" + ";" + "Pattern Count" + ";" + "Last Update");
1440                    foreach (string avatar in statistic.Keys)
1441                    {
1442                        foreach (long mID in statistic[avatar].Keys)
1443                        {
1444                            sw.WriteLine(avatar + ";" + mID.ToString() + ";" + statistic[avatar][mID].Hostname + ";" + statistic[avatar][mID].Count + ";" + statistic[avatar][mID].Date);
1445                        }
1446                    }
1447                }
1448            }
[2411]1449            catch (Exception)
1450            {
[2500]1451                GuiLogMessage(string.Format("Failed to write Userstatistics to {0}", path), NotificationLevel.Error);
[2411]1452            }
[2292]1453
[2500]1454            //For testing purpose. This writes the Maschinestatistics to the main folder if no different path was chosen
[2292]1455            if (settings.CsvPath == "")
1456            {
[2500]1457                try
[2292]1458                {
[2500]1459                    //using the default save folder %APPDATA%\Local\Cryptool2
1460                    using (StreamWriter sw = new StreamWriter(string.Format("{0}\\Maschine{1}.csv", DirectoryHelper.DirectoryLocal, dataIdentifier)))
1461                    {
1462                        sw.WriteLine("Maschineid" + ";" + "Name" + ";" + "Sum" + ";" + "Users");
[2292]1463                        foreach (long mID in maschinehierarchie.Keys)
1464                        {
1465                            sw.WriteLine(mID + ";" + maschinehierarchie[mID].Hostname + ";" + maschinehierarchie[mID].Sum + ";" + maschinehierarchie[mID].Users);
1466                        }
[2500]1467                    }
[2292]1468                }
[2500]1469                catch (Exception)
1470                {
1471                    GuiLogMessage(string.Format("Failed to write Maschinestatistics to {0}", path), NotificationLevel.Error);
1472                }
1473            }             
[2217]1474        }
1475
[2292]1476        internal void GenerateMaschineStats()
1477        {
1478            maschinehierarchie = null;
1479            maschinehierarchie = new Dictionary<long, Maschinfo>();
1480
1481            foreach (string avatar in statistic.Keys)
1482            {
1483                Dictionary<long, Information> Maschines = statistic[avatar];
1484
1485                //add the maschine count to the maschinestatistics
1486                foreach (long mid in Maschines.Keys)
1487                {
1488                    //if the maschine exists in maschinestatistic add it to the sum
1489                    if (maschinehierarchie.ContainsKey(mid))
1490                    {
1491
1492                        maschinehierarchie[mid].Sum = maschinehierarchie[mid].Sum + Maschines[mid].Count;
1493                        maschinehierarchie[mid].Hostname = Maschines[mid].Hostname;
[2304]1494                        maschinehierarchie[mid].Users = maschinehierarchie[mid].Users + avatar + " | ";
[2292]1495                    }
1496                    else
1497                    {
1498                        //else make a new entry
[2304]1499                        maschinehierarchie.Add(mid, new Maschinfo() { Sum = Maschines[mid].Count , Hostname = Maschines[mid].Hostname , Users = "| " + avatar + " | "});
[2292]1500                    }
1501                }
1502            }
1503
1504            maschinehierarchie = maschinehierarchie.OrderByDescending((x) => x.Value.Sum).ToDictionary(x => x.Key, y => y.Value);
1505        }
1506
[2527]1507        internal BigInteger calculatedChunks()
1508        {
1509            return maschinehierarchie.Keys.Aggregate<long, BigInteger>(0, (current, mid) => current + maschinehierarchie[mid].Sum);
1510        }
1511
[2476]1512        private static DateTime defaultstart = DateTime.MinValue;
1513        private static string username = P2PSettings.Default.PeerName;
1514        private static long maschineid = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
1515        private static string maschinename = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetHostName();
1516
[2484]1517        private static void EnhanceUserName(ref ValueKey vk)
[1634]1518        {
[2456]1519            DateTime chunkstart = DateTime.UtcNow;
[2491]1520            username = P2PSettings.Default.PeerName;
[2456]1521
[2467]1522            //enhance our userdata:
1523            if ((username != null) && (!username.Equals("")))
1524            {
1525                vk.user = username;
1526                vk.time = chunkstart;
1527                vk.maschid = maschineid;
1528                vk.maschname = maschinename;
1529            }
1530            else
1531            {
1532                vk.user = "Unknown";
1533                vk.time = defaultstart;
1534                vk.maschid = 666;
1535                vk.maschname = "Devil";
1536            }
1537        }
1538
1539        internal void updateToplist()
1540        {
[908]1541            LinkedListNode<ValueKey> node;
1542            while (valuequeue.Count != 0)
1543            {
1544                ValueKey vk = (ValueKey)valuequeue.Dequeue();
[1634]1545
1546                //if (costList.Contains(vk)) continue;
1547                var result = costList.Where(valueKey => valueKey.key == vk.key);
1548                if (result.Count() > 0)
1549                {
1550                    continue;
1551                }
1552
[908]1553                if (this.costMaster.getRelationOperator() == RelationOperator.LargerThen)
1554                {
1555                    if (vk.value > costList.Last().value)
[744]1556                    {
[908]1557                        node = costList.First;
1558                        while (node != null)
[780]1559                        {
[908]1560                            if (vk.value > node.Value.value)
[780]1561                            {
[1159]1562                                if (node == costList.First)
1563                                    Top1 = vk;
[908]1564                                costList.AddBefore(node, vk);
1565                                costList.RemoveLast();
1566                                value_threshold = costList.Last.Value.value;
1567                                break;
[780]1568                            }
[908]1569                            node = node.Next;
1570                        }//end while
1571                    }//end if
1572                }
1573                else
[951]1574                {
[908]1575                    if (vk.value < costList.Last().value)
1576                    {
1577                        node = costList.First;
1578                        while (node != null)
[819]1579                        {
[908]1580                            if (vk.value < node.Value.value)
[744]1581                            {
[1159]1582                                if (node == costList.First)
1583                                    Top1 = vk;
[908]1584                                costList.AddBefore(node, vk);
1585                                costList.RemoveLast();
1586                                value_threshold = costList.Last.Value.value;
1587                                break;
[744]1588                            }
[908]1589                            node = node.Next;
1590                        }//end while
[793]1591                    }//end if
[908]1592                }
1593            }
1594        }
[744]1595
[939]1596        #endregion
1597
[2146]1598        private void StartThreads(IControlEncryption sender, int bytesToUse, KeyPattern.KeyPattern[] patterns, BigInteger[] doneKeysA, BigInteger[] openCLDoneKeysA, BigInteger[] keycounters, BigInteger[] keysleft, Stack threadStack)
[908]1599        {
[2194]1600            //First start the opencl threads:
1601            int i = 0;
1602            foreach (var ds in settings.DeviceSettings)
[908]1603            {
[2194]1604                if (ds.useDevice)
1605                {
1606                    WaitCallback worker = new WaitCallback(KeySearcherJob);
1607                    doneKeysA[i] = new BigInteger();
1608                    openCLDoneKeysA[i] = new BigInteger();
1609                    keycounters[i] = new BigInteger();
1610
1611                    ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, openCLDoneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack, ds });
1612                    i++;
1613                }
1614            }
1615
1616            //Then the CPU threads:
1617            for (; i < patterns.Length; i++)
1618            {
[908]1619                WaitCallback worker = new WaitCallback(KeySearcherJob);
1620                doneKeysA[i] = new BigInteger();
[2146]1621                openCLDoneKeysA[i] = new BigInteger();
[908]1622                keycounters[i] = new BigInteger();
[2086]1623
[2194]1624                ThreadPool.QueueUserWorkItem(worker, new object[] { patterns, i, doneKeysA, openCLDoneKeysA, keycounters, keysleft, sender, bytesToUse, threadStack, null });
[908]1625            }
1626        }
[785]1627
[1674]1628        private KeyPattern.KeyPattern[] splitPatternForThreads(KeyPattern.KeyPattern pattern)
[908]1629        {
[2086]1630            int threads = settings.CoresUsed;
[2194]1631            threads += settings.DeviceSettings.Count(x => x.useDevice); 
[2086]1632
1633            if (threads < 1)
1634                return null;
1635
1636            KeyPattern.KeyPattern[] patterns = new KeyPattern.KeyPattern[threads];
1637            if (threads > 1)
[908]1638            {
[1674]1639                KeyPattern.KeyPattern[] patterns2 = pattern.split();
[1135]1640                if (patterns2 == null)
1641                {
[1674]1642                    patterns2 = new KeyPattern.KeyPattern[1];
[1135]1643                    patterns2[0] = pattern;
1644                    return patterns2;
1645                }
[908]1646                patterns[0] = patterns2[0];
1647                patterns[1] = patterns2[1];
1648                int p = 1;
[2086]1649                threads -= 2;
1650
[908]1651                while (threads > 0)
1652                {
1653                    int maxPattern = -1;
1654                    BigInteger max = 0;
1655                    for (int i = 0; i <= p; i++)
1656                        if (patterns[i].size() > max)
[785]1657                        {
[908]1658                            max = patterns[i].size();
1659                            maxPattern = i;
[785]1660                        }
[1674]1661                    KeyPattern.KeyPattern[] patterns3 = patterns[maxPattern].split();
[1135]1662                    if (patterns3 == null)
1663                    {
[1674]1664                        patterns3 = new KeyPattern.KeyPattern[p+1];
[1135]1665                        for (int i = 0; i <= p; i++)
1666                            patterns3[i] = patterns[i];
1667                        return patterns3;
1668                    }
[908]1669                    patterns[maxPattern] = patterns3[0];
1670                    patterns[++p] = patterns3[1];
1671                    threads--;
1672                }
1673            }
1674            else
[2002]1675                patterns[0] = pattern;
[908]1676            return patterns;
[676]1677        }
[415]1678
[677]1679        private void keyPatternChanged()
1680        {
[1674]1681            Pattern = new KeyPattern.KeyPattern(controlMaster.getKeyPattern());
[677]1682        }
1683
[702]1684        #endregion
1685
[676]1686        public void GuiLogMessage(string message, NotificationLevel loglevel)
1687        {
1688            if (OnGuiLogNotificationOccured != null)
1689                OnGuiLogNotificationOccured(this, new GuiLogEventArgs(message, this, loglevel));
1690        }
1691
[716]1692        public void ProgressChanged(double value, double max)
1693        {
1694            if (OnPluginProgressChanged != null)
1695            {
1696                OnPluginProgressChanged(this, new PluginProgressEventArgs(value, max));
[744]1697
[716]1698            }
1699        }
1700
[939]1701        /// <summary>
1702        /// used for delivering the results from the worker threads to the main thread:
1703        /// </summary>
[971]1704        public struct ValueKey
[702]1705        {
[2456]1706            public override bool Equals(object obj)
1707            {
[2457]1708                if (obj != null && obj is ValueKey && keya != null && ((ValueKey)obj).keya != null)
1709                    return (keya.SequenceEqual(((ValueKey)obj).keya));
1710                else
1711                    return false;
[2456]1712            }
1713
[702]1714            public double value;
1715            public String key;
[785]1716            public byte[] decryption;
[2010]1717            public byte[] keya;
[2428]1718            //---------------------
[2359]1719            public string user { get; set; }
1720            public DateTime time { get; set; }
1721            public long maschid { get; set; }
1722            public string maschname { get; set; }
[2428]1723            //---------------------
[702]1724        };
[415]1725    }
[1030]1726
1727    /// <summary>
1728    /// Represents one entry in our result list
1729    /// </summary>
1730    public class ResultEntry
1731    {
1732        public string Ranking { get; set; }
1733        public string Value { get; set; }
1734        public string Key { get; set; }
1735        public string Text { get; set; }
[2306]1736        //-------
1737        public string User { get; set; }
1738        public DateTime Time { get; set; }
1739        public long Maschid { get; set; }
1740        public string Maschname { get; set; }
1741        //-------
[1030]1742    }
[2240]1743    /// <summary>
1744    /// Represents one entry in our statistic list
1745    /// </summary>
1746    public class Information
1747    {
1748        public int Count { get; set; }
1749        public string Hostname { get; set; }
1750        public DateTime Date { get; set; }
[2292]1751    }
1752    /// <summary>
1753    /// Represents one entry in our maschine statistic list
1754    /// </summary>
1755    public class Maschinfo
1756    {
1757        public int Sum { get; set; }
1758        public string Hostname { get; set; }
1759        public string Users { get; set; }
[2240]1760    } 
[951]1761}
Note: See TracBrowser for help on using the repository browser.