CASA/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/server.cpp

1351 lines
35 KiB
C++
Raw Normal View History

/***********************************************************************
*
* 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 "ipcint.h"
extern "C" {
#include "casa_s_ipc.h"
}
#include "schannel.h"
#include "serverthread.h"
#include "serverreq.h"
//===[ Type definitions ]==================================================
#define MAX_FILE_PATH_LEN 1024
//
// Socket Mapping definitions
//
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define LINGER struct linger
#define SOCKADDR_IN struct sockaddr_in
#define closesocket close
//===[ Function prototypes ]===============================================
extern unsigned long numServerReqObjects;
extern unsigned long numSChannelObjects;
//===[ Global variables ]==================================================
// Debug variables
int DebugLevel = 0;
bool UseSyslog = false;
// Application Name for logging purposes
char unInitialized[] = "Uninitialized";
char *pAppName = unInitialized;
// Indicators
bool svcInitialized = false;
bool svcStarted = false;
bool serverAddressSet = false;
// Listen Port Number
bool use_AF_INET;
bool use_PF_UNIX;
unsigned short int listenPortNumber = 0;
char listenSocketFile[MAX_FILE_PATH_LEN];
// Listening Socket
int listenSocket = INVALID_SOCKET;
// Operating parameters
bool acceptingConnections = true;
bool terminating = false;
// SChannel list
list<SChannel*> sChannelList;
pthread_mutex_t serverMutex;
// Mutex for interlocked operations
pthread_mutex_t interlockedMutex;
//
// Active Server Request Map - This map contains all of the active ServerReq objects.
// The key used to obtain ServerReq object in the map
// is the request Id. Note, this id is associated with
// a request when ProcessRequest() is called and it does
// not have anything to do with the requests rpc id.
//
typedef map<int32_t, ServerReq*> RSMap;
typedef RSMap::iterator RSMapIter;
typedef pair<RSMapIter, bool> RSIterBoolPair;
RSMap rsMap;
int numActiveRequests = 0;
//
// Next request id (Can not be zero)
//
int32_t nextReqId = 1;
//
// Pending ServerRequests List and count - Server requests are staged on this lists until
// they become active.
//
list<ServerReq*> pendingServerReqList;
int numPendingRequests = 0;
// ServerThreads operating parameters
list<ServerThread*> waitingServerThreadList;
int waitingServerThreads = 0;
//++=======================================================================
int
ServiceRequest(
ServerReq *pServerReq)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L1
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "ServiceRequest- Start\n", 0);
// Obtain server mutex
pthread_mutex_lock(&serverMutex);
// Do not process if trying to terminate
if (!terminating)
{
try {
// Insert the request into the pending server request list
pendingServerReqList.push_back(pServerReq);
numPendingRequests ++;
// Check if there is a thread that can be awaken to process the request
if (waitingServerThreads)
{
// There are waiting ServerThreads, remove one from the list
// and reduce the waitingServerThreads count.
list<ServerThread*>::iterator iter = waitingServerThreadList.begin();
ServerThread *pServerThread = *iter;
waitingServerThreadList.erase(iter);
waitingServerThreads --;
// Wake up the server thread
pServerThread->awaken();
}
// Success
retStatus = 0;
}
catch (...) {
DbgTrace(0, "ServiceRequest- Exception caught\n", 0);
}
}
// Release server mutex
pthread_mutex_unlock(&serverMutex);
DbgTrace(1, "ServiceRequest- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- ServiceRequest() --*/
//++=======================================================================
void
AbortPendingRequests(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "AbortPendingRequests- Start\n", 0);
// Obtain server mutex
pthread_mutex_lock(&serverMutex);
// Abort and delete all of the ServerReq in the pendingServerReqList
while (numPendingRequests)
{
list<ServerReq*>::iterator iter = pendingServerReqList.begin();
ServerReq *pServerReq = *iter;
pendingServerReqList.erase(iter);
numPendingRequests --;
pServerReq->abort();
delete pServerReq;
}
// Release server mutex
pthread_mutex_unlock(&serverMutex);
DbgTrace(1, "AbortPendingRequests- End\n", 0);
} /*-- AbortPendingRequests() --*/
//++=======================================================================
void
AwakenSuspendedServerThreads(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "AwakenSuspendedServerThreads- Start\n", 0);
// Obtain server mutex
pthread_mutex_lock(&serverMutex);
// Awaken all of the ServerThreads in the waitingServerThreadsList
while (waitingServerThreads)
{
list<ServerThread*>::iterator iter = waitingServerThreadList.begin();
ServerThread *pServerThread = *iter;
waitingServerThreadList.erase(iter);
waitingServerThreads --;
// Wake up the server thread
pServerThread->awaken();
}
// Release server mutex
pthread_mutex_unlock(&serverMutex);
DbgTrace(1, "AwakenSuspendedServerThreads- End\n", 0);
} /*-- AwakenSuspendedServerThreads() --*/
//++=======================================================================
void
RemoveFromSChannelList(
SChannel *pSChannel)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
list<SChannel*>::iterator iter;
bool objectRemoved = false;
DbgTrace(1, "RemoveFromSChannelList- Start, Obj = %08X\n", pSChannel);
// Obtain server mutex
pthread_mutex_lock(&serverMutex);
// Find the object in the list
if (!sChannelList.empty())
{
iter = sChannelList.begin();
while (iter != sChannelList.end())
{
if (*iter == pSChannel)
{
// Object found, remove it from the list.
sChannelList.erase(iter);
// Remember that we removed the object
objectRemoved = true;
break;
}
// Proceed to the next item
iter ++;
}
}
// Release server mutex
pthread_mutex_unlock(&serverMutex);
// Check if the object was removed
if (objectRemoved == false)
{
DbgTrace(0, "RemoveFromSChannelList- Error, did not find object in list\n", 0);
}
DbgTrace(1, "RemoveFromSChannelList- End\n", 0);
} /*-- RemoveFromSChannelList() --*/
//++=======================================================================
void
ShutdownSChannels(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
list<SChannel*>::iterator iter;
SChannel *pSChannel;
struct timespec waitTime = {0};
DbgTrace(1, "ShutdownSChannels- Start\n", 0);
// Obtain server mutex
pthread_mutex_lock(&serverMutex);
// Close all of the SChannels in the SChannelList
if (!sChannelList.empty())
{
iter = sChannelList.begin();
while (iter != sChannelList.end())
{
// Found SChannel in the idle list, close it.
(*iter)->closeChannel();
// Move on to the next item in the list
iter ++;
}
}
// Release server mutex
pthread_mutex_unlock(&serverMutex);
// Loop until all SChannels are gone
while (numSChannelObjects != 0)
{
// Wait for sometime
waitTime.tv_sec = 1; // One second
nanosleep(&waitTime, NULL);
}
DbgTrace(1, "ShutdownSChannels- End\n", 0);
} /*-- ShutdownSChannels() --*/
//++=======================================================================
int
OpenSocket(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int openedSocket;
// Open a domain socket if a listen port number has not
// been configured else open a Tcp socket.
if (use_PF_UNIX)
openedSocket = socket(PF_UNIX, SOCK_STREAM, 0);
else
openedSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
return openedSocket;
} /*-- OpenSocket() --*/
//++=======================================================================
int
BindSocket(int socketToBind)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus;
// Bind domain socket if a listen port number has not
// been configured else open a Tcp socket.
if (use_PF_UNIX)
{
struct sockaddr_un listenAddr;
// Set the file creation mask to 000
mode_t prevMask = umask(000);
// Remove pre-existing socket
unlink(listenSocketFile);
// Setup the address that the daemon will use to listen
// for connections.
listenAddr.sun_family = AF_UNIX;
strcpy(listenAddr.sun_path, listenSocketFile);
// Perform the bind operation
retStatus = bind(socketToBind,
(const sockaddr*) &listenAddr,
sizeof(listenAddr.sun_family) + strlen(listenAddr.sun_path));
// Return the file creation mask to its previous value
umask(prevMask);
}
else
{
struct sockaddr_in listenAddr = {0};
int on = 1;
// Setup the address that the daemon will use to listen
// for connections.
listenAddr.sin_family = AF_INET;
listenAddr.sin_addr.s_addr = htonl(INADDR_ANY);
listenAddr.sin_port = htons(listenPortNumber);
// Set the SO_REUSEADDR option on the socket to avoid
// problems in case of a re-start.
setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
// Perform the bind operation
retStatus = bind(socketToBind,
(const sockaddr*) &listenAddr,
sizeof(struct sockaddr_in));
}
return retStatus;
} /*-- BindSocket() --*/
//++=======================================================================
int
AcceptConnection(int acceptPendingSocket)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int connectionSocket;
socklen_t remoteAddrLen;
// Use the appropriate address structure when Accepting connection
if (use_PF_UNIX)
{
struct sockaddr_un remoteAddr;
remoteAddrLen = sizeof(remoteAddr);
// Perform the accept operation
connectionSocket = accept(acceptPendingSocket,
(struct sockaddr*) &remoteAddr,
&remoteAddrLen);
}
else
{
struct sockaddr_in remoteAddr;
remoteAddrLen = sizeof(remoteAddr);
// Perform the accept operation
connectionSocket = accept(acceptPendingSocket,
(struct sockaddr*) &remoteAddr,
&remoteAddrLen);
}
return connectionSocket;
} /*-- AcceptConnection() --*/
//++=======================================================================
void
ServiceConnections(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int connSocket;
SChannel *pSChannel;
bool sChannelAddedToList = false;
DbgTrace(1, "ServiceConnections- Start\n", 0);
// Open listening Tcp socket
listenSocket = OpenSocket();
if (listenSocket != INVALID_SOCKET)
{
// Bind the socket
if (!BindSocket(listenSocket))
{
// Socket has been bound to our listen address, now set
// the socket in listen mode.
if (listen(listenSocket, SOMAXCONN) != SOCKET_ERROR)
{
// The socket is now in listen mode, start accepting connections.
while (acceptingConnections)
{
pSChannel = NULL;
connSocket = AcceptConnection(listenSocket);
if (connSocket != INVALID_SOCKET)
{
// We received a new connection
//
// Obtain server mutex
pthread_mutex_lock(&serverMutex);
// Create a SChannel object to service the connection
try {
pSChannel = new SChannel(connSocket);
// Associate a smart pointer with the channel to make sure
// that it does not go away prematurely while we execute
// SChannel::init(), also, this will allow the object to
// get cleaned up if its initialization fails.
SmartSChannel smartSChannel = pSChannel;
// SChannel created, insert it into the SChannel list.
sChannelList.push_back(pSChannel);
sChannelAddedToList = true;
// Initialize the SChannel
if (pSChannel->init())
{
DbgTrace(0, "ServiceConnections- SChannel intialization failed\n", 0);
// Remove the SChannel object from the SChannel list
sChannelList.pop_back();
sChannelAddedToList = false;
}
}
catch (...) {
DbgTrace(0, "ServiceConnections- Exception caught\n", 0);
// Free necessary resources
if (pSChannel)
{
if (sChannelAddedToList)
sChannelList.pop_back();
delete pSChannel;
}
else
closesocket(connSocket);
}
// Release server mutex
pthread_mutex_unlock(&serverMutex);
}
else
{
// Check if accept failed because we got interrupted
if (errno == EINTR)
{
// We got interrupted during the accept, try again.
continue;
}
else
{
// This could be because the listen socket got closed.
DbgTrace(1, "ServiceConnections- Accept failed, error = %d\n", errno);
// Break out of the accept loop if the socket indeed got closed
if (listenSocket == INVALID_SOCKET)
break;
}
}
}
}
else
{
DbgTrace(0, "ServiceConnections- Listen failed, error = %d\n", errno);
}
}
else
{
DbgTrace(0, "ServiceConnections- Unable to bind socket, error = %d\n", errno);
}
// Close listening socket if necessary
if (listenSocket != INVALID_SOCKET)
closesocket(listenSocket);
}
else
{
DbgTrace(0, "ServiceConnections- Unable to open socket, error = %d\n", errno);
}
DbgTrace(1, "ServiceConnections- End\n", 0);
} /*-- ServiceConnections() --*/
//++=======================================================================
void* ServiceConnectionsThread(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ServiceConnectionsThread- Start\n", 0);
// Set the thread in the detached state so that it is cleaned up when it exits
pthread_detach(pthread_self());
// Service connections until no longer necessary
ServiceConnections();
// Clean up
ShutdownSChannels();
DbgTrace(1, "ServiceConnectionsThread- End\n", 0);
// Exit
pthread_exit(NULL);
return 0; // never-reached!
} /*-- ServiceConnectionsThread() --*/
//++=======================================================================
extern "C"
int32_t
IpcServerGetRequest(void)
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: The id of the pending request.
// 0 == Not able to wait for request.
//
// Abstract: A server thread invokes this method to be informed when
// a request is received that needs to be acted upon.
//
// Notes: The routine blocks until a request becomes available or
// until the IpcServer is shutdown.
//
// An application can execute this method from multiple
// threads to allow requests to be process concurrently.
//
// L1
//=======================================================================--
{
int32_t requestId = 0;
DbgTrace(1, "IpcServerGetRequest- Start\n", 0);
// Make sure that the service has been started
if (!svcStarted)
{
DbgTrace(0, "IpcServerGetRequest- Service has not been started\n", 0);
goto exit;
}
try {
// Instantiate ServerThread object
ServerThread serverThread;
// Obtain server mutex
pthread_mutex_lock(&serverMutex);
// Try to find a request to process
while (!terminating)
{
// Make sure that this is initialized to zero
requestId = 0;
// Check if there is a request for us to process
if (numPendingRequests)
{
// Obtain pending request and place it in the active map
list<ServerReq*>::iterator iter = pendingServerReqList.begin();
ServerReq *pServerReq = *iter;
pendingServerReqList.erase(iter);
numPendingRequests --;
// Assign an id to this request and increment
// the nextReqId.
//
// Protect against zero since it is not valid.
if (nextReqId != 0)
{
requestId = nextReqId;
nextReqId ++;
}
else
{
requestId = 1;
nextReqId = 2;
}
// Place the request in the active request map
RSIterBoolPair insertResult = rsMap.insert(make_pair(requestId, pServerReq));
if (!insertResult.second)
{
// Insertion failed
DbgTrace(0, "IpcServerGetRequest- Unable to insert ServerReq into map\n", 0);
// Abort and free the request
pServerReq->abort();
delete pServerReq;
// Try again
continue;
}
else
{
// Increment the number of active requests
numActiveRequests ++;
// Exit to allow the calling thread to process the request
break;
}
}
else
{
// There is not a request for us to process, place us on the waiting
// server thread list and wait to be awaken.
waitingServerThreadList.push_back(&serverThread);
waitingServerThreads ++;
serverThread.suspend(&serverMutex);
}
}
// Release server mutex
pthread_mutex_unlock(&serverMutex);
}
catch (...) {
DbgTrace(1, "IpcServerGetRequest- Exception caught\n", 0);
}
exit:
DbgTrace(1, "IpcServerGetRequest- End, requestId = %08X\n", requestId);
return requestId;
} /*-- IpcServerGetRequest() --*/
//++=======================================================================
extern "C"
int32_t
IpcServerGetRequestData(
IN int32_t requestId,
INOUT char **ppReqData)
//
// Arguments In: requestId - The id of the request being processed.
//
// Arguments Out: ppReqData - Pointer to variable that will receive a
// pointer to the buffer containing the request
// data the client.
//
// Returns: The length of the request data returned.
//
// Abstract: Method to obtain the data associated with a particular
// request.
//
// Notes: The returned buffer SHOULD NOT be released by the calling
// application.
//
// L1
//=======================================================================--
{
int32_t reqDataLen = 0;
DbgTrace(1, "IpcServerGetRequestData- Start, requestId = %08X\n", requestId);
// Make sure that the service has been started
if (svcStarted)
{
// Obtain server mutex
pthread_mutex_lock(&serverMutex);
// Find request in the active map
RSMapIter iter = rsMap.find(requestId);
if (iter != rsMap.end())
{
// Request was found in the map, obtain a reference to it.
ServerReq *pServerReq = iter->second;
// Release server mutex
pthread_mutex_unlock(&serverMutex);
// Obtain the request data associated with the request
reqDataLen = pServerReq->getReqData(ppReqData);
}
else
{
DbgTrace(0, "IpcServerGetRequestData- Request not found in map\n", 0);
// Release server mutex
pthread_mutex_unlock(&serverMutex);
}
}
else
{
DbgTrace(0, "IpcServerGetRequestData- Service has not been started\n", 0);
}
DbgTrace(1, "IpcServerGetRequestData- End, reqDataLen = %08X\n", reqDataLen);
return reqDataLen;
} /*-- IpcServerGetRequestData() --*/
//++=======================================================================
extern "C"
void
IpcServerCompleteRequest(
IN int32_t requestId,
IN char *pReplyData)
//
// Arguments In: requestId - The id of the request being completed.
//
// pReplyData - Pointer to reply data that must be sent to
// the client for this request.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Method to complete a request being processed.
//
// Notes: The returned buffer will not NOT be released by the method.
//
// L1
//=======================================================================--
{
DbgTrace(1, "IpcServerCompleteRequest- Start, requestId = %08X\n", requestId);
// Make sure that the service has been started
if (svcStarted)
{
// Obtain server mutex
pthread_mutex_lock(&serverMutex);
// Find request in the active map
RSMapIter iter = rsMap.find(requestId);
if (iter != rsMap.end())
{
// Request was found in the map, get a reference to it and
// remove it from the map>
ServerReq *pServerReq = iter->second;
rsMap.erase(iter);
numActiveRequests --;
// Release server mutex
pthread_mutex_unlock(&serverMutex);
// Coomplete the request and delete it.
pServerReq->complete(pReplyData);
delete pServerReq;
}
else
{
DbgTrace(0, "IpcServerCompleteRequest- Request not found in map\n", 0);
// Release server mutex
pthread_mutex_unlock(&serverMutex);
}
}
else
{
DbgTrace(0, "IpcServerCompleteRequest- Service has not been started\n", 0);
}
DbgTrace(1, "IpcServerCompleteRequest- End\n", 0);
} /*-- IpcServerCompleteRequest() --*/
//++=======================================================================
extern "C"
void
IpcServerAbortRequest(
IN int32_t requestId)
//
// Arguments In: requestId - The id of the request being aborted.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Method to abort a request being processed.
//
// Notes:
//
// L1
//=======================================================================--
{
DbgTrace(1, "IpcServerAbortRequest- Start, requestId = %08X\n", requestId);
// Make sure that the service has been started
if (svcStarted)
{
// Obtain server mutex
pthread_mutex_lock(&serverMutex);
// Find request in the active map
RSMapIter iter = rsMap.find(requestId);
if (iter != rsMap.end())
{
// Request was found in the map, get a reference to it and
// remove it from the map>
ServerReq *pServerReq = iter->second;
rsMap.erase(iter);
numActiveRequests --;
// Release server mutex
pthread_mutex_unlock(&serverMutex);
// Coomplete the request and delete it.
pServerReq->abort();
delete pServerReq;
}
else
{
DbgTrace(0, "IpcServerAbortRequest- Request not found in map\n", 0);
// Release server mutex
pthread_mutex_unlock(&serverMutex);
}
}
else
{
DbgTrace(0, "IpcServerAbortRequest- Service has not been started\n", 0);
}
DbgTrace(1, "IpcServerAbortRequest- End\n", 0);
} /*-- IpcServerAbortRequest() --*/
//++=======================================================================
extern "C"
int
IpcServerStart(void)
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to enable the reception of server requests.
//
// Note: The service needs to be initialized and the listen address
// needs to be set before calling this procedure.
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "IpcServerStart- Start\n", 0);
// Make sure that the listen address has been set
if (serverAddressSet)
{
// Do not do anything if we have already been started
if (!svcStarted)
{
// Create a threat to service connections
pthread_t thread;
int threadCreateStatus;
threadCreateStatus = pthread_create(&thread,
NULL,
(void*(*)(void*))ServiceConnectionsThread,
(void*)NULL);
if (threadCreateStatus != 0)
{
DbgTrace(0, "IpcServerStart- Unable to create service connections thread, error = %08X\n", threadCreateStatus);
retStatus = -1;
}
else
{
// Success
svcStarted = true;
retStatus = 0;
}
}
}
else
{
DbgTrace(0, "IpcServerStart- Either not initialized or the address has not been set\n", 0);
}
DbgTrace(1, "IpcServerStart- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- IpcServerStart() --*/
//++=======================================================================
extern "C"
int
IpcServerSetUnAddress(
IN char *pSocketFileName)
//
// Arguments In: pSocketFileName - Pointer to string containing the name
// of the socket file to listen on.
//
// Arguments Out: None.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to set the socket file name to utilize for
// communicating with the server via DOMAIN sockets.
//
// Note: The service needs to be initialized before calling this procedure.
//
// L1
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "IpcServerSetUnAddress- Start\n", 0);
// Verify the input parameters
if (pSocketFileName == NULL
|| strlen(pSocketFileName) >= sizeof(listenSocketFile))
{
DbgTrace(0, "IpcServerSetUnAddress- Invalid input parameter\n", 0);
goto exit;
}
// Make sure that we have been initialized
if (svcInitialized)
{
// Make sure that the address has not already been set.
if (serverAddressSet == false)
{
// Save a copy of the socket file name
strcpy(listenSocketFile, pSocketFileName);
// Remember this
serverAddressSet = true;
use_AF_INET = false;
use_PF_UNIX = true;
// Success
retStatus = 0;
}
else
{
DbgTrace(0, "IpcServerSetUnAddress- Already set\n", 0);
}
}
else
{
DbgTrace(0, "IpcServerSetUnAddress- Service not yet initialized\n", 0);
}
exit:
DbgTrace(1, "IpcServerSetUnAddress- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- IpcServerSetUnAddress() --*/
//++=======================================================================
extern "C"
int
IpcServerSetInAddress(
IN unsigned short int listenPort)
//
// Arguments In: serverPort - Server's listening port number.
//
// Arguments Out: None.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to set the address to utilize for communicating
// with the server via TCP sockets.
//
// Note: The service needs to be initialized before calling this procedure.
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "IpcServerSetInAddress- Start\n", 0);
// Verify the input parameters
if (listenPort == 0)
{
DbgTrace(0, "IpcServerSetInAddress- Invalid input parameter\n", 0);
goto exit;
}
// Make sure that we have been initialized
if (svcInitialized)
{
// Make sure that the address has not already been set.
if (serverAddressSet == false)
{
// Save the listen port number
listenPortNumber = listenPort;
// Remember this
serverAddressSet = true;
use_AF_INET = true;
use_PF_UNIX = false;
// Success
retStatus = 0;
}
else
{
DbgTrace(0, "IpcServerSetInAddress- Already set\n", 0);
}
}
else
{
DbgTrace(0, "IpcServerSetInAddress- Service not yet initialized\n", 0);
}
exit:
DbgTrace(1, "IpcServerSetInAddress- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- IpcServerSetInAddress() --*/
//++=======================================================================
extern "C"
int
IpcServerInit(
IN char *pName,
IN int debugLevel,
IN bool useSyslog)
//
// Arguments In: pName - Pointer to string containing the name that the
// calling application wants associated with the
// debug logs emitted by the library.
//
// debugLevel - The level that the library should use for
// determining what information should be logged
// for debugging purposes. 0 being the lowest
// level.
//
// useSyslog - Set to TRUE to log debug statements using Syslog,
// else debugs are log to stderr.
//
// Arguments Out: None.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to initialize the IPC infrastructure for process.
//
// Note: It is necessary to call the start procedure to start
// servicing requests.
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "IpcServerInit- Start\n", 0);
// Check input parameters
if (pAppName == NULL)
{
DbgTrace(0, "IpcServerInit- Invalid parameter\n", 0);
goto exit;
}
// Save a copy of the application name
pAppName = new char[strlen(pName) + 1];
if (pAppName == NULL)
{
DbgTrace(0, "IpcServerInit- Memory allocation failure\n", 0);
goto exit;
}
strcpy(pAppName, pName);
// Save the rest of the debug settings
DebugLevel = debugLevel;
UseSyslog = useSyslog;
// Set to ignore SIGPIPE signals
signal(SIGPIPE, SIG_IGN);
// Initialize our mutexes
pthread_mutex_init(&serverMutex, NULL);
pthread_mutex_init(&interlockedMutex, NULL);
// Success
svcInitialized = true;
retStatus = 0;
exit:
DbgTrace(1, "IpcServerInit- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- IpcServerInit() --*/
//++=======================================================================
extern "C"
void
IpcServerShutdown(void)
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Method to shutdown the IPC service.
//
// Note:
//
// L2
//=======================================================================--
{
DbgTrace(1, "IpcServerShutdown- Start\n", 0);
// Verify that we have been initialized
if (svcInitialized)
{
// We are being asked to terminate
terminating = true;
// Abort all pending requests
AbortPendingRequests();
// Awaken any suspended server threads
AwakenSuspendedServerThreads();
// Wait for all of the active requests to complete
while (numActiveRequests)
sleep(1);
// Close the listen socket if not already closed. This will
// cause the ServiceConnectionsThread to clean things up and
// shutdown.
if (listenSocket != INVALID_SOCKET)
{
// Close the socket
closesocket(listenSocket);
listenSocket = INVALID_SOCKET;
}
// Forget about having being initialized
svcInitialized = false;
}
// Free the AppName string if necessary
if (pAppName != unInitialized)
{
delete[] pAppName;
pAppName = unInitialized;
}
// Forget about some things
serverAddressSet = false;
svcInitialized = false;
DbgTrace(1, "IpcServerShutdown- End\n", 0);
} /*-- IpcServerShutdown() --*/
//=========================================================================
//=========================================================================