Jeff's patches for a multi-threaded gss-sample suite, modified to not break the
authorKen Raeburn <raeburn@mit.edu>
Fri, 21 Oct 2005 01:17:20 +0000 (01:17 +0000)
committerKen Raeburn <raeburn@mit.edu>
Fri, 21 Oct 2005 01:17:20 +0000 (01:17 +0000)
single-threaded UNIX case.  (Tested on Linux/x86.)  Needs stylistic cleanup at
some point.

ticket: 3214
tags: pullup

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17445 dc483132-0cff-0310-8789-dd5450dbe970

src/appl/gss-sample/ChangeLog
src/appl/gss-sample/gss-client.c
src/appl/gss-sample/gss-misc.c
src/appl/gss-sample/gss-server.c

index b641880dba576ac7c7bff5dae936da69efd2740f..25c4c3fb8199596980d5c79c8d39d2b6a0b66fa8 100644 (file)
@@ -1,3 +1,36 @@
+2005-10-20  Ken Raeburn  <raeburn@mit.edu>
+           Jeffrey Altman  <jaltman@mit.edu>
+
+       * gss-server.c [!_WIN32]: Include port-sockets.h instead of the
+       various network-related UNIX header files.
+       (worker_bee): New function.
+       (main): Use it.
+       (max_threads): New variable.
+       (thread_count, hMutex, hEvent) [_WIN32]: New variables.
+       (InitHandles, CleanupHandles, WaitAndIncrementThreadCounter,
+       DecrementAndSignalThreadCounter) [_WIN32]: New functions.
+       (main) [_WIN32]: Accept new option -threads, and keep that many
+       threads going.
+       (usage) [_WIN32]: Document new option.
+
+       * gss-client.c [!_WIN32]: Include assert.h.
+       (max_threads): New variable.
+       (service_name, server_host, msg, mechanism, port, use_file,
+       gss_flags, min_stat, oid, mcount, ccount, auth_flag, wrap_flag,
+       encrypt_flag, mic_flag, v1_format): Moved variables to top level
+       from inside main.
+       (worker_bee): New function, with call_server call moved from
+       main.
+       (main): Call it.
+       (thread_count, hMutex, hEvent) [_WIN32]: New variables.
+       (InitHandles, CleanupHandles, WaitAndIncrementThreadCounter,
+       DecrementAndSignalThreadCounter) [_WIN32]: New functions.
+       (main) [_WIN32]: Accept new option -threads, and keep that many
+       threads going.
+       (usage) [_WIN32]: Document new option.
+
+       * gss-misc.c (send_token): Delete unused variable "len".
+
 2004-03-08  Ken Raeburn  <raeburn@mit.edu>
 
        * Makefile.in (MY_SUBDIRS): Deleted.
