The non-java project is being replaced by a client and a server project

in order to allow for the client component to be consumed by
distributions targeting the desktop. This check-in is for the server
project.
This commit is contained in:
Juan Carlos Luciani
2006-11-13 04:05:01 +00:00
parent 4f53c776c9
commit 2cc21a344c
99 changed files with 21159 additions and 0 deletions

View File

@@ -0,0 +1,131 @@
#!/bin/sh
#
# Startup script for the Casa Authtoken Validate Daemon (casa_atvd)
#
# /etc/init.d/casa_atvd
#
# description: casa_atvd validates CASA
# authentication tokens on behalf of native (non-java)
# services.
#
# processname: casa_atvd
# pidfile: None
# config utility: None
### BEGIN INIT INFO
# Provides: casa_atvd
# Required-Start: $local_fs $remote_fs
# X-UnitedLinux-Should-Start: $syslog $time
# Required-Stop: $local_fs $remote_fs
# X-UnitedLinux-Should-Stop: $syslog $time
# Default-Start: 1 2 3 5
# Default-Stop:
# Short-Description: Casa Authtoken Validate Daemon
# Description: Start Casa Authtoken Validate Daemon
### END INIT INFO
. /etc/rc.status
# Shell functions sourced from /etc/rc.status:
# rc_check check and set local and overall rc status
# rc_status check and set local and overall rc status
# rc_status -v ditto but be verbose in local rc status
# rc_status -v -r ditto and clear the local rc status
# rc_failed set local and overall rc status to failed
# rc_reset clear local rc status (overall remains)
# rc_exit exit appropriate to overall rc status
# First reset status of this service
rc_reset
MyStatus()
{
ps ax | grep "$DAEMON" | grep -v grep 2>&1 > /dev/null
if [ "x$?" = "x0" ]; then
RVAL=0
else
RVAL=3
fi
}
START_DAEMON_CMD=start_daemon
START_DAEMON_CMD_FLAG=-u
STATUS=MyStatus
LOG_SUCCESS=log_success_msg
LOG_FAILURE=log_failure_msg
LOG_WARNING=log_warning_msg
ECHO=
DAEMON=/usr/bin/casa_atvd
DAEMON_USER=casaatvd
StartDAEMON()
{
# Source the environments file for our daemon
. /etc/CASA/authtoken/validate/envvars
# Update the limit parameters
#
# Do not allow for unlimited core dumps if the daemon is automatically
# re-starting crashed processes.
if [ $DAEMON_NO_AUTORESTART_AFTER_CRASH ]; then
if [ $DAEMON_NO_AUTORESTART_AFTER_CRASH -ne 0 ]; then
# Feature disabled, allow core dumping.
ulimit -c unlimited
else
# Check if core dumping is allowed with the feature enabled
if [ $DAEMON_COREDUMPS_WANTED ]; then
ulimit -c unlimited
fi
fi
else
# Check if core dumping is allowed with the feature enabled
if [ $DAEMON_COREDUMPS_WANTED ]; then
ulimit -c unlimited
fi
fi
ulimit -f unlimited
# Start the daemon
echo -n "Starting casa_atvd..."
$START_DAEMON_CMD $START_DAEMON_CMD_FLAG $DAEMON_USER $DAEMON -d
RVAL=$?
$ECHO
}
StopDAEMON()
{
echo -n "Stopping casa_atvd..."
killproc $DAEMON
RVAL=$?
$ECHO
}
case "$1" in
start)
StartDAEMON
;;
stop)
StopDAEMON
;;
restart|reload|force-reload)
StopDAEMON
sleep 1
StartDAEMON
;;
status)
$STATUS
;;
*)
echo -n "Usage: $0 <start|stop|restart|reload|force-reload>" > /dev/stderr
RVAL=1
;;
esac
rc_failed $RVAL
rc_status -v
rc_exit

View File

