• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

E:/PROJECTS/cvsed/mixed/VIRTUA~1/rpcdispatch/pipesrv.h

Go to the documentation of this file.
00001 
00007 #pragma once
00008 #include "../rpcdispatch/rpcdisp.h"
00009 #include <bzscmn/bzscmn.h>
00010 
00012 template <bool _MessageOriented, bool _AutoReconnect, bool _FailTransferOnListening = false> class PipeServer
00013 {
00014 private:
00015         HANDLE m_hPipe;
00016         HANDLE m_hNextInstance;
00017         BazisLib::String m_PipeName;
00018         bool m_bReconnectPending;
00019         bool m_bClientConnected;
00020         unsigned m_Timeout;
00021         unsigned m_LastError;
00022 
00023         OVERLAPPED m_Overlapped;
00024         HANDLE m_hEvt;
00025 
00026 private:
00027         HANDLE CreatePipeInstance()
00028         {
00029                 return CreateNamedPipe(m_PipeName.c_str(),
00030                                                                   PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
00031                                                                   _MessageOriented ? (PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE) : (PIPE_TYPE_BYTE | PIPE_READMODE_BYTE),
00032                                                                   2,
00033                                                                   131072,
00034                                                                   131072,
00035                                                                   m_Timeout,
00036                                                                   NULL);
00037         }
00038 
00039 private:
00040         template<bool out> size_t TransferWithTimeout(void *pData, size_t size)
00041         {
00042                 DWORD dwOk = 0;
00043                 if (out)
00044                         WriteFile(m_hPipe, pData, (DWORD)size, &dwOk, &m_Overlapped);
00045                 else
00046                         ReadFile(m_hPipe, pData, (DWORD)size, &dwOk, &m_Overlapped);
00047                 m_LastError = GetLastError();
00048                 if (dwOk)
00049                         return dwOk;
00050                 switch (m_LastError)
00051                 {
00052                 case ERROR_PIPE_LISTENING:
00053                         m_bClientConnected = false;
00054                         return 0;
00055                 case ERROR_IO_PENDING:
00056                         m_bClientConnected = true;
00057                         break;
00058                 default:
00059                         return 0;
00060                 }
00061                 if (WaitForSingleObject(m_hEvt, m_Timeout) == WAIT_OBJECT_0)
00062                 {
00063                         GetOverlappedResult(m_hPipe, &m_Overlapped, &dwOk, TRUE);
00064                         return dwOk;
00065                 }
00066                 CancelIo(m_hPipe);
00067                 GetOverlappedResult(m_hPipe, &m_Overlapped, &dwOk, TRUE);
00068                 return dwOk;
00069         }
00070 
00071 public:
00072 
00073         unsigned GetLastOperationError()
00074         {
00075                 return m_LastError;
00076         }
00077 
00078         bool ReconnectPipe()
00079         {
00080                 if (m_hPipe != INVALID_HANDLE_VALUE)
00081                         CloseHandle(m_hPipe);
00082                 if (m_hNextInstance == INVALID_HANDLE_VALUE)
00083                         m_hNextInstance = CreatePipeInstance();
00084 
00085                 m_hPipe = m_hNextInstance;
00086                 m_hNextInstance = CreatePipeInstance();
00087                 m_bClientConnected = false;
00088 
00089                 m_bReconnectPending = false;
00090                 if ((m_hPipe != INVALID_HANDLE_VALUE) && (m_hNextInstance != INVALID_HANDLE_VALUE))
00091                         return true;
00092                 else
00093                         return false;
00094         }
00095 
00096         ~PipeServer()
00097         {
00098                 if (m_hPipe != INVALID_HANDLE_VALUE)
00099                         CloseHandle(m_hPipe);
00100                 if (m_hNextInstance != INVALID_HANDLE_VALUE)
00101                         CloseHandle(m_hNextInstance);
00102                 if (m_hEvt != INVALID_HANDLE_VALUE)
00103                         CloseHandle(m_hEvt);
00104         }
00105 
00106         PipeServer(const TCHAR *pszPipeName, unsigned Timeout = 1000)
00107                 : m_PipeName(pszPipeName)
00108                 , m_hPipe(INVALID_HANDLE_VALUE)
00109                 , m_hNextInstance(INVALID_HANDLE_VALUE)
00110                 , m_bReconnectPending(false)
00111                 , m_Timeout(Timeout)
00112                 , m_bClientConnected(false)
00113                 , m_LastError(0)
00114         {
00115                 m_hEvt = CreateEvent(NULL, TRUE, FALSE, NULL);
00116                 memset(&m_Overlapped, 0, sizeof(m_Overlapped));
00117                 m_Overlapped.hEvent = m_hEvt;
00118                 ReconnectPipe();
00119         }
00120 
00121         size_t Send(const void *pData, size_t Size)
00122         {
00123                 SIZE_T dwOk;
00124                 while (!(dwOk = TransferWithTimeout<true>((void *)pData, Size)))
00125                 {
00126                         switch(m_LastError)
00127                         {
00128                         case ERROR_PIPE_LISTENING:
00129                                 if (_FailTransferOnListening)
00130                                         return false;
00131                                 if (!ConnectNamedPipe(m_hPipe, NULL))
00132                                         return false;
00133                                 continue;
00134                                 break;
00135                         case ERROR_BROKEN_PIPE:
00136                                 m_bReconnectPending = true;
00137                                 break;
00138                         }
00139                         return false;
00140                 }
00141                 return dwOk;
00142         }
00143 
00144         size_t Receive(void *pData, size_t Size, bool PartialRecvAllowed = true)
00145         {
00146                 size_t offset = 0;
00147                 for (;;)
00148                 {
00149                         SIZE_T dwOk = 0;
00150                         dwOk = TransferWithTimeout<false>(((char *)pData) + offset, Size - offset);
00151                         if (dwOk)
00152                         {
00153                                 if (PartialRecvAllowed)
00154                                         return dwOk;
00155                                 else
00156                                 {
00157                                         offset += dwOk;
00158                                         if (offset == Size)
00159                                                 return Size;
00160                                         else
00161                                                 continue;
00162                                 }
00163                         }
00164                         else
00165                         {
00166                                 switch(m_LastError)
00167                                 {
00168                                 case ERROR_PIPE_LISTENING:
00169                                         if (_FailTransferOnListening)
00170                                                 return 0;
00171                                         if (!ConnectNamedPipe(m_hPipe, NULL))
00172                                                 return 0;
00173                                         continue;
00174                                         break;
00175                                 case ERROR_BROKEN_PIPE:
00176                                         m_bReconnectPending = true;
00177                                         if (_AutoReconnect)
00178                                         {
00179                                                 ReconnectPipe();
00180                                                 continue;
00181                                         }
00182                                         break;
00183                                 }
00184                                 return 0;
00185                         }
00186                 }
00187         }
00188 
00189         bool HasDataInBuffer()
00190         {
00191                 DWORD dataAvailable = 0;
00192                 for (;;)
00193                 {
00194                         if (!PeekNamedPipe(m_hPipe, NULL, 0, NULL, &dataAvailable, NULL))
00195                         {
00196                                 m_LastError = GetLastError();
00197                                 switch(m_LastError)
00198                                 {
00199                                 case ERROR_BROKEN_PIPE:
00200                                         m_bClientConnected = false;
00201                                         m_bReconnectPending = true;
00202                                         if (_AutoReconnect)
00203                                         {
00204                                                 ReconnectPipe();
00205                                                 continue;
00206                                         }
00207                                         break;
00208                                 case ERROR_PIPE_LISTENING:
00209                                         m_bClientConnected = false;
00210                                         break;
00211                                 }
00212                                 return false;
00213                         }
00214                         m_bClientConnected = true;
00215                         return (dataAvailable != 0);
00216                 }
00217         }
00218 
00219         bool IsClientConnected()
00220         {
00221                 return m_bClientConnected;
00222         }
00223 
00224         void DiscardBufferedData()
00225         {
00226                 DWORD dataAvailable = 0;
00227                 for (;;)
00228                 {
00229                         if (!PeekNamedPipe(m_hPipe, NULL, 0, NULL, &dataAvailable, NULL))
00230                         {
00231                                 m_LastError = GetLastError();
00232                                 if (m_LastError == ERROR_BROKEN_PIPE)
00233                                 {
00234                                         m_bReconnectPending = true;
00235                                         if (_AutoReconnect)
00236                                         {
00237                                                 ReconnectPipe();
00238                                                 continue;
00239                                         }
00240                                 }
00241                                 return;
00242                         }
00243                         char *pTemp = new char[dataAvailable];
00244                         Receive(pTemp, dataAvailable, false);
00245                         delete pTemp;
00246                         return;
00247                 }
00248         }
00249 
00250         bool ReconnectPending()
00251         {
00252                 return m_bReconnectPending;
00253         }
00254 };
00255