39 #if defined(NCBI_OS_UNIX)
44 # include <sys/socket.h>
45 # include <sys/types.h>
47 #elif !defined(NCBI_OS_MSWIN)
48 # error "The CNamedPipe class is supported only on Windows and Unix"
52 #define NCBI_USE_ERRCODE_X Connect_Pipe
55 #define NAMEDPIPE_THROW(err, errtxt) \
56 THROW0_TRACE(x_FormatError(int(err), errtxt))
62 #if defined(HAVE_SOCKLEN_T) || defined(_SOCKLEN_T)
96 DWORD rv = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
97 FORMAT_MESSAGE_FROM_SYSTEM |
98 FORMAT_MESSAGE_MAX_WIDTH_MASK |
99 FORMAT_MESSAGE_IGNORE_INSERTS,
101 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
105 errstr = errmsg.c_str();
110 ::LocalFree((HLOCAL) tmpstr);
121 return retval.
get() ? retval.
get() : message;
127 return "[CNamedPipe::" + where +
"] " + what;
138 #if defined(NCBI_OS_MSWIN)
146 return (
error == ERROR_NO_DATA ||
147 error == ERROR_BROKEN_PIPE ||
148 error == ERROR_PIPE_NOT_CONNECTED ?
true :
false);
199 m_ReadStatus(eIO_Closed), m_WriteStatus(eIO_Closed)
222 +
"\" already open");
227 SECURITY_ATTRIBUTES attr;
228 attr.nLength =
sizeof(attr);
229 attr.bInheritHandle =
TRUE;
230 attr.lpSecurityDescriptor =
NULL;
242 unsigned long x_sleep = 1;
246 GENERIC_READ | GENERIC_WRITE,
247 FILE_SHARE_READ | FILE_SHARE_WRITE,
248 &attr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
252 DWORD mode = PIPE_READMODE_BYTE | PIPE_NOWAIT;
253 if ( ::SetNamedPipeHandleState(pipe, &
mode,
NULL,
NULL) ) {
256 error = ::GetLastError();
259 error = ::GetLastError();
262 &&
error != ERROR_PIPE_BUSY) ||
264 &&
error != ERROR_PIPE_NOT_CONNECTED)) {
266 &&
error == ERROR_FILE_NOT_FOUND) {
273 "Named pipe \"" + pipename
276 ?
"open" :
"set non-blocking"));
282 if (x_timeout != INFINITE) {
283 if (x_sleep > x_timeout) {
286 x_timeout -= x_sleep;
303 catch (
string& what) {
320 +
"\" already exists");
326 "Named pipe \"" + pipename
333 SECURITY_ATTRIBUTES attr;
334 attr.nLength =
sizeof(attr);
335 attr.bInheritHandle =
TRUE;
336 attr.lpSecurityDescriptor =
NULL;
339 m_Pipe = ::CreateNamedPipe
342 PIPE_TYPE_BYTE | PIPE_NOWAIT,
351 if (
error == ERROR_ALREADY_EXISTS) {
355 "Named pipe \"" + pipename
356 +
"\" failed to create");
364 catch (
string& what) {
392 unsigned long x_sleep = 1;
398 if (
error == ERROR_PIPE_CONNECTED) {
403 if (
error == ERROR_NO_DATA) {
409 +
"\" still connected");
411 if (
error != ERROR_PIPE_LISTENING) {
414 +
"\" not listening");
420 if (x_timeout != INFINITE) {
421 if (x_sleep > x_timeout) {
424 x_timeout -= x_sleep;
439 catch (
string& what) {
454 +
"\" failed to flush");
460 if (!::DisconnectNamedPipe(
m_Pipe)) {
465 +
"\" failed to disconnect");
470 (void) ::CloseHandle(
m_Pipe);
487 +
"\" already disconnected");
494 catch (
string& what) {
513 catch (
string& what) {
519 (void) ::CloseHandle(
m_Pipe);
540 unsigned long x_sleep = 1;
567 if (x_timeout != INFINITE) {
568 if (x_sleep > x_timeout) {
571 x_timeout -= x_sleep;
598 :
" not connected"));
612 if (bytes_avail >
count) {
616 if ( !bytes_avail ) {
625 *n_read = bytes_avail;
630 }
else if (status != eIO_Closed) {
636 catch (
string& what) {
645 size_t* n_written,
const STimeout* timeout)
648 _ASSERT(n_written && !*n_written);
658 :
" not connected"));
671 DWORD bytes_written = 0;
673 unsigned long x_sleep = 1;
676 if ( bytes_written ) {
697 +
"\" write failed");
705 if (x_timeout != INFINITE) {
706 if (x_sleep > x_timeout) {
709 x_timeout -= x_sleep;
719 *n_written = bytes_written;
722 catch (
string& what) {
737 :
" not connected")));
751 return status == eIO_Closed ?
eIO_Success : status;
759 switch ( direction ) {
772 #elif defined(NCBI_OS_UNIX)
781 static const int kListenQueueSize = 64;
812 bool x_SetSocketBufSize(
int sock,
size_t bufsize,
int dir);
825 : m_LSocket(0), m_IoSocket(0), m_PipeSize(0)
845 if (m_LSocket || m_IoSocket) {
848 +
"\" already open");
853 if (status == eIO_Closed
859 "Named pipe \"" + pipename
860 +
"\" failed to open UNIX socket: "
869 if (!x_SetSocketBufSize(fd, pipesize, SO_SNDBUF) ||
870 !x_SetSocketBufSize(fd, pipesize, SO_RCVBUF)) {
874 "Named pipe \"" + pipename
876 " UNIX socket buffer size "
886 catch (
string& what) {
900 if (m_LSocket || m_IoSocket) {
903 +
"\" already exists");
907 switch (pipe.GetType()) {
917 "Named pipe path \"" + pipename
918 +
"\" already exists");
926 "Named pipe \"" + pipename
927 +
"\" failed to create listening"
931 m_PipeSize = pipesize;
935 catch (
string& what) {
948 if (!m_LSocket || m_IoSocket) {
952 +
'"' +
string(m_LSocket
964 +
"\" failed to accept in UNIX socket: "
973 if (!x_SetSocketBufSize(fd, m_PipeSize, SO_SNDBUF) ||
974 !x_SetSocketBufSize(fd, m_PipeSize, SO_RCVBUF)) {
977 +
"\" failed to set UNIX socket buffer "
985 catch (
string& what) {
1020 if ( !m_IoSocket ) {
1023 +
"\" already disconnected"));
1032 if (!m_LSocket && !m_IoSocket) {
1053 if ( !m_IoSocket ) {
1056 +
'"' +
string(m_LSocket
1070 +
"\" read failed: "
1074 catch (
string& what) {
1083 size_t* n_written,
const STimeout* timeout)
1086 _ASSERT(n_written && !*n_written);
1091 if ( !m_IoSocket ) {
1094 +
'"' +
string(m_LSocket
1108 +
"\" write failed: "
1112 catch (
string& what) {
1122 if ( !m_IoSocket ) {
1130 return SOCK_Wait(m_IoSocket, event, timeout);
1136 return !m_IoSocket ? eIO_Closed :
SOCK_Status(m_IoSocket, direction);
1140 bool CNamedPipeHandle::x_SetSocketBufSize(
int sock,
size_t bufsize,
int dir)
1146 if (::getsockopt(sock, SOL_SOCKET, dir, &bs_old, &bs_len) == 0
1147 && bs_new > bs_old) {
1148 if (::setsockopt(sock, SOL_SOCKET, dir, &bs_new, bs_len) != 0) {
1167 : m_PipeSize(pipesize),
1168 m_OpenTimeout(0), m_ReadTimeout(0), m_WriteTimeout(0)
1208 n_written = &x_written;
1241 switch (direction) {
1301 #ifdef NCBI_OS_MSWIN
1302 static const char kSeparators[] =
":/\\";
1304 static const char kSeparators[] =
"/";
1306 if (pipename.find_first_of(kSeparators) !=
NPOS) {
1311 #if defined(NCBI_OS_MSWIN)
1313 #elif defined(NCBI_OS_UNIX)
1316 const char* pipedir =
"/var/tmp";
1317 if (::stat(pipedir, &
st) != 0 || !S_ISDIR(
st.st_mode)
1318 || ::access(pipedir, W_OK) != 0) {
1320 if (::stat(pipedir, &
st) != 0 || !S_ISDIR(
st.st_mode)
1321 || ::access(pipedir, W_OK) != 0) {
1395 Create(pipename, timeout);
EIO_Status Status(EIO_Event direction) const
EIO_Status Open(const string &pipename, const STimeout *timeout, size_t pipesize, CNamedPipeClient::TFlags flags)
EIO_Status x_WaitForRead(const STimeout *timeout, DWORD *in_avail)
EIO_Status Close(bool close=true)
EIO_Status Read(void *buf, size_t count, size_t *n_read, const STimeout *timeout)
EIO_Status Listen(const STimeout *timeout)
EIO_Status x_Disconnect(bool orderly)
EIO_Status Disconnect(void)
EIO_Status Create(const string &pipename, size_t pipesize)
EIO_Status Wait(EIO_Event event, const STimeout *timeout)
EIO_Status Write(const void *buf, size_t count, size_t *n_written, const STimeout *timeout)
element_type * get(void) const
Get pointer.
@ eTakeOwnership
An object can take ownership of another.
@ eNoOwnership
No ownership is assumed.
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
@ eSocket
Socket (UNIX only)
CNamedPipeClient(size_t pipesize=0)
Default constructor.
const STimeout * m_OpenTimeout
Timeouts.
EIO_Status Create(const string &pipename, const STimeout *timeout=kDefaultTimeout, size_t pipesize=0)
Create a server-side pipe.
CNamedPipeServer(size_t pipesize=0)
Default constructor.
EIO_Status Wait(EIO_Event event, const STimeout *timeout)
Wait for I/O readiness in the pipe.
EIO_Status Status(EIO_Event direction) const
Return (for the specified "direction"): eIO_Closed – if the pipe is closed for I/O; eIO_Timeout – if ...
const STimeout * GetTimeout(EIO_Event event) const
Get the pipe I/O timeout (or NULL, if the timeout is infinite).
bool m_IsClientSide
client/server-side pipe
STimeout m_ReadTimeoutValue
storage for m_ReadTimeout
string m_PipeName
pipe name
EIO_Status Close(void)
Close pipe connection.
EIO_Status Listen(void)
Listen on a pipe for new client connection.
void x_SetName(const string &pipename)
STimeout m_OpenTimeoutValue
storage for m_OpenTimeout
size_t m_PipeSize
pipe size
virtual ~CNamedPipe()
Destructor.
CNamedPipe(size_t pipe_size=0)
Constructor.
const STimeout * m_WriteTimeout
eIO_Write
EIO_Status Read(void *buf, size_t count, size_t *n_read=0)
Read data from the pipe.
STimeout m_WriteTimeoutValue
storage for m_WriteTimeout
const STimeout * m_ReadTimeout
eIO_Read
EIO_Status SetTimeout(EIO_Event event, const STimeout *timeout)
Specify timeout for the pipe I/O (see Open|Read|Write functions).
CNamedPipeHandle * m_NamedPipeHandle
OS-specific handle.
EIO_Status Open(const string &pipename, const STimeout *timeout=kDefaultTimeout, size_t pipesize=0, TFlags flags=0)
Open a client-side pipe connection.
EIO_Status Disconnect(void)
Disconnect the client.
EIO_Status Write(const void *buf, size_t count, size_t *n_written=0)
Write data to the pipe.
@ fNoLogIfClosed
Do not log error if server end is closed.
#define END_NCBI_SCOPE
End previously defined NCBI scope.
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
EIO_Status LSOCK_CreateUNIX(const char *path, unsigned short backlog, LSOCK *lsock, TSOCK_Flags flags)
EIO_Status SOCK_SetTimeout(SOCK sock, EIO_Event event, const STimeout *timeout)
Specify timeout for the connection I/O (see SOCK_[Read|Write|Close]()).
EIO_Status SOCK_Close(SOCK sock)
Close the SOCK handle, and destroy all relevant internal data.
EIO_Status LSOCK_Accept(LSOCK lsock, const STimeout *timeout, SOCK *sock)
[SERVER-side] Accept connection from a client.
EIO_Status SOCK_Read(SOCK sock, void *buf, size_t size, size_t *n_read, EIO_ReadMethod how)
Read/peek up to "size" bytes from "sock" to a buffer pointed to by "buf".
EIO_Status SOCK_Status(SOCK sock, EIO_Event direction)
Return low-level socket I/O status of *last* socket operation.
EIO_Status SOCK_Wait(SOCK sock, EIO_Event event, const STimeout *timeout)
Block on the socket until either the specified "event" is available or "timeout" expires (if "timeout...
EIO_Status SOCK_Write(SOCK sock, const void *data, size_t size, size_t *n_written, EIO_WriteMethod how)
Write "size" bytes of "data" to "sock".
EIO_Status LSOCK_Close(LSOCK lsock)
[SERVER-side] Close the listening socket, destroy relevant internal data.
EIO_Status SOCK_CreateUNIX(const char *path, const STimeout *timeout, SOCK *sock, const void *data, size_t size, TSOCK_Flags flags)
EIO_Status SOCK_GetOSHandle(SOCK sock, void *handle_buf, size_t handle_size)
Same as SOCK_GetOSHandleEx(sock, handle_buf, handle_size, eNoOwnership).
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
static string & ToLower(string &str)
Convert string to lower case – string& version.
const long kMicroSecondsPerSecond
Number of microseconds in one second.
unsigned long NcbiTimeoutToMs(const STimeout *timeout)
unsigned int usec
microseconds (modulo 1,000,000)
const char * IO_StatusStr(EIO_Status status)
Get the text form of an enum status value.
const char * NcbiMessagePlusError(int *dynamic, const char *message, int error, const char *descr)
Add current "error" (and maybe its description) to the message: <message>[ {error=[[<error>][,...
EIO_Event
I/O event (or direction).
@ eIO_Timeout
timeout expired before any I/O succeeded
@ eIO_Success
everything is fine, no error occurred
@ eIO_Unknown
unknown I/O error (likely fatal but can retry)
@ eIO_InvalidArg
bad argument / parameter value(s) supplied
@ eIO_ReadPlain
read readily available data only, wait if none
@ eIO_WritePlain
write as much as possible, report back how much
@ eIO_ReadWrite
eIO_Read | eIO_Write (also, eCONN_OnFlush)
@ eIO_Open
also serves as no-event indicator in SOCK_Poll
@ eIO_Close
also serves as an error indicator in SOCK_Poll
#define INVALID_HANDLE_VALUE
A value for an invalid file handle.
#define HANDLE
An abstraction for a file handle.
unsigned int
A callback function used to compare two keys in a database.
Definition of all error codes used in connect library (xconnect.lib, xconnext.lib etc).
static const STimeout kZeroTimeout
#define NAMEDPIPE_THROW(err, errtxt)
static string x_FormatError(int error, const string &message)
AutoPtr< char, CDeleter< char > > TTempCharPtr
static string s_FormatErrorMessage(const string &where, const string &what)
const unsigned long kWaitPrecision
static const STimeout * s_SetTimeout(const STimeout *from, STimeout *to)
static bool x_IsDisconnectError(DWORD error)
Portable interprocess named pipe API for: UNIX, MS-Win.
#define TRUE
bool replacment for C indicating true.
void SleepMilliSec(unsigned long ml_sec, EInterruptOnSignal onsignal=eRestartOnSignal)
Defines classes: CDirEntry, CFile, CDir, CSymLink, CMemoryFile, CFileUtil, CFileLock,...
static PCRE2_SIZE bufsize
static SLJIT_INLINE sljit_ins st(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)