Enhanced to allow clients to submit requests to different remote
endpoints.
This commit is contained in:
parent
48d4d947ea
commit
960d27db69
@ -56,6 +56,7 @@ CFILES =
|
|||||||
CPPFILES = channelproto.cpp \
|
CPPFILES = channelproto.cpp \
|
||||||
cchannel.cpp \
|
cchannel.cpp \
|
||||||
clientreq.cpp \
|
clientreq.cpp \
|
||||||
|
remoteendpoint.cpp \
|
||||||
client.cpp
|
client.cpp
|
||||||
|
|
||||||
CSFILES_CSC :=
|
CSFILES_CSC :=
|
||||||
|
@ -33,6 +33,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include "cchannel.h"
|
#include "cchannel.h"
|
||||||
#include "clientreq.h"
|
#include "clientreq.h"
|
||||||
|
#include "remoteendpoint.h"
|
||||||
|
|
||||||
|
|
||||||
//===[ External data ]=====================================================
|
//===[ External data ]=====================================================
|
||||||
@ -41,27 +42,10 @@ extern "C" {
|
|||||||
|
|
||||||
//===[ Manifest constants ]================================================
|
//===[ Manifest constants ]================================================
|
||||||
|
|
||||||
#define MAX_RPC_RETRIES 3
|
#define DEFAULT_MAX_RPC_RETRIES 3
|
||||||
|
|
||||||
#define MAX_CHANNELS 3
|
|
||||||
|
|
||||||
//===[ Type definitions ]==================================================
|
//===[ Type definitions ]==================================================
|
||||||
|
|
||||||
//
|
|
||||||
// Class for maintaining SmartCChannel pointers within the daemonVector.
|
|
||||||
//
|
|
||||||
class SmartCChannelPointer
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
SmartCChannel *m_pSmartCChannel;
|
|
||||||
public:
|
|
||||||
|
|
||||||
SmartCChannelPointer() : m_pSmartCChannel(NULL) {}
|
|
||||||
~SmartCChannelPointer() { if (m_pSmartCChannel != NULL) delete m_pSmartCChannel; }
|
|
||||||
SmartCChannel* getPointer() { return m_pSmartCChannel; }
|
|
||||||
void setPointer(SmartCChannel *pSmartCChannel) { m_pSmartCChannel = pSmartCChannel; }
|
|
||||||
};
|
|
||||||
|
|
||||||
//===[ Function prototypes ]===============================================
|
//===[ Function prototypes ]===============================================
|
||||||
|
|
||||||
//===[ Global variables ]==================================================
|
//===[ Global variables ]==================================================
|
||||||
@ -74,9 +58,8 @@ bool UseSyslog = false;
|
|||||||
char unInitialized[] = "Uninitialized";
|
char unInitialized[] = "Uninitialized";
|
||||||
char *pAppName = unInitialized;
|
char *pAppName = unInitialized;
|
||||||
|
|
||||||
vector<SmartCChannelPointer> cchannelVector;
|
// Application threaded information
|
||||||
int numCChannels;
|
bool appMultithreaded;
|
||||||
int numChannelSubmits = 0;
|
|
||||||
|
|
||||||
// Client mutex
|
// Client mutex
|
||||||
pthread_mutex_t clientMutex;
|
pthread_mutex_t clientMutex;
|
||||||
@ -84,52 +67,379 @@ pthread_mutex_t clientMutex;
|
|||||||
// Mutex for interlocked operations
|
// Mutex for interlocked operations
|
||||||
pthread_mutex_t interlockedMutex;
|
pthread_mutex_t interlockedMutex;
|
||||||
|
|
||||||
// Indications
|
// Indicators
|
||||||
bool svcInitialized = false;
|
bool svcInitialized = false;
|
||||||
bool serverAddressSet = false;
|
|
||||||
|
|
||||||
// Server address variables
|
// Map of open remote endpoints.
|
||||||
bool use_AF_INET;
|
//
|
||||||
bool use_PF_UNIX;
|
// This map contains all of the open remote
|
||||||
struct sockaddr_in serverInAddr = {0};
|
// endpoint objects. The key used to obtain
|
||||||
struct sockaddr_un serverUnAddr = {0};
|
// RemoteEndPoint objects from the map is an
|
||||||
|
// object handle.
|
||||||
|
//
|
||||||
|
typedef map<uint32_t, SmartPtr<RemoteEndPoint>*> REPMap;
|
||||||
|
typedef REPMap::iterator REPMapIter;
|
||||||
|
typedef pair<REPMapIter, bool> REPIterBoolPair;
|
||||||
|
REPMap repMap;
|
||||||
|
|
||||||
|
// RemoteEndPoint handle allocator
|
||||||
|
uint32_t remoteEndPointHandleAllocator = 1;
|
||||||
|
|
||||||
|
|
||||||
//++=======================================================================
|
//++=======================================================================
|
||||||
void
|
extern "C"
|
||||||
ReInitializeIpc(void)
|
int
|
||||||
|
IpcClientOpenUnixRemoteEndPoint(
|
||||||
|
IN char *pSocketFileName,
|
||||||
|
IN int maxRpcRetries,
|
||||||
|
INOUT uint32_t *pEndPointHandle)
|
||||||
//
|
//
|
||||||
// Arguments In: None.
|
// Arguments In: port - Server's listening port number.
|
||||||
|
//
|
||||||
|
// address - The server's IP Address. Use
|
||||||
|
// 0x7F000001 if the server is local.
|
||||||
|
//
|
||||||
|
// maxRpcRetries - Maximum number of Rpc retries that
|
||||||
|
// should be utilized when submitting
|
||||||
|
// a request to the endpoint. A value
|
||||||
|
// of zero requests that the default
|
||||||
|
// setting be utilized.
|
||||||
//
|
//
|
||||||
// Arguments Out: None.
|
// Arguments Out: pEndPointHandle - Pointer to variable that will receive
|
||||||
|
// the endpoint handle.
|
||||||
//
|
//
|
||||||
// Returns: Nothing.
|
// Returns: 0 == Success
|
||||||
|
// -1 == Failure
|
||||||
//
|
//
|
||||||
// Abstract: Method to re-initialize the IPC infrastructure for process.
|
// Abstract: Method to open a UNIX (PF_UNIX) remote endpoint.
|
||||||
|
//
|
||||||
|
// Note: The service should have been initialized before calling
|
||||||
|
// this procedure.
|
||||||
//
|
//
|
||||||
// L2
|
// L0
|
||||||
//=======================================================================--
|
//=======================================================================--
|
||||||
{
|
{
|
||||||
CChannel *pCChannel;
|
int retStatus = -1;
|
||||||
|
|
||||||
DbgTrace(1, "ReInitializeIpc- Start\n", 0);
|
DbgTrace(1, "IpcClientOpenUnixRemoteEndPoint- Start\n", 0);
|
||||||
|
|
||||||
// Clean up all allocated SmartCChannel objects
|
// Verify the input parameters
|
||||||
for (int i = 0; i < cchannelVector.size(); i++)
|
if (pSocketFileName == NULL
|
||||||
|
|| pEndPointHandle == NULL)
|
||||||
{
|
{
|
||||||
// Close the channel if present
|
DbgTrace(0, "IpcClientOpenUnixRemoteEndPoint- Invalid parameter\n", 0);
|
||||||
if (cchannelVector[i].getPointer() != NULL)
|
goto exit;
|
||||||
{
|
|
||||||
pCChannel = *(cchannelVector[i].getPointer());
|
|
||||||
pCChannel->closeChannel();
|
|
||||||
|
|
||||||
// Free the SmartCChannel
|
|
||||||
delete cchannelVector[i].getPointer();
|
|
||||||
cchannelVector[i].setPointer(NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgTrace(1, "ReInitializeIpc- End\n", 0);
|
// Verify that we have been initialized
|
||||||
|
if (svcInitialized)
|
||||||
|
{
|
||||||
|
// Set the default max rpc retry value if necessary
|
||||||
|
if (maxRpcRetries == 0)
|
||||||
|
maxRpcRetries = DEFAULT_MAX_RPC_RETRIES;
|
||||||
|
|
||||||
|
// Acquire our mutex
|
||||||
|
pthread_mutex_lock(&clientMutex);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Instantiate a RemoteEndPoint object and keep track of it
|
||||||
|
// with a smart pointer.
|
||||||
|
SmartRemoteEndPoint *pSmartRemoteEndPoint = new SmartRemoteEndPoint(new RemoteEndPoint(appMultithreaded,
|
||||||
|
maxRpcRetries,
|
||||||
|
pSocketFileName));
|
||||||
|
|
||||||
|
// Allocate a handle for the endpoint
|
||||||
|
uint32_t handle = remoteEndPointHandleAllocator ++;
|
||||||
|
|
||||||
|
// Insert the new RemoteEndPoint into the REP map
|
||||||
|
REPIterBoolPair insertResult;
|
||||||
|
insertResult = repMap.insert(make_pair(handle, pSmartRemoteEndPoint));
|
||||||
|
if (!insertResult.second)
|
||||||
|
{
|
||||||
|
// Insertion failed
|
||||||
|
DbgTrace(0, "IpcClientOpenUnixRemoteEndPoint- Unable to insert RemoteEndPoint into REP\n", 0);
|
||||||
|
delete pSmartRemoteEndPoint;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// RemoteEndPoint inserted in the REP map, success.
|
||||||
|
*pEndPointHandle = handle;
|
||||||
|
retStatus = 0;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
DbgTrace(0, "IpcClientOpenUnixRemoteEndPoint- Exception caught\n", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&clientMutex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgTrace(0, "IpcClientOpenUnixRemoteEndPoint- Not initialized\n", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
DbgTrace(1, "IpcClientOpenUnixRemoteEndPoint- End, status = %08X\n", retStatus);
|
||||||
|
|
||||||
|
return retStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//++=======================================================================
|
||||||
|
extern "C"
|
||||||
|
int
|
||||||
|
IpcClientOpenInetRemoteEndPoint(
|
||||||
|
IN unsigned short int port,
|
||||||
|
IN uint32_t address,
|
||||||
|
IN int maxRpcRetries,
|
||||||
|
INOUT uint32_t *pEndPointHandle)
|
||||||
|
//
|
||||||
|
// Arguments In: port - Server's listening port number.
|
||||||
|
//
|
||||||
|
// address - The server's IP Address. Use
|
||||||
|
// 0x7F000001 if the server is local.
|
||||||
|
//
|
||||||
|
// maxRpcRetries - Maximum number of Rpc retries that
|
||||||
|
// should be utilized when submitting
|
||||||
|
// a request to the endpoint. A value
|
||||||
|
// of zero requests that the default
|
||||||
|
// setting be utilized.
|
||||||
|
//
|
||||||
|
// Arguments Out: pEndPointHandle - Pointer to variable that will receive
|
||||||
|
// the endpoint handle.
|
||||||
|
//
|
||||||
|
// Returns: 0 == Success
|
||||||
|
// -1 == Failure
|
||||||
|
//
|
||||||
|
// Abstract: Method to open a TCP (AF_INET) remote endpoint.
|
||||||
|
//
|
||||||
|
// Note: The service should have been initialized before calling
|
||||||
|
// this procedure.
|
||||||
|
//
|
||||||
|
// L0
|
||||||
|
//=======================================================================--
|
||||||
|
{
|
||||||
|
int retStatus = -1;
|
||||||
|
|
||||||
|
DbgTrace(1, "IpcClientOpenInetRemoteEndPoint- Start\n", 0);
|
||||||
|
|
||||||
|
// Verify the input parameters
|
||||||
|
if (pEndPointHandle == NULL)
|
||||||
|
{
|
||||||
|
DbgTrace(0, "IpcClientOpenInetRemoteEndPoint- Invalid parameter\n", 0);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that we have been initialized
|
||||||
|
if (svcInitialized)
|
||||||
|
{
|
||||||
|
// Set the default max rpc retry value if necessary
|
||||||
|
if (maxRpcRetries == 0)
|
||||||
|
maxRpcRetries = DEFAULT_MAX_RPC_RETRIES;
|
||||||
|
|
||||||
|
// Acquire our mutex
|
||||||
|
pthread_mutex_lock(&clientMutex);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Instantiate a RemoteEndPoint object and keep track of it
|
||||||
|
// with a smart pointer.
|
||||||
|
SmartRemoteEndPoint *pSmartRemoteEndPoint = new SmartRemoteEndPoint(new RemoteEndPoint(appMultithreaded,
|
||||||
|
maxRpcRetries,
|
||||||
|
port,
|
||||||
|
address));
|
||||||
|
|
||||||
|
// Allocate a handle for the endpoint
|
||||||
|
uint32_t handle = remoteEndPointHandleAllocator ++;
|
||||||
|
|
||||||
|
// Insert the new RemoteEndPoint into the REP map
|
||||||
|
REPIterBoolPair insertResult;
|
||||||
|
insertResult = repMap.insert(make_pair(handle, pSmartRemoteEndPoint));
|
||||||
|
if (!insertResult.second)
|
||||||
|
{
|
||||||
|
// Insertion failed
|
||||||
|
DbgTrace(0, "IpcClientOpenInetRemoteEndPoint- Unable to insert RemoteEndPoint into REP\n", 0);
|
||||||
|
delete pSmartRemoteEndPoint;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// RemoteEndPoint inserted in the REP map, success.
|
||||||
|
*pEndPointHandle = handle;
|
||||||
|
retStatus = 0;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
DbgTrace(0, "IpcClientOpenInetRemoteEndPoint- Exception caught\n", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&clientMutex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgTrace(0, "IpcClientOpenInetRemoteEndPoint- Not initialized\n", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
DbgTrace(1, "IpcClientOpenInetRemoteEndPoint- End, status = %08X\n", retStatus);
|
||||||
|
|
||||||
|
return retStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//++=======================================================================
|
||||||
|
extern "C"
|
||||||
|
int
|
||||||
|
IpcClientCloseRemoteEndPoint(
|
||||||
|
IN uint32_t endPointHandle)
|
||||||
|
//
|
||||||
|
// Arguments In: endpointHandle - Handle of the endpoint being closed.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Arguments Out: None.
|
||||||
|
// the endpoint handle.
|
||||||
|
//
|
||||||
|
// Returns: 0 == Success
|
||||||
|
// -1 == Failure
|
||||||
|
//
|
||||||
|
// Abstract: Method to close a remote endpoint.
|
||||||
|
//
|
||||||
|
// Note: The service should have been initialized before calling
|
||||||
|
// this procedure.
|
||||||
|
//
|
||||||
|
// L0
|
||||||
|
//=======================================================================--
|
||||||
|
{
|
||||||
|
int retStatus = -1;
|
||||||
|
|
||||||
|
DbgTrace(1, "IpcClientCloseRemoteEndPoint- Start\n", 0);
|
||||||
|
|
||||||
|
// Verify that we have been initialized
|
||||||
|
if (svcInitialized)
|
||||||
|
{
|
||||||
|
// Acquire our mutex
|
||||||
|
pthread_mutex_lock(&clientMutex);
|
||||||
|
|
||||||
|
// Find the appropriate RemoteEndPoint object in the REP Map using
|
||||||
|
// the handle provided by the caller.
|
||||||
|
REPMapIter iter = repMap.find(endPointHandle);
|
||||||
|
if (iter != repMap.end())
|
||||||
|
{
|
||||||
|
// Object was found in the map, remove it.
|
||||||
|
SmartRemoteEndPoint *pSmartRemoteEndPoint = iter->second;
|
||||||
|
repMap.erase(iter);
|
||||||
|
|
||||||
|
// Release our mutex before deleting the endpoint
|
||||||
|
pthread_mutex_unlock(&clientMutex);
|
||||||
|
|
||||||
|
// Close the endpoint
|
||||||
|
delete pSmartRemoteEndPoint;
|
||||||
|
|
||||||
|
// Success
|
||||||
|
retStatus = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgTrace(0, "IpcClientCloseRemoteEndPoint- Invalid handle\n", 0);
|
||||||
|
|
||||||
|
// Release our mutex
|
||||||
|
pthread_mutex_unlock(&clientMutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgTrace(0, "IpcClientCloseRemoteEndPoint- Not initialized\n", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
DbgTrace(1, "IpcClientCloseRemoteEndPoint- End, status = %08X\n", retStatus);
|
||||||
|
|
||||||
|
return retStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//++=======================================================================
|
||||||
|
extern "C"
|
||||||
|
int
|
||||||
|
IpcClientSubmitReq(
|
||||||
|
IN uint32_t endPointHandle,
|
||||||
|
IN char *pClientData,
|
||||||
|
IN int clientDataLen,
|
||||||
|
INOUT char **ppServerData,
|
||||||
|
INOUT int *pServerDataLen)
|
||||||
|
//
|
||||||
|
// Arguments In: endPointHandle - Handle of the remote endpoint that will
|
||||||
|
// be the target of the request.
|
||||||
|
//
|
||||||
|
// pClientData - Pointer to client data that must be sent to
|
||||||
|
// the server. Buffer is NEVER released by the
|
||||||
|
// procedure.
|
||||||
|
//
|
||||||
|
// clientDataLen - Length of the client data.
|
||||||
|
//
|
||||||
|
// Arguments Out: ppServerData - Pointer to variable that will receive a
|
||||||
|
// pointer to the buffer containing the data
|
||||||
|
// received from the server.
|
||||||
|
//
|
||||||
|
// pServerDataLen - Pointer to variable that will receive the
|
||||||
|
// length of the data received from the server.
|
||||||
|
//
|
||||||
|
// Returns: 0 == Request completed gracefully
|
||||||
|
// -1 == Request did not complete gracefully
|
||||||
|
//
|
||||||
|
// Abstract: Method to submit a request.
|
||||||
|
//
|
||||||
|
// Note: The routine blocks until the request completes.
|
||||||
|
//
|
||||||
|
// L0
|
||||||
|
//=======================================================================--
|
||||||
|
{
|
||||||
|
int retStatus = -1;
|
||||||
|
|
||||||
|
DbgTrace(1, "IpcClientSubmitReq- Start\n", 0);
|
||||||
|
|
||||||
|
// Verify that we have been initialized
|
||||||
|
if (svcInitialized)
|
||||||
|
{
|
||||||
|
// Acquire our mutex
|
||||||
|
pthread_mutex_lock(&clientMutex);
|
||||||
|
|
||||||
|
// Find the appropriate RemoteEndPoint object in the REP Map using
|
||||||
|
// the handle provided by the caller.
|
||||||
|
REPMapIter iter = repMap.find(endPointHandle);
|
||||||
|
if (iter != repMap.end())
|
||||||
|
{
|
||||||
|
// Object was found in the map, use it to submit
|
||||||
|
// the request.
|
||||||
|
SmartRemoteEndPoint *pSmartRemoteEndPoint = new SmartRemoteEndPoint(*(iter->second));
|
||||||
|
|
||||||
|
// Release our mutex before deleting the endpoint
|
||||||
|
pthread_mutex_unlock(&clientMutex);
|
||||||
|
|
||||||
|
// Submit the request
|
||||||
|
retStatus = (*pSmartRemoteEndPoint)->submitReq(pClientData,
|
||||||
|
clientDataLen,
|
||||||
|
ppServerData,
|
||||||
|
pServerDataLen);
|
||||||
|
|
||||||
|
// Get rid of the reference to the remote endpoint
|
||||||
|
delete pSmartRemoteEndPoint;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgTrace(0, "IpcClientSubmitReq- Invalid handle\n", 0);
|
||||||
|
|
||||||
|
// Release our mutex
|
||||||
|
pthread_mutex_unlock(&clientMutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgTrace(0, "IpcClientSubmitReq- Not initialized\n", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DbgTrace(1, "IpcClientSubmitReq- End, retStatus = %08X\n", retStatus);
|
||||||
|
|
||||||
|
return retStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -181,54 +491,36 @@ IpcClientInit(
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save a copy of the application name
|
// Verify that we have not been initialized already
|
||||||
pAppName = new char[strlen(pName) + 1];
|
if (!svcInitialized)
|
||||||
if (pAppName == NULL)
|
|
||||||
{
|
{
|
||||||
DbgTrace(0, "IpcClientInit- Memory allocation failure\n", 0);
|
// Save a copy of the application name
|
||||||
goto exit;
|
pAppName = new char[strlen(pName) + 1];
|
||||||
}
|
if (pAppName == NULL)
|
||||||
strcpy(pAppName, pName);
|
{
|
||||||
|
DbgTrace(0, "IpcClientInit- Memory allocation failure\n", 0);
|
||||||
// Save the rest of the debug settings
|
goto exit;
|
||||||
DebugLevel = debugLevel;
|
|
||||||
UseSyslog = useSyslog;
|
|
||||||
|
|
||||||
// Initialize our mutexes
|
|
||||||
pthread_mutex_init(&clientMutex, NULL);
|
|
||||||
pthread_mutex_init(&interlockedMutex, NULL);
|
|
||||||
|
|
||||||
// Proceed based on whether or not we have already instantiated
|
|
||||||
// SmartCChannel vectors.
|
|
||||||
if (cchannelVector.size() == 0)
|
|
||||||
{
|
|
||||||
// SmartCChannel entries have not been instantiated
|
|
||||||
//
|
|
||||||
// Setup the number of channels that we may have based on
|
|
||||||
// whether the application is multi-threaded or not.
|
|
||||||
if (multithreaded)
|
|
||||||
numCChannels = MAX_CHANNELS;
|
|
||||||
else
|
|
||||||
numCChannels = 1;
|
|
||||||
|
|
||||||
// Instantiate entries in SmartCChannel vector
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < numCChannels; i++)
|
|
||||||
cchannelVector.push_back(SmartCChannelPointer());
|
|
||||||
|
|
||||||
// Done initializing
|
|
||||||
svcInitialized = true;
|
|
||||||
retStatus = 0;
|
|
||||||
|
|
||||||
} catch (...) {
|
|
||||||
DbgTrace(0, "IpcClientInit- Exception caught while initializing the cchannelVector\n", 0);
|
|
||||||
}
|
}
|
||||||
|
strcpy(pAppName, pName);
|
||||||
|
|
||||||
|
// Save the app multithreaded information
|
||||||
|
appMultithreaded = multithreaded;
|
||||||
|
|
||||||
|
// Save the rest of the debug settings
|
||||||
|
DebugLevel = debugLevel;
|
||||||
|
UseSyslog = useSyslog;
|
||||||
|
|
||||||
|
// Initialize our mutexes
|
||||||
|
pthread_mutex_init(&clientMutex, NULL);
|
||||||
|
pthread_mutex_init(&interlockedMutex, NULL);
|
||||||
|
|
||||||
|
// Success
|
||||||
|
svcInitialized = true;
|
||||||
|
retStatus = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// SmartCChannel vector has already been instantiated
|
DbgTrace(0, "IpcClientInit- Initialized already\n", 0);
|
||||||
ReInitializeIpc();
|
|
||||||
retStatus = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -239,134 +531,6 @@ exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//++=======================================================================
|
|
||||||
extern "C"
|
|
||||||
int
|
|
||||||
IpcClientSetUnAddress(
|
|
||||||
IN char *pSocketFileName)
|
|
||||||
//
|
|
||||||
// Arguments In: pSocketFileName - Pointer to string containing the name
|
|
||||||
// of the socket file.
|
|
||||||
//
|
|
||||||
// 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 should have been initialized before calling
|
|
||||||
// this procedure.
|
|
||||||
//
|
|
||||||
// L1
|
|
||||||
//=======================================================================--
|
|
||||||
{
|
|
||||||
int retStatus = -1;
|
|
||||||
|
|
||||||
DbgTrace(1, "IpcClientSetUnAddress- Start\n", 0);
|
|
||||||
|
|
||||||
// Verify that we have been initialized
|
|
||||||
if (svcInitialized)
|
|
||||||
{
|
|
||||||
// Verify that the address has not already been set
|
|
||||||
if (serverAddressSet == false)
|
|
||||||
{
|
|
||||||
// Set the necessary information in the serverUnAddr variable
|
|
||||||
serverUnAddr.sun_family = AF_UNIX;
|
|
||||||
strcpy(serverUnAddr.sun_path, pSocketFileName);
|
|
||||||
|
|
||||||
// Set the necessary flags to indicate that DOMAIN sockets
|
|
||||||
// should be used for communications.
|
|
||||||
use_PF_UNIX = true;
|
|
||||||
use_AF_INET = false;
|
|
||||||
|
|
||||||
// Success
|
|
||||||
serverAddressSet = true;
|
|
||||||
retStatus = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DbgTrace(0, "IpcClientSetUnAddress- Already set\n", 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DbgTrace(0, "IpcClientSetUnAddress- Not initialized\n", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
DbgTrace(1, "IpcClientSetUnAddress- End, status = %08X\n", retStatus);
|
|
||||||
|
|
||||||
return retStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//++=======================================================================
|
|
||||||
extern "C"
|
|
||||||
int
|
|
||||||
IpcClientSetInAddress(
|
|
||||||
IN unsigned short int serverPort,
|
|
||||||
IN uint32_t serverAddress)
|
|
||||||
//
|
|
||||||
// Arguments In: serverPort - Server's listening port number.
|
|
||||||
//
|
|
||||||
// serverAddress - The server's IP Address. Use
|
|
||||||
// 0x7F000001 if the server is local.
|
|
||||||
//
|
|
||||||
// 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 should have been initialized before calling
|
|
||||||
// this procedure.
|
|
||||||
//
|
|
||||||
// L1
|
|
||||||
//=======================================================================--
|
|
||||||
{
|
|
||||||
int retStatus = -1;
|
|
||||||
|
|
||||||
DbgTrace(1, "IpcClientSetInAddress- Start\n", 0);
|
|
||||||
|
|
||||||
// Verify that we have been initialized
|
|
||||||
if (svcInitialized)
|
|
||||||
{
|
|
||||||
// Verify that the address has not already been set
|
|
||||||
if (serverAddressSet == false)
|
|
||||||
{
|
|
||||||
// Set the necessary information in the serverInAddr variable
|
|
||||||
serverInAddr.sin_family = AF_INET;
|
|
||||||
serverInAddr.sin_port = htons(serverPort);
|
|
||||||
serverInAddr.sin_addr.s_addr = htonl(serverAddress);
|
|
||||||
|
|
||||||
// Set the necessary flags to indicate that TCP sockets
|
|
||||||
// should be used for communications.
|
|
||||||
use_AF_INET = true;
|
|
||||||
use_PF_UNIX = false;
|
|
||||||
|
|
||||||
// Success
|
|
||||||
serverAddressSet = true;
|
|
||||||
retStatus = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DbgTrace(0, "IpcClientSetInAddress- Already set\n", 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DbgTrace(0, "IpcClientSetInAddress- Not initialized\n", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
DbgTrace(1, "IpcClientSetInAddress- End, status = %08X\n", retStatus);
|
|
||||||
|
|
||||||
return retStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//++=======================================================================
|
//++=======================================================================
|
||||||
extern "C"
|
extern "C"
|
||||||
void
|
void
|
||||||
@ -380,251 +544,47 @@ IpcClientShutdown(void)
|
|||||||
//
|
//
|
||||||
// Abstract: Method to shutdown the IPC infrastructure for process.
|
// Abstract: Method to shutdown the IPC infrastructure for process.
|
||||||
//
|
//
|
||||||
// L2
|
// L0
|
||||||
//=======================================================================--
|
//=======================================================================--
|
||||||
{
|
{
|
||||||
DbgTrace(1, "IpcClientShutdown- Start\n", 0);
|
DbgTrace(1, "IpcClientShutdown- Start\n", 0);
|
||||||
|
|
||||||
ReInitializeIpc();
|
// Verify that we have been initialized
|
||||||
|
if (svcInitialized)
|
||||||
// Free the AppName string if necessary
|
|
||||||
if (pAppName != unInitialized)
|
|
||||||
{
|
{
|
||||||
delete[] pAppName;
|
// Forget about having been initialized
|
||||||
pAppName = unInitialized;
|
svcInitialized = false;
|
||||||
|
|
||||||
|
// Clean up the REP map
|
||||||
|
pthread_mutex_lock(&clientMutex);
|
||||||
|
while (!repMap.empty())
|
||||||
|
{
|
||||||
|
REPMapIter iter = repMap.begin();
|
||||||
|
SmartRemoteEndPoint *pSmartRemoteEndPoint = iter->second;
|
||||||
|
repMap.erase(iter);
|
||||||
|
pthread_mutex_unlock(&clientMutex);
|
||||||
|
|
||||||
|
delete pSmartRemoteEndPoint;
|
||||||
|
pthread_mutex_lock(&clientMutex);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&clientMutex);
|
||||||
|
|
||||||
|
// Free the AppName string if necessary
|
||||||
|
if (pAppName != unInitialized)
|
||||||
|
{
|
||||||
|
delete[] pAppName;
|
||||||
|
pAppName = unInitialized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgTrace(0, "IpcClientShutdown- Not initialized\n", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgTrace(1, "IpcClientShutdown- End\n", 0);
|
DbgTrace(1, "IpcClientShutdown- End\n", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//++=======================================================================
|
|
||||||
SmartCChannel *
|
|
||||||
getCChannel(void)
|
|
||||||
//
|
|
||||||
// Arguments In: Nothing.
|
|
||||||
//
|
|
||||||
// Arguments Out: Nothing.
|
|
||||||
//
|
|
||||||
// Returns: Pointer to SmartCChannel object if successful, otherwise
|
|
||||||
// NULL.
|
|
||||||
//
|
|
||||||
// Abstract: Method to get a SmartCChannel for submitting a request.
|
|
||||||
//
|
|
||||||
// L2
|
|
||||||
//=======================================================================--
|
|
||||||
{
|
|
||||||
SmartCChannel *pSmartCChannel = NULL;
|
|
||||||
int channelSelector = (numChannelSubmits++) % numCChannels;
|
|
||||||
|
|
||||||
DbgTrace(1, "IPCCLNT -getCChannel- Start\n", 0);
|
|
||||||
|
|
||||||
// Just exit if the server address has not been set
|
|
||||||
if (!serverAddressSet)
|
|
||||||
{
|
|
||||||
DbgTrace(0, "IPCCLNT -getCChannel- Server address not set\n", 0);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtain client mutex
|
|
||||||
pthread_mutex_lock(&clientMutex);
|
|
||||||
|
|
||||||
// Check if there is an available and usable channel for the client
|
|
||||||
if (cchannelVector[channelSelector].getPointer() != NULL
|
|
||||||
&& (*cchannelVector[channelSelector].getPointer())->ok())
|
|
||||||
{
|
|
||||||
// Use the available channel
|
|
||||||
pSmartCChannel = new SmartCChannel(*cchannelVector[channelSelector].getPointer());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The channel is either unavailable or unusable, clean up
|
|
||||||
// the channel if it is indeed unusable.
|
|
||||||
if (cchannelVector[channelSelector].getPointer() != NULL)
|
|
||||||
{
|
|
||||||
// Clean up the channel
|
|
||||||
CChannel *pCChannel = *cchannelVector[channelSelector].getPointer();
|
|
||||||
pCChannel->closeChannel();
|
|
||||||
delete cchannelVector[channelSelector].getPointer();
|
|
||||||
cchannelVector[channelSelector].setPointer(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
CChannel *pCChannel;
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Use the appropriate server address when instantiating
|
|
||||||
// the CChannel object.
|
|
||||||
if (use_PF_UNIX)
|
|
||||||
{
|
|
||||||
// PF_UNIX
|
|
||||||
pCChannel = new CChannel(&serverUnAddr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Assume AF_INET
|
|
||||||
pCChannel = new CChannel(&serverInAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// CChannel object created, now associate a SmartCChannel
|
|
||||||
// object with it. It is important to do this to keep
|
|
||||||
// the object from being deleted as we initialize it.
|
|
||||||
cchannelVector[channelSelector].setPointer(new SmartCChannel(pCChannel));
|
|
||||||
|
|
||||||
// Initialize the CChannel
|
|
||||||
if (pCChannel->init() == 0)
|
|
||||||
{
|
|
||||||
// CChannel initialization succeeded, use it to
|
|
||||||
// satisfy the caller.
|
|
||||||
pSmartCChannel = new SmartCChannel(*cchannelVector[channelSelector].getPointer());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// CChannel initialization failed
|
|
||||||
delete cchannelVector[channelSelector].getPointer();
|
|
||||||
cchannelVector[channelSelector].setPointer(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
DbgTrace(0, "getCChannel- Exception caught\n", 0);
|
|
||||||
|
|
||||||
// Try to clean things up just in case
|
|
||||||
if (cchannelVector[channelSelector].getPointer())
|
|
||||||
{
|
|
||||||
delete cchannelVector[channelSelector].getPointer();
|
|
||||||
cchannelVector[channelSelector].setPointer(NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (pCChannel != NULL)
|
|
||||||
delete pCChannel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release client mutex
|
|
||||||
pthread_mutex_unlock(&clientMutex);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
|
|
||||||
DbgTrace(1, "getCChannel- End, Obj = %08X\n", pSmartCChannel);
|
|
||||||
|
|
||||||
return pSmartCChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//++=======================================================================
|
|
||||||
extern "C"
|
|
||||||
int
|
|
||||||
IpcClientSubmitReq(
|
|
||||||
IN char *pClientData,
|
|
||||||
IN int clientDataLen,
|
|
||||||
INOUT char **ppServerData,
|
|
||||||
INOUT int *pServerDataLen)
|
|
||||||
//
|
|
||||||
// Arguments In: pClientData - Pointer to client data that must be sent to
|
|
||||||
// the server. Buffer is NEVER released by the
|
|
||||||
// procedure.
|
|
||||||
//
|
|
||||||
// clientDataLen - Length of the client data.
|
|
||||||
//
|
|
||||||
// Arguments Out: ppServerData - Pointer to variable that will receive a
|
|
||||||
// pointer to the buffer containing the data
|
|
||||||
// received from the server.
|
|
||||||
//
|
|
||||||
// pServerDataLen - Pointer to variable that will receive the
|
|
||||||
// length of the data received from the server.
|
|
||||||
//
|
|
||||||
// Returns: 0 == Request completed gracefully
|
|
||||||
// -1 == Request did not complete gracefully
|
|
||||||
//
|
|
||||||
// Abstract: Method to submit a request.
|
|
||||||
//
|
|
||||||
// Note: The routine blocks until the request completes.
|
|
||||||
//
|
|
||||||
// L2
|
|
||||||
//=======================================================================--
|
|
||||||
{
|
|
||||||
int retStatus = -1;
|
|
||||||
|
|
||||||
DbgTrace(1, "IpcClientSubmitReq- Start\n", 0);
|
|
||||||
|
|
||||||
try {
|
|
||||||
SmartCChannel *pSmartCChannel;
|
|
||||||
|
|
||||||
// Perform the following in a loop to deal with abnormal connection terminations
|
|
||||||
unsigned long rpcRetryCount = 0;
|
|
||||||
while (rpcRetryCount < MAX_RPC_RETRIES)
|
|
||||||
{
|
|
||||||
// Get SmartCChannel
|
|
||||||
pSmartCChannel = getCChannel();
|
|
||||||
if (pSmartCChannel != NULL)
|
|
||||||
{
|
|
||||||
// Get pointer to channel object
|
|
||||||
CChannel *pCChannel = *pSmartCChannel;
|
|
||||||
|
|
||||||
// Allocate a requestId
|
|
||||||
uint32_t reqId = pCChannel->allocReqId();
|
|
||||||
|
|
||||||
// Allocate client request object.
|
|
||||||
ClientReq clientReq(reqId);
|
|
||||||
|
|
||||||
// Submit the request via the channel
|
|
||||||
if (pCChannel->submitReq(reqId,
|
|
||||||
clientReq,
|
|
||||||
pClientData,
|
|
||||||
clientDataLen) == 0)
|
|
||||||
{
|
|
||||||
// Request submission over the channel succeeded, now
|
|
||||||
// wait for the completion of the request.
|
|
||||||
clientReq.waitForCompletion(ppServerData,
|
|
||||||
pServerDataLen);
|
|
||||||
|
|
||||||
// Remove the request from the channel
|
|
||||||
pCChannel->removeReq(reqId);
|
|
||||||
|
|
||||||
// Now proceed based on the completion status
|
|
||||||
ClientReq::CompletionStatus compStatus = clientReq.completionStatus();
|
|
||||||
if (compStatus == ClientReq::SuccessCompletionStatus)
|
|
||||||
{
|
|
||||||
// Success
|
|
||||||
retStatus = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DbgTrace(0, "IpcClientSubmitReq- Request submittion over the channel failed\n", 0);
|
|
||||||
|
|
||||||
// Remove the request from the channel
|
|
||||||
pCChannel->removeReq(reqId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the SmartCChannel
|
|
||||||
delete pSmartCChannel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DbgTrace(0, "IpcClientSubmitReq- Channel unavailable\n", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop trying if the RPC succeeded
|
|
||||||
if (retStatus == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Account for this RPC try
|
|
||||||
rpcRetryCount ++;
|
|
||||||
DbgTrace(0, "IpcClientSubmitReq- Will attempt to retry RPC, count = %d\n", rpcRetryCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(...) {
|
|
||||||
|
|
||||||
DbgTrace(0, "IpcClientSubmitReq-- Exception caught\n", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
DbgTrace(1, "IpcClientSubmitReq- End, retStatus = %08X\n", retStatus);
|
|
||||||
|
|
||||||
return retStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
|
|
||||||
|
@ -0,0 +1,428 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
#include "cchannel.h"
|
||||||
|
#include "clientreq.h"
|
||||||
|
#include "remoteendpoint.h"
|
||||||
|
#include <assert.h> // Ensure that NDEBUG is defined for release builds!
|
||||||
|
|
||||||
|
//===[ External data ]=====================================================
|
||||||
|
|
||||||
|
//===[ External prototypes ]===============================================
|
||||||
|
|
||||||
|
//===[ Manifest constants ]================================================
|
||||||
|
|
||||||
|
#define REMOTE_ENDPOINT_SIGNATURE 0x54525653 // SVRT
|
||||||
|
|
||||||
|
//===[ Type definitions ]==================================================
|
||||||
|
|
||||||
|
//===[ Function prototypes ]===============================================
|
||||||
|
|
||||||
|
//===[ Global variables ]==================================================
|
||||||
|
|
||||||
|
//===[ Type definitions ]==================================================
|
||||||
|
|
||||||
|
//===[ Function prototypes ]===============================================
|
||||||
|
|
||||||
|
//===[ Global variables ]==================================================
|
||||||
|
|
||||||
|
//
|
||||||
|
// Object Counters
|
||||||
|
//
|
||||||
|
unsigned long numRemoteEndPointObjects = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//++=======================================================================
|
||||||
|
RemoteEndPoint::RemoteEndPoint(
|
||||||
|
bool multithreaded,
|
||||||
|
int maxRpcRetries,
|
||||||
|
char *pSocketFileName) :
|
||||||
|
|
||||||
|
m_signature (REMOTE_ENDPOINT_SIGNATURE),
|
||||||
|
m_numChannelSubmits (0),
|
||||||
|
m_maxRpcRetries (maxRpcRetries)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
//
|
||||||
|
// Abstract:
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
//
|
||||||
|
// L0
|
||||||
|
//=======================================================================--
|
||||||
|
{
|
||||||
|
DbgTrace(1, "RemoteEndPoint::RemoteEndPoint- Start, Obj = %08X\n", this);
|
||||||
|
|
||||||
|
// Initialize our mutex
|
||||||
|
pthread_mutex_init(&m_mutex, NULL);
|
||||||
|
|
||||||
|
// Set the necessary information in the m_serverUnAddr variable
|
||||||
|
m_serverUnAddr.sun_family = AF_UNIX;
|
||||||
|
strcpy(m_serverUnAddr.sun_path, pSocketFileName);
|
||||||
|
|
||||||
|
// Set the necessary flags to indicate that DOMAIN sockets
|
||||||
|
// should be used for communications.
|
||||||
|
m_Use_PF_UNIX = true;
|
||||||
|
m_Use_AF_INET = false;
|
||||||
|
|
||||||
|
// Setup the number of channels that we may have based on
|
||||||
|
// whether the application is multi-threaded or not.
|
||||||
|
if (multithreaded)
|
||||||
|
m_numCChannels = MAX_CHANNELS_PER_ENDPOINT;
|
||||||
|
else
|
||||||
|
m_numCChannels = 1;
|
||||||
|
|
||||||
|
// Instantiate entries in SmartCChannel vector
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < m_numCChannels; i++)
|
||||||
|
m_cchannelVector.push_back(SmartCChannelPointer());
|
||||||
|
} catch (...) {
|
||||||
|
DbgTrace(0, "RemoteEndPoint::RemoteEndPoint- Exception caught while initializing the cchannelVector\n", 0);
|
||||||
|
throw bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the object count
|
||||||
|
InterlockedIncrement(&numRemoteEndPointObjects);
|
||||||
|
|
||||||
|
DbgTrace(1, "RemoteEndPoint::RemoteEndPoint- End\n", 0);
|
||||||
|
|
||||||
|
} /*-- RemoteEndPoint::RemoteEndPoint() --*/
|
||||||
|
|
||||||
|
|
||||||
|
//++=======================================================================
|
||||||
|
RemoteEndPoint::RemoteEndPoint(
|
||||||
|
bool multithreaded,
|
||||||
|
int maxRpcRetries,
|
||||||
|
unsigned short int port,
|
||||||
|
uint32_t address) :
|
||||||
|
|
||||||
|
m_signature (REMOTE_ENDPOINT_SIGNATURE),
|
||||||
|
m_numChannelSubmits (0),
|
||||||
|
m_maxRpcRetries (maxRpcRetries)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
//
|
||||||
|
// Abstract:
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
//
|
||||||
|
// L0
|
||||||
|
//=======================================================================--
|
||||||
|
{
|
||||||
|
DbgTrace(1, "RemoteEndPoint::RemoteEndPoint- Start, Obj = %08X\n", this);
|
||||||
|
|
||||||
|
// Initialize our mutex
|
||||||
|
pthread_mutex_init(&m_mutex, NULL);
|
||||||
|
|
||||||
|
// Set the necessary information in the serverInAddr variable
|
||||||
|
m_serverInAddr.sin_family = AF_INET;
|
||||||
|
m_serverInAddr.sin_port = htons(port);
|
||||||
|
m_serverInAddr.sin_addr.s_addr = htonl(address);
|
||||||
|
|
||||||
|
// Set the necessary flags to indicate that TCP sockets
|
||||||
|
// should be used for communications.
|
||||||
|
m_Use_AF_INET = true;
|
||||||
|
m_Use_PF_UNIX = false;
|
||||||
|
|
||||||
|
// Setup the number of channels that we may have based on
|
||||||
|
// whether the application is multi-threaded or not.
|
||||||
|
if (multithreaded)
|
||||||
|
m_numCChannels = MAX_CHANNELS_PER_ENDPOINT;
|
||||||
|
else
|
||||||
|
m_numCChannels = 1;
|
||||||
|
|
||||||
|
// Instantiate entries in SmartCChannel vector
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < m_numCChannels; i++)
|
||||||
|
m_cchannelVector.push_back(SmartCChannelPointer());
|
||||||
|
} catch (...) {
|
||||||
|
DbgTrace(0, "RemoteEndPoint::RemoteEndPoint- Exception caught while initializing the cchannelVector\n", 0);
|
||||||
|
throw bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the object count
|
||||||
|
InterlockedIncrement(&numRemoteEndPointObjects);
|
||||||
|
|
||||||
|
DbgTrace(1, "RemoteEndPoint::RemoteEndPoint- End\n", 0);
|
||||||
|
|
||||||
|
} /*-- RemoteEndPoint::RemoteEndPoint() --*/
|
||||||
|
|
||||||
|
|
||||||
|
//++=======================================================================
|
||||||
|
RemoteEndPoint::~RemoteEndPoint(void)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
//
|
||||||
|
// Abstract:
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
//
|
||||||
|
// L0
|
||||||
|
//=======================================================================--
|
||||||
|
{
|
||||||
|
DbgTrace(1, "RemoteEndPoint::~RemoteEndPoint- Start, Obj = %08X\n", this);
|
||||||
|
|
||||||
|
// Clean up all allocated SmartCChannel objects
|
||||||
|
for (int i = 0; i < m_cchannelVector.size(); i++)
|
||||||
|
{
|
||||||
|
if (m_cchannelVector[i].getPointer() != NULL)
|
||||||
|
{
|
||||||
|
CChannel *pCChannel = *(m_cchannelVector[i].getPointer());
|
||||||
|
pCChannel->closeChannel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_cchannelVector.clear();
|
||||||
|
|
||||||
|
// Decrement the object count
|
||||||
|
InterlockedDecrement(&numRemoteEndPointObjects);
|
||||||
|
|
||||||
|
DbgTrace(1, "RemoteEndPoint::~RemoteEndPoint- End\n", 0);
|
||||||
|
|
||||||
|
} /*-- RemoteEndPoint::~RemoteEndPoint() --*/
|
||||||
|
|
||||||
|
|
||||||
|
//++=======================================================================
|
||||||
|
SmartCChannel*
|
||||||
|
RemoteEndPoint::getCChannel(void)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
//
|
||||||
|
// Abstract:
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
//
|
||||||
|
// L0
|
||||||
|
//=======================================================================--
|
||||||
|
{
|
||||||
|
SmartCChannel *pSmartCChannel = NULL;
|
||||||
|
int channelSelector = (m_numChannelSubmits++) % m_numCChannels;
|
||||||
|
|
||||||
|
DbgTrace(1, "RemoteEndPoint::getCChannel- Start, Obj = %08X\n", this);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
assert(m_signature == REMOTE_ENDPOINT_SIGNATURE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Obtain our mutex
|
||||||
|
pthread_mutex_lock(&m_mutex);
|
||||||
|
|
||||||
|
// Check if there is an available and usable channel for the client
|
||||||
|
if (m_cchannelVector[channelSelector].getPointer() != NULL
|
||||||
|
&& (*m_cchannelVector[channelSelector].getPointer())->ok())
|
||||||
|
{
|
||||||
|
// Use the available channel
|
||||||
|
pSmartCChannel = new SmartCChannel(*m_cchannelVector[channelSelector].getPointer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The channel is either unavailable or unusable, clean up
|
||||||
|
// the channel if it is indeed unusable.
|
||||||
|
if (m_cchannelVector[channelSelector].getPointer() != NULL)
|
||||||
|
{
|
||||||
|
// Clean up the channel
|
||||||
|
CChannel *pCChannel = *m_cchannelVector[channelSelector].getPointer();
|
||||||
|
pCChannel->closeChannel();
|
||||||
|
delete m_cchannelVector[channelSelector].getPointer();
|
||||||
|
m_cchannelVector[channelSelector].setPointer(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
CChannel *pCChannel;
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Use the appropriate server address when instantiating
|
||||||
|
// the CChannel object.
|
||||||
|
if (m_Use_PF_UNIX)
|
||||||
|
{
|
||||||
|
// PF_UNIX
|
||||||
|
pCChannel = new CChannel(&m_serverUnAddr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Assume AF_INET
|
||||||
|
pCChannel = new CChannel(&m_serverInAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CChannel object created, now associate a SmartCChannel
|
||||||
|
// object with it. It is important to do this to keep
|
||||||
|
// the object from being deleted as we initialize it.
|
||||||
|
m_cchannelVector[channelSelector].setPointer(new SmartCChannel(pCChannel));
|
||||||
|
|
||||||
|
// Initialize the CChannel
|
||||||
|
if (pCChannel->init() == 0)
|
||||||
|
{
|
||||||
|
// CChannel initialization succeeded, use it to
|
||||||
|
// satisfy the caller.
|
||||||
|
pSmartCChannel = new SmartCChannel(*m_cchannelVector[channelSelector].getPointer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// CChannel initialization failed
|
||||||
|
delete m_cchannelVector[channelSelector].getPointer();
|
||||||
|
m_cchannelVector[channelSelector].setPointer(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
DbgTrace(0, "getCChannel- Exception caught\n", 0);
|
||||||
|
|
||||||
|
// Try to clean things up just in case
|
||||||
|
if (m_cchannelVector[channelSelector].getPointer())
|
||||||
|
{
|
||||||
|
delete m_cchannelVector[channelSelector].getPointer();
|
||||||
|
m_cchannelVector[channelSelector].setPointer(NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pCChannel != NULL)
|
||||||
|
delete pCChannel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release client mutex
|
||||||
|
pthread_mutex_unlock(&m_mutex);
|
||||||
|
|
||||||
|
DbgTrace(1, "RemoteEndPoint::getCChannel- End\n", 0);
|
||||||
|
|
||||||
|
return pSmartCChannel;
|
||||||
|
|
||||||
|
} /*-- RemoteEndPoint::getCChannel() --*/
|
||||||
|
|
||||||
|
|
||||||
|
//++=======================================================================
|
||||||
|
int
|
||||||
|
RemoteEndPoint::submitReq(
|
||||||
|
char *pClientData,
|
||||||
|
int clientDataLen,
|
||||||
|
char **ppServerData,
|
||||||
|
int *pServerDataLen)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
//
|
||||||
|
// Abstract:
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
//
|
||||||
|
// L0
|
||||||
|
//=======================================================================--
|
||||||
|
{
|
||||||
|
int retStatus = -1;
|
||||||
|
|
||||||
|
DbgTrace(1, "RemoteEndPoint::submitReq- Start, Obj = %08X\n", this);
|
||||||
|
|
||||||
|
try {
|
||||||
|
SmartCChannel *pSmartCChannel;
|
||||||
|
|
||||||
|
// Perform the following in a loop to deal with abnormal connection terminations
|
||||||
|
unsigned long rpcRetryCount = 0;
|
||||||
|
while (rpcRetryCount < m_maxRpcRetries)
|
||||||
|
{
|
||||||
|
// Get SmartCChannel
|
||||||
|
pSmartCChannel = getCChannel();
|
||||||
|
if (pSmartCChannel != NULL)
|
||||||
|
{
|
||||||
|
// Get pointer to channel object
|
||||||
|
CChannel *pCChannel = *pSmartCChannel;
|
||||||
|
|
||||||
|
// Allocate a requestId
|
||||||
|
uint32_t reqId = pCChannel->allocReqId();
|
||||||
|
|
||||||
|
// Allocate client request object.
|
||||||
|
ClientReq clientReq(reqId);
|
||||||
|
|
||||||
|
// Submit the request via the channel
|
||||||
|
if (pCChannel->submitReq(reqId,
|
||||||
|
clientReq,
|
||||||
|
pClientData,
|
||||||
|
clientDataLen) == 0)
|
||||||
|
{
|
||||||
|
// Request submission over the channel succeeded, now
|
||||||
|
// wait for the completion of the request.
|
||||||
|
clientReq.waitForCompletion(ppServerData,
|
||||||
|
pServerDataLen);
|
||||||
|
|
||||||
|
// Remove the request from the channel
|
||||||
|
pCChannel->removeReq(reqId);
|
||||||
|
|
||||||
|
// Now proceed based on the completion status
|
||||||
|
ClientReq::CompletionStatus compStatus = clientReq.completionStatus();
|
||||||
|
if (compStatus == ClientReq::SuccessCompletionStatus)
|
||||||
|
{
|
||||||
|
// Success
|
||||||
|
retStatus = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgTrace(0, "RemoteEndPoint::submitReq- Request submittion over the channel failed\n", 0);
|
||||||
|
|
||||||
|
// Remove the request from the channel
|
||||||
|
pCChannel->removeReq(reqId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the SmartCChannel
|
||||||
|
delete pSmartCChannel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DbgTrace(0, "RemoteEndPoint::submitReq- Channel unavailable\n", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop trying if the RPC succeeded
|
||||||
|
if (retStatus == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Account for this RPC try
|
||||||
|
rpcRetryCount ++;
|
||||||
|
DbgTrace(0, "RemoteEndPoint::submitReq- Will attempt to retry RPC, count = %d\n", rpcRetryCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...) {
|
||||||
|
|
||||||
|
DbgTrace(0, "RemoteEndPoint::submitReq- Exception caught\n", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DbgTrace(1, "RemoteEndPoint::submitReq- End\n", 0);
|
||||||
|
|
||||||
|
return retStatus;
|
||||||
|
|
||||||
|
} /*-- RemoteEndPoint::submitReq() --*/
|
||||||
|
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
//=========================================================================
|
||||||
|
|
@ -0,0 +1,203 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* 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 _REMOTEENDPOINT_
|
||||||
|
#define _REMOTEENDPOINT_
|
||||||
|
|
||||||
|
//===[ Include files ]=====================================================
|
||||||
|
|
||||||
|
//===[ External data ]=====================================================
|
||||||
|
|
||||||
|
//===[ External prototypes ]===============================================
|
||||||
|
|
||||||
|
//===[ Manifest constants ]================================================
|
||||||
|
|
||||||
|
#define MAX_CHANNELS_PER_ENDPOINT 3
|
||||||
|
|
||||||
|
//===[ Type definitions ]==================================================
|
||||||
|
|
||||||
|
//===[ Function prototypes ]===============================================
|
||||||
|
|
||||||
|
//===[ Global variables ]==================================================
|
||||||
|
|
||||||
|
//===[ Type definitions ]==================================================
|
||||||
|
|
||||||
|
//
|
||||||
|
// Server Thread Class
|
||||||
|
//
|
||||||
|
class RemoteEndPoint : public ObjRef
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Class for maintaining SmartCChannel pointers within the daemonVector.
|
||||||
|
//
|
||||||
|
class SmartCChannelPointer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SmartCChannel *m_pSmartCChannel;
|
||||||
|
public:
|
||||||
|
|
||||||
|
SmartCChannelPointer() : m_pSmartCChannel(NULL) {}
|
||||||
|
~SmartCChannelPointer() { if (m_pSmartCChannel != NULL) delete m_pSmartCChannel; }
|
||||||
|
SmartCChannel* getPointer() { return m_pSmartCChannel; }
|
||||||
|
void setPointer(SmartCChannel *pSmartCChannel) { m_pSmartCChannel = pSmartCChannel; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Signature
|
||||||
|
unsigned long m_signature;
|
||||||
|
|
||||||
|
// End-point address
|
||||||
|
bool m_Use_AF_INET;
|
||||||
|
bool m_Use_PF_UNIX;
|
||||||
|
struct sockaddr_in m_serverInAddr;
|
||||||
|
struct sockaddr_un m_serverUnAddr;
|
||||||
|
|
||||||
|
// SmartCChannelPointers vector
|
||||||
|
vector<SmartCChannelPointer> m_cchannelVector;
|
||||||
|
int m_numCChannels;
|
||||||
|
|
||||||
|
// Endpoint mutex
|
||||||
|
pthread_mutex_t m_mutex;
|
||||||
|
|
||||||
|
// Number of submits made to the endpoint
|
||||||
|
int m_numChannelSubmits;
|
||||||
|
|
||||||
|
// Max number of Rpc retries
|
||||||
|
int m_maxRpcRetries;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//
|
||||||
|
// Destructor
|
||||||
|
~RemoteEndPoint(void);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Constructor
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// multithreaded (input) -
|
||||||
|
// Set to TRUE if the process is
|
||||||
|
// multithreaded.
|
||||||
|
//
|
||||||
|
// maxRpcRetries (input) -
|
||||||
|
// Max Rpc retries.
|
||||||
|
//
|
||||||
|
// pSocketFileName (input) -
|
||||||
|
// Pointer to string containing the name
|
||||||
|
// of the socket file.
|
||||||
|
//
|
||||||
|
// Abstract: Constructs RemoteEndPoint object and initializes it using
|
||||||
|
// a domain socket file name.
|
||||||
|
//
|
||||||
|
// Returns: Nothing.
|
||||||
|
//
|
||||||
|
RemoteEndPoint(bool multiThreaded,
|
||||||
|
int maxRpcRetries,
|
||||||
|
char *pSocketFileName);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Constructor
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// multithreaded (input) -
|
||||||
|
// Set to TRUE if the process is
|
||||||
|
// multithreaded.
|
||||||
|
//
|
||||||
|
// maxRpcRetries (input) -
|
||||||
|
// Max Rpc retries.
|
||||||
|
//
|
||||||
|
// port (input) -
|
||||||
|
// Server's listening port number.
|
||||||
|
//
|
||||||
|
// address (input) -
|
||||||
|
// The server's IP Address. Use
|
||||||
|
// 0x7F000001 if the endpoint is local.
|
||||||
|
//
|
||||||
|
// Abstract: Constructs RemoteEndPoint object and initializes it using
|
||||||
|
// a tcp socket address.
|
||||||
|
//
|
||||||
|
// Returns: Nothing.
|
||||||
|
//
|
||||||
|
RemoteEndPoint(bool multiThreaded,
|
||||||
|
int maxRpcRetries,
|
||||||
|
unsigned short int port,
|
||||||
|
uint32_t address);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get a SmartCChannel.
|
||||||
|
//
|
||||||
|
// Parameters: None.
|
||||||
|
//
|
||||||
|
// Abstract: Gets a SmartCChannel for submitting requests to the
|
||||||
|
// remote endpoint.
|
||||||
|
//
|
||||||
|
// Returns: Pointer to SmartCChannel object if successful, otherwise
|
||||||
|
// NULL.
|
||||||
|
//
|
||||||
|
SmartCChannel *getCChannel(void);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Submit a request to the endpoint,
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// pClientData (input) -
|
||||||
|
// Pointer to client data that must be sent to
|
||||||
|
// the server. Buffer is NEVER released by the
|
||||||
|
// procedure.
|
||||||
|
//
|
||||||
|
// clientDataLen (input) -
|
||||||
|
// Length of the client data.
|
||||||
|
//
|
||||||
|
// ppServerData (input/output) -
|
||||||
|
// Pointer to variable that will receive a
|
||||||
|
// pointer to the buffer containing the data
|
||||||
|
// received from the server.
|
||||||
|
//
|
||||||
|
// pServerDataLen (input/output) -
|
||||||
|
// Pointer to variable that will receive the
|
||||||
|
// length of the data received from the server.
|
||||||
|
//
|
||||||
|
// Abstract: Method to submit a request.
|
||||||
|
//
|
||||||
|
// Returns: 0 == Request completed gracefully
|
||||||
|
// -1 == Request did not complete gracefully
|
||||||
|
//
|
||||||
|
// Note: The routine blocks until the request completes.
|
||||||
|
//
|
||||||
|
int submitReq(char *pClientData,
|
||||||
|
int clientDataLen,
|
||||||
|
char **ppServerData,
|
||||||
|
int *pServerDataLen);
|
||||||
|
};
|
||||||
|
typedef SmartPtr<RemoteEndPoint> SmartRemoteEndPoint;
|
||||||
|
|
||||||
|
|
||||||
|
//===[ Function prototypes ]===============================================
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _REMOTEENDPOINT_
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
//=========================================================================
|
||||||
|
|
@ -74,7 +74,8 @@ bool errorDetected = false;
|
|||||||
|
|
||||||
|
|
||||||
//++=======================================================================
|
//++=======================================================================
|
||||||
void* SubmitThread()
|
void* SubmitThread(
|
||||||
|
uint32_t remoteEndPointHandle)
|
||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
//
|
//
|
||||||
@ -102,7 +103,8 @@ void* SubmitThread()
|
|||||||
pthread_mutex_unlock(&testMutex);
|
pthread_mutex_unlock(&testMutex);
|
||||||
|
|
||||||
// Submit request to the server
|
// Submit request to the server
|
||||||
if (IpcClientSubmitReq(reqData,
|
if (IpcClientSubmitReq(remoteEndPointHandle,
|
||||||
|
reqData,
|
||||||
strlen(reqData),
|
strlen(reqData),
|
||||||
&pReplyData,
|
&pReplyData,
|
||||||
&replyDataLen) != 0)
|
&replyDataLen) != 0)
|
||||||
@ -148,6 +150,7 @@ ExecuteTests(void)
|
|||||||
int threadCreateStatus;
|
int threadCreateStatus;
|
||||||
int threadCreatedCount = 0;
|
int threadCreatedCount = 0;
|
||||||
int i;
|
int i;
|
||||||
|
uint32_t endPointHandle;
|
||||||
|
|
||||||
DbgTrace(1, "ExecuteTests- Start\n", 0);
|
DbgTrace(1, "ExecuteTests- Start\n", 0);
|
||||||
|
|
||||||
@ -158,8 +161,10 @@ ExecuteTests(void)
|
|||||||
false) == 0)
|
false) == 0)
|
||||||
{
|
{
|
||||||
// Set the server listen address
|
// Set the server listen address
|
||||||
if (IpcClientSetInAddress(5000,
|
if (IpcClientOpenInetRemoteEndPoint(5000,
|
||||||
0x7F000001) == 0)
|
0x7F000001,
|
||||||
|
0,
|
||||||
|
&endPointHandle) == 0)
|
||||||
{
|
{
|
||||||
// Start the configured number of threads to submit requests to
|
// Start the configured number of threads to submit requests to
|
||||||
// the server.
|
// the server.
|
||||||
@ -168,7 +173,7 @@ ExecuteTests(void)
|
|||||||
threadCreateStatus = pthread_create(&thread,
|
threadCreateStatus = pthread_create(&thread,
|
||||||
NULL,
|
NULL,
|
||||||
(void*(*)(void*))SubmitThread,
|
(void*(*)(void*))SubmitThread,
|
||||||
(void*)NULL);
|
(void*)endPointHandle);
|
||||||
if (threadCreateStatus == 0)
|
if (threadCreateStatus == 0)
|
||||||
threadCreatedCount ++;
|
threadCreatedCount ++;
|
||||||
else
|
else
|
||||||
@ -185,10 +190,16 @@ ExecuteTests(void)
|
|||||||
sleep(1);
|
sleep(1);
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the remote endpoint
|
||||||
|
if (IpcClientCloseRemoteEndPoint(endPointHandle) != 0)
|
||||||
|
{
|
||||||
|
DbgTrace(0, "ExecuteTests- Error closing remote endpoint\n", 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DbgTrace(0, "ExecuteTests- Error setting server address\n", 0);
|
DbgTrace(0, "ExecuteTests- Error opening remote endpoint\n", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
IpcClientShutdown();
|
IpcClientShutdown();
|
||||||
|
Loading…
Reference in New Issue
Block a user