@@ -0,0 +1,122 @@
#######################################################################
#
# 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)
JAVA_LIBDIR = /usr/lib/jvm/java-1.5.0-ibm/jre/bin
JAVA_INCDIR = /usr/lib/jvm/java-1.5.0-ibm/include
# handle Mono secondary dependencies
export MONO_PATH := $(MONO_PATH)
MODULE_NAME = CasaAuthtokenValidateD
CFILES =
CPPFILES = server.cpp
CSFILES_CSC :=
INCLUDES = -I. -I$(ROOT)/include -I$(JAVA_INCDIR)
RESOURCES =
if LIB64
DEFINES += -D_LIB64
endif
CFLAGS += -Wno-format-extra-args -fno-strict-aliasing $(INCLUDES) $(DEFINES)
CPPFLAGS += -Wno-format-extra-args -fno-strict-aliasing -fPIC $(INCLUDES) $(DEFINES) $(RPM_OPT_FLAGS)
LIBS = -lpthread -lcasa_s_ipc -ljvm -ljsig -lj9thr23
LDFLAGS = -L$(LIBDIR)/$(TARGET_CFG) -L$(JAVA_LIBDIR) -L$(JAVA_LIBDIR)/classic
OBJDIR = ./$(TARGET_CFG)/$(LIB)
OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) $(addprefix $(OBJDIR)/, $(CPPFILES:%.cpp=%.o))
EXTRA_DIST = $(CFILES) $(CPPFILES) *.h CasaAuthtokenValidateD envvars
CUR_DIR := $(shell pwd)
all: $(OBJDIR)/$(MODULE_NAME)
#
# Pattern based rules.
#
vpath %.c .
vpath %.cpp .
$(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

View File

@@ -0,0 +1,35 @@
############################################################
# #
# Environment variable file for casa_atvd. #
# #
# Note: This file is sourced by the casa_atvd rc script #
# when starting the service. #
# #
# The following variables are utilized by the daemon #
# and its rc script: #
# #
# DAEMON_NO_AUTORESTART_AFTER_CRASH - #
# #
# Set this variable to "1" if you want to disable the #
# auto-restart daemon after abnormal termination #
# feature. This variable is intended to facilitate #
# the discovery of problems during quality assurance #
# testing. Disabling of the auto-restart daemon after #
# abnormal termination feature will result in a #
# configuration that is less fault tolerant. #
# #
# DAEMON_COREDUMPS_WANTED - #
# #
# Set this variable to allow core dumps to be taken #
# when a daemon terminates abnormally. This variable #
# is only meaningful when the auto-restart daemon #
# feature mentioned above is enabled. Core dumps are #
# allowed to be taken when the auto-restart daemon #
# feature is disabled. Core dumps of novell-xsrvd #
# service processes are taken to the #
# /var/novell/xtier folder. #
# #
############################################################
LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}":/usr/lib/jvm/java-1.5.0-ibm/jre/bin:/usr/lib/jvm/java-1.5.0-ibm/jre/bin/classic
export LD_LIBRARY_PATH

View File

@@ -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_
//=========================================================================
//=========================================================================

View File

