|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef NAMEDPIPE_H |
|
#define NAMEDPIPE_H |
|
|
|
#include <windows.h> |
|
|
|
#include <memory> |
|
#include <string> |
|
#include <vector> |
|
|
|
#include "../shared/OwnedHandle.h" |
|
|
|
class EventLoop; |
|
|
|
class NamedPipe |
|
{ |
|
private: |
|
|
|
friend class EventLoop; |
|
NamedPipe() {} |
|
~NamedPipe() { closePipe(); } |
|
bool serviceIo(std::vector<HANDLE> *waitHandles); |
|
void startPipeWorkers(); |
|
|
|
enum class ServiceResult { NoProgress, Error, Progress }; |
|
|
|
private: |
|
class IoWorker |
|
{ |
|
public: |
|
IoWorker(NamedPipe &namedPipe); |
|
virtual ~IoWorker() {} |
|
ServiceResult service(); |
|
void waitForCanceledIo(); |
|
HANDLE getWaitEvent(); |
|
protected: |
|
NamedPipe &m_namedPipe; |
|
bool m_pending = false; |
|
DWORD m_currentIoSize = 0; |
|
OwnedHandle m_event; |
|
OVERLAPPED m_over = {}; |
|
enum { kIoSize = 64 * 1024 }; |
|
char m_buffer[kIoSize]; |
|
virtual void completeIo(DWORD size) = 0; |
|
virtual bool shouldIssueIo(DWORD *size, bool *isRead) = 0; |
|
}; |
|
|
|
class InputWorker : public IoWorker |
|
{ |
|
public: |
|
InputWorker(NamedPipe &namedPipe) : IoWorker(namedPipe) {} |
|
protected: |
|
virtual void completeIo(DWORD size) override; |
|
virtual bool shouldIssueIo(DWORD *size, bool *isRead) override; |
|
}; |
|
|
|
class OutputWorker : public IoWorker |
|
{ |
|
public: |
|
OutputWorker(NamedPipe &namedPipe) : IoWorker(namedPipe) {} |
|
DWORD getPendingIoSize(); |
|
protected: |
|
virtual void completeIo(DWORD size) override; |
|
virtual bool shouldIssueIo(DWORD *size, bool *isRead) override; |
|
}; |
|
|
|
public: |
|
struct OpenMode { |
|
typedef int t; |
|
enum { None = 0, Reading = 1, Writing = 2, Duplex = 3 }; |
|
}; |
|
|
|
std::wstring name() const { return m_name; } |
|
void openServerPipe(LPCWSTR pipeName, OpenMode::t openMode, |
|
int outBufferSize, int inBufferSize); |
|
void connectToServer(LPCWSTR pipeName, OpenMode::t openMode); |
|
size_t bytesToSend(); |
|
void write(const void *data, size_t size); |
|
void write(const char *text); |
|
size_t readBufferSize(); |
|
void setReadBufferSize(size_t size); |
|
size_t bytesAvailable(); |
|
size_t peek(void *data, size_t size); |
|
size_t read(void *data, size_t size); |
|
std::string readToString(size_t size); |
|
std::string readAllToString(); |
|
void closePipe(); |
|
bool isClosed() { return m_handle == nullptr; } |
|
bool isConnected() { return !isClosed() && !isConnecting(); } |
|
bool isConnecting() { return m_connectEvent.get() != nullptr; } |
|
|
|
private: |
|
|
|
std::wstring m_name; |
|
OVERLAPPED m_connectOver = {}; |
|
OwnedHandle m_connectEvent; |
|
OpenMode::t m_openMode = OpenMode::None; |
|
size_t m_readBufferSize = 64 * 1024; |
|
std::string m_inQueue; |
|
std::string m_outQueue; |
|
HANDLE m_handle = nullptr; |
|
std::unique_ptr<InputWorker> m_inputWorker; |
|
std::unique_ptr<OutputWorker> m_outputWorker; |
|
}; |
|
|
|
#endif |
|
|