Created Linux IPC libraries to be used by the AuthToken components.
At this point there is still work to do on them.
This commit is contained in:
		| @@ -0,0 +1,122 @@ | ||||
| ####################################################################### | ||||
| # | ||||
| #  Copyright (C) 2006 Novell, Inc. | ||||
| # | ||||
| #  This program is free software; you can redistribute it and/or | ||||
| #  modify it under the terms of the GNU General Public | ||||
| #  License as published by the Free Software Foundation; either | ||||
| #  version 2 of the License, or (at your option) any later version. | ||||
| # | ||||
| #  This program is distributed in the hope that it will be useful, | ||||
| #  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
| #  General Public License for more details. | ||||
| # | ||||
| #  You should have received a copy of the GNU General Public | ||||
| #  License along with this program; if not, write to the Free | ||||
| #  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| # | ||||
| #  Author: Juan Carlos Luciani <jluciani@novell.com> | ||||
| # | ||||
| ####################################################################### | ||||
|  | ||||
| if DEBUG | ||||
| TARGET_CFG = Debug | ||||
| CFLAGS += -v -w | ||||
| 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 | ||||
|  | ||||
							
								
								
									
										1081
									
								
								CASA-auth-token/non-java/utilities/IpcLibs/linux/client/cchannel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1081
									
								
								CASA-auth-token/non-java/utilities/IpcLibs/linux/client/cchannel.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| #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<uint32_t, ClientReq*> RCMap; | ||||
|    typedef RCMap::iterator RCMapIter; | ||||
|    typedef pair<RCMapIter, bool> RCIterBoolPair; | ||||
|    RCMap                m_rcMap; | ||||
|  | ||||
|    // | ||||
|    // Service connection thread procedure | ||||
|    // | ||||
|    // Parameters: | ||||
|    //    pSmartCChannel (input) - | ||||
|    //       Pointer to SmartPtr<CChannel> object. | ||||
|    // | ||||
|    // Abstract: Thread in charge of servicing channel connection. | ||||
|    // | ||||
|    // Returns: Nothing. | ||||
|    // | ||||
|    static void* connectionThread(SmartPtr<CChannel> *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<CChannel> SmartCChannel; | ||||
|  | ||||
|  | ||||
| //===[ Function prototypes ]=============================================== | ||||
|  | ||||
|  | ||||
| #endif // _CCHANNEL_ | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
|  | ||||
| //===[ 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<SmartCChannelPointer> 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; | ||||
| } | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
|  | ||||
| //===[ 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() --*/ | ||||
|  | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
|  | ||||
| #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_ | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
|  | ||||
| @@ -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 | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| //===[ Include files ]===================================================== | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdbool.h> | ||||
| #include <getopt.h> | ||||
| #include <errno.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netdb.h> | ||||
| #include <pthread.h> | ||||
| #include <unistd.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #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() --*/ | ||||
|  | ||||
		Reference in New Issue
	
	Block a user