@@ -0,0 +1,839 @@
/***********************************************************************
*
* 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"
#include <jni.h>
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
#define MAXFD 64
#define DOMAIN_SOCKET_FILE_NAME "/var/lib/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;
int maxWaitingThreads = beginThreads * 4;
// Worker thread pool operating parameters
double numThreads = 0;
double numBusyThreads = 0;
double numPerishingThreads = 0;
// Listen Port Number
//int listenPortNumber = 5000;
int listenPortNumber = 0;
// Parameter indicating whether or not the server needs to run
// as a daemon.
bool daemonize = false;
// Name to use for logging purposes
char appName[] = "CasaAuthtokenValidateD";
// Debug Level
int DebugLevel = 0;
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;
// Java parameters
JavaVM *g_jvm = NULL;
JNIEnv *g_env = NULL;
char classpath[] = "-Djava.class.path=/usr/share/java/CASA/authtoken/CasaAuthToken.jar:/usr/share/java/CASA/authtoken/external/axis.jar:/usr/share/java/CASA/authtoken/external/axis-ant.jar:/usr/share/java/CASA/authtoken/external/commons-discovery-0.2.jar:/usr/share/java/CASA/authtoken/external/commons-logging-1.0.4.jar:/usr/share/java/CASA/authtoken/external/jaxrpc.jar:/usr/share/java/CASA/authtoken/external/log4j-1.2.8.jar:/usr/share/java/CASA/authtoken/external/saaj.jar:/usr/share/java/CASA/authtoken/external/wsdl4j-1.5.1.jar:/usr/share/java/CASA/authtoken/external/wss4j-1.5.0.jar:/usr/share/java/CASA/authtoken/external/xalan.jar:/usr/share/java/CASA/authtoken/external/xercesImpl.jar:/usr/share/java/CASA/authtoken/external/xml-apis.jar:/usr/share/java/CASA/authtoken/external/xmlsec-1.2.1.jar:/usr/share/java/CASA/authtoken/external:/etc/CASA/authtoken/keys/client";
// Java AuthenticationToken Class and method name
//char authTokenClassName[] = "jtest";
//char authTokenClassValidateMethodName[] = "test4";
char authTokenClassName[] = "com/novell/casa/authtoksvc/AuthToken";
char authTokenClassValidateMethodName[] = "validate";
//++=======================================================================
void
GrowWorkerThreadPool(int growNumber)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes: The serverMutex needs to be held when calling this
// procedure.
//
// L2
//=======================================================================--
{
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:
//
// L2
//=======================================================================--
{
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:
//
// L2
//=======================================================================--
{
bool retValue;
DbgTrace(1, "WorkerThreadWaiting- Start\n", 0);
// Acquire our mutex
pthread_mutex_lock(&serverMutex);
// Decrement the numBusyThread count
numBusyThreads --;
// Check if we have too many idle workers
if ((numThreads - numBusyThreads - numPerishingThreads) > maxWaitingThreads
&& numThreads > beginThreads)
{
// We want to let this worker perish
numPerishingThreads ++;
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:
//
// L2
//=======================================================================--
{
bool perishingThread = false;
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());
// Attach the thread to the JVM
JNIEnv *env;
JavaVMAttachArgs attachArgs = {0};
attachArgs.version = JNI_VERSION_1_4;
if (g_jvm->AttachCurrentThread((void**) &env, &attachArgs) >= 0)
{
// We are now attached to the JVM, find the helper class that
// we need.
jclass helperClass = env->FindClass(authTokenClassName);
if (helperClass)
{
// Helper class found, now get the id of the method that we invoke
jmethodID mId = env->GetStaticMethodID(helperClass,
authTokenClassValidateMethodName,
"(Ljava/lang/String;)Ljava/lang/String;");
if (mId)
{
// 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();
// Lets push the jvm local frame to allow us to clean up our local
// references later.
env->PushLocalFrame(10);
// Encapsulate the request data into a string object
jstring inString = env->NewStringUTF(pReqData);
if (inString)
{
// Invoke our helper method
jstring outString = (jstring) env->CallStaticObjectMethod(helperClass, mId, inString);
// Check if an excption occurred
if (env->ExceptionCheck() == JNI_TRUE)
{
// There is a pending exception, display the info which in turn clears it.
env->ExceptionDescribe();
}
else
{
if (outString)
{
// The helper method succeded, complete the request
// with the data returned.
const char *pOutChars = env->GetStringUTFChars(outString, NULL);
if (pOutChars)
{
IpcServerCompleteRequest(requestId, (char*) pOutChars);
env->ReleaseStringUTFChars(outString, pOutChars);
}
else
{
DbgTrace(0, "WorkerThread- Unable to get UTF characters\n", 0);
IpcServerAbortRequest(requestId);
}
}
else
{
// The helper method failed, just abort the request.
IpcServerAbortRequest(requestId);
}
}
}
else
{
DbgTrace(0, "WorkerThread- UTF String allocation failure\n", 0);
IpcServerAbortRequest(requestId);
}
// Pop the jvm local frame to clean up our local references
env->PopLocalFrame(NULL);
// 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);
// Remember that we are a perishing thread so that we can reduce the
// count as we exit.
perishingThread = true;
break;
}
}
else
{
DbgTrace(0, "WorkerThread- Error obtaining Request data\n", 0);
IpcServerAbortRequest(requestId);
}
}
else
{
// No need to service requests any longer
break;
}
}
}
else
{
DbgTrace(0, "WorkerThread- Failed to get method id\n", 0);
}
}
else
{
DbgTrace(0, "WorkerThread- Failed to find helper class\n", 0);
}
// Detach from the JVM
g_jvm->DetachCurrentThread();
}
else
{
DbgTrace(0, "WorkerThread- Failed to attach to JVM\n", 0);
}
// 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);
if (perishingThread)
numPerishingThreads --;
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() --*/
//++=======================================================================
int
InitJavaInvoke(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "InitJavaInvoke- Start\n", 0);
JavaVMOption options[6];
options[0].optionString = classpath;
options[1].optionString = "-Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser";
options[2].optionString = "-Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl";
options[3].optionString = "-Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl";
//options[4].optionString = "-Xcheck:jni";
//options[5].optionString = "-Djaxp.debug=1";
JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_4;
vm_args.options = options;
vm_args.nOptions = 4;
vm_args.ignoreUnrecognized = true;
if (JNI_CreateJavaVM(&g_jvm, (void**)&g_env, &vm_args) >= 0)
{
// Success
retStatus = 0;
}
else
{
DbgTrace(0, "InitJavaInvoke- Error creating Java VM\n", 0);
}
DbgTrace(1, "InitJavaInvoke- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- InitJavaInvoke() --*/
//++=======================================================================
void
UnInitJavaInvoke(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "UnInitJavaInvoke- Start\n", 0);
// Destroy the jvm
g_jvm->DestroyJavaVM();
g_jvm = NULL;
g_env = NULL;
DbgTrace(1, "UnInitJavaInvoke- End\n", 0);
} /*-- UnInitJavaInvoke() --*/
//++=======================================================================
void
DaemonInit(
const char *pname)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes: Copy of daemon_init() in Richard Stevens Unix Network
// Programming Book.
//
// L2
//=======================================================================--
{
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/lib/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:
//
// L2
//=======================================================================--
{
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 JVM
if (InitJavaInvoke() == 0)
{
// 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);
DbgTrace(0, "main- Exiting, numThreads = %d\n", numThreads);
}
}
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);
}
// Un-initialize JVM
UnInitJavaInvoke();
}
else
{
DbgTrace(0, "main- JVM 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() --*/
//=========================================================================
//=========================================================================