Created Linux IPC libraries to be used by the AuthToken components.
At this point there is still work to do on them.
This commit is contained in:
		@@ -0,0 +1,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() --*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//=========================================================================
 | 
			
		||||
//=========================================================================
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user