index f7b578a19052e68833bf20c8a4fb9b53f31abe86..d05ab41d576bce069dc8825ff70338d2cfca7e85 100644 (file)
@@ -20,7 +20,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 /*
- * Copyright (C) 2003, 2004 by the Massachusetts Institute of Technology.
+ * Copyright (C) 2003, 2004, 2005 by the Massachusetts Institute of Technology.
  * All rights reserved.
  *
  * Export of this software from the United States of America may
@@ -50,6 +50,7 @@
 #include <windows.h>
 #include <winsock.h>
 #else
+#include <assert.h>
 #include <unistd.h>
 #include <ctype.h>
 #include <sys/types.h>
@@ -69,7 +70,11 @@ static int verbose = 1;
 static void usage()
 {
      fprintf(stderr, "Usage: gss-client [-port port] [-mech mechanism] [-d]\n");
-     fprintf(stderr, "       [-seq] [-noreplay] [-nomutual]\n");
+     fprintf(stderr, "       [-seq] [-noreplay] [-nomutual]");
+#ifdef _WIN32
+     fprintf(stderr, " [-threads num]");
+#endif  
+     fprintf(stderr, "\n");
      fprintf(stderr, "       [-f] [-q] [-ccount count] [-mcount count]\n");
      fprintf(stderr, "       [-v1] [-na] [-nw] [-nx] [-nm] host service msg\n");
      exit(1);
@@ -595,20 +600,94 @@ static void parse_oid(char *mechanism, gss_OID *oid)
        free(mechstr);
 }
 
+static int max_threads = 1;
+
+#ifdef _WIN32
+static thread_count = 0;
+static HANDLE hMutex = NULL;
+static HANDLE hEvent = NULL;
+
+void
+InitHandles(void)
+{
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+}
+
+void
+CleanupHandles(void)
+{
+    CloseHandle(hMutex);
+    CloseHandle(hEvent);
+}
+
+BOOL
+WaitAndIncrementThreadCounter(void)
+{
+    for (;;) {
+        if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+            if ( thread_count < max_threads ) {
+                thread_count++;
+                ReleaseMutex(hMutex);
+                return TRUE;
+            } else {
+                ReleaseMutex(hMutex);
+
+                if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) {
+                    continue;
+                } else {
+                    return FALSE;
+                }
+            }
+        } else {
+            return FALSE;
+        }
+    }
+}
+
+BOOL
+DecrementAndSignalThreadCounter(void)
+{
+    if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+        if ( thread_count == max_threads )
+            ResetEvent(hEvent);
+        thread_count--;
+        ReleaseMutex(hMutex);
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+#endif
+
+static char *service_name, *server_host, *msg;
+static char *mechanism = 0;
+static u_short port = 4444;
+static int use_file = 0;
+static OM_uint32 gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
+static OM_uint32 min_stat;
+static gss_OID oid = GSS_C_NULL_OID;
+static int mcount = 1, ccount = 1;
+static int auth_flag, wrap_flag, encrypt_flag, mic_flag, v1_format;
+
+void worker_bee(void * unused)
+{
+    if (call_server(server_host, port, oid, service_name,
+                    gss_flags, auth_flag, wrap_flag, encrypt_flag, mic_flag,
+                    v1_format, msg, use_file, mcount) < 0)
+        exit(1);
+
+#ifdef _WIN32
+    if ( max_threads > 1 )
+        DecrementAndSignalThreadCounter();
+#endif
+}
+
 int main(argc, argv)
      int argc;
      char **argv;
 {
-     char *service_name, *server_host, *msg;
-     char *mechanism = 0;
-     u_short port = 4444;
-     int use_file = 0;
-     OM_uint32 gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
-     OM_uint32 min_stat;
-     gss_OID oid = GSS_C_NULL_OID;
-     int mcount = 1, ccount = 1;
      int i;
-     int auth_flag, wrap_flag, encrypt_flag, mic_flag, v1_format;
 
      display_file = stdout;
      auth_flag = wrap_flag = encrypt_flag = mic_flag = 1;
@@ -625,7 +704,15 @@ int main(argc, argv)
               argc--; argv++;
               if (!argc) usage();
               mechanism = *argv;
-          } else if (strcmp(*argv, "-d") == 0) {
+          } 
+#ifdef _WIN32
+           else if (strcmp(*argv, "-threads") == 0) {
+               argc--; argv++;
+               if (!argc) usage();
+               max_threads = atoi(*argv);
+           } 
+#endif
+           else if (strcmp(*argv, "-d") == 0) {
               gss_flags |= GSS_C_DELEG_FLAG;
           } else if (strcmp(*argv, "-seq") == 0) {
               gss_flags |= GSS_C_SEQUENCE_FLAG;
@@ -664,6 +751,13 @@ int main(argc, argv)
      if (argc != 3)
          usage();
 
+#ifdef _WIN32
+     if (max_threads < 1) {
+         fprintf(stderr, "warning: there must be at least one thread\n");
+         max_threads = 1;
+     }
+#endif
+
      server_host = *argv++;
      service_name = *argv++;
      msg = *argv++;
@@ -671,15 +765,34 @@ int main(argc, argv)
      if (mechanism)
         parse_oid(mechanism, &oid);
 
-     for (i = 0; i < ccount; i++) {
-       if (call_server(server_host, port, oid, service_name,
-                      gss_flags, auth_flag, wrap_flag, encrypt_flag, mic_flag,
-                      v1_format,                      msg, use_file, mcount) < 0)
-        exit(1);
+     if (max_threads == 1) {
+         for (i = 0; i < ccount; i++) {
+              worker_bee(0);
+         }
+     } else {
+#ifdef _WIN32
+         for (i = 0; i < ccount; i++) {
+              if ( WaitAndIncrementThreadCounter() ) {
+                   uintptr_t handle = _beginthread(worker_bee, 0, (void *)0);
+                   if (handle == (uintptr_t)-1) {
+                        exit(1);
+                   }
+              } else {
+                   exit(1);
+              }
+         }
+#else
+         /* boom */
+         assert(max_threads == 1);
+#endif
      }
 
      if (oid != GSS_C_NULL_OID)
         (void) gss_release_oid(&min_stat, &oid);
         
