diff --git a/CASA-auth-token/non-java/Makefile.am b/CASA-auth-token/non-java/Makefile.am index 84e5e7ff..f8ff03e5 100644 --- a/CASA-auth-token/non-java/Makefile.am +++ b/CASA-auth-token/non-java/Makefile.am @@ -20,9 +20,9 @@ # ####################################################################### -SUBDIRS = server package +SUBDIRS = utilities server package -DIST_SUBDIRS = include server package +DIST_SUBDIRS = include utilities server package EXTRA_DIST = autogen.sh diff --git a/CASA-auth-token/non-java/configure.in b/CASA-auth-token/non-java/configure.in index 67cc5781..59d08e82 100644 --- a/CASA-auth-token/non-java/configure.in +++ b/CASA-auth-token/non-java/configure.in @@ -264,6 +264,12 @@ package/Makefile package/linux/Makefile package/linux/CASA_auth_token_native.spec include/Makefile +utilities/Makefile +utilities/IpcLibs/Makefile +utilities/IpcLibs/linux/Makefile +utilities/IpcLibs/linux/common/Makefile +utilities/IpcLibs/linux/client/Makefile +utilities/IpcLibs/linux/server/Makefile server/Makefile server/AuthTokenValidate/Makefile server/AuthTokenValidate/linux/Makefile diff --git a/CASA-auth-token/non-java/include/casa_c_ipc.h b/CASA-auth-token/non-java/include/casa_c_ipc.h new file mode 100644 index 00000000..4fdbc6a0 --- /dev/null +++ b/CASA-auth-token/non-java/include/casa_c_ipc.h @@ -0,0 +1,184 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _IPCCLIENT_ +#define _IPCCLIENT_ + +//===[ Header files specific to this module ]============================== + +//===[ Manifest constants ]============================== + +#ifndef IN +#define IN +#endif +#ifndef OUT +#define OUT +#endif +#ifndef INOUT +#define INOUT +#endif + +//===[ Structure Definitions ]============================== + +//===[ Function Prototypes ]============================== + + +//++======================================================================= +extern "C" +int +IpcClientInit( + IN char *pName, + IN bool multithreaded, + 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. +// +// multithreaded - Set to TRUE if the process is +// multithreaded. +// +// 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 appropriate function to +// set the server address before a request can be submitted. +// +//=======================================================================-- + + +//++======================================================================= +extern "C" +void +IpcClientShutdown(void); +// +// Arguments In: None. +// +// Arguments Out: None. +// +// Returns: 0 == Success +// -1 == Failure +// +// Abstract: Method to shutdown the IPC infrastructure for process. +// +//=======================================================================-- + + +//++======================================================================= +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. +// +//=======================================================================-- + + +//++======================================================================= +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. +// +//=======================================================================-- + + +//++======================================================================= +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. +// +//=======================================================================-- + +#endif // _IPCCLIENT_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/non-java/include/casa_s_ipc.h b/CASA-auth-token/non-java/include/casa_s_ipc.h new file mode 100644 index 00000000..f12753d1 --- /dev/null +++ b/CASA-auth-token/non-java/include/casa_s_ipc.h @@ -0,0 +1,254 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _IPCSERVER_ +#define _IPCSERVER_ + +//===[ Header files specific to this module ]============================== + +//===[ Manifest constants ]============================== + +#ifndef IN +#define IN +#endif +#ifndef OUT +#define OUT +#endif +#ifndef INOUT +#define INOUT +#endif + +//===[ Structure Definitions ]============================== + +//===[ Function Prototypes ]============================== + + +//++======================================================================= +extern +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. +// +//=======================================================================-- + + +//++======================================================================= +extern +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. +// +//=======================================================================-- + + +//++======================================================================= +extern +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. +// +//=======================================================================-- + + +//++======================================================================= +extern +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: +// +//=======================================================================-- + + +//++======================================================================= +extern +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. +// +//=======================================================================-- + + +//++======================================================================= +extern +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. +// +//=======================================================================-- + + +//++======================================================================= +extern +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. +// +//=======================================================================-- + + +//++======================================================================= +extern +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. +// +//=======================================================================-- + + +//++======================================================================= +extern +void +IpcServerShutdown(void); +// +// Arguments In: None. +// +// Arguments Out: None. +// +// Returns: Nothing. +// +// Abstract: Method to shutdown the IPC service. +// +// Note: +// +//=======================================================================-- + + +#endif // _IPCSERVER_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/Makefile.am b/CASA-auth-token/non-java/utilities/IpcLibs/Makefile.am new file mode 100644 index 00000000..331523b2 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = $(TARGET_OS) + +DIST_SUBDIRS = linux + +CFILES = + +EXTRA_DIST = $(CFILES) *.h + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/Makefile.am b/CASA-auth-token/non-java/utilities/IpcLibs/linux/Makefile.am new file mode 100644 index 00000000..487f7fc2 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = client server + +DIST_SUBDIRS = common client server + +CFILES = + +EXTRA_DIST = $(CFILES) *.h + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/Makefile.am b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/Makefile.am new file mode 100644 index 00000000..c8d77505 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/Makefile.am @@ -0,0 +1,122 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +if DEBUG +TARGET_CFG = Debug +CFLAGS += -v -w +CPPFLAGS = -g $(CFLAGS) +DEFINES = -DDBG +else +TARGET_CFG = Release +CPPFLAGS = -O2 -w $(CFLAGS) +DEFINES = -DNDEBUG +endif + +# Override the link setting for C++ +LINK = g++ + +SUBDIRS = + +DIST_SUBDIRS = + +ROOT = ../../../.. + +LIBDIR = $(ROOT)/$(LIB) + +# handle Mono secondary dependencies +export MONO_PATH := $(MONO_PATH) + +COMMON = ../common +CLIENT = . + +MODULE_NAME = libcasa_c_ipc +MODULE_EXT = so + +CFILES = + +CPPFILES = channelproto.cpp \ + cchannel.cpp \ + clientreq.cpp \ + client.cpp + +CSFILES_CSC := +INCLUDES = -I. -I.. -I../common -I../../../../include +RESOURCES = +DEFINES += -Wno-format-extra-args -fno-strict-aliasing +CFLAGS += $(INCLUDES) $(DEFINES) +CPPFLAGS += $(INCLUDES) $(DEFINES) +LIBS = -lpthread -ldl -lexpat +LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) + +OBJDIR = ./$(TARGET_CFG)/$(LIB) +OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) $(addprefix $(OBJDIR)/, $(CPPFILES:%.cpp=%.o)) + +EXTRA_DIST = $(CFILES) *.h + +CUR_DIR := $(shell pwd) + +all: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + +# +# Pattern based rules. +# +vpath %.c $(CLIENT) $(COMMON) +vpath %.cpp $(CLIENT) $(COMMON) + +$(OBJDIR)/%.o: %.c + $(CC) -c $(CFLAGS) -o $@ $< + +$(OBJDIR)/%.o: %.cpp + $(CC) -c $(CPPFLAGS) -o $@ $< + +$(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT): $(OBJDIR) $(OBJS) + @echo [======== Linking $@ ========] + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + cp -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT) + +$(OBJDIR): + [ -d $(OBJDIR) ] || mkdir -p $(OBJDIR) + [ -d $(LIBDIR) ] || mkdir -p $(LIBDIR) + [ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(TARGET_CFG) + + +install-exec-local: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL_PROGRAM) $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(DESTDIR)$(libdir)/ + +uninstall-local: + cd $(DESTDIR)$(libdir); rm -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + rmdir $(DESTDIR)$(libdir) + +#installcheck-local: install +# $(mkinstalldirs) $(DESTDIR)$(libdir) +# $(INSTALL_PROGRAM) $(DESTDIR)$(libdir) +# cd $(DESTDIR)$(libdir); $(MONO) + +clean-local: + if [ -d $(TARGET_CFG) ]; then rm -rf $(TARGET_CFG); fi + +distclean-local: + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/cchannel.cpp b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/cchannel.cpp new file mode 100644 index 00000000..2b2a2a07 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/cchannel.cpp @@ -0,0 +1,1081 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "ipcint.h" +#include "cchannel.h" +#include "clientreq.h" + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +// +// Socket Mapping definitions +// +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define LINGER struct linger +#define SOCKADDR_IN struct sockaddr_in +#define closesocket close + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// +// Object Counters +// +unsigned long numCChannelObjects = 0; + + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +CChannel::CChannel( + struct sockaddr_in *pRemoteAddress) : + + m_state (State_Uninitialized), + m_socket (INVALID_SOCKET), + m_reqIdAllocator (1) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "CChannel::CChannel(TcpSocket)- Start, Obj = %08X\n", this); + + // Use Tcp socket + m_useTcpSocket = true; + + // Save a copy of the remote address + memcpy(&m_remoteAddrIn, pRemoteAddress, sizeof(struct sockaddr_in)); + + // Initialize the mutex + if (pthread_mutex_init(&m_mutex, NULL) != 0) + { + DbgTrace(0, "CChannel::CChannel- Mutex initialization failed\n", 0); + + // Throw exception + throw bad_alloc(); + } + + // Increment the object count + InterlockedIncrement(&numCChannelObjects); + + DbgTrace(1, "CChannel::CChannel(TcpSocket)- End\n", 0); + +} /*-- CChannel::CChannel(TcpSocket) --*/ + + +//++======================================================================= +CChannel::CChannel( + struct sockaddr_un *pRemoteAddress) : + + m_state (State_Uninitialized), + m_socket (INVALID_SOCKET), + m_reqIdAllocator (1) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "CChannel::CChannel(DomainSocket)- Start, Obj = %08X\n", this); + + // Do not use Tcp socket + m_useTcpSocket = false; + + // Save a copy of the remote address + memcpy(&m_remoteAddrUn, pRemoteAddress, sizeof(struct sockaddr_un)); + + // Initialize the mutex + if (pthread_mutex_init(&m_mutex, NULL) != 0) + { + DbgTrace(0, "CChannel::CChannel- Mutex initialization failed\n", 0); + + // Throw exception + throw bad_alloc(); + } + + // Increment the object count + InterlockedIncrement(&numCChannelObjects); + + DbgTrace(1, "CChannel::CChannel(DomainSocket)- End\n", 0); + +} /*-- CChannel::CChannel(DomainSocket) --*/ + + +//++======================================================================= +CChannel::~CChannel(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "CChannel::~CChannel- Start, Obj = %08X\n", this); + + // Cleanup resources allocated for the object + pthread_mutex_destroy(&m_mutex); + + // Free connection socket if necessary + if (m_socket != INVALID_SOCKET) + { + shutdown(m_socket, SHUT_RDWR); + struct linger linger_opt = {1, 15}; + setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)); + closesocket(m_socket); + } + + // Decrement the object count + InterlockedDecrement(&numCChannelObjects); + + DbgTrace(1, "CChannel::~CChannel- End\n", 0); + +} /*-- CChannel::~CChannel() --*/ + + +//++======================================================================= +void +CChannel::openSocket(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "CChannel::openSocket- Start\n", 0); + + // Open a domain socket if not using Tcp + if (m_useTcpSocket == false) + m_socket = socket(PF_UNIX, SOCK_STREAM, 0); + else + m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + DbgTrace(1, "CChannel::openSocket- End\n", 0); + +} /*-- CChannel::openSocket() --*/ + + +//++======================================================================= +int +CChannel::connectSocket(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus; + + DbgTrace(1, "CChannel::connectSocket- Start\n", 0); + + // Proceed based on whether or not we need + // to use Tcp sockets. + if (m_useTcpSocket) + { + struct sockaddr_in localAddr = {0}; + + // Setup the address structure + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Perform bind operation + retStatus = bind(m_socket, + (const sockaddr*) &localAddr, + sizeof(struct sockaddr_in)); + if (!retStatus) + { + // Perform connect operation + retStatus = connect(m_socket, + (struct sockaddr*) &m_remoteAddrIn, + sizeof(struct sockaddr_in)); + if (retStatus == SOCKET_ERROR) + { + DbgTrace(0, "CChannel::connectSocket- Connection creation failed, error = %d\n", errno); + } + } + else + { + DbgTrace(0, "CChannel::connectSocket- Unable to bind socket, error = %d", errno); + } + } + else + { + // Perform connect operation + retStatus = connect(m_socket, + (struct sockaddr*) &m_remoteAddrUn, + sizeof(m_remoteAddrUn.sun_family) + strlen(m_remoteAddrUn.sun_path)); + if (retStatus == SOCKET_ERROR) + { + DbgTrace(0, "CChannel::connectSocket- Connection creation failed, error = %d\n", errno); + } + } + + DbgTrace(1, "CChannel::connectSocket- End, status = %08X\n", retStatus); + + return retStatus; + +} /*-- CChannel::connectSocket() --*/ + + +//++======================================================================= +int +CChannel::init(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + SmartCChannel *pSmartCChannel = NULL; + + DbgTrace(1, "CChannel::init- Start, Obj = %08X\n", this); + + // Verify the state of the object + if (m_state == State_Uninitialized) + { + openSocket(); + if (m_socket != INVALID_SOCKET) + { + if (connectSocket() != SOCKET_ERROR) + { + // Advance the object state + m_state = State_Connected; + + // Launch a thread to service the channel connection + try { + // Create a SmartCChannel object to make sure that the object + // does not get deleted prematurely. + pSmartCChannel = new SmartCChannel(this); + + // Create the channel connection thread + pthread_t thread; + int threadCreateStatus = pthread_create(&thread, + NULL, + (void*(*)(void*))CChannel::connectionThread, + pSmartCChannel); + if (threadCreateStatus == 0) + { + // We succeeded + retStatus = 0; + } + else + { + DbgTrace(0, "CChannel::init- Unable to create channel connection thread, error = %08X\n", threadCreateStatus); + } + } + catch (...) { + DbgTrace(0, "CChannel::init- Exception caught creating smart pointer\n", 0); + } + } + else + { + DbgTrace(0, "CChannel::init- Connection creation failed, error = %d\n", errno); + } + } + else + { + DbgTrace(0, "CChannel::init- Unable to open socket, error = %d\n", errno); + } + } + else + { + DbgTrace(0, "CChannel::init- invalid state, state = %d\n", m_state); + } + + // Deal with initialization failures + if (retStatus) + { + // Adjust the object state + m_state = State_FailedInitialization; + + // Free SmartCChannel just in case + delete pSmartCChannel; + } + + DbgTrace(1, "CChannel::init- End, status = %08X\n", retStatus); + + return retStatus; + +} /*-- CChannel::init() --*/ + + +//++======================================================================= +void* +CChannel::connectionThread( + SmartPtr *pSmartCChannel) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + CChannel *pCChannel = *pSmartCChannel; + bool doneReceivingData = false; + unsigned long bytesReceived; + uint32_t reqId; + int payloadLength; + unsigned long totalPayloadBytesReceived = 0; + char reqDataPktHdr[sizeof(ReqDataPktHdrTemplate) - 1]; + char *pRecvBuff; + RCMapIter iter; + ClientReq *pClientReq; + + DbgTrace(1, "CChannel::connectionThread- Start, Obj = %08X\n", pCChannel); + + // Set the thread in the detached state so that it is cleaned up when it exits + pthread_detach(pthread_self()); + + // Check that we are still connected + if (pCChannel->m_state == State_Connected) + { + // Receive and process channel data + while (!doneReceivingData) + { + DbgTrace(2, "CChannel::connectionThread- Receive Loop, Obj = %08X\n", pCChannel); + + // Receive the ReqDataPktHdr. Note, if we add other packet types and if the + // packet types have different header lengths, then we will need to modify + // this code to first receive the packet type and then receive the rest + // of the header based on type. + while (1) + { + bytesReceived = recv(pCChannel->m_socket, + reqDataPktHdr, + sizeof(ReqDataPktHdrTemplate) - 1, + MSG_WAITALL); + if (bytesReceived == SOCKET_ERROR + && errno == EINTR) + { + continue; + } + break; + } + if (bytesReceived != SOCKET_ERROR) + { + // Check if the connection was terminated + if (bytesReceived == (sizeof(ReqDataPktHdrTemplate) - 1)) + { + // Get the payload length + if (ChannelProto::getReqIdAndPayloadLength(reqDataPktHdr, + sizeof(reqDataPktHdr), + &reqId, + &payloadLength)) + { + // Procced based on the packet type + switch (ChannelProto::getPktType(*reqDataPktHdr)) + { + case ChannelProto::ReqDataCarrierPacketType: + + DbgTrace(2, "CChannel::connectionThread- Processing Request Data Packet, Obj = %08X\n", pCChannel); + + // Allocate a buffer big enough to receive the payload + pRecvBuff = (char*) malloc(payloadLength); + if (pRecvBuff != NULL) + { + // Buffer allocated, receive the request payload. + while (1) + { + bytesReceived = recv(pCChannel->m_socket, + pRecvBuff, + payloadLength, + MSG_WAITALL); + if (bytesReceived == SOCKET_ERROR + && errno == EINTR) + { + continue; + } + break; + } + if (bytesReceived != SOCKET_ERROR) + { + // Verify that we received all of the payload + if (bytesReceived == payloadLength) + { + // Received all of the payload data + totalPayloadBytesReceived += bytesReceived; + + // Acquire exclusive access to the CChannel object + pthread_mutex_lock(&pCChannel->m_mutex); + + // Find the appropriate ClientReq object in the ClientReqMap using + // the reqId present in the Req Data Packet Header. + iter = pCChannel->m_rcMap.find(reqId); + if (iter != pCChannel->m_rcMap.end()) + { + // Object was found in the map, use it to process the + // request payload. + pClientReq = iter->second; + pClientReq->processServerData(pRecvBuff, + bytesReceived); + + // Forget about the receive buffer + pRecvBuff = NULL; + } + else + { + DbgTrace(0, "CChannel::connectionThread- Error, did not find object in map, Obj = %08X\n", pCChannel); + } + + // Release exclusive access to the CChannel object + pthread_mutex_unlock(&pCChannel->m_mutex); + } + else + { + DbgTrace(1, "CChannel::connectionThread- Connection aborted prematurely, Obj = %08X\n", pCChannel); + //DbgTrace(0, "CChannel::connectionThread- 1Connection aborted prematurely, Obj = %08X\n", pCChannel); + //DbgTrace(0, "CChannel::connectionThread- 1bytesReceived = %d\n", bytesReceived); + //DbgTrace(0, "CChannel::connectionThread- 1payloadLength = %d\n", payloadLength); + //DbgTrace(0, "CChannel::connectionThread- 1errno = %d\n", errno); + //printf("bytesReceived = %d, payloadLength = %d\n", bytesReceived, payloadLength); + //printf("CChannel::connectionThread- 1Connection aborted prematurely, Obj = %08X\n", pCChannel); + doneReceivingData = true; + } + } + else + { + DbgTrace(1, "CChannel::connectionThread- Connection aborted prematurely, Obj = %08X\n", pCChannel); + //DbgTrace(0, "CChannel::connectionThread- 2Connection aborted prematurely, Obj = %08X\n", pCChannel); + //DbgTrace(0, "CChannel::connectionThread- 2errno = %d\n", errno); + //printf("Socket error = %d\n", errno); + //printf("CChannel::connectionThread- 2Connection aborted prematurely, Obj = %08X\n", pCChannel); + doneReceivingData = true; + } + + // Free receive buffer if necessary + if (pRecvBuff) + delete[] pRecvBuff; + } + else + { + DbgTrace(0, "CChannel::connectionThread- Unable to allocate receive buffer, Obj = %08X\n", pCChannel); + doneReceivingData = true; + } + break; + + case ChannelProto::ReqErrorCarrierPacketType: + + DbgTrace(1, "CChannel::connectionThread- Processing Request Error Packet, Obj = %08X\n", pCChannel); + + // Acquire exclusive access to the CChannel object + pthread_mutex_lock(&pCChannel->m_mutex); + + // Find the appropriate ClientReq object in the ClientReqMap using + // the reqId present in the Req Data Packet Header. + iter = pCChannel->m_rcMap.find(reqId); + if (iter != pCChannel->m_rcMap.end()) + { + // Object was found in the map, use it to process the Request Error. + pClientReq = iter->second; + pClientReq->processError(); + } + else + { + DbgTrace(0, "CChannel::connectionThread- Error, did not find object in map, Obj = %08X\n", pCChannel); + } + + // Release exclusive access to the CChannel object + pthread_mutex_unlock(&pCChannel->m_mutex); + break; + + default: + + DbgTrace(0, "CChannel::connectionThread- Unknown Packet Type, Obj = %08X\n", pCChannel); + doneReceivingData = true; + break; + } + } + else + { + DbgTrace(1, "CChannel::connectionThread- Unable to obtain payload length, Obj = %08X\n", pCChannel); + doneReceivingData = true; + } + } + else + { + DbgTrace(1, "CChannel::connectionThread- The channel connection was terminated, Obj = %08X\n", pCChannel); + //DbgTrace(0, "CChannel::connectionThread- 3The channel connection was terminated, Obj = %08X\n", pCChannel); + //DbgTrace(0, "CChannel::connectionThread- 3bytesReceived = %d\n", bytesReceived); + //DbgTrace(0, "CChannel::connectionThread- 3expected = %d\n", ReqDataPktHdrTemplate.length()); + //DbgTrace(0, "CChannel::connectionThread- 3errno = %d\n", errno); + //printf("bytesReceived = %d, expected = %d\n", bytesReceived, ReqDataPktHdrTemplate.length()); + //printf("CChannel::connectionThread- 3The channel connection was terminated, Obj = %08X\n", pCChannel); + doneReceivingData = true; + } + } + else + { + DbgTrace(1, "CChannel::connectionThread- The channel connection was aborted, Obj = %08X\n", pCChannel); + //DbgTrace(0, "CChannel::connectionThread- 4The channel connection was aborted, Obj = %08X\n", pCChannel); + //DbgTrace(0, "CChannel::connectionThread- 4errno = %d\n", errno); + //printf("Socket error = %d\n", errno); + //printf("CChannel::connectionThread- 4The channel connection was aborted, Obj = %08X\n", pCChannel); + doneReceivingData = true; + } + } + } + + // Acquire exclusive access to the CChannel object + pthread_mutex_lock(&pCChannel->m_mutex); + + // Try to change the CChannel state to disconnected + if (pCChannel->m_state == State_Connected) + pCChannel->m_state = State_Disconnected; + + // Deliver error notifications to all of the ClientReqs + // still associated with the CChannel. + if (!pCChannel->m_rcMap.empty()) + { + iter = pCChannel->m_rcMap.begin(); + while (iter != pCChannel->m_rcMap.end()) + { + // Object was found in the map, deliver error notification + // to it. + pClientReq = iter->second; + pClientReq->processError(); + + // Move on to the next element in the map + iter ++; + } + } + + // Release exclusive access to the CChannel object + pthread_mutex_unlock(&pCChannel->m_mutex); + + // Free SmartCChannel + delete pSmartCChannel; + + DbgTrace(1, "CChannel::connectionThread- End\n", 0); + + // Exit + pthread_exit(NULL); + + return 0; // never-reached! + +} /*-- CChannel::connectionThread() --*/ + + +//++======================================================================= +void +CChannel::closeChannel(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + + DbgTrace(1, "CChannel::closeChannel- Start, Obj = %08X\n", this); + + // Acquire CChannel mutex + pthread_mutex_lock(&m_mutex); + + // Switch the socket state to closed + m_state = State_Closed; + + // Check if we must close the socket + if (m_socket != INVALID_SOCKET) + { + // Socket needs to be closed, this will + // release the channel connection thread + // if it is active. + shutdown(m_socket, SHUT_RDWR); + struct linger linger_opt = {1, 15}; + setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)); + closesocket(m_socket); + m_socket = INVALID_SOCKET; + } + + // Release CChannel mutex + pthread_mutex_unlock(&m_mutex); + + DbgTrace(1, "CChannel::closeChannel- End\n", 0); + +} /*-- CChannel::closeChannel() --*/ + + +//++======================================================================= +bool +CChannel::ok(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + bool retStatus; + + DbgTrace(1, "CChannel::ok- Start, Obj = %08X\n", this); + + // Return true if connected + if (m_state == State_Connected) + retStatus = true; + else + retStatus = false; + + DbgTrace(1, "CChannel::ok- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- CChannel::ok() --*/ + + +//++======================================================================= +uint32_t +CChannel::allocReqId(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + uint32_t allocatedId; + + DbgTrace(1, "CChannel::allocReqId- Start, Obj = %08X\n", this); + + // Perform atomic operation + allocatedId = InterlockedIncrement(&m_reqIdAllocator); + + DbgTrace(1, "CChannel::allocReqId- End, allocatedId = %08X\n", allocatedId); + + return allocatedId; + +} /*-- CChannel::allocReqId() --*/ + + +//++======================================================================= +int +CChannel::submitReq( + uint32_t reqId, + ClientReq &clientReq, + char *pClientData, + int clientDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + char reqDataPktHdr[sizeof(ReqDataPktHdrTemplate) - 1]; + struct msghdr sendmsgHdr = {0}; + struct iovec ioVectors[2]; + unsigned long bytesSent; + unsigned long totalBytesSent = 0; + unsigned long bytesToSend = sizeof(reqDataPktHdr) + clientDataLen; + + DbgTrace(1, "CChannel::submitReq- Start, Obj = %08X\n", this); + + // Acquire exclusive access to the channel object + pthread_mutex_lock(&m_mutex); + + // Verify that the channel is connected + if (m_state == State_Connected) + { + // Insert the specified ClientReq into the ClientReqMap and forward the client + // data to the server. + RCIterBoolPair insertResult; + insertResult = m_rcMap.insert(make_pair(reqId, &clientReq)); + if (!insertResult.second) + { + // Insertion failed + DbgTrace(0, "CChannel::submitReq- Unable to insert ClientReq into ClientReqMap, Obj = %08X\n", this); + } + else + { + // Insertion succeded, now send the request to the server. + // + // Build ReqDataHeader + if (ChannelProto::buildReqDataPktHdr(reqId, + clientDataLen, + reqDataPktHdr) == 0) + { + // Packet header was built, now sent it along with the client data to + // the server. + ioVectors[0].iov_base = reqDataPktHdr; + ioVectors[0].iov_len = sizeof(reqDataPktHdr); + ioVectors[1].iov_base = (char*) pClientData; + ioVectors[1].iov_len = clientDataLen; + sendmsgHdr.msg_iov = ioVectors; + sendmsgHdr.msg_iovlen = 2; + while (1) + { + bytesSent = sendmsg(m_socket, + &sendmsgHdr, + MSG_NOSIGNAL); + if (bytesSent == SOCKET_ERROR) + { + // Check if we were interrupted during the transfer + if (errno == EINTR) + { + // Just try again + continue; + } + + // An unrecoverable error was encountered during the send operation, + // assume there was a communication failure. Close the socket to make + // sure that the connectionThread cleans up. + DbgTrace(0, "CChannel::submitReq- sendmsg error, errno = %d\n", errno); + m_state = State_Disconnected; + shutdown(m_socket, SHUT_RDWR); + struct linger linger_opt = {1, 15}; + setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)); + closesocket(m_socket); + m_socket = INVALID_SOCKET; + break; + } + else + { + // Account for the bytes sent + totalBytesSent += bytesSent; + + // Check if we are done sending all of the data + if (totalBytesSent >= bytesToSend) + { + // We are done + break; + } + else + { + // Adjust the ioVector structure to send data not yet sent + if (totalBytesSent >= sizeof(reqDataPktHdr)) + { + // The packet header was sent, use only one ioVector. + int clientDataAlreadySent = totalBytesSent - sizeof(reqDataPktHdr); + ioVectors[0].iov_base = (char*) pClientData + clientDataAlreadySent; + ioVectors[0].iov_len = clientDataLen - clientDataAlreadySent; + sendmsgHdr.msg_iov = ioVectors; + sendmsgHdr.msg_iovlen = 1; + } + else + { + // Not all of the packet header was sent, use two ioVectors. + ioVectors[0].iov_base = (char*) reqDataPktHdr + totalBytesSent; + ioVectors[0].iov_len = sizeof(reqDataPktHdr) - totalBytesSent; + ioVectors[1].iov_base = (char*) pClientData; + ioVectors[1].iov_len = clientDataLen; + sendmsgHdr.msg_iov = ioVectors; + sendmsgHdr.msg_iovlen = 2; + } + } + } + } + + // Return success even if the send failed to allow things to be cleaned up + // by the connectionThread routine. + retStatus = 0; + } + else + { + DbgTrace(0, "CChannel::submitReq- Error building Req Data Pkt Header, Obj = %08X\n", this); + + // Remove ClientReq from the ClientReqMap + RCMapIter iter = m_rcMap.find(reqId); + if (iter != m_rcMap.end()) + { + // Object was found in the map, remove it. + m_rcMap.erase(iter); + } + else + { + DbgTrace(0, "CChannel::submitReq- Error, did not find object in map to remove\n", 0); + } + } + } + } + else + { + DbgTrace(1, "CChannel::submitReq- Channel not connected, state = %08X\n", m_state); + } + + // Release exclusive access to the channel object + pthread_mutex_unlock(&m_mutex); + + DbgTrace(1, "CChannel::submitReq- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- CChannel::submitReq() --*/ + + +//++======================================================================= +void +CChannel::removeReq( + uint32_t reqId) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "CChannel::removeReq- Start, Obj = %08X\n", this); + + // Acquire exclusive access to the channel object + pthread_mutex_lock(&m_mutex); + + // Try to find the ClientReq in the ClientReqMap using the reqId + RCMapIter iter = m_rcMap.find(reqId); + if (iter != m_rcMap.end()) + { + // Object was found in the map, remove it. + m_rcMap.erase(iter); + } + else + { + DbgTrace(0, "CChannel::removeReq- Error, did not find object in map\n", 0); + } + + // Release exclusive access to the channel object + pthread_mutex_unlock(&m_mutex); + + DbgTrace(1, "CChannel::removeReq- End\n", 0); + +} /*-- CChannel::removeReq() --*/ + + +//++======================================================================= +int +CChannel::sendData( + uint32_t reqId, + char *pClientData, + int clientDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + char reqDataPktHdr[sizeof(ReqDataPktHdrTemplate) - 1]; + struct msghdr sendmsgHdr = {0}; + struct iovec ioVectors[2]; + unsigned long bytesSent; + unsigned long totalBytesSent = 0; + unsigned long bytesToSend = sizeof(reqDataPktHdr) + clientDataLen; + + DbgTrace(1, "CChannel::sendData- Start, Obj = %08X\n", this); + + // Acquire exclusive access to the channel object + pthread_mutex_lock(&m_mutex); + + // Verify that the channel is connected + if (m_state == State_Connected) + { + // Build ReqDataHeader + if (ChannelProto::buildReqDataPktHdr(reqId, + clientDataLen, + reqDataPktHdr) == 0) + { + // Packet header was built, now sent it along with the client data to + // the server. + ioVectors[0].iov_base = reqDataPktHdr; + ioVectors[0].iov_len = sizeof(reqDataPktHdr); + ioVectors[1].iov_base = (char*) pClientData; + ioVectors[1].iov_len = clientDataLen; + sendmsgHdr.msg_iov = ioVectors; + sendmsgHdr.msg_iovlen = 2; + while (1) + { + bytesSent = sendmsg(m_socket, + &sendmsgHdr, + MSG_NOSIGNAL); + if (bytesSent == SOCKET_ERROR) + { + // Check if we were interrupted during the transfer + if (errno == EINTR) + { + // Just try again + continue; + } + + // An unrecoverable error was encountered during the send operation, + // assume there was a communication failure. Close the socket to make + // sure that the connectionThread cleans up. + DbgTrace(0, "CChannel::sendData- sendmsg error, errno = %d\n", errno); + m_state = State_Disconnected; + shutdown(m_socket, SHUT_RDWR); + struct linger linger_opt = {1, 15}; + setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)); + closesocket(m_socket); + m_socket = INVALID_SOCKET; + break; + } + else + { + // Account for the bytes sent + totalBytesSent += bytesSent; + + // Check if we are done sending all of the data + if (totalBytesSent >= bytesToSend) + { + // We are done + break; + } + else + { + // Adjust the ioVector structure to send data not yet sent + if (totalBytesSent >= sizeof(reqDataPktHdr)) + { + // The packet header was sent, use only one ioVector. + int clientDataAlreadySent = totalBytesSent - sizeof(reqDataPktHdr); + ioVectors[0].iov_base = (char*) pClientData + clientDataAlreadySent; + ioVectors[0].iov_len = clientDataLen - clientDataAlreadySent; + sendmsgHdr.msg_iov = ioVectors; + sendmsgHdr.msg_iovlen = 1; + } + else + { + // Not all of the packet header was sent, use two ioVectors. + ioVectors[0].iov_base = (char*) reqDataPktHdr + totalBytesSent; + ioVectors[0].iov_len = sizeof(reqDataPktHdr) - totalBytesSent; + ioVectors[1].iov_base = (char*) pClientData; + ioVectors[1].iov_len = clientDataLen; + sendmsgHdr.msg_iov = ioVectors; + sendmsgHdr.msg_iovlen = 2; + } + } + } + } + + // Return success even if the send failed to allow things to be cleaned up + // by the connectionThread routine. + retStatus = 0; + } + else + { + DbgTrace(0, "CChannel::sendData- Error building Req Data Pkt Header, Obj = %08X\n", this); + } + } + else + { + DbgTrace(1, "CChannel::sendData- Channel not connected, state = %08X\n", m_state); + } + + // Release exclusive access to the channel object + pthread_mutex_unlock(&m_mutex); + + DbgTrace(1, "CChannel::sendData- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- CChannel::sendData() --*/ + + +//========================================================================= +//========================================================================= + + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/cchannel.h b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/cchannel.h new file mode 100644 index 00000000..093c1e49 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/cchannel.h @@ -0,0 +1,274 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _CCHANNEL_ +#define _CCHANNEL_ + +//===[ Include files ]===================================================== + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Type definitions ]================================================== + +// Forward reference +class ClientReq; + +// +// CChannel Class Definition +// +class CChannel : public ObjRef +{ + // Object State + enum ChannelStates + { + State_Uninitialized = 1, + State_FailedInitialization, + State_Connected, + State_Disconnected, + State_Closed + }; + ChannelStates m_state; + + // Connection socket + int m_socket; + + // Connection addresses + struct sockaddr_in m_remoteAddrIn; + struct sockaddr_un m_remoteAddrUn; + bool m_useTcpSocket; + + // ReqId Allocator + uint32_t m_reqIdAllocator; + + // Synchronization variables + pthread_mutex_t m_mutex; + + // + // Client Request Map - This map contains all of the active ClientReq objects. + // The key used to obtain ClientReq object in the map + // is the Request Id. + // + typedef map RCMap; + typedef RCMap::iterator RCMapIter; + typedef pair RCIterBoolPair; + RCMap m_rcMap; + + // + // Service connection thread procedure + // + // Parameters: + // pSmartCChannel (input) - + // Pointer to SmartPtr object. + // + // Abstract: Thread in charge of servicing channel connection. + // + // Returns: Nothing. + // + static void* connectionThread(SmartPtr *pSmartCChannel); + + // + // Open socket routine + // + // Parameters: None. + // + // Abstract: Opens CChannel object socket. + // + // Returns: Nothing. + // + void openSocket(void); + + // + // Connect socket routine + // + // Parameters: None. + // + // Abstract: Connects the CChannel object socket. + // + // Returns: Socket connect operation return status. + // + int connectSocket(void); + +public: + + // + // Constructor + // + // Parameters: + // remoteAddress (input) - + // Reference to sockaddr_in structure containing the remote + // endpoint address. + // + // Abstract: Constructs CChannel object. + // + // Returns: Nothing. + // + CChannel(struct sockaddr_in *remoteAddress); + + // + // Constructor + // + // Parameters: + // remoteAddress (input) - + // Reference to sockaddr_un structure containing the remote + // endpoint address. + // + // Abstract: Constructs CChannel object. + // + // Returns: Nothing. + // + CChannel(struct sockaddr_un *remoteAddress); + + // + // Destructor + ~CChannel(void); + + // + // Initialization routine + // + // Parameters: None. + // + // Abstract: Initializes CChannel object. + // + // Returns: 0 if successful. + // + int init(void); + + // + // Close channel routine + // + // Parameters: None. + // + // Abstract: Closes the channel. + // + // Returns: Nothing. + // + void closeChannel(void); + + // + // Check channel status routine. + // + // Parameters: None. + // + // Abstract: Checks if the channel status is OK + // + // Returns: True if the channel status is OK. + // + bool ok(void); + + // + // Allocate Request Id routine + // + // Parameters: None. + // + // Abstract: Closes the channel. + // + // Returns: Allocated Request Id. + // + uint32_t allocReqId(void); + + // + // Submit Request routine + // + // Parameters: + // reqId (input) - + // Id of the Request. + // + // clientReq (input) - + // Reference to ClientReq object. + // + // 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. + // + // Abstract: Submits a Request. + // + // Returns: 0 if successful. + // + int submitReq(uint32_t reqId, + ClientReq &clientReq, + char *pClientData, + int clientDataLen); + + // + // Remove Request routine + // + // Parameters: + // reqId (input) - + // Id of the Request. + // + // Abstract: Removes a Request from the channel. + // + // Returns: Nothing. + // + void removeReq(uint32_t reqId); + + // + // Send Data routine + // + // Parameters: + // reqId (input) - + // Id of the Request. + // + // 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. + // + // + // Abstract: Sends data to the server for a previously + // submitted Request. + // + // Returns: 0 if successful. + // + int sendData(uint32_t reqId, + char *pClientData, + int clientDataLen); +}; +typedef SmartPtr SmartCChannel; + + +//===[ Function prototypes ]=============================================== + + +#endif // _CCHANNEL_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/client.cpp b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/client.cpp new file mode 100644 index 00000000..f6db41e1 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/client.cpp @@ -0,0 +1,630 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "ipcint.h" + +extern "C" { +#include "casa_c_ipc.h" +} + +#include "cchannel.h" +#include "clientreq.h" + + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +#define MAX_RPC_RETRIES 3 + +#define MAX_CHANNELS 3 + +//===[ 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 ]=============================================== + +//===[ Global variables ]================================================== + +// Debug Level +int DebugLevel = 0; +bool UseSyslog = false; + +// Application Name for logging purposes +char unInitialized[] = "Uninitialized"; +char *pAppName = unInitialized; + +vector cchannelVector; +int numCChannels; +int numChannelSubmits = 0; + +// Client mutex +pthread_mutex_t clientMutex; + +// Mutex for interlocked operations +pthread_mutex_t interlockedMutex; + +// Indications +bool svcInitialized = false; +bool serverAddressSet = false; + +// Server address variables +bool use_AF_INET; +bool use_PF_UNIX; +struct sockaddr_in serverInAddr = {0}; +struct sockaddr_un serverUnAddr = {0}; + + +//++======================================================================= +void +ReInitializeIpc(void) +// +// Arguments In: None. +// +// Arguments Out: None. +// +// Returns: Nothing. +// +// Abstract: Method to re-initialize the IPC infrastructure for process. +// +// L2 +//=======================================================================-- +{ + CChannel *pCChannel; + + DbgTrace(1, "ReInitializeIpc- Start\n", 0); + + // Clean up all allocated SmartCChannel objects + for (int i = 0; i < cchannelVector.size(); i++) + { + // Close the channel if present + if (cchannelVector[i].getPointer() != NULL) + { + pCChannel = *(cchannelVector[i].getPointer()); + pCChannel->closeChannel(); + + // Free the SmartCChannel + delete cchannelVector[i].getPointer(); + cchannelVector[i].setPointer(NULL); + } + } + + DbgTrace(1, "ReInitializeIpc- End\n", 0); +} + + +//++======================================================================= +extern "C" +int +IpcClientInit( + IN char *pName, + IN bool multithreaded, + 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. +// +// multithreaded - Set to TRUE if the process is +// multithreaded. +// +// 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 appropriate function to +// set the server address before a request can be submitted. +// +// L0 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "IpcClientInit- Start\n", 0); + + // Check input parameters + if (pAppName == NULL) + { + DbgTrace(0, "IpcClientInit- Invalid parameter\n", 0); + goto exit; + } + + // Save a copy of the application name + pAppName = new char[strlen(pName) + 1]; + if (pAppName == NULL) + { + DbgTrace(0, "IpcClientInit- Memory allocation failure\n", 0); + goto exit; + } + strcpy(pAppName, pName); + + // Save the rest of the debug settings + 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); + } + } + else + { + // SmartCChannel vector has already been instantiated + ReInitializeIpc(); + retStatus = 0; + } + +exit: + + DbgTrace(1, "IpcClientInit- End, status = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +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. +// +// L0 +//=======================================================================-- +{ + 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. +// +// L0 +//=======================================================================-- +{ + 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" +void +IpcClientShutdown(void) +// +// Arguments In: None. +// +// Arguments Out: None. +// +// Returns: Nothing. +// +// Abstract: Method to shutdown the IPC infrastructure for process. +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "IpcClientShutdown- Start\n", 0); + + ReInitializeIpc(); + + // Free the AppName string if necessary + if (pAppName != unInitialized) + { + delete[] pAppName; + pAppName = unInitialized; + } + + 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; +} + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/clientreq.cpp b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/clientreq.cpp new file mode 100644 index 00000000..06369742 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/clientreq.cpp @@ -0,0 +1,353 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "ipcint.h" +#include "cchannel.h" +#include "clientreq.h" + + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// +// Object Counters +// +unsigned long numClientReqObjects = 0; + + +//++======================================================================= +ClientReq::ClientReq( + uint32_t reqId) : + + m_reqId (reqId), + m_pServerData (NULL), + m_submitThreadActive (true), + m_completed (false), + m_internalProblem (false) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ClientReq::ClientReq- Start, Obj = %08X\n", this); + + // Initialize the mutex + if (pthread_mutex_init(&m_mutex, NULL) != 0) + { + DbgTrace(0, "ClientReq::ClientReq- Mutex initialization failed\n", 0); + + // Throw exception + throw bad_alloc(); + } + + // Initialize the condition + if (pthread_cond_init(&m_condition, NULL) != 0) + { + DbgTrace(0, "ClientReq::ClientReq- Condition initialization failed\n", 0); + + // Destroy the allocated mutex + pthread_mutex_destroy(&m_mutex); + + // Throw exception + throw bad_alloc(); + } + + // Increment the object count + InterlockedIncrement(&numClientReqObjects); + + DbgTrace(1, "ClientReq::ClientReq- End\n", 0); + +} /*-- ClientReq::ClientReq() --*/ + + +//++======================================================================= +ClientReq::~ClientReq(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ClientReq::~ClientReq- Start, Obj = %08X\n", this); + + // Cleanup resources allocated for the object + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_condition); + + // Release any server data that we may have + if (m_pServerData != NULL) + free(m_pServerData); + + // Decrement the object count + InterlockedDecrement(&numClientReqObjects); + + DbgTrace(1, "ClientReq::~ClientReq- End\n", 0); + +} /*-- ClientReq::~ClientReq() --*/ + + +//++======================================================================= +void +ClientReq::processServerData( + char *pServerData, + int serverDataLength) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ClientReq::processServerData- Start, Obj = %08X\n", this); + + // Acquire exclusive access to the object + pthread_mutex_lock(&m_mutex); + + try { + + // Save server dataetup the ServerData object + m_pServerData = pServerData; + m_serverDataLen = serverDataLength; + + // Check if we must awaken the thread that submitted the request + // so that it can service the server data. + if (!m_submitThreadActive) + { + // The submit thread is not active, awaken it. + m_submitThreadActive = true; + pthread_cond_signal(&m_condition); + } + } + catch(...) { + + DbgTrace(0, "ClientReq::processServerData- Exception caught, Obj = %08X\n", this); + + // Free the server data buffer + delete[] pServerData; + + // Record that we suffered an internal problem and mark the + // request as completed. + m_internalProblem = true; + m_completed = true; + + // Check if we must awaken the thread that submitted the request + // so that it can deal with the problem. + if (!m_submitThreadActive) + { + // The submit thread is not active, awaken it. + m_submitThreadActive = true; + pthread_cond_signal(&m_condition); + } + } + + // Release exclusive access to the object + pthread_mutex_unlock(&m_mutex); + + DbgTrace(1, "ClientReq::processServerData- End\n", 0); + +} /*-- ClientReq::processServerData() --*/ + + +//++======================================================================= +void +ClientReq::processError(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ClientReq::processError- Start, Obj = %08X\n", this); + + // Acquire exclusive access to the object + pthread_mutex_lock(&m_mutex); + + // Record that we suffered an internal problem and mark the + // request as completed. + m_internalProblem = true; + m_completed = true; + + // Check if we must awaken the thread that submitted the request + // so that it can deal with the problem. + if (!m_submitThreadActive) + { + // The submit thread is not active, awaken it. + m_submitThreadActive = true; + pthread_cond_signal(&m_condition); + } + + // Release exclusive access to the object + pthread_mutex_unlock(&m_mutex); + + DbgTrace(1, "ClientReq::processError- End\n", 0); + +} /*-- ClientReq::processError() --*/ + + +//++======================================================================= +int +ClientReq::waitForCompletion( + char **ppResponseData, + int *pResponseDataLength) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus; + int oldCancelState; + + DbgTrace(1, "ClientReq::waitForCompletion- Start, Obj = %08X\n", this); + + // Make sure that the thread can not be cancelled while executing + // in this routine. + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldCancelState); + + // Acquire exclusive access to the object + pthread_mutex_lock(&m_mutex); + + // Continue until the request completes + while (!m_completed) + { + // Wait to be awaken + // + // Indicate that we are no longer active + m_submitThreadActive = false; + pthread_cond_wait(&m_condition, &m_mutex); + } + + // Release exclusive access to the object + pthread_mutex_unlock(&m_mutex); + + // Determine the parameters that should be returned + if (!m_internalProblem) + { + retStatus = 0; + *ppResponseData = m_pServerData; + *pResponseDataLength = m_serverDataLen; + + // Forget about the server data buffer + m_pServerData = NULL; + } + else + retStatus = -1; + + DbgTrace(1, "ClientReq::waitForCompletion- End, retStatus = %08X\n", retStatus); + + // Restore the threads cancel state + pthread_setcancelstate(oldCancelState, NULL); + + return retStatus; + +} /*-- ClientReq::waitForCompletion() --*/ + + +//++======================================================================= +ClientReq::CompletionStatus +ClientReq::completionStatus(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CompletionStatus compStatus; + + DbgTrace(1, "ClientReq::completionStatus- Start, Obj = %08X\n", this); + + // Check if we encountered any issues + if (m_internalProblem) + { + compStatus = ErrorCompletionStatus; + } + else + { + compStatus = SuccessCompletionStatus; + } + + DbgTrace(1, "ClientReq::completionStatus- End, compStatus = %08X\n", compStatus); + + return compStatus; + +} /*-- ClientReq::completionStatus() --*/ + + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/clientreq.h b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/clientreq.h new file mode 100644 index 00000000..d707a9bb --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/clientreq.h @@ -0,0 +1,173 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +#ifndef _CLIENTREQ_ +#define _CLIENTREQ_ + +//===[ Include files ]===================================================== + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Type definitions ]================================================== + +// +// Client Request Class +// +class ClientReq +{ + // Req Id + uint32_t m_reqId; + + // Server Data + char *m_pServerData; + int m_serverDataLen; + + // Flag indicating the state of the submitting + // thread. + bool m_submitThreadActive; + + // Flag indicating that the Request has completed. + bool m_completed; + + // Flag indicating that a problem was encountered + // while processing the Request. + bool m_internalProblem; + + // Synchronization variables + pthread_mutex_t m_mutex; + pthread_cond_t m_condition; + +public: + + // Completion Statuses + enum CompletionStatus + { + SuccessCompletionStatus = 1, + ErrorCompletionStatus + }; + + // + // Constructor + // + // Parameters: + // reqId (input) - + // Id of the Request. + // + // clientHandler (input) - + // Pointer to Client Handler routine. + // + // Abstract: Constructs ClientReq object. + // + // Returns: Nothing. + // + ClientReq(uint32_t reqId); + + // + // Destructor + ~ClientReq(void); + + // + // Process Server Data routine + // + // Parameters: + // pServerData (input) - + // Pointer to buffer containing the server data. + // Buffer is released by call to the routine. + // + // serverDataLength (input) - + // Length of the server data. + // + // Abstract: Processes server data. + // + // Returns: Nothing. + // + void processServerData(char *pServerData, + int serverDataLength); + + // + // Process Error routine + // + // Parameters: None. + // + // Abstract: Processes channel and server error + // indication. + // + // Returns: Nothing. + // + void processError(void); + + // + // Wait For Completion routine + // + // Parameters: + // ppResponseData (input/output) - + // Pointer to variable that will receive pointer to + // buffer containing the data sent by the server. + // + // pResponseDataLength (input/output) - + // Pointer to variable that will receive the length + // of the data sent by the server. + // + // + // Abstract: Waits for the Request completion. + // + // Returns: 0 == Request completed gracefully + // -1 == Request did not complete gracefully + // + int waitForCompletion(char **ppResponseData, + int *pResponseDataLength); + + // + // Completion status + // + // Parameters: None. + // + // Abstract: Obtains the request completion status. + // + // Returns: Request completion status. + // status in order to find out. + // + ClientReq::CompletionStatus completionStatus(void); +}; + + +//===[ Function prototypes ]=============================================== + + +#endif // _CLIENTREQ_ + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/test/makeClient.sh b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/test/makeClient.sh new file mode 100755 index 00000000..f810ece5 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/test/makeClient.sh @@ -0,0 +1,3 @@ +#!/bin/bash +gcc -o TestClient testClient.c -g -I../../../../../include -L../../../../../lib/Release -lpthread -lcasa_c_ipc -Xlinker -rpath -Xlinker ../../../../../lib/Release + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/test/testClient.c b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/test/testClient.c new file mode 100644 index 00000000..47e7a8bc --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/client/test/testClient.c @@ -0,0 +1,286 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "casa_s_ipc.h" + +//===[ Type definitions ]================================================== + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0) \ + printf(X, Y); \ + else if (DebugLevel >= LEVEL) \ + printf(X, Y); \ +} + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Usage string +char usage[] = "\nTest: usage: [-c requestCount] [-t submitThreadCount] [-D DebugLevel]\n"; + +int DebugLevel = 3; + +// Request count +int submitReqCount = 100; + +// Submit thread count +int submitThreadCount = 1; + +// Synch mutex +pthread_mutex_t testMutex; + +bool errorDetected = false; + + +//++======================================================================= +void* SubmitThread() +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +//=======================================================================-- +{ + char reqData[] = "This is the request data"; + char *pReplyData; + int replyDataLen; + + DbgTrace(1, "SubmitThread- Start\n", 0); + + pthread_mutex_lock(&testMutex); + while (submitReqCount != 0 + && !errorDetected) + { + submitReqCount --; + pthread_mutex_unlock(&testMutex); + + // Submit request to the server + if (IpcClientSubmitReq(reqData, + strlen(reqData), + &pReplyData, + &replyDataLen) != 0) + { + DbgTrace(0, "SubmitThread- Req submit error\n", 0); + errorDetected = true; + } + else + { + // Free the reply data buffer + free(pReplyData); + } + + pthread_mutex_lock(&testMutex); + } + + DbgTrace(1, "SubmitThread- End\n", 0); + + // Exit + pthread_exit(NULL); + + return 0; // never-reached! +} + + +//++======================================================================= +void +ExecuteTests(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +//=======================================================================-- +{ + pthread_t thread; + int threadCreateStatus; + int threadCreatedCount = 0; + int i; + + DbgTrace(1, "ExecuteTests- Start\n", 0); + + // Initialize the Client Ipc Subsystem + if (IpcClientInit("TestClient", + true, + 3, + false) == 0) + { + // Set the server listen address + if (IpcClientSetInAddress(5000, + 0x7F000001) == 0) + { + // Start the configured number of threads to submit requests to + // the server. + for (i = 0; i < submitThreadCount; i++) + { + threadCreateStatus = pthread_create(&thread, + NULL, + (void*(*)(void*))SubmitThread, + (void*)NULL); + if (threadCreateStatus == 0) + threadCreatedCount ++; + else + { + DbgTrace(0, "ExecuteTests- Error creating submit thread, error = %08X\n", threadCreateStatus); + } + } + + // Wait for the requests to be submitted + if (threadCreatedCount != 0) + { + while (submitReqCount + && !errorDatected) + sleep(1); + sleep(1); + } + } + else + { + DbgTrace(0, "ExecuteTests- Error setting server address\n", 0); + } + + IpcClientShutdown(); + } + else + { + DbgTrace(0, "ExecuteTests- Ipc subsystem initialization failed\n", 0); + } + + DbgTrace(1, "ExecuteTests- End\n", 0); +} + + +//++======================================================================= +int +main( + int argc, + char* argv[]) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int optionsSpecified = 0; + bool doneScanning = false; + bool invalidOption = false; + int option; + + printf("**** Ipc Client test ****\n"); + + // Scan through the options specified + while (!doneScanning) + { + opterr = 0; + option = getopt(argc, argv, "c:t:D:"); + + // Proceed based on the result + switch (option) + { + case 'D': + // Set the debug level + printf("DebugLevel = %s\n", optarg); + DebugLevel = atoi(optarg); + optionsSpecified++; + break; + + case 'c': + // Set the submit request count + submitReqCount = atoi(optarg); + optionsSpecified++; + break; + + case 't': + // Set the submit thread count + submitThreadCount = 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) + { + printf("submitReqCount = %d\n", submitReqCount); + printf("submitThreadCount = %d\n", submitThreadCount); + ExecuteTests(); + } + else + { + // Invalid option detected + printf(usage, argv[0]); + } + + return 0; + +} /*-- main() --*/ + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/Makefile.am b/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/Makefile.am new file mode 100644 index 00000000..e387861d --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = + +DIST_SUBDIRS = + +CFILES = + +EXTRA_DIST = $(CFILES) *.h + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/channelproto.cpp b/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/channelproto.cpp new file mode 100644 index 00000000..c20fb353 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/channelproto.cpp @@ -0,0 +1,388 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "ipcint.h" + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Channel Packet Types +string DataCarrierTypeTemplate = "TypeXX"; +string ReqDataCarrierType = "Type01"; +string ReqErrorCarrierType = "Type02"; + +// Channel Packet Headers +string ReqIdHdr = "ReqIdHdr ="; +string PayloadLengthHdr = "PayloadLength ="; + +// Req Data Pkt Hdr Template +string ReqDataPktHdrTemplate = "Type01\r\nReqIdHdr =XXXXXXXX\r\nPayloadLength =XXXXXXXX\r\n\r\n"; + +// Req Error Pkt Hdr Template +string ReqErrorPktHdrTemplate = "Type02\r\nReqIdHdr =XXXXXXXX\r\nPayloadLength =XXXXXXXX\r\n\r\n"; + + +//++======================================================================= +int +ChannelProto::buildReqDataPktHdr( + uint32_t reqId, + int32_t payloadLength, + char *pPktHdr) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "ChannelProto::buildReqDataPktHdr- Start\n", 0); + + try { + // - Req Data Packet Header Format - + // + // ReqDataCarrierType + // ReqIdHdr value (value format=%08X) + // PayloadLengthHdr value (value format=%08X) + // + + // Setup the necessary value strings + char wrkBuffer[10]; + + sprintf(wrkBuffer, "%08X", reqId); + string reqIdValue = wrkBuffer; + sprintf(wrkBuffer, "%08X", payloadLength); + string payloadLengthValue = wrkBuffer; + + // Format the header. + char* pCurr = pPktHdr; + + memcpy(pCurr, ReqDataCarrierType.c_str(), ReqDataCarrierType.length()); + pCurr += ReqDataCarrierType.length(); + memcpy(pCurr, "\r\n", 2); + pCurr += 2; + + memcpy(pCurr, ReqIdHdr.c_str(), ReqIdHdr.length()); + pCurr += ReqIdHdr.length(); + memcpy(pCurr, reqIdValue.c_str(), reqIdValue.length()); + pCurr += reqIdValue.length(); + memcpy(pCurr, "\r\n", 2); + pCurr += 2; + + memcpy(pCurr, PayloadLengthHdr.c_str(), PayloadLengthHdr.length()); + pCurr += PayloadLengthHdr.length(); + memcpy(pCurr, payloadLengthValue.c_str(), payloadLengthValue.length()); + pCurr += payloadLengthValue.length(); + memcpy(pCurr, "\r\n\r\n", 4); + + // Success + retStatus = 0; + } + catch (...) { + DbgTrace(0, "ChannelProto::buildReqDataPktHdr- Exception caught while creating header\n", 0); + } + + DbgTrace(1, "ChannelProto::buildReqDataPktHdr- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- ChannelProto::buildReqDataPktHdr() --*/ + + +//++======================================================================= +int +ChannelProto::buildReqErrorPktHdr( + uint32_t reqId, + int32_t payloadLength, + char *pPktHdr) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "ChannelProto::buildReqErrorPktHdr- Start\n", 0); + + try { + // - Req Error Packet Header Format - + // + // ReqErrorCarrierType + // ReqIdHdr value (value format=%08X) + // PayloadLengthHdr value (value format=%08X) + // + + // Setup the necessary value strings + char wrkBuffer[10]; + + sprintf(wrkBuffer, "%08X", reqId); + string reqIdValue = wrkBuffer; + sprintf(wrkBuffer, "%08X", payloadLength); + string payloadLengthValue = wrkBuffer; + + // Format the header. + char* pCurr = pPktHdr; + + memcpy(pCurr, ReqErrorCarrierType.c_str(), ReqErrorCarrierType.length()); + pCurr += ReqErrorCarrierType.length(); + memcpy(pCurr, "\r\n", 2); + pCurr += 2; + + memcpy(pCurr, ReqIdHdr.c_str(), ReqIdHdr.length()); + pCurr += ReqIdHdr.length(); + memcpy(pCurr, reqIdValue.c_str(), reqIdValue.length()); + pCurr += reqIdValue.length(); + memcpy(pCurr, "\r\n", 2); + pCurr += 2; + + memcpy(pCurr, PayloadLengthHdr.c_str(), PayloadLengthHdr.length()); + pCurr += PayloadLengthHdr.length(); + memcpy(pCurr, payloadLengthValue.c_str(), payloadLengthValue.length()); + pCurr += payloadLengthValue.length(); + memcpy(pCurr, "\r\n\r\n", 4); + + // Success + retStatus = 0; + } + catch (...) { + DbgTrace(0, "ChannelProto::buildReqErrorPktHdr- Exception caught while creating header\n", 0); + } + + DbgTrace(1, "ChannelProto::buildReqErrorPktHdr- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- ChannelProto::buildReqErrorPktHdr() --*/ + + +//++======================================================================= +ChannelProto::PacketTypes +ChannelProto::getPktType( + char &buff) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + PacketTypes packetType = UnknownPacketType; + + DbgTrace(1, "ChannelProto::getPktType- Start\n", 0); + + // Find the end of the Channel Packet Type + char *pCurr = &buff; + while (*pCurr != '\r') + pCurr ++; + + // Found the end of the Channel Packet Type, now + // calculate its length. + int channelPktTypeLength = pCurr - &buff; + + // Now start comparing + if (channelPktTypeLength == ReqDataCarrierType.length() + && !memcmp(&buff, ReqDataCarrierType.c_str(), channelPktTypeLength)) + { + // The type is Channel Req Data Carrier + packetType = ReqDataCarrierPacketType; + } + else if (channelPktTypeLength == ReqErrorCarrierType.length() + && !memcmp(&buff, ReqErrorCarrierType.c_str(), channelPktTypeLength)) + { + // The type is Channel Req Error Carrier + packetType = ReqErrorCarrierPacketType; + } + else + { + DbgTrace(0, "ChannelProto::getPktType- No match found\n", 0); + } + + DbgTrace(1, "ChannelProto::getPktType- End, type = %d\n", packetType); + + return packetType; + +} /*-- ChannelProto::getPktType() --*/ + + +//++======================================================================= +bool +ChannelProto::getReqIdAndPayloadLength( + char *pBuff, + int hdrLength, + uint32_t *pReqId, + int32_t *pPayloadLength) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + bool reqIdObtained = false; + bool payloadLengthObtained = false; + + DbgTrace(1, "ChannelProto::getReqIdAndPayloadLength- Start\n", 0); + + char *pCurr = pBuff; + char *pChannelHdr = NULL; + int bytesLeft = hdrLength; + + // Skip the Channel Packet Type + while (bytesLeft >= 2) + { + if (*pCurr == '\r' + && *(pCurr+1) == '\n') + { + // Found the end of the channel packet type + pCurr += 2; + bytesLeft -= 2; + break; + } + else + { + pCurr ++; + bytesLeft --; + } + } + + // Start processing Channel Packet Headers + pChannelHdr = pCurr; + while (bytesLeft >= 2 + && (!reqIdObtained || !payloadLengthObtained)) + { + if (*pCurr == '\r' + && *(pCurr+1) == '\n') + { + // Found the end of the current channel header + pCurr += 2; + bytesLeft -= 2; + + // Check if the line is empty or if it contained a + // channel header. + if ((pCurr - pChannelHdr) == 2) + { + // This was an empty line, which means that + // we reached the end of the channel packet header. + break; + } + else + { + // Check if the header is the Req Id Hdr + if (!reqIdObtained && (pCurr - pChannelHdr) > ReqIdHdr.length() + && !memcmp(pChannelHdr, ReqIdHdr.c_str(), ReqIdHdr.length())) + { + // We found the Req Id Hdr, get the value. + char *pValue = pChannelHdr + ReqIdHdr.length(); + + // Temporarily NULL terminate the value + *(pCurr-2) = '\0'; + + // Convert the value to hex + *pReqId = strtoul(pValue, NULL, 16); + + // Undo the damage that we did + *(pCurr-2) = '\r'; + + // Remember that the Req Id was obtained + reqIdObtained = true; + } + // Check if the header is the Payload Length Hdr + else if ((pCurr - pChannelHdr) > PayloadLengthHdr.length() + && !memcmp(pChannelHdr, PayloadLengthHdr.c_str(), PayloadLengthHdr.length())) + { + // We found the Payload Length Hdr, get the value. + char *pValue = pChannelHdr + PayloadLengthHdr.length(); + + // Temporarily NULL terminate the value + *(pCurr-2) = '\0'; + + // Convert the value to hex + *pPayloadLength = strtoul(pValue, NULL, 16); + + // Undo the damage that we did + *(pCurr-2) = '\r'; + + // Remember that the Payload Lenght was obtained + payloadLengthObtained = true; + } + + // Get set to process the next header + pChannelHdr = pCurr; + } + } + else + { + pCurr ++; + bytesLeft --; + } + } + + DbgTrace(1, + "ChannelProto::getReqIdAndPayloadLength- End, retStatus = %08X\n", + reqIdObtained && payloadLengthObtained); + + return reqIdObtained && payloadLengthObtained; + +} /*-- ChannelProto::getReqIdAndPayloadLength() --*/ + + +//========================================================================= +//========================================================================= + + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/channelproto.h b/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/channelproto.h new file mode 100644 index 00000000..669a22ac --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/channelproto.h @@ -0,0 +1,157 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _CHANNELPROTO_ +#define _CHANNELPROTO_ + +//===[ Include files ]===================================================== + +//===[ External data ]===================================================== + +extern string ReqDataPktHdrTemplate; +extern string ReqErrorPktHdrTemplate; + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Type definitions ]================================================== + +// +// ChannelProto Class Definition +// +class ChannelProto +{ +public: + + // Packet Types + enum PacketTypes + { + ReqDataCarrierPacketType = 1, + ReqErrorCarrierPacketType, + UnknownPacketType + }; + + // + // Build Req Data Packet Header routine + // + // Parameters: + // reqId (input) - + // Req id. + // + // payloadLength (input) - + // Length of the payload being carried by the packet. + // + // pPktHdt (input/output) - + // Pointer to buffer that will receive the header. + // Note, this buffer needs to be big eneough to + // contain the ReqDataPktHdrTemplate string. + // + // Abstract: Returns Req Data Pkt Hdr for the specified + // parameters. + // + // Returns: 0 if successful. + // + static int buildReqDataPktHdr(uint32_t reqId, + int32_t payloadLength, + char *pPktHdr); + + // + // Build Req Error Packet Header routine + // + // Parameters: + // reqId (input) - + // Req id. + // + // payloadLength (input) - + // Length of the payload being carried by the packet. + // + // pPktHdt (input/output) - + // Pointer to buffer that will receive the header. + // Note, this buffer needs to be big eneough to + // contain the ReqErrorPktHdrTemplate string. + // + // Abstract: Returns Req Error Pkt Hdr for the specified + // parameters. + // + // Returns: 0 if successful. + // + static int buildReqErrorPktHdr(uint32_t reqId, + int32_t payloadLength, + char *pPktHdr); + + // + // Get Channel Packet Type routine + // + // Parameters: + // buff (input) - + // Reference to buffer containing the packet data. + // + // Abstract: Returns the type of the specified channel packet. + // + // Returns: Channel packet type. + // + static PacketTypes getPktType(char &buff); + + // + // Get Req Id and Payload Length Values routine + // + // Parameters: + // buff (input) - + // Reference to buffer containing the packet data. + // + // hdrLength (input) - + // Length of the channel header. + // + // pReqId (input/output) - + // Pointer to variable that will receive the req id. + // + // pPayloadLength (input/output) - + // Pointer to variable that will receive the payload length. + // + // Abstract: Returns the values of the ReqId and PayloadLength headers + // present in the channel packet header. + // + // Returns: True if successful. + // + static bool getReqIdAndPayloadLength(char *pBuff, + int hdrLength, + uint32_t *pReqId, + int32_t *pPayloadLength); +}; + + +//===[ Function prototypes ]=============================================== + + +#endif // _CHANNELPROTO_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/ipcint.h b/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/ipcint.h new file mode 100644 index 00000000..88511035 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/ipcint.h @@ -0,0 +1,149 @@ +/**********************\************************************************* + * + * 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 + * + ***********************************************************************/ + +#ifndef _IPCINT_ +#define _IPCINT_ + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +using namespace std; + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // Ensure that NDEBUG is defined for release builds! +#include +} + +//===[ External data ]===================================================== + +extern int DebugLevel; +extern bool UseSyslog; +extern char *pAppName; +extern pthread_mutex_t interlockedMutex; + +//===[ Macro definitions ]================================================= + +// +// DbgTrace macro define +// +#define MAX_FORMAT_STRING_LEN 1024 +#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0) { \ + char *pFormatString = new char[MAX_FORMAT_STRING_LEN]; \ + if (pFormatString) { \ + snprintf(pFormatString, MAX_FORMAT_STRING_LEN, X, Y); \ + if (UseSyslog) \ + syslog(LOG_USER | LOG_INFO, "%s -%s", pAppName, pFormatString); \ + else \ + fprintf(stderr, "%s -%s", pAppName, pFormatString); \ + delete[] pFormatString; \ + } \ + } else if (DebugLevel >= LEVEL) { \ + char *pFormatString = new char[MAX_FORMAT_STRING_LEN]; \ + if (pFormatString) { \ + snprintf(pFormatString, MAX_FORMAT_STRING_LEN, X, Y); \ + if (UseSyslog) \ + syslog(LOG_USER | LOG_DEBUG, "%s -%s", pAppName, pFormatString); \ + else \ + fprintf(stderr, "%s -%s", pAppName, pFormatString); \ + delete[] pFormatString; \ + } \ + } \ +} + +// +// Interlocked Increment and Decrement macros +// +// Well, kind of interlocked :-). +// +__inline static unsigned long +InterlockedIncrement(unsigned long *pValue) +{ + pthread_mutex_lock(&interlockedMutex); + *pValue ++; + pthread_mutex_unlock(&interlockedMutex); +} + +__inline static unsigned long +InterlockedDecrement(unsigned long *pValue) +{ + pthread_mutex_lock(&interlockedMutex); + *pValue --; + pthread_mutex_unlock(&interlockedMutex); +} + +__inline static uint32_t +InterlockedIncrement(uint32_t *pValue) +{ + pthread_mutex_lock(&interlockedMutex); + *pValue ++; + pthread_mutex_unlock(&interlockedMutex); +} + +__inline static uint32_t +InterlockedDecrement(uint32_t *pValue) +{ + pthread_mutex_lock(&interlockedMutex); + *pValue --; + pthread_mutex_unlock(&interlockedMutex); +} + +//===[ Include files ]===================================================== + +#include "smartptr.h" +#include "channelproto.h" + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + + +#endif // _IPCINT_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/smartptr.h b/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/smartptr.h new file mode 100644 index 00000000..2bc67aca --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/common/smartptr.h @@ -0,0 +1,280 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef SMARTPTR_H +#define SMARTPTR_H + +/******************************************************************************* +* Include Files +*******************************************************************************/ + +/******************************************************************************* +* Definitions +*******************************************************************************/ + +/******************************************************************************* +* Types and Classes +*******************************************************************************/ + + +//------------------------------------------------------------------------------ +// Reference Object +// +// In order to use the SmartPtr<> class, the object type used to instantiate +// the SmartPtr template must inheirit from the ObjRef class. +// +//------------------------------------------------------------------------------ +class ObjRef +{ + //--------------------------------------------------------------------------- + // Public interface + // + public: + + ObjRef() : m_Count(0) {} + + void IncRefCount(void) + { + InterlockedIncrement((unsigned long*)&m_Count); + } + + bool DecRefCount(void) + { + if ((m_Count > 0) && (InterlockedDecrement((unsigned long*)&m_Count) == 0)) + { + return true; + } + else + { + return false; + } + } + + unsigned int GetRefCount(void) const + { + return m_Count; + } + + //--------------------------------------------------------------------------- + // Private data + // + private: + + // BUGBUG!! - Need to put a lock in here so the count can be updated atomically. + // or use an interlocked inc/dec if one exists. + mutable unsigned int m_Count; + +}; + + +//------------------------------------------------------------------------------ +// SmartPtr Object +// +//------------------------------------------------------------------------------ +template +class SmartPtr +{ + //--------------------------------------------------------------------------- + // Public interface + // + public: + + SmartPtr(); + SmartPtr(T* ptr); + SmartPtr(const SmartPtr& ref); + + virtual ~SmartPtr(); + + operator bool (void) const; + bool operator! (void) const; + bool operator== (SmartPtr& ref) const; + bool operator!= (SmartPtr& ref) const; + + SmartPtr& operator= (const SmartPtr& ref); + SmartPtr& operator= (T* ptr); + + T& operator* (void) const; + T* operator-> (void) const; + operator T* (void) const; + + //--------------------------------------------------------------------------- + // Private interface + // + private: + + void deleteObject(void); + void resetPtr(T* newPtr); + + //--------------------------------------------------------------------------- + // Private data + // + private: + + T* m_Ptr; + +}; + + + +template +inline SmartPtr::SmartPtr() : + m_Ptr(0) +{ +} // End of SmartPtr::SmartPtr() + + +template +inline SmartPtr::SmartPtr(T* ptr) : + m_Ptr(0) +{ + resetPtr(ptr); + +} // End of SmartPtr::SmartPtr() + + +template +inline SmartPtr::SmartPtr(const SmartPtr& ref) : + m_Ptr(0) +{ + resetPtr(ref.m_Ptr); + +} // End of SmartPtr::SmartPtr() + + +template +inline SmartPtr::~SmartPtr() +{ + deleteObject(); + +} // End of SmartPtr::~SmartPtr() + + +template +inline SmartPtr::operator bool (void) const +{ + return m_Ptr != 0; + +} // End of SmartPtr::operator bool() + + +template +inline bool SmartPtr::operator! (void) const +{ + return m_Ptr == 0; + +} // End of SmartPtr::operator!() + + +template +inline bool SmartPtr::operator== (SmartPtr& ref) const +{ + return m_Ptr == ref.m_Ptr; + +} // End of SmartPtr::operator==() + + +template +inline bool SmartPtr::operator!= (SmartPtr& ref) const +{ + return m_Ptr != ref.m_Ptr; + +} // End of SmartPtr::operator==() + + +template +inline SmartPtr& SmartPtr::operator= (const SmartPtr& ref) +{ + resetPtr(ref.m_Ptr); + return *this; + +} // End of SmartPtr::operator=() + + +template +inline SmartPtr& SmartPtr::operator= (T* ptr) +{ + resetPtr(ptr); + return *this; + +} // End of SmartPtr::operator=() + + +template +inline T& SmartPtr::operator* (void) const +{ + return *m_Ptr; + +} // End of SmartPtr::operator*() + + +template +inline T* SmartPtr::operator-> (void) const +{ + return m_Ptr; + +} // End of SmartPtr::operator->() + + +template +inline SmartPtr::operator T* (void) const +{ + return m_Ptr; + +} // End of SmartPtr::operator T*() + + +template +inline void SmartPtr::deleteObject(void) +{ + if (m_Ptr && m_Ptr->DecRefCount()) + { + delete m_Ptr; + m_Ptr = 0; + } + +} // End of SmartPtr::deleteObject() + + +template +inline void SmartPtr::resetPtr(T* newPtr) +{ + if (m_Ptr != newPtr) + { + deleteObject(); + m_Ptr = newPtr; + + if (m_Ptr) + { + // New object reference. + m_Ptr->IncRefCount(); + } + } + +} // End of SmartPtr::resetPtr() + + +#endif // SMARTPTR_H +/******************************************************************************/ +/******************************************************************************/ + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/Makefile.am b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/Makefile.am new file mode 100644 index 00000000..a2310d9e --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/Makefile.am @@ -0,0 +1,123 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +if DEBUG +TARGET_CFG = Debug +CFLAGS += -v -w +CPPFLAGS = -g $(CFLAGS) +DEFINES = -DDBG +else +TARGET_CFG = Release +CPPFLAGS = -O2 -w $(CFLAGS) +DEFINES = -DNDEBUG +endif + +# Override the link setting for C++ +LINK = g++ + +SUBDIRS = + +DIST_SUBDIRS = + +ROOT = ../../../.. + +LIBDIR = $(ROOT)/$(LIB) + +# handle Mono secondary dependencies +export MONO_PATH := $(MONO_PATH) + +COMMON = ../common +SERVER = . + +MODULE_NAME = libcasa_s_ipc +MODULE_EXT = so + +CFILES = + +CPPFILES = channelproto.cpp \ + schannel.cpp \ + serverreq.cpp \ + serverthread.cpp \ + server.cpp + +CSFILES_CSC := +INCLUDES = -I. -I.. -I../common -I../../../../include +RESOURCES = +DEFINES += -Wno-format-extra-args -fno-strict-aliasing +CFLAGS += $(INCLUDES) $(DEFINES) +CPPFLAGS += $(INCLUDES) $(DEFINES) +LIBS = -lpthread -ldl -lexpat +LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) + +OBJDIR = ./$(TARGET_CFG)/$(LIB) +OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) $(addprefix $(OBJDIR)/, $(CPPFILES:%.cpp=%.o)) + +EXTRA_DIST = $(CFILES) *.h + +CUR_DIR := $(shell pwd) + +all: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + +# +# Pattern based rules. +# +vpath %.c $(SERVER) $(COMMON) +vpath %.cpp $(SERVER) $(COMMON) + +$(OBJDIR)/%.o: %.c + $(CC) -c $(CFLAGS) -o $@ $< + +$(OBJDIR)/%.o: %.cpp + $(CC) -c $(CPPFLAGS) -o $@ $< + +$(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT): $(OBJDIR) $(OBJS) + @echo [======== Linking $@ ========] + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + cp -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT) + +$(OBJDIR): + [ -d $(OBJDIR) ] || mkdir -p $(OBJDIR) + [ -d $(LIBDIR) ] || mkdir -p $(LIBDIR) + [ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(TARGET_CFG) + + +install-exec-local: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL_PROGRAM) $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(DESTDIR)$(libdir)/ + +uninstall-local: + cd $(DESTDIR)$(libdir); rm -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + rmdir $(DESTDIR)$(libdir) + +#installcheck-local: install +# $(mkinstalldirs) $(DESTDIR)$(libdir) +# $(INSTALL_PROGRAM) $(DESTDIR)$(libdir) +# cd $(DESTDIR)$(libdir); $(MONO) + +clean-local: + if [ -d $(TARGET_CFG) ]; then rm -rf $(TARGET_CFG); fi + +distclean-local: + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/schannel.cpp b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/schannel.cpp new file mode 100644 index 00000000..2d374340 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/schannel.cpp @@ -0,0 +1,698 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "ipcint.h" +#include "schannel.h" +#include "serverreq.h" + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +extern int +ServiceRequest( + ServerReq *pServerReq); + +extern void +RemoveFromSChannelList( + SChannel *pSChannel); + + +//===[ Manifest constants ]================================================ + +// +// Socket Mapping definitions +// +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define LINGER struct linger +#define SOCKADDR_IN struct sockaddr_in +#define closesocket close + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// +// Object Counters +// +unsigned long numSChannelObjects = 0; + + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +SChannel::SChannel( + int connSocket) : + + m_state (State_Connected), + m_socket (connSocket) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "SChannel::SChannel- Start, Obj = %08X\n", this); + + // Initialize the mutex + if (pthread_mutex_init(&m_mutex, NULL) != 0) + { + DbgTrace(0, "SChannel::SChannel- Mutex initialization failed\n", 0); + + // Throw exception + throw bad_alloc(); + } + + // Increment the object count + InterlockedIncrement(&numSChannelObjects); + + DbgTrace(1, "SChannel::SChannel- End\n", 0); + +} /*-- SChannel::SChannel() --*/ + + +//++======================================================================= +SChannel::~SChannel(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "SChannel::~SChannel- Start, Obj = %08X\n", this); + + // Cleanup resources allocated for the object + pthread_mutex_destroy(&m_mutex); + + // Free connection socket if necessary + if (m_socket != INVALID_SOCKET) + { + shutdown(m_socket, SHUT_RDWR); + struct linger linger_opt = {1, 15}; + setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)); + closesocket(m_socket); + } + + // Decrement the object count + InterlockedDecrement(&numSChannelObjects); + + DbgTrace(1, "SChannel::~SChannel- End\n", 0); + +} /*-- SChannel::~SChannel() --*/ + + +//++======================================================================= +int +SChannel::init(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + SmartSChannel *pSmartSChannel = NULL; + + DbgTrace(1, "SChannel::init- Start, Obj = %08X\n", this); + + // Verify the state of the object + if (m_state == State_Connected) + { + // Launch a thread to service the channel connection + try { + // Create a SmartSChannel object to make sure that the object + // does not get deleted prematurely. + pSmartSChannel = new SmartSChannel(this); + + // Create the channel connection thread + pthread_t thread; + int threadCreateStatus = pthread_create(&thread, + NULL, + (void*(*)(void*))SChannel::connectionThread, + pSmartSChannel); + if (threadCreateStatus == 0) + { + // We succeeded + retStatus = 0; + } + else + { + DbgTrace(0, "SChannel::init- Unable to create channel connection thread, error = %08X\n", threadCreateStatus); + } + } + catch (...) { + DbgTrace(0, "SChannel::init- Exception caught creating smart pointer\n", 0); + } + } + else + { + DbgTrace(0, "SChannel::init- invalid state, state = %d\n", m_state); + } + + // Deal with initialization failures + if (retStatus) + { + // Adjust the object state + m_state = State_FailedInitialization; + + // Free SmartSChannel just in case + delete pSmartSChannel; + } + + DbgTrace(1, "SChannel::init- End, status = %08X\n", retStatus); + + return retStatus; + +} /*-- SChannel::init() --*/ + + +//++======================================================================= +void* +SChannel::connectionThread( + SmartPtr *pSmartSChannel) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + SChannel *pSChannel = *pSmartSChannel; + bool doneReceivingData = false; + unsigned long bytesReceived; + unsigned long bytesSent; + uint32_t reqId; + int payloadLength; + unsigned long totalPayloadBytesReceived = 0; + char reqDataPktHdr[ReqDataPktHdrTemplate.length()]; + char reqErrorPktHdr[ReqErrorPktHdrTemplate.length()]; + char *pRecvBuff; + ServerReq *pServerReq; + + DbgTrace(1, "SChannel::connectionThread- Start, Obj = %08X\n", pSChannel); + + // Set the thread in the detached state so that it is cleaned up when it exits + pthread_detach(pthread_self()); + + // Check that we are still connected + if (pSChannel->m_state == State_Connected) + { + // Receive and process channel data + while (!doneReceivingData) + { + DbgTrace(2, "SChannel::connectionThread- Receive Loop, Obj = %08X\n", pSChannel); + + // Receive the ReqDataPktHdr. Note, if we add other packet types and if the + // packet types have different header lengths, then we will need to modify + // this code to first receive the packet type and then receive the rest + // of the header based on type. + while (1) + { + bytesReceived = recv(pSChannel->m_socket, + reqDataPktHdr, + ReqDataPktHdrTemplate.length(), + MSG_WAITALL); + if (bytesReceived != SOCKET_ERROR + || errno != EINTR) + { + break; + } + } + if (bytesReceived != SOCKET_ERROR) + { + // Check if the connection was terminated + if (bytesReceived == ReqDataPktHdrTemplate.length()) + { + // Get the reqId and payload length + if (ChannelProto::getReqIdAndPayloadLength(reqDataPktHdr, + sizeof(reqDataPktHdr), + &reqId, + &payloadLength)) + { + // Procced based on the packet type + switch (ChannelProto::getPktType(*reqDataPktHdr)) + { + case ChannelProto::ReqDataCarrierPacketType: + + DbgTrace(2, "SChannel::connectionThread- Processing Request Data Packet, Obj = %08X\n", pSChannel); + + // Allocate a buffer big enough to receive the payload + pRecvBuff = new char[payloadLength]; + if (pRecvBuff != NULL) + { + // Buffer allocated, receive the Req payload. + while (1) + { + bytesReceived = recv(pSChannel->m_socket, + pRecvBuff, + payloadLength, + MSG_WAITALL); + if (bytesReceived != SOCKET_ERROR + || errno != EINTR) + { + break; + } + } + if (bytesReceived != SOCKET_ERROR) + { + // Verify that we received all of the payload + if (bytesReceived == payloadLength) + { + // Received all of the payload data + totalPayloadBytesReceived += bytesReceived; + + // Instantiate ServerReq object + bool reqProcessingStartedSuccessfully = false; + + try { + pServerReq = new ServerReq(pSChannel, + reqId, + pRecvBuff, + bytesReceived); + } + catch (...) { + DbgTrace(0, "SChannel::connectionThread- Exception caught creating ServerReq obj\n", 0); + } + + // Acquire exclusive access to the SChannel object + pthread_mutex_lock(&pSChannel->m_mutex); + + if (pServerReq) + { + // Forget about the receive buffer + pRecvBuff = NULL; + + // Start processing the Request + if (ServiceRequest(pServerReq) != 0) + { + // Failed to start processing of the Request, delete the ServerReq object. + DbgTrace(0, "SChannel::connectionThread- StartRequest failed, Obj = %08X\n", pSChannel); + delete pServerReq; + } + else + { + reqProcessingStartedSuccessfully = true; + } + } + else + { + //DbgTrace(1, "SChannel::connectionThread- Failed to obtain idle ServerReq, Obj = %08X\n", pSChannel); + DbgTrace(0, "SChannel::connectionThread- Failed to obtain idle ServerReq, Obj = %08X\n", pSChannel); + } + + // Check if we must send an Request Error packet back to the client + if (reqProcessingStartedSuccessfully == false) + { + // Build ReqErrorHeader + if (ChannelProto::buildReqErrorPktHdr(reqId, + 0, + reqErrorPktHdr) == 0) + { + // Packet header was built, now sent it to the client. + bytesSent = send(pSChannel->m_socket, + reqErrorPktHdr, + sizeof(reqErrorPktHdr), + MSG_NOSIGNAL); + if (bytesSent != sizeof(reqErrorPktHdr)) + { + DbgTrace(1, "SChannel::connectionThread- Connection aborted prematurely, Obj = %08X\n", pSChannel); + //printf("SChannel::connectionThread- 1Connection aborted prematurely, Obj = %08X\n", pSChannel); + doneReceivingData = true; + } + } + else + { + DbgTrace(0, "SChannel::connectionThread- Error building Req End Pkt Header, Obj = %08X\n", pSChannel); + } + } + + // Release exclusive access to the SChannel object + pthread_mutex_unlock(&pSChannel->m_mutex); + } + else + { + DbgTrace(1, "SChannel::connectionThread- Connection aborted prematurely, Obj = %08X\n", pSChannel); + //printf("bytesReceived = %d, payloadLength = %d\n", bytesReceived, payloadLength); + //printf("SChannel::connectionThread- 2Connection aborted prematurely, Obj = %08X\n", pSChannel); + doneReceivingData = true; + } + } + else + { + DbgTrace(1, "SChannel::connectionThread- Connection aborted prematurely, Obj = %08X\n", pSChannel); + //printf("Socket error = %d\n", errno); + //printf("SChannel::connectionThread- 3Connection aborted prematurely, Obj = %08X\n", pSChannel); + doneReceivingData = true; + } + + // Free receive buffer if necessary + if (pRecvBuff) + delete[] pRecvBuff; + } + else + { + DbgTrace(0, "SChannel::connectionThread- Unable to allocate receive buffer, Obj = %08X\n", pSChannel); + doneReceivingData = true; + } + break; + + default: + + DbgTrace(0, "SChannel::connectionThread- Unknown Packet Type, Obj = %08X\n", pSChannel); + doneReceivingData = true; + break; + } + } + else + { + DbgTrace(1, "SChannel::connectionThread- Unable to obtain payload length, Obj = %08X\n", pSChannel); + doneReceivingData = true; + } + } + else + { + DbgTrace(1, "SChannel::connectionThread- The channel connection was terminated, Obj = %08X\n", pSChannel); + //printf("bytesReceived = %d, expected = %d\n", bytesReceived, ReqDataPktHdrTemplate.length()); + //printf("SChannel::connectionThread- 4The channel connection was terminated, Obj = %08X\n", pSChannel); + doneReceivingData = true; + } + } + else + { + DbgTrace(1, "SChannel::connectionThread- The channel connection was aborted, Obj = %08X\n", pSChannel); + //printf("Socket error = %d\n", errno); + //printf("SChannel::connectionThread- 5The channel connection was aborted, Obj = %08X\n", pSChannel); + doneReceivingData = true; + } + } + } + + // Acquire exclusive access to the SChannel object + pthread_mutex_lock(&pSChannel->m_mutex); + + // Try to change the SChannel state to disconnected + if (pSChannel->m_state == State_Connected) + pSChannel->m_state = State_Disconnected; + + // Release exclusive access to the SChannel object + pthread_mutex_unlock(&pSChannel->m_mutex); + + // Remove ourselves from the SChannel list + RemoveFromSChannelList(pSChannel); + + // Free SmartSChannel + delete pSmartSChannel; + + DbgTrace(1, "SChannel::connectionThread- End\n", 0); + + // Exit + pthread_exit(NULL); + + return 0; // never-reached! + +} /*-- SChannel::connectionThread() --*/ + + +//++======================================================================= +void +SChannel::closeChannel(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + + DbgTrace(1, "SChannel::closeChannel- Start, Obj = %08X\n", this); + + // Acquire SChannel mutex + pthread_mutex_lock(&m_mutex); + + // Switch the socket state to closed + m_state = State_Closed; + + // Check if we must close the socket + if (m_socket != INVALID_SOCKET) + { + // Socket needs to be closed, this will + // release the channel connection thread + // if it is active. + shutdown(m_socket, SHUT_RDWR); + struct linger linger_opt = {1, 15}; + setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)); + closesocket(m_socket); + m_socket = INVALID_SOCKET; + } + + // Release SChannel mutex + pthread_mutex_unlock(&m_mutex); + + DbgTrace(1, "SChannel::closeChannel- End\n", 0); + +} /*-- SChannel::closeChannel() --*/ + + +//++======================================================================= +int +SChannel::sendReplyData( + uint32_t reqId, + char *pServerData, + int32_t serverDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + char reqDataPktHdr[ReqDataPktHdrTemplate.length()]; + struct msghdr sendmsgHdr = {0}; + struct iovec ioVectors[2]; + unsigned long bytesSent; + + DbgTrace(1, "SChannel::sendReplyData- Start, Obj = %08X\n", this); + + // Acquire exclusive access to the channel object + pthread_mutex_lock(&m_mutex); + + // Verify that the channel is connected + if (m_state == State_Connected) + { + // Build ReqDataHeader + if (ChannelProto::buildReqDataPktHdr(reqId, + serverDataLen, + reqDataPktHdr) == 0) + { + // Packet header was built, now sent it along with the client data to + // the server. + ioVectors[0].iov_base = reqDataPktHdr; + ioVectors[0].iov_len = sizeof(reqDataPktHdr); + ioVectors[1].iov_base = pServerData; + ioVectors[1].iov_len = serverDataLen; + sendmsgHdr.msg_iov = ioVectors; + sendmsgHdr.msg_iovlen = 2; + while (1) + { + bytesSent = sendmsg(m_socket, + &sendmsgHdr, + MSG_NOSIGNAL); + if (bytesSent != SOCKET_ERROR + || errno != EINTR) + { + break; + } + } + if (bytesSent != (sizeof(reqDataPktHdr) + serverDataLen)) + { + // The send was unsuccessful, assume there was a communication + // failure. Close the socket to make sure that the connectionThread + // cleans up. + m_state = State_Disconnected; + shutdown(m_socket, SHUT_RDWR); + struct linger linger_opt = {1, 15}; + setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)); + closesocket(m_socket); + m_socket = INVALID_SOCKET; + } + + // Return success even if the send failed to allow things to be cleaned up + // by the connectionThread routine. + retStatus = 0; + } + else + { + DbgTrace(0, "SChannel::sendReplyData- Error building Req Data Pkt Header, Obj = %08X\n", this); + } + } + else + { + DbgTrace(1, "SChannel::sendReplyData- Channel not connected, state = %08X\n", m_state); + } + + // Release exclusive access to the channel object + pthread_mutex_unlock(&m_mutex); + + DbgTrace(1, "SChannel::sendReplyData- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- SChannel::sendData() --*/ + + +//++======================================================================= +int +SChannel::sendReplyError( + uint32_t reqId) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + int retStatus = -1; + char reqErrorPktHdr[ReqErrorPktHdrTemplate.length()]; + + struct msghdr sendmsgHdr = {0}; + struct iovec ioVectors[2]; + unsigned long bytesSent; + + DbgTrace(1, "SChannel::sendReplyError- Start, Obj = %08X\n", this); + + // Acquire exclusive access to the channel object + pthread_mutex_lock(&m_mutex); + + // Verify that the channel is connected + if (m_state == State_Connected) + { + // Build ReqErrorHeader + if (ChannelProto::buildReqErrorPktHdr(reqId, + 0, + reqErrorPktHdr) == 0) + { + // Packet header was built, now sent it to the client. + while (1) + { + bytesSent = send(m_socket, + reqErrorPktHdr, + sizeof(reqErrorPktHdr), + MSG_NOSIGNAL); + if (bytesSent != SOCKET_ERROR + || errno != EINTR) + { + break; + } + } + if (bytesSent != sizeof(reqErrorPktHdr)) + { + // The send was unsuccessful, assume there was a communication + // failure. Close the socket to make sure that the connectionThread + // cleans up. + m_state = State_Disconnected; + shutdown(m_socket, SHUT_RDWR); + struct linger linger_opt = {1, 15}; + setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)); + closesocket(m_socket); + m_socket = INVALID_SOCKET; + } + + // Return success even if the send failed to allow things to be cleaned up + // by the connectionThread routine. + retStatus = 0; + } + else + { + DbgTrace(0, "SChannel::sendReplyError- Error building Req Error Pkt Header, Obj = %08X\n", this); + } + } + else + { + DbgTrace(1, "SChannel::sendReplyError- Channel not connected, state = %08X\n", m_state); + } + + // Release exclusive access to the channel object + pthread_mutex_unlock(&m_mutex); + + DbgTrace(1, "SChannel::sendReplyError- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- SChannel::sendData() --*/ + + +//========================================================================= +//========================================================================= + + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/schannel.h b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/schannel.h new file mode 100644 index 00000000..963256d4 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/schannel.h @@ -0,0 +1,178 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _SCHANNEL_ +#define _SCHANNEL_ + +//===[ Include files ]===================================================== + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Type definitions ]================================================== + +// Forward reference +class ServerReq; + +// +// SChannel Class Definition +// +class SChannel : public ObjRef +{ + // Object State + enum ChannelStates + { + State_FailedInitialization = 1, + State_Connected, + State_Disconnected, + State_Closed + }; + ChannelStates m_state; + + // Connection socket + int m_socket; + + // Synchronization variables + pthread_mutex_t m_mutex; + + // + // 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. + // + typedef map RSMap; + typedef RSMap::iterator RSMapIter; + typedef pair RSIterBoolPair; + RSMap m_rsMap; + + // + // Service connection thread procedure + // + // Parameters: + // pSmartSChannel (input) - + // Pointer to SmartPtr object. + // + // Abstract: Thread in charge of servicing channel connection. + // + // Returns: Nothing. + // + static void* connectionThread(SmartPtr *pSmartSChannel); + +public: + + // + // Constructor + // + // Parameters: + // connSocket (input) - + // Socket for channel connection. + // + // Abstract: Constructs SChannel object. + // + // Returns: Nothing. + // + SChannel(int connSocket); + + // + // Destructor + ~SChannel(void); + + // + // Initialization routine + // + // Parameters: None. + // + // Abstract: Initializes SChannel object. + // + // Returns: 0 if successful. + // + int init(void); + + // + // Close channel routine + // + // Parameters: None. + // + // Abstract: Closes the channel. + // + // Returns: Nothing. + // + void closeChannel(void); + + // + // Send Reply Data routine + // + // Parameters: + // reqId (input) - + // Request Id. + // + // pServerData (input) - + // Pointer to server data that must be sent to + // the client. Buffer is NOT released by the + // procedure. + // + // serverDataLen (input) - + // Length of the server data. + // + // Abstract: Sends data to the client for active Request. + // + // Returns: 0 if successful. + // + int sendReplyData(uint32_t reqId, + char *pServerData, + int32_t serverDataLen); + + // + // Send Reply Error routine + // + // Parameters: + // reqId (input) - + // Request Id. + // + // Abstract: Indicates to the client that the request was + // not processed successfully.. + // + // Returns: 0 if successful. + // + int sendReplyError(uint32_t reqId); +}; +typedef SmartPtr SmartSChannel; + + +//===[ Function prototypes ]=============================================== + + +#endif // _SCHANNEL_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/server.cpp b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/server.cpp new file mode 100644 index 00000000..395492e7 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/server.cpp @@ -0,0 +1,1353 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ 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 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 RSMap; +typedef RSMap::iterator RSMapIter; +typedef pair 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 pendingServerReqList; +int numPendingRequests = 0; + +// ServerThreads operating parameters +list waitingServerThreadList; +int waitingServerThreads = 0; + + +//++======================================================================= +int +ServiceRequest( + ServerReq *pServerReq) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + 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::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: +// +// L0 +//=======================================================================-- +{ + 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::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: +// +// L0 +//=======================================================================-- +{ + DbgTrace(1, "AwakenSuspendedServerThreads- Start\n", 0); + + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Awaken all of the ServerThreads in the waitingServerThreadsList + while (waitingServerThreads) + { + list::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::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::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: +// +// L0 +//=======================================================================-- +{ + 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. +// +// L0 +//=======================================================================-- +{ + 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 *pServerThread = new 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::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 pending 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(pServerThread); + waitingServerThreads ++; + pServerThread->suspend(&serverMutex); + } + } + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + + // Free ServerThread object + delete pServerThread; + } + 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. +// +// L0 +//=======================================================================-- +{ + 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. +// +// L0 +//=======================================================================-- +{ + 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: +// +// L0 +//=======================================================================-- +{ + 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. +// +// L0 +//=======================================================================-- +{ + 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. +// +// L0 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "IpcServerSetUnAddress- Start\n", 0); + + // Verify the input parameters + if (pSocketFileName == NULL + || strlen(pSocketFileName) >= sizeof(pSocketFileName)) + { + 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. +// +// L0 +//=======================================================================-- +{ + 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. +// +// L0 +//=======================================================================-- +{ + 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: +// +// L0 +//=======================================================================-- +{ + 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() --*/ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverreq.cpp b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverreq.cpp new file mode 100644 index 00000000..b99c91e1 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverreq.cpp @@ -0,0 +1,222 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "ipcint.h" +#include "schannel.h" +#include "serverreq.h" +#include // Ensure that NDEBUG is defined for release builds! + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +#define SERVER_REQ_SIGNATURE 0x52525653 // SVRR + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// +// Object Counters +// +unsigned long numServerReqObjects = 0; + + +//++======================================================================= +ServerReq::ServerReq( + SChannel *pSChannel, + uint32_t reqId, + char *pClientData, + int32_t clientDataLength) : + + m_signature (SERVER_REQ_SIGNATURE), + m_reqId (reqId), + m_pClientData (pClientData), + m_clientDataLength (clientDataLength) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ServerReq::ServerReq- Start, Obj = %08X\n", this); + + // Create a SmartSChannel object to keep the SChannel object from + // going away while we process the request. + m_pSmartSChannel = new SmartSChannel(pSChannel); + + // Increment the object count + InterlockedIncrement(&numServerReqObjects); + + DbgTrace(1, "ServerReq::ServerReq- End\n", 0); + +} /*-- ServerReq::ServerReq() --*/ + + +//++======================================================================= +ServerReq::~ServerReq(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ServerReq::~ServerReq- Start, Obj = %08X\n", this); + + // Free any client data that may be hanging around + if (m_pClientData) + free(m_pClientData); + + // Decrement the object count + InterlockedDecrement(&numServerReqObjects); + + DbgTrace(1, "ServerReq::~ServerReq- End\n", 0); + +} /*-- ServerReq::~ServerReq() --*/ + + +//++======================================================================= +int +ServerReq::getReqData( + char **ppClientData) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ServerReq::getReqData- Start, Obj = %08X\n", this); + +#if DEBUG + assert(m_signature == SERVER_REQ_SIGNATURE); +#endif + + // Return pointer to the client data + *ppClientData = m_pClientData; + + DbgTrace(1, "ServerReq::getReqData- End, reqDataLen = %08X\n", m_clientDataLength); + + return m_clientDataLength; +} + + +//++======================================================================= +void +ServerReq::complete( + char *pServerData) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + SChannel *pSChannel = *m_pSmartSChannel; + + DbgTrace(1, "ServerReq::complete- Start, Obj = %08X\n", this); + +#if DEBUG + assert(m_signature == SERVER_REQ_SIGNATURE); +#endif + + // Send data to the client + pSChannel->sendReplyData(m_reqId, + pServerData, + strlen(pServerData)); + + DbgTrace(1, "ServerReq::complete- End\n", 0); + +} /*-- ServerReq::complete() --*/ + + +//++======================================================================= +void +ServerReq::abort(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + SChannel *pSChannel = *m_pSmartSChannel; + + DbgTrace(1, "ServerReq::abort- Start, Obj = %08X\n", this); + +#if DEBUG + assert(m_signature == SERVER_REQ_SIGNATURE); +#endif + + // Send an error to the client + pSChannel->sendReplyError(m_reqId); + + DbgTrace(1, "ServerReq::abort- End\n", 0); + +} /*-- ServerReq::abort() --*/ + + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverreq.h b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverreq.h new file mode 100644 index 00000000..adb1ed5d --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverreq.h @@ -0,0 +1,145 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +#ifndef _SERVERREQ_ +#define _SERVERREQ_ + +//===[ Include files ]===================================================== + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Type definitions ]================================================== + +// +// Server Request Class +// +class ServerReq +{ + // Signature + unsigned long m_signature; + + // Id of request being processed + uint32_t m_reqId; + + // SmartSChannel object pointer for request being processed. + SmartSChannel *m_pSmartSChannel; + + // Request Client Data + char *m_pClientData; + int32_t m_clientDataLength; + +public: + + // + // Destructor + ~ServerReq(void); + + // + // Constructor + // + // Parameters: + // pSChannel (input) - + // Pointer to SChannel object. + // + // reqId (input) - + // Request Id. + // + // pClientData (input) - + // Pointer to buffer containing the client data. + // Buffer is released when the object is destroyed. + // + // clientDataLength (input) - + // Length of the client data. + // + // Abstract: Constructs ServerReq object. + // + // Returns: Nothing. + // + ServerReq(SChannel *pSChannel, + uint32_t reqId, + char *pClientData, + int32_t clientDataLength); + + // + // Get request Data routine + // + // Parameters: + // ppClientData (input/output) - + // Pointer to variable that will receive pointer to + // data sent by the client. Buffer should NOT released by + // caller. + // + // Abstract: Sends the requests reply data to the client. + // + // Returns: The length of the client request data. 0 if not successful. + // + int getReqData(char **ppClientData); + + // + // Complete Request routine + // + // Parameters: + // pServerData (input) - + // Pointer to server data that must be sent to + // the client. Buffer is NOT released by the + // procedure. + // + // Abstract: Completes the request. + // + // Returns: Nothing. + // + void complete(char *pServerData); + + // + // Abort Request routine + // + // Parameters: None. + // + // Abstract: Aborts the request. + // + // Returns: Nothing. + // + void abort(void); +}; + + +//===[ Function prototypes ]=============================================== + + +#endif // _SERVERREQ_ + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverthread.cpp b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverthread.cpp new file mode 100644 index 00000000..7f7367a2 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverthread.cpp @@ -0,0 +1,181 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "ipcint.h" +#include "serverthread.h" +#include // Ensure that NDEBUG is defined for release builds! + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +#define SERVER_THREAD_SIGNATURE 0x54525653 // SVRT + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// +// Object Counters +// +unsigned long numServerThreadObjects = 0; + + +//++======================================================================= +ServerThread::ServerThread(void) : + + m_signature (SERVER_THREAD_SIGNATURE) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ServerThread::ServerThread- Start, Obj = %08X\n", this); + + // Initialize the condition + if (pthread_cond_init(&m_condition, NULL) != 0) + { + DbgTrace(0, "ServerThread::ServerThread- Condition initialization failed\n", 0); + + // Throw exception + throw bad_alloc(); + } + + // Increment the object count + InterlockedIncrement(&numServerThreadObjects); + + DbgTrace(1, "ServerThread::ServerThread- End\n", 0); + +} /*-- ServerThread::ServerThread() --*/ + + +//++======================================================================= +ServerThread::~ServerThread(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ServerThread::~ServerThread- Start, Obj = %08X\n", this); + + // Cleanup resources allocated for the object + pthread_cond_destroy(&m_condition); + + // Decrement the object count + InterlockedDecrement(&numServerThreadObjects); + + DbgTrace(1, "ServerThread::~ServerThread- End\n", 0); + +} /*-- ServerThread::~ServerThread() --*/ + + +//++======================================================================= +void +ServerThread::awaken(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ServerThread::awaken- Start, Obj = %08X\n", this); + +#if DEBUG + assert(m_signature == SERVER_THREAD_SIGNATURE); +#endif + + // Signal ourselves to wake up + pthread_cond_signal(&m_condition); + + DbgTrace(1, "ServerThread::awaken- End\n", 0); + +} /*-- ServerThread::awaken() --*/ + + +//++======================================================================= +void +ServerThread::suspend( + pthread_mutex_t *pMutex) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ServerThread::suspend- Start, Obj = %08X\n", this); + +#if DEBUG + assert(m_signature == SERVER_THREAD_SIGNATURE); +#endif + + // Wait until signaled to awaken + pthread_cond_wait(&m_condition, pMutex); + + DbgTrace(1, "ServerThread::suspend- End\n", 0); + +} /*-- ServerThread::suspend() --*/ + + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverthread.h b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverthread.h new file mode 100644 index 00000000..74d7f8dc --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/serverthread.h @@ -0,0 +1,107 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +#ifndef _SERVERTHREAD_ +#define _SERVERTHREAD_ + +//===[ Include files ]===================================================== + +//===[ External data ]===================================================== + +//===[ External prototypes ]=============================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Type definitions ]================================================== + +// +// Server Thread Class +// +class ServerThread +{ + // Signature + unsigned long m_signature; + + // Synchronization variable + pthread_cond_t m_condition; + +public: + + // + // Destructor + ~ServerThread(void); + + // + // Constructor + // + // Parameters: None. + // + // Abstract: Constructs ServerThread object. + // + // Returns: Nothing. + // + ServerThread(void); + + // + // Awaken ServerThread routine + // + // Parameters: None. + // + // Abstract: Awakens a ServerThread. + // + // Returns: Nothing. + // + void awaken(void); + + // + // Suspend ServerThread routine + // + // Parameters: + // pMutex (input) - + // Pointer to mutex to associate with + // condition used for waiting.. + // + // Abstract: Suspends a ServerThread. + // + // Returns: Nothing. + // + void suspend(pthread_mutex_t *pMutex); +}; + + +//===[ Function prototypes ]=============================================== + + +#endif // _SERVERTHREAD_ + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/test/makeServer.sh b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/test/makeServer.sh new file mode 100755 index 00000000..2b565cd5 --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/test/makeServer.sh @@ -0,0 +1,3 @@ +#!/bin/bash +gcc -o TestServer testServer.c -g -I../../../../../include -L../../../../../lib/Release -lpthread -lcasa_s_ipc -Xlinker -rpath -Xlinker ../../../../../lib/Release + diff --git a/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/test/testServer.c b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/test/testServer.c new file mode 100644 index 00000000..f8b1241e --- /dev/null +++ b/CASA-auth-token/non-java/utilities/IpcLibs/linux/server/test/testServer.c @@ -0,0 +1,311 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "casa_s_ipc.h" + +//===[ Type definitions ]================================================== + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0) \ + printf(X, Y); \ + else if (DebugLevel >= LEVEL) \ + printf(X, Y); \ +} + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Usage string +char usage[] = "\nTest: usage: -l lifetime [-D DebugLevel]\n"; + +int DebugLevel = 3; + +// Test lifetime +int testLifetime = 60; // Seconds + +bool processingRequests = true; + + +//++======================================================================= +void* UnInitThread() +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +//=======================================================================-- +{ + DbgTrace(1, "UnInitThread- Start\n", 0); + + // Sleep for the configured amount + sleep(testLifetime); + + // Stop processing Rpc Requests + processingRequests = false; + + // Un-init the Svc Rpc Service Subsystem + IpcServerShutdown(); + + DbgTrace(1, "UnInitThread- End\n", 0); + + // Exit + pthread_exit(NULL); + + return 0; // never-reached! +} + + +//++======================================================================= +void* ProcessRequestThread(int32_t requestId) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +//=======================================================================-- +{ + char *pReqData = NULL; + + DbgTrace(1, "ProcessRequestThread- Start\n", 0); + + // Get the rpc data + int dataLen = IpcServerGetRequestData(requestId, &pReqData); + if (dataLen != 0) + { + // Just echo the data back as the reply + IpcServerCompleteRequest(requestId,pReqData); + } + else + { + DbgTrace(0, "ProcessRequestThread- Error obtaining Request data\n", 0); + IpcServerAbortRequest(requestId); + } + + DbgTrace(1, "ProcessRequestThread- End\n", 0); + + // Exit + pthread_exit(NULL); + + return 0; // never-reached! +} + + +//++======================================================================= +void +ExecuteTests(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +//=======================================================================-- +{ + pthread_t thread; + int threadCreateStatus; + + DbgTrace(1, "ExecuteTests- Start\n", 0); + + // Initialize the Svc Ipc Subsystem + if (IpcServerInit("TestServer", + 3, + false) == 0) + { + // Set the server listen address + if (IpcServerSetInAddress(5000) == 0) + { + // Now start servicing requests. + if (IpcServerStart() == 0) + { + // The Ipc subsystem was started, now create a thread for + // un-initializing the Ipc subsystem after a while. + threadCreateStatus = pthread_create(&thread, + NULL, + (void*(*)(void*))UnInitThread, + (void*)NULL); + if (threadCreateStatus != 0) + { + DbgTrace(0, "ExecuteTests- Unable to create un-initialization thread, error = %08X\n", threadCreateStatus); + IpcServerShutdown(); + } + else + { + // Process Incoming Requests + while (processingRequests) + { + int32_t requestId = IpcServerGetRequest(); + if (requestId != 0) + { + // Create a thread to handle the request + threadCreateStatus = pthread_create(&thread, + NULL, + (void*(*)(void*))ProcessRequestThread, + (void*)requestId); + if (threadCreateStatus != 0) + { + DbgTrace(0, "ExecuteTests- Unable to create process request thread, error = %08X\n", threadCreateStatus); + IpcServerAbortRequest(requestId); + } + } + else + { + // No need to service requests any longer + break; + } + } + } + } + else + { + DbgTrace(0, "ExecuteTests- Error starting the Ipc subsystem\n", 0); + IpcServerShutdown(); + } + } + else + { + DbgTrace(0, "ExecuteTests- Error setting server address\n", 0); + IpcServerShutdown(); + } + } + else + { + DbgTrace(0, "ExecuteTests- Ipc subsystem initialization failed\n", 0); + } + + DbgTrace(1, "ExecuteTests- End\n", 0); +} + + +//++======================================================================= +int +main( + int argc, + char* argv[]) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int optionsSpecified = 0; + bool doneScanning = false; + bool invalidOption = false; + int option; + + printf("**** Ipc Server test ****\n"); + + // Scan through the options specified + while (!doneScanning) + { + opterr = 0; + option = getopt(argc, argv, "l:D:"); + + // Proceed based on the result + switch (option) + { + case 'D': + // Set the debug level + printf("DebugLevel = %s\n", optarg); + DebugLevel = atoi(optarg); + optionsSpecified++; + break; + + case 'l': + // Set the test lifetime + printf("Lifetime = %s\n", optarg); + testLifetime = 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) + { + ExecuteTests(); + } + else + { + // Invalid option detected + printf(usage, argv[0]); + } + + return 0; + +} /*-- main() --*/ + diff --git a/CASA-auth-token/non-java/utilities/Makefile.am b/CASA-auth-token/non-java/utilities/Makefile.am new file mode 100644 index 00000000..4430276e --- /dev/null +++ b/CASA-auth-token/non-java/utilities/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = IpcLibs + +DIST_SUBDIRS = IpcLibs + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in +