|
@@ -47,10 +47,13 @@ IpcConnection::IpcConnection(const char *endpoint,void (*commandHandler)(void *,
|
|
|
_handler(commandHandler),
|
|
|
_arg(arg),
|
|
|
#ifdef __WINDOWS__
|
|
|
- _sock(INVALID_HANDLE_VALUE)
|
|
|
+ _sock(INVALID_HANDLE_VALUE),
|
|
|
+ _incoming(false),
|
|
|
#else
|
|
|
- _sock(0)
|
|
|
+ _sock(-1),
|
|
|
#endif
|
|
|
+ _run(true),
|
|
|
+ _running(true)
|
|
|
{
|
|
|
#ifdef __WINDOWS__
|
|
|
_sock = CreateFileA(endpoint,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,NULL,OPEN_EXISTING,0,NULL);
|
|
@@ -74,7 +77,7 @@ IpcConnection::IpcConnection(const char *endpoint,void (*commandHandler)(void *,
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- Thread::start(this);
|
|
|
+ _thread = Thread::start(this);
|
|
|
}
|
|
|
|
|
|
#ifdef __WINDOWS__
|
|
@@ -84,19 +87,26 @@ IpcConnection::IpcConnection(int s,void (*commandHandler)(void *,IpcConnection *
|
|
|
#endif
|
|
|
_handler(commandHandler),
|
|
|
_arg(arg),
|
|
|
- _sock(s)
|
|
|
+ _sock(s),
|
|
|
+#ifdef __WINDOWS__
|
|
|
+ _incoming(true),
|
|
|
+#endif
|
|
|
+ _run(true),
|
|
|
+ _running(true)
|
|
|
{
|
|
|
- Thread::start(this);
|
|
|
+ _thread = Thread::start(this);
|
|
|
}
|
|
|
|
|
|
IpcConnection::~IpcConnection()
|
|
|
{
|
|
|
_writeLock.lock();
|
|
|
+ _run = false;
|
|
|
+ _writeLock.unlock();
|
|
|
+
|
|
|
#ifdef __WINDOWS__
|
|
|
- HANDLE s = _sock;
|
|
|
- _sock = INVALID_HANDLE_VALUE;
|
|
|
- if (s != INVALID_HANDLE_VALUE) {
|
|
|
- CloseHandle(s);
|
|
|
+ while (_running) {
|
|
|
+ Thread::cancelIO(_thread);
|
|
|
+ Sleep(100);
|
|
|
}
|
|
|
#else
|
|
|
int s = _sock;
|
|
@@ -106,7 +116,6 @@ IpcConnection::~IpcConnection()
|
|
|
::close(s);
|
|
|
}
|
|
|
#endif
|
|
|
- _writeLock.unlock();
|
|
|
}
|
|
|
|
|
|
void IpcConnection::printf(const char *format,...)
|
|
@@ -115,22 +124,20 @@ void IpcConnection::printf(const char *format,...)
|
|
|
int n;
|
|
|
char tmp[65536];
|
|
|
|
|
|
- Mutex::Lock _l(_writeLock);
|
|
|
-
|
|
|
- if (_sock <= 0)
|
|
|
- return;
|
|
|
-
|
|
|
va_start(ap,format);
|
|
|
n = (int)::vsnprintf(tmp,sizeof(tmp),format,ap);
|
|
|
va_end(ap);
|
|
|
if (n <= 0)
|
|
|
return;
|
|
|
|
|
|
+ Mutex::Lock _l(_writeLock);
|
|
|
+
|
|
|
#ifdef __WINDOWS__
|
|
|
- DWORD bsent = 0;
|
|
|
- WriteFile(_sock,tmp,n,&bsent,NULL);
|
|
|
+ _writeBuf.append(tmp,n);
|
|
|
+ Thread::cancelIO(_thread);
|
|
|
#else
|
|
|
- ::write(_sock,tmp,n);
|
|
|
+ if (_sock > 0)
|
|
|
+ ::write(_sock,tmp,n);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -140,29 +147,51 @@ void IpcConnection::threadMain()
|
|
|
char tmp[65536];
|
|
|
char linebuf[65536];
|
|
|
unsigned int lineptr = 0;
|
|
|
+ char c;
|
|
|
+
|
|
|
#ifdef __WINDOWS__
|
|
|
- HANDLE s;
|
|
|
DWORD n,i;
|
|
|
+ std::string wbuf;
|
|
|
#else
|
|
|
int s,n,i;
|
|
|
#endif
|
|
|
- char c;
|
|
|
|
|
|
- for(;;) {
|
|
|
+ while (_run) {
|
|
|
#ifdef __WINDOWS__
|
|
|
- s = _sock;
|
|
|
- if (s == INVALID_HANDLE_VALUE)
|
|
|
- break;
|
|
|
- if (!ReadFile(s,tmp,sizeof(tmp),&n,NULL))
|
|
|
+ {
|
|
|
+ Mutex::Lock _l(_writeLock);
|
|
|
+ if (!_run)
|
|
|
+ break;
|
|
|
+ if (_writeBuf.length() > 0) {
|
|
|
+ wbuf.append(_writeBuf);
|
|
|
+ _writeBuf.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (wbuf.length() > 0) {
|
|
|
+ n = 0;
|
|
|
+ if ((WriteFile(_sock,wbuf.data(),(DWORD)(wbuf.length()),&n,NULL))&&(n > 0)) {
|
|
|
+ if (n < (DWORD)wbuf.length())
|
|
|
+ wbuf.erase(0,n);
|
|
|
+ else wbuf.clear();
|
|
|
+ } else if (GetLastError() != ERROR_OPERATION_ABORTED)
|
|
|
+ break;
|
|
|
+ FlushFileBuffers(_sock);
|
|
|
+ }
|
|
|
+ if (!_run)
|
|
|
break;
|
|
|
- if (n < 0)
|
|
|
+ n = 0;
|
|
|
+ if ((!ReadFile(_sock,tmp,sizeof(tmp),&n,NULL))||(n <= 0)) {
|
|
|
+ if (GetLastError() == ERROR_OPERATION_ABORTED)
|
|
|
+ n = 0;
|
|
|
+ else break;
|
|
|
+ }
|
|
|
+ if (!_run)
|
|
|
break;
|
|
|
#else
|
|
|
- s = _sock;
|
|
|
- if (s <= 0)
|
|
|
+ if ((s = _sock) <= 0)
|
|
|
break;
|
|
|
n = (int)::read(s,tmp,sizeof(tmp));
|
|
|
- if (n <= 0)
|
|
|
+ if ((n <= 0)||(_sock <= 0))
|
|
|
break;
|
|
|
#endif
|
|
|
for(i=0;i<n;++i) {
|
|
@@ -177,22 +206,19 @@ void IpcConnection::threadMain()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- {
|
|
|
- _writeLock.lock();
|
|
|
- s = _sock;
|
|
|
+ _writeLock.lock();
|
|
|
+ bool r = _run;
|
|
|
+ _writeLock.unlock();
|
|
|
+
|
|
|
#ifdef __WINDOWS__
|
|
|
- _sock = INVALID_HANDLE_VALUE;
|
|
|
- if (s != INVALID_HANDLE_VALUE)
|
|
|
- CloseHandle(s);
|
|
|
-#else
|
|
|
- _sock = 0;
|
|
|
- if (s > 0)
|
|
|
- ::close(s);
|
|
|
+ if (_incoming)
|
|
|
+ DisconnectNamedPipe(_sock);
|
|
|
+ CloseHandle(_sock);
|
|
|
+ _running = false;
|
|
|
#endif
|
|
|
- _writeLock.unlock();
|
|
|
- }
|
|
|
|
|
|
- _handler(_arg,this,IPC_EVENT_CONNECTION_CLOSED,(const char *)0);
|
|
|
+ if (r)
|
|
|
+ _handler(_arg,this,IPC_EVENT_CONNECTION_CLOSED,(const char *)0);
|
|
|
}
|
|
|
|
|
|
} // namespace ZeroTier
|