From 1e58eaf103f415baf573ddcb5f665221907934c0 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Fri, 26 Apr 2019 16:07:06 -0700 Subject: [PATCH 01/12] Experimental --- microscript/ILibDuktape_net.c | 253 +++++++++++++++++++++++++++++++++- microstack/ILibProcessPipe.c | 95 +++++++++++-- microstack/ILibProcessPipe.h | 7 + 3 files changed, 344 insertions(+), 11 deletions(-) diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index c4e4275..a9972e9 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -21,10 +21,12 @@ limitations under the License. #include "ILibDuktape_DuplexStream.h" #include "ILibDuktapeModSearch.h" #include "ILibDuktape_EventEmitter.h" +#include "ILibDuktape_ChildProcess.h" #include "microstack/ILibAsyncSocket.h" #include "microstack/ILibCrypto.h" #include "microstack/ILibAsyncServerSocket.h" #include "microstack/ILibRemoteLogging.h" +#include "microstack/ILibProcessPipe.h" #ifdef _POSIX #include @@ -32,6 +34,11 @@ limitations under the License. #include #endif +#ifdef WIN32 +#include +#include +#endif + typedef struct ILibDuktape_net_socket { duk_context *ctx; @@ -71,6 +78,28 @@ typedef struct ILibDuktape_net_server_session int ILibDuktape_TLS_ctx2socket = -1; int ILibDuktape_TLS_ctx2server = -1; +#ifdef WIN32 +#define ILibDuktape_net_IPC_BUFFERSIZE 4096 +typedef struct ILibDuktape_net_WindowsIPC +{ + ILibProcessPipe_Manager manager; + duk_context *ctx; + void *object, *mSocket; + HANDLE mPipeHandle; + ILibProcessPipe_Pipe mPipe; + + OVERLAPPED overlapped; + ILibDuktape_DuplexStream *ds; + + int processingRead; + char *buffer; + int bufferLength; + int bufferOffset; + int bytesLeft; + +}ILibDuktape_net_WindowsIPC; +#endif + #define ILibDuktape_SecureContext2CertBuffer "\xFF_SecureContext2CertBuffer" #define ILibDuktape_SecureContext2SSLCTXPTR "\xFF_SecureContext2SSLCTXPTR" #define ILibDuktape_GlobalTunnel_DataPtr "\xFF_GlobalTunnel_DataPtr" @@ -78,6 +107,8 @@ int ILibDuktape_TLS_ctx2server = -1; #define ILibDuktape_net_Server_buffer "\xFF_FixedBuffer" #define ILibDuktape_net_Server_Session_buffer "\xFF_SessionFixedBuffer" #define ILibDuktape_net_socket_ptr "\xFF_SocketPtr" +#define ILibDuktape_net_WindowsIPC_Buffer "\xFF_WindowsIPC" +#define ILibDuktape_net_WindowsIPC_PendingArray "\xFF_WindowsIPC_PendingArray" #define ILibDuktape_SERVER2ContextTable "\xFF_Server2ContextTable" #define ILibDuktape_SERVER2OPTIONS "\xFF_ServerToOptions" #define ILibDuktape_SERVER2LISTENOPTIONS "\xFF_ServerToListenOptions" @@ -689,6 +720,161 @@ void ILibDuktape_net_server_OnSendOK(ILibAsyncServerSocket_ServerModule AsyncSer ILibDuktape_DuplexStream_Ready(session->stream); } + +#ifdef WIN32 +extern void ILibProcessPipe_FreePipe(ILibProcessPipe_Pipe pipeObject); + +int ILibDuktape_net_server_IPC_unshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user) +{ + ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; + if (!ILibMemory_CanaryOK(user)) { return(0); } + + winIPC->bufferOffset += (winIPC->bytesLeft - unshiftBytes); + winIPC->bytesLeft = unshiftBytes; + return(unshiftBytes); +} +void ILibDuktape_net_server_IPC_readsink(ILibProcessPipe_Pipe sender, void *user, DWORD dwErrorCode, char *buffer, int bufferLen) +{ + ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; + if (!ILibMemory_CanaryOK(user)) { return; } + + if (dwErrorCode == 0) + { + ILibDuktape_DuplexStream_WriteData(winIPC->ds, buffer, bufferLen); + } + else + { + ILibDuktape_DuplexStream_Closed(winIPC->ds); + } +} +void ILibDuktape_net_server_IPC_PauseSink(ILibDuktape_DuplexStream *sender, void *user) +{ + // No-OP, becuase all we need to so is set Paused flag, which is already the case when we get here +} +void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, void *user) +{ + ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; + if (winIPC->processingRead != 0) { return; } + winIPC->processingRead = 1; + + if (winIPC->buffer == NULL) + { + winIPC->buffer = ILibMemory_Allocate(ILibDuktape_net_IPC_BUFFERSIZE, 0, NULL, NULL); + winIPC->bufferLength = ILibDuktape_net_IPC_BUFFERSIZE; + winIPC->bufferOffset = 0; + winIPC->bytesLeft = 0; + } + + if (winIPC->bytesLeft <= 0) + { + winIPC->bytesLeft = 0; + winIPC->bufferOffset = 0; + ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer, winIPC->bufferLength, winIPC, ILibDuktape_net_server_IPC_readsink); + } + else + { + // Check to see if we can drain any of the buffer first + int tmpBytesLeft; + while (winIPC->ds->readableStream->paused == 0) + { + tmpBytesLeft = winIPC->bytesLeft; + ILibDuktape_DuplexStream_WriteData(winIPC->ds, winIPC->buffer + winIPC->bufferOffset, winIPC->bytesLeft); + if (tmpBytesLeft == winIPC->bytesLeft) { break; } // No Data was consumed + if (winIPC->bytesLeft <= 0) + { + winIPC->bytesLeft = 0; + winIPC->bufferOffset = 0; + } + if (winIPC->ds->readableStream->paused == 0 && (winIPC->bytesLeft == 0 || (winIPC->bytesLeft > 0 && tmpBytesLeft == winIPC->bytesLeft))) + { + ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer + winIPC->bufferOffset + winIPC->bytesLeft, winIPC->bufferLength - winIPC->bufferOffset - winIPC->bytesLeft, winIPC, ILibDuktape_net_server_IPC_readsink); + break; + } + } + } + winIPC->processingRead = 0; +} +void ILibDuktape_net_server_IPC_WriteCompletionEvent(ILibProcessPipe_Pipe sender, void *user, DWORD errorCode, int bytesWritten) +{ + if (!ILibMemory_CanaryOK(user)) { return; } + ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; + duk_idx_t top = duk_get_top(winIPC->ctx); + + duk_push_heapptr(winIPC->ctx, winIPC->object); // [obj] + duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array] + duk_get_prop_string(winIPC->ctx, -1, "shift"); // [obj][array][shift] + duk_dup(winIPC->ctx, -2); // [obj][array][shift][this] + if (duk_pcall_method(winIPC->ctx, 0) != 0) // [obj][array][buffer] + { + ILibDuktape_Process_UncaughtExceptionEx(winIPC->ctx, "Internal Error: net.socket.ipc.writeCompletionEvent"); + duk_set_top(winIPC->ctx, top); // ... + return; + } + duk_pop(winIPC->ctx); // [obj][array] + if (duk_get_length(winIPC->ctx, -1) > 0) + { + // Still pending Writes + duk_get_prop_index(winIPC->ctx, -1, 0); // [obj][array][buffer] + duk_size_t bufLen; + char *buf = (char*)Duktape_GetBuffer(winIPC->ctx, -1, &bufLen); + duk_set_top(winIPC->ctx, top); // ... + ILibProcessPipe_Pipe_WriteEx(winIPC->mPipe, buf, (int)bufLen, winIPC, ILibDuktape_net_server_IPC_WriteCompletionEvent); + } +} +ILibTransport_DoneState ILibDuktape_net_server_IPC_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user) +{ + if (!ILibMemory_CanaryOK(user)) { return(ILibTransport_DoneState_ERROR); } + ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; + + duk_push_heapptr(winIPC->ctx, winIPC->object); // [obj] + duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array] + + + char *q = duk_push_fixed_buffer(winIPC->ctx, bufferLen); // [obj][array][buffer] + duk_size_t len = duk_get_length(winIPC->ctx, -2); + duk_put_prop_index(winIPC->ctx, -2, (duk_uarridx_t)len); // [obj][array] + memcpy_s(q, bufferLen, buffer, bufferLen); + duk_pop_2(winIPC->ctx); // ... + + if (len == 0) + { + // No Pending Writes + ILibProcessPipe_Pipe_WriteEx(winIPC->mPipe, q, bufferLen, winIPC, ILibDuktape_net_server_IPC_WriteCompletionEvent); + } + + return(ILibTransport_DoneState_INCOMPLETE); +} +void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void *user) +{ + if (!ILibMemory_CanaryOK(user)) { return; } + ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; + + ILibProcessPipe_FreePipe(winIPC->mPipe); + winIPC->mPipe = NULL; +} +BOOL ILibDuktape_net_server_IPC_ConnectSink(HANDLE event, ILibWaitHandle_ErrorStatus status, void* user) +{ + if (ILibMemory_CanaryOK(user)) + { + ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; + ILibDuktape_EventEmitter_SetupEmit(winIPC->ctx, winIPC->object, "connection"); // [emit][this][connection] + duk_push_object(winIPC->ctx); // [emit][this][connection][socket] + ILibDuktape_WriteID(winIPC->ctx, "net.socket.ipc"); + duk_push_array(winIPC->ctx); duk_put_prop_string(winIPC->ctx, -2, ILibDuktape_net_WindowsIPC_PendingArray); + winIPC->mSocket = duk_get_heapptr(winIPC->ctx, -1); + winIPC->ds = ILibDuktape_DuplexStream_InitEx(winIPC->ctx, ILibDuktape_net_server_IPC_WriteSink, ILibDuktape_net_server_IPC_EndSink, ILibDuktape_net_server_IPC_PauseSink, ILibDuktape_net_server_IPC_ResumeSink, ILibDuktape_net_server_IPC_unshiftSink, winIPC); + winIPC->mPipe = ILibProcessPipe_Pipe_CreateFromExisting(winIPC->manager, winIPC->mPipeHandle, ILibProcessPipe_Pipe_ReaderHandleType_Overlapped); + + if (duk_pcall_method(winIPC->ctx, 2) != 0) + { + ILibDuktape_Process_UncaughtExceptionEx(winIPC->ctx, "Error emitting net.socket.ipc.connection"); + } + duk_pop(winIPC->ctx); + } + return(FALSE); +} +#endif + duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx) { int nargs = duk_get_top(ctx); @@ -762,15 +948,75 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx) } } - if (ipc != NULL) + if (ipc != NULL && port == 0) { -#ifdef _POSIX +#if defined(_POSIX) if (ipcLen > sizeof(ipcaddr.sun_path)) { return(ILibDuktape_Error(ctx, "Path too long")); } ipcaddr.sun_family = AF_UNIX; strcpy_s((char*)(ipcaddr.sun_path), sizeof(ipcaddr.sun_path), ipc); server->server = ILibCreateAsyncServerSocketModuleWithMemoryEx(Duktape_GetChain(ctx), maxConnections, initalBufferSize, (struct sockaddr*)&ipcaddr, ILibDuktape_net_server_OnConnect, ILibDuktape_net_server_OnDisconnect, ILibDuktape_net_server_OnReceive, ILibDuktape_net_server_OnInterrupt, ILibDuktape_net_server_OnSendOK, sizeof(void*), sizeof(void*)); +#elif defined(WIN32) + // IPC on Windows Implemented as Named Pipe + + SECURITY_ATTRIBUTES IPC_SA = { 0 }; + SECURITY_ATTRIBUTES *pIPC_SA = &IPC_SA; + PACL IPC_ACL; + SECURITY_DESCRIPTOR IPC_SD; + EXPLICIT_ACCESS IPC_EA = { 0 }; + + duk_push_this(ctx); + ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_net_WindowsIPC)); + duk_put_prop_string(ctx, -2, ILibDuktape_net_WindowsIPC_Buffer); + winIPC->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + duk_eval_string(ctx, "require('child_process');"); + winIPC->manager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager); + duk_pop(ctx); + + if (Duktape_GetBooleanProperty(ctx, 0, "writableAll", 0) != 0) + { + // World Writable, so we need to set the Security Descriptor to reflect that + IPC_EA.grfAccessMode = SET_ACCESS; + IPC_EA.grfInheritance = NO_INHERITANCE; + IPC_EA.grfAccessPermissions = FILE_GENERIC_READ | FILE_WRITE_DATA; + IPC_EA.Trustee.TrusteeForm = TRUSTEE_IS_NAME; + IPC_EA.Trustee.TrusteeType = TRUSTEE_IS_GROUP; + IPC_EA.Trustee.ptstrName = "EVERYONE"; + + SetEntriesInAcl(1, &IPC_EA, NULL, &IPC_ACL); + InitializeSecurityDescriptor(&IPC_SD, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(&IPC_SD, TRUE, IPC_ACL, FALSE); + + memset(&IPC_SA, 0, sizeof(SECURITY_ATTRIBUTES)); + IPC_SA.nLength = sizeof(SECURITY_ATTRIBUTES); + IPC_SA.bInheritHandle = FALSE; + IPC_SA.lpSecurityDescriptor = &IPC_SD; + } + else + { + // Default security is Read/Write for LocalSystem and owner, and Read for everybody else + pIPC_SA = NULL; + } + + winIPC->mPipeHandle = CreateNamedPipeA((LPCSTR)ipc, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_REJECT_REMOTE_CLIENTS, + 1, ILibDuktape_net_IPC_BUFFERSIZE, ILibDuktape_net_IPC_BUFFERSIZE, 0, pIPC_SA); + if (winIPC->mPipeHandle == INVALID_HANDLE_VALUE) + { + CloseHandle(winIPC->overlapped.hEvent); + duk_del_prop_string(ctx, -1, ILibDuktape_net_WindowsIPC_Buffer); + return(ILibDuktape_Error(ctx, "Error Creating Named Pipe: %s", ipc)); + } + winIPC->ctx = ctx; + winIPC->object = duk_get_heapptr(ctx, -1); + + ConnectNamedPipe(winIPC->mPipeHandle, &winIPC->overlapped); + ILibProcessPipe_WaitHandle_Add2(winIPC->manager, winIPC->overlapped.hEvent, winIPC, ILibDuktape_net_server_IPC_ConnectSink); + + if (pIPC_SA != NULL) { LocalFree(IPC_ACL); } + return(1); #endif } else @@ -828,7 +1074,8 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx) ignore_result(backlog); #endif - return 0; + duk_push_this(ctx); + return 1; } duk_ret_t ILibDuktape_net_server_Finalizer(duk_context *ctx) { diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c index ae68561..b663a0e 100644 --- a/microstack/ILibProcessPipe.c +++ b/microstack/ILibProcessPipe.c @@ -82,8 +82,8 @@ typedef struct ILibProcessPipe_PipeObject HANDLE mPipe_Reader_ResumeEvent; HANDLE mPipe_ReadEnd; HANDLE mPipe_WriteEnd; - struct _OVERLAPPED *mOverlapped; - void *mOverlapped_opaqueData; + OVERLAPPED *mOverlapped,*mwOverlapped; + void *mOverlapped_opaqueData, *user3, *user4; #else int mPipe_ReadEnd, mPipe_WriteEnd; #endif @@ -163,6 +163,14 @@ typedef struct ILibProcessPipe_WaitHandle int timeRemaining; int timeout; }ILibProcessPipe_WaitHandle; +typedef struct ILibProcessPipe_WaitHandle_APC +{ + HANDLE callingThread; + HANDLE ev; + ILibWaitHandle_ErrorStatus status; + ILibProcessPipe_WaitHandle_Handler callback; + void *user; +}ILibProcessPipe_WaitHandle_APC; HANDLE ILibProcessPipe_Manager_GetWorkerThread(ILibProcessPipe_Manager mgr) { return(((ILibProcessPipe_Manager_Object*)mgr)->workerThread); @@ -236,6 +244,32 @@ void ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(ILibProcessPipe_Manager m ILibProcessPipe_WaitHandle_AddEx(mgr, waitHandle); } +void __stdcall ILibProcessPipe_WaitHandle_Add2_apcsink(ULONG_PTR obj) +{ + if (ILibMemory_CanaryOK((void*)obj)) + { + ILibProcessPipe_WaitHandle_APC *apcState = (ILibProcessPipe_WaitHandle_APC*)obj; + if (apcState->callback != NULL) { apcState->callback(apcState->ev, apcState->status, apcState->user); } + ILibMemory_Free(apcState); + } +} +BOOL ILibProcessPipe_WaitHandle_Add2_sink(HANDLE event, ILibWaitHandle_ErrorStatus status, void* user) +{ + if (ILibMemory_CanaryOK(user)) + { + QueueUserAPC((PAPCFUNC)ILibProcessPipe_WaitHandle_Add2_apcsink, ((ILibProcessPipe_WaitHandle_APC*)user)->callingThread, (ULONG_PTR)user); + } + return(FALSE); +} +void ILibProcessPipe_WaitHandle_Add2_WithNonZeroTimeout(ILibProcessPipe_Manager mgr, HANDLE event, int milliseconds, void *user, ILibProcessPipe_WaitHandle_Handler callback) +{ + ILibProcessPipe_WaitHandle_APC *apcState = ILibMemory_SmartAllocate(sizeof(ILibProcessPipe_WaitHandle_APC)); + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &apcState->callingThread, THREAD_SET_CONTEXT, FALSE, 0); + apcState->callback = callback; + apcState->user = user; + ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(mgr, event, milliseconds, apcState, ILibProcessPipe_WaitHandle_Add2_sink); +} + void ILibProcessPipe_Manager_WindowsRunLoopEx(void *arg) { ILibProcessPipe_Manager_Object *manager = (ILibProcessPipe_Manager_Object*)arg; @@ -518,7 +552,7 @@ void ILibProcessPipe_FreePipe(ILibProcessPipe_PipeObject *pipeObject) #ifdef WIN32 if (pipeObject->mPipe_ReadEnd != NULL) { CloseHandle(pipeObject->mPipe_ReadEnd); } - if (pipeObject->mPipe_WriteEnd != NULL) { CloseHandle(pipeObject->mPipe_WriteEnd); } + if (pipeObject->mPipe_WriteEnd != NULL && pipeObject->mPipe_WriteEnd != pipeObject->mPipe_ReadEnd) { CloseHandle(pipeObject->mPipe_WriteEnd); } if (pipeObject->mOverlapped != NULL) { CloseHandle(pipeObject->mOverlapped->hEvent); free(pipeObject->mOverlapped); } if (pipeObject->mPipe_Reader_ResumeEvent != NULL) { CloseHandle(pipeObject->mPipe_Reader_ResumeEvent); } #endif @@ -565,9 +599,10 @@ ILibProcessPipe_Pipe ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(ILib #ifdef WIN32 if (handleType == ILibProcessPipe_Pipe_ReaderHandleType_Overlapped) { - if ((retVal->mOverlapped = (struct _OVERLAPPED*)malloc(sizeof(struct _OVERLAPPED))) == NULL) { ILIBCRITICALEXIT(254); } - memset(retVal->mOverlapped, 0, sizeof(struct _OVERLAPPED)); + void *tmpExtra; + retVal->mOverlapped = (OVERLAPPED*)ILibMemory_Allocate(sizeof(OVERLAPPED), sizeof(void*), NULL, &tmpExtra); if ((retVal->mOverlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { ILIBCRITICALEXIT(254); } + ((void**)tmpExtra)[0] = retVal; } #else fcntl(existingPipe, F_SETFL, O_NONBLOCK); @@ -1555,16 +1590,22 @@ ILibTransport_DoneState ILibProcessPipe_Pipe_Write(ILibProcessPipe_Pipe po, char } else { + if (pipeObject->manager != NULL) + { #ifdef WIN32 - ILibRemoteLogging_printf(ILibChainGetLogger(pipeObject->manager->ChainLink.ParentChain), ILibRemoteLogging_Modules_Microstack_Pipe, ILibRemoteLogging_Flags_VerbosityLevel_1, "ILibProcessPipe[Write]: BrokenPipe(%d) on Pipe: %p", GetLastError(), (void*)pipeObject); + ILibRemoteLogging_printf(ILibChainGetLogger(pipeObject->manager->ChainLink.ParentChain), ILibRemoteLogging_Modules_Microstack_Pipe, ILibRemoteLogging_Flags_VerbosityLevel_1, "ILibProcessPipe[Write]: BrokenPipe(%d) on Pipe: %p", GetLastError(), (void*)pipeObject); #else - ILibRemoteLogging_printf(ILibChainGetLogger(pipeObject->manager->ChainLink.ParentChain), ILibRemoteLogging_Modules_Microstack_Pipe, ILibRemoteLogging_Flags_VerbosityLevel_1, "ILibProcessPipe[Write]: BrokenPipe(%d) on Pipe: %p", result < 0 ? errno : 0, (void*)pipeObject); + ILibRemoteLogging_printf(ILibChainGetLogger(pipeObject->manager->ChainLink.ParentChain), ILibRemoteLogging_Modules_Microstack_Pipe, ILibRemoteLogging_Flags_VerbosityLevel_1, "ILibProcessPipe[Write]: BrokenPipe(%d) on Pipe: %p", result < 0 ? errno : 0, (void*)pipeObject); #endif + } ILibQueue_UnLock(pipeObject->WriteBuffer); if (pipeObject->brokenPipeHandler != NULL) { #ifdef WIN32 - ILibProcessPipe_WaitHandle_Remove(pipeObject->manager, pipeObject->mOverlapped->hEvent); // Pipe Broken, so remove ourselves from the processing loop + if (pipeObject->manager != NULL) + { + ILibProcessPipe_WaitHandle_Remove(pipeObject->manager, pipeObject->mOverlapped->hEvent); // Pipe Broken, so remove ourselves from the processing loop + } #endif ((ILibProcessPipe_GenericBrokenPipeHandler)pipeObject->brokenPipeHandler)(pipeObject); } @@ -1602,6 +1643,44 @@ void ILibProcessPipe_Pipe_AddPipeReadHandler(ILibProcessPipe_Pipe targetPipe, in ILibProcessPipe_Process_StartPipeReader(targetPipe, bufferSize, &ILibProcessPipe_Pipe_ReadSink, targetPipe, OnReadHandler); } #ifdef WIN32 +void __stdcall ILibProcessPipe_Pipe_Read_CompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) +{ + ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)((void**)ILibMemory_GetExtraMemory(lpOverlapped, sizeof(OVERLAPPED)))[0]; + if (!ILibMemory_CanaryOK(j)) { return; } + + ILibProcessPipe_Pipe_ReadExHandler callback = (ILibProcessPipe_Pipe_ReadExHandler)j->user2; + if (callback != NULL) { callback(j, j->user1, dwErrorCode, j->buffer, dwNumberOfBytesTransfered); } +} +void __stdcall ILibProcessPipe_Pipe_Write_CompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) +{ + ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)((void**)ILibMemory_GetExtraMemory(lpOverlapped, sizeof(OVERLAPPED)))[0]; + if (!ILibMemory_CanaryOK(j)) { return; } + + if (j->user4 != NULL) + { + ((ILibProcessPipe_Pipe_WriteExHandler)j->user4)(j, j->user3, dwErrorCode, dwNumberOfBytesTransfered); + } +} +void ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_ReadExHandler OnReadHandler) +{ + ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)targetPipe; + j->buffer = buffer; + j->bufferSize = bufferLength; + j->user1 = user; + j->user2 = OnReadHandler; + ReadFileEx(j->mPipe_ReadEnd, j->buffer, j->bufferSize, j->mOverlapped, ILibProcessPipe_Pipe_Read_CompletionRoutine); +} +void ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_WriteExHandler OnWriteHandler) +{ + ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)targetPipe; + if (j->mwOverlapped == NULL) + { + j->mwOverlapped = (OVERLAPPED*)ILibMemory_Allocate(sizeof(OVERLAPPED), 0, NULL, NULL); + } + j->user3 = user; + j->user4 = OnWriteHandler; + WriteFileEx(j->mPipe_WriteEnd, buffer, bufferLength, j->mwOverlapped, ILibProcessPipe_Pipe_Write_CompletionRoutine); +} DWORD ILibProcessPipe_Process_GetPID(ILibProcessPipe_Process p) { return(p != NULL ? (DWORD)((ILibProcessPipe_Process_Object*)p)->PID : 0); } #else pid_t ILibProcessPipe_Process_GetPID(ILibProcessPipe_Process p) { return(p != NULL ? (pid_t)((ILibProcessPipe_Process_Object*)p)->PID : 0); } diff --git a/microstack/ILibProcessPipe.h b/microstack/ILibProcessPipe.h index 7710f72..b12e973 100644 --- a/microstack/ILibProcessPipe.h +++ b/microstack/ILibProcessPipe.h @@ -44,6 +44,8 @@ typedef enum ILibProcessPipe_SpawnTypes }ILibProcessPipe_SpawnTypes; #ifdef WIN32 +typedef void(*ILibProcessPipe_Pipe_ReadExHandler)(ILibProcessPipe_Pipe sender, void *user, DWORD errorCode, char *buffer, int bufferLen); +typedef void(*ILibProcessPipe_Pipe_WriteExHandler)(ILibProcessPipe_Pipe sender, void *user, DWORD errorCode, int bytesWritten); typedef enum ILibProcessPipe_Pipe_ReaderHandleType { ILibProcessPipe_Pipe_ReaderHandleType_NotOverLapped = 0, //!< Spawn a I/O processing thread @@ -55,6 +57,8 @@ HANDLE ILibProcessPipe_Manager_GetWorkerThread(ILibProcessPipe_Manager mgr); ILibTransport_DoneState ILibProcessPipe_Pipe_Write(ILibProcessPipe_Pipe writePipe, char* buffer, int bufferLen, ILibTransport_MemoryOwnership ownership); void ILibProcessPipe_Pipe_AddPipeReadHandler(ILibProcessPipe_Pipe targetPipe, int bufferSize, ILibProcessPipe_Pipe_ReadHandler OnReadHandler); #ifdef WIN32 + void ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_ReadExHandler OnReadHandler); + void ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_WriteExHandler OnWriteHandler); ILibProcessPipe_Pipe ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(ILibProcessPipe_Manager manager, HANDLE existingPipe, ILibProcessPipe_Pipe_ReaderHandleType handleType, int extraMemorySize); #define ILibProcessPipe_Pipe_CreateFromExisting(PipeManager, ExistingPipe, HandleType) ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(PipeManager, ExistingPipe, HandleType, 0) #else @@ -100,6 +104,9 @@ typedef BOOL(*ILibProcessPipe_WaitHandle_Handler)(HANDLE event, ILibWaitHandle_E void ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(ILibProcessPipe_Manager mgr, HANDLE event, int milliseconds, void *user, ILibProcessPipe_WaitHandle_Handler callback); #define ILibProcessPipe_WaitHandle_Add(processPipeManager, eventHandle, user, callback) ILibProcessPipe_WaitHandle_Add_WithNonZeroTimeout(processPipeManager, eventHandle, 0, user, callback) void ILibProcessPipe_WaitHandle_Remove(ILibProcessPipe_Manager mgr, HANDLE event); +void ILibProcessPipe_WaitHandle_Add2_WithNonZeroTimeout(ILibProcessPipe_Manager mgr, HANDLE event, int milliseconds, void *user, ILibProcessPipe_WaitHandle_Handler callback); +#define ILibProcessPipe_WaitHandle_Add2(processPipeManager, eventHandle, user, callback) ILibProcessPipe_WaitHandle_Add2_WithNonZeroTimeout(processPipeManager, eventHandle, 0, user, callback) + #endif #define ILibTransports_ProcessPipe 0x60 #endif From 8c6a230d1eea71584d51a23b058865436963a2fe Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Tue, 30 Apr 2019 15:15:20 -0700 Subject: [PATCH 02/12] 1. Fixed bug with createConnection() 2. Updated Windows IPC --- meshcore/agentcore.h | 2 +- microscript/ILibDuktape_net.c | 133 ++++++++++++++++++++++++++++------ microstack/ILibProcessPipe.c | 4 +- 3 files changed, 113 insertions(+), 26 deletions(-) diff --git a/meshcore/agentcore.h b/meshcore/agentcore.h index 73a04e7..68c96e2 100644 --- a/meshcore/agentcore.h +++ b/meshcore/agentcore.h @@ -140,7 +140,7 @@ typedef enum MeshAgentHost_BatteryInfo extern char* MeshAgentHost_BatteryInfo_STRINGS[]; #ifdef WIN32 -typedef HRESULT (*DpiAwarenessFunc)(PROCESS_DPI_AWARENESS); +typedef HRESULT (__stdcall *DpiAwarenessFunc)(PROCESS_DPI_AWARENESS); #endif typedef struct MeshAgentHostContainer diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index a9972e9..c89faba 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -84,7 +84,7 @@ typedef struct ILibDuktape_net_WindowsIPC { ILibProcessPipe_Manager manager; duk_context *ctx; - void *object, *mSocket; + void *mServer, *mSocket; HANDLE mPipeHandle; ILibProcessPipe_Pipe mPipe; @@ -122,6 +122,15 @@ void ILibDuktape_net_socket_PUSH(duk_context *ctx, ILibAsyncSocket_SocketModule duk_ret_t ILibDuktape_tls_server_addContext(duk_context *ctx); #endif +#ifdef WIN32 +ILibTransport_DoneState ILibDuktape_net_server_IPC_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user); +void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void *user); +void ILibDuktape_net_server_IPC_PauseSink(ILibDuktape_DuplexStream *sender, void *user); +void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, void *user); +int ILibDuktape_net_server_IPC_unshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user); +#endif + + void ILibDuktape_net_socket_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffer, int *p_beginPointer, int endPointer, ILibAsyncSocket_OnInterrupt* OnInterrupt, void **user, int *PAUSE) { ILibDuktape_net_socket *ptrs = (ILibDuktape_net_socket*)((ILibChain_Link*)socketModule)->ExtraMemoryPtr; @@ -264,6 +273,43 @@ duk_ret_t ILibDuktape_net_socket_connect_errorDispatch(duk_context *ctx) duk_pop(ctx); // ... return(0); } +#ifdef WIN32 +void ILibDuktape_net_socket_ipc_error(duk_context *ctx, void ** args, int argsLen) +{ + ILibDuktape_net_WindowsIPC *winIPC = ((ILibDuktape_net_WindowsIPC**)args)[0]; + ILibDuktape_EventEmitter_SetupEmit(winIPC->ctx, winIPC->mSocket, "error"); // [emit][this][error] + duk_push_string(winIPC->ctx, "Error Connecting Named Pipe"); // [emit][this][error][err] + duk_pcall_method(winIPC->ctx, 2); duk_pop(winIPC->ctx); // ... +} +void ILibDuktape_net_Socket_ipc_dataHookCallbackCont(duk_context *ctx, void ** args, int argsLen) +{ + ILibDuktape_EventEmitter *emitter = (ILibDuktape_EventEmitter*)args[0]; + + duk_push_heapptr(emitter->ctx, emitter->object); // [stream] + duk_get_prop_string(emitter->ctx, -1, "resume"); // [stream][resume] + duk_dup(emitter->ctx, -2); // [stream][resume][this] + duk_pcall_method(emitter->ctx, 0); + duk_pop(emitter->ctx); // ... +} +void ILibDuktape_net_socket_ipc_dataHookCallback(ILibDuktape_EventEmitter *sender, char *eventName, void *hookedCallback) +{ + if (ILibDuktape_EventEmitter_HasListeners(sender, "data") == 0) + { + int top = duk_get_top(sender->ctx); + duk_push_heapptr(sender->ctx, sender->object); // [stream] + duk_get_prop_string(sender->ctx, -1, "isPaused"); // [stream][isPaused] + duk_dup(sender->ctx, -2); // [stream][isPaused][this] + if (duk_pcall_method(sender->ctx, 0) == 0) + { + if (duk_get_boolean(sender->ctx, -1)) // [stream][bool] + { + ILibDuktape_Immediate(sender->ctx, (void**)&sender, 1, ILibDuktape_net_Socket_ipc_dataHookCallbackCont); + } + } + duk_set_top(sender->ctx, top); + } +} +#endif duk_ret_t ILibDuktape_net_socket_connect(duk_context *ctx) { int nargs = duk_get_top(ctx); @@ -309,9 +355,44 @@ duk_ret_t ILibDuktape_net_socket_connect(duk_context *ctx) } if (duk_is_string(ctx, 0) || (pathLen > 0 && port == 0)) { - // This is a PATH string (Domain Socket) -#ifndef _POSIX - //return(ILibDuktape_Error(ctx, "AF_UNIX sockets not supported on this platform")); + // This is a PATH string (Domain Socket on Linux/MacOS, Named Pipe on Windows) +#ifdef WIN32 + duk_push_this(ctx); + duk_push_array(ctx); duk_put_prop_string(ctx, -2, ILibDuktape_net_WindowsIPC_PendingArray); + ILibDuktape_WriteID(ctx, "net.socket.ipc"); + + ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_net_WindowsIPC)); + duk_put_prop_string(ctx, -2, ILibDuktape_net_WindowsIPC_Buffer); + winIPC->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + winIPC->ctx = ctx; + winIPC->mSocket = duk_get_heapptr(ctx, -1); + + duk_eval_string(ctx, "require('child_process');"); + winIPC->manager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager); + duk_pop(ctx); + + if ((winIPC->mPipeHandle = CreateFileA(path, GENERIC_READ | FILE_WRITE_DATA, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0)) == INVALID_HANDLE_VALUE) + { + // We'll emit the 'error' event on the next event loop, becuase if 'createConnection' was called, there is no way the event listener is set yet + ILibDuktape_Immediate(ctx, (void**)&winIPC, 1, ILibDuktape_net_socket_ipc_error); + } + else + { + // SUCCESS + winIPC->ds = ILibDuktape_DuplexStream_InitEx(winIPC->ctx, ILibDuktape_net_server_IPC_WriteSink, ILibDuktape_net_server_IPC_EndSink, ILibDuktape_net_server_IPC_PauseSink, ILibDuktape_net_server_IPC_ResumeSink, ILibDuktape_net_server_IPC_unshiftSink, winIPC); + winIPC->mPipe = ILibProcessPipe_Pipe_CreateFromExisting(winIPC->manager, winIPC->mPipeHandle, ILibProcessPipe_Pipe_ReaderHandleType_Overlapped); + winIPC->ds->readableStream->paused = 1; + ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "data", ILibDuktape_net_socket_ipc_dataHookCallback); + + ILibDuktape_EventEmitter_SetupEmit(winIPC->ctx, winIPC->mSocket, "connect"); //[emit][this][connect] + if (duk_pcall_method(winIPC->ctx, 1) != 0) + { + ILibDuktape_Process_UncaughtExceptionEx(winIPC->ctx, "Error in net.socket.connect.onConnect(): "); + } + duk_pop(winIPC->ctx); + } + + return(1); #else if (pathLen > 0) @@ -559,6 +640,7 @@ duk_ret_t ILibDuktape_net_createConnection(duk_context *ctx) void *net; ILibAsyncSocket_SocketModule sm; ILibDuktape_net_socket *ptrs; + int nargs = duk_get_top(ctx), i; duk_push_this(ctx); // [net] duk_get_prop_string(ctx, -1, "chain"); // [net][chain] @@ -570,20 +652,19 @@ duk_ret_t ILibDuktape_net_createConnection(duk_context *ctx) ptrs = (ILibDuktape_net_socket*)((ILibChain_Link*)sm)->ExtraMemoryPtr; ptrs->net = net; - duk_push_pointer(ctx, ptrs); // [net][ptrs] - duk_put_prop_string(ctx, -2, ILibDuktape_net_socket_ptr); // [net] - - ILibDuktape_net_socket_PUSH(ctx, sm); - - ILibDuktape_net_socket_connect(ctx); - duk_push_this(ctx); - duk_del_prop_string(ctx, -1, ILibDuktape_net_socket_ptr); - duk_push_heapptr(ctx, ptrs->object); + ILibDuktape_net_socket_PUSH(ctx, sm); // [net][socket] + duk_get_prop_string(ctx, -1, "connect"); // [net][socket][connect] + duk_dup(ctx, -2); // [net][socket][connect][this] + for (i = 0; i < nargs; ++i) + { + duk_dup(ctx, i); // [net][socket][connect][this][...args...] + } + duk_call_method(ctx, nargs); duk_pop(ctx); // [net][socket] if (duk_is_object(ctx, 0)) { - duk_dup(ctx, 0); - duk_put_prop_string(ctx, -2, ILibDuktape_SOCKET2OPTIONS); - } + duk_dup(ctx, 0); // [net][socket][options] + duk_put_prop_string(ctx, -2, ILibDuktape_SOCKET2OPTIONS); // [net][socket] + } return 1; } @@ -740,7 +821,8 @@ void ILibDuktape_net_server_IPC_readsink(ILibProcessPipe_Pipe sender, void *user if (dwErrorCode == 0) { - ILibDuktape_DuplexStream_WriteData(winIPC->ds, buffer, bufferLen); + winIPC->bytesLeft += bufferLen; + ILibDuktape_net_server_IPC_ResumeSink(winIPC->ds, winIPC); } else { @@ -800,7 +882,7 @@ void ILibDuktape_net_server_IPC_WriteCompletionEvent(ILibProcessPipe_Pipe sender ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; duk_idx_t top = duk_get_top(winIPC->ctx); - duk_push_heapptr(winIPC->ctx, winIPC->object); // [obj] + duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj] duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array] duk_get_prop_string(winIPC->ctx, -1, "shift"); // [obj][array][shift] duk_dup(winIPC->ctx, -2); // [obj][array][shift][this] @@ -826,7 +908,7 @@ ILibTransport_DoneState ILibDuktape_net_server_IPC_WriteSink(ILibDuktape_DuplexS if (!ILibMemory_CanaryOK(user)) { return(ILibTransport_DoneState_ERROR); } ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; - duk_push_heapptr(winIPC->ctx, winIPC->object); // [obj] + duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj] duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_PendingArray); // [obj][array] @@ -857,13 +939,15 @@ BOOL ILibDuktape_net_server_IPC_ConnectSink(HANDLE event, ILibWaitHandle_ErrorSt if (ILibMemory_CanaryOK(user)) { ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; - ILibDuktape_EventEmitter_SetupEmit(winIPC->ctx, winIPC->object, "connection"); // [emit][this][connection] + ILibDuktape_EventEmitter_SetupEmit(winIPC->ctx, winIPC->mServer, "connection"); // [emit][this][connection] duk_push_object(winIPC->ctx); // [emit][this][connection][socket] ILibDuktape_WriteID(winIPC->ctx, "net.socket.ipc"); duk_push_array(winIPC->ctx); duk_put_prop_string(winIPC->ctx, -2, ILibDuktape_net_WindowsIPC_PendingArray); winIPC->mSocket = duk_get_heapptr(winIPC->ctx, -1); winIPC->ds = ILibDuktape_DuplexStream_InitEx(winIPC->ctx, ILibDuktape_net_server_IPC_WriteSink, ILibDuktape_net_server_IPC_EndSink, ILibDuktape_net_server_IPC_PauseSink, ILibDuktape_net_server_IPC_ResumeSink, ILibDuktape_net_server_IPC_unshiftSink, winIPC); winIPC->mPipe = ILibProcessPipe_Pipe_CreateFromExisting(winIPC->manager, winIPC->mPipeHandle, ILibProcessPipe_Pipe_ReaderHandleType_Overlapped); + winIPC->ds->readableStream->paused = 1; + ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "data", ILibDuktape_net_socket_ipc_dataHookCallback); if (duk_pcall_method(winIPC->ctx, 2) != 0) { @@ -970,7 +1054,10 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx) ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_net_WindowsIPC)); duk_put_prop_string(ctx, -2, ILibDuktape_net_WindowsIPC_Buffer); winIPC->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - + winIPC->ctx = ctx; + winIPC->mServer = duk_get_heapptr(ctx, -1); + + duk_eval_string(ctx, "require('child_process');"); winIPC->manager = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager); duk_pop(ctx); @@ -1009,9 +1096,7 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx) duk_del_prop_string(ctx, -1, ILibDuktape_net_WindowsIPC_Buffer); return(ILibDuktape_Error(ctx, "Error Creating Named Pipe: %s", ipc)); } - winIPC->ctx = ctx; - winIPC->object = duk_get_heapptr(ctx, -1); - + ConnectNamedPipe(winIPC->mPipeHandle, &winIPC->overlapped); ILibProcessPipe_WaitHandle_Add2(winIPC->manager, winIPC->overlapped.hEvent, winIPC, ILibDuktape_net_server_IPC_ConnectSink); diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c index b663a0e..e75d0fc 100644 --- a/microstack/ILibProcessPipe.c +++ b/microstack/ILibProcessPipe.c @@ -1675,7 +1675,9 @@ void ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)targetPipe; if (j->mwOverlapped == NULL) { - j->mwOverlapped = (OVERLAPPED*)ILibMemory_Allocate(sizeof(OVERLAPPED), 0, NULL, NULL); + void **extra; + j->mwOverlapped = (OVERLAPPED*)ILibMemory_Allocate(sizeof(OVERLAPPED), sizeof(void*), NULL, (void**)&extra); + extra[0] = j; } j->user3 = user; j->user4 = OnWriteHandler; From 9319b61bfa834771ae6f26cbad4bdfc7ffb17844 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 1 May 2019 16:10:11 -0700 Subject: [PATCH 03/12] Fixed bug with ReallocRaw macro, if the memoy location moves --- microstack/ILibParsers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microstack/ILibParsers.h b/microstack/ILibParsers.h index 172a9e5..a1f6175 100644 --- a/microstack/ILibParsers.h +++ b/microstack/ILibParsers.h @@ -385,7 +385,7 @@ int ILibIsRunningOnChainThread(void* chain); void* ILibMemory_AllocateA_Init(void *buffer); #define ILibMemory_AllocateRaw(memPtr, memSize) if((memPtr = malloc(memSize)) == NULL) {ILIBCRITICALEXIT(254);} -#define ILibMemory_ReallocateRaw(memPtr, memSize) if((memPtr = realloc(memPtr, memSize)) == NULL) {ILIBCRITICALEXIT(254);} +#define ILibMemory_ReallocateRaw(ppMemory, memSize) if(((*ppMemory) = realloc(*ppMemory, memSize)) == NULL) {ILIBCRITICALEXIT(254);} void* ILibMemory_Allocate(int containerSize, int extraMemorySize, void** allocatedContainer, void **extraMemory); int ILibMemory_GetExtraMemorySize(void* extraMemory); From 40b3ca4d03e848ca3a1c84ecf6787c836a3aae5e Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 1 May 2019 16:10:58 -0700 Subject: [PATCH 04/12] 1. Added CancelEx 2. Updated, so if ReadEx is used, buffer is not freed directly --- microstack/ILibProcessPipe.c | 13 ++++++++++++- microstack/ILibProcessPipe.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c index e75d0fc..634455d 100644 --- a/microstack/ILibProcessPipe.c +++ b/microstack/ILibProcessPipe.c @@ -79,6 +79,7 @@ typedef struct ILibProcessPipe_PipeObject ILibProcessPipe_GenericBrokenPipeHandler brokenPipeHandler; void *user1, *user2; #ifdef WIN32 + int usingCompletionRoutine; HANDLE mPipe_Reader_ResumeEvent; HANDLE mPipe_ReadEnd; HANDLE mPipe_WriteEnd; @@ -554,10 +555,13 @@ void ILibProcessPipe_FreePipe(ILibProcessPipe_PipeObject *pipeObject) if (pipeObject->mPipe_ReadEnd != NULL) { CloseHandle(pipeObject->mPipe_ReadEnd); } if (pipeObject->mPipe_WriteEnd != NULL && pipeObject->mPipe_WriteEnd != pipeObject->mPipe_ReadEnd) { CloseHandle(pipeObject->mPipe_WriteEnd); } if (pipeObject->mOverlapped != NULL) { CloseHandle(pipeObject->mOverlapped->hEvent); free(pipeObject->mOverlapped); } + if (pipeObject->mwOverlapped != NULL) { free(pipeObject->mwOverlapped); } if (pipeObject->mPipe_Reader_ResumeEvent != NULL) { CloseHandle(pipeObject->mPipe_Reader_ResumeEvent); } + if (pipeObject->buffer != NULL && pipeObject->usingCompletionRoutine == 0) { free(pipeObject->buffer); } +#else + if (pipeObject->buffer != NULL) { free(pipeObject->buffer); } #endif - if (pipeObject->buffer != NULL) { free(pipeObject->buffer); } if (pipeObject->WriteBuffer != NULL) { ILibProcessPipe_WriteData* data; @@ -1661,9 +1665,16 @@ void __stdcall ILibProcessPipe_Pipe_Write_CompletionRoutine(DWORD dwErrorCode, D ((ILibProcessPipe_Pipe_WriteExHandler)j->user4)(j, j->user3, dwErrorCode, dwNumberOfBytesTransfered); } } +int ILibProcessPipe_Pipe_CancelEx(ILibProcessPipe_Pipe targetPipe) +{ + ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)targetPipe; + if (!ILibMemory_CanaryOK(j) || j->mPipe_ReadEnd == NULL) { return(2); } + return(CancelIoEx(j->mPipe_ReadEnd, NULL)); +} void ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_ReadExHandler OnReadHandler) { ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)targetPipe; + j->usingCompletionRoutine = 1; j->buffer = buffer; j->bufferSize = bufferLength; j->user1 = user; diff --git a/microstack/ILibProcessPipe.h b/microstack/ILibProcessPipe.h index b12e973..b5f01e1 100644 --- a/microstack/ILibProcessPipe.h +++ b/microstack/ILibProcessPipe.h @@ -57,6 +57,7 @@ HANDLE ILibProcessPipe_Manager_GetWorkerThread(ILibProcessPipe_Manager mgr); ILibTransport_DoneState ILibProcessPipe_Pipe_Write(ILibProcessPipe_Pipe writePipe, char* buffer, int bufferLen, ILibTransport_MemoryOwnership ownership); void ILibProcessPipe_Pipe_AddPipeReadHandler(ILibProcessPipe_Pipe targetPipe, int bufferSize, ILibProcessPipe_Pipe_ReadHandler OnReadHandler); #ifdef WIN32 + int ILibProcessPipe_Pipe_CancelEx(ILibProcessPipe_Pipe targetPipe); void ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_ReadExHandler OnReadHandler); void ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_WriteExHandler OnWriteHandler); ILibProcessPipe_Pipe ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(ILibProcessPipe_Manager manager, HANDLE existingPipe, ILibProcessPipe_Pipe_ReaderHandleType handleType, int extraMemorySize); From b9f18b9897208baedfc90c5a3eb98beab70d6575 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 1 May 2019 16:12:25 -0700 Subject: [PATCH 05/12] Added CreateFinalizerEx, where you can specify 'singleton' which clears any previously defined finalizers --- microscript/ILibDuktape_Helpers.c | 5 +++-- microscript/ILibDuktape_Helpers.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/microscript/ILibDuktape_Helpers.c b/microscript/ILibDuktape_Helpers.c index 511b8cf..0355814 100644 --- a/microscript/ILibDuktape_Helpers.c +++ b/microscript/ILibDuktape_Helpers.c @@ -574,9 +574,10 @@ duk_ret_t ILibDuktape_IndependentFinalizer_Dispatch(duk_context *ctx) return 0; } -void ILibDuktape_CreateFinalizer(duk_context *ctx, duk_c_function func) +void ILibDuktape_CreateFinalizerEx(duk_context *ctx, duk_c_function func, int singleton) { - ILibDuktape_EventEmitter_Create(ctx); + ILibDuktape_EventEmitter *e = ILibDuktape_EventEmitter_Create(ctx); + if (singleton != 0) { ILibDuktape_EventEmitter_RemoveAllListeners(e, "~"); } ILibDuktape_EventEmitter_PrependOnce(ctx, -1, "~", func); } duk_ret_t ILibDuktape_CreateProperty_InstanceMethod_Sink(duk_context *ctx) diff --git a/microscript/ILibDuktape_Helpers.h b/microscript/ILibDuktape_Helpers.h index 1fba350..f462c99 100644 --- a/microscript/ILibDuktape_Helpers.h +++ b/microscript/ILibDuktape_Helpers.h @@ -107,7 +107,8 @@ void ILibDuktape_CreateProperty_InstanceMethod(duk_context *ctx, char *methodNam void ILibDuktape_CreateProperty_InstanceMethodEx(duk_context *ctx, char *methodName, void *funcHeapPtr); void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName); #define ILibDuktape_CreateReadonlyProperty_int(ctx, propName, propValue) duk_push_int(ctx, propValue);ILibDuktape_CreateReadonlyProperty(ctx, propName) -void ILibDuktape_CreateFinalizer(duk_context *ctx, duk_c_function func); +void ILibDuktape_CreateFinalizerEx(duk_context *ctx, duk_c_function func, int singleton); +#define ILibDuktape_CreateFinalizer(ctx, func) ILibDuktape_CreateFinalizerEx(ctx, func, 0) void *ILibDuktape_Memory_Alloc(duk_context *ctx, duk_size_t size); void *ILibDuktape_Memory_AllocEx(duk_context *ctx, duk_idx_t index, duk_size_t size); From 014aa11ec02f48260ebba5e0b71cdf8ed3da740d Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 1 May 2019 16:12:59 -0700 Subject: [PATCH 06/12] Updated ReadableStream, so you can define it multiple times, such that the finalizer will not compound --- microscript/ILibDuktape_ReadableStream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microscript/ILibDuktape_ReadableStream.c b/microscript/ILibDuktape_ReadableStream.c index 6b1ed8d..feccf12 100644 --- a/microscript/ILibDuktape_ReadableStream.c +++ b/microscript/ILibDuktape_ReadableStream.c @@ -935,7 +935,7 @@ ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx, retVal->ResumeHandler = OnResume; retVal->UnshiftHandler = OnUnshift; sem_init(&(retVal->pipeLock), 0, 1); - ILibDuktape_CreateFinalizer(ctx, ILibDuktape_ReadableStream_PipeLockFinalizer); + ILibDuktape_CreateFinalizerEx(ctx, ILibDuktape_ReadableStream_PipeLockFinalizer, 1); retVal->emitter = emitter = ILibDuktape_EventEmitter_Create(ctx); ILibDuktape_EventEmitter_CreateEventEx(emitter, "end"); From 585595791b13f5cf5bbfe864e0e5f44b6a2e5e14 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 1 May 2019 16:13:27 -0700 Subject: [PATCH 07/12] Updated to use revices ReAlloc Macro --- microscript/ILibDuktape_HttpStream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microscript/ILibDuktape_HttpStream.c b/microscript/ILibDuktape_HttpStream.c index 55fb60a..df6103b 100644 --- a/microscript/ILibDuktape_HttpStream.c +++ b/microscript/ILibDuktape_HttpStream.c @@ -1045,7 +1045,7 @@ void ILibDuktape_HttpStream_http_request_transform(struct ILibDuktape_Transform if (bufferLen > 0) { ILibDuktape_readableStream_WriteData(sender->target, buffer, bufferLen); - ILibMemory_ReallocateRaw(data->buffer, data->bufferLen + bufferLen); + ILibMemory_ReallocateRaw(&(data->buffer), data->bufferLen + bufferLen); memcpy_s(data->buffer + data->bufferLen, bufferLen, buffer, bufferLen); data->bufferLen = data->bufferLen + bufferLen; } From 6f1e1c4d9e9aae87d365882054549e6e249a00f4 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 1 May 2019 16:13:43 -0700 Subject: [PATCH 08/12] Updated Windows IPC --- microscript/ILibDuktape_net.c | 94 +++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index c89faba..aa512ae 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -96,7 +96,7 @@ typedef struct ILibDuktape_net_WindowsIPC int bufferLength; int bufferOffset; int bytesLeft; - + int unshiftedBytes; }ILibDuktape_net_WindowsIPC; #endif @@ -128,6 +128,7 @@ void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void * void ILibDuktape_net_server_IPC_PauseSink(ILibDuktape_DuplexStream *sender, void *user); void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, void *user); int ILibDuktape_net_server_IPC_unshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user); +duk_ret_t ILibDuktape_net_server_IPC_ConnectSink_Finalizer(duk_context *ctx); #endif @@ -385,6 +386,8 @@ duk_ret_t ILibDuktape_net_socket_connect(duk_context *ctx) ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "data", ILibDuktape_net_socket_ipc_dataHookCallback); ILibDuktape_EventEmitter_SetupEmit(winIPC->ctx, winIPC->mSocket, "connect"); //[emit][this][connect] + ILibDuktape_EventEmitter_PrependOnce(winIPC->ctx, -2, "~", ILibDuktape_net_server_IPC_ConnectSink_Finalizer); + if (duk_pcall_method(winIPC->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(winIPC->ctx, "Error in net.socket.connect.onConnect(): "); @@ -809,9 +812,7 @@ int ILibDuktape_net_server_IPC_unshiftSink(ILibDuktape_DuplexStream *sender, int { ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; if (!ILibMemory_CanaryOK(user)) { return(0); } - - winIPC->bufferOffset += (winIPC->bytesLeft - unshiftBytes); - winIPC->bytesLeft = unshiftBytes; + winIPC->unshiftedBytes = unshiftBytes; return(unshiftBytes); } void ILibDuktape_net_server_IPC_readsink(ILibProcessPipe_Pipe sender, void *user, DWORD dwErrorCode, char *buffer, int bufferLen) @@ -827,6 +828,22 @@ void ILibDuktape_net_server_IPC_readsink(ILibProcessPipe_Pipe sender, void *user else { ILibDuktape_DuplexStream_Closed(winIPC->ds); + ILibProcessPipe_FreePipe(winIPC->mPipe); + winIPC->mPipe = NULL; + + if (winIPC->mServer != NULL) + { + // Server IPC, so we can create a new Instance, and listen for a connection + duk_context *ctx = winIPC->ctx; // We need to dereference this, because winIPC will go out of scope when we call listen + CloseHandle(winIPC->overlapped.hEvent); + if (winIPC->buffer != NULL) { free(winIPC->buffer); winIPC->buffer = NULL; } + + duk_push_heapptr(ctx, winIPC->mServer); // [server] + duk_get_prop_string(ctx, -1, "listen"); // [server][listen] + duk_swap_top(ctx, -2); // [listen][this] + duk_get_prop_string(ctx, -1, ILibDuktape_SERVER2LISTENOPTIONS); // [listen][this][options] + duk_pcall_method(ctx, 1); duk_pop(ctx); // ... + } } } void ILibDuktape_net_server_IPC_PauseSink(ILibDuktape_DuplexStream *sender, void *user) @@ -856,19 +873,32 @@ void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, voi else { // Check to see if we can drain any of the buffer first - int tmpBytesLeft; while (winIPC->ds->readableStream->paused == 0) { - tmpBytesLeft = winIPC->bytesLeft; + winIPC->unshiftedBytes = 0; ILibDuktape_DuplexStream_WriteData(winIPC->ds, winIPC->buffer + winIPC->bufferOffset, winIPC->bytesLeft); - if (tmpBytesLeft == winIPC->bytesLeft) { break; } // No Data was consumed - if (winIPC->bytesLeft <= 0) + if (winIPC->unshiftedBytes > 0) { - winIPC->bytesLeft = 0; - winIPC->bufferOffset = 0; + winIPC->bufferOffset += (winIPC->bytesLeft - winIPC->unshiftedBytes); + if (winIPC->bytesLeft == winIPC->unshiftedBytes) + { + winIPC->unshiftedBytes = 0; + } + winIPC->bytesLeft = winIPC->unshiftedBytes; } - if (winIPC->ds->readableStream->paused == 0 && (winIPC->bytesLeft == 0 || (winIPC->bytesLeft > 0 && tmpBytesLeft == winIPC->bytesLeft))) + else { + winIPC->bufferOffset = winIPC->bytesLeft = 0; + } + + if (winIPC->ds->readableStream->paused == 0 && (winIPC->bytesLeft == 0 || (winIPC->bytesLeft > 0 && winIPC->unshiftedBytes == 0))) + { + if (winIPC->bufferLength - winIPC->bufferOffset - winIPC->bytesLeft == 0) + { + // We need to grow the buffer + ILibMemory_ReallocateRaw(&(winIPC->buffer), winIPC->bufferLength + ILibDuktape_net_IPC_BUFFERSIZE); + winIPC->bufferLength += ILibDuktape_net_IPC_BUFFERSIZE; + } ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer + winIPC->bufferOffset + winIPC->bytesLeft, winIPC->bufferLength - winIPC->bufferOffset - winIPC->bytesLeft, winIPC, ILibDuktape_net_server_IPC_readsink); break; } @@ -878,7 +908,7 @@ void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, voi } void ILibDuktape_net_server_IPC_WriteCompletionEvent(ILibProcessPipe_Pipe sender, void *user, DWORD errorCode, int bytesWritten) { - if (!ILibMemory_CanaryOK(user)) { return; } + if (!ILibMemory_CanaryOK(user) || errorCode != 0) { return; } ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; duk_idx_t top = duk_get_top(winIPC->ctx); @@ -931,8 +961,37 @@ void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void * if (!ILibMemory_CanaryOK(user)) { return; } ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; - ILibProcessPipe_FreePipe(winIPC->mPipe); - winIPC->mPipe = NULL; + if (ILibProcessPipe_Pipe_CancelEx(winIPC->mPipe) == 0) + { + ILibProcessPipe_FreePipe(winIPC->mPipe); + winIPC->mPipe = NULL; + if (winIPC->mServer != NULL) + { + // Server IPC, so we can create a new Instance, and listen for a connection + duk_context *ctx = winIPC->ctx; // We need to dereference this, because winIPC will go out of scope when we call listen + CloseHandle(winIPC->overlapped.hEvent); + + duk_push_heapptr(ctx, winIPC->mServer); // [server] + duk_get_prop_string(ctx, -1, "listen"); // [server][listen] + duk_swap_top(ctx, -2); // [listen][this] + duk_get_prop_string(ctx, -1, ILibDuktape_SERVER2LISTENOPTIONS); // [listen][this][options] + duk_pcall_method(ctx, 1); duk_pop(ctx); // ... + } + } +} +duk_ret_t ILibDuktape_net_server_IPC_ConnectSink_Finalizer(duk_context *ctx) +{ + ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)Duktape_GetBufferProperty(ctx, 0, ILibDuktape_net_WindowsIPC_Buffer); + if (winIPC->mPipe != NULL && winIPC->mPipeHandle != NULL) + { + // It's ok to do this, becuase the CancelEx happens on the same thread, and the completion routine will use an APC Queue, so the Canary will fail before it tries to deref + ILibProcessPipe_Pipe_CancelEx(winIPC->mPipe); + ILibProcessPipe_FreePipe(winIPC->mPipe); + winIPC->mPipe = NULL; + } + if (winIPC->buffer != NULL) { free(winIPC->buffer); winIPC->buffer = NULL; } + + return(0); } BOOL ILibDuktape_net_server_IPC_ConnectSink(HANDLE event, ILibWaitHandle_ErrorStatus status, void* user) { @@ -942,12 +1001,19 @@ BOOL ILibDuktape_net_server_IPC_ConnectSink(HANDLE event, ILibWaitHandle_ErrorSt ILibDuktape_EventEmitter_SetupEmit(winIPC->ctx, winIPC->mServer, "connection"); // [emit][this][connection] duk_push_object(winIPC->ctx); // [emit][this][connection][socket] ILibDuktape_WriteID(winIPC->ctx, "net.socket.ipc"); + + duk_push_heapptr(winIPC->ctx, winIPC->mServer); // [emit][this][connection][socket][server] + duk_get_prop_string(winIPC->ctx, -1, ILibDuktape_net_WindowsIPC_Buffer); // [emit][this][connection][socket][server][buffer] + duk_remove(winIPC->ctx, -2); // [emit][this][connection][socket][buffer] + duk_put_prop_string(winIPC->ctx, -2, ILibDuktape_net_WindowsIPC_Buffer); // [emit][this][connection][socket] + duk_push_array(winIPC->ctx); duk_put_prop_string(winIPC->ctx, -2, ILibDuktape_net_WindowsIPC_PendingArray); winIPC->mSocket = duk_get_heapptr(winIPC->ctx, -1); winIPC->ds = ILibDuktape_DuplexStream_InitEx(winIPC->ctx, ILibDuktape_net_server_IPC_WriteSink, ILibDuktape_net_server_IPC_EndSink, ILibDuktape_net_server_IPC_PauseSink, ILibDuktape_net_server_IPC_ResumeSink, ILibDuktape_net_server_IPC_unshiftSink, winIPC); winIPC->mPipe = ILibProcessPipe_Pipe_CreateFromExisting(winIPC->manager, winIPC->mPipeHandle, ILibProcessPipe_Pipe_ReaderHandleType_Overlapped); winIPC->ds->readableStream->paused = 1; ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter_GetEmitter(winIPC->ctx, -1), "data", ILibDuktape_net_socket_ipc_dataHookCallback); + ILibDuktape_EventEmitter_PrependOnce(winIPC->ctx, -1, "~", ILibDuktape_net_server_IPC_ConnectSink_Finalizer); if (duk_pcall_method(winIPC->ctx, 2) != 0) { From c6e0d2a0acb42c4f51bfdbf184bcd066b1d0d6a6 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 1 May 2019 16:38:12 -0700 Subject: [PATCH 09/12] Fixed IPC_Write to emit drain when no more pending writes --- microscript/ILibDuktape_net.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index aa512ae..dbe56e8 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -932,6 +932,11 @@ void ILibDuktape_net_server_IPC_WriteCompletionEvent(ILibProcessPipe_Pipe sender duk_set_top(winIPC->ctx, top); // ... ILibProcessPipe_Pipe_WriteEx(winIPC->mPipe, buf, (int)bufLen, winIPC, ILibDuktape_net_server_IPC_WriteCompletionEvent); } + else + { + // No more pending writes, so we can emit drain + ILibDuktape_DuplexStream_Ready(winIPC->ds); + } } ILibTransport_DoneState ILibDuktape_net_server_IPC_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user) { From 067a3ee2a244492821a1811840332610fb1e2b7f Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 1 May 2019 16:41:03 -0700 Subject: [PATCH 10/12] removed printf --- meshcore/agentcore.c | 1 - 1 file changed, 1 deletion(-) diff --git a/meshcore/agentcore.c b/meshcore/agentcore.c index f77a287..d59f822 100644 --- a/meshcore/agentcore.c +++ b/meshcore/agentcore.c @@ -4457,7 +4457,6 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para #if defined(WIN32) && defined(_LINKVM) && !defined(WINSERVICE) if (agentHost->dpiAwareness != NULL) { - printf("Setting DPIAwareness to per monitor\n"); agentHost->dpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); } else From 6770921ca7eb61362131f8087cad16e0a23fe498 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 1 May 2019 21:19:56 -0700 Subject: [PATCH 11/12] Updated ReadEx/WriteEx so it returns status, which can be used to detect broken pipe --- microscript/ILibDuktape_net.c | 10 ++++++++-- microstack/ILibProcessPipe.c | 22 ++++++++++++++++++---- microstack/ILibProcessPipe.h | 4 ++-- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index dbe56e8..05bf267 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -868,7 +868,10 @@ void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, voi { winIPC->bytesLeft = 0; winIPC->bufferOffset = 0; - ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer, winIPC->bufferLength, winIPC, ILibDuktape_net_server_IPC_readsink); + if (ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer, winIPC->bufferLength, winIPC, ILibDuktape_net_server_IPC_readsink) != 0) + { + ILibDuktape_DuplexStream_Closed(winIPC->ds); + } } else { @@ -899,7 +902,10 @@ void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, voi ILibMemory_ReallocateRaw(&(winIPC->buffer), winIPC->bufferLength + ILibDuktape_net_IPC_BUFFERSIZE); winIPC->bufferLength += ILibDuktape_net_IPC_BUFFERSIZE; } - ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer + winIPC->bufferOffset + winIPC->bytesLeft, winIPC->bufferLength - winIPC->bufferOffset - winIPC->bytesLeft, winIPC, ILibDuktape_net_server_IPC_readsink); + if (ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer + winIPC->bufferOffset + winIPC->bytesLeft, winIPC->bufferLength - winIPC->bufferOffset - winIPC->bytesLeft, winIPC, ILibDuktape_net_server_IPC_readsink) != 0) + { + ILibDuktape_DuplexStream_Closed(winIPC->ds); + } break; } } diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c index 634455d..1e0d83c 100644 --- a/microstack/ILibProcessPipe.c +++ b/microstack/ILibProcessPipe.c @@ -1671,7 +1671,7 @@ int ILibProcessPipe_Pipe_CancelEx(ILibProcessPipe_Pipe targetPipe) if (!ILibMemory_CanaryOK(j) || j->mPipe_ReadEnd == NULL) { return(2); } return(CancelIoEx(j->mPipe_ReadEnd, NULL)); } -void ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_ReadExHandler OnReadHandler) +int ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_ReadExHandler OnReadHandler) { ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)targetPipe; j->usingCompletionRoutine = 1; @@ -1679,9 +1679,16 @@ void ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, j->bufferSize = bufferLength; j->user1 = user; j->user2 = OnReadHandler; - ReadFileEx(j->mPipe_ReadEnd, j->buffer, j->bufferSize, j->mOverlapped, ILibProcessPipe_Pipe_Read_CompletionRoutine); + if (!ReadFileEx(j->mPipe_ReadEnd, j->buffer, j->bufferSize, j->mOverlapped, ILibProcessPipe_Pipe_Read_CompletionRoutine)) + { + return(GetLastError()); + } + else + { + return(0); + } } -void ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_WriteExHandler OnWriteHandler) +int ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_WriteExHandler OnWriteHandler) { ILibProcessPipe_PipeObject *j = (ILibProcessPipe_PipeObject*)targetPipe; if (j->mwOverlapped == NULL) @@ -1692,7 +1699,14 @@ void ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, } j->user3 = user; j->user4 = OnWriteHandler; - WriteFileEx(j->mPipe_WriteEnd, buffer, bufferLength, j->mwOverlapped, ILibProcessPipe_Pipe_Write_CompletionRoutine); + if (!WriteFileEx(j->mPipe_WriteEnd, buffer, bufferLength, j->mwOverlapped, ILibProcessPipe_Pipe_Write_CompletionRoutine)) + { + return(GetLastError()); + } + else + { + return(0); + } } DWORD ILibProcessPipe_Process_GetPID(ILibProcessPipe_Process p) { return(p != NULL ? (DWORD)((ILibProcessPipe_Process_Object*)p)->PID : 0); } #else diff --git a/microstack/ILibProcessPipe.h b/microstack/ILibProcessPipe.h index b5f01e1..09c2899 100644 --- a/microstack/ILibProcessPipe.h +++ b/microstack/ILibProcessPipe.h @@ -58,8 +58,8 @@ ILibTransport_DoneState ILibProcessPipe_Pipe_Write(ILibProcessPipe_Pipe writePip void ILibProcessPipe_Pipe_AddPipeReadHandler(ILibProcessPipe_Pipe targetPipe, int bufferSize, ILibProcessPipe_Pipe_ReadHandler OnReadHandler); #ifdef WIN32 int ILibProcessPipe_Pipe_CancelEx(ILibProcessPipe_Pipe targetPipe); - void ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_ReadExHandler OnReadHandler); - void ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_WriteExHandler OnWriteHandler); + int ILibProcessPipe_Pipe_ReadEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_ReadExHandler OnReadHandler); + int ILibProcessPipe_Pipe_WriteEx(ILibProcessPipe_Pipe targetPipe, char *buffer, int bufferLength, void *user, ILibProcessPipe_Pipe_WriteExHandler OnWriteHandler); ILibProcessPipe_Pipe ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(ILibProcessPipe_Manager manager, HANDLE existingPipe, ILibProcessPipe_Pipe_ReaderHandleType handleType, int extraMemorySize); #define ILibProcessPipe_Pipe_CreateFromExisting(PipeManager, ExistingPipe, HandleType) ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(PipeManager, ExistingPipe, HandleType, 0) #else From ac07dc59d59a4cec4613098a90dee51a39c9f527 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 1 May 2019 23:21:27 -0700 Subject: [PATCH 12/12] Updated, so if broken pipe detected, server will re-bind if necessary --- microscript/ILibDuktape_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index 05bf267..98571b4 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -870,7 +870,7 @@ void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, voi winIPC->bufferOffset = 0; if (ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer, winIPC->bufferLength, winIPC, ILibDuktape_net_server_IPC_readsink) != 0) { - ILibDuktape_DuplexStream_Closed(winIPC->ds); + ILibDuktape_net_server_IPC_readsink(winIPC->mPipe, winIPC, 1, NULL, 0); } } else @@ -904,7 +904,7 @@ void ILibDuktape_net_server_IPC_ResumeSink(ILibDuktape_DuplexStream *sender, voi } if (ILibProcessPipe_Pipe_ReadEx(winIPC->mPipe, winIPC->buffer + winIPC->bufferOffset + winIPC->bytesLeft, winIPC->bufferLength - winIPC->bufferOffset - winIPC->bytesLeft, winIPC, ILibDuktape_net_server_IPC_readsink) != 0) { - ILibDuktape_DuplexStream_Closed(winIPC->ds); + ILibDuktape_net_server_IPC_readsink(winIPC->mPipe, winIPC, 1, NULL, 0); } break; }