2006-11-13 05:05:01 +01:00
|
|
|
/***********************************************************************
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
|
2006-12-08 06:45:03 +01:00
|
|
|
#define MIN_THREADS 1
|
|
|
|
#define MAX_THREADS 4096
|
|
|
|
#define DEFAULT_BEGIN_THREADS 5
|
|
|
|
#define DEFAULT_GROW_THREADS 5
|
|
|
|
|
2006-11-13 05:05:01 +01:00
|
|
|
#define DOMAIN_SOCKET_FILE_NAME "/var/lib/CASA/authtoken/validate/socket"
|
|
|
|
|
|
|
|
//===[ Type definitions ]==================================================
|
|
|
|
|
|
|
|
//===[ Function prototypes ]===============================================
|
|
|
|
|
|
|
|
void*
|
|
|
|
WorkerThread(void*);
|
|
|
|
|
|
|
|
//===[ Global variables ]==================================================
|
|
|
|
|
|
|
|
// Usage string
|
2006-11-15 06:06:54 +01:00
|
|
|
char usage[] = "\nCasaAuthtokenValidateD: usage: [-p ListenPort] [-b BeginThreads] [-g GrowThreads] [-m MaxThreads] [-D DebugLevel] [-d] [-s]\n";
|
2006-11-13 05:05:01 +01:00
|
|
|
|
|
|
|
// Worker thread pool configuration parameters
|
2006-12-08 06:45:03 +01:00
|
|
|
int beginThreads = DEFAULT_BEGIN_THREADS;
|
|
|
|
int growThreads = DEFAULT_GROW_THREADS;
|
|
|
|
int maxThreads = MAX_THREADS;
|
2006-11-13 05:05:01 +01:00
|
|
|
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;
|
2006-12-08 06:45:03 +01:00
|
|
|
unsigned short int listenPortNumber = 0;
|
2006-11-13 05:05:01 +01:00
|
|
|
|
|
|
|
// 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
|
2006-11-15 06:06:54 +01:00
|
|
|
bool singleThreaded = false;
|
2006-11-13 05:05:01 +01:00
|
|
|
bool terminating = false;
|
|
|
|
|
|
|
|
// Java parameters
|
|
|
|
JavaVM *g_jvm = NULL;
|
|
|
|
JNIEnv *g_env = NULL;
|
|
|
|
|
2007-03-19 17:20:18 +01:00
|
|
|
char classpath[] = "-Djava.class.path=/usr/share/java/CASA/authtoken/CasaJaasSupport.jar:/usr/share/java/CASA/authtoken/CasaAuthToken.jar:/usr/share/java/log4j.jar:/usr/share/java/commons-logging.jar:/usr/share/java/CASA/authtoken/external/apache.org/xmlsec-1.4.0.jar:/usr/share/java/xerces-j2.jar:/etc/CASA/authtoken/keys/client";
|
2006-11-13 05:05:01 +01:00
|
|
|
// Java AuthenticationToken Class and method name
|
|
|
|
//char authTokenClassName[] = "jtest";
|
|
|
|
//char authTokenClassValidateMethodName[] = "test4";
|
|
|
|
char authTokenClassName[] = "com/novell/casa/authtoksvc/AuthToken";
|
|
|
|
char authTokenClassValidateMethodName[] = "validate";
|
|
|
|
|
|
|
|
|
2006-11-15 06:06:54 +01:00
|
|
|
//++=======================================================================
|
|
|
|
void
|
|
|
|
ServiceRequests(void)
|
|
|
|
//
|
|
|
|
// Arguments:
|
|
|
|
//
|
|
|
|
// Returns:
|
|
|
|
//
|
|
|
|
// Abstract:
|
|
|
|
//
|
|
|
|
// Notes:
|
|
|
|
//
|
|
|
|
// L2
|
|
|
|
//=======================================================================--
|
|
|
|
{
|
|
|
|
DbgTrace(1, "ServiceRequests- Start\n", 0);
|
|
|
|
|
|
|
|
// We are now attached to the JVM, find the helper class that
|
|
|
|
// we need.
|
|
|
|
jclass helperClass = g_env->FindClass(authTokenClassName);
|
|
|
|
if (helperClass)
|
|
|
|
{
|
|
|
|
// Helper class found, now get the id of the method that we invoke
|
|
|
|
jmethodID mId = g_env->GetStaticMethodID(helperClass,
|
2007-02-06 23:52:44 +01:00
|
|
|
authTokenClassValidateMethodName,
|
|
|
|
"(Ljava/lang/String;)Ljava/lang/String;");
|
2006-11-15 06:06:54 +01:00
|
|
|
if (mId)
|
|
|
|
{
|
|
|
|
// Loop until told to terminate
|
|
|
|
while (!terminating)
|
|
|
|
{
|
|
|
|
// Get a request that needs servicing
|
2006-12-08 06:45:03 +01:00
|
|
|
uint32_t requestId = IpcServerGetRequest();
|
2006-11-15 06:06:54 +01:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
// Lets push the jvm local frame to allow us to clean up our local
|
|
|
|
// references later.
|
|
|
|
g_env->PushLocalFrame(10);
|
|
|
|
|
|
|
|
// Encapsulate the request data into a string object
|
|
|
|
jstring inString = g_env->NewStringUTF(pReqData);
|
|
|
|
if (inString)
|
|
|
|
{
|
|
|
|
// Invoke our helper method
|
|
|
|
jstring outString = (jstring) g_env->CallStaticObjectMethod(helperClass, mId, inString);
|
|
|
|
|
|
|
|
// Check if an excption occurred
|
|
|
|
if (g_env->ExceptionCheck() == JNI_TRUE)
|
|
|
|
{
|
|
|
|
// There is a pending exception, display the info which in turn clears it.
|
|
|
|
g_env->ExceptionDescribe();
|
|
|
|
IpcServerAbortRequest(requestId);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (outString)
|
|
|
|
{
|
|
|
|
// The helper method succeded, complete the request
|
|
|
|
// with the data returned.
|
|
|
|
const char *pOutChars = g_env->GetStringUTFChars(outString, NULL);
|
|
|
|
if (pOutChars)
|
|
|
|
{
|
|
|
|
IpcServerCompleteRequest(requestId, (char*) pOutChars);
|
|
|
|
g_env->ReleaseStringUTFChars(outString, pOutChars);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DbgTrace(0, "ServiceRequests- Unable to get UTF characters\n", 0);
|
|
|
|
IpcServerAbortRequest(requestId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// The helper method failed, just abort the request.
|
|
|
|
IpcServerAbortRequest(requestId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DbgTrace(0, "ServiceRequests- UTF String allocation failure\n", 0);
|
|
|
|
IpcServerAbortRequest(requestId);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pop the jvm local frame to clean up our local references
|
|
|
|
g_env->PopLocalFrame(NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DbgTrace(0, "ServiceRequests- Error obtaining Request data\n", 0);
|
|
|
|
IpcServerAbortRequest(requestId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// No need to service requests any longer
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DbgTrace(0, "ServiceRequests- Failed to get method id\n", 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DbgTrace(0, "ServiceRequests- Failed to find helper class\n", 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
DbgTrace(1, "ServiceRequests- End\n", 0);
|
|
|
|
|
|
|
|
} /*-- ServiceRequests() --*/
|
|
|
|
|
|
|
|
|
2006-11-13 05:05:01 +01:00
|
|
|
//++=======================================================================
|
|
|
|
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,
|
2006-11-15 06:06:54 +01:00
|
|
|
(void*(*)(void*))WorkerThread,
|
2006-11-13 05:05:01 +01:00
|
|
|
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();
|
2006-11-15 06:06:54 +01:00
|
|
|
IpcServerAbortRequest(requestId);
|
2006-11-13 05:05:01 +01:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2006-11-15 06:06:54 +01:00
|
|
|
// Success
|
|
|
|
retStatus = 0;
|
2006-11-13 05:05:01 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DbgTrace(0, "InitJavaInvoke- Error creating Java VM\n", 0);
|
|
|
|
}
|
|
|
|
|
2006-12-08 06:45:03 +01:00
|
|
|
DbgTrace(1, "InitJavaInvoke- End, retStatus = %0X\n", retStatus);
|
2006-11-13 05:05:01 +01:00
|
|
|
|
|
|
|
return retStatus;
|
|
|
|
|
|
|
|
} /*-- InitJavaInvoke() --*/
|
|
|
|
|
|
|
|
|
|
|
|
//++=======================================================================
|
|
|
|
void
|
|
|
|
UnInitJavaInvoke(void)
|
|
|
|
//
|
|
|
|
// Arguments:
|
|
|
|
//
|
|
|
|
// Returns:
|
|
|
|
//
|
|
|
|
// Abstract:
|
|
|
|
//
|
|
|
|
// Notes:
|
|
|
|
//
|
|
|
|
// L2
|
|
|
|
//=======================================================================--
|
|
|
|
{
|
|
|
|
DbgTrace(1, "UnInitJavaInvoke- Start\n", 0);
|
|
|
|
|
|
|
|
// Destroy the jvm
|
2006-12-08 06:45:03 +01:00
|
|
|
if (g_jvm)
|
|
|
|
{
|
|
|
|
g_jvm->DestroyJavaVM();
|
|
|
|
g_jvm = NULL;
|
|
|
|
}
|
2006-11-13 05:05:01 +01:00
|
|
|
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)
|
|
|
|
{
|
2006-12-08 06:45:03 +01:00
|
|
|
long int value = 0;
|
2006-11-13 05:05:01 +01:00
|
|
|
opterr = 0;
|
2006-11-15 06:06:54 +01:00
|
|
|
option = getopt(argc, argv, "m:p:b:g:D:ds");
|
2006-11-13 05:05:01 +01:00
|
|
|
|
|
|
|
// Proceed based on the result
|
|
|
|
switch (option)
|
|
|
|
{
|
|
|
|
case 'p':
|
|
|
|
// Port number option, record location of
|
|
|
|
// argument.
|
2006-12-08 06:45:03 +01:00
|
|
|
errno = 0;
|
|
|
|
value = strtol(optarg, (char**) NULL, 10);
|
|
|
|
if (errno == 0
|
|
|
|
&& value > 0
|
|
|
|
&& value <= USHRT_MAX)
|
|
|
|
{
|
|
|
|
listenPortNumber = (unsigned short int) value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Specified ListenPort parameter out of range, using default value");
|
|
|
|
}
|
2006-11-13 05:05:01 +01:00
|
|
|
optionsSpecified ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'b':
|
|
|
|
// Begin threads option, override the default parameter
|
|
|
|
// with the value of the option.
|
2006-12-08 06:45:03 +01:00
|
|
|
errno = 0;
|
|
|
|
value = strtol(optarg, (char**) NULL, 10);
|
|
|
|
if (errno == 0
|
|
|
|
&& value >= MIN_THREADS
|
|
|
|
&& value <= MAX_THREADS)
|
|
|
|
{
|
|
|
|
beginThreads = (int) value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Specified BeginThreads parameter out of range, using default value");
|
|
|
|
}
|
2006-11-13 05:05:01 +01:00
|
|
|
|
|
|
|
optionsSpecified ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'g':
|
|
|
|
// Grow threads option, override the default parameter
|
|
|
|
// with the value of the option.
|
2006-12-08 06:45:03 +01:00
|
|
|
errno = 0;
|
|
|
|
value = strtol(optarg, (char**) NULL, 10);
|
|
|
|
if (errno == 0
|
|
|
|
&& value >= MIN_THREADS
|
|
|
|
&& value <= MAX_THREADS)
|
|
|
|
{
|
|
|
|
growThreads = (int) value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Specified GrowThreads parameter out of range, using default value");
|
|
|
|
}
|
2006-11-13 05:05:01 +01:00
|
|
|
|
|
|
|
optionsSpecified ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'm':
|
|
|
|
// Max threads option, override the default parameter
|
|
|
|
// with the value of the option.
|
2006-12-08 06:45:03 +01:00
|
|
|
errno = 0;
|
|
|
|
value = strtol(optarg, (char**) NULL, 10);
|
|
|
|
if (errno == 0
|
|
|
|
&& value >= MIN_THREADS
|
|
|
|
&& value <= MAX_THREADS)
|
|
|
|
{
|
|
|
|
maxThreads = (int) value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Specified MaxThreads parameter out of range, using default value");
|
|
|
|
}
|
2006-11-13 05:05:01 +01:00
|
|
|
|
|
|
|
optionsSpecified ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd':
|
|
|
|
// Run as daemon option
|
|
|
|
daemonize = true;
|
|
|
|
|
|
|
|
optionsSpecified ++;
|
|
|
|
break;
|
|
|
|
|
2006-11-15 06:06:54 +01:00
|
|
|
case 's':
|
|
|
|
// Run single threaded
|
|
|
|
singleThreaded = true;
|
2006-11-14 09:07:01 +01:00
|
|
|
|
|
|
|
optionsSpecified ++;
|
|
|
|
break;
|
2006-11-15 06:06:54 +01:00
|
|
|
|
2006-11-13 05:05:01 +01:00
|
|
|
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)
|
|
|
|
{
|
2006-11-15 06:06:54 +01:00
|
|
|
// Proceed according to run model configured
|
|
|
|
if (singleThreaded)
|
|
|
|
{
|
|
|
|
// Runninf in single-threaded model
|
|
|
|
ServiceRequests();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Running in multi-threaded model
|
|
|
|
//
|
|
|
|
// Acquire our mutex
|
|
|
|
pthread_mutex_lock(&serverMutex);
|
2006-11-13 05:05:01 +01:00
|
|
|
|
2006-11-15 06:06:54 +01:00
|
|
|
// Start worker threads
|
|
|
|
GrowWorkerThreadPool(beginThreads);
|
2006-11-13 05:05:01 +01:00
|
|
|
|
2006-11-15 06:06:54 +01:00
|
|
|
// Wait for the worker threads to terminate
|
|
|
|
pthread_cond_wait(&serverCondition, &serverMutex);
|
2006-11-13 05:05:01 +01:00
|
|
|
|
2006-11-15 06:06:54 +01:00
|
|
|
// Release our mutex
|
|
|
|
pthread_mutex_unlock(&serverMutex);
|
|
|
|
}
|
2006-11-13 05:05:01 +01:00
|
|
|
|
|
|
|
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.
|
2006-12-08 06:45:03 +01:00
|
|
|
fprintf(stderr, usage, argv[0]);
|
2006-11-13 05:05:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
} /*-- main() --*/
|
|
|
|
|
|
|
|
|
|
|
|
//=========================================================================
|
|
|
|
//=========================================================================
|
|
|
|
|
|
|
|
|