Created the Validate AuthToken Daemon. There is still work to be done on
this component.
This commit is contained in:
		| @@ -20,9 +20,9 @@ | ||||
| # | ||||
| ####################################################################### | ||||
|  | ||||
| SUBDIRS = $(TARGET_OS) idenTokenProviders | ||||
| SUBDIRS = $(TARGET_OS) idenTokenProviders Svc | ||||
|  | ||||
| DIST_SUBDIRS = linux idenTokenProviders | ||||
| DIST_SUBDIRS = linux idenTokenProviders Svc | ||||
|  | ||||
| CFILES = | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,37 @@ | ||||
| ####################################################################### | ||||
| # | ||||
| #  Copyright (C) 2006 Novell, Inc. | ||||
| # | ||||
| #  This program is free software; you can redistribute it and/or | ||||
| #  modify it under the terms of the GNU General Public | ||||
| #  License as published by the Free Software Foundation; either | ||||
| #  version 2 of the License, or (at your option) any later version. | ||||
| # | ||||
| #  This program is distributed in the hope that it will be useful, | ||||
| #  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
| #  General Public License for more details. | ||||
| # | ||||
| #  You should have received a copy of the GNU General Public | ||||
| #  License along with this program; if not, write to the Free | ||||
| #  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| # | ||||
| #  Author: Juan Carlos Luciani <jluciani@novell.com> | ||||
| # | ||||
| ####################################################################### | ||||
|  | ||||
| SUBDIRS = $(TARGET_OS) | ||||
|  | ||||
| DIST_SUBDIRS = linux | ||||
|  | ||||
| CFILES = | ||||
|  | ||||
| EXTRA_DIST = $(CFILES) *.h | ||||
|  | ||||
| .PHONY: package package-clean package-install package-uninstall | ||||
| package package-clean package-install package-uninstall: | ||||
| 	$(MAKE) -C $(TARGET_OS) $@ | ||||
|  | ||||
| maintainer-clean-local: | ||||
| 	rm -f Makefile.in | ||||
|  | ||||
| @@ -0,0 +1,116 @@ | ||||
| ####################################################################### | ||||
| # | ||||
| #  Copyright (C) 2006 Novell, Inc. | ||||
| # | ||||
| #  This program is free software; you can redistribute it and/or | ||||
| #  modify it under the terms of the GNU General Public | ||||
| #  License as published by the Free Software Foundation; either | ||||
| #  version 2 of the License, or (at your option) any later version. | ||||
| # | ||||
| #  This program is distributed in the hope that it will be useful, | ||||
| #  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
| #  General Public License for more details. | ||||
| # | ||||
| #  You should have received a copy of the GNU General Public | ||||
| #  License along with this program; if not, write to the Free | ||||
| #  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| # | ||||
| #  Author: Juan Carlos Luciani <jluciani@novell.com> | ||||
| # | ||||
| ####################################################################### | ||||
|  | ||||
| if DEBUG | ||||
| TARGET_CFG = Debug | ||||
| CFLAGS += -v -w | ||||
| DEFINES = -DDBG | ||||
| else | ||||
| TARGET_CFG = Release | ||||
| DEFINES = -DNDEBUG | ||||
| endif | ||||
|  | ||||
| # Override the link setting for C++ | ||||
| LINK = g++ | ||||
|  | ||||
| SUBDIRS = | ||||
|  | ||||
| DIST_SUBDIRS = | ||||
|  | ||||
| ROOT = ../../../.. | ||||
|  | ||||
| LIBDIR = $(ROOT)/$(LIB) | ||||
| BINDIR = $(ROOT)/$(BIN) | ||||
|  | ||||
| # handle Mono secondary dependencies | ||||
| export MONO_PATH := $(MONO_PATH) | ||||
|  | ||||
| MODULE_NAME = CasaAuthtokenValidateD | ||||
|  | ||||
| CFILES = | ||||
|  | ||||
| CPPFILES = server.cpp | ||||
|  | ||||
| CSFILES_CSC := | ||||
| INCLUDES = -I. -I$(ROOT)/include | ||||
| RESOURCES = | ||||
| DEFINES += -Wno-format-extra-args -fno-strict-aliasing -fshort-wchar  | ||||
| CFLAGS += $(INCLUDES) $(DEFINES) | ||||
| CPPFLAGS += -fPIC $(INCLUDES) $(DEFINES) | ||||
| LIBS = -lpthread -lcasa_s_ipc | ||||
| LDFLAGS = -L$(LIBDIR)/$(TARGET_CFG) | ||||
|  | ||||
| OBJDIR = ./$(TARGET_CFG)/$(LIB) | ||||
| OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) $(addprefix $(OBJDIR)/, $(CPPFILES:%.cpp=%.o)) | ||||
|  | ||||
| EXTRA_DIST = $(CFILES) *.h | ||||
|  | ||||
| CUR_DIR := $(shell pwd) | ||||
|  | ||||
| all: $(OBJDIR)/$(MODULE_NAME) | ||||
|  | ||||
| # | ||||
| # Pattern based rules. | ||||
| # | ||||
| vpath %.c $(CLIENT) $(COMMON) | ||||
| vpath %.cpp $(CLIENT) $(COMMON) | ||||
|  | ||||
| $(OBJDIR)/%.o: %.c | ||||
| 	$(CC) -c $(CFLAGS) -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/%.o: %.cpp | ||||
| 	$(CC) -c $(CPPFLAGS) -o $@ $< | ||||
|  | ||||
| $(OBJDIR)/$(MODULE_NAME): $(OBJDIR) $(OBJS) | ||||
| 	@echo [======== Linking $@ ========] | ||||
| 	$(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) | ||||
| 	cp -f $(OBJDIR)/$(MODULE_NAME) $(BINDIR)/$(TARGET_CFG)/$(MODULE_NAME) | ||||
|  | ||||
| $(OBJDIR): | ||||
| 	[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR) | ||||
| 	[ -d $(LIBDIR) ] || mkdir -p $(LIBDIR) | ||||
| 	[ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(TARGET_CFG) | ||||
| 	[ -d $(BINDIR) ] || mkdir -p $(BINDIR) | ||||
| 	[ -d $(BINDIR)/$(TARGET_CFG) ] || mkdir -p $(BINDIR)/$(TARGET_CFG) | ||||
|  | ||||
|  | ||||
| install-exec-local: $(OBJDIR)/$(MODULE_NAME) | ||||
| 	$(mkinstalldirs) $(DESTDIR)$(libdir) | ||||
| 	$(INSTALL_PROGRAM) $(OBJDIR)/$(MODULE_NAME) $(DESTDIR)$(libdir)/ | ||||
|  | ||||
| uninstall-local: | ||||
| 	cd $(DESTDIR)$(libdir); rm -f $(OBJDIR)/$(MODULE_NAME) | ||||
| 	rmdir $(DESTDIR)$(libdir) | ||||
|  | ||||
| #installcheck-local: install | ||||
| #	$(mkinstalldirs) $(DESTDIR)$(libdir) | ||||
| #	$(INSTALL_PROGRAM) $(DESTDIR)$(libdir) | ||||
| #	cd $(DESTDIR)$(libdir); $(MONO) | ||||
|  | ||||
| clean-local: | ||||
| 	if [ -d $(TARGET_CFG) ]; then  rm -rf $(TARGET_CFG); fi | ||||
|  | ||||
| distclean-local: | ||||
|  | ||||
| maintainer-clean-local: | ||||
| 	rm -f Makefile.in | ||||
|  | ||||
| @@ -0,0 +1,148 @@ | ||||
| /**********************\************************************************* | ||||
|  *  | ||||
|  *  Copyright (C) 2006 Novell, Inc. All Rights Reserved. | ||||
|  * | ||||
|  *  This library is free software; you can redistribute it and/or | ||||
|  *  modify it under the terms of the GNU Lesser General Public | ||||
|  *  License as published by the Free Software Foundation; version 2.1 | ||||
|  *  of the License. | ||||
|  * | ||||
|  *  This library is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  *  Library Lesser General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU Lesser General Public | ||||
|  *  License along with this library; if not, Novell, Inc. | ||||
|  *  | ||||
|  *  To contact Novell about this file by physical or electronic mail,  | ||||
|  *  you may find current contact information at www.novell.com. | ||||
|  *  | ||||
|  *  Author: Juan Carlos Luciani <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| #ifndef _IPCINT_ | ||||
| #define _IPCINT_ | ||||
|  | ||||
| //===[ Include files ]===================================================== | ||||
|  | ||||
| #include <iostream> | ||||
| #include <string> | ||||
| #include <list> | ||||
| #include <map> | ||||
| #include <vector> | ||||
| using namespace std; | ||||
|  | ||||
| extern "C" { | ||||
| #include <stdint.h> | ||||
| #include <unistd.h> | ||||
| #include <stdio.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/wait.h> | ||||
| #include <errno.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <pthread.h> | ||||
| #include <syslog.h> | ||||
| #include <signal.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/file.h> | ||||
| #include <assert.h>     // Ensure that NDEBUG is defined for release builds! | ||||
| #include <sys/ipc.h> | ||||
| #include <casa_s_ipc.h> | ||||
| } | ||||
|  | ||||
| //===[ External data ]===================================================== | ||||
|  | ||||
| extern int DebugLevel; | ||||
| extern bool UseSyslog; | ||||
| extern char appName[]; | ||||
| extern char *pAppName; | ||||
| extern pthread_mutex_t interlockedMutex; | ||||
|  | ||||
| //===[ Macro definitions ]================================================= | ||||
|  | ||||
| // | ||||
| // DbgTrace macro define | ||||
| // | ||||
| #define MAX_FORMAT_STRING_LEN 1024 | ||||
| #define DbgTrace(LEVEL, X, Y) {                                      \ | ||||
|    if (LEVEL == 0 || DebugLevel >= LEVEL) {                          \ | ||||
|       if (UseSyslog)                                                 \ | ||||
|          syslog(LOG_USER | LOG_INFO, X, Y);                          \ | ||||
|       else {                                                         \ | ||||
|          char *pFormatString = new char[MAX_FORMAT_STRING_LEN];      \ | ||||
|          if (pFormatString) {                                        \ | ||||
|             snprintf(pFormatString, MAX_FORMAT_STRING_LEN, X, Y);    \ | ||||
|             fprintf(stderr, "%s -%s", appName, pFormatString);       \ | ||||
|             delete[] pFormatString;                                  \ | ||||
|          }                                                           \ | ||||
|       }                                                              \ | ||||
|    }                                                                 \ | ||||
| } | ||||
|  | ||||
| // | ||||
| // Interlocked Increment and Decrement macros | ||||
| //  | ||||
| // Well, kind of interlocked :-). | ||||
| //  | ||||
| __inline static unsigned long | ||||
| InterlockedIncrement(unsigned long *pValue) | ||||
| { | ||||
|    unsigned long retVal; | ||||
|    pthread_mutex_lock(&interlockedMutex); | ||||
|    (*pValue) ++; | ||||
|    retVal = *pValue; | ||||
|    pthread_mutex_unlock(&interlockedMutex); | ||||
|    return retVal; | ||||
| } | ||||
|  | ||||
| __inline static unsigned long | ||||
| InterlockedDecrement(unsigned long *pValue) | ||||
| { | ||||
|    unsigned long retVal; | ||||
|    pthread_mutex_lock(&interlockedMutex); | ||||
|    (*pValue) --; | ||||
|    retVal = *pValue; | ||||
|    pthread_mutex_unlock(&interlockedMutex); | ||||
|    return retVal; | ||||
| } | ||||
|  | ||||
| __inline static uint32_t | ||||
| InterlockedIncrement(uint32_t *pValue) | ||||
| { | ||||
|    uint32_t retVal; | ||||
|    pthread_mutex_lock(&interlockedMutex); | ||||
|    (*pValue) ++; | ||||
|    retVal = *pValue; | ||||
|    pthread_mutex_unlock(&interlockedMutex); | ||||
|    return retVal; | ||||
| } | ||||
|  | ||||
| __inline static uint32_t | ||||
| InterlockedDecrement(uint32_t *pValue) | ||||
| { | ||||
|    uint32_t retVal; | ||||
|    pthread_mutex_lock(&interlockedMutex); | ||||
|    (*pValue) --; | ||||
|    retVal = *pValue; | ||||
|    pthread_mutex_unlock(&interlockedMutex); | ||||
|    return retVal; | ||||
| } | ||||
|  | ||||
| //===[ Include files ]===================================================== | ||||
|  | ||||
| //===[ External prototypes ]=============================================== | ||||
|  | ||||
| //===[ Manifest constants ]================================================ | ||||
|  | ||||
| //===[ Type definitions ]================================================== | ||||
|  | ||||
| //===[ Function prototypes ]=============================================== | ||||
|  | ||||
|  | ||||
| #endif // _IPCINT_ | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
| @@ -0,0 +1,639 @@ | ||||
| /*********************************************************************** | ||||
|  *  | ||||
|  *  Copyright (C) 2006 Novell, Inc. All Rights Reserved. | ||||
|  * | ||||
|  *  This library is free software; you can redistribute it and/or | ||||
|  *  modify it under the terms of the GNU Lesser General Public | ||||
|  *  License as published by the Free Software Foundation; version 2.1 | ||||
|  *  of the License. | ||||
|  * | ||||
|  *  This library is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  *  Library Lesser General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU Lesser General Public | ||||
|  *  License along with this library; if not, Novell, Inc. | ||||
|  *  | ||||
|  *  To contact Novell about this file by physical or electronic mail,  | ||||
|  *  you may find current contact information at www.novell.com. | ||||
|  *  | ||||
|  *  Author: Juan Carlos Luciani <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
|  | ||||
| //===[ Include files ]===================================================== | ||||
|  | ||||
| #include "internal.h" | ||||
|  | ||||
| //===[ External data ]===================================================== | ||||
|  | ||||
| //===[ External prototypes ]=============================================== | ||||
|  | ||||
| //===[ Manifest constants ]================================================ | ||||
|  | ||||
| #define MAXFD 64 | ||||
|  | ||||
| #define DOMAIN_SOCKET_FILE_NAME "/var/CASA/authtoken/validate/socket" | ||||
|  | ||||
| //===[ Type definitions ]================================================== | ||||
|  | ||||
| //===[ Function prototypes ]=============================================== | ||||
|  | ||||
| void* | ||||
| WorkerThread(void*); | ||||
|  | ||||
| //===[ Global variables ]================================================== | ||||
|  | ||||
| // Usage string | ||||
| char  usage[] = "\nCasaAuthtokenValidateD: usage: [-p ListenPort] [-b BeginThreads] [-g GrowThreads] [-m MaxThreads] [-D DebugLevel] [-d]\n"; | ||||
|  | ||||
| // Worker thread pool configuration parameters | ||||
| int   beginThreads = 5; | ||||
| int   growThreads = 5; | ||||
| int   maxThreads = 4096; | ||||
| int   minWaitingThreads = beginThreads; | ||||
|  | ||||
| // Worker thread pool operating parameters | ||||
| double   numThreads = 0; | ||||
| double   numBusyThreads = 0; | ||||
|  | ||||
| // Listen Port Number | ||||
| int   listenPortNumber = 5000; | ||||
| //int   listenPortNumber = 0; | ||||
|  | ||||
| // Parameter indicating whether or not XSrv needs to run | ||||
| // as a daemon. | ||||
| bool  daemonize = false; | ||||
|  | ||||
| // Name to use for logging purposes | ||||
| char  appName[] = "CasaAuthtokenValidateD"; | ||||
|  | ||||
| // Debug Level | ||||
| int   DebugLevel = 3; | ||||
| bool  UseSyslog = false; | ||||
|  | ||||
| // Variables for daemon auto-restart after crash feature | ||||
| static bool autoRestartAfterCrash = true; | ||||
|  | ||||
| // Synchronization variables | ||||
| pthread_mutex_t   interlockedMutex; | ||||
| pthread_mutex_t   serverMutex; | ||||
| pthread_cond_t    serverCondition; | ||||
|  | ||||
| // Operating parameters | ||||
| bool  terminating = false; | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| void | ||||
| GrowWorkerThreadPool(int growNumber) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: The serverMutex needs to be held when calling this | ||||
| //         procedure. | ||||
| // | ||||
| // L0 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    DbgTrace(1, "GrowWorkerThreadPool- Start\n", 0); | ||||
|  | ||||
|    for (int i = 0; i < growNumber; i++) | ||||
|    { | ||||
|       int threadCreateStatus; | ||||
|       pthread_t thread; | ||||
|  | ||||
|       if ((threadCreateStatus = pthread_create(&thread, | ||||
|                                                NULL, | ||||
|                                                (void*(*)(void*))WorkerThread, | ||||
|                                                NULL) == 0)) | ||||
|       { | ||||
|          // Worker thread created | ||||
|          numThreads ++; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          DbgTrace(0, "GrowWorkerThreadPool- Thread creation failed, status = %0d\n", threadCreateStatus); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    // Let our server know if we ended up with no worker threads | ||||
|    if (numThreads == 0) | ||||
|       pthread_cond_signal(&serverCondition); | ||||
|  | ||||
|    DbgTrace(1, "GrowWorkerThreadPool- End\n", 0); | ||||
|  | ||||
| }  /*-- GrowWorkerThreadPool() --*/ | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| void | ||||
| WorkerThreadBusy(void) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L0 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    DbgTrace(1, "WorkerThreadBusy- Start\n", 0); | ||||
|  | ||||
|    // Acquire our mutex | ||||
|    pthread_mutex_lock(&serverMutex); | ||||
|  | ||||
|    // Increment the numBusyThread count and grow the number of worker threads | ||||
|    // if necessary. | ||||
|    numBusyThreads ++; | ||||
|    if ((numThreads - numBusyThreads) < minWaitingThreads) | ||||
|       GrowWorkerThreadPool(growThreads); | ||||
|  | ||||
|    // Release our mutex | ||||
|    pthread_mutex_unlock(&serverMutex); | ||||
|  | ||||
|    DbgTrace(1, "WorkerThreadBusy- End\n", 0); | ||||
|  | ||||
| }  /*-- WorkerThreadBusy() --*/ | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| bool | ||||
| WorkerThreadWaiting(void) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L0 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    bool  retValue; | ||||
|  | ||||
|    DbgTrace(1, "WorkerThreadWaiting- Start\n", 0); | ||||
|  | ||||
|    // Acquire our mutex | ||||
|    pthread_mutex_lock(&serverMutex); | ||||
|  | ||||
|    // Decrement the numBusyThread count and determine if there are | ||||
|    // too many of us laying around. | ||||
|    numBusyThreads --; | ||||
|    if ((numThreads - numBusyThreads) > minWaitingThreads | ||||
|        && ((numBusyThreads + growThreads) / numThreads) < 0.33 ) | ||||
|       retValue = true; | ||||
|    else | ||||
|       retValue = false; | ||||
|  | ||||
|    // Release our mutex | ||||
|    pthread_mutex_unlock(&serverMutex); | ||||
|  | ||||
|    DbgTrace(1, "WorkerThreadWaiting- End, retValue = %X\n", retValue); | ||||
|  | ||||
|    return retValue; | ||||
|  | ||||
| }  /*-- WorkerThreadWaiting() --*/ | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| void* | ||||
| WorkerThread(void*) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L0 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    DbgTrace(1, "WorkerThread- Start\n", 0); | ||||
|  | ||||
|    // Set the thread in the detached state so that it is cleaned up when it exits | ||||
| 	pthread_detach(pthread_self()); | ||||
|  | ||||
|    // Loop until told to terminate | ||||
|    while (!terminating) | ||||
|    { | ||||
|       // Get a request that needs servicing | ||||
|       int32_t requestId = IpcServerGetRequest(); | ||||
|       if (requestId != 0) | ||||
|       { | ||||
|          // We got a request that needs servicing, now get the | ||||
|          // data associated with it. | ||||
|          char *pReqData; | ||||
|          int dataLen = IpcServerGetRequestData(requestId, &pReqData); | ||||
|          if (dataLen != 0) | ||||
|          { | ||||
|             // Indicate that we are now busy | ||||
|             WorkerThreadBusy(); | ||||
|  | ||||
|             // Just echo the data back as the reply | ||||
|             IpcServerCompleteRequest(requestId, pReqData); | ||||
|  | ||||
|             // Indicate that we are no longer busy and get indication of | ||||
|             // whether or not we should continue to try to process requests. | ||||
|             if (WorkerThreadWaiting() == true) | ||||
|             { | ||||
|                DbgTrace(1, "WorkerThread- Requested to terminate\n", 0); | ||||
|                break; | ||||
|             } | ||||
|          } | ||||
|          else | ||||
|          { | ||||
|             DbgTrace(0, "WorkerThread- Error obtaining Request data\n", 0); | ||||
|             IpcServerAbortRequest(requestId); | ||||
|          } | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          // No need to service requests any longer | ||||
|          break; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    // Decrement the number of worker threads and signal our main thread | ||||
|    // to terminate itself if we are the last worker thread. | ||||
|    pthread_mutex_lock(&serverMutex); | ||||
|    numThreads --; | ||||
|    if (numThreads == 0) | ||||
|       pthread_cond_signal(&serverCondition); | ||||
|    pthread_mutex_unlock(&serverMutex); | ||||
|  | ||||
|    DbgTrace(1, "WorkerThread- End\n", 0); | ||||
|  | ||||
|    // Exit | ||||
| 	pthread_exit(NULL); | ||||
|  | ||||
| 	return 0;	// never-reached! | ||||
|  | ||||
| }  /*-- WorkerThread() --*/ | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| void | ||||
| SigTermHandler( | ||||
|    int signum) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L2 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    DbgTrace(1, "SigTermHandler- Start\n", 0); | ||||
|  | ||||
|    // Indicate that we are terminating | ||||
|    terminating = true; | ||||
|  | ||||
|    // Shutdown the IPC Server | ||||
|    IpcServerShutdown(); | ||||
|  | ||||
|    DbgTrace(1, "SigTermHandler- End\n", 0); | ||||
|  | ||||
| }  /*-- SigTermHandler() --*/ | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| void | ||||
| DaemonInit( | ||||
|    const char *pname) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: Copy of daemon_init() in Richard Stevens Unix Network | ||||
| //         Programming Book. | ||||
| // | ||||
| // L0 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    pid_t             pid; | ||||
|    char              *pNoAutoRestartEnvvar; | ||||
|  | ||||
|    DbgTrace(1, "DaemonInit- Start\n", 0); | ||||
|  | ||||
|    // Determine if we need to disable the auto-restart after crash feature | ||||
|    if ((pNoAutoRestartEnvvar = getenv("CASA_NO_AUTORESTART_AFTER_CRASH")) != NULL | ||||
|        && strcmp(pNoAutoRestartEnvvar, "0") != 0) | ||||
|    { | ||||
|       DbgTrace(1, "DaemonInit- Disabling daemon auto-restart after crash feature\n", 0); | ||||
|       autoRestartAfterCrash = false; | ||||
|    } | ||||
|  | ||||
|    // Fork to run in the background, check for error. | ||||
|    if ((pid = fork()) == -1) | ||||
|    { | ||||
|       DbgTrace(0, "DaemonInit- Fork error = %d\n", errno); | ||||
|       exit(0); | ||||
|    } | ||||
|    else if (pid != 0) | ||||
|    { | ||||
|       // The fork succeeded and we are the parent process, terminate | ||||
|       // ourselves. | ||||
|       exit(0); | ||||
|    } | ||||
|  | ||||
|    /* 1st child continues */ | ||||
|  | ||||
|    // Become the session leader and set to ignore SIGHUP | ||||
|    setsid(); | ||||
|    signal(SIGHUP, SIG_IGN); | ||||
|  | ||||
|    // Fork again to guarantee that the daemon can not acquire a | ||||
|    // controlling terminal. | ||||
|    if ((pid = fork()) == -1) | ||||
|    { | ||||
|       DbgTrace(0, "DaemonInit- Fork error = %d\n", errno); | ||||
|       exit(0); | ||||
|    } | ||||
|    else if (pid != 0) | ||||
|    { | ||||
|       // The fork succeeded and we are the parent process, terminate | ||||
|       // ourselves. | ||||
|       exit(0); | ||||
|    } | ||||
|  | ||||
|    /* 2nd child continues */ | ||||
|  | ||||
|    // Close any open descriptors | ||||
|    for (int i = 0; i < MAXFD; i++) | ||||
|       close(i); | ||||
|  | ||||
|  | ||||
|    // Spawn a worker | ||||
|    if ((pid = fork()) == -1) | ||||
|    { | ||||
|       DbgTrace(0, "DaemonInit- Fork error = %d\n", errno); | ||||
|       exit(0); | ||||
|    } | ||||
|    else if (pid == 0) | ||||
|    { | ||||
|       // The fork succeeded and we are the worker, continue. | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       // We are the parent of the server, check if we must execute the auto-restart | ||||
|       // server after crash logic. | ||||
|       if (autoRestartAfterCrash) | ||||
|       { | ||||
|          // Execute auto-restart server after crash logic | ||||
|          while (1) | ||||
|          { | ||||
|             int childExitStatus; | ||||
|  | ||||
|             // Wait for children to exit | ||||
|             pid = wait(&childExitStatus); | ||||
|             if (pid != -1) | ||||
|             { | ||||
|                // Fork worker | ||||
|                if ((pid = fork()) == -1) | ||||
|                { | ||||
|                   DbgTrace(0, "DaemonInit- Fork error = %d\n", errno); | ||||
|                   exit(0); | ||||
|                } | ||||
|                else if (pid == 0) | ||||
|                { | ||||
|                   // The fork succeeded and we are the server, exit the loop | ||||
|                   // to start. | ||||
|                   goto childContinue; | ||||
|                } | ||||
|  | ||||
|                // We are the parent process, continue to watch for a terminated child process. | ||||
|                syslog(LOG_USER | LOG_INFO, "CasaAuthtokenValidateD: Worker re-started after it terminated unexpectedly"); | ||||
|                sleep(1);   // To keep from consuming too many cycles | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                // Check if we must exit the loop | ||||
|                if (errno != EINTR) | ||||
|                   break; | ||||
|             } | ||||
|          } | ||||
|       } | ||||
|        | ||||
|       // Terminate ourselves. | ||||
|       exit(0); | ||||
|    } | ||||
|  | ||||
| childContinue: | ||||
|  | ||||
|    // Set flag to inform DbgTrace macros to use Syslog | ||||
|    UseSyslog = true; | ||||
|  | ||||
|    // Change the working directory | ||||
|    chdir("/var/CASA/authtoken/validate"); | ||||
|  | ||||
|    // Clear our file mode creation mask | ||||
|    umask(0); | ||||
|  | ||||
|    // Get ready to log | ||||
|    openlog(appName, LOG_CONS | LOG_NOWAIT | LOG_ODELAY| LOG_PID, LOG_USER); | ||||
|  | ||||
|    if (DebugLevel == 0) | ||||
|       setlogmask(LOG_UPTO(LOG_INFO)); | ||||
|    else | ||||
|       setlogmask(LOG_UPTO(LOG_DEBUG)); | ||||
|  | ||||
|    DbgTrace(1, "DaemonInit- End\n", 0); | ||||
|  | ||||
| }  /*-- DaemonInit() --*/ | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| int | ||||
| main( | ||||
|    int argc, | ||||
|    char* argv[]) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L0 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    int         optionsSpecified = 0; | ||||
|    bool        doneScanning = false; | ||||
|    bool        invalidOption = false; | ||||
|    int         option; | ||||
|  | ||||
|    //printf("**** AuthTokenValidate Daemon ****\n"); | ||||
|  | ||||
|    // Scan through the options specified | ||||
|    while (!doneScanning) | ||||
|    { | ||||
|       opterr = 0; | ||||
|       option = getopt(argc, argv, "m:p:b:g:D:d"); | ||||
|  | ||||
|       // Proceed based on the result | ||||
|       switch (option) | ||||
|       { | ||||
|          case 'p': | ||||
|             // Port number option, record location of | ||||
|             // argument. | ||||
|             listenPortNumber = atoi(optarg); | ||||
|  | ||||
|             optionsSpecified ++; | ||||
|             break; | ||||
|  | ||||
|          case 'b': | ||||
|             // Begin threads option, override the default parameter | ||||
|             // with the value of the option. | ||||
|             beginThreads = atoi(optarg); | ||||
|  | ||||
|             optionsSpecified ++; | ||||
|             break; | ||||
|  | ||||
|          case 'g': | ||||
|             // Grow threads option, override the default parameter | ||||
|             // with the value of the option. | ||||
|             growThreads = atoi(optarg); | ||||
|  | ||||
|             optionsSpecified ++; | ||||
|             break; | ||||
|  | ||||
|          case 'm': | ||||
|             // Max threads option, override the default parameter | ||||
|             // with the value of the option. | ||||
|             maxThreads = atoi(optarg); | ||||
|  | ||||
|             optionsSpecified ++; | ||||
|             break; | ||||
|  | ||||
|          case 'd': | ||||
|             // Run as daemon option | ||||
|             daemonize = true; | ||||
|     | ||||
|             optionsSpecified ++; | ||||
|             break; | ||||
|  | ||||
|          case 'D': | ||||
|             // Set the debug level | ||||
|             DebugLevel = atoi(optarg); | ||||
|             optionsSpecified++; | ||||
|             break; | ||||
|  | ||||
|          case '?': | ||||
|             // Invalid option detected | ||||
|             doneScanning = true; | ||||
|             invalidOption = true; | ||||
|             break; | ||||
|  | ||||
|          default: | ||||
|             // Done scanning | ||||
|             doneScanning = true; | ||||
|             break; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    // Do some sanity checking | ||||
|    if (!invalidOption | ||||
|        && beginThreads > 0 | ||||
|        && maxThreads > (growThreads+beginThreads) | ||||
|        && beginThreads <= maxThreads) | ||||
|    { | ||||
|       // The server is ready to start, check if we must | ||||
|       // run it as a daemon. | ||||
|       if (daemonize) | ||||
|          DaemonInit(argv[0]); | ||||
|  | ||||
|       // Set a handler for SIGTERM | ||||
|       signal(SIGTERM, SigTermHandler); | ||||
|  | ||||
|       // Initialize our mutexes | ||||
|       pthread_mutex_init(&interlockedMutex, NULL); | ||||
|       pthread_mutex_init(&serverMutex, NULL); | ||||
|  | ||||
|       // Initialize the condition that we will use to wait | ||||
|       // for the exit of all of our worker threads. | ||||
|       if (pthread_cond_init(&serverCondition, NULL) == 0) | ||||
|       { | ||||
|          // Initialize the IPC Server | ||||
|          if (IpcServerInit(appName, | ||||
|                            DebugLevel, | ||||
|                            UseSyslog) == 0) | ||||
|          { | ||||
|             // Now setup the appropriate listen address | ||||
|             int setAddressResult; | ||||
|             if (listenPortNumber == 0) | ||||
|                setAddressResult = IpcServerSetUnAddress(DOMAIN_SOCKET_FILE_NAME); | ||||
|             else | ||||
|                setAddressResult = IpcServerSetInAddress(listenPortNumber); | ||||
|  | ||||
|             if (setAddressResult == 0) | ||||
|             { | ||||
|                // Now start the IPC server | ||||
|                if (IpcServerStart() == 0) | ||||
|                { | ||||
|                   // Acquire our mutex | ||||
|                   pthread_mutex_lock(&serverMutex); | ||||
|  | ||||
|                   // Start worker threads | ||||
|                   GrowWorkerThreadPool(beginThreads); | ||||
|  | ||||
|                   // Wait for the worker threads to terminate | ||||
|                   pthread_cond_wait(&serverCondition, &serverMutex); | ||||
|  | ||||
|                   // Release our mutex | ||||
|                   pthread_mutex_unlock(&serverMutex); | ||||
|                } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                DbgTrace(0, "main- Setting of listen address failed\n", 0); | ||||
|             } | ||||
|          } | ||||
|          else | ||||
|          { | ||||
|             DbgTrace(0, "main- Initialization of Ipc server failed\n", 0); | ||||
|          } | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          DbgTrace(0, "main- Condition initialization failed\n", 0); | ||||
|       } | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       // Invalid option detected or the user failed to | ||||
|       // specify the listening port number. | ||||
|       printf(usage, argv[0]); | ||||
|    } | ||||
|  | ||||
|    return 0; | ||||
|  | ||||
| }  /*-- main() --*/ | ||||
|  | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user