+#ifdef _WIN32
+     CleanupHandles();
+#endif
+
      return 0;
 }
index 1347a547b337e9003fa4711b9470b989231db40c..c912792e09ee2b197388e9c7026881908c750ab4 100644 (file)
@@ -160,7 +160,7 @@ int send_token(s, flags, tok)
      int flags;
      gss_buffer_t tok;
 {
-     int len, ret;
+     int ret;
      unsigned char char_flags = (unsigned char) flags;
      unsigned char lenbuf[4];
 
index e5adc618bf86f6c129e550035261bede99921d04..dae67afa28cd9e29ce7ddb979a77febdb1ff20a1 100644 (file)
@@ -20,7 +20,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 /*
- * Copyright (C) 2004 by the Massachusetts Institute of Technology.
+ * Copyright (C) 2004,2005 by the Massachusetts Institute of Technology.
  * All rights reserved.
  *
  * Export of this software from the United States of America may
 #include <windows.h>
 #include <winsock.h>
 #else
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
+#include "port-sockets.h"
 #endif
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 
 static void usage()
 {
-     fprintf(stderr, "Usage: gss-server [-port port] [-verbose] [-once]\n");
+     fprintf(stderr, "Usage: gss-server [-port port] [-verbose] [-once]");
+#ifdef _WIN32
+     fprintf(stderr, " [-threads num]");
+#endif
+     fprintf(stderr, "\n");
      fprintf(stderr, "       [-inetd] [-export] [-logfile file] service_name\n");
      exit(1);
 }
@@ -554,6 +555,90 @@ static int sign_server(s, server_creds, export)
     return(0);
 }
 
+static int max_threads = 1;
+
+#ifdef _WIN32
+static thread_count = 0;
+static HANDLE hMutex = NULL;
+static HANDLE hEvent = NULL;
+
+void
+InitHandles(void)
+{
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+}
+
+void
+CleanupHandles(void)
+{
+    CloseHandle(hMutex);
+    CloseHandle(hEvent);
+}
+
+BOOL
+WaitAndIncrementThreadCounter(void)
+{
+    for (;;) {
+        if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+            if ( thread_count < max_threads ) {
+                thread_count++;
+                ReleaseMutex(hMutex);
+                return TRUE;
+            } else {
+                ReleaseMutex(hMutex);
+
+                if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) {
+                    continue;
+                } else {
+                    return FALSE;
+                }
+            }
+        } else {
+            return FALSE;
+        }
+    }
+}
+
+BOOL
+DecrementAndSignalThreadCounter(void)
+{
+    if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) {
+        if ( thread_count == max_threads )
+            ResetEvent(hEvent);
+        thread_count--;
+        ReleaseMutex(hMutex);
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+#endif
+
+struct _work_plan {
+    int             s;
+    gss_cred_id_t   server_creds;
+    int             export;
+};
+
+void 
+worker_bee(void * param)
+{
+    struct _work_plan *work = (struct _work_plan *) param;
+
+    /* this return value is not checked, because there's
+     * not really anything to do if it fails 
+     */
+    sign_server(work->s, work->server_creds, work->export);
+    closesocket(work->s);
+    free(work);
+
+#ifdef _WIN32
+    if ( max_threads > 1 )
+        DecrementAndSignalThreadCounter();
+#endif
+}
+
 int
 main(argc, argv)
      int argc;
