Changeset 2417


Ignore:
Timestamp:
Jan 22, 2011, 12:57:36 AM (10 years ago)
Author:
schwittmann
Message:

Several ExternalClient improvements:

  • Separated connected and request job events
  • Added basic authentication
  • Lookup DNS again after getting disconnected
  • Fixed some socket exceptions
  • Prevent slow clients from submitting old jobs by using unique job identifiers
Location:
trunk/CrypPlugins/KeySearcher
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/CrypPlugins/KeySearcher/ExternalClient/Main.cpp

    r2205 r2417  
    1616void usage(char **argv)
    1717{
    18     printf("Usage: %s $THREAD_NUM $HOST $PORT\n\n", argv[0]);
    19     printf("    THREAD_NUM - Number of concurrent threads\n");
     18    printf("Usage: %s $HOST $PORT [$PASSWORD]\n\n", argv[0]);
    2019    printf("    HOST       - PC running cryptool\n");
    2120    printf("    PORT       - Cryptool's listening port\n");
     21    printf("    [PASSWORD] - Password used to auth with server\n");
    2222}
    2323
    24 int threadNum;
     24bool lookup(const char* host, sockaddr_in & serv_addr)
     25{
     26    hostent *server = gethostbyname(host);
    2527
     28    if(!server)
     29        return false;
     30
     31    serv_addr.sin_family = AF_INET;
     32    bcopy((char *)server->h_addr,
     33            (char *)&serv_addr.sin_addr.s_addr,
     34            server->h_length);
     35
     36    return true;
     37}
    2638
    2739int main (int argc, char **argv)
    2840{
    29     if(argc != 4)
     41    if(argc != 3 && argc != 4)
    3042    {
    3143        usage(argv);
     
    3345    }
    3446
    35     threadNum = atoi(argv[1]);
    36     if(threadNum== 0)
     47    const char* password = "";
     48    if(argc == 4)
    3749    {
    38         printf("Invalid number of threads\n");
    39         return 1;
     50        password = argv[3];
    4051    }
    4152
    42     hostent *server = gethostbyname(argv[2]);
    43     if(!server)
    44     {
    45         printf("Invalid host\n");
    46         return 1;
    47     }
    48 
    49     int port = atoi(argv[3]);
     53    int port = atoi(argv[2]);
    5054
    5155    if(port == 0 || port <= 0 || port > 0xFFFF)
     
    5761    sockaddr_in serv_addr;
    5862    bzero((char *) &serv_addr, sizeof(serv_addr));
    59     serv_addr.sin_family = AF_INET;
    60     bcopy((char *)server->h_addr,
    61             (char *)&serv_addr.sin_addr.s_addr,
    62             server->h_length);
    6363    serv_addr.sin_port = htons(port);
     64
    6465    while(true)
    6566    {
    66         networkThread(serv_addr, port);
     67        if(!lookup(argv[1], serv_addr))
     68        {
     69            printf("failed to lookup %s..\n", argv[1]);
     70            continue;
     71        }
     72        networkThread(serv_addr, port, password);
    6773        printf("Reconnecting in %u seconds\n", RECONNECT_TIME);
    6874        sleep(RECONNECT_TIME);
  • trunk/CrypPlugins/KeySearcher/ExternalClient/Network.cpp

    r2258 r2417  
    4646// Queue of completed jobs
    4747std::queue<JobResult> finishedJobs;
    48 void GetJobsAndPostResults(PlatformIndependentWrapper& wrapper)
     48void GetJobsAndPostResults(PlatformIndependentWrapper& wrapper, const char* password)
    4949{
    5050    if (cryptool == 0)
     
    5353    wrapper.WriteInt(ClientOpcodes::HELLO);
    5454    wrapper.WriteString(getIdentificationStr());
     55    wrapper.WriteString(password);
    5556
    5657    while(!finishedJobs.empty())
     
    6364    while(true)
    6465    {
     66        // TODO: soft break
     67        wrapper.WriteInt(ClientOpcodes::JOB_REQUEST);
    6568        switch(wrapper.ReadInt())
    6669        {
     
    8992                }
    9093                break;
     94            case ServerOpcodes::WRONG_PASSWORD:
     95                printf("Server didn't accept our password :(\n");
     96                break;
    9197        }
    9298    }
    9399}
    94100
    95 void networkThread(sockaddr_in serv_addr, int port)
     101void networkThread(sockaddr_in serv_addr, int port, const char* password)
    96102{
    97103    printf("Connecting to %s on port %i\n", inet_ntoa(serv_addr.sin_addr), port);
     
    100106    if (sockfd < 0)
    101107    {
    102         printf("ERROR opening socket\n");
     108        printf("  ERROR opening socket\n");
    103109        return;
    104110    }
     
    106112    if (connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
    107113    {
    108         printf("Couldn't connect\n");
     114        printf("  Couldn't connect\n");
    109115        close(sockfd);
    110116        return;
    111117    }
    112     printf("Connection established\n");
     118    printf("  Connection established\n");
    113119
    114120    try{
    115121        PlatformIndependentWrapper w(sockfd);
    116         GetJobsAndPostResults(w);
     122        GetJobsAndPostResults(w, password);
    117123    } catch(SocketException)
    118124    {
  • trunk/CrypPlugins/KeySearcher/ExternalClient/Network.h

    r2205 r2417  
    1 void networkThread(sockaddr_in, int);
     1void networkThread(sockaddr_in, int, const char*);
    22
  • trunk/CrypPlugins/KeySearcher/ExternalClient/Opcodes.h

    r2207 r2417  
    77        HELLO = 0,
    88        JOB_RESULT = 1,
     9        JOB_REQUEST = 2,
    910    };
    1011};
     
    1516    {
    1617        NEW_JOB = 0,
     18        WRONG_PASSWORD = 1,
    1719    };
    1820};
  • trunk/CrypPlugins/KeySearcher/ExternalClient/runclient.sh

    r2212 r2417  
    11#!/bin/bash
    22export LD_LIBRARY_PATH=~/src/ati-stream-sdk-v2.2-lnx32/lib/x86/:.
    3 make && ./bin/Cryptool 2 192.168.2.114 6234
     3make && ./bin/Cryptool 192.168.1.109 6235 123
  • trunk/CrypPlugins/KeySearcher/KeySearcher.cs

    r2411 r2417  
    252252        private IKeyTranslator externalKeyTranslator;
    253253        private BigInteger externalKeysProcessed;
    254         private EndPoint externalClientConnected;
     254        /// <summary>
     255        /// List of clients which connected while there was no job available. Will receive
     256        /// a job a soon as one is available.
     257        /// </summary>
     258        private List<EndPoint> waitingExternalClients = new List<EndPoint>();
     259        private Guid currentExternalJobGuid = Guid.NewGuid();
    255260        private AutoResetEvent waitForExternalClientToFinish = new AutoResetEvent(false);
    256261        private DateTime assignTime;
     262        private bool externalClientJobsAvailable = false;
    257263        #endregion
    258264
     
    823829                {
    824830                    GuiLogMessage(Resources.Waiting_for_external_client_, NotificationLevel.Info);
     831                    if (cryptoolServer != null)
     832                    {
     833
     834                    }
    825835                    cryptoolServer = new CryptoolServer();
    826                     externalClientConnected = null;
     836                    waitingExternalClients.Clear();
    827837                    cryptoolServer.Port = settings.Port;
    828                     cryptoolServer.OnJobCompleted += server_OnJobCompleted;
    829                     cryptoolServer.OnClientConnected += server_OnClientConnected;
     838                    cryptoolServer.OnJobCompleted += cryptoolServer_OnJobCompleted;
     839                    cryptoolServer.OnClientAuth = cryptoolServer_OnClientAuth;
    830840                    cryptoolServer.OnClientDisconnected += cryptoolServer_OnClientDisconnected;
     841                    cryptoolServer.OnClientRequestedJob += cryptoolServer_OnClientRequestedJob;
     842                    cryptoolServer.OnErrorLog += cryptoolServer_OnErrorLog;
    831843                    serverThread = new Thread(new ThreadStart(delegate
    832844                                                                      {
     
    850862                    //stop server here!
    851863                    cryptoolServer.Shutdown();
    852                     cryptoolServer.OnJobCompleted -= server_OnJobCompleted;
    853                     cryptoolServer.OnClientConnected -= server_OnClientConnected;
     864                    cryptoolServer.OnJobCompleted -= cryptoolServer_OnJobCompleted;
     865                    cryptoolServer.OnClientAuth = null;
    854866                    cryptoolServer.OnClientDisconnected -= cryptoolServer_OnClientDisconnected;
     867                    cryptoolServer.OnClientRequestedJob -= cryptoolServer_OnClientRequestedJob;
     868                    cryptoolServer.OnErrorLog -= cryptoolServer_OnErrorLog;
    855869                }
    856870            }
     
    914928                    externalKeyTranslator = ControlMaster.getKeyTranslator();
    915929                    externalKeyTranslator.SetKeys(pattern);
    916                     if (externalClientConnected != null)
    917                         AssignJobToClient(externalClientConnected, externalKeySearcherOpenCLCode.CreateOpenCLBruteForceCode(externalKeyTranslator));
     930                    currentExternalJobGuid = Guid.NewGuid();
     931                    foreach (var client in waitingExternalClients)
     932                    {
     933                        AssignJobToClient(client, externalKeySearcherOpenCLCode.CreateOpenCLBruteForceCode(externalKeyTranslator));
     934                    }
     935                    waitingExternalClients.Clear();
     936                    externalClientJobsAvailable = true;
    918937                }
    919938                waitForExternalClientToFinish.Reset();
    920939                waitForExternalClientToFinish.WaitOne();
     940                lock (this)
     941                {
     942                    externalClientJobsAvailable = false;
     943                }
    921944            }
    922945            else
     
    10701093        {
    10711094            GuiLogMessage(Resources.Client_disconnected_, NotificationLevel.Info);
    1072             externalClientConnected = null;
    1073         }
    1074 
    1075         void server_OnClientConnected(System.Net.EndPoint client, string identification)
    1076         {
    10771095            lock (this)
    10781096            {
    1079                 if (externalClientConnected == null)
    1080                 {
    1081                     externalClientConnected = client;
    1082                     GuiLogMessage(string.Format(Resources.Client__0__connected_, identification), NotificationLevel.Info);
    1083                     AssignJobToClient(client, externalKeySearcherOpenCLCode.CreateOpenCLBruteForceCode(externalKeyTranslator));
    1084                 }
    1085                 else
    1086                 {
    1087                     GuiLogMessage(Resources.Client_tried_to_connect__but_only_one_client_allowed_, NotificationLevel.Info);
    1088                 }
    1089             }
     1097                waitingExternalClients.Remove(client);
     1098            }
     1099        }
     1100
     1101        bool cryptoolServer_OnClientAuth(System.Net.EndPoint client, string name, string password)
     1102        {
     1103            if(settings.ExternalClientPassword.Length == 0 ||
     1104                settings.ExternalClientPassword == password)
     1105            {
     1106                GuiLogMessage(string.Format(Resources.Client__0__connected_, name), NotificationLevel.Info);
     1107                return true;
     1108            }
     1109            GuiLogMessage(string.Format(Resources.Client__0__tried_to_auth_with_invalid_password, name), NotificationLevel.Info);
     1110            return false;
    10901111        }
    10911112
     
    10931114        {
    10941115            JobInput j = new JobInput();
    1095             j.Guid = Guid.NewGuid().ToString();
     1116            j.Guid = currentExternalJobGuid.ToString();
    10961117            j.Src = src;
    10971118            var key = externalKeyTranslator.GetKey();
     
    11051126        }
    11061127
    1107         void server_OnJobCompleted(System.Net.EndPoint client, JobResult jr)
     1128        void cryptoolServer_OnJobCompleted(System.Net.EndPoint client, JobResult jr)
    11081129        {
    11091130            GuiLogMessage(string.Format(Resources.Client_returned_result_of_job_with_Guid__0__, jr.Guid), NotificationLevel.Info);
     1131            lock (this)
     1132            {
     1133                if (!jr.Guid.Equals(currentExternalJobGuid.ToString()))
     1134                {
     1135                    GuiLogMessage(string.Format(Resources.Received_late_job_result_0_from_client_1, jr.Guid, client), NotificationLevel.Warning);
     1136                    return;
     1137                }
     1138
     1139                // Set new guid. Will prevent concurrent clients
     1140                // from supplying old results for new chunks.
     1141                currentExternalJobGuid = Guid.NewGuid();
     1142            }
    11101143            //check:
    11111144            var op = this.costMaster.getRelationOperator();
     
    11561189                                                                                    }, null);
    11571190
    1158 
    1159             if (externalKeysProcessed != keysInThisChunk)
    1160             {
    1161                 AssignJobToClient(client, null);
    1162             }
    1163             else
     1191            if (externalKeysProcessed == keysInThisChunk)
    11641192            {
    11651193                waitForExternalClientToFinish.Set();
    1166             }
     1194                lock (this)
     1195                {
     1196                    externalClientJobsAvailable = false;
     1197                }
     1198            }
     1199        }
     1200
     1201        void cryptoolServer_OnErrorLog(string str)
     1202        {
     1203            GuiLogMessage(str, NotificationLevel.Error);
     1204        }
     1205
     1206        void cryptoolServer_OnClientRequestedJob(EndPoint ipep)
     1207        {
     1208            lock (this)
     1209            {
     1210                if(externalClientJobsAvailable)
     1211                {
     1212                    AssignJobToClient(ipep, externalKeySearcherOpenCLCode.CreateOpenCLBruteForceCode(externalKeyTranslator));
     1213                }
     1214                else
     1215                {
     1216                    waitingExternalClients.Add(ipep);
     1217                }
     1218            }
     1219       
    11671220        }
    11681221
  • trunk/CrypPlugins/KeySearcher/KeySearcherSettings.cs

    r2334 r2417  
    406406        }
    407407
     408        private String externalClientPassword = "";
     409        [TaskPane("ExternalClientPasswordSettings", "ExternalClientPasswordSettingsDesc", "GroupExternalClient", 3, false, ControlType.TextBoxHidden)]
     410        public String ExternalClientPassword
     411        {
     412            get { return externalClientPassword; }
     413            set
     414            {
     415                if (value != externalClientPassword)
     416                {
     417                    externalClientPassword = value;
     418                    hasChanges = true;
     419                    OnPropertyChanged("ExternalClientPassword");
     420                }
     421            }
     422        }
    408423        #endregion
    409424
  • trunk/CrypPlugins/KeySearcher/Properties/Resources.Designer.cs

    r2415 r2417  
    251251       
    252252        /// <summary>
     253        ///   Looks up a localized string similar to Client &apos;{0}&apos; tried to authenticate using an invalid password.
     254        /// </summary>
     255        internal static string Client__0__tried_to_auth_with_invalid_password {
     256            get {
     257                return ResourceManager.GetString("Client__0__tried_to_auth_with_invalid_password", resourceCulture);
     258            }
     259        }
     260       
     261        /// <summary>
    253262        ///   Looks up a localized string similar to Client disconnected!.
    254263        /// </summary>
     
    535544            get {
    536545                return ResourceManager.GetString("Endgame_Mode_", resourceCulture);
     546            }
     547        }
     548       
     549        /// <summary>
     550        ///   Looks up a localized string similar to Password.
     551        /// </summary>
     552        internal static string ExternalClientPasswordSettings {
     553            get {
     554                return ResourceManager.GetString("ExternalClientPasswordSettings", resourceCulture);
     555            }
     556        }
     557       
     558        /// <summary>
     559        ///   Looks up a localized string similar to Password used for authenticating external clients.
     560        /// </summary>
     561        internal static string ExternalClientPasswordSettingsDesc {
     562            get {
     563                return ResourceManager.GetString("ExternalClientPasswordSettingsDesc", resourceCulture);
    537564            }
    538565        }
     
    10351062       
    10361063        /// <summary>
     1064        ///   Looks up a localized string similar to Received late job result {0} from client &apos;{1}&apos;.
     1065        /// </summary>
     1066        internal static string Received_late_job_result_0_from_client_1 {
     1067            get {
     1068                return ResourceManager.GetString("Received_late_job_result_0_from_client_1", resourceCulture);
     1069            }
     1070        }
     1071       
     1072        /// <summary>
    10371073        ///   Looks up a localized string similar to Received (link):.
    10381074        /// </summary>
  • trunk/CrypPlugins/KeySearcher/Properties/Resources.de-DE.resx

    r2415 r2417  
    592592    <value>Statistiken</value>
    593593  </data>
     594  <data name="ExternalClientPasswordSettings" xml:space="preserve">
     595    <value>Passwort</value>
     596  </data>
     597  <data name="ExternalClientPasswordSettingsDesc" xml:space="preserve">
     598    <value>Passwort mit dem sich externe Clients authentifizieren müssen</value>
     599  </data>
    594600</root>
  • trunk/CrypPlugins/KeySearcher/Properties/Resources.resx

    r2415 r2417  
    592592    <value>Statistics</value>
    593593  </data>
     594  <data name="ExternalClientPasswordSettings" xml:space="preserve">
     595    <value>Password</value>
     596  </data>
     597  <data name="ExternalClientPasswordSettingsDesc" xml:space="preserve">
     598    <value>Password used for authenticating external clients</value>
     599  </data>
     600  <data name="Received_late_job_result_0_from_client_1" xml:space="preserve">
     601    <value>Received late job result {0} from client '{1}'</value>
     602  </data>
     603  <data name="Client__0__tried_to_auth_with_invalid_password" xml:space="preserve">
     604    <value>Client '{0}' tried to authenticate using an invalid password</value>
     605  </data>
    594606</root>
  • trunk/CrypPlugins/KeySearcher/Server/Opcodes.cs

    r2202 r2417  
    99    HELLO = 0,
    1010    JOB_RESULT = 1,
     11    JOB_REQUEST = 2
    1112}
    1213
     
    1415{
    1516    NEW_JOB = 0,
     17    WRONG_PASSWORD = 1,
    1618}
    1719
  • trunk/CrypPlugins/KeySearcher/Server/Server.cs

    r2411 r2417  
    88class CryptoolServer
    99{
     10    #region Properties
     11
    1012    public int Port {get;set;}
    11    
     13
     14    #endregion
     15
     16    #region Events
     17
    1218    public delegate void JobCompletedDelegate(EndPoint ipep, JobResult j);
    1319    public event JobCompletedDelegate OnJobCompleted;
    1420
    15 
    16     public delegate void ClientConnectedDelegate(EndPoint ipep, String identification);
    17     public event ClientConnectedDelegate OnClientConnected;
    18 
    19     public delegate void ClientDisconnectedDelegate(EndPoint ipep);
    20     public event ClientDisconnectedDelegate OnClientDisconnected;
     21    public delegate bool ClientConnectedDelegate(EndPoint ipep, String name, String password);
     22    public ClientConnectedDelegate OnClientAuth;
     23
     24    public delegate void EndPointDelegate(EndPoint ipep);
     25    public event EndPointDelegate OnClientDisconnected;
     26
     27    public event EndPointDelegate OnClientRequestedJob;
     28
     29    public delegate void StringDelegate(String str);
     30    public event StringDelegate OnErrorLog;
     31   
     32    #endregion
     33
     34    #region Variables
    2135
    2236    private Dictionary<EndPoint, TcpClient> connectedClients = new Dictionary<EndPoint, TcpClient>();
    2337    private TcpListener tcpListener;
    2438    private bool running = false;
     39
     40    #endregion
    2541
    2642    ///<summary>
     
    2945    public void Run()
    3046    {
     47        if (OnJobCompleted == null ||
     48            OnClientAuth == null ||
     49            OnClientDisconnected == null ||
     50            OnClientRequestedJob == null ||
     51            OnErrorLog == null)
     52        {
     53            throw new Exception("One of the mandatory events was not bound");
     54        }
     55
    3156        lock (this)
    3257        {
     
    4267            tcpListener = new TcpListener(IPAddress.Any, Port);
    4368            tcpListener.Start();
    44             Console.WriteLine("Listening for client on port " + Port);
    4569            while (running)
    4670            {
    4771                TcpClient client = tcpListener.AcceptTcpClient();
    48                 Console.WriteLine("Got connection from " + client);
    4972                lock (connectedClients)
    5073                {
     
    6083        catch (SocketException e)
    6184        {
    62             if (running)
    63             {
    64                 Console.WriteLine("CryptoolServer: Got SocketException while running");
    65             }
    66         }
    67 
    68 
    69         tcpListener.Stop();
    70         foreach(var client in connectedClients)
    71             client.Value.Close();
     85            if (running && OnErrorLog != null)
     86            {
     87                OnErrorLog("CryptoolServer: Got SocketException while running");
     88            }
     89        }
     90        finally
     91        {
     92            try
     93            {
     94                tcpListener.Stop();
     95            }
     96            catch (Exception)
     97            {
     98            }
     99            lock (connectedClients)
     100            {
     101                foreach (var client in connectedClients)
     102                    client.Value.Close();
     103            }
     104        }
    72105    }
    73106   
     
    77110        lock(connectedClients)
    78111        {
    79             if(!connectedClients.TryGetValue(i, out client))
    80                 throw new ArgumentException("Not connected to "+i);
     112            if (!connectedClients.TryGetValue(i, out client))
     113            {
     114                if (OnErrorLog != null)
     115                    OnErrorLog("Tried to send job to not present external client " + i);
     116                return;
     117            }
    81118        }
    82119
     
    101138        EndPoint ep = client.Client.RemoteEndPoint;
    102139
     140        bool identified = false;
    103141        try
    104142        {
    105143            var wrapped = new PlatformIndependentWrapper(client);
    106             while(true)
    107             {
    108                 switch((ClientOpcodes)wrapped.ReadInt())
     144            while (true)
     145            {
     146                switch ((ClientOpcodes)wrapped.ReadInt())
    109147                {
    110148                    case ClientOpcodes.HELLO:
    111149                        {
    112                             String identification = wrapped.ReadString();
    113                             if(OnClientConnected != null)
    114                                 OnClientConnected(ep, identification);
     150                            String name = wrapped.ReadString();
     151                            String password = wrapped.ReadString();
     152                            if (OnClientAuth == null || !OnClientAuth(ep, name, password))
     153                            {
     154                                wrapped.WriteInt((int)ServerOpcodes.WRONG_PASSWORD);
     155                                return;
     156                            }
     157                            identified = true;
    115158                        }
    116159                        break;
     
    118161                    case ClientOpcodes.JOB_RESULT:
    119162                        {
     163                            if (!identified)
     164                            {
     165                                if (OnErrorLog != null)
     166                                {
     167                                    OnErrorLog("Client '" + ep + "' tried to post result without identification");
     168                                }
     169                                return;
     170                            }
     171
    120172                            var jobGuid = wrapped.ReadString();
    121173                            var resultList = new List<KeyValuePair<float, int>>();
     
    132184                            rs.ResultList = resultList;
    133185
    134                             if(OnJobCompleted != null)
     186                            if (OnJobCompleted != null)
    135187                            {
    136188                                OnJobCompleted(ep, rs);
     189                            }
     190                        }
     191                        break;
     192
     193                    case ClientOpcodes.JOB_REQUEST:
     194                        {
     195                            if (!identified)
     196                            {
     197                                if (OnErrorLog != null)
     198                                {
     199                                    OnErrorLog("Client '" + ep + "' tried to request job without identification");
     200                                }
     201                                return;
     202                            }
     203
     204                            if (OnClientRequestedJob != null)
     205                            {
     206                                OnClientRequestedJob(ep);
    137207                            }
    138208                        }
     
    141211            }
    142212        }
    143         catch(Exception e)
    144         {
    145             Console.WriteLine("Client exited with exception "+e);
    146         }
    147 
    148         lock(connectedClients)
    149         {
    150             connectedClients.Remove(ep);
    151         }
    152 
    153         if(OnClientDisconnected != null)
    154             OnClientDisconnected(ep);
     213        catch (SocketException)
     214        {
     215            // left blank intentionally. Will be thrown on client disconnect.
     216        }
     217        catch (Exception e)
     218        {
     219            if (OnErrorLog != null)
     220            {
     221                OnErrorLog("Client '" + ep + "' caused exception " + e);
     222            }
     223        }
     224        finally
     225        {
     226            // just to be sure..
     227            client.Close();
     228
     229            lock (connectedClients)
     230            {
     231                connectedClients.Remove(ep);
     232            }
     233
     234            if (OnClientDisconnected != null)
     235                OnClientDisconnected(ep);
     236        }
    155237    }
    156238
Note: See TracChangeset for help on using the changeset viewer.