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:
		
							
								
								
									
										37
									
								
								CASA-auth-token/non-java/utilities/IpcLibs/linux/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								CASA-auth-token/non-java/utilities/IpcLibs/linux/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <jluciani@novell.com> | ||||
| # | ||||
| ####################################################################### | ||||
|  | ||||
| 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 | ||||
|  | ||||
| @@ -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() --*/ | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
| # | ||||
| ####################################################################### | ||||
|  | ||||
| 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 | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
|  | ||||
| //===[ 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() --*/ | ||||
|  | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
|  | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| #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_ | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
							
								
								
									
										149
									
								
								CASA-auth-token/non-java/utilities/IpcLibs/linux/common/ipcint.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								CASA-auth-token/non-java/utilities/IpcLibs/linux/common/ipcint.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| #ifndef _IPCINT_ | ||||
| #define _IPCINT_ | ||||
|  | ||||
| //===[ Include files ]===================================================== | ||||
|  | ||||
| #include <iostream> | ||||
| #include <string> | ||||
| #include <list> | ||||
| #include <map> | ||||
| #include <vector> | ||||
| using namespace std; | ||||
|  | ||||
| extern "C" { | ||||
| #include <stdint.h> | ||||
| #include <unistd.h> | ||||
| #include <stdio.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <sys/un.h> | ||||
| #include <netinet/in.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <errno.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <pthread.h> | ||||
| #include <syslog.h> | ||||
| #include <signal.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/file.h> | ||||
| #include <assert.h>     // Ensure that NDEBUG is defined for release builds! | ||||
| #include <sys/ipc.h> | ||||
| } | ||||
|  | ||||
| //===[ 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_ | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| #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 T> | ||||
| class SmartPtr | ||||
| { | ||||
|    //--------------------------------------------------------------------------- | ||||
|    // Public interface | ||||
|    // | ||||
|    public: | ||||
|  | ||||
|    SmartPtr(); | ||||
|    SmartPtr(T* ptr); | ||||
|    SmartPtr(const SmartPtr<T>& ref); | ||||
|  | ||||
|    virtual ~SmartPtr(); | ||||
|  | ||||
|    operator bool (void) const; | ||||
|    bool operator! (void) const; | ||||
|    bool operator== (SmartPtr<T>& ref) const; | ||||
|    bool operator!= (SmartPtr<T>& ref) const; | ||||
|  | ||||
|    SmartPtr<T>& operator= (const SmartPtr<T>& ref); | ||||
|    SmartPtr<T>& 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<class T> | ||||
| inline SmartPtr<T>::SmartPtr() : | ||||
|    m_Ptr(0) | ||||
| { | ||||
| }  // End of SmartPtr::SmartPtr() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline SmartPtr<T>::SmartPtr(T* ptr) : | ||||
|    m_Ptr(0) | ||||
| { | ||||
|    resetPtr(ptr); | ||||
|  | ||||
| }  // End of SmartPtr::SmartPtr() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline SmartPtr<T>::SmartPtr(const SmartPtr<T>& ref) : | ||||
|    m_Ptr(0) | ||||
| { | ||||
|    resetPtr(ref.m_Ptr); | ||||
|  | ||||
| }  // End of SmartPtr::SmartPtr() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline SmartPtr<T>::~SmartPtr() | ||||
| { | ||||
|    deleteObject(); | ||||
|  | ||||
| }  // End of SmartPtr::~SmartPtr() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline SmartPtr<T>::operator bool (void) const | ||||
| { | ||||
|    return m_Ptr != 0; | ||||
|  | ||||
| }  // End of SmartPtr::operator bool() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline bool SmartPtr<T>::operator! (void) const | ||||
| { | ||||
|    return m_Ptr == 0; | ||||
|  | ||||
| }  // End of SmartPtr::operator!() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline bool SmartPtr<T>::operator== (SmartPtr<T>& ref) const | ||||
| { | ||||
|    return m_Ptr == ref.m_Ptr; | ||||
|  | ||||
| }  // End of SmartPtr::operator==() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline bool SmartPtr<T>::operator!= (SmartPtr<T>& ref) const | ||||
| { | ||||
|    return m_Ptr != ref.m_Ptr; | ||||
|  | ||||
| }  // End of SmartPtr::operator==() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline SmartPtr<T>& SmartPtr<T>::operator= (const SmartPtr<T>& ref) | ||||
| { | ||||
|    resetPtr(ref.m_Ptr); | ||||
|    return *this; | ||||
|  | ||||
| }  // End of SmartPtr::operator=() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline SmartPtr<T>& SmartPtr<T>::operator= (T* ptr) | ||||
| { | ||||
|    resetPtr(ptr); | ||||
|    return *this; | ||||
|  | ||||
| }  // End of SmartPtr::operator=() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline T& SmartPtr<T>::operator* (void) const | ||||
| { | ||||
|    return *m_Ptr; | ||||
|  | ||||
| }  // End of SmartPtr::operator*() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline T* SmartPtr<T>::operator-> (void) const | ||||
| { | ||||
|    return m_Ptr; | ||||
|  | ||||
| }  // End of SmartPtr::operator->() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline SmartPtr<T>::operator T* (void) const | ||||
| { | ||||
|    return m_Ptr; | ||||
|  | ||||
| }  // End of SmartPtr::operator T*() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline void SmartPtr<T>::deleteObject(void) | ||||
| { | ||||
|    if (m_Ptr && m_Ptr->DecRefCount()) | ||||
|    { | ||||
|       delete m_Ptr; | ||||
|       m_Ptr = 0; | ||||
|    } | ||||
|  | ||||
| }  // End of SmartPtr::deleteObject() | ||||
|  | ||||
|  | ||||
| template<class T> | ||||
| inline void SmartPtr<T>::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 | ||||
| /******************************************************************************/ | ||||
| /******************************************************************************/ | ||||
|  | ||||
| @@ -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 <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 | ||||
| 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 | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
|  | ||||
| //===[ 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<SChannel> *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() --*/ | ||||
|  | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
|  | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| #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<uint32_t, ServerReq*> RSMap; | ||||
|    typedef RSMap::iterator RSMapIter; | ||||
|    typedef pair<RSMapIter, bool> RSIterBoolPair; | ||||
|    RSMap                m_rsMap; | ||||
|  | ||||
|    // | ||||
|    // Service connection thread procedure | ||||
|    // | ||||
|    // Parameters: | ||||
|    //    pSmartSChannel (input) - | ||||
|    //       Pointer to SmartPtr<SChannel> object. | ||||
|    // | ||||
|    // Abstract: Thread in charge of servicing channel connection. | ||||
|    // | ||||
|    // Returns: Nothing. | ||||
|    // | ||||
|    static void* connectionThread(SmartPtr<SChannel> *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<SChannel> SmartSChannel; | ||||
|  | ||||
|  | ||||
| //===[ Function prototypes ]=============================================== | ||||
|  | ||||
|  | ||||
| #endif // _SCHANNEL_ | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
							
								
								
									
										1353
									
								
								CASA-auth-token/non-java/utilities/IpcLibs/linux/server/server.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1353
									
								
								CASA-auth-token/non-java/utilities/IpcLibs/linux/server/server.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
|  | ||||
| //===[ Include files ]===================================================== | ||||
|  | ||||
| #include "ipcint.h" | ||||
| #include "schannel.h" | ||||
| #include "serverreq.h" | ||||
| #include <assert.h>     // 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() --*/ | ||||
|  | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
|  | ||||
| #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_ | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
|  | ||||
| //===[ Include files ]===================================================== | ||||
|  | ||||
| #include "ipcint.h" | ||||
| #include "serverthread.h" | ||||
| #include <assert.h>     // 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() --*/ | ||||
|  | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
|  | ||||
| @@ -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 <jluciani@novell.com> | ||||
|  * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
|  | ||||
| #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_ | ||||
|  | ||||
| //========================================================================= | ||||
| //========================================================================= | ||||
|  | ||||
| @@ -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 | ||||
|  | ||||
| @@ -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 <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: -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() --*/ | ||||
|  | ||||
		Reference in New Issue
	
	Block a user