@@ -563,7 +648,6 @@ main(argc, argv)
      gss_cred_id_t server_creds;
      OM_uint32 min_stat;
      u_short port = 4444;
-     int s;
      int once = 0;
      int do_inetd = 0;
      int export = 0;
@@ -576,7 +660,15 @@ main(argc, argv)
               argc--; argv++;
               if (!argc) usage();
               port = atoi(*argv);
-         } else if (strcmp(*argv, "-verbose") == 0) {
+         } 
+#ifdef _WIN32
+          else if (strcmp(*argv, "-threads") == 0) {
+              argc--; argv++;
+              if (!argc) usage();
+              max_threads = atoi(*argv);
+          } 
+#endif
+          else if (strcmp(*argv, "-verbose") == 0) {
              verbose = 1;
          } else if (strcmp(*argv, "-once") == 0) {
              once = 1;
@@ -612,6 +704,18 @@ main(argc, argv)
      if ((*argv)[0] == '-')
          usage();
 
+#ifdef _WIN32
+    if (max_threads < 1) {
+        fprintf(stderr, "warning: there must be at least one thread\n");
+        max_threads = 1;
+    }
+
+    if (max_threads > 1 && do_inetd)
+        fprintf(stderr, "warning: one thread may be used in conjunction with inetd\n");
+
+    InitHandles();
+#endif
+
      service_name = *argv;
 
      if (server_acquire_creds(service_name, &server_creds) < 0)
@@ -627,23 +731,56 @@ main(argc, argv)
         int stmp;
 
         if ((stmp = create_socket(port)) >= 0) {
+             if (listen(stmp, max_threads == 1 ? 0 : max_threads) < 0)
+                 perror("listening on socket");
+
             do {
+                 struct _work_plan * work = malloc(sizeof(struct _work_plan));
+
+                 if ( work == NULL ) {
+                     fprintf(stderr, "fatal error: out of memory");
+                     break;
+                 }
+
                 /* Accept a TCP connection */
-                if ((s = accept(stmp, NULL, 0)) < 0) {
+                 if ((work->s = accept(stmp, NULL, 0)) < 0) {
                     perror("accepting connection");
                     continue;
                 }
-                /* this return value is not checked, because there's
-                   not really anything to do if it fails */
-                sign_server(s, server_creds, export);
-                close(s);
+                  
+                 work->server_creds = server_creds;
+                 work->export = export;
+
+                 if (max_threads == 1) {
+                     worker_bee((void *)work);
+                 } 
+#ifdef _WIN32
+                 else {
+                     if ( WaitAndIncrementThreadCounter() ) {
+                         uintptr_t handle = _beginthread(worker_bee, 0, (void *)work);
+                         if (handle == (uintptr_t)-1) {
+                             closesocket(work->s);
+                             free(work);
+                         }
+                     } else {
+                         fprintf(stderr, "fatal error incrementing thread counter");
+                         closesocket(work->s);
+                         free(work);
+                         break;
+                     }
+                 }
+#endif
             } while (!once);
  
-            close(stmp);
+            closesocket(stmp);
         }
      }
 
      (void) gss_release_cred(&min_stat, &server_creds);
 
+#ifdef _WIN32
+    CleanupHandles();
+#endif
+
      return 0;
 }