356 lines
7.7 KiB
C++
356 lines
7.7 KiB
C++
#include "HGNamedPipe.h"
|
||
#include "HGInc.h"
|
||
#include <string>
|
||
|
||
struct HGNamedPipeOutImpl
|
||
{
|
||
HGNamedPipeOutImpl()
|
||
{
|
||
#if defined(HG_CMP_MSC)
|
||
m_hConnectEvent = NULL;
|
||
m_hWriteEvent = NULL;
|
||
m_hPipe = INVALID_HANDLE_VALUE;
|
||
m_pOverlapped = NULL;
|
||
#else
|
||
m_filePath.empty();
|
||
m_fdPipe = -1;
|
||
#endif
|
||
}
|
||
|
||
~HGNamedPipeOutImpl()
|
||
{
|
||
#if defined(HG_CMP_MSC)
|
||
delete m_pOverlapped;
|
||
m_pOverlapped = NULL;
|
||
CloseHandle(m_hPipe);
|
||
m_hPipe = INVALID_HANDLE_VALUE;
|
||
CloseHandle(m_hWriteEvent);
|
||
m_hWriteEvent = NULL;
|
||
CloseHandle(m_hConnectEvent);
|
||
m_hConnectEvent = NULL;
|
||
#else
|
||
if (-1 != m_fdPipe)
|
||
{
|
||
close(m_fdPipe);
|
||
m_fdPipe = -1;
|
||
}
|
||
unlink(m_filePath.c_str());
|
||
#endif
|
||
}
|
||
|
||
#if defined(HG_CMP_MSC)
|
||
HANDLE m_hConnectEvent;
|
||
HANDLE m_hWriteEvent;
|
||
HANDLE m_hPipe;
|
||
OVERLAPPED *m_pOverlapped;
|
||
#else
|
||
std::string m_filePath;
|
||
int m_fdPipe;
|
||
#endif
|
||
};
|
||
|
||
struct HGNamedPipeInImpl
|
||
{
|
||
HGNamedPipeInImpl()
|
||
{
|
||
#if defined(HG_CMP_MSC)
|
||
m_hReadEvent = NULL;
|
||
m_hPipe = INVALID_HANDLE_VALUE;
|
||
#else
|
||
m_fdPipe = -1;
|
||
#endif
|
||
}
|
||
|
||
~HGNamedPipeInImpl()
|
||
{
|
||
#if defined(HG_CMP_MSC)
|
||
CloseHandle(m_hPipe);
|
||
m_hPipe = INVALID_HANDLE_VALUE;
|
||
CloseHandle(m_hReadEvent);
|
||
m_hReadEvent = NULL;
|
||
#else
|
||
if (-1 != m_fdPipe)
|
||
{
|
||
close(m_fdPipe);
|
||
m_fdPipe = -1;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
#if defined(HG_CMP_MSC)
|
||
HANDLE m_hReadEvent;
|
||
HANDLE m_hPipe;
|
||
#else
|
||
int m_fdPipe;
|
||
#endif
|
||
};
|
||
|
||
HGResult HGAPI HGBase_CreateNamedPipe(const HGChar* pipeName, HGNamedPipeOut* pipeOut)
|
||
{
|
||
if (NULL == pipeName || NULL == pipeOut)
|
||
{
|
||
return HGBASE_ERR_INVALIDARG;
|
||
}
|
||
|
||
#if defined(HG_CMP_MSC)
|
||
HANDLE hConnectEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||
assert(NULL != hConnectEvent);
|
||
HANDLE hWriteEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||
assert(NULL != hWriteEvent);
|
||
|
||
char name[256];
|
||
sprintf(name, "\\\\.\\pipe\\%s", pipeName);
|
||
HANDLE hPipe = CreateNamedPipeA(name, PIPE_ACCESS_OUTBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
|
||
0, 1, 1024, 1024, 0, NULL);
|
||
if (INVALID_HANDLE_VALUE == hPipe)
|
||
{
|
||
CloseHandle(hWriteEvent);
|
||
CloseHandle(hConnectEvent);
|
||
return HGBASE_ERR_FAIL;
|
||
}
|
||
|
||
OVERLAPPED* pOverlapped = new OVERLAPPED;
|
||
memset(pOverlapped, 0, sizeof(OVERLAPPED));
|
||
pOverlapped->hEvent = hConnectEvent;
|
||
if (!ConnectNamedPipe(hPipe, pOverlapped))
|
||
{
|
||
DWORD err = GetLastError();
|
||
if (ERROR_IO_PENDING != err && ERROR_PIPE_CONNECTED != err)
|
||
{
|
||
delete pOverlapped;
|
||
CloseHandle(hPipe);
|
||
CloseHandle(hWriteEvent);
|
||
CloseHandle(hConnectEvent);
|
||
return HGBASE_ERR_FAIL;
|
||
}
|
||
}
|
||
|
||
HGNamedPipeOutImpl* pipeOutImpl = new HGNamedPipeOutImpl;
|
||
pipeOutImpl->m_hConnectEvent = hConnectEvent;
|
||
pipeOutImpl->m_hWriteEvent = hWriteEvent;
|
||
pipeOutImpl->m_hPipe = hPipe;
|
||
pipeOutImpl->m_pOverlapped = pOverlapped;
|
||
#else
|
||
char name[256];
|
||
sprintf(name, "/tmp/%s", pipeName);
|
||
if (access(name, F_OK) != -1)
|
||
return HGBASE_ERR_FAIL;
|
||
|
||
if (0 != mkfifo(name, 0777))
|
||
return HGBASE_ERR_FAIL;
|
||
|
||
int fdPipe = open(name, O_WRONLY);
|
||
if (-1 == fdPipe)
|
||
return HGBASE_ERR_FAIL;
|
||
|
||
HGNamedPipeOutImpl* pipeOutImpl = new HGNamedPipeOutImpl;
|
||
pipeOutImpl->m_filePath = name;
|
||
pipeOutImpl->m_fdPipe = fdPipe;
|
||
#endif
|
||
|
||
*pipeOut = (HGNamedPipeOut)pipeOutImpl;
|
||
return HGBASE_ERR_OK;
|
||
}
|
||
|
||
HGResult HGAPI HGBase_DestroyNamedPipe(HGNamedPipeOut pipeOut)
|
||
{
|
||
if (NULL == pipeOut)
|
||
{
|
||
return HGBASE_ERR_INVALIDARG;
|
||
}
|
||
|
||
HGNamedPipeOutImpl* pipeOutImpl = (HGNamedPipeOutImpl*)pipeOut;
|
||
delete pipeOutImpl;
|
||
return HGBASE_ERR_OK;
|
||
}
|
||
|
||
HGResult HGAPI HGBase_WriteNamedPipe(HGNamedPipeOut pipeOut, const HGByte* data, HGUInt size, HGUInt *writeSize)
|
||
{
|
||
if (NULL == pipeOut || NULL == data || 0 == size)
|
||
{
|
||
return HGBASE_ERR_INVALIDARG;
|
||
}
|
||
|
||
HGNamedPipeOutImpl* pipeOutImpl = (HGNamedPipeOutImpl*)pipeOut;
|
||
|
||
#if defined(HG_CMP_MSC)
|
||
// <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>
|
||
WaitForSingleObject(pipeOutImpl->m_hConnectEvent, INFINITE);
|
||
DWORD dwTransferBytes = 0; // <20><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
if (!GetOverlappedResult(pipeOutImpl->m_hPipe, pipeOutImpl->m_pOverlapped, &dwTransferBytes, TRUE))
|
||
{
|
||
// <20>ֶ<EFBFBD>ֹͣ
|
||
return HGBASE_ERR_FAIL;
|
||
}
|
||
|
||
OVERLAPPED overlapped = { 0 };
|
||
overlapped.hEvent = pipeOutImpl->m_hWriteEvent;
|
||
DWORD dwNumerOfWriteBytes = 0;
|
||
if (!WriteFile(pipeOutImpl->m_hPipe, data, size, &dwNumerOfWriteBytes, &overlapped))
|
||
{
|
||
if (ERROR_IO_PENDING != GetLastError())
|
||
{
|
||
// д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
return HGBASE_ERR_FAIL;
|
||
}
|
||
|
||
WaitForSingleObject(pipeOutImpl->m_hWriteEvent, INFINITE);
|
||
if (!GetOverlappedResult(pipeOutImpl->m_hPipe, &overlapped, &dwNumerOfWriteBytes, TRUE))
|
||
{
|
||
// <20>ֶ<EFBFBD>ֹͣ
|
||
return HGBASE_ERR_FAIL;
|
||
}
|
||
}
|
||
|
||
if (NULL != writeSize)
|
||
*writeSize = dwNumerOfWriteBytes;
|
||
#else
|
||
int res = write(pipeOutImpl->m_fdPipe, data, size);
|
||
if (-1 == res)
|
||
return HGBASE_ERR_FAIL;
|
||
|
||
if (NULL != writeSize)
|
||
*writeSize = res;
|
||
#endif
|
||
|
||
return HGBASE_ERR_OK;
|
||
}
|
||
|
||
HGResult HGAPI HGBase_StopWriteNamedPipe(HGNamedPipeOut pipeOut)
|
||
{
|
||
if (NULL == pipeOut)
|
||
{
|
||
return HGBASE_ERR_INVALIDARG;
|
||
}
|
||
|
||
HGNamedPipeOutImpl* pipeOutImpl = (HGNamedPipeOutImpl*)pipeOut;
|
||
#if defined(HG_CMP_MSC)
|
||
SetEvent(pipeOutImpl->m_hConnectEvent);
|
||
SetEvent(pipeOutImpl->m_hWriteEvent);
|
||
#else
|
||
if (-1 != pipeOutImpl->m_fdPipe)
|
||
{
|
||
close(pipeOutImpl->m_fdPipe);
|
||
pipeOutImpl->m_fdPipe = -1;
|
||
}
|
||
#endif
|
||
return HGBASE_ERR_OK;
|
||
}
|
||
|
||
HGResult HGAPI HGBase_OpenNamedPipe(const HGChar* pipeName, HGNamedPipeIn* pipeIn)
|
||
{
|
||
if (NULL == pipeName || NULL == pipeIn)
|
||
{
|
||
return HGBASE_ERR_INVALIDARG;
|
||
}
|
||
|
||
#if defined(HG_CMP_MSC)
|
||
HANDLE hReadEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||
assert(NULL != hReadEvent);
|
||
|
||
char name[256];
|
||
sprintf(name, "\\\\.\\pipe\\%s", pipeName);
|
||
if (!WaitNamedPipeA(name, NMPWAIT_USE_DEFAULT_WAIT))
|
||
{
|
||
DWORD dw = GetLastError();
|
||
return HGBASE_ERR_FAIL;
|
||
}
|
||
|
||
HANDLE hPipe = CreateFileA(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
|
||
if (INVALID_HANDLE_VALUE == hPipe)
|
||
{
|
||
CloseHandle(hReadEvent);
|
||
return HGBASE_ERR_FAIL;
|
||
}
|
||
|
||
HGNamedPipeInImpl* pipeInImpl = new HGNamedPipeInImpl;
|
||
pipeInImpl->m_hReadEvent = hReadEvent;
|
||
pipeInImpl->m_hPipe = hPipe;
|
||
#else
|
||
char name[256];
|
||
sprintf(name, "/tmp/%s", pipeName);
|
||
int fdPipe = open(name, O_RDONLY);
|
||
if (-1 == fdPipe)
|
||
return HGBASE_ERR_FAIL;
|
||
|
||
HGNamedPipeInImpl* pipeInImpl = new HGNamedPipeInImpl;
|
||
pipeInImpl->m_fdPipe = fdPipe;
|
||
#endif
|
||
|
||
*pipeIn = (HGNamedPipeIn)pipeInImpl;
|
||
return HGBASE_ERR_OK;
|
||
}
|
||
|
||
HGResult HGAPI HGBase_CloseNamedPipe(HGNamedPipeIn pipeIn)
|
||
{
|
||
if (NULL == pipeIn)
|
||
{
|
||
return HGBASE_ERR_INVALIDARG;
|
||
}
|
||
|
||
HGNamedPipeInImpl* pipeInImpl = (HGNamedPipeInImpl*)pipeIn;
|
||
delete pipeInImpl;
|
||
return HGBASE_ERR_OK;
|
||
}
|
||
|
||
HGResult HGAPI HGBase_ReadNamedPipe(HGNamedPipeIn pipeIn, HGByte* data, HGUInt size, HGUInt* readSize)
|
||
{
|
||
if (NULL == pipeIn || NULL == data || 0 == size)
|
||
{
|
||
return HGBASE_ERR_INVALIDARG;
|
||
}
|
||
|
||
HGNamedPipeInImpl* pipeInImpl = (HGNamedPipeInImpl*)pipeIn;
|
||
#if defined(HG_CMP_MSC)
|
||
OVERLAPPED overlapped = { 0 };
|
||
overlapped.hEvent = pipeInImpl->m_hReadEvent;
|
||
DWORD dwNumerOfReadBytes = 0;
|
||
if (!ReadFile(pipeInImpl->m_hPipe, data, size, &dwNumerOfReadBytes, &overlapped))
|
||
{
|
||
if (ERROR_IO_PENDING != GetLastError())
|
||
{
|
||
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
|
||
return HGBASE_ERR_FAIL;
|
||
}
|
||
|
||
WaitForSingleObject(pipeInImpl->m_hReadEvent, INFINITE);
|
||
if (!GetOverlappedResult(pipeInImpl->m_hPipe, &overlapped, &dwNumerOfReadBytes, TRUE))
|
||
{
|
||
// <20>ֶ<EFBFBD>ֹͣ
|
||
return HGBASE_ERR_FAIL;
|
||
}
|
||
}
|
||
|
||
if (NULL != readSize)
|
||
*readSize = dwNumerOfReadBytes;
|
||
#else
|
||
int res = read(pipeInImpl->m_fdPipe, data, size);
|
||
if (-1 == res)
|
||
return HGBASE_ERR_FAIL;
|
||
if (NULL != readSize)
|
||
*readSize = res;
|
||
#endif
|
||
|
||
return HGBASE_ERR_OK;
|
||
}
|
||
|
||
HGResult HGAPI HGBase_StopReadNamedPipe(HGNamedPipeIn pipeIn)
|
||
{
|
||
if (NULL == pipeIn)
|
||
{
|
||
return HGBASE_ERR_INVALIDARG;
|
||
}
|
||
|
||
HGNamedPipeInImpl* pipeInImpl = (HGNamedPipeInImpl*)pipeIn;
|
||
#if defined(HG_CMP_MSC)
|
||
SetEvent(pipeInImpl->m_hReadEvent);
|
||
#else
|
||
if (-1 != pipeInImpl->m_fdPipe)
|
||
{
|
||
close(pipeInImpl->m_fdPipe);
|
||
pipeInImpl->m_fdPipe = -1;
|
||
}
|
||
#endif
|
||
return HGBASE_ERR_OK;
|
||
}
|