From 74d4ae2c1e93e9d81359e21b3a417590f7a5ec78 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Sat, 23 May 2020 01:02:44 -0700 Subject: [PATCH 01/21] Windows, rev1 update --- microscript/ILibDuktape_HECI.c | 352 +++++++++++++++++------------- microscript/ILibDuktape_Helpers.h | 4 + microscript/ILibDuktape_net.c | 22 +- microstack/ILibParsers.c | 12 +- modules/amt-lme.js | 2 + modules/amt-mei.js | 1 + 6 files changed, 233 insertions(+), 160 deletions(-) diff --git a/microscript/ILibDuktape_HECI.c b/microscript/ILibDuktape_HECI.c index d14313a..d74421d 100644 --- a/microscript/ILibDuktape_HECI.c +++ b/microscript/ILibDuktape_HECI.c @@ -57,13 +57,16 @@ struct HECI_CONNECT_client_data #define ILibDuktape_HECI_Descriptor "\xFF_HECI_Descriptor" #define ILibDuktape_HECI_ChildProcess "\xFF_HECI_ChildProcess" #define ILibDuktape_HECI_Q "\xFF_HECI_Q" -#define ILibDuktape_HECI_IoctlWaitHandle "\xFF_HECI_IoctlWaitHandle" +#define ILibDuktape_HECI_CTX_PTRS "\xFF_HECI_CTX_PTRS" +//#define ILibDuktape_HECI_IoctlWaitHandle "\xFF_HECI_IoctlWaitHandle" +#define ILibDuktape_HECI_OVERLAPPED "\xFF_HECI_OVERLAPPED" #define ILibDuktape_HECI_Child "\xFF_HECI_Child" #define ILibDuktape_HECI_Parent "\xFF_HECI_Parent" #define ILibDuktape_HECI_Root "\xFF_HECI_Root" #define ILibDuktape_HECI_MaxBufferSize "\xFF_HECI_MaxBufSize" #define ILibDuktape_HECI_SessionMemPtr "\xFF_HECI_SessionMemPtr" #define ILibDuktape_HECI_Session_NoPipeline "\xFF_HECI_Session_NoPipeline" +#define ILibDuktape_HECI_Session_Metadata "\xFF_HECI_Session_Metadata" #ifdef __DOXY__ /*! @@ -148,7 +151,6 @@ typedef struct HECI_chainLink { ILibChain_Link link; duk_context *ctx; - void *Q; ILibDuktape_HECI_Session *session; void *heciObject; int descriptor; @@ -597,9 +599,10 @@ void __stdcall ILibDuktape_HECI_Session_Start(ULONG_PTR obj) DWORD bytesRead; if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Session_Start()\n"); } BOOL result = ReadFile(session->descriptor, session->buffer, (DWORD)session->bufferSize, &bytesRead, &(session->v)); - //if (ILibDuktape_HECI_Debug) { printf("...[WaitHandle Added]\n"); } - ILibChain_AddWaitHandle(session->chain, session->v.hEvent, -1, ILibDuktape_HECI_Session_ReceiveSink, session); + duk_push_heapptr(session->stream->readableStream->ctx, session->stream->ParentObject); // [session] + ILibChain_AddWaitHandleEx(session->chain, session->v.hEvent, -1, ILibDuktape_HECI_Session_ReceiveSink, session, (char*)Duktape_GetStringPropertyValue(session->stream->readableStream->ctx, -1, ILibDuktape_HECI_Session_Metadata, "heci.session")); + duk_pop(session->stream->readableStream->ctx); // ... } #endif @@ -607,16 +610,16 @@ duk_ret_t ILibDuktape_HECI_create_OnClientConnect(duk_context *ctx) { int statusCode = duk_require_int(ctx, 0); ILibDuktape_HECI_Session *session = NULL; - duk_dup(ctx, 2); // [Session] + duk_dup(ctx, 2); // [Session] if (statusCode != 0) { - duk_get_prop_string(ctx, -1, "emit"); // [session][emit] - duk_swap_top(ctx, -2); // [emit][this] - duk_push_string(ctx, "error"); // [emit][this][error] + duk_get_prop_string(ctx, -1, "emit"); // [session][emit] + duk_swap_top(ctx, -2); // [emit][this] + duk_push_string(ctx, "error"); // [emit][this][error] duk_push_error_object(ctx, DUK_ERR_ERROR, "HECI Connection Error [%d]", statusCode); // [emit][this][error][err] duk_push_int(ctx, statusCode); duk_put_prop_string(ctx, -2, "errno"); if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "HECI.session.onError(): "); } - duk_pop(ctx); // ... + duk_pop(ctx); // ... } else { @@ -695,6 +698,8 @@ duk_ret_t ILibDuktape_HECI_create_OnClientConnect(duk_context *ctx) } duk_ret_t ILibDuktape_HECI_Session_connect(duk_context *ctx) { + if (ILibDuktape_HECI_Debug) { printf("connect()\n"); } + int i; int nargs = duk_get_top(ctx); duk_push_this(ctx); // [Session] @@ -708,6 +713,8 @@ duk_ret_t ILibDuktape_HECI_Session_connect(duk_context *ctx) duk_remove(ctx, -2); // [doIoctl][this][CLIENT_CONNECT] duk_dup(ctx, 0); // [doIoctl][this][CLIENT_CONNECT][guid] duk_push_fixed_buffer(ctx, 16); // [doIoctl][this][CLIENT_CONNECT][guid][outBuffer] + duk_push_buffer_object(ctx, -1, 0, 16, DUK_BUFOBJ_NODEJS_BUFFER); // [doIoctl][this][CLIENT_CONNECT][guid][outBuffer][buf] + duk_remove(ctx, -2); duk_push_c_function(ctx, ILibDuktape_HECI_create_OnClientConnect, DUK_VARARGS); // [doIoctl][this][CLIENT_CONNECT][guid][outBuffer][callback] duk_push_int(ctx, 0); duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Session_NoPipeline); @@ -736,7 +743,8 @@ void __stdcall ILibDuktape_HECI_Session_CloseSink2(ULONG_PTR obj) #endif duk_ret_t ILibDuktape_HECI_Session_close(duk_context *ctx) { - duk_push_this(ctx); // [session] + if (ILibDuktape_HECI_Debug) { printf("heci.disconnect()\n\n"); } + duk_push_this(ctx); // [session] if (duk_has_prop_string(ctx, -1, ILibDuktape_HECI_Child)) { @@ -758,6 +766,8 @@ duk_ret_t ILibDuktape_HECI_Session_close(duk_context *ctx) ILibChain_RemoveWaitHandle(session->chain, session->wv.hEvent); session->stream = NULL; CloseHandle(session->descriptor); + CloseHandle(session->v.hEvent); session->v.hEvent = NULL; + CloseHandle(session->wv.hEvent); session->wv.hEvent = NULL; } #else int d = Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_HECI_Descriptor, -1); @@ -777,8 +787,27 @@ duk_ret_t ILibDuktape_HECI_Session_close(duk_context *ctx) return(0); } +duk_ret_t ILibDuktape_HECI_session_descriptorMetadata(duk_context *ctx) +{ + duk_push_this(ctx); // [session] + duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Session_Metadata); // [session][oldVal] + duk_push_string(ctx, ", "); // [session][oldVal][newVal] + duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [session][val] + duk_dup(ctx, 0); // [session][val][newVal] + duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [session][newVal] + duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Session_Metadata); // [session] + + ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_HECI_SessionMemPtr); + if (session != NULL) + { + ILibChain_WaitHandle_UpdateMetadata(duk_ctx_chain(ctx), session->v.hEvent, (char*)Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_HECI_Session_Metadata, "heci.session")); + } + return(0); +} duk_ret_t ILibDuktape_HECI_create(duk_context *ctx) { + if (ILibDuktape_HECI_Debug) { printf("\n\nILibDuktape_HECI_create()\n"); } + duk_push_object(ctx); // [Session] ILibDuktape_WriteID(ctx, "heci.session"); ILibDuktape_HECI_Push(ctx, NULL); // [Session][HECI] @@ -787,6 +816,8 @@ duk_ret_t ILibDuktape_HECI_create(duk_context *ctx) duk_push_this(ctx); // [session][HECI][root] duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Root); // [session][HECI] duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Child); // [Session] + duk_push_string(ctx, "heci.session"); duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Session_Metadata); + ILibDuktape_CreateEventWithSetterEx(ctx, "descriptorMetadata", ILibDuktape_HECI_session_descriptorMetadata); duk_push_this(ctx); // [Session][root] ILibDuktape_Push_ObjectStash(ctx); // [Session][root][stash] @@ -844,86 +875,70 @@ void ILibDuktape_HECI_IoctlHandler_Dispatch(void *chain, void *user) ILibDuktape_Push_ObjectStash(data->ctx); // [heci][stash] duk_del_prop_string(data->ctx, -1, Duktape_GetStashKey(data->data)); // (This will dereference args passed to doIoctl) duk_pop_2(ctx); // ... - if (ILibDuktape_HECI_Debug) { printf("** Release HECI Ioctl Data [%p]\n", (void*)data); } + if (ILibDuktape_HECI_Debug) { printf("doIoctl() [COMPLETE] -> ** Release HECI Ioctl Data [%p]\n", (void*)data); } ILibMemory_Free(data); } #ifdef WIN32 -void ILibDuktape_HECI_NextIoctl(ILibQueue q); +//void ILibDuktape_HECI_NextIoctl(ILibQueue q); +void ILibDuktape_HECI_NextIoctl(duk_context *ctx, void *heci); BOOL ILibDuktape_HECI_IoctlHandler(void * chain, HANDLE h, ILibWaitHandle_ErrorStatus errors, void *user) { - if (errors == ILibWaitHandle_ErrorStatus_INVALID_HANDLE || errors == ILibWaitHandle_ErrorStatus_REMOVED) { return(FALSE); } if (!ILibMemory_CanaryOK(user)) { return(FALSE); } - ILibDuktape_HECI_ioctl_data *data = (ILibDuktape_HECI_ioctl_data*)user; - ILibQueue Q = data->Q; + duk_context *ctx = (duk_context*)((void**)user)[0]; + int top = duk_get_top(ctx); + + duk_push_heapptr(ctx, ((void**)user)[1]); // [HECI] + duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [HECI][QUEUE] + HANDLE descriptor = Duktape_GetPointerProperty(ctx, -2, ILibDuktape_HECI_Descriptor); + OVERLAPPED *p = (OVERLAPPED*)Duktape_GetBufferProperty(ctx, -2, ILibDuktape_HECI_OVERLAPPED); + DWORD bytesReceived = 0; if (errors == ILibWaitHandle_ErrorStatus_NONE) { - BOOL result = GetOverlappedResult(data->device, &(data->v), &(data->bytesReceived), FALSE); - data->code = result == TRUE ? 0 : (int)GetLastError(); + if (GetOverlappedResult(descriptor, p, &bytesReceived, FALSE) == FALSE) { return(TRUE); } + duk_queue_deQueue(ctx, -1); // [HECI][QUEUE][OBJ] + duk_get_prop_string(ctx, -1, "callback"); // [HECI][QUEUE][OBJ][callback] + duk_get_prop_string(ctx, -1, "apply"); // [HECI][QUEUE][OBJ][callback][apply] + duk_swap_top(ctx, -2); // [HECI][QUEUE][OBJ][apply][func] + duk_dup(ctx, -5); // [HECI][QUEUE][OBJ][apply][func][this] + duk_get_prop_string(ctx, -4, "args"); // [HECI][QUEUE][OBJ][apply][func][this][args] + duk_get_prop_string(ctx, -5, "outbuffer"); // [HECI][QUEUE][OBJ][apply][func][this][args][outbuffer] + if (!duk_is_null(ctx, -1)) { duk_buffer_slice(ctx, -1, 0, bytesReceived); } // [HECI][QUEUE][OBJ][apply][func][this][args][outbuffer] + duk_array_unshift(ctx, -2); // [HECI][QUEUE][OBJ][apply][func][this][args] + duk_push_int(ctx, 0); duk_array_unshift(ctx, -2); // [HECI][QUEUE][OBJ][apply][func][this][args] + duk_pcall_method(ctx, 2); duk_pop_2(ctx); // [HECI][QUEUE] + if (!duk_queue_isEmpty(ctx, -1)) + { + ILibDuktape_HECI_NextIoctl(ctx, ((void**)user)[1]); + duk_set_top(ctx, top); + return(TRUE); + } } else { - data->code = -1; + DebugBreak(); } - - ILibQueue_DeQueue(data->Q); - ILibChain_RemoveWaitHandle(data->chain, h); - - if (data->abort != 0 || !ILibMemory_CanaryOK(data->reserved)) - { - // ABORT - ILibQueue Q = (ILibQueue)data->Q; - void *node = ILibLinkedList_GetNode_Head(data->Q); - while (node != NULL) - { - if (ILibDuktape_HECI_Debug) { printf("** ABORT HECI Ioctl Data [%p]\n", ILibLinkedList_GetDataFromNode(node)); } - ILibMemory_Free(ILibLinkedList_GetDataFromNode(node)); - node = ILibLinkedList_GetNextNode(node); - } - if (ILibDuktape_HECI_Debug) { printf("<== Queue: %p Destroyed in IOCTL Handler ==>\n", (void*)Q); } - ILibQueue_Destroy(Q); - return(FALSE); - } - - ILibDuktape_HECI_IoctlHandler_Dispatch(data->chain, data); - - if (ILibQueue_GetCount(Q) > 0) - { - ILibDuktape_HECI_NextIoctl(Q); - } - return(TRUE); + duk_set_top(ctx, top); + return(FALSE); } -void ILibDuktape_HECI_NextIoctl(ILibQueue q) +void ILibDuktape_HECI_NextIoctl(duk_context *ctx, void *heci) { - ILibDuktape_HECI_ioctl_data *data = (ILibDuktape_HECI_ioctl_data*)ILibQueue_PeekQueue(q); - int res; - if (data == NULL) { return; } // This line is unnecessary, because this method is only called on a non-empty Queue, but to satisfy Klockwork... + duk_push_heapptr(ctx, heci); // [HECI] + HANDLE descriptor = (HANDLE)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_Descriptor); + OVERLAPPED *p = (OVERLAPPED*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_HECI_OVERLAPPED); + void **ptrs = (void**)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_HECI_CTX_PTRS); + duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [HECI][QUEUE] - data->bytesReceived = 0; + duk_queue_peek(ctx, -1); // [HECI][QUEUE][OBJ] + duk_size_t bufferLen = 0; + duk_size_t outBufferLen = 0; + char *buffer = Duktape_GetBufferPropertyEx(ctx, -1, "buffer", &bufferLen); + char *outBuffer = Duktape_GetBufferPropertyEx(ctx, -1, "outbuffer", &outBufferLen); + DWORD dwIoControlCode = (DWORD)Duktape_GetIntPropertyValue(ctx, -1, "code", 0); - ResetEvent(data->v.hEvent); - res = DeviceIoControl(data->device, (DWORD)data->code, data->buffer, (DWORD)data->bufferLen, data->outBuffer, (DWORD)data->outBufferLen, &(data->bytesReceived), &(data->v)); - ILibChain_AddWaitHandle(data->chain, data->v.hEvent, 2000, ILibDuktape_HECI_IoctlHandler, data); -} -void __stdcall ILibDuktape_HECI_apc_AddIoctl(ULONG_PTR obj) -{ - ILibDuktape_HECI_ioctl_data *data = (ILibDuktape_HECI_ioctl_data*)obj; - ILibQueue_EnQueue(data->Q, data); - if (ILibQueue_GetCount(data->Q) == 1) - { - ILibDuktape_HECI_NextIoctl(data->Q); - } -} -#endif -#ifdef _POSIX -void ILibDuktape_HECI_AddIoctl(ILibDuktape_HECI_ioctl_data *data) -{ - ILibQueue_EnQueue(data->Q, data); - if (ILibQueue_GetCount(data->Q) == 1) - { - ILibForceUnBlockChain(data->chain); - } + DeviceIoControl(descriptor, dwIoControlCode, buffer, (DWORD)bufferLen, outBuffer, (DWORD)outBufferLen, NULL, p); + ILibChain_AddWaitHandleEx(duk_ctx_chain(ctx), p->hEvent, 5000, ILibDuktape_HECI_IoctlHandler, ptrs, "heci.doIoctl()"); } #endif @@ -934,7 +949,6 @@ duk_ret_t ILibDuktape_HECI_doIoctl(duk_context *ctx) char *buffer = duk_is_null(ctx, 1) ? NULL : (char*)Duktape_GetBuffer(ctx, 1, &bufferLen); int nargs = duk_get_top(ctx); int i; - ILibQueue Q; duk_size_t outBufferLen; char *outBuffer; int cbx; @@ -964,77 +978,110 @@ duk_ret_t ILibDuktape_HECI_doIoctl(duk_context *ctx) } #endif - duk_require_function(ctx, cbx); - duk_push_this(ctx); // [heci] - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [heci][q] - Q = (ILibQueue)duk_get_pointer(ctx, -1); - duk_pop(ctx); // [heci] + duk_require_function(ctx, cbx); // Make sure a callback function was specified - ILibDuktape_Push_ObjectStash(ctx); // [heci][stash] - duk_push_array(ctx); // [heci][stash][array] - ILibDuktape_HECI_ioctl_data *data; - data = (ILibDuktape_HECI_ioctl_data*)ILibMemory_SmartAllocate(bufferLen + sizeof(ILibDuktape_HECI_ioctl_data)); - data->ctxnonce = duk_ctx_nonce(ctx); - if (ILibDuktape_HECI_Debug) { printf("-> Allocate HECI Ioctl Data [%p]\n", (void*)data); } - data->reserved = Duktape_PushBuffer(ctx, sizeof(void*)); // [heci][stash][array][ptr] - duk_put_prop_index(ctx, -2, 0); // [heci][stash][array] - if (outBufferLen > 0) - { // [heci][stash][array][buffer] - duk_dup(ctx, 2); - } - else - { - duk_push_null(ctx); // [heci][stash][array][buffer] - } - - duk_put_prop_index(ctx, -2, 1); // [heci][stash][array] - data->ctx = ctx; + duk_push_this(ctx); // [HECI] + duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [HECI][QUEUE] + duk_push_object(ctx); // [HECI][QUEUE][OBJ] - duk_dup(ctx, cbx); // [heci][stash][array][callback] - duk_put_prop_index(ctx, -2, 2); // [heci][stash][array] - -#ifdef WIN32 - duk_get_prop_string(ctx, -3, ILibDuktape_HECI_IoctlWaitHandle); // [heci][stash][array][handle] - data->v.hEvent = (HANDLE)duk_get_pointer(ctx, -1); - duk_pop(ctx); // [heci][stash][array] -#endif - - duk_get_prop_string(ctx, -3, ILibDuktape_HECI_Descriptor); // [heci][stash][array][descriptor] -#ifdef WIN32 - data->device = (HANDLE)duk_get_pointer(ctx, -1); -#elif defined(_POSIX) - data->device = duk_get_int(ctx, -1); -#endif - duk_pop(ctx); // [heci][stash][array] - data->chain = Duktape_GetChain(ctx); - data->Q = Q; - data->code = code; - data->outBuffer = outBuffer; - data->outBufferLen = outBufferLen; - data->heciObject = duk_get_heapptr(ctx, -3); - data->bufferLen = bufferLen; - data->data = duk_get_heapptr(ctx, -1); - memcpy_s(data->buffer, bufferLen, buffer, bufferLen); + duk_dup(ctx, cbx); duk_put_prop_string(ctx, -2, "callback"); + duk_dup(ctx, 1); duk_put_prop_string(ctx, -2, "buffer"); + if (outBufferLen > 0) { duk_dup(ctx, 2); } else { duk_push_null(ctx); } + duk_put_prop_string(ctx, -2, "outbuffer"); + duk_push_int(ctx, code); duk_put_prop_string(ctx, -2, "code"); + void **ptrs = Duktape_PushBuffer(ctx, 2 * sizeof(void*)); duk_put_prop_string(ctx, -2, ILibDuktape_HECI_CTX_PTRS); + ptrs[0] = ctx; + ptrs[1] = duk_get_heapptr(ctx, -3); + duk_push_array(ctx); // [HECI][QUEUE][OBJ][ARGS] for (i = cbx + 1; i < nargs; ++i) - { - duk_dup(ctx, i); // [heci][stash][array][object] - duk_put_prop_index(ctx, -2, i-1); // [heci][stash][array] - } - duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [heci][stash] - - + { + duk_dup(ctx, i); // [HECI][QUEUE][OBJ][ARGS][arg] + duk_array_push(ctx, -2); // [HECI][QUEUE][OBJ][ARGS] + } + duk_put_prop_string(ctx, -2, "args"); // [HECI][QUEUE][OBJ] + duk_queue_enQueue(ctx, -2); // [HECI][QUEUE] + if (duk_get_length(ctx, -1) == 1) + { #ifdef WIN32 - duk_get_prop_string(ctx, -2, ILibDuktape_HECI_ChildProcess); // [heci][stash][childProcess] - duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager); // [heci][stash][childProcess][manager] - data->pipeManager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1); - - ILibDuktape_HECI_apc_AddIoctl((ULONG_PTR)data); -#elif defined(_POSIX) - ILibDuktape_HECI_AddIoctl(data); + ILibDuktape_HECI_NextIoctl(ctx, duk_get_heapptr(ctx, -2)); +#else + ILibForceUnBlockChain(duk_ctx_chain(ctx)); #endif - + } return(0); +// +// duk_require_function(ctx, cbx); +// duk_push_this(ctx); // [heci] +// duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [heci][q] +// qptr = duk_get_heapptr(ctx, -1); +// duk_pop(ctx); // [heci] +// +// ILibDuktape_Push_ObjectStash(ctx); // [heci][stash] +// duk_push_array(ctx); // [heci][stash][array] +// ILibDuktape_HECI_ioctl_data *data; +// data = (ILibDuktape_HECI_ioctl_data*)ILibMemory_SmartAllocate(bufferLen + sizeof(ILibDuktape_HECI_ioctl_data)); +// data->ctxnonce = duk_ctx_nonce(ctx); +// if (ILibDuktape_HECI_Debug) { printf("doIoctl() -> Allocate HECI Ioctl Data [%p]\n", (void*)data); } +// data->reserved = Duktape_PushBuffer(ctx, sizeof(void*)); // [heci][stash][array][ptr] +// duk_put_prop_index(ctx, -2, 0); // [heci][stash][array] +// if (outBufferLen > 0) +// { // [heci][stash][array][buffer] +// duk_dup(ctx, 2); +// } +// else +// { +// duk_push_null(ctx); // [heci][stash][array][buffer] +// } +// +// duk_put_prop_index(ctx, -2, 1); // [heci][stash][array] +// data->ctx = ctx; +// +// duk_dup(ctx, cbx); // [heci][stash][array][callback] +// duk_put_prop_index(ctx, -2, 2); // [heci][stash][array] +// +//#ifdef WIN32 +// duk_get_prop_string(ctx, -3, ILibDuktape_HECI_IoctlWaitHandle); // [heci][stash][array][handle] +// data->v.hEvent = (HANDLE)duk_get_pointer(ctx, -1); +// duk_pop(ctx); // [heci][stash][array] +//#endif +// +// duk_get_prop_string(ctx, -3, ILibDuktape_HECI_Descriptor); // [heci][stash][array][descriptor] +//#ifdef WIN32 +// data->device = (HANDLE)duk_get_pointer(ctx, -1); +//#elif defined(_POSIX) +// data->device = duk_get_int(ctx, -1); +//#endif +// duk_pop(ctx); // [heci][stash][array] +// data->chain = Duktape_GetChain(ctx); +// data->Q = Q; +// data->code = code; +// data->outBuffer = outBuffer; +// data->outBufferLen = outBufferLen; +// data->heciObject = duk_get_heapptr(ctx, -3); +// data->bufferLen = bufferLen; +// data->data = duk_get_heapptr(ctx, -1); +// memcpy_s(data->buffer, bufferLen, buffer, bufferLen); +// +// for (i = cbx + 1; i < nargs; ++i) +// { +// duk_dup(ctx, i); // [heci][stash][array][object] +// duk_put_prop_index(ctx, -2, i-1); // [heci][stash][array] +// } +// duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [heci][stash] +// +// +//#ifdef WIN32 +// duk_get_prop_string(ctx, -2, ILibDuktape_HECI_ChildProcess); // [heci][stash][childProcess] +// duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager); // [heci][stash][childProcess][manager] +// data->pipeManager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1); +// +// ILibDuktape_HECI_apc_AddIoctl((ULONG_PTR)data); +//#elif defined(_POSIX) +// ILibDuktape_HECI_AddIoctl(data); +//#endif +// +// return(0); } #ifdef WIN32 @@ -1067,18 +1114,6 @@ duk_ret_t ILibDuktape_HECI_Finalizer(duk_context *ctx) if (h != NULL) { CloseHandle(h); } #endif - if (duk_has_prop_string(ctx, 0, ILibDuktape_HECI_Q)) - { -#ifdef WIN32 - ILibQueue Q = (ILibQueue)Duktape_GetPointerProperty(ctx, 0, ILibDuktape_HECI_Q); - duk_get_prop_string(ctx, 0, ILibDuktape_HECI_ChildProcess); - ILibProcessPipe_Manager mgr = (ILibProcessPipe_Manager)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager); - ILibDuktape_HECI_Finalizer2((ULONG_PTR)Q); -#else - duk_get_prop_string(ctx, 0, ILibDuktape_HECI_Q); - ILibQueue_Destroy((ILibQueue)duk_get_pointer(ctx, -1)); -#endif - } #ifdef _POSIX if (duk_has_prop_string(ctx, 0, ILibDuktape_HECI_ChainLink)) @@ -1175,6 +1210,8 @@ duk_ret_t ILibDuktape_HECI_reset(duk_context *ctx) { duk_push_this(ctx); #ifdef WIN32 + if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_reset()\n"); } + HANDLE h = (HANDLE)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_Descriptor); CloseHandle(h); h = ILibDuktape_HECI_windowsInit(); @@ -1203,8 +1240,13 @@ void ILibDuktape_HECI_Push(duk_context *ctx, void *chain) } duk_put_prop_string(ctx, -2, ILibDuktape_HECI_ChildProcess); // [HECI] - duk_push_pointer(ctx, CreateEvent(NULL, TRUE, FALSE, NULL)); - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_IoctlWaitHandle); // [HECI] + OVERLAPPED *v = Duktape_PushBuffer(ctx, sizeof(OVERLAPPED)); // [HECI][OVERLAPPED] + v->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + duk_put_prop_string(ctx, -2, ILibDuktape_HECI_OVERLAPPED); // [HECI] + void **ptrs = (void**)Duktape_PushBuffer(ctx, 2*sizeof(void*)); duk_put_prop_string(ctx, -2, ILibDuktape_HECI_CTX_PTRS); + ptrs[0] = ctx; + ptrs[1] = duk_get_heapptr(ctx, -1); + #elif defined(_POSIX) && !defined(__APPLE__) int h = ILibDuktape_HECI_linuxInit(); if (h < 0) { ILibDuktape_Error(ctx, "error initializing HECI"); return; } @@ -1218,7 +1260,6 @@ void ILibDuktape_HECI_Push(duk_context *ctx, void *chain) hlink->link.PreSelectHandler = ILibDuktape_HECI_PreSelect; hlink->link.PostSelectHandler = ILibDuktape_HECI_PostSelect; hlink->link.DestroyHandler = ILibDuktape_HECI_Destroy; - hlink->Q = ILibQueue_Create(); duk_push_pointer(ctx, hlink); // [HECI][link] duk_put_prop_string(ctx, -2, ILibDuktape_HECI_ChainLink); // [HECI] @@ -1228,11 +1269,8 @@ void ILibDuktape_HECI_Push(duk_context *ctx, void *chain) ILibDuktape_CreateInstanceMethod(ctx, "doIoctl", ILibDuktape_HECI_doIoctl, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "disconnect", ILibDuktape_HECI_Session_close, 0); ILibDuktape_CreateInstanceMethod(ctx, "reset", ILibDuktape_HECI_reset, 0); -#if defined(_POSIX) && !defined(__APPLE__) - duk_push_pointer(ctx, hlink->Q); // [HECI][Q] -#else - duk_push_pointer(ctx, ILibQueue_Create()); // [HECI][Q] -#endif + + duk_queue_create(ctx); duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Q); // [HECI] duk_push_object(ctx); #ifdef WIN32 diff --git a/microscript/ILibDuktape_Helpers.h b/microscript/ILibDuktape_Helpers.h index c314de6..f9d00a2 100644 --- a/microscript/ILibDuktape_Helpers.h +++ b/microscript/ILibDuktape_Helpers.h @@ -98,6 +98,7 @@ char *Duktape_Duplicate_GetStringEx(duk_context *ctx, duk_idx_t i, duk_size_t *l #define duk_array_pop(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "pop");duk_swap_top(ctx, -2);duk_call_method(ctx, 0); #define duk_array_push(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "push");duk_swap_top(ctx, -2);duk_dup(ctx,-3);duk_pcall_method(ctx, 1);duk_pop_2(ctx); #define duk_array_join(ctx, i, str) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "join");duk_swap_top(ctx, -2);duk_push_string(ctx, str);duk_pcall_method(ctx, 1); +#define duk_array_unshift(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "unshift");duk_swap_top(ctx, -2);duk_dup(ctx, -3);duk_remove(ctx, -4);duk_pcall_method(ctx, 1);duk_pop(ctx); #define duk_queue_create(ctx) duk_push_array(ctx) #define duk_queue_enQueue(ctx, i) duk_array_push(ctx, i) @@ -105,6 +106,9 @@ char *Duktape_Duplicate_GetStringEx(duk_context *ctx, duk_idx_t i, duk_size_t *l #define duk_queue_peek(ctx, i) duk_get_prop_index(ctx, i, 0) #define duk_queue_isEmpty(ctx, i) (duk_get_length(ctx, i)==0) +#define duk_buffer_slice(ctx, i, start, len) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "slice");duk_swap_top(ctx, -2);duk_push_int(ctx, start);duk_push_int(ctx, len);duk_pcall_method(ctx, 2);duk_remove(ctx, -2); +#define duk_string_concat(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "concat");duk_swap_top(ctx, -2);duk_dup(ctx, -3);duk_pcall_method(ctx, 1);duk_remove(ctx, -2); + int Duktape_GetBooleanProperty(duk_context *ctx, duk_idx_t i, char *propertyName, int defaultValue); struct sockaddr_in6* Duktape_IPAddress4_FromString(char* address, unsigned short port); struct sockaddr_in6* Duktape_IPAddress6_FromString(char* address, unsigned short port); diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index 4ebe3d4..b89ca91 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -122,6 +122,7 @@ typedef struct ILibDuktape_net_WindowsIPC #define ILibDuktape_SERVER2LISTENOPTIONS "\xFF_ServerToListenOptions" #define ILibDuktape_TLSSocket2SecureContext "\xFF_TLSSocket2SecureContext" #define ILibDuktape_IPAddress_SockAddr "\xFF_IPAddress_SockAddr" +#define ILibDuktape_net_server_metadata "\xFF_net_server_metadata" extern void ILibAsyncServerSocket_RemoveFromChain(ILibAsyncServerSocket_ServerModule serverModule); @@ -1326,7 +1327,21 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx) #endif duk_push_this(ctx); - if (server->server != NULL) { ILibChain_Link_SetMetadata(server->server, Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "net.Server")); } + if (server->server != NULL) + { + duk_get_prop_string(ctx, -1, ILibDuktape_OBJID); // [server][str] + if (duk_has_prop_string(ctx, -2, ILibDuktape_net_server_metadata)) + { + duk_push_string(ctx, ", "); // [server][str][newVal] + duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [server][str] + duk_get_prop_string(ctx, -2, ILibDuktape_net_server_metadata); // [server][str][metadata] + duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [server][metadata] + duk_dup(ctx, -1); // [server][metadata][clone] + duk_put_prop_string(ctx, -3, ILibDuktape_net_server_metadata); // [server][metadata] + } + ILibChain_Link_SetMetadata(server->server, (char*)duk_get_string(ctx, -1)); + duk_pop(ctx); + } return 1; } @@ -1466,6 +1481,11 @@ duk_ret_t ILibDuktape_net_createServer_metadata(duk_context *ctx) memcpy_s(tmp2, ILibMemory_Size(tmp2), tmp, ILibMemory_Size(tmp2) - 1); ILibChain_Link_SetMetadata(server->server, tmp2); } + else + { + duk_dup(ctx, 0); // [server][string] + duk_put_prop_string(ctx, -2, ILibDuktape_net_server_metadata); + } return(0); } diff --git a/microstack/ILibParsers.c b/microstack/ILibParsers.c index d8aa27a..89da431 100644 --- a/microstack/ILibParsers.c +++ b/microstack/ILibParsers.c @@ -2079,9 +2079,16 @@ int ILibChain_WindowsSelect(void *chain, fd_set *readset, fd_set *writeset, fd_s // TIMEOUT occured if (((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->handler != NULL) { - ((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->handler(chain, waitList[i], ILibWaitHandle_ErrorStatus_TIMEOUT, ((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->user); + if (((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->handler(chain, waitList[i], ILibWaitHandle_ErrorStatus_TIMEOUT, ((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->user) == FALSE) + { + ILibLinkedList_Remove(((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->node); + } } - ILibLinkedList_Remove(((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->node); + else + { + ILibLinkedList_Remove(((ILibChain_WaitHandleInfo*)waitList[ILibChain_HandleInfoIndex(i)])->node); + } + waitList[i] = NULL; waitList[ILibChain_HandleInfoIndex(i)] = NULL; } @@ -3432,6 +3439,7 @@ void ILibChain_AddWaitHandleEx(void *chain, HANDLE h, int msTIMEOUT, ILibChain_W info->expiration.tv_usec += ((msTIMEOUT % 1000) * 1000); } } + ILibMemory_Free(metadata); } void __stdcall ILibChain_RemoveWaitHandle_APC(ULONG_PTR u) { diff --git a/modules/amt-lme.js b/modules/amt-lme.js index c5263ae..b7bea1d 100644 --- a/modules/amt-lme.js +++ b/modules/amt-lme.js @@ -124,6 +124,7 @@ function lme_heci(options) { this._ObjectID = "lme"; this._LME = heci.create(); + this._LME.descriptorMetadata = "amt-lme"; this._LME._binded = {}; this._LME.LMS = this; this._LME.on('error', function (e) { this.LMS.emit('error', e); }); @@ -173,6 +174,7 @@ function lme_heci(options) { try { // Bind a new server socket if not already present this[name][port] = require('net').createServer(); + this[name][port].descriptorMetadata = 'amt-lme (port: ' + port + ')'; this[name][port].HECI = this; if (lme_port_offset == 0) { this[name][port].listen({ port: port, host: '127.0.0.1' }); // Normal mode diff --git a/modules/amt-mei.js b/modules/amt-mei.js index 3a724e1..e06eee1 100644 --- a/modules/amt-mei.js +++ b/modules/amt-mei.js @@ -27,6 +27,7 @@ function amt_heci() { this._setupPTHI = function _setupPTHI() { this._amt = heci.create(); + this._amt.descriptorMetadata = "amt-pthi"; this._amt.BiosVersionLen = 65; this._amt.UnicodeStringLen = 20; From 7c3236ba8d7f3f5f3201b578ca135f9ea79e69e4 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Sun, 24 May 2020 00:10:48 -0700 Subject: [PATCH 02/21] Added helpers, and updated HECI cleanup --- microscript/ILibDuktape_HECI.c | 18 ++++++++++++++++-- microscript/ILibDuktape_Helpers.h | 7 +++++++ microscript/ILibDuktape_Polyfills.c | 14 ++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/microscript/ILibDuktape_HECI.c b/microscript/ILibDuktape_HECI.c index d74421d..c205bc3 100644 --- a/microscript/ILibDuktape_HECI.c +++ b/microscript/ILibDuktape_HECI.c @@ -675,6 +675,7 @@ duk_ret_t ILibDuktape_HECI_create_OnClientConnect(duk_context *ctx) #ifdef WIN32 duk_push_this(ctx); // [HECI] session->descriptor = (HANDLE)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_Descriptor); + duk_del_prop_string(ctx, -1, ILibDuktape_HECI_Descriptor); duk_get_prop_string(ctx, -1, ILibDuktape_HECI_ChildProcess); // [HECI][childProcess] duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager); // [HECI][childProcess][manager] session->mgr = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1); @@ -928,6 +929,7 @@ void ILibDuktape_HECI_NextIoctl(duk_context *ctx, void *heci) HANDLE descriptor = (HANDLE)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_Descriptor); OVERLAPPED *p = (OVERLAPPED*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_HECI_OVERLAPPED); void **ptrs = (void**)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_HECI_CTX_PTRS); + duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [HECI][QUEUE] duk_queue_peek(ctx, -1); // [HECI][QUEUE][OBJ] @@ -981,6 +983,9 @@ duk_ret_t ILibDuktape_HECI_doIoctl(duk_context *ctx) duk_require_function(ctx, cbx); // Make sure a callback function was specified duk_push_this(ctx); // [HECI] +#ifdef WIN32 + if (!duk_has_prop_string(ctx, -1, ILibDuktape_HECI_Descriptor)) { return(ILibDuktape_Error(ctx, "Invalid Operation. Call Reset()")); } +#endif duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [HECI][QUEUE] duk_push_object(ctx); // [HECI][QUEUE][OBJ] @@ -1110,8 +1115,14 @@ duk_ret_t ILibDuktape_HECI_Finalizer(duk_context *ctx) { if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Finalizer()\n"); } #ifdef WIN32 - HANDLE h = Duktape_GetPointerProperty(ctx, 0, ILibDuktape_HECI_IoctlWaitHandle); + HANDLE h = Duktape_GetPointerProperty(ctx, 0, ILibDuktape_HECI_Descriptor); if (h != NULL) { CloseHandle(h); } + OVERLAPPED *p = (OVERLAPPED*)Duktape_GetBufferProperty(ctx, 0, ILibDuktape_HECI_OVERLAPPED); + if (p->hEvent != NULL) + { + ILibChain_RemoveWaitHandle(duk_ctx_chain(ctx), p->hEvent); + CloseHandle(p->hEvent); + } #endif @@ -1213,7 +1224,10 @@ duk_ret_t ILibDuktape_HECI_reset(duk_context *ctx) if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_reset()\n"); } HANDLE h = (HANDLE)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_Descriptor); - CloseHandle(h); + if (h != NULL) + { + CloseHandle(h); + } h = ILibDuktape_HECI_windowsInit(); duk_push_pointer(ctx, h); duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Descriptor); diff --git a/microscript/ILibDuktape_Helpers.h b/microscript/ILibDuktape_Helpers.h index f9d00a2..78dbebb 100644 --- a/microscript/ILibDuktape_Helpers.h +++ b/microscript/ILibDuktape_Helpers.h @@ -106,6 +106,13 @@ char *Duktape_Duplicate_GetStringEx(duk_context *ctx, duk_idx_t i, duk_size_t *l #define duk_queue_peek(ctx, i) duk_get_prop_index(ctx, i, 0) #define duk_queue_isEmpty(ctx, i) (duk_get_length(ctx, i)==0) +#define duk_table_put(ctx, i, key) duk_put_prop_string(ctx, i, key) +#define duk_table_get(ctx, i, key) duk_get_prop_string(ctx, i, key) +#define duk_table_get_buffer(ctx, i, key) Duktape_GetBufferProperty(ctx, i, key) +#define duk_table_keys(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "keys");duk_swap_top(ctx, -2);if(duk_pcall_method(ctx, 0)!=0){duk_pop(ctx);duk_push_null(ctx);} +#define duk_table_hasKey(ctx, i, key) duk_has_prop_string(ctx, i, key) +#define duk_table_delKey(ctx, i, key) duk_del_prop_string(ctx, i, key) + #define duk_buffer_slice(ctx, i, start, len) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "slice");duk_swap_top(ctx, -2);duk_push_int(ctx, start);duk_push_int(ctx, len);duk_pcall_method(ctx, 2);duk_remove(ctx, -2); #define duk_string_concat(ctx, i) duk_dup(ctx, i);duk_get_prop_string(ctx, -1, "concat");duk_swap_top(ctx, -2);duk_dup(ctx, -3);duk_pcall_method(ctx, 1);duk_remove(ctx, -2); diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index e308282..c7b29c7 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -1813,6 +1813,18 @@ duk_ret_t ILibDuktape_Polyfills_Array_peek(duk_context *ctx) duk_get_prop_index(ctx, -1, (duk_uarridx_t)duk_get_length(ctx, -1) - 1); return(1); } +duk_ret_t ILibDuktape_Polyfills_Object_keys(duk_context *ctx) +{ + duk_push_this(ctx); // [obj] + duk_push_array(ctx); // [obj][keys] + duk_enum(ctx, -2, DUK_ENUM_OWN_PROPERTIES_ONLY); // [obj][keys][enum] + while (duk_next(ctx, -1, 0)) // [obj][keys][enum][key] + { + duk_array_push(ctx, -3); // [obj][keys][enum] + } + duk_pop(ctx); // [obj][keys] + return(1); +} void ILibDuktape_Polyfills_object(duk_context *ctx) { // Polyfill Object._hashCode() @@ -1820,6 +1832,8 @@ void ILibDuktape_Polyfills_object(duk_context *ctx) duk_get_prop_string(ctx, -1, "prototype"); // [g][Object][prototype] duk_push_c_function(ctx, ILibDuktape_Polyfills_Object_hashCode, 0); // [g][Object][prototype][func] ILibDuktape_CreateReadonlyProperty(ctx, "_hashCode"); // [g][Object][prototype] + duk_push_c_function(ctx, ILibDuktape_Polyfills_Object_keys, 0); // [g][Object][prototype][func] + ILibDuktape_CreateReadonlyProperty(ctx, "keys"); // [g][Object][prototype] duk_pop_2(ctx); // [g] duk_get_prop_string(ctx, -1, "Array"); // [g][Array] From 1577458365dddfd7f9d099d8d5775d2e4c1ec058 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Mon, 25 May 2020 09:21:34 -0700 Subject: [PATCH 03/21] Update DescriptorEvents --- microscript/ILibDuktape_EventEmitter.h | 1 + microscript/ILibDuktape_Polyfills.c | 125 +++++++++++++++++++------ 2 files changed, 97 insertions(+), 29 deletions(-) diff --git a/microscript/ILibDuktape_EventEmitter.h b/microscript/ILibDuktape_EventEmitter.h index 53ef34a..d040788 100644 --- a/microscript/ILibDuktape_EventEmitter.h +++ b/microscript/ILibDuktape_EventEmitter.h @@ -62,6 +62,7 @@ int ILibDuktape_EventEmitter_HasListeners2(ILibDuktape_EventEmitter *emitter, ch #define ILibDuktape_EventEmitter_SetupEmit(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "emit");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName) #define ILibDuktape_EventEmitter_SetupOn(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "on");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName) #define ILibDuktape_EventEmitter_SetupPrependOnce(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "prependOnceListener");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName) +#define ILibDuktape_EventEmitter_GetEmitReturn(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "emit_returnValue");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName);if(duk_pcall_method(ctx, 1)!=0){duk_push_null(ctx);} int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler int ILibDuktape_EventEmitter_AddOnEx(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func); diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index c7b29c7..51f47a6 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -39,6 +39,7 @@ limitations under the License. #define ILibDuktape_DescriptorEvents_ChainLink "\xFF_DescriptorEvents_ChainLink" #define ILibDuktape_DescriptorEvents_Table "\xFF_DescriptorEvents_Table" +#define ILibDuktape_DescriptorEvents_HTable "\xFF_DescriptorEvents_HTable" #define ILibDuktape_DescriptorEvents_FD "\xFF_DescriptorEvents_FD" #define ILibDuktape_DescriptorEvents_Options "\xFF_DescriptorEvents_Options" #define ILibDuktape_DescriptorEvents_WaitHandle "\xFF_DescriptorEvents_WindowsWaitHandle" @@ -2492,47 +2493,76 @@ duk_ret_t ILibDuktape_DescriptorEvents_Remove(duk_context *ctx) return(0); } #ifdef WIN32 -void ILibDuktape_DescriptorEvents_WaitHandle_EventThread(void *chain, void *user) +char *DescriptorEvents_Status[] = { "NONE", "INVALID_HANDLE", "TIMEOUT", "REMOVED", "EXITING", "ERROR" }; +BOOL ILibDuktape_DescriptorEvents_WaitHandleSink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, void* user) { - if (!ILibMemory_CanaryOK((void*)user)) { return; } - ILibDuktape_DescriptorEvents_WindowsWaitHandle *v = (ILibDuktape_DescriptorEvents_WindowsWaitHandle*)user; + BOOL ret = FALSE; + duk_context *ctx = (duk_context*)((void**)user)[0]; + + int top = duk_get_top(ctx); + duk_push_heapptr(ctx, ((void**)user)[1]); // [events] + duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_HTable); // [events][table] + duk_push_sprintf(ctx, "%p", h); // [events][table][key] + duk_get_prop(ctx, -2); // [events][table][val] + if (!duk_is_null_or_undefined(ctx, -1)) + { + void *hptr = duk_get_heapptr(ctx, -1); + ILibDuktape_EventEmitter_SetupEmit(ctx, hptr, "signaled"); // [events][table][val][emit][this][signaled] + duk_push_string(ctx, DescriptorEvents_Status[(int)status]); // [events][table][val][emit][this][signaled][status] + if (duk_pcall_method(ctx, 2) == 0) // [events][table][val][undef] + { + ILibDuktape_EventEmitter_GetEmitReturn(ctx, hptr, "signaled"); // [events][table][val][undef][ret] + if (duk_is_boolean(ctx, -1) && duk_get_boolean(ctx, -1) != 0) + { + ret = TRUE; + } + } + } + duk_set_top(ctx, top); - UnregisterWait(v->waitHandle); v->waitHandle = NULL; - ILibDuktape_EventEmitter_SetupEmit(v->ctx, v->object, "signaled"); // [emit][this][signaled] - if (duk_pcall_method(v->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(v->ctx, "WaitHandleAPC Error "); } - duk_pop(v->ctx); -} -void __stdcall ILibDuktape_DescriptorEvents_WaitHandleSignaled(void *user, BOOLEAN TimerOrWaitFired) -{ - if (!ILibMemory_CanaryOK(user)) { return; } - ILibDuktape_DescriptorEvents_WindowsWaitHandle *v = (ILibDuktape_DescriptorEvents_WindowsWaitHandle*)user; - Duktape_RunOnEventLoop(v->chain, duk_ctx_nonce(v->ctx), v->ctx, ILibDuktape_DescriptorEvents_WaitHandle_EventThread, NULL, user); + return(ret); } #endif duk_ret_t ILibDuktape_DescriptorEvents_Add(duk_context *ctx) { + ILibDuktape_EventEmitter *e; #ifdef WIN32 if (duk_is_object(ctx, 0) && duk_has_prop_string(ctx, 0, "_ptr")) { + // Adding a Windows Wait Handle HANDLE h = (HANDLE)Duktape_GetPointerProperty(ctx, 0, "_ptr"); if (h != NULL) { - duk_push_object(ctx); // [value] - ILibDuktape_DescriptorEvents_WindowsWaitHandle *v = (ILibDuktape_DescriptorEvents_WindowsWaitHandle*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_DescriptorEvents_WindowsWaitHandle)); - duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_WaitHandle); - - ILibDuktape_EventEmitter *e = ILibDuktape_EventEmitter_Create(ctx); - ILibDuktape_EventEmitter_CreateEventEx(e, "signaled"); - v->ctx = ctx; - v->object = duk_get_heapptr(ctx, -1); - v->chain = Duktape_GetChain(ctx); - v->eventThread = ILibChain_GetMicrostackThreadHandle(v->chain); - if (RegisterWaitForSingleObject(&(v->waitHandle), h, ILibDuktape_DescriptorEvents_WaitHandleSignaled, (void*)v, INFINITE, WT_EXECUTEINPERSISTENTTHREAD | WT_EXECUTEONLYONCE) == 0) + // Normal Add Wait Handle + char *metadata = "DescriptorEvents"; + int timeout = -1; + duk_push_this(ctx); // [events] + ILibChain_Link *link = (ILibChain_Link*)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_DescriptorEvents_ChainLink); + duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_HTable); // [events][table] + duk_push_object(ctx); // [events][table][value] + duk_push_sprintf(ctx, "%p", h); // [events][table][value][key] + duk_dup(ctx, -2); // [events][table][value][key][value] + duk_dup(ctx, 0); + duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_WaitHandle); // [events][table][value][key][value] + if (duk_is_object(ctx, 1)) { duk_dup(ctx, 1); } + else { duk_push_object(ctx); } // [events][table][value][key][value][options] + if (duk_has_prop_string(ctx, -1, "metadata")) { - return(ILibDuktape_Error(ctx, "Error(%d) Calling RegisterWaitForSingleObject() ", GetLastError())); + duk_push_string(ctx, metadata); // [events][table][value][key][value][options][str1] + duk_get_prop_string(ctx, -2, "DescriptorEvents, "); // [events][table][value][key][value][options][str1][str2] + duk_string_concat(ctx, -2); // [events][table][value][key][value][options][str] + metadata = (char*)duk_get_string(ctx, -1); + duk_put_prop_string(ctx, -2, "metadata"); // [events][table][value][key][value][options] } + timeout = Duktape_GetIntPropertyValue(ctx, -1, "timeout", -1); + duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_Options); // [events][table][value][key][value] + duk_put_prop(ctx, -4); // [events][table][value] + e = ILibDuktape_EventEmitter_Create(ctx); + ILibDuktape_EventEmitter_CreateEventEx(e, "signaled"); + ILibChain_AddWaitHandleEx(duk_ctx_chain(ctx), h, timeout, ILibDuktape_DescriptorEvents_WaitHandleSink, link->ExtraMemoryPtr, metadata); return(1); } + return(ILibDuktape_Error(ctx, "Invalid Parameter")); } #endif @@ -2544,14 +2574,22 @@ duk_ret_t ILibDuktape_DescriptorEvents_Add(duk_context *ctx) duk_push_object(ctx); // [obj][table][value] duk_dup(ctx, 0); // [obj][table][value][key] duk_dup(ctx, -2); // [obj][table][value][key][value] - ILibDuktape_EventEmitter *e = ILibDuktape_EventEmitter_Create(ctx); + e = ILibDuktape_EventEmitter_Create(ctx); ILibDuktape_EventEmitter_CreateEventEx(e, "readset"); ILibDuktape_EventEmitter_CreateEventEx(e, "writeset"); ILibDuktape_EventEmitter_CreateEventEx(e, "errorset"); duk_dup(ctx, 0); // [obj][table][value][key][value][FD] duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_FD); // [obj][table][value][key][value] - duk_dup(ctx, 1); duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_Options); - + duk_dup(ctx, 1); // [obj][table][value][key][value][options] + duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_Options); // [obj][table][value][key][value] + char* metadata = Duktape_GetStringPropertyValue(ctx, -1, "metadata", NULL); + if (metadata != NULL) + { + duk_push_string(ctx, "DescriptorEvents, "); // [obj][table][value][key][value][str1] + duk_push_string(ctx, metadata); // [obj][table][value][key][value][str1][str2] + duk_string_concat(ctx, -2); // [obj][table][value][key][value][newStr] + duk_put_prop_string(ctx, -2, "metadata"); // [obj][table][value][key][value] + } duk_put_prop(ctx, -4); // [obj][table][value] return(1); @@ -2618,16 +2656,45 @@ duk_ret_t ILibDuktape_DescriptorEvents_GetCount(duk_context *ctx) #endif return(1); } +char* ILibDuktape_DescriptorEvents_Query(void* chain, void *object, int fd, size_t *dataLen) +{ + char *retVal = ((ILibChain_Link*)object)->MetaData; + *dataLen = strnlen_s(retVal, 1024); + + duk_context *ctx = (duk_context*)((void**)((ILibChain_Link*)object)->ExtraMemoryPtr)[0]; + void *h = ((void**)((ILibChain_Link*)object)->ExtraMemoryPtr)[1]; + if (h == NULL || ctx == NULL || !duk_ctx_is_alive(ctx)) { return(retVal); } + int top = duk_get_top(ctx); + + duk_push_heapptr(ctx, h); // [events] + duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Table); // [events][table] + duk_push_int(ctx, fd); // [events][table][key] + if (duk_has_prop(ctx, -2) != 0) // [events][table] + { + duk_push_int(ctx, fd); duk_get_prop(ctx, -2); // [events][table][val] + duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Options); // [events][table][val][options] + if (!duk_is_null_or_undefined(ctx, -1)) + { + retVal = Duktape_GetStringPropertyValueEx(ctx, -1, "metadata", retVal, dataLen); + } + } + + duk_set_top(ctx, top); + return(retVal); +} void ILibDuktape_DescriptorEvents_Push(duk_context *ctx, void *chain) { ILibChain_Link *link = (ILibChain_Link*)ILibChain_Link_Allocate(sizeof(ILibChain_Link), 2 * sizeof(void*)); - link->MetaData = "ILibDuktape_DescriptorEvents"; + link->MetaData = "DescriptorEvents"; link->PreSelectHandler = ILibDuktape_DescriptorEvents_PreSelect; link->PostSelectHandler = ILibDuktape_DescriptorEvents_PostSelect; + link->QueryHandler = ILibDuktape_DescriptorEvents_Query; duk_push_object(ctx); duk_push_pointer(ctx, link); duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_ChainLink); duk_push_object(ctx); duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_Table); + duk_push_object(ctx); duk_put_prop_string(ctx, -2, ILibDuktape_DescriptorEvents_HTable); + ILibDuktape_CreateFinalizer(ctx, ILibDuktape_DescriptorEvents_Finalizer); ((void**)link->ExtraMemoryPtr)[0] = ctx; From b47af8bb4b8927ba3e49ba3a3ea835c14a02bb05 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Mon, 25 May 2020 14:05:04 -0700 Subject: [PATCH 04/21] Update DescriptorEvents WaitHandle logic --- microscript/ILibDuktape_Polyfills.c | 42 ++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index 51f47a6..c63d7b8 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -40,6 +40,7 @@ limitations under the License. #define ILibDuktape_DescriptorEvents_ChainLink "\xFF_DescriptorEvents_ChainLink" #define ILibDuktape_DescriptorEvents_Table "\xFF_DescriptorEvents_Table" #define ILibDuktape_DescriptorEvents_HTable "\xFF_DescriptorEvents_HTable" +#define ILibDuktape_DescriptorEvents_CURRENT "\xFF_DescriptorEvents_CURRENT" #define ILibDuktape_DescriptorEvents_FD "\xFF_DescriptorEvents_FD" #define ILibDuktape_DescriptorEvents_Options "\xFF_DescriptorEvents_Options" #define ILibDuktape_DescriptorEvents_WaitHandle "\xFF_DescriptorEvents_WindowsWaitHandle" @@ -2483,6 +2484,22 @@ void ILibDuktape_DescriptorEvents_PostSelect(void* object, int slct, fd_set *rea } duk_ret_t ILibDuktape_DescriptorEvents_Remove(duk_context *ctx) { +#ifdef WIN32 + if (duk_is_object(ctx, 0) && duk_has_prop_string(ctx, 0, "_ptr")) + { + // Windows Wait Handle + HANDLE h = (HANDLE)Duktape_GetPointerProperty(ctx, 0, "_ptr"); + duk_push_this(ctx); // [obj] + duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_HTable); // [obj][table] + ILibChain_RemoveWaitHandle(duk_ctx_chain(ctx), h); + duk_push_sprintf(ctx, "%p", h); duk_del_prop(ctx, -2); // [obj][table] + if (Duktape_GetPointerProperty(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT) == h) + { + duk_del_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT); + } + return(0); + } +#endif if (!duk_is_number(ctx, 0)) { return(ILibDuktape_Error(ctx, "Invalid Descriptor")); } ILibForceUnBlockChain(Duktape_GetChain(ctx)); @@ -2507,6 +2524,8 @@ BOOL ILibDuktape_DescriptorEvents_WaitHandleSink(void *chain, HANDLE h, ILibWait if (!duk_is_null_or_undefined(ctx, -1)) { void *hptr = duk_get_heapptr(ctx, -1); + if (status != ILibWaitHandle_ErrorStatus_NONE) { duk_push_sprintf(ctx, "%p", h); duk_del_prop(ctx, -3); } + duk_push_pointer(ctx, h); duk_put_prop_string(ctx, -3, ILibDuktape_DescriptorEvents_CURRENT); ILibDuktape_EventEmitter_SetupEmit(ctx, hptr, "signaled"); // [events][table][val][emit][this][signaled] duk_push_string(ctx, DescriptorEvents_Status[(int)status]); // [events][table][val][emit][this][signaled][status] if (duk_pcall_method(ctx, 2) == 0) // [events][table][val][undef] @@ -2516,7 +2535,17 @@ BOOL ILibDuktape_DescriptorEvents_WaitHandleSink(void *chain, HANDLE h, ILibWait { ret = TRUE; } + } + duk_set_top(ctx, top); + duk_push_heapptr(ctx, ((void**)user)[1]); // [events] + duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_HTable); // [events][table] + + if (ret == FALSE && Duktape_GetPointerProperty(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT) == h) + { + duk_push_sprintf(ctx, "%p", h); // [events][table][key] + duk_del_prop(ctx, -2); // [events][table] } + duk_del_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT); // [events][table] } duk_set_top(ctx, top); @@ -2539,6 +2568,12 @@ duk_ret_t ILibDuktape_DescriptorEvents_Add(duk_context *ctx) duk_push_this(ctx); // [events] ILibChain_Link *link = (ILibChain_Link*)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_DescriptorEvents_ChainLink); duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_HTable); // [events][table] + if (Duktape_GetPointerProperty(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT) == h) + { + // We are adding a wait handle from the event handler for this same signal, so remove this attribute, + // so the signaler doesn't remove the object we are about to put in. + duk_del_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_CURRENT); + } duk_push_object(ctx); // [events][table][value] duk_push_sprintf(ctx, "%p", h); // [events][table][value][key] duk_dup(ctx, -2); // [events][table][value][key][value] @@ -2548,9 +2583,10 @@ duk_ret_t ILibDuktape_DescriptorEvents_Add(duk_context *ctx) else { duk_push_object(ctx); } // [events][table][value][key][value][options] if (duk_has_prop_string(ctx, -1, "metadata")) { - duk_push_string(ctx, metadata); // [events][table][value][key][value][options][str1] - duk_get_prop_string(ctx, -2, "DescriptorEvents, "); // [events][table][value][key][value][options][str1][str2] - duk_string_concat(ctx, -2); // [events][table][value][key][value][options][str] + duk_push_string(ctx, "DescriptorEvents, "); // [events][table][value][key][value][options][str1] + duk_get_prop_string(ctx, -2, "metadata"); // [events][table][value][key][value][options][str1][str2] + duk_string_concat(ctx, -2); // [events][table][value][key][value][options][str1][newstr] + duk_remove(ctx, -2); // [events][table][value][key][value][options][newstr] metadata = (char*)duk_get_string(ctx, -1); duk_put_prop_string(ctx, -2, "metadata"); // [events][table][value][key][value][options] } From aa1460ab04313a621adf79bc83424515dac76b98 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Mon, 25 May 2020 16:45:27 -0700 Subject: [PATCH 05/21] Fixed FFI interop signed/unsigned problem --- microscript/ILibDuktape_GenericMarshal.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/microscript/ILibDuktape_GenericMarshal.c b/microscript/ILibDuktape_GenericMarshal.c index 355e34d..61dae19 100644 --- a/microscript/ILibDuktape_GenericMarshal.c +++ b/microscript/ILibDuktape_GenericMarshal.c @@ -33,11 +33,7 @@ limitations under the License. #include #endif -#if defined(_WIN64) || defined(__LP64__) - typedef uint_fast64_t PTRSIZE; -#else - typedef uint_fast32_t PTRSIZE; -#endif +typedef uintptr_t PTRSIZE; #ifdef WIN32 #define APICALLTYPE __stdcall @@ -1209,7 +1205,7 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvokeAsync(duk_context *ctx) } else if (duk_is_number(ctx, i)) { - data->vars[i] = (PTRSIZE)duk_require_int(ctx, i); + data->vars[i] = (uintptr_t)(duk_require_uint(ctx, i) == 0 ? duk_require_int(ctx, i) : duk_require_uint(ctx, i)); } else if (duk_is_pointer(ctx, i)) { @@ -1320,7 +1316,7 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx) } else if (duk_is_number(ctx, i)) { - vars[i] = (PTRSIZE)duk_require_int(ctx, i); + vars[i] = (uintptr_t)(duk_require_uint(ctx, i) == 0 ? duk_require_int(ctx, i) : duk_require_uint(ctx, i)); } else if (duk_is_pointer(ctx, i)) { From 84385ec7e653340e9460c4ad9878009c769c6bcf Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Mon, 25 May 2020 21:29:45 -0700 Subject: [PATCH 06/21] Fixed memory leak --- microscript/ILibDuktape_Polyfills.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index c63d7b8..340d196 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -1502,16 +1502,15 @@ ILibTransport_DoneState ILibDuktape_Stream_Writable_WriteSink(struct ILibDuktape { void *h; ILibTransport_DoneState retVal = ILibTransport_DoneState_INCOMPLETE; - duk_push_this(stream->ctx); // [writable] duk_get_prop_string(stream->ctx, -1, "_write"); // [writable][_write] duk_swap_top(stream->ctx, -2); // [_write][this] if (stream->Reserved == 0) { duk_push_external_buffer(stream->ctx); // [_write][this][extBuffer] - duk_insert(stream->ctx, -3); // [extBuffer][_write][this] - duk_config_buffer(stream->ctx, -3, buffer, (duk_size_t)bufferLen); - duk_push_buffer_object(stream->ctx, -3, 0, (duk_size_t)bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);// [extBuffer][_write][this][buffer] + duk_config_buffer(stream->ctx, -1, buffer, (duk_size_t)bufferLen); + duk_push_buffer_object(stream->ctx, -1, 0, (duk_size_t)bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);// [_write][this][extBuffer][buffer] + duk_remove(stream->ctx, -2); // [_write][this][buffer] } else { @@ -1544,7 +1543,6 @@ ILibTransport_DoneState ILibDuktape_Stream_Writable_WriteSink(struct ILibDuktape duk_push_heap_stash(stream->ctx); duk_del_prop_string(stream->ctx, -1, Duktape_GetStashKey(h)); duk_pop(stream->ctx); - return(retVal); } duk_ret_t ILibDuktape_Stream_Writable_EndSink_finish(duk_context *ctx) From 110b09a8323cb74c9057ce8cdca99b2b9ba20ef9 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Tue, 26 May 2020 19:02:05 -0700 Subject: [PATCH 07/21] Added buffermode to Polyfill writaableStream --- microscript/ILibDuktape_Polyfills.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index 340d196..0f27249 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -1503,14 +1503,25 @@ ILibTransport_DoneState ILibDuktape_Stream_Writable_WriteSink(struct ILibDuktape void *h; ILibTransport_DoneState retVal = ILibTransport_DoneState_INCOMPLETE; duk_push_this(stream->ctx); // [writable] + int bufmode = Duktape_GetIntPropertyValue(stream->ctx, -1, "bufferMode", 0); duk_get_prop_string(stream->ctx, -1, "_write"); // [writable][_write] duk_swap_top(stream->ctx, -2); // [_write][this] if (stream->Reserved == 0) { - duk_push_external_buffer(stream->ctx); // [_write][this][extBuffer] - duk_config_buffer(stream->ctx, -1, buffer, (duk_size_t)bufferLen); + if (bufmode == 0) + { + // Legacy Mode. We use an external buffer, so a memcpy does not occur. JS must copy memory if it needs to save it + duk_push_external_buffer(stream->ctx); // [_write][this][extBuffer] + duk_config_buffer(stream->ctx, -1, buffer, (duk_size_t)bufferLen); + } + else + { + // Compliant Mode. We copy the buffer into a buffer that will be wholly owned by the recipient + char *cb = (char*)duk_push_fixed_buffer(stream->ctx, (duk_size_t)bufferLen); // [_write][this][extBuffer] + memcpy_s(cb, (size_t)bufferLen, buffer, (size_t)bufferLen); + } duk_push_buffer_object(stream->ctx, -1, 0, (duk_size_t)bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);// [_write][this][extBuffer][buffer] - duk_remove(stream->ctx, -2); // [_write][this][buffer] + duk_remove(stream->ctx, -2); // [_write][this][buffer] } else { From 9e32152877aa48ade56c723f94d5a9243a118a1a Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Tue, 26 May 2020 19:08:58 -0700 Subject: [PATCH 08/21] First rev --- modules/heci.js | 491 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 491 insertions(+) create mode 100644 modules/heci.js diff --git a/modules/heci.js b/modules/heci.js new file mode 100644 index 0000000..bcdb39a --- /dev/null +++ b/modules/heci.js @@ -0,0 +1,491 @@ +/* +Copyright 2020 Intel Corporation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +var GM = null; +var setup = null; +var kernel32 = null; +var duplex = require('stream').Duplex; + + +if (process.platform == 'win32') +{ + GM = require('_GenericMarshal'); + setup = GM.CreateNativeProxy('SetupAPI.dll'); + setup.CreateMethod('SetupDiGetClassDevsA'); + setup.CreateMethod('SetupDiEnumDeviceInterfaces'); + setup.CreateMethod('SetupDiGetDeviceInterfaceDetailA'); + setup.CreateMethod('SetupDiDestroyDeviceInfoList'); + + kernel32 = GM.CreateNativeProxy('Kernel32.dll'); + kernel32.CreateMethod('CloseHandle'); + kernel32.CreateMethod('CreateEventA'); + kernel32.CreateMethod('CreateFileA'); + kernel32.CreateMethod('DeviceIoControl'); + kernel32.CreateMethod('GetOverlappedResult'); + kernel32.CreateMethod('ReadFile'); + kernel32.CreateMethod('WriteFile'); +} + +var DIGCF_DEFAULT = 0x00000001; +var DIGCF_PRESENT = 0x00000002; +var DIGCF_ALLCLASSES = 0x00000004; +var DIGCF_PROFILE = 0x00000008; +var DIGCF_DEVICEINTERFACE = 0x00000010; +var ERROR_INSUFFICIENT_BUFFER = 122; +var GENERIC_READ = 0x80000000; +var GENERIC_WRITE = 0x40000000; +var FILE_SHARE_READ = 0x00000001; +var FILE_SHARE_WRITE = 0x00000002; +var OPEN_EXISTING = 3; +var FILE_FLAG_OVERLAPPED = 0x40000000; +var ERROR_IO_PENDING = 997; + +function heci_create() +{ + var ret = new duplex( + { + 'write': function (chunk, flush) + { + console.log('write:' + chunk.length + ' on ' + this._hashCode()); + if (this._writeoverlapped == null) { throw ('Not Connected'); } + if (chunk.length > this.MaxBufferSize) { throw ('Buffer too large'); } + this._pendingWrites.unshift({ buffer: chunk, flush: flush }); + if (this._pendingWrites.length == 1) + { + // Kickstart the write + this._processWrite(); + } + + return (false); + }, + 'final': function (flush) + { + flush(); + }, + 'read': function(size) + { + console.log('read: (' + size + ') on ' + this._hashCode()); + if (!this._readbuffer) { this._readbuffer = GM.CreateVariable(this.MaxBufferSize); } + + var result = kernel32.ReadFile(this._descriptor, this._readbuffer, this._readbuffer._size, 0, this._readoverlapped); + if(result.Val != 0 || result._LastError == ERROR_IO_PENDING) + { + if(!this._rDescriptorEvent) + { + this._rDescriptorEvent = require('DescriptorEvents').addDescriptor(this._readoverlapped.hEvent, { metadata: 'heci.session [read]' }); + this._rDescriptorEvent.session = this; + this._rDescriptorEvent.on('signaled', function (status) + { + console.log('Read Status: ' + status + ' on ' + this.session._hashCode()); + if(status != 'NONE') + { + console.log('****** ' + status + '******'); + this.session.push(null); + return; + } + var bytesRead = GM.CreateVariable(4); + var result; + if((result=kernel32.GetOverlappedResult(this.session._descriptor, this.session._readoverlapped, bytesRead, 0)).Val != 0) + { + var buffer = this.session._readbuffer.toBuffer().slice(0, bytesRead.toBuffer().readUInt32LE()); + console.log(buffer.length + ' bytes READ'); + + var pushResult = this.session.push(buffer); + if (this.session._options.noPipeline != 0 && this.session._pendingWrites.length>0) + { + // Unlock a write + console.log('pendingWriteCount: ' + this.session._pendingWrites.length); + var item = this.session._pendingWrites.pop(); + console.log('pendingWriteCount is now: ' + this.session._pendingWrites.length); + + if (this.session._pendingWrites.length > 0) + { + this.session._processWrite(); + } + else + { + console.log('Write/Flush'); + item.flush(); + } + } + + if (pushResult) + { + // We can read more, because data is still flowing + console.log('READING MORE on ' + this.session._hashCode()); + var result = kernel32.ReadFile(this.session._descriptor, this.session._readbuffer, this.session._readbuffer._size, 0, this.session._readoverlapped); + if(result.Val != 0 || result._LastError == ERROR_IO_PENDING) + { + return (true); + } + else + { + console.log('Sometype of error: ' + result._LastError); + this.session.push(null); + } + } + } + else + { + console.log('READ_OVERLAPPED_ERROR: ' + result._LastError + ' on ' + this.session._hashCode()); + } + + }); + } + } + else + { + console.log('Some Other Error: ' + result._LastError); + } + } + }); + ret._ObjectID = 'heci.session'; + ret.bufferMode = 1; + ret._ioctls = []; + ret._pendingWrites = []; + ret.heciParent = this; + + require('events').EventEmitter.call(ret, true) + .createEvent('connect') + .createEvent('error') + .addMethod('connect', function _connect(guid, options) + { + console.log('connect()'); + this.doIoctl(this.heciParent.IOCTL.CLIENT_CONNECT, guid, Buffer.alloc(16), function _onconnect(status, buffer, opt) + { + if(status!=0) + { + console.log('HECI Connection Error [' + this.LastError + ']'); + this.emit('error', 'HECI Connection Error [' + this.LastError + ']'); + return; + } + if(buffer.length <=4) + { + // Invalid Response + this.emit('error', 'HECI Connection Error [INVALID RESPONSE]'); + return; + } + Object.defineProperty(this, "MaxBufferSize", { value: buffer.readUInt32LE() }); + this._options = opt; + this._readoverlapped = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 20); + this._writeoverlapped = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 20); + this._readoverlapped.hEvent = kernel32.CreateEventA(0, 1, 0, 0); + this._writeoverlapped.hEvent = kernel32.CreateEventA(0, 1, 0, 0); + this._readoverlapped.hEvent.pointerBuffer().copy(this._readoverlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer()); + this._writeoverlapped.hEvent.pointerBuffer().copy(this._writeoverlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer()); + + console.log('Connected, buffer size: ' + this.MaxBufferSize); + this._read(this.MaxBufferSize); + this.emit('connect'); + }, options); + }) + .addMethod('descriptorPath', function _descriptorPath() + { + console.log(' heci.createDescriptor()'); + + var result; + var ii; + var deviceDetail; + var bufferSize = GM.CreateVariable(4); // DWORD + var heciguid = GM.CreateVariable(this.heciParent.GUIDS.HECI); + var deviceInfo = setup.SetupDiGetClassDevsA(heciguid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (deviceInfo.Val == -1) + { + console.log('... Unable to acquire [deviceInfo]'); + throw ('unable to acquire [deviceInfo]'); + } + console.log('... acquired [deviceInfo]'); + + + var interfaceData = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 28); + interfaceData.toBuffer().writeUInt32LE(interfaceData._size, 0); + + for (ii = 0; setup.SetupDiEnumDeviceInterfaces(deviceInfo, 0, heciguid, ii, interfaceData).Val != 0; ++ii) + { + // Found our device instance + if ((result = setup.SetupDiGetDeviceInterfaceDetailA(deviceInfo, interfaceData, 0, 0, bufferSize, 0)).Val == 0) + { + if (result._LastError != ERROR_INSUFFICIENT_BUFFER) + { + continue; + } + } + + // Allocate a big enough buffer to get detail data + deviceDetail = GM.CreateVariable(bufferSize.toBuffer().readUInt32LE()); + deviceDetail.toBuffer().writeUInt32LE(GM.PointerSize == 8 ? 8 : 5, 0); + + // Try again to get the device interface detail info + if (setup.SetupDiGetDeviceInterfaceDetailA(deviceInfo, interfaceData, deviceDetail, bufferSize, 0, 0).Val == 0) + { + deviceDetail = NULL; + continue; + } + break; + } + setup.SetupDiDestroyDeviceInfoList(deviceInfo); + if (deviceDetail == null) + { + console.log('... failed to acquire [deviceDetail]'); + throw ('unable to acquire [deviceDetail]'); + } + + var devPath = deviceDetail.Deref(4, GM.PointerSize); + return (devPath.String); + }) + .addMethod('createDescriptor', function _createDescriptor(path) + { + var devPath = GM.CreateVariable(path); + var ret = kernel32.CreateFileA(devPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + if (ret.Val == -1) + { + console.log('... failed to acquire [descriptor]'); + throw ('failed to acquire descriptor'); + } + console.log('... acquired [DESCRIPTOR]'); + return (ret); + }); + if (process.platform == 'win32') + { + ret._overlapped = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 20); + ret._overlapped.hEvent = kernel32.CreateEventA(0, 1, 0, 0); + + var overlapped_eventptr = ret._overlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer(); + ret._overlapped.hEvent.pointerBuffer().copy(overlapped_eventptr); + } + ret.disconnect = function disconnect() + { + // Clean up all Handles and Descriptors + console.log('DISCONNECT on ' + this._hashCode()); + + + // + // doIoctl() + // + if (this._descriptorEvent) + { + if (this._overlapped) { require('DescriptorEvents').removeDescriptor(this._overlapped.hEvent); } + this._descriptorEvent = null; + } + if (this._overlapped) + { + kernel32.CloseHandle(this._overlapped.hEvent); + this._overlapped = null; + } + + // + // Read + // + if (this._rDescriptorEvent) + { + if (this._readoverlapped) { require('DescriptorEvents').removeDescriptor(this._readoverlapped.hEvent); } + this._rDescriptorEvent = null; + } + if (this._readoverlapped) + { + kernel32.CloseHandle(this._readoverlapped.hEvent); + this._readoverlapped = null; + } + + // + // Write + // + if (this._wDescriptorEvent) + { + if (this._writeoverlapped) { require('DescriptorEvents').removeDescriptor(this._writeoverlapped.hEvent); } + this._wDescriptorEvent = null; + } + if (this._writeoverlapped) + { + kernel32.CloseHandle(this._writeoverlapped.hEvent); + this._writeoverlapped = null; + } + + // + // HECI + // + if (this._descriptor) + { + kernel32.CloseHandle(this._descriptor); + this._descriptor = null; + } + + }; + ret.doIoctl = function doIoctl(code, inputBuffer, outputBuffer, callback) + { + console.log('doIoctl()'); + if(typeof(callback)!='function') { throw('Callback not specified');} + var i; + var parms = []; + for (i = 4; i < arguments.length; ++i) + { + parms.push(arguments[i]); + } + + this._ioctls.unshift({ code: code, input: inputBuffer, output: outputBuffer, callback: callback, parms: parms }); + if(this._ioctls.length == 1) + { + // First IOCTL, so we need to send the first one + this._send(this._ioctls.peek()); + } + }; + ret._send = function _send(options) + { + if(this._descriptor == null) + { + this._descriptor = this.createDescriptor(this.descriptorPath()); + this._descriptorEvent = require('DescriptorEvents').addDescriptor(this._overlapped.hEvent, {metadata: 'heci'}); + this._descriptorEvent.session = this; + this._descriptorEvent.on('signaled', function(status) + { + var data = this.session._ioctls.pop(); + if(status == 'NONE') + { + var bytesRead = GM.CreateVariable(4); + var result = kernel32.GetOverlappedResult(this.session._descriptor, this.session._overlapped, bytesRead, 0); + if(result.Val != 0) + { + var out = data.output; + try + { + out.slice(0,bytesRead.toBuffer().readUInt32LE()); + } + catch(e) + { + out = null; + } + data.parms.unshift(out); + data.parms.unshift(0); + this.session.LastError = 'NONE'; + } + else + { + data.parms.unshift(null); + data.parms.unshift(1); + this.session.LastError = 'OVERLAPPED_ERROR: ' + result._LastError; + } + } + else + { + data.parms.unshift(null); + data.parms.unshift(1); + this.session.LastError = status; + } + try + { + data.callback.apply(this.session, data.parms); + } + catch(ue) + { + process.emit('uncaughtException', ue); + } + if(this.session._ioctls.length > 0) + { + // Still more IOCTLs to send + this.session._send(this.session._ioctls.peek()); + return (true); + } + }); + } + kernel32.DeviceIoControl(this._descriptor, options.code, GM.CreateVariable(options.input), options.input.length, GM.CreateVariable(options.output), options.output.length, 0, this._overlapped); + }; + ret._processWrite = function _processWrite() + { + var chunk = this._pendingWrites.peek(); + console.log('_WRITING: ' + chunk.buffer.length + ' bytes' + ' on ' + this._hashCode()); + if (chunk.buffer.length == 23) + { + console.log(chunk.buffer.toString('hex')); + GM.CreateVariable(chunk.buffer)._debug(); + } + var result = kernel32.WriteFile(this._descriptor, GM.CreateVariable(chunk.buffer), chunk.buffer.length, 0, this._writeoverlapped); + if(result.Val != 0 || result._LastError == ERROR_IO_PENDING) + { + if(!this._wDescriptorEvent) + { + this._wDescriptorEvent = require('DescriptorEvents').addDescriptor(this._writeoverlapped.hEvent, { metadata: 'heci.session [write]' }); + this._wDescriptorEvent.session = this; + this._wDescriptorEvent.on('signaled', this._processWrite_signaled); + } + } + else + { + console.log('Write Error: ' + result._LastError); + } + }; + ret._processWrite_signaled = function _processWrite_signaled(status) + { + console.log('Write Signaled: ' + status); + if(status == 'NONE') + { + // No Errors + var bytesWritten = GM.CreateVariable(4); + var result = kernel32.GetOverlappedResult(this.session._descriptor, this.session._writeoverlapped, bytesWritten, 0); + if(result.Val != 0) + { + console.log(bytesWritten.toBuffer().readUInt32LE() + ' bytes written'); + console.log('noPipeline = ' + this.session._options.noPipeline, this.session._pendingWrites.length); + if(this.session._options.noPipeline==null || this.session._options.noPipeline == false) + { + var item = this.session._pendingWrites.pop(); + if (this.session._pendingWrites.length > 0) + { + this.session._processWrite(); + } + else + { + console.log('Write/Flush'); + item.flush(); + } + return (true); + } + } + } + }; + return (ret); +} + +var ioctl = {}; +Object.defineProperty(ioctl, 'HECI_VERSION', { value: 0x8000E000 }); +Object.defineProperty(ioctl, 'CLIENT_CONNECT', { value: 0x8000E004 }); +var guids = {}; +Object.defineProperty(guids, 'AMT', { value: Buffer.from('2800F812B7B42D4BACA846E0FF65814C', 'hex') }); +Object.defineProperty(guids, 'LME', { value: Buffer.from('DBA4336776047B4EB3AFBCFC29BEE7A7', 'hex') }); +if (process.platform == 'win32') +{ + Object.defineProperty(guids, 'HECI', { value: Buffer.from('34FFD1E25834A94988DA8E6915CE9BE5', 'hex') }); +} + + +module.exports = { _ObjectID: 'heci', IOCTL: ioctl, GUIDS: guids, create: heci_create }; +Object.defineProperty(module.exports, "supported", { + get: function () + { + try + { + var p = this.create().descriptorPath(); + console.log(p); + var d = this.create().createDescriptor(p); + console.log(d.Val); + return(true); + } + catch(e) + { + console.log(e); + return (false); + } + } +}); \ No newline at end of file From b24a9ec638f9bac931bb8bd418982cd6fe407310 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 27 May 2020 03:17:23 -0700 Subject: [PATCH 09/21] Linux Update for ioctl and fs.read --- microscript/ILibDuktape_Polyfills.c | 20 +++ microscript/ILibDuktape_fs.c | 201 ++++++++++++++++++++++++++-- 2 files changed, 209 insertions(+), 12 deletions(-) diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index 0f27249..58e39c8 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -2782,6 +2782,23 @@ duk_ret_t ILibDuktape_Polyfills_isBuffer(duk_context *ctx) duk_push_boolean(ctx, duk_is_buffer_data(ctx, 0)); return(1); } +#if defined(_POSIX) && !defined(__APPLE__) && !defined(_FREEBSD) +duk_ret_t ILibDuktape_ioctl_func(duk_context *ctx) +{ + int fd = (int)duk_require_int(ctx, 0); + int code = (int)duk_require_int(ctx, 1); + duk_size_t outBufferLen = 0; + char *outBuffer = Duktape_GetBuffer(ctx, 2, &outBufferLen); + + duk_push_int(ctx, ioctl(fd, _IOC(_IOC_READ | _IOC_WRITE, 'H', code, outBufferLen), outBuffer) ? errno : 0); + return(1); +} +void ILibDuktape_ioctl_Push(duk_context *ctx, void *chain) +{ + duk_push_c_function(ctx, ILibDuktape_ioctl_func, DUK_VARARGS); + ILibDuktape_WriteID(ctx, "ioctl"); +} +#endif void ILibDuktape_uuidv4_Push(duk_context *ctx, void *chain) { duk_push_object(ctx); @@ -2819,6 +2836,9 @@ void ILibDuktape_Polyfills_Init(duk_context *ctx) ILibDuktape_ModSearch_AddHandler(ctx, "ChainViewer", ILibDuktape_ChainViewer_Push); ILibDuktape_ModSearch_AddHandler(ctx, "DescriptorEvents", ILibDuktape_DescriptorEvents_Push); ILibDuktape_ModSearch_AddHandler(ctx, "uuid/v4", ILibDuktape_uuidv4_Push); +#if defined(_POSIX) && !defined(__APPLE__) && !defined(_FREEBSD) + ILibDuktape_ModSearch_AddHandler(ctx, "ioctl", ILibDuktape_ioctl_Push); +#endif // Global Polyfills diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c index b4fbd2d..0f96663 100644 --- a/microscript/ILibDuktape_fs.c +++ b/microscript/ILibDuktape_fs.c @@ -21,6 +21,7 @@ limitations under the License. #include #include #include +#include #endif #include "microstack/ILibParsers.h" @@ -66,6 +67,9 @@ limitations under the License. #define FS_NOTIFY_DISPATCH_PTR "\xFF_FSWatcher_NotifyDispatchPtr" #define FS_CHAIN_PTR "\xFF_FSWatcher_ChainPtr" #define FS_WATCH_PATH "\xFF_FSWatcher_Path" +#define FS_EVENT_R_DESCRIPTORS "\xFF_FSEventReadDescriptors" +#define FS_EVENT_W_DESCRIPTORS "\xFF_FSEventWriteDescriptors" +#define FS_EVENT_DESCRIPTORS_IO "\xFF_FSEventDescriptors_IO" #if defined(_POSIX) && !defined(__APPLE__) typedef struct ILibDuktape_fs_linuxWatcher @@ -197,6 +201,17 @@ FILE* ILibDuktape_fs_getFilePtr(duk_context *ctx, int fd) duk_ret_t ILibDuktape_fs_closeSync(duk_context *ctx) { int fd = duk_require_int(ctx, 0); + + if (fd < 65535) + { +#ifdef WIN32 + _close(fd); +#else + close(fd); +#endif + return(0); + } + FILE *f; char *key = ILibScratchPad; sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%d", fd); @@ -263,21 +278,36 @@ duk_ret_t ILibDuktape_fs_openSync(duk_context *ctx) #else char *path = ILibDuktape_fs_fixLinuxPath((char*)duk_require_string(ctx, 0)); #endif - char *flags = (char*)duk_require_string(ctx, 1); - int retVal = -1; - - if (nargs < 2) { return(ILibDuktape_Error(ctx, "Too few arguments")); } - - retVal = ILibDuktape_fs_openSyncEx(ctx, path, flags, NULL); - if (retVal > 0) + if (duk_is_string(ctx, 1)) { - duk_push_int(ctx, retVal); - return 1; + char *flags = (char*)duk_require_string(ctx, 1); + int retVal = -1; + + if (nargs < 2) { return(ILibDuktape_Error(ctx, "Too few arguments")); } + + retVal = ILibDuktape_fs_openSyncEx(ctx, path, flags, NULL); + if (retVal > 0) + { + duk_push_int(ctx, retVal); + return 1; + } + else + { + return(ILibDuktape_Error(ctx, "fs.openSync(): Error opening '%s'", path)); + } } - else + int flags = (int)duk_require_int(ctx, 1); +#ifdef WIN32 + int fd = -1; + if (_wsopen_s(&fd, (wchar_t*)ILibDuktape_String_UTF8ToWide(ctx, path), flags, 0, 0) != 0) { - return(ILibDuktape_Error(ctx, "fs.openSync(): Error opening '%s'", path)); + return(ILibDuktape_Error(ctx, "openSync() Error: %d ", errno)); } + duk_push_int(ctx, fd); +#else + duk_push_int(ctx, open(path, flags)); +#endif + return(1); } duk_ret_t ILibDuktape_fs_readSync(duk_context *ctx) { @@ -303,6 +333,146 @@ duk_ret_t ILibDuktape_fs_readSync(duk_context *ctx) return(ILibDuktape_Error(ctx, "FS I/O Error")); } +duk_ret_t ILibDuktape_fs_read_readsetSink(duk_context *ctx) +{ + int fd = duk_require_int(ctx, 0); + duk_push_this(ctx); // [DescriptorEvents] + duk_get_prop_string(ctx, -1, FS_EVENT_DESCRIPTORS_IO); // [DescriptorEvents][pending] + duk_array_pop(ctx, -1); // [DescriptorEvents][pending][options] + + duk_size_t bufferLen; + char *buffer = Duktape_GetBufferProperty(ctx, -1, "buffer"); + duk_size_t offset = (duk_size_t)Duktape_GetIntPropertyValue(ctx, -1, "offset", 0); + duk_size_t length = (duk_size_t)Duktape_GetIntPropertyValue(ctx, -1, "length", (int)bufferLen); + int bytesRead = read(fd, buffer + offset, length); + int status = bytesRead < 0 ? errno : 0; + + duk_get_prop_string(ctx, -1, "callback"); // [DescriptorEvents][pending][options][callback] + duk_get_prop_string(ctx, -1, "call"); duk_swap_top(ctx, -2);// ..............[pending][options][call][this] + duk_eval_string(ctx, "require('fs');"); // ..............[pending][options][call][fn/this][this] + duk_push_int(ctx, status); // ..............[pending][options][call][fn/this][this][err/status] + duk_push_int(ctx, bytesRead); // ..............[pending][options][call][fn/this][this][err/status][bytesRead] + duk_get_prop_string(ctx, -6, "buffer"); // ..............[pending][options][call][fn/this][this][err/status][bytesRead][buffer] + if (duk_pcall_method(ctx, 4) != 0) // [DescriptorEvents][pending][options][val] + { + ILibDuktape_Process_UncaughtExceptionEx(ctx, "fs.read() Callback Error: %s ", duk_safe_to_string(ctx, -1)); + } + duk_pop_2(ctx); // [DescriptorEvents][pending] + if (duk_get_length(ctx, -1) == 0) + { + // No more pending I/O operations, so we can cleanup the DescriptorEvents + duk_eval_string(ctx, "require('DescriptorEvents');"); // .....[DescriptorEvents] + duk_get_prop_string(ctx, -1, "removeDescriptor"); // .....[DescriptorEvents][removeDescriptor] + duk_swap_top(ctx, -2); // .....[removeDescriptor][this] + duk_push_int(ctx, fd); // .....[removeDescriptor][this][fd] + duk_pcall_method(ctx, 1); duk_pop(ctx); // [DescriptorEvents][pending] + + duk_eval_string(ctx, "require('fs');"); // [DescriptorEvents][pending][FS] + duk_get_prop_string(ctx, -1,FS_EVENT_R_DESCRIPTORS);// [DescriptorEvents][pending][FS][table] + duk_del_prop_index(ctx, -1, fd); + } + return(0); +} +duk_ret_t ILibDuktape_fs_read(duk_context *ctx) +{ + int top = duk_get_top(ctx); + if (top > 2) + { + // Simplify flow, by converting to an options object + duk_push_this(ctx); // [fs] + duk_get_prop_string(ctx, -1, "read"); // [fs][read] + duk_swap_top(ctx, -2); // [read][this] + duk_dup(ctx, 0); // [read][this][fd] + duk_push_object(ctx); // [read][this][fd][options] + duk_dup(ctx, 1); duk_put_prop_string(ctx, -2, "buffer"); + duk_dup(ctx, 2); duk_put_prop_string(ctx, -2, "offset"); + duk_dup(ctx, 3); duk_put_prop_string(ctx, -2, "length"); + duk_dup(ctx, 4); duk_put_prop_string(ctx, -2, "position"); + duk_dup(ctx, 5); // [read][this][fd][options][callback] + duk_call_method(ctx, 3); + return(1); + } + if (top == 2 && duk_is_function(ctx, 1)) + { + // Simplify flow, by converting to a default options object + duk_push_this(ctx); // [fs] + duk_get_prop_string(ctx, -1, "read"); // [fs][read] + duk_swap_top(ctx, -2); // [read][this] + duk_dup(ctx, 0); // [read][this][fd] + duk_push_object(ctx); // [read][this][fd][options] + duk_push_fixed_buffer(ctx, 16384); // [read][this][fd][options][buffer] + duk_push_buffer_object(ctx, -1, 0, 16384, DUK_BUFOBJ_NODEJS_BUFFER); + duk_remove(ctx, -2); // [read][this][fd][options][buffer] + duk_put_prop_string(ctx, -2, "buffer"); // [read][this][fd][options] + duk_push_int(ctx, 0); duk_put_prop_string(ctx, -2, "offset"); + duk_push_int(ctx, 16384); duk_put_prop_string(ctx, -2, "length"); + duk_push_null(ctx); duk_put_prop_string(ctx, -2, "position"); + duk_dup(ctx, 1); // [read][this][fd][options][callback] + duk_call_method(ctx, 3); + return(1); + } + if (!(duk_is_number(ctx, 0) && duk_is_object(ctx, 1) && duk_is_function(ctx, 2))) { return(ILibDuktape_Error(ctx, "Invalid Parameters")); } + int fd = (int)duk_require_int(ctx, 0); + + // First, we'll attempt to read, and see if it completes or is pending + duk_size_t bufferLen; + char *buffer = Duktape_GetBufferProperty(ctx, 1, "buffer"); + duk_size_t offset = (duk_size_t)Duktape_GetIntPropertyValue(ctx, 1, "offset", 0); + duk_size_t length = (duk_size_t)Duktape_GetIntPropertyValue(ctx, 1, "length", (int)bufferLen); + int bytesRead = read(fd, buffer + offset, length); + if (bytesRead >= 0 || (errno != E_AGAIN && errno != E_WOULDBLOCK)) + { + // Completed + int errStatus = bytesRead >= 0 ? 0 : errno; + duk_dup(ctx, 2); // [func] + duk_get_prop_string(ctx, -1, "call"); // [func][call] + duk_swap_top(ctx, -2); // [call][this] + duk_push_this(ctx); // [call][this][this/fs] + duk_push_int(ctx, errStatus); // [call][this][this/fs][err/status] + duk_push_int(ctx, bytesRead); // [call][this][this/fs][err/status][bytesRead] + duk_get_prop_string(ctx, 1, "buffer"); // [call][this][this/fs][err/status][bytesRead][buffer] + duk_call_method(ctx, 4); + return(0); + } + + // + // Setup the EventDescriptor listener, because the read did not complete + // + duk_push_this(ctx); // [fs] + duk_get_prop_string(ctx, -1, FS_EVENT_R_DESCRIPTORS); // [fs][table] + if (!duk_has_prop_index(ctx, -1, fd)) + { + duk_eval_string(ctx, "require('DescriptorEvents');"); // [fs][table][DE] + duk_get_prop_string(ctx, -1, "addDescriptor"); // [fs][table][DE][addDescriptor] + duk_swap_top(ctx, -2); // [fs][table][addDescriptor][this] + duk_push_int(ctx, fd); // [fs][table][addDescriptor][this][fd] + duk_push_object(ctx); // [fs][table][addDescriptor][this][fd][options] + duk_push_true(ctx); duk_put_prop_string(ctx, -2, "readset"); + if (duk_has_prop_string(ctx, 1, "metadata")) + { + duk_push_string(ctx, "fs.read(), "); // [fs][table][addDescriptor][this][fd][options][str] + duk_get_prop_string(ctx, 1, "metadata"); // [fs][table][addDescriptor][this][fd][options][str][str2] + duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [fs][table][addDescriptor][this][fd][options][metadata] + duk_put_prop_string(ctx, -2, "metadata"); // [fs][table][addDescriptor][this][fd][options] + } + else + { + duk_push_string(ctx, "fs.read()"); duk_put_prop_string(ctx, -2, "metadata"); + } + duk_call_method(ctx, 2); // [fs][table][descriptorEvent] + ILibDuktape_EventEmitter_SetupOn(ctx, duk_get_heapptr(ctx, -1), "readset"); // ........[on][this][readset] + duk_push_c_function(ctx, ILibDuktape_fs_read_readsetSink, DUK_VARARGS); // ........[on][this][readset][func] + duk_call_method(ctx, 2); duk_pop(ctx); // [fs][table][descriptorEvent] + duk_push_array(ctx); duk_put_prop_string(ctx, -1, FS_EVENT_DESCRIPTORS_IO); + duk_put_prop_index(ctx, -2, fd); // [fs][table] + } + duk_get_prop_index(ctx, -1, fd); // [fs][table][desriptorEvent] + duk_get_prop_string(ctx, -1, FS_EVENT_DESCRIPTORS_IO); // [fs][table][desriptorEvent][pending] + duk_dup(ctx, 1); // [fs][table][desriptorEvent][pending][options] + duk_dup(ctx, 2); duk_put_prop_string(ctx, -2, "callback"); // [fs][table][desriptorEvent][pending][options] + duk_array_unshift(ctx, -2); // [fs][table][desriptorEvent][pending] + return(0); +} duk_ret_t ILibDuktape_fs_writeSync(duk_context *ctx) { int nargs = duk_get_top(ctx); @@ -1644,16 +1814,22 @@ void ILibDuktape_fs_PUSH(duk_context *ctx, void *chain) duk_push_pointer(ctx, chain); // [fs][chain] duk_put_prop_string(ctx, -2, FS_CHAIN_PTR); // [fs] - duk_push_int(ctx, 0); // [fs][nextFD] + duk_push_int(ctx, 65535); // [fs][nextFD] duk_put_prop_string(ctx, -2, FS_NextFD); // [fs] duk_push_object(ctx); // [fs][descriptors] duk_put_prop_string(ctx, -2, FS_FDS); // [fs] + duk_push_object(ctx); + duk_put_prop_string(ctx, -2, FS_EVENT_R_DESCRIPTORS); + duk_push_object(ctx); + duk_put_prop_string(ctx, -2, FS_EVENT_W_DESCRIPTORS); + ILibDuktape_CreateInstanceMethod(ctx, "closeSync", ILibDuktape_fs_closeSync, 1); ILibDuktape_CreateInstanceMethod(ctx, "openSync", ILibDuktape_fs_openSync, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "readSync", ILibDuktape_fs_readSync, 5); ILibDuktape_CreateInstanceMethod(ctx, "writeSync", ILibDuktape_fs_writeSync, DUK_VARARGS); + ILibDuktape_CreateInstanceMethod(ctx, "read", ILibDuktape_fs_read, DUK_VARARGS); #ifdef WIN32 ILibDuktape_CreateInstanceMethod(ctx, "_readdirSync", ILibDuktape_fs_readdirSync, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "_statSync", ILibDuktape_fs_statSync, 1); @@ -1701,6 +1877,7 @@ void ILibDuktape_fs_PUSH(duk_context *ctx, void *chain) }\ ds.on('close', function onCopyFileDone(){delete this.ss.fs._copyStreams[this.ss.id];});\ };\ + exports.constants = {O_RDONLY: 0, O_WRONLY: 1, O_RDWR: 4, O_NONBLOCK: 2048};\ exports.copyFileSync = function copyFileSync(src, dest)\ {\ var buffer = this.readFileSync(src, {flags: 'rb'});\ From 2c3585627b935ad55c6a1094de1282d661c322e6 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 27 May 2020 16:57:57 -0700 Subject: [PATCH 10/21] linux update --- microscript/ILibDuktape_fs.c | 202 ++++++++++++++++++++++++++++++++--- modules/amt-mei.js | 11 +- modules/heci.js | 162 ++++++++++++++++++++++++---- 3 files changed, 338 insertions(+), 37 deletions(-) diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c index 0f96663..c62e9b7 100644 --- a/microscript/ILibDuktape_fs.c +++ b/microscript/ILibDuktape_fs.c @@ -341,18 +341,22 @@ duk_ret_t ILibDuktape_fs_read_readsetSink(duk_context *ctx) duk_array_pop(ctx, -1); // [DescriptorEvents][pending][options] duk_size_t bufferLen; - char *buffer = Duktape_GetBufferProperty(ctx, -1, "buffer"); + char *buffer = Duktape_GetBufferPropertyEx(ctx, -1, "buffer", &bufferLen); duk_size_t offset = (duk_size_t)Duktape_GetIntPropertyValue(ctx, -1, "offset", 0); duk_size_t length = (duk_size_t)Duktape_GetIntPropertyValue(ctx, -1, "length", (int)bufferLen); +#ifdef WIN32 + int bytesRead = _read(fd, buffer + offset, (unsigned int)length); +#else int bytesRead = read(fd, buffer + offset, length); +#endif int status = bytesRead < 0 ? errno : 0; duk_get_prop_string(ctx, -1, "callback"); // [DescriptorEvents][pending][options][callback] - duk_get_prop_string(ctx, -1, "call"); duk_swap_top(ctx, -2);// ..............[pending][options][call][this] - duk_eval_string(ctx, "require('fs');"); // ..............[pending][options][call][fn/this][this] - duk_push_int(ctx, status); // ..............[pending][options][call][fn/this][this][err/status] - duk_push_int(ctx, bytesRead); // ..............[pending][options][call][fn/this][this][err/status][bytesRead] - duk_get_prop_string(ctx, -6, "buffer"); // ..............[pending][options][call][fn/this][this][err/status][bytesRead][buffer] + duk_eval_string(ctx, "require('fs');"); // ..............[pending][options][callback][this] + duk_push_int(ctx, status); // ..............[pending][options][callback][this][err/status] + duk_push_int(ctx, bytesRead); // ..............[pending][options][callback][this][err/status][bytesRead] + duk_get_prop_string(ctx, -5, "buffer"); // ..............[pending][options][callback][this][err/status][bytesRead][buffer] + duk_dup(ctx, -6); // ..............[pending][options][callback][this][err/status][bytesRead][buffer][options] if (duk_pcall_method(ctx, 4) != 0) // [DescriptorEvents][pending][options][val] { ILibDuktape_Process_UncaughtExceptionEx(ctx, "fs.read() Callback Error: %s ", duk_safe_to_string(ctx, -1)); @@ -373,6 +377,172 @@ duk_ret_t ILibDuktape_fs_read_readsetSink(duk_context *ctx) } return(0); } +duk_ret_t ILibDuktape_fs_write_writeset_sink(duk_context *ctx) +{ + int fd = (int)duk_require_int(ctx, 0); + duk_push_this(ctx); // [events] + duk_get_prop_string(ctx, -1, FS_EVENT_DESCRIPTORS_IO); // [events][pending] + duk_size_t bufferLen; + char *buffer = Duktape_GetBufferPropertyEx(ctx, -1, "buffer", &bufferLen); + int performCleanup = 0; +#ifdef WIN32 + int bytesWritten = _write(fd, buffer, (unsigned int)bufferLen); +#else + int bytesWritten = write(fd, buffer, bufferLen); +#endif + if (bytesWritten == bufferLen) + { + // Complete + duk_del_prop_string(ctx, -2, FS_EVENT_DESCRIPTORS_IO); + duk_get_prop_string(ctx, -1, "callback"); // [events][pending][callback] + duk_eval_string(ctx, "require('fs');"); // [events][pending][callback][this] + duk_push_int(ctx, 0); // [events][pending][callback][this][status] + duk_get_prop_string(ctx, -5, "original"); // [events][pending][callback][this][status][buffer] + duk_get_length(ctx, -1); // [events][pending][callback][this][status][buffer][length] + duk_swap_top(ctx, -2); // [events][pending][callback][this][status][bytesWritten][buffer] + duk_get_prop_string(ctx, -6, "opt"); // [events][pending][callback][this][status][bytesWritten][buffer][options] + if (duk_pcall_method(ctx, 4) != 0) // [events][pending][ret] + { + ILibDuktape_Process_UncaughtExceptionEx(ctx, "fs.write() Callback Error: %s ", duk_safe_to_string(ctx, -1)); + } + duk_pop_2(ctx); // [events] + if (!duk_has_prop_string(ctx, -1, FS_EVENT_DESCRIPTORS_IO)) + { + performCleanup = 1; + } + } + else + { + if (bytesWritten > 0) // [events][pending] + { + duk_get_prop_string(ctx, -1, "buffer"); // [events][pending][buffer] + duk_buffer_slice(ctx, -1, bytesWritten, (int)bufferLen - bytesWritten); // ....][buffer][sliced] + duk_put_prop_string(ctx, -3, "buffer"); // [events][pending][oldBuffer] + } + else + { + int e = errno; + if (e != EAGAIN && e != EWOULDBLOCK && e != EINTR) // [events][pending] + { + // Error occured + duk_del_prop_string(ctx, -2, FS_EVENT_DESCRIPTORS_IO); + performCleanup = 1; + + duk_get_prop_string(ctx, -1, "callback"); // [events][pending][callback] + duk_eval_string(ctx, "require('fs');"); // [events][pending][callback][this] + duk_push_int(ctx, e); // [events][pending][callback][this][status] + duk_get_prop_string(ctx, -5, "original"); // [events][pending][callback][this][status][buffer] + duk_push_int(ctx, 0); // [events][pending][callback][this][status][buffer][written] + duk_swap_top(ctx, -2); // [events][pending][callback][this][status][bytesWritten][buffer] + duk_get_prop_string(ctx, -6, "opt"); // [events][pending][callback][this][status][bytesWritten][buffer][options] + if (duk_pcall_method(ctx, 4) != 0) // [events][pending][ret] + { + ILibDuktape_Process_UncaughtExceptionEx(ctx, "fs.write() Callback Error: %s ", duk_safe_to_string(ctx, -1)); + } + } + } + } + if (performCleanup != 0) + { + // No more pending writes, so we can do some cleanup + duk_eval_string(ctx, "require('fs');"); // ... [fs] + duk_get_prop_string(ctx, -1, FS_EVENT_W_DESCRIPTORS); // ... [fs][table] + duk_del_prop_index(ctx, -1, fd); // ... [fs][table] + + // And we can also unhook ourselves + duk_eval_string(ctx, "require('EventDescriptors');"); // ... [eventdescriptors] + duk_get_prop_string(ctx, -1, "removeDescriptor"); // ... [eventdescriptors][remove] + duk_swap_top(ctx, -2); // ... [remove][this] + duk_push_int(ctx, fd); // ... [remove][this][fd] + duk_call_method(ctx, 1); // ... [ret] + } + return(0); +} +duk_ret_t ILibDuktape_fs_write(duk_context *ctx) +{ + int top = duk_get_top(ctx); + int fd = (int)duk_require_int(ctx, 0); + duk_size_t bufferLen; + char *buffer = Duktape_GetBuffer(ctx, 1, &bufferLen); + int cbx = 2; + int offset = 0, length = (int)bufferLen, e; + int position = -1; + if (duk_is_number(ctx, 2)) { offset = (int)duk_require_int(ctx, 2); cbx++; } + if (duk_is_number(ctx, 3)) { length = (int)duk_require_int(ctx, 3); cbx++; } + if (duk_is_number(ctx, 4)) { position = (int)duk_require_int(ctx, 4); cbx++; } + if (!duk_is_function(ctx, cbx)) { return(ILibDuktape_Error(ctx, "Invalid Parameters")); } + +#ifdef WIN32 + int bytesWritten = _write(fd, buffer + offset, length); +#else + int bytesWritten = write(fd, buffer + offset, length); +#endif + if (bytesWritten == length) + { + // Completed + duk_require_function(ctx, cbx); // [func] + duk_push_this(ctx); // [func][this] + duk_push_int(ctx, 0); // [func][this][ERR] + duk_push_int(ctx, bytesWritten); // [func][this][ERR][bytesWritten] + duk_dup(ctx, 1); // [func][this][ERR][bytesWritten][buffer] + duk_dup(ctx, cbx + 1); // [func][this][ERR][bytesWritten][buffer][options] + duk_call_method(ctx, 4); + return(0); + } + if (bytesWritten > 0 || (e = errno) == EAGAIN || e == EWOULDBLOCK || e == EINTR) + { + // Partial Write + duk_push_this(ctx); // [fs] + duk_get_prop_string(ctx, -1, FS_EVENT_W_DESCRIPTORS); // [fs][table] + if (!duk_has_prop_index(ctx, -1, fd)) + { + duk_eval_string(ctx, "require('DescriptorEvents');"); // [fs][table][DescriptorEvents] + duk_get_prop_string(ctx, -1, "addDescriptor"); // [fs][table][DescriptorEvents][add] + duk_swap_top(ctx, -2); // [fs][table][add][this] + duk_push_int(ctx, fd); // [fs][table][add][this][fd] + duk_push_object(ctx); // [fs][table][add][this][fd][options] + duk_push_true(ctx); duk_put_prop_string(ctx, -2, "writeset"); // ...[add][this][fd][options] + if (duk_is_object(ctx, cbx + 1) && duk_has_prop_string(ctx, cbx + 1, "metadata")) + { + duk_push_string(ctx, "fs.write(), "); // [fs][table][add][this][fd][options][str1] + duk_get_prop_string(ctx, cbx + 1, "metadata"); // [fs][table][add][this][fd][options][str1][str2] + duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [fs][table][add][this][fd][options][metadata] + } + else + { + duk_push_string(ctx, "fs.write()"); // [fs][table][add][this][fd][options][metadata] + } + duk_put_prop_string(ctx, -2, "metadata"); // [fs][table][add][this][fd][options] + duk_call_method(ctx, 2); // [fs][table][events] + ILibDuktape_EventEmitter_SetupOn(ctx, duk_get_heapptr(ctx, -1), "writeset"); // [on][this][writeset] + duk_push_c_function(ctx, ILibDuktape_fs_write_writeset_sink, DUK_VARARGS); // [on][this][writeset][func] + duk_call_method(ctx, 2); duk_pop(ctx); // [fs][table][events] ............................. + duk_put_prop_index(ctx, -2, fd); // [fs][table] + } + duk_get_prop_index(ctx, -1, fd); // [fs][table][events] + duk_push_object(ctx); // [fs][table][events][pending] + if (duk_is_object(ctx, cbx + 1)) { duk_dup(ctx, cbx + 1); duk_put_prop_string(ctx, -2, "opt"); } + duk_dup(ctx, 1); // [fs][table][events][pending][buffer] + duk_buffer_slice(ctx, -1, offset + length, length - offset);// [fs][table][events][pending][buffer][sliced] + duk_dup(ctx, -1); // [fs][table][events][pending][buffer][sliced][dup] + duk_put_prop_string(ctx, -4, "buffer"); // [fs][table][events][pending][buffer][sliced] + duk_put_prop_string(ctx, -3, "original"); // [fs][table][events][pending][buffer] + duk_pop(ctx); // [fs][table][events][pending] + duk_dup(ctx, cbx); duk_put_prop_string(ctx, -2, "callback");// [fs][table][events][pending] + duk_put_prop_string(ctx, -2, FS_EVENT_DESCRIPTORS_IO); // [fs][table][events] + return(0); + } + + // ERROR + duk_require_function(ctx, cbx); // [func] + duk_push_this(ctx); // [func][this] + duk_push_int(ctx, e); // [func][this][ERR] + duk_push_int(ctx, bytesWritten); // [func][this][ERR][bytesWritten] + duk_dup(ctx, 1); // [func][this][ERR][bytesWritten][buffer] + duk_dup(ctx, cbx + 1); // [func][this][ERR][bytesWritten][buffer][options] + duk_call_method(ctx, 4); + return(0); +} duk_ret_t ILibDuktape_fs_read(duk_context *ctx) { int top = duk_get_top(ctx); @@ -416,21 +586,24 @@ duk_ret_t ILibDuktape_fs_read(duk_context *ctx) // First, we'll attempt to read, and see if it completes or is pending duk_size_t bufferLen; - char *buffer = Duktape_GetBufferProperty(ctx, 1, "buffer"); + char *buffer = Duktape_GetBufferPropertyEx(ctx, 1, "buffer", &bufferLen); duk_size_t offset = (duk_size_t)Duktape_GetIntPropertyValue(ctx, 1, "offset", 0); duk_size_t length = (duk_size_t)Duktape_GetIntPropertyValue(ctx, 1, "length", (int)bufferLen); +#ifdef WIN32 + int bytesRead = _read(fd, buffer + offset, (unsigned int)length); +#else int bytesRead = read(fd, buffer + offset, length); - if (bytesRead >= 0 || (errno != E_AGAIN && errno != E_WOULDBLOCK)) +#endif + if (bytesRead >= 0 || (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)) { // Completed int errStatus = bytesRead >= 0 ? 0 : errno; duk_dup(ctx, 2); // [func] - duk_get_prop_string(ctx, -1, "call"); // [func][call] - duk_swap_top(ctx, -2); // [call][this] - duk_push_this(ctx); // [call][this][this/fs] - duk_push_int(ctx, errStatus); // [call][this][this/fs][err/status] - duk_push_int(ctx, bytesRead); // [call][this][this/fs][err/status][bytesRead] - duk_get_prop_string(ctx, 1, "buffer"); // [call][this][this/fs][err/status][bytesRead][buffer] + duk_push_this(ctx); // [func][this] + duk_push_int(ctx, errStatus); // [func][this][err/status] + duk_push_int(ctx, bytesRead); // [func][this][err/status][bytesRead] + duk_get_prop_string(ctx, 1, "buffer"); // [func][this][err/status][bytesRead][buffer] + duk_dup(ctx, 3); // [func][this][err/status][bytesRead][buffer][options] duk_call_method(ctx, 4); return(0); } @@ -1830,6 +2003,7 @@ void ILibDuktape_fs_PUSH(duk_context *ctx, void *chain) ILibDuktape_CreateInstanceMethod(ctx, "readSync", ILibDuktape_fs_readSync, 5); ILibDuktape_CreateInstanceMethod(ctx, "writeSync", ILibDuktape_fs_writeSync, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "read", ILibDuktape_fs_read, DUK_VARARGS); + ILibDuktape_CreateInstanceMethod(ctx, "write", ILibDuktape_fs_write, DUK_VARARGS); #ifdef WIN32 ILibDuktape_CreateInstanceMethod(ctx, "_readdirSync", ILibDuktape_fs_readdirSync, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "_statSync", ILibDuktape_fs_statSync, 1); diff --git a/modules/amt-mei.js b/modules/amt-mei.js index e06eee1..304ac35 100644 --- a/modules/amt-mei.js +++ b/modules/amt-mei.js @@ -398,20 +398,25 @@ function amt_heci() { fn.apply(this, opt); }, callback, optional); } - this.getProtocolVersion = function getProtocolVersion(callback) { + this.getProtocolVersion = function getProtocolVersion(callback) + { var optional = []; for (var i = 1; i < arguments.length; ++i) { opt.push(arguments[i]); } - heci.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) { + if (!this._tmpSession) { this._tmpSession = heci.create(); this._tmpSession.parent = this;} + this._tmpSession.doIoctl(heci.IOCTL.HECI_VERSION, Buffer.alloc(5), Buffer.alloc(5), function (status, buffer, self, fn, opt) + { if (status == 0) { var result = buffer.readUInt8(0).toString() + '.' + buffer.readUInt8(1).toString() + '.' + buffer.readUInt8(2).toString() + '.' + buffer.readUInt16BE(3).toString(); opt.unshift(result); fn.apply(self, opt); } - else { + else + { opt.unshift(null); fn.apply(self, opt); } + }, this, callback, optional); } } diff --git a/modules/heci.js b/modules/heci.js index bcdb39a..5c64283 100644 --- a/modules/heci.js +++ b/modules/heci.js @@ -60,16 +60,24 @@ function heci_create() 'write': function (chunk, flush) { console.log('write:' + chunk.length + ' on ' + this._hashCode()); - if (this._writeoverlapped == null) { throw ('Not Connected'); } if (chunk.length > this.MaxBufferSize) { throw ('Buffer too large'); } + + if (process.platform == 'win32') + { + if (this._writeoverlapped == null) { throw ('Not Connected'); } + } this._pendingWrites.unshift({ buffer: chunk, flush: flush }); + if (this._pendingWrites.length == 1) { // Kickstart the write this._processWrite(); } - return (false); + if (process.platform == 'win32') + { + return (false); + } }, 'final': function (flush) { @@ -78,7 +86,16 @@ function heci_create() 'read': function(size) { console.log('read: (' + size + ') on ' + this._hashCode()); - if (!this._readbuffer) { this._readbuffer = GM.CreateVariable(this.MaxBufferSize); } + if (!this._readbuffer) + { + this._readbuffer = process.platform == 'win32' ? GM.CreateVariable(this.MaxBufferSize) : Buffer.alloc(this.MaxBufferSize); + } + + if (process.platform == 'linux') + { + this._processRead(); + return; + } var result = kernel32.ReadFile(this._descriptor, this._readbuffer, this._readbuffer._size, 0, this._readoverlapped); if(result.Val != 0 || result._LastError == ERROR_IO_PENDING) @@ -194,7 +211,13 @@ function heci_create() }) .addMethod('descriptorPath', function _descriptorPath() { - console.log(' heci.createDescriptor()'); + if (process.platform == 'linux') + { + if (require('fs').existsSync('/dev/mei')) { return ('/dev/mei'); } + if (require('fs').existsSync('/dev/mei0')) { return ('/dev/mei0'); } + throw ('HECI not supported'); + } + if (process.platform != 'win32') { throw ('HECI not supported'); } var result; var ii; @@ -248,6 +271,12 @@ function heci_create() }) .addMethod('createDescriptor', function _createDescriptor(path) { + if (process.platform == 'linux') + { + return (require('fs').openSync(path, require('fs').constants.O_RDWR | require('fs').constants.O_NONBLOCK)); + } + if (process.platform != 'win32') { throw ('HECI not supported'); } + var devPath = GM.CreateVariable(path); var ret = kernel32.CreateFileA(devPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (ret.Val == -1) @@ -327,7 +356,8 @@ function heci_create() ret.doIoctl = function doIoctl(code, inputBuffer, outputBuffer, callback) { console.log('doIoctl()'); - if(typeof(callback)!='function') { throw('Callback not specified');} + if (typeof (callback) != 'function') { throw ('Callback not specified'); } + var i; var parms = []; for (i = 4; i < arguments.length; ++i) @@ -335,6 +365,20 @@ function heci_create() parms.push(arguments[i]); } + + if (process.platform == 'linux') + { + if (outputBuffer.length < inputBuffer.length) { throw ('output buffer is too small'); } + outputBuffer.fill(0); + inputBuffer.copy(outputBuffer); + if (this._descriptor == null) { this._descriptor = this.createDescriptor(this.descriptorPath()); } + var ret = require('ioctl')(this._descriptor, code, outputBuffer); + parms.unshift(outputBuffer); + parms.unshift(ret); + callback.apply(this, parms); + return; + } + this._ioctls.unshift({ code: code, input: inputBuffer, output: outputBuffer, callback: callback, parms: parms }); if(this._ioctls.length == 1) { @@ -342,6 +386,7 @@ function heci_create() this._send(this._ioctls.peek()); } }; + ret._send = function _send(options) { if(this._descriptor == null) @@ -406,24 +451,46 @@ function heci_create() { var chunk = this._pendingWrites.peek(); console.log('_WRITING: ' + chunk.buffer.length + ' bytes' + ' on ' + this._hashCode()); - if (chunk.buffer.length == 23) + + if (process.platform == 'win32') { - console.log(chunk.buffer.toString('hex')); - GM.CreateVariable(chunk.buffer)._debug(); - } - var result = kernel32.WriteFile(this._descriptor, GM.CreateVariable(chunk.buffer), chunk.buffer.length, 0, this._writeoverlapped); - if(result.Val != 0 || result._LastError == ERROR_IO_PENDING) - { - if(!this._wDescriptorEvent) + var result = kernel32.WriteFile(this._descriptor, GM.CreateVariable(chunk.buffer), chunk.buffer.length, 0, this._writeoverlapped); + if (result.Val != 0 || result._LastError == ERROR_IO_PENDING) { - this._wDescriptorEvent = require('DescriptorEvents').addDescriptor(this._writeoverlapped.hEvent, { metadata: 'heci.session [write]' }); - this._wDescriptorEvent.session = this; - this._wDescriptorEvent.on('signaled', this._processWrite_signaled); + if (!this._wDescriptorEvent) + { + this._wDescriptorEvent = require('DescriptorEvents').addDescriptor(this._writeoverlapped.hEvent, { metadata: 'heci.session [write]' }); + this._wDescriptorEvent.session = this; + this._wDescriptorEvent.on('signaled', this._processWrite_signaled); + } + } + else + { + console.log('Write Error: ' + result._LastError); } } - else + + require('fs').write(this._descriptor, chunk.buffer, ret._processWrite_linux_signaled, { metadata: 'heci.session', session: this }); + }; + ret._processWrite_linux_signaled = function _processWrite_linux_signaled(status, bytesWritten, buffer, options) + { + if(status == 0) { - console.log('Write Error: ' + result._LastError); + console.log(bytesWritten + ' bytes written'); + console.log('noPipeline = ' + options.session._options.noPipeline, options.session._pendingWrites.length); + if (options.session._options.noPipeline == null || options.session._options.noPipeline == false) + { + var item = options.session._pendingWrites.pop(); + if (options.session._pendingWrites.length > 0) + { + options.session._processWrite(); + } + else + { + console.log('Write/Flush'); + item.flush(); + } + } } }; ret._processWrite_signaled = function _processWrite_signaled(status) @@ -455,12 +522,67 @@ function heci_create() } } }; + ret._processRead_readSet_sink = function _processRead_readSet_sink(status, bytesRead, buffer, options) + { + if (status != 0) { options.session.push(null); return; } + console.log(bytesRead + ' bytes read'); + + buffer = buffer.slice(0, bytesRead); + var pushResult = options.session.push(buffer); + if (options.session._options.noPipeline != 0 && options.session._pendingWrites.length > 0) + { + // Unlock a write + console.log('pendingWriteCount: ' + options.session._pendingWrites.length); + var item = options.session._pendingWrites.pop(); + + if (options.session._pendingWrites.length > 0) + { + options.session._processWrite(); + } + else + { + console.log('Write/Flush'); + item.flush(); + } + } + + if (pushResult) + { + // We can read more, because data is still flowing + console.log('READING MORE on ' + options.session._hashCode()); + var result = kernel32.ReadFile(this.session._descriptor, this.session._readbuffer, this.session._readbuffer._size, 0, this.session._readoverlapped); + if (result.Val != 0 || result._LastError == ERROR_IO_PENDING) + { + options.session._processRead(); + return (true); + } + else + { + console.log('Sometype of error: ' + result._LastError); + this.session.push(null); + } + } + + }; + ret._processRead = function _processRead() + { + require('fs').read(this._descriptor, { metadata: 'heci.session', buffer: this._readbuffer, session: this }, _processRead_readSet_sink); + }; return (ret); } var ioctl = {}; -Object.defineProperty(ioctl, 'HECI_VERSION', { value: 0x8000E000 }); -Object.defineProperty(ioctl, 'CLIENT_CONNECT', { value: 0x8000E004 }); +if(process.platform == 'win32') +{ + Object.defineProperty(ioctl, 'HECI_VERSION', { value: 0x8000E000 }); + Object.defineProperty(ioctl, 'CLIENT_CONNECT', { value: 0x8000E004 }); +} +if(process.platform == 'linux') +{ + Object.defineProperty(ioctl, 'HECI_VERSION', { value: 0x00 }); + Object.defineProperty(ioctl, 'CLIENT_CONNECT', { value: 0x01 }); +} + var guids = {}; Object.defineProperty(guids, 'AMT', { value: Buffer.from('2800F812B7B42D4BACA846E0FF65814C', 'hex') }); Object.defineProperty(guids, 'LME', { value: Buffer.from('DBA4336776047B4EB3AFBCFC29BEE7A7', 'hex') }); From 3b3cf725a84b716e49194600a4f6841ab66ae67a Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 27 May 2020 17:26:02 -0700 Subject: [PATCH 11/21] linux update for fcntl --- microscript/ILibDuktape_fs.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c index c62e9b7..3a64c28 100644 --- a/microscript/ILibDuktape_fs.c +++ b/microscript/ILibDuktape_fs.c @@ -298,14 +298,22 @@ duk_ret_t ILibDuktape_fs_openSync(duk_context *ctx) } int flags = (int)duk_require_int(ctx, 1); #ifdef WIN32 - int fd = -1; + int fd = -1; if (_wsopen_s(&fd, (wchar_t*)ILibDuktape_String_UTF8ToWide(ctx, path), flags, 0, 0) != 0) { return(ILibDuktape_Error(ctx, "openSync() Error: %d ", errno)); } duk_push_int(ctx, fd); #else - duk_push_int(ctx, open(path, flags)); + int fd = open(path, flags); + duk_push_int(ctx, fd); +#ifdef _POSIX + if (fd >= 0 && (flags & O_NONBLOCK) == O_NONBLOCK) + { + flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, O_NONBLOCK | flags); + } +#endif #endif return(1); } From bb5cecac23de57ec74c24fce97d0e20dcb42f572 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 27 May 2020 18:41:27 -0700 Subject: [PATCH 12/21] fixed bug with function callback definition --- microscript/ILibDuktape_fs.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c index 3a64c28..c5e43bc 100644 --- a/microscript/ILibDuktape_fs.c +++ b/microscript/ILibDuktape_fs.c @@ -488,7 +488,8 @@ duk_ret_t ILibDuktape_fs_write(duk_context *ctx) if (bytesWritten == length) { // Completed - duk_require_function(ctx, cbx); // [func] + duk_require_function(ctx, cbx); + duk_dup(ctx, cbx); // [func] duk_push_this(ctx); // [func][this] duk_push_int(ctx, 0); // [func][this][ERR] duk_push_int(ctx, bytesWritten); // [func][this][ERR][bytesWritten] @@ -542,7 +543,8 @@ duk_ret_t ILibDuktape_fs_write(duk_context *ctx) } // ERROR - duk_require_function(ctx, cbx); // [func] + duk_require_function(ctx, cbx); + duk_dup(ctx, cbx); // [func] duk_push_this(ctx); // [func][this] duk_push_int(ctx, e); // [func][this][ERR] duk_push_int(ctx, bytesWritten); // [func][this][ERR][bytesWritten] @@ -554,7 +556,7 @@ duk_ret_t ILibDuktape_fs_write(duk_context *ctx) duk_ret_t ILibDuktape_fs_read(duk_context *ctx) { int top = duk_get_top(ctx); - if (top > 2) + if (top > 2 && (!duk_is_function(ctx, 2))) { // Simplify flow, by converting to an options object duk_push_this(ctx); // [fs] @@ -644,7 +646,7 @@ duk_ret_t ILibDuktape_fs_read(duk_context *ctx) ILibDuktape_EventEmitter_SetupOn(ctx, duk_get_heapptr(ctx, -1), "readset"); // ........[on][this][readset] duk_push_c_function(ctx, ILibDuktape_fs_read_readsetSink, DUK_VARARGS); // ........[on][this][readset][func] duk_call_method(ctx, 2); duk_pop(ctx); // [fs][table][descriptorEvent] - duk_push_array(ctx); duk_put_prop_string(ctx, -1, FS_EVENT_DESCRIPTORS_IO); + duk_push_array(ctx); duk_put_prop_string(ctx, -2, FS_EVENT_DESCRIPTORS_IO); duk_put_prop_index(ctx, -2, fd); // [fs][table] } duk_get_prop_index(ctx, -1, fd); // [fs][table][desriptorEvent] From 5cd41e9ebd09ebd19c9e29348572d78b93447d97 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 27 May 2020 19:07:04 -0700 Subject: [PATCH 13/21] Updated constants --- microscript/ILibDuktape_fs.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c index c5e43bc..a7bcd93 100644 --- a/microscript/ILibDuktape_fs.c +++ b/microscript/ILibDuktape_fs.c @@ -22,6 +22,7 @@ limitations under the License. #include #include #include +#include #endif #include "microstack/ILibParsers.h" @@ -2038,6 +2039,18 @@ void ILibDuktape_fs_PUSH(duk_context *ctx, void *chain) ILibDuktape_CreateInstanceMethod(ctx, "mkdirSync", ILibDuktape_fs_mkdirSync, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "rmdirSync", ILibDuktape_fs_rmdirSync, 1); + duk_push_object(ctx); +#ifdef WIN32 + duk_push_int(ctx, _O_RDONLY); duk_put_prop_string(ctx, -2, "O_RDONLY"); + duk_push_int(ctx, _O_WRONLY); duk_put_prop_string(ctx, -2, "O_WRONLY"); + duk_push_int(ctx, _O_RDWR); duk_put_prop_string(ctx, -2, "O_RDWR"); +#else + duk_push_int(ctx, O_RDONLY); duk_put_prop_string(ctx, -2, "O_RDONLY"); + duk_push_int(ctx, O_WRONLY); duk_put_prop_string(ctx, -2, "O_WRONLY"); + duk_push_int(ctx, O_RDWR); duk_put_prop_string(ctx, -2, "O_RDWR"); + duk_push_int(ctx, O_NONBLOCK); duk_put_prop_string(ctx, -2, "O_NONBLOCK"); +#endif + duk_put_prop_string(ctx, -2, "constants"); ILibDuktape_CreateFinalizer(ctx, ILibDuktape_fs_Finalizer); @@ -2061,7 +2074,6 @@ void ILibDuktape_fs_PUSH(duk_context *ctx, void *chain) }\ ds.on('close', function onCopyFileDone(){delete this.ss.fs._copyStreams[this.ss.id];});\ };\ - exports.constants = {O_RDONLY: 0, O_WRONLY: 1, O_RDWR: 4, O_NONBLOCK: 2048};\ exports.copyFileSync = function copyFileSync(src, dest)\ {\ var buffer = this.readFileSync(src, {flags: 'rb'});\ From 67bb0b98dc277a8956dbcb9661154bc19056d319 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 27 May 2020 21:17:32 -0700 Subject: [PATCH 14/21] Updated DescriptorEvents to support separate FD_SET watchers Updated heci.js linux support --- microscript/ILibDuktape_Polyfills.c | 40 +++++++++- microscript/ILibDuktape_fs.c | 10 ++- modules/heci.js | 117 ++++++++++++++-------------- 3 files changed, 103 insertions(+), 64 deletions(-) diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index 58e39c8..e2ff4f1 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -2515,7 +2515,29 @@ duk_ret_t ILibDuktape_DescriptorEvents_Remove(duk_context *ctx) duk_push_this(ctx); // [obj] duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Table); // [obj][table] duk_dup(ctx, 0); // [obj][table][key] - duk_del_prop(ctx, -2); // [obj][table] + if (!duk_is_null_or_undefined(ctx, 1) && duk_is_object(ctx, 1)) + { + duk_get_prop(ctx, -2); // [obj][table][value] + if (duk_is_null_or_undefined(ctx, -1)) { return(0); } + duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Options); //..[table][value][options] + if (duk_has_prop_string(ctx, 1, "readset")) { duk_push_false(ctx); duk_put_prop_string(ctx, -2, "readset"); } + if (duk_has_prop_string(ctx, 1, "writeset")) { duk_push_false(ctx); duk_put_prop_string(ctx, -2, "writeset"); } + if (duk_has_prop_string(ctx, 1, "errorset")) { duk_push_false(ctx); duk_put_prop_string(ctx, -2, "errorset"); } + if( Duktape_GetBooleanProperty(ctx, -1, "readset", 0) == 0 && + Duktape_GetBooleanProperty(ctx, -1, "writeset", 0) == 0 && + Duktape_GetBooleanProperty(ctx, -1, "errorset", 0) == 0) + { + // No FD_SET watchers, so we can remove the entire object + duk_pop_2(ctx); // [obj][table] + duk_dup(ctx, 0); // [obj][table][key] + duk_del_prop(ctx, -2); // [obj][table] + } + } + else + { + // Remove All FD_SET watchers for this FD + duk_del_prop(ctx, -2); // [obj][table] + } return(0); } #ifdef WIN32 @@ -2616,6 +2638,20 @@ duk_ret_t ILibDuktape_DescriptorEvents_Add(duk_context *ctx) duk_push_this(ctx); // [obj] duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Table); // [obj][table] + duk_dup(ctx, 0); // [obj][table][key] + if (duk_has_prop(ctx, -2)) // [obj][table] + { + // There's already a watcher, so let's just merge the FD_SETS + duk_dup(ctx, 0); // [obj][table][key] + duk_get_prop(ctx, -2); // [obj][table][value] + duk_get_prop_string(ctx, -1, ILibDuktape_DescriptorEvents_Options); //..[table][value][options] + if (Duktape_GetBooleanProperty(ctx, 1, "readset", 0) != 0) { duk_push_true(ctx); duk_put_prop_string(ctx, -2, "readset"); } + if (Duktape_GetBooleanProperty(ctx, 1, "writeset", 0) != 0) { duk_push_true(ctx); duk_put_prop_string(ctx, -2, "writeset"); } + if (Duktape_GetBooleanProperty(ctx, 1, "errorset", 0) != 0) { duk_push_true(ctx); duk_put_prop_string(ctx, -2, "errorset"); } + duk_pop(ctx); // [obj][table][value] + return(1); + } + duk_push_object(ctx); // [obj][table][value] duk_dup(ctx, 0); // [obj][table][value][key] duk_dup(ctx, -2); // [obj][table][value][key][value] @@ -2745,7 +2781,7 @@ void ILibDuktape_DescriptorEvents_Push(duk_context *ctx, void *chain) ((void**)link->ExtraMemoryPtr)[0] = ctx; ((void**)link->ExtraMemoryPtr)[1] = duk_get_heapptr(ctx, -1); ILibDuktape_CreateInstanceMethod(ctx, "addDescriptor", ILibDuktape_DescriptorEvents_Add, 2); - ILibDuktape_CreateInstanceMethod(ctx, "removeDescriptor", ILibDuktape_DescriptorEvents_Remove, 1); + ILibDuktape_CreateInstanceMethod(ctx, "removeDescriptor", ILibDuktape_DescriptorEvents_Remove, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "getDescriptorCount", ILibDuktape_DescriptorEvents_GetCount, 0); ILibAddToChain(chain, link); diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c index a7bcd93..e5179f5 100644 --- a/microscript/ILibDuktape_fs.c +++ b/microscript/ILibDuktape_fs.c @@ -373,12 +373,14 @@ duk_ret_t ILibDuktape_fs_read_readsetSink(duk_context *ctx) duk_pop_2(ctx); // [DescriptorEvents][pending] if (duk_get_length(ctx, -1) == 0) { - // No more pending I/O operations, so we can cleanup the DescriptorEvents + // No more pending read I/O operations, so we can cleanup the DescriptorEvents duk_eval_string(ctx, "require('DescriptorEvents');"); // .....[DescriptorEvents] duk_get_prop_string(ctx, -1, "removeDescriptor"); // .....[DescriptorEvents][removeDescriptor] duk_swap_top(ctx, -2); // .....[removeDescriptor][this] duk_push_int(ctx, fd); // .....[removeDescriptor][this][fd] - duk_pcall_method(ctx, 1); duk_pop(ctx); // [DescriptorEvents][pending] + duk_push_object(ctx); // .....[removeDescriptor][this][fd][options] + duk_push_true(ctx); duk_put_prop_string(ctx, -2, "readset");//..[removeDescriptor][this][fd][options] + duk_pcall_method(ctx, 2); duk_pop(ctx); // [DescriptorEvents][pending] duk_eval_string(ctx, "require('fs');"); // [DescriptorEvents][pending][FS] duk_get_prop_string(ctx, -1,FS_EVENT_R_DESCRIPTORS);// [DescriptorEvents][pending][FS][table] @@ -463,7 +465,9 @@ duk_ret_t ILibDuktape_fs_write_writeset_sink(duk_context *ctx) duk_get_prop_string(ctx, -1, "removeDescriptor"); // ... [eventdescriptors][remove] duk_swap_top(ctx, -2); // ... [remove][this] duk_push_int(ctx, fd); // ... [remove][this][fd] - duk_call_method(ctx, 1); // ... [ret] + duk_push_object(ctx); // ... [remove][this][fd][options] + duk_push_true(ctx); duk_put_prop_string(ctx, -2, "writeset");//[remove][this][fd][options] + duk_call_method(ctx, 2); // ... [ret] } return(0); } diff --git a/modules/heci.js b/modules/heci.js index 5c64283..09305c7 100644 --- a/modules/heci.js +++ b/modules/heci.js @@ -299,59 +299,69 @@ function heci_create() { // Clean up all Handles and Descriptors console.log('DISCONNECT on ' + this._hashCode()); - - - // - // doIoctl() - // - if (this._descriptorEvent) + if (process.platform == 'linux') { - if (this._overlapped) { require('DescriptorEvents').removeDescriptor(this._overlapped.hEvent); } - this._descriptorEvent = null; - } - if (this._overlapped) - { - kernel32.CloseHandle(this._overlapped.hEvent); - this._overlapped = null; + if(this._descriptor != null) + { + require('DescriptorEvents').removeDescriptor(this._descriptor); + require('fs').closeSync(this._descriptor); + this._descriptor = null; + } } - // - // Read - // - if (this._rDescriptorEvent) + if (process.platform == 'win32') { - if (this._readoverlapped) { require('DescriptorEvents').removeDescriptor(this._readoverlapped.hEvent); } - this._rDescriptorEvent = null; - } - if (this._readoverlapped) - { - kernel32.CloseHandle(this._readoverlapped.hEvent); - this._readoverlapped = null; - } + // + // doIoctl() + // + if (this._descriptorEvent) + { + if (this._overlapped) { require('DescriptorEvents').removeDescriptor(this._overlapped.hEvent); } + this._descriptorEvent = null; + } + if (this._overlapped) + { + kernel32.CloseHandle(this._overlapped.hEvent); + this._overlapped = null; + } - // - // Write - // - if (this._wDescriptorEvent) - { - if (this._writeoverlapped) { require('DescriptorEvents').removeDescriptor(this._writeoverlapped.hEvent); } - this._wDescriptorEvent = null; - } - if (this._writeoverlapped) - { - kernel32.CloseHandle(this._writeoverlapped.hEvent); - this._writeoverlapped = null; - } + // + // Read + // + if (this._rDescriptorEvent) + { + if (this._readoverlapped) { require('DescriptorEvents').removeDescriptor(this._readoverlapped.hEvent); } + this._rDescriptorEvent = null; + } + if (this._readoverlapped) + { + kernel32.CloseHandle(this._readoverlapped.hEvent); + this._readoverlapped = null; + } - // - // HECI - // - if (this._descriptor) - { - kernel32.CloseHandle(this._descriptor); - this._descriptor = null; - } + // + // Write + // + if (this._wDescriptorEvent) + { + if (this._writeoverlapped) { require('DescriptorEvents').removeDescriptor(this._writeoverlapped.hEvent); } + this._wDescriptorEvent = null; + } + if (this._writeoverlapped) + { + kernel32.CloseHandle(this._writeoverlapped.hEvent); + this._writeoverlapped = null; + } + // + // HECI + // + if (this._descriptor) + { + kernel32.CloseHandle(this._descriptor); + this._descriptor = null; + } + } }; ret.doIoctl = function doIoctl(code, inputBuffer, outputBuffer, callback) { @@ -470,7 +480,7 @@ function heci_create() } } - require('fs').write(this._descriptor, chunk.buffer, ret._processWrite_linux_signaled, { metadata: 'heci.session', session: this }); + require('fs').write(this._descriptor, chunk.buffer, this._processWrite_linux_signaled, { metadata: 'heci.session', session: this }); }; ret._processWrite_linux_signaled = function _processWrite_linux_signaled(status, bytesWritten, buffer, options) { @@ -550,19 +560,8 @@ function heci_create() { // We can read more, because data is still flowing console.log('READING MORE on ' + options.session._hashCode()); - var result = kernel32.ReadFile(this.session._descriptor, this.session._readbuffer, this.session._readbuffer._size, 0, this.session._readoverlapped); - if (result.Val != 0 || result._LastError == ERROR_IO_PENDING) - { - options.session._processRead(); - return (true); - } - else - { - console.log('Sometype of error: ' + result._LastError); - this.session.push(null); - } + options.session._processRead(); } - }; ret._processRead = function _processRead() { From 4a428afe88a5963cf3b67d45edde793f9f111292 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 27 May 2020 21:20:27 -0700 Subject: [PATCH 15/21] Added windows check around overlapped definition --- modules/heci.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/heci.js b/modules/heci.js index 09305c7..745dea0 100644 --- a/modules/heci.js +++ b/modules/heci.js @@ -197,13 +197,16 @@ function heci_create() } Object.defineProperty(this, "MaxBufferSize", { value: buffer.readUInt32LE() }); this._options = opt; - this._readoverlapped = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 20); - this._writeoverlapped = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 20); - this._readoverlapped.hEvent = kernel32.CreateEventA(0, 1, 0, 0); - this._writeoverlapped.hEvent = kernel32.CreateEventA(0, 1, 0, 0); - this._readoverlapped.hEvent.pointerBuffer().copy(this._readoverlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer()); - this._writeoverlapped.hEvent.pointerBuffer().copy(this._writeoverlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer()); - + + if (process.platform == 'win32') + { + this._readoverlapped = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 20); + this._writeoverlapped = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 20); + this._readoverlapped.hEvent = kernel32.CreateEventA(0, 1, 0, 0); + this._writeoverlapped.hEvent = kernel32.CreateEventA(0, 1, 0, 0); + this._readoverlapped.hEvent.pointerBuffer().copy(this._readoverlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer()); + this._writeoverlapped.hEvent.pointerBuffer().copy(this._writeoverlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer()); + } console.log('Connected, buffer size: ' + this.MaxBufferSize); this._read(this.MaxBufferSize); this.emit('connect'); From 724619845425d599c3d93c984651c62401bc330b Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 27 May 2020 21:23:38 -0700 Subject: [PATCH 16/21] Fixed typo --- modules/heci.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/heci.js b/modules/heci.js index 745dea0..9acce1a 100644 --- a/modules/heci.js +++ b/modules/heci.js @@ -568,7 +568,7 @@ function heci_create() }; ret._processRead = function _processRead() { - require('fs').read(this._descriptor, { metadata: 'heci.session', buffer: this._readbuffer, session: this }, _processRead_readSet_sink); + require('fs').read(this._descriptor, { metadata: 'heci.session', buffer: this._readbuffer, session: this }, this._processRead_readSet_sink); }; return (ret); } From 2b053ef627accdcd05d0fc09d7e93736f6ed838c Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Wed, 27 May 2020 23:11:30 -0700 Subject: [PATCH 17/21] Fixed race --- modules/amt-lme.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/amt-lme.js b/modules/amt-lme.js index b7bea1d..bea0098 100644 --- a/modules/amt-lme.js +++ b/modules/amt-lme.js @@ -117,6 +117,7 @@ function lme_heci(options) { emitterUtils.createEvent('notify'); emitterUtils.createEvent('bind'); + this.on('newListener', function (name, func) { if (name == 'connect' && this._LME._connected == true) { func.call(this);} }); if ((options != null) && (options.debug == true)) { lme_port_offset = -100; } // LMS debug mode var heci = require('heci'); @@ -124,11 +125,14 @@ function lme_heci(options) { this._ObjectID = "lme"; this._LME = heci.create(); + this._LME._connected = false; this._LME.descriptorMetadata = "amt-lme"; this._LME._binded = {}; this._LME.LMS = this; this._LME.on('error', function (e) { this.LMS.emit('error', e); }); - this._LME.on('connect', function () { + this._LME.on('connect', function () + { + this._connected = true; this.on('data', function (chunk) { // this = HECI var cmd = chunk.readUInt8(0); From 72baa548fa1140e1b6345fa24d0a8ae55085a087 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Thu, 28 May 2020 00:27:46 -0700 Subject: [PATCH 18/21] Updated debug log messages --- modules/heci.js | 68 +++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 39 deletions(-) diff --git a/modules/heci.js b/modules/heci.js index 9acce1a..e870ff3 100644 --- a/modules/heci.js +++ b/modules/heci.js @@ -59,9 +59,7 @@ function heci_create() { 'write': function (chunk, flush) { - console.log('write:' + chunk.length + ' on ' + this._hashCode()); if (chunk.length > this.MaxBufferSize) { throw ('Buffer too large'); } - if (process.platform == 'win32') { if (this._writeoverlapped == null) { throw ('Not Connected'); } @@ -85,7 +83,6 @@ function heci_create() }, 'read': function(size) { - console.log('read: (' + size + ') on ' + this._hashCode()); if (!this._readbuffer) { this._readbuffer = process.platform == 'win32' ? GM.CreateVariable(this.MaxBufferSize) : Buffer.alloc(this.MaxBufferSize); @@ -106,10 +103,9 @@ function heci_create() this._rDescriptorEvent.session = this; this._rDescriptorEvent.on('signaled', function (status) { - console.log('Read Status: ' + status + ' on ' + this.session._hashCode()); if(status != 'NONE') { - console.log('****** ' + status + '******'); + console.info3('>>> heci.session signaled with status: ' + status); this.session.push(null); return; } @@ -118,15 +114,14 @@ function heci_create() if((result=kernel32.GetOverlappedResult(this.session._descriptor, this.session._readoverlapped, bytesRead, 0)).Val != 0) { var buffer = this.session._readbuffer.toBuffer().slice(0, bytesRead.toBuffer().readUInt32LE()); - console.log(buffer.length + ' bytes READ'); + console.info3(buffer.length + ' bytes READ'); var pushResult = this.session.push(buffer); if (this.session._options.noPipeline != 0 && this.session._pendingWrites.length>0) { // Unlock a write - console.log('pendingWriteCount: ' + this.session._pendingWrites.length); + console.info2('pendingWriteCount: ' + this.session._pendingWrites.length); var item = this.session._pendingWrites.pop(); - console.log('pendingWriteCount is now: ' + this.session._pendingWrites.length); if (this.session._pendingWrites.length > 0) { @@ -134,7 +129,7 @@ function heci_create() } else { - console.log('Write/Flush'); + console.info2('Write/Flush'); item.flush(); } } @@ -142,7 +137,6 @@ function heci_create() if (pushResult) { // We can read more, because data is still flowing - console.log('READING MORE on ' + this.session._hashCode()); var result = kernel32.ReadFile(this.session._descriptor, this.session._readbuffer, this.session._readbuffer._size, 0, this.session._readoverlapped); if(result.Val != 0 || result._LastError == ERROR_IO_PENDING) { @@ -150,14 +144,14 @@ function heci_create() } else { - console.log('Sometype of error: ' + result._LastError); + console.info1('Sometype of error: ' + result._LastError); this.session.push(null); } } } else { - console.log('READ_OVERLAPPED_ERROR: ' + result._LastError + ' on ' + this.session._hashCode()); + console.info1('READ_OVERLAPPED_ERROR: ' + result._LastError + ' on ' + this.session._hashCode()); } }); @@ -165,7 +159,7 @@ function heci_create() } else { - console.log('Some Other Error: ' + result._LastError); + console.info1('Some Other Error: ' + result._LastError); } } }); @@ -180,12 +174,12 @@ function heci_create() .createEvent('error') .addMethod('connect', function _connect(guid, options) { - console.log('connect()'); + console.info1('connect()'); this.doIoctl(this.heciParent.IOCTL.CLIENT_CONNECT, guid, Buffer.alloc(16), function _onconnect(status, buffer, opt) { if(status!=0) { - console.log('HECI Connection Error [' + this.LastError + ']'); + console.info1('HECI Connection Error [' + this.LastError + ']'); this.emit('error', 'HECI Connection Error [' + this.LastError + ']'); return; } @@ -207,7 +201,7 @@ function heci_create() this._readoverlapped.hEvent.pointerBuffer().copy(this._readoverlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer()); this._writeoverlapped.hEvent.pointerBuffer().copy(this._writeoverlapped.Deref(GM.PointerSize == 8 ? 24 : 16, GM.PointerSize).toBuffer()); } - console.log('Connected, buffer size: ' + this.MaxBufferSize); + console.info1('Connected, buffer size: ' + this.MaxBufferSize); this._read(this.MaxBufferSize); this.emit('connect'); }, options); @@ -230,10 +224,10 @@ function heci_create() var deviceInfo = setup.SetupDiGetClassDevsA(heciguid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (deviceInfo.Val == -1) { - console.log('... Unable to acquire [deviceInfo]'); + console.info1('... Unable to acquire [deviceInfo]'); throw ('unable to acquire [deviceInfo]'); } - console.log('... acquired [deviceInfo]'); + console.info1('... acquired [deviceInfo]'); var interfaceData = GM.CreateVariable(GM.PointerSize == 8 ? 32 : 28); @@ -265,7 +259,7 @@ function heci_create() setup.SetupDiDestroyDeviceInfoList(deviceInfo); if (deviceDetail == null) { - console.log('... failed to acquire [deviceDetail]'); + console.info1('... failed to acquire [deviceDetail]'); throw ('unable to acquire [deviceDetail]'); } @@ -284,10 +278,10 @@ function heci_create() var ret = kernel32.CreateFileA(devPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (ret.Val == -1) { - console.log('... failed to acquire [descriptor]'); + console.info1('... failed to acquire [descriptor]'); throw ('failed to acquire descriptor'); } - console.log('... acquired [DESCRIPTOR]'); + console.info1('... acquired [DESCRIPTOR]'); return (ret); }); if (process.platform == 'win32') @@ -301,7 +295,7 @@ function heci_create() ret.disconnect = function disconnect() { // Clean up all Handles and Descriptors - console.log('DISCONNECT on ' + this._hashCode()); + console.info1('DISCONNECT on ' + this._hashCode()); if (process.platform == 'linux') { if(this._descriptor != null) @@ -368,7 +362,6 @@ function heci_create() }; ret.doIoctl = function doIoctl(code, inputBuffer, outputBuffer, callback) { - console.log('doIoctl()'); if (typeof (callback) != 'function') { throw ('Callback not specified'); } var i; @@ -463,7 +456,7 @@ function heci_create() ret._processWrite = function _processWrite() { var chunk = this._pendingWrites.peek(); - console.log('_WRITING: ' + chunk.buffer.length + ' bytes' + ' on ' + this._hashCode()); + console.info3('_WRITING: ' + chunk.buffer.length + ' bytes' + ' on ' + this._hashCode()); if (process.platform == 'win32') { @@ -479,7 +472,7 @@ function heci_create() } else { - console.log('Write Error: ' + result._LastError); + console.info1('Write Error: ' + result._LastError); } } @@ -489,8 +482,8 @@ function heci_create() { if(status == 0) { - console.log(bytesWritten + ' bytes written'); - console.log('noPipeline = ' + options.session._options.noPipeline, options.session._pendingWrites.length); + console.info3(bytesWritten + ' bytes written'); + console.info3('noPipeline = ' + options.session._options.noPipeline, options.session._pendingWrites.length); if (options.session._options.noPipeline == null || options.session._options.noPipeline == false) { var item = options.session._pendingWrites.pop(); @@ -500,7 +493,7 @@ function heci_create() } else { - console.log('Write/Flush'); + console.info3('Write/Flush'); item.flush(); } } @@ -508,7 +501,7 @@ function heci_create() }; ret._processWrite_signaled = function _processWrite_signaled(status) { - console.log('Write Signaled: ' + status); + console.info3('Write Signaled: ' + status); if(status == 'NONE') { // No Errors @@ -516,8 +509,8 @@ function heci_create() var result = kernel32.GetOverlappedResult(this.session._descriptor, this.session._writeoverlapped, bytesWritten, 0); if(result.Val != 0) { - console.log(bytesWritten.toBuffer().readUInt32LE() + ' bytes written'); - console.log('noPipeline = ' + this.session._options.noPipeline, this.session._pendingWrites.length); + console.info3(bytesWritten.toBuffer().readUInt32LE() + ' bytes written'); + console.info3('noPipeline = ' + this.session._options.noPipeline, this.session._pendingWrites.length); if(this.session._options.noPipeline==null || this.session._options.noPipeline == false) { var item = this.session._pendingWrites.pop(); @@ -527,7 +520,7 @@ function heci_create() } else { - console.log('Write/Flush'); + console.info3('Write/Flush'); item.flush(); } return (true); @@ -538,14 +531,14 @@ function heci_create() ret._processRead_readSet_sink = function _processRead_readSet_sink(status, bytesRead, buffer, options) { if (status != 0) { options.session.push(null); return; } - console.log(bytesRead + ' bytes read'); + console.info3(bytesRead + ' bytes read'); buffer = buffer.slice(0, bytesRead); var pushResult = options.session.push(buffer); if (options.session._options.noPipeline != 0 && options.session._pendingWrites.length > 0) { // Unlock a write - console.log('pendingWriteCount: ' + options.session._pendingWrites.length); + console.info3('pendingWriteCount: ' + options.session._pendingWrites.length); var item = options.session._pendingWrites.pop(); if (options.session._pendingWrites.length > 0) @@ -554,7 +547,7 @@ function heci_create() } else { - console.log('Write/Flush'); + console.info3('Write/Flush'); item.flush(); } } @@ -562,12 +555,12 @@ function heci_create() if (pushResult) { // We can read more, because data is still flowing - console.log('READING MORE on ' + options.session._hashCode()); options.session._processRead(); } }; ret._processRead = function _processRead() { + if (this._descriptor == null) { return; } require('fs').read(this._descriptor, { metadata: 'heci.session', buffer: this._readbuffer, session: this }, this._processRead_readSet_sink); }; return (ret); @@ -601,14 +594,11 @@ Object.defineProperty(module.exports, "supported", { try { var p = this.create().descriptorPath(); - console.log(p); var d = this.create().createDescriptor(p); - console.log(d.Val); return(true); } catch(e) { - console.log(e); return (false); } } From 3824ef638c47e4b26ddfaaecf50c25d32d284232 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Thu, 28 May 2020 00:54:30 -0700 Subject: [PATCH 19/21] Updated project files, and fixed compiler warnings --- makefile | 2 +- meshconsole/MeshConsole.vcxproj | 2 - meshservice/MeshService.vcxproj | 2 - microscript/ILibDuktape_ChildProcess.c | 3 +- microscript/ILibDuktape_HECI.c | 1313 --------------------- microscript/ILibDuktape_HECI.h | 25 - microscript/ILibDuktape_Polyfills.c | 11 + microscript/ILibDuktape_ScriptContainer.c | 4 - microscript/ILibDuktape_fs.c | 2 - modules/heci.js | 1 + 10 files changed, 15 insertions(+), 1350 deletions(-) delete mode 100644 microscript/ILibDuktape_HECI.c delete mode 100644 microscript/ILibDuktape_HECI.h diff --git a/makefile b/makefile index eb004da..a217685 100644 --- a/makefile +++ b/makefile @@ -118,7 +118,7 @@ SOURCES += microscript/ILibDuktape_SimpleDataStore.c microscript/ILibDuktape_Gen SOURCES += microscript/ILibDuktape_fs.c microscript/ILibDuktape_SHA256.c microscript/ILibduktape_EventEmitter.c SOURCES += microscript/ILibDuktape_EncryptionStream.c microscript/ILibDuktape_Polyfills.c microscript/ILibDuktape_Dgram.c SOURCES += microscript/ILibDuktape_ScriptContainer.c microscript/ILibDuktape_MemoryStream.c microscript/ILibDuktape_NetworkMonitor.c -SOURCES += microscript/ILibDuktape_ChildProcess.c microscript/ILibDuktape_HECI.c microscript/ILibDuktape_HttpStream.c microscript/ILibDuktape_Debugger.c +SOURCES += microscript/ILibDuktape_ChildProcess.c microscript/ILibDuktape_HttpStream.c microscript/ILibDuktape_Debugger.c SOURCES += $(ADDITIONALSOURCES) # Mesh Agent core diff --git a/meshconsole/MeshConsole.vcxproj b/meshconsole/MeshConsole.vcxproj index 29eac37..b5b7376 100644 --- a/meshconsole/MeshConsole.vcxproj +++ b/meshconsole/MeshConsole.vcxproj @@ -68,7 +68,6 @@ - @@ -118,7 +117,6 @@ - diff --git a/meshservice/MeshService.vcxproj b/meshservice/MeshService.vcxproj index 096bb1a..7c72d1c 100644 --- a/meshservice/MeshService.vcxproj +++ b/meshservice/MeshService.vcxproj @@ -573,7 +573,6 @@ - @@ -625,7 +624,6 @@ - diff --git a/microscript/ILibDuktape_ChildProcess.c b/microscript/ILibDuktape_ChildProcess.c index 538fa58..5c0f5cc 100644 --- a/microscript/ILibDuktape_ChildProcess.c +++ b/microscript/ILibDuktape_ChildProcess.c @@ -170,7 +170,8 @@ duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx) } duk_push_this(ctx); // [spawnedProcess] - char *_target = Duktape_GetStringPropertyValue(ctx, -1, "_target", NULL); + //char *_target = Duktape_GetStringPropertyValue(ctx, -1, "_target", NULL); + if (!ILibChain_IsLinkAlive(Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager))) { return(ILibDuktape_Error(ctx, "Cannot waitExit() because JS Engine is exiting")); diff --git a/microscript/ILibDuktape_HECI.c b/microscript/ILibDuktape_HECI.c deleted file mode 100644 index c205bc3..0000000 --- a/microscript/ILibDuktape_HECI.c +++ /dev/null @@ -1,1313 +0,0 @@ -/* -Copyright 2006 - 2018 Intel Corporation - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include "ILibDuktape_HECI.h" -#include "ILibDuktapeModSearch.h" -#include "ILibDuktape_Helpers.h" -#include "ILibDuktape_DuplexStream.h" -#include "ILibDuktape_EventEmitter.h" -#include "ILibDuktape_ChildProcess.h" -#include "../microstack/ILibParsers.h" -#include "../microstack/ILibProcessPipe.h" -#include "../microstack/ILibRemoteLogging.h" - -#ifndef _NOHECI - -#ifdef WIN32 -#include -#include -#include -#include -DEFINE_GUID(GUID_DEVINTERFACE_HECI, 0xE2D1FF34, 0x3458, 0x49A9, 0x88, 0xDA, 0x8E, 0x69, 0x15, 0xCE, 0x9B, 0xE5); -#elif defined(_POSIX) -typedef struct HECI_client -{ - unsigned int max_msg_length; - unsigned char protocol_version; - unsigned char reserved[3]; -}HECI_client; -typedef struct uuid_le -{ - unsigned char b[16]; -}uuid_le; -struct HECI_CONNECT_client_data -{ - union - { - uuid_le uuid; - HECI_client properties; - }; -}; -#endif - -#define ILibDuktape_HECI_ChainLink "\xFF_HECI_ChainLink" -#define ILibDuktape_HECI_Descriptor "\xFF_HECI_Descriptor" -#define ILibDuktape_HECI_ChildProcess "\xFF_HECI_ChildProcess" -#define ILibDuktape_HECI_Q "\xFF_HECI_Q" -#define ILibDuktape_HECI_CTX_PTRS "\xFF_HECI_CTX_PTRS" -//#define ILibDuktape_HECI_IoctlWaitHandle "\xFF_HECI_IoctlWaitHandle" -#define ILibDuktape_HECI_OVERLAPPED "\xFF_HECI_OVERLAPPED" -#define ILibDuktape_HECI_Child "\xFF_HECI_Child" -#define ILibDuktape_HECI_Parent "\xFF_HECI_Parent" -#define ILibDuktape_HECI_Root "\xFF_HECI_Root" -#define ILibDuktape_HECI_MaxBufferSize "\xFF_HECI_MaxBufSize" -#define ILibDuktape_HECI_SessionMemPtr "\xFF_HECI_SessionMemPtr" -#define ILibDuktape_HECI_Session_NoPipeline "\xFF_HECI_Session_NoPipeline" -#define ILibDuktape_HECI_Session_Metadata "\xFF_HECI_Session_Metadata" - -#ifdef __DOXY__ -/*! -\implements EventEmitter -\brief JavaScript object interface for HECI calls. require('heci') to use; -*/ -class Heci -{ -public: - /*! - \brief Performs an Ioctl on the HECI device - \param code Ioctl Code to invoke - \param inBuffer \ Input data for Ioctl. Can be null - \param outBuffer \ Optional. Output data from Ioctl. Must be specified if Ioctl code returns data - \param callback Dispatched when a response is received from the HECI device\n - status Success Code. 0 = Success, Error code on failure\n - buffer \ Output Buffer\n - args Optional parameters that were passed in\n - \param args Optional arguments to pass when the callback is called - */ - void doIoctl(code, inBuffer[, outBuffer], callback[, ...args]); -}; -#endif - -typedef struct ILibDuktape_HECI_ioctl_data -{ - duk_context *ctx; - uintptr_t ctxnonce; - void *heciObject; - void *data; - void *Q; - void *chain; - ILibProcessPipe_Manager pipeManager; -#ifdef WIN32 - OVERLAPPED v; - HANDLE device; - DWORD bytesReceived; - DWORD abort; -#elif defined(_POSIX) - int device; -#endif - void *reserved; - - int code; - char *outBuffer; - void *outBuffer_obj; - duk_size_t outBufferLen; - duk_size_t bufferLen; - char buffer[]; -}ILibDuktape_HECI_ioctl_data; - -typedef struct ILibDuktape_HECI_Session -{ - void *chain; - int noPipelining; - ILibDuktape_DuplexStream *stream; -#ifdef WIN32 - OVERLAPPED v; - OVERLAPPED wv; - ILibProcessPipe_Manager mgr; - HANDLE descriptor; - DWORD bytesRead; -#else - int descriptor; -#endif - ILibQueue PendingWrites; - duk_size_t bufferSize; - char buffer[]; -}ILibDuktape_HECI_Session; -typedef struct ILibDuktape_HECI_WriteState -{ - ILibDuktape_HECI_Session *session; - int returnIgnored; -#ifndef WIN32 - int bufferOffset; -#endif - int bufferLen; - char buffer[]; -}ILibDuktape_HECI_WriteState; - -typedef struct HECI_chainLink -{ - ILibChain_Link link; - duk_context *ctx; - ILibDuktape_HECI_Session *session; - void *heciObject; - int descriptor; - int paused; -}HECI_chainLink; - -void ILibDuktape_HECI_Push(duk_context *ctx, void *chain); -ILibTransport_DoneState ILibDuktape_HECI_Session_WriteHandler_Process(ILibDuktape_HECI_Session *session); -extern int ILibDuktape_HECI_Debug; - -#ifdef WIN32 -BOOL ILibDuktape_HECI_Session_ReceiveSink(void *chain, HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user); - -HANDLE ILibDuktape_HECI_windowsInit() -{ - PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetail = NULL; - HDEVINFO hDeviceInfo; - DWORD bufferSize; - SP_DEVICE_INTERFACE_DATA interfaceData; - LONG ii = 0; - HANDLE retVal = NULL; - - if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_windowsInit()\n"); } - - // Find all devices that have our interface - hDeviceInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_HECI, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (hDeviceInfo == INVALID_HANDLE_VALUE) - { - if (ILibDuktape_HECI_Debug) { printf("...[FAILED]\n"); } - return(NULL); - } - if (ILibDuktape_HECI_Debug) { printf("...[Acquired hDeviceInfo]\n"); } - - - // Setup the interface data struct - interfaceData.cbSize = sizeof(interfaceData); - for (ii = 0; - SetupDiEnumDeviceInterfaces(hDeviceInfo, NULL, (LPGUID)&GUID_DEVINTERFACE_HECI, ii, &interfaceData); - ++ii) - { - // Found our device instance - if (!SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &interfaceData, NULL, 0, &bufferSize, NULL)) - { - DWORD err = GetLastError(); - if (err != ERROR_INSUFFICIENT_BUFFER) - { - continue; - } - } - - // Allocate a big enough buffer to get detail data - deviceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)ILibMemory_AllocateA(bufferSize); - if (deviceDetail == NULL) { continue; } - - // Setup the device interface struct - deviceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); - - // Try again to get the device interface detail info - if (!SetupDiGetDeviceInterfaceDetail(hDeviceInfo, &interfaceData, deviceDetail, bufferSize, NULL, NULL)) - { - deviceDetail = NULL; - continue; - } - - break; - } - SetupDiDestroyDeviceInfoList(hDeviceInfo); - - if (deviceDetail == NULL) - { - if (ILibDuktape_HECI_Debug) { printf("...[deviceDetail FAILED]\n"); } - return(NULL); - } - - retVal = CreateFile(deviceDetail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (retVal == INVALID_HANDLE_VALUE) - { - if (ILibDuktape_HECI_Debug) { printf("...[FAILED to acquire descriptor]\n"); } - return(NULL); - } - if (ILibDuktape_HECI_Debug) { printf("...[Acquired Descriptor]\n"); } - - return(retVal); -} -#else -int ILibDuktape_HECI_linuxInit() -{ - int fd, flags; - - if ((fd = open("/dev/mei", O_RDWR)) == -1 && (fd = open("/dev/mei0", O_RDWR)) == -1) - { - return(-1); - } - else - { - flags = fcntl(fd, F_GETFL, 0); - if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) { printf("Failed to set O_NONBLOCK\n"); close(fd); fd = -1; } - return(fd); - } -} -#endif - -duk_ret_t ILibDuktape_HECI_SessionFinalizer(duk_context *ctx) -{ - if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_SessionFinalizer()\n"); } - if (duk_has_prop_string(ctx, 0, ILibDuktape_HECI_SessionMemPtr)) - { - duk_get_prop_string(ctx, 0, ILibDuktape_HECI_SessionMemPtr); - ILibDuktape_HECI_Session *s = (ILibDuktape_HECI_Session*)Duktape_GetBuffer(ctx, -1, NULL); - if (s != NULL && s->PendingWrites != NULL) { ILibQueue_Destroy(s->PendingWrites); } // ToDo: If there is anything pending, we need to clear that too - if (s != NULL) { s->stream = NULL; } - } - return(0); -} - - -void ILibDuktape_HECI_Session_EmitErrorEvent(void *chain, void *session) -{ - ILibDuktape_HECI_Session *s = (ILibDuktape_HECI_Session*)session; - duk_context *ctx = s->stream->readableStream->ctx; - if (ILibIsRunningOnChainThread(chain) == 0) { Duktape_RunOnEventLoop(chain, duk_ctx_nonce(ctx), ctx, ILibDuktape_HECI_Session_EmitErrorEvent, NULL, session); return; } - - duk_push_heapptr(ctx, s->stream->ParentObject); // [session] - duk_get_prop_string(ctx, -1, "emit"); // [session][emit] - duk_swap_top(ctx, -2); // [emit][this] - duk_push_string(ctx, "error"); // [emit][this][error] - duk_push_error_object(ctx, DUK_ERR_ERROR, "HECI Connection Error"); // [emit][this][error][err] - if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "HECI.session.onError(): "); } - duk_pop(ctx); // ... -} -void ILibDuktape_HECI_Session_EmitStreamReady(void *chain, void *session) -{ - if (ILibIsRunningOnChainThread(chain) == 0) { Duktape_RunOnEventLoop(chain, duk_ctx_nonce(((ILibDuktape_HECI_Session*)session)->stream->writableStream->ctx), ((ILibDuktape_HECI_Session*)session)->stream->writableStream->ctx, ILibDuktape_HECI_Session_EmitStreamReady, NULL, session); return; } - ILibDuktape_DuplexStream_Ready(((ILibDuktape_HECI_Session*)session)->stream); -} - -#ifdef WIN32 -BOOL ILibDuktape_HECI_Session_WriteHandler_Ready(void *chain, HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user) -{ - if (errors != ILibWaitHandle_ErrorStatus_NONE) { return(FALSE); } - - ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user; - DWORD bytesWritten; - - if (!ILibMemory_CanaryOK(session)) { return(FALSE); } - - ILibChain_RemoveWaitHandle(session->chain, session->wv.hEvent); - - if (session->noPipelining == 0) - { - ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)ILibQueue_DeQueue(session->PendingWrites); - free(state); - } - - if (GetOverlappedResult(session->descriptor, &(session->wv), &bytesWritten, FALSE) == 0) - { - // Broken Connection - ILibDuktape_HECI_Session_EmitErrorEvent(session->chain, (void*)session); - } - else - { - if (session->noPipelining == 0) - { - // Write Completed - ILibDuktape_HECI_Session_WriteHandler_Process(session); - } - } - return(TRUE); -} -#endif - -ILibTransport_DoneState ILibDuktape_HECI_Session_WriteHandler_Process(ILibDuktape_HECI_Session *session) -{ - ILibTransport_DoneState retVal = ILibTransport_DoneState_ERROR; - int returnIgnored = 0; - -#ifdef WIN32 - DWORD bytesWritten; - BOOL result = TRUE; -#else - ssize_t bytesWritten; -#endif - - while (session->noPipelining || ILibQueue_GetCount(session->PendingWrites) > 0) - { - ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)ILibQueue_PeekQueue(session->PendingWrites); - returnIgnored = state->returnIgnored; - -#ifdef WIN32 - if ((result = WriteFile(state->session->descriptor, state->buffer, state->bufferLen, &bytesWritten, &(state->session->wv))) == TRUE) - { - if (session->noPipelining == 0) { ILibQueue_DeQueue(state->session->PendingWrites); free(state); } - } - else - { - break; - } -#elif defined(_POSIX) - - bytesWritten = write(state->session->descriptor, state->buffer + state->bufferOffset, state->bufferLen - state->bufferOffset); - if (bytesWritten > 0) - { - state->bufferOffset += bytesWritten; - if (state->bufferOffset == state->bufferLen) { ILibQueue_DeQueue(state->session->PendingWrites); free(state); retVal = session->noPipelining == 0 ? ILibTransport_DoneState_COMPLETE:ILibTransport_DoneState_INCOMPLETE; } - } - else - { - if (errno != EAGAIN) - { - // Error Occured - retVal = ILibTransport_DoneState_ERROR; - ILibDuktape_HECI_Session_EmitErrorEvent(session->chain, (void*)session); - } - else - { - retVal = ILibTransport_DoneState_INCOMPLETE; - } - break; - } -#endif - - if (session->noPipelining != 0) { break; } - } - -#ifdef WIN32 - if (result == FALSE) - { - if (GetLastError() == ERROR_IO_PENDING) - { - // Not done writing - retVal = ILibTransport_DoneState_INCOMPLETE; - ILibChain_AddWaitHandle(session->chain, session->wv.hEvent, -1, ILibDuktape_HECI_Session_WriteHandler_Ready, session); - } - else - { - // Error Occured - retVal = ILibTransport_DoneState_ERROR; - ILibDuktape_HECI_Session_EmitErrorEvent(session->chain, (void*)session); - } - } - else - { - if (session->noPipelining == 0) - { - // No more Pending Writes - retVal = ILibTransport_DoneState_COMPLETE; - if (returnIgnored != 0) { ILibDuktape_HECI_Session_EmitStreamReady(session->chain, (void*)session); } - } - else - { - retVal = ILibTransport_DoneState_INCOMPLETE; - } - } -#else - if (ILibQueue_GetCount(session->PendingWrites) == 0 && session->noPipelining == 0) - { - // No more Pending Writes - retVal = ILibTransport_DoneState_COMPLETE; - if (returnIgnored != 0) { ILibDuktape_HECI_Session_EmitStreamReady(session->chain, (void*)session); } - } -#endif - return(retVal); -} - -#ifdef WIN32 -void __stdcall ILibDuktape_HECI_Session_WriteHandler(ULONG_PTR obj) -{ - // This Method is always dispatched from the WindowsRunLoop APC Thread - - ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)obj; - ILibQueue_EnQueue(state->session->PendingWrites, state); - - if (ILibQueue_GetCount(state->session->PendingWrites) == 1) - { - // No Pending Writes, so we can go ahead and send out the first block - ILibDuktape_HECI_Session_WriteHandler_Process(state->session); - } -} -#elif defined(_POSIX) -ILibTransport_DoneState ILibDuktape_HECI_Session_WriteHandler(void *chain, ILibDuktape_HECI_WriteState* state) -{ - // This Method is always dispatched from the Microstack Thread - ILibQueue_EnQueue(state->session->PendingWrites, state); - - if (ILibQueue_GetCount(state->session->PendingWrites) == 1) - { - return(ILibDuktape_HECI_Session_WriteHandler_Process(state->session)); - } - else - { - return(ILibTransport_DoneState_INCOMPLETE); - } -} -#endif - -ILibTransport_DoneState ILibDuktape_HECI_Session_WriteSink_NoPipeline(void *chain, void *user) -{ - // This is always called from the Microstack Thread - - ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)user; - ILibQueue_EnQueue(state->session->PendingWrites, state); - if (ILibQueue_GetCount(state->session->PendingWrites) == 1) - { - return(ILibDuktape_HECI_Session_WriteHandler_Process(state->session)); - } - else - { - return(ILibTransport_DoneState_INCOMPLETE); - } -} -ILibTransport_DoneState ILibDuktape_HECI_Session_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user) -{ - if ((duk_size_t)bufferLen > ((ILibDuktape_HECI_Session*)user)->bufferSize) { return(ILibTransport_DoneState_ERROR); } - - ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user; - ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)ILibMemory_Allocate(bufferLen + sizeof(ILibDuktape_HECI_WriteState), 0, NULL, NULL); - state->session = session; - state->bufferLen = bufferLen; - memcpy_s(state->buffer, bufferLen, buffer, bufferLen); - - if (session->noPipelining == 0) - { -#if defined(WIN32) - state->returnIgnored = 1; - ILibDuktape_HECI_Session_WriteHandler((ULONG_PTR)state); -#elif defined(_POSIX) - if (ILibIsRunningOnChainThread(stream->readableStream->chain) != 0) - { - return(ILibDuktape_HECI_Session_WriteHandler(NULL, state)); - } - else - { - state->returnIgnored = 1; - ILibChain_RunOnMicrostackThreadEx(stream->readableStream->chain, (ILibChain_StartEvent)ILibDuktape_HECI_Session_WriteHandler, state); - } -#endif - } - else - { - // We can't pipeline write requests - if (ILibIsRunningOnChainThread(stream->readableStream->chain) != 0) - { - return(ILibDuktape_HECI_Session_WriteSink_NoPipeline(stream->readableStream->chain, state)); - } - else - { - state->returnIgnored = 1; - Duktape_RunOnEventLoop(stream->readableStream->chain, duk_ctx_nonce(stream->readableStream->ctx), stream->readableStream->ctx, (Duktape_EventLoopDispatch)ILibDuktape_HECI_Session_WriteSink_NoPipeline, NULL, state); - } - } - - return(ILibTransport_DoneState_INCOMPLETE); -} -void ILibDuktape_HECI_Session_EndSink(ILibDuktape_DuplexStream *stream, void *user) -{ - duk_context *ctx = stream->readableStream->ctx; - duk_push_this(ctx); - duk_get_prop_string(ctx, -1, "disconnect"); - duk_swap_top(ctx, -2); - if (duk_pcall_method(ctx, 0) != 0) { ILibDuktape_Process_UncaughtException(ctx); } - duk_pop(ctx); -} -void ILibDuktape_HECI_Session_PauseSink(ILibDuktape_DuplexStream *sender, void *user) -{ -#ifdef WIN32 - // NO-OP Because we are already PAUSED, since we context switched - UNREFERENCED_PARAMETER(sender); - UNREFERENCED_PARAMETER(user); -#else - UNREFERENCED_PARAMETER(sender); - UNREFERENCED_PARAMETER(user); -#endif -} -void ILibDuktape_HECI_Session_ResumeSink_NoPipeline(void *chain, void *user) -{ - // This is always called from the Microstack Thread - ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user; - ILibDuktape_HECI_WriteState *state = (ILibDuktape_HECI_WriteState*)ILibQueue_DeQueue(session->PendingWrites); - free(state); - - if (ILibQueue_GetCount(session->PendingWrites) == 0) - { - ILibDuktape_HECI_Session_EmitStreamReady(session->chain, session); - } - else - { - ILibDuktape_HECI_Session_WriteHandler_Process(session); - } -} -void ILibDuktape_HECI_Session_ResumeSink(ILibDuktape_DuplexStream *sender, void *user) -{ - ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user; - if (session->noPipelining != 0) - { - ILibDuktape_HECI_Session_ResumeSink_NoPipeline(sender->readableStream->chain, session); - } - -#ifdef WIN32 - BOOL result = ReadFile(session->descriptor, session->buffer, (DWORD)session->bufferSize, &(session->bytesRead), &(session->v)); - if (result == TRUE || GetLastError() == ERROR_IO_PENDING) - { - //if (ILibDuktape_HECI_Debug) { printf("...[Wait Handle Added]\n"); } - ILibChain_AddWaitHandle(session->chain, session->v.hEvent, -1, ILibDuktape_HECI_Session_ReceiveSink, session); - } -#endif -} -#ifdef WIN32 -void ILibDuktape_HECI_Session_ReceiveSink2(void *chain, void *user) -{ - ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user; - if (!ILibMemory_CanaryOK(session)) { return; } - - ILibDuktape_DuplexStream_WriteData(session->stream, session->buffer, session->bytesRead); - if (session->stream != NULL && !session->stream->readableStream->paused) - { - ILibDuktape_HECI_Session_ResumeSink(session->stream, session->stream->user); - } -} -BOOL ILibDuktape_HECI_Session_ReceiveSink(void *chain, HANDLE event, ILibWaitHandle_ErrorStatus errors, void* user) -{ - //if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Session_ReceiveSink\n"); } - if (errors != ILibWaitHandle_ErrorStatus_NONE) - { - if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Session_ReceiveSink\n"); } - if (ILibDuktape_HECI_Debug) { printf("...[ERROR: %d]\n", errors); } - return(FALSE); - } - //if (ILibDuktape_HECI_Debug) { printf("...[SIGNALED]\n"); } - ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)user; - if (ILibMemory_CanaryOK(session)) - { - if (GetOverlappedResult(session->descriptor, &(session->v), &(session->bytesRead), FALSE) == TRUE) - { - ILibDuktape_DuplexStream_WriteData(session->stream, session->buffer, session->bytesRead); - if (session->stream != NULL && !session->stream->readableStream->paused) - { - ILibDuktape_HECI_Session_ResumeSink(session->stream, session->stream->user); - } - } - } - return(FALSE); -} -void __stdcall ILibDuktape_HECI_Session_Start(ULONG_PTR obj) -{ - ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)obj; - DWORD bytesRead; - if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Session_Start()\n"); } - BOOL result = ReadFile(session->descriptor, session->buffer, (DWORD)session->bufferSize, &bytesRead, &(session->v)); - - duk_push_heapptr(session->stream->readableStream->ctx, session->stream->ParentObject); // [session] - ILibChain_AddWaitHandleEx(session->chain, session->v.hEvent, -1, ILibDuktape_HECI_Session_ReceiveSink, session, (char*)Duktape_GetStringPropertyValue(session->stream->readableStream->ctx, -1, ILibDuktape_HECI_Session_Metadata, "heci.session")); - duk_pop(session->stream->readableStream->ctx); // ... -} -#endif - -duk_ret_t ILibDuktape_HECI_create_OnClientConnect(duk_context *ctx) -{ - int statusCode = duk_require_int(ctx, 0); - ILibDuktape_HECI_Session *session = NULL; - duk_dup(ctx, 2); // [Session] - if (statusCode != 0) - { - duk_get_prop_string(ctx, -1, "emit"); // [session][emit] - duk_swap_top(ctx, -2); // [emit][this] - duk_push_string(ctx, "error"); // [emit][this][error] - duk_push_error_object(ctx, DUK_ERR_ERROR, "HECI Connection Error [%d]", statusCode); // [emit][this][error][err] - duk_push_int(ctx, statusCode); duk_put_prop_string(ctx, -2, "errno"); - if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "HECI.session.onError(): "); } - duk_pop(ctx); // ... - } - else - { - duk_size_t bufferLen; - char *buffer = (char*)Duktape_GetBuffer(ctx, 1, &bufferLen); - if (bufferLen > 4) - { - duk_push_int(ctx, ((int*)buffer)[0]); - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_MaxBufferSize); // [session] - - session = (ILibDuktape_HECI_Session*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_HECI_Session) + ((int*)buffer)[0]); // [session][buffer] - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_SessionMemPtr); // [session] -#ifdef WIN32 - session->v.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - session->wv.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); -#endif - session->chain = Duktape_GetChain(ctx); - session->bufferSize = (duk_size_t)((int*)buffer)[0]; - session->stream = ILibDuktape_DuplexStream_Init(ctx, - ILibDuktape_HECI_Session_WriteSink, ILibDuktape_HECI_Session_EndSink, - ILibDuktape_HECI_Session_PauseSink, ILibDuktape_HECI_Session_ResumeSink, session); - ILibDuktape_CreateReadonlyProperty_int(ctx, "maxBufferSize", (int)session->bufferSize); - session->PendingWrites = ILibQueue_Create(); - duk_push_current_function(ctx); - session->noPipelining = Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_HECI_Session_NoPipeline, 0); - duk_pop(ctx); -#ifdef _POSIX - //printf("Session: %p\n", session); - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Child); // [session][heci] - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_ChainLink); // [session][heci][link] - HECI_chainLink *link = (HECI_chainLink*)duk_get_pointer(ctx, -1); - link->session = session; - duk_pop_2(ctx); // [session] -#endif - - //printf("NoPipeline: %d\n", session->noPipelining); - } - else - { - // Even tho it was a success, the result buffer is invalid - duk_get_prop_string(ctx, -1, "emit"); // [session][emit] - duk_swap_top(ctx, -2); // [emit][this] - duk_push_string(ctx, "error"); // [emit][this][error] - duk_push_error_object(ctx, DUK_ERR_ERROR, "HECI Connection Error"); // [emit][this][error][err] - if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "HECI.session.onError(): "); } - duk_pop(ctx); // ... - } - } - - if (session != NULL) - { - // Hookup the Send/Receive logic -#ifdef WIN32 - duk_push_this(ctx); // [HECI] - session->descriptor = (HANDLE)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_Descriptor); - duk_del_prop_string(ctx, -1, ILibDuktape_HECI_Descriptor); - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_ChildProcess); // [HECI][childProcess] - duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager); // [HECI][childProcess][manager] - session->mgr = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1); - ILibDuktape_HECI_Session_Start((ULONG_PTR)session); -#else - duk_push_this(ctx); // [HECI] - session->descriptor = Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_HECI_Descriptor, -1); - ILibForceUnBlockChain(session->chain); -#endif - - duk_dup(ctx, 2); - duk_get_prop_string(ctx, -1, "emit"); // [session][emit] - duk_swap_top(ctx, -2); // [emit][this] - duk_push_string(ctx, "connect"); // [emit][this][connect] - if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "HECI.session.onConnect(): "); } - duk_pop(ctx); // ... - - - } - return(0); -} -duk_ret_t ILibDuktape_HECI_Session_connect(duk_context *ctx) -{ - if (ILibDuktape_HECI_Debug) { printf("connect()\n"); } - - int i; - int nargs = duk_get_top(ctx); - duk_push_this(ctx); // [Session] - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Child); // [Session][HECI] - duk_remove(ctx, -2); // [HECI] - - duk_get_prop_string(ctx, -1, "doIoctl"); // [HECI][func] - duk_swap_top(ctx, -2); // [doIoctl][this] - duk_get_prop_string(ctx, -1, "IOCTL"); // [doIoctl][this][IOCTL] - duk_get_prop_string(ctx, -1, "CLIENT_CONNECT"); // [doIoctl][this][IOCTL][CLIENT_CONNECT] - duk_remove(ctx, -2); // [doIoctl][this][CLIENT_CONNECT] - duk_dup(ctx, 0); // [doIoctl][this][CLIENT_CONNECT][guid] - duk_push_fixed_buffer(ctx, 16); // [doIoctl][this][CLIENT_CONNECT][guid][outBuffer] - duk_push_buffer_object(ctx, -1, 0, 16, DUK_BUFOBJ_NODEJS_BUFFER); // [doIoctl][this][CLIENT_CONNECT][guid][outBuffer][buf] - duk_remove(ctx, -2); - duk_push_c_function(ctx, ILibDuktape_HECI_create_OnClientConnect, DUK_VARARGS); // [doIoctl][this][CLIENT_CONNECT][guid][outBuffer][callback] - duk_push_int(ctx, 0); - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Session_NoPipeline); - - for (i = 1; i < nargs; ++i) - { - if (duk_is_function(ctx, i)) { ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter_GetEmitter_fromThis(ctx), "connect", duk_require_heapptr(ctx, i)); } - else if (duk_is_object(ctx, i)) - { - int noPipeline = Duktape_GetIntPropertyValue(ctx, i, "noPipeline", 0); - duk_push_int(ctx, noPipeline); - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Session_NoPipeline); - } - } - duk_push_this(ctx); // [doIoctl][this][CLIENT_CONNECT][guid][outBuffer][callback][Session] - duk_call_method(ctx, 5); // [retVal] - duk_pop(ctx); // ... - return(0); -} -#ifdef WIN32 -void __stdcall ILibDuktape_HECI_Session_CloseSink2(ULONG_PTR obj) -{ - HANDLE h = (HANDLE)obj; - CloseHandle(h); -} -#endif -duk_ret_t ILibDuktape_HECI_Session_close(duk_context *ctx) -{ - if (ILibDuktape_HECI_Debug) { printf("heci.disconnect()\n\n"); } - duk_push_this(ctx); // [session] - - if (duk_has_prop_string(ctx, -1, ILibDuktape_HECI_Child)) - { - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Child); // [session][heci] - duk_get_prop_string(ctx, -1, "disconnect"); // [session][heci][close] - duk_swap_top(ctx, -2); // [session][close][this] - duk_call_method(ctx, 0); - } - - duk_push_this(ctx); -#ifdef WIN32 - ILibDuktape_HECI_Session *session = NULL; - if (duk_has_prop_string(ctx, -1, ILibDuktape_HECI_SessionMemPtr)) - { - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_SessionMemPtr); // [HECI][SESSION] - session = (ILibDuktape_HECI_Session*)Duktape_GetBuffer(ctx, -1, NULL); - - ILibChain_RemoveWaitHandle(session->chain, session->v.hEvent); - ILibChain_RemoveWaitHandle(session->chain, session->wv.hEvent); - session->stream = NULL; - CloseHandle(session->descriptor); - CloseHandle(session->v.hEvent); session->v.hEvent = NULL; - CloseHandle(session->wv.hEvent); session->wv.hEvent = NULL; - } -#else - int d = Duktape_GetIntPropertyValue(ctx, -1, ILibDuktape_HECI_Descriptor, -1); - HECI_chainLink *hcl = (HECI_chainLink*)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_ChainLink); - if (hcl != NULL) - { - hcl->descriptor = -1; - if (d != -1) { close(d); }; - duk_del_prop_string(ctx, -1, ILibDuktape_HECI_Descriptor); - } -#endif - - duk_push_this(ctx); // [Session] - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Root); // [Session][root] - ILibDuktape_Push_ObjectStash(ctx); // [Session][root][stash] - duk_del_prop_string(ctx, -1, Duktape_GetStashKey(duk_get_heapptr(ctx, -3))); - - return(0); -} -duk_ret_t ILibDuktape_HECI_session_descriptorMetadata(duk_context *ctx) -{ - duk_push_this(ctx); // [session] - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Session_Metadata); // [session][oldVal] - duk_push_string(ctx, ", "); // [session][oldVal][newVal] - duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [session][val] - duk_dup(ctx, 0); // [session][val][newVal] - duk_string_concat(ctx, -2); duk_remove(ctx, -2); // [session][newVal] - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Session_Metadata); // [session] - - ILibDuktape_HECI_Session *session = (ILibDuktape_HECI_Session*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_HECI_SessionMemPtr); - if (session != NULL) - { - ILibChain_WaitHandle_UpdateMetadata(duk_ctx_chain(ctx), session->v.hEvent, (char*)Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_HECI_Session_Metadata, "heci.session")); - } - return(0); -} -duk_ret_t ILibDuktape_HECI_create(duk_context *ctx) -{ - if (ILibDuktape_HECI_Debug) { printf("\n\nILibDuktape_HECI_create()\n"); } - - duk_push_object(ctx); // [Session] - ILibDuktape_WriteID(ctx, "heci.session"); - ILibDuktape_HECI_Push(ctx, NULL); // [Session][HECI] - duk_dup(ctx, -2); // [Session][HECI][Session] - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Parent); // [Session][HECI] - duk_push_this(ctx); // [session][HECI][root] - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Root); // [session][HECI] - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Child); // [Session] - duk_push_string(ctx, "heci.session"); duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Session_Metadata); - ILibDuktape_CreateEventWithSetterEx(ctx, "descriptorMetadata", ILibDuktape_HECI_session_descriptorMetadata); - - duk_push_this(ctx); // [Session][root] - ILibDuktape_Push_ObjectStash(ctx); // [Session][root][stash] - duk_dup(ctx, -3); // [Session][root][stash][Session] - duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [Session][root][stash] - duk_pop(ctx); // [Session][root] - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Root); // [Session] - - ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_Create(ctx); - ILibDuktape_EventEmitter_CreateEventEx(emitter, "connect"); - ILibDuktape_EventEmitter_CreateEventEx(emitter, "error"); - ILibDuktape_CreateProperty_InstanceMethod(ctx, "connect", ILibDuktape_HECI_Session_connect, DUK_VARARGS); - ILibDuktape_CreateFinalizer(ctx, ILibDuktape_HECI_SessionFinalizer); - ILibDuktape_CreateInstanceMethod(ctx, "disconnect", ILibDuktape_HECI_Session_close, 0); - return(1); -} - - -void ILibDuktape_HECI_IoctlHandler_Dispatch(void *chain, void *user) -{ - ILibDuktape_HECI_ioctl_data *data = (ILibDuktape_HECI_ioctl_data*)user; - duk_size_t count; - int i; - duk_context *ctx; - - if (!ILibMemory_CanaryOK(data) || ! ILibMemory_CanaryOK(data->reserved)) - { - // Abort Dispatch, becuase the HECI object was GC'ed. - if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_IoctlHandler_Dispatch() [ABORTED]\n"); } - if (ILibMemory_CanaryOK(data)) - { - if (ILibDuktape_HECI_Debug) { printf("...Release HECI Ioctl Data [%p]\n", (void*)data); } - ILibMemory_Free(data); - } - return; - } - - ctx = data->ctx; - duk_push_heapptr(data->ctx, data->data); // [array] - duk_push_heapptr(data->ctx, data->heciObject); // [array][heci] - duk_get_prop_index(data->ctx, -2, 2); // [array][heci][callback] - duk_swap_top(data->ctx, -2); // [array][callback][this] - count = duk_get_length(data->ctx, -3); - duk_push_int(data->ctx, data->code); // [array][callback][this][status] - duk_get_prop_index(data->ctx, -4, 1); // [array][callback][this][status][buffer] - - for (i = 3; i < (int)count; ++i) - { - duk_get_prop_index(data->ctx, -i - 2, i); // [array][callback][this][status][buffer][...args...] - } - if (duk_pcall_method(data->ctx, (duk_idx_t)count - 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "heci.ioctlHandler_Dispatch.callback(): "); } - duk_pop_2(data->ctx); // ... - - duk_push_heapptr(data->ctx, data->heciObject); // [heci] - ILibDuktape_Push_ObjectStash(data->ctx); // [heci][stash] - duk_del_prop_string(data->ctx, -1, Duktape_GetStashKey(data->data)); // (This will dereference args passed to doIoctl) - duk_pop_2(ctx); // ... - if (ILibDuktape_HECI_Debug) { printf("doIoctl() [COMPLETE] -> ** Release HECI Ioctl Data [%p]\n", (void*)data); } - ILibMemory_Free(data); -} -#ifdef WIN32 -//void ILibDuktape_HECI_NextIoctl(ILibQueue q); -void ILibDuktape_HECI_NextIoctl(duk_context *ctx, void *heci); -BOOL ILibDuktape_HECI_IoctlHandler(void * chain, HANDLE h, ILibWaitHandle_ErrorStatus errors, void *user) -{ - if (!ILibMemory_CanaryOK(user)) { return(FALSE); } - - duk_context *ctx = (duk_context*)((void**)user)[0]; - int top = duk_get_top(ctx); - - duk_push_heapptr(ctx, ((void**)user)[1]); // [HECI] - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [HECI][QUEUE] - HANDLE descriptor = Duktape_GetPointerProperty(ctx, -2, ILibDuktape_HECI_Descriptor); - OVERLAPPED *p = (OVERLAPPED*)Duktape_GetBufferProperty(ctx, -2, ILibDuktape_HECI_OVERLAPPED); - DWORD bytesReceived = 0; - - if (errors == ILibWaitHandle_ErrorStatus_NONE) - { - if (GetOverlappedResult(descriptor, p, &bytesReceived, FALSE) == FALSE) { return(TRUE); } - duk_queue_deQueue(ctx, -1); // [HECI][QUEUE][OBJ] - duk_get_prop_string(ctx, -1, "callback"); // [HECI][QUEUE][OBJ][callback] - duk_get_prop_string(ctx, -1, "apply"); // [HECI][QUEUE][OBJ][callback][apply] - duk_swap_top(ctx, -2); // [HECI][QUEUE][OBJ][apply][func] - duk_dup(ctx, -5); // [HECI][QUEUE][OBJ][apply][func][this] - duk_get_prop_string(ctx, -4, "args"); // [HECI][QUEUE][OBJ][apply][func][this][args] - duk_get_prop_string(ctx, -5, "outbuffer"); // [HECI][QUEUE][OBJ][apply][func][this][args][outbuffer] - if (!duk_is_null(ctx, -1)) { duk_buffer_slice(ctx, -1, 0, bytesReceived); } // [HECI][QUEUE][OBJ][apply][func][this][args][outbuffer] - duk_array_unshift(ctx, -2); // [HECI][QUEUE][OBJ][apply][func][this][args] - duk_push_int(ctx, 0); duk_array_unshift(ctx, -2); // [HECI][QUEUE][OBJ][apply][func][this][args] - duk_pcall_method(ctx, 2); duk_pop_2(ctx); // [HECI][QUEUE] - if (!duk_queue_isEmpty(ctx, -1)) - { - ILibDuktape_HECI_NextIoctl(ctx, ((void**)user)[1]); - duk_set_top(ctx, top); - return(TRUE); - } - } - else - { - DebugBreak(); - } - duk_set_top(ctx, top); - return(FALSE); -} -void ILibDuktape_HECI_NextIoctl(duk_context *ctx, void *heci) -{ - duk_push_heapptr(ctx, heci); // [HECI] - HANDLE descriptor = (HANDLE)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_Descriptor); - OVERLAPPED *p = (OVERLAPPED*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_HECI_OVERLAPPED); - void **ptrs = (void**)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_HECI_CTX_PTRS); - - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [HECI][QUEUE] - - duk_queue_peek(ctx, -1); // [HECI][QUEUE][OBJ] - duk_size_t bufferLen = 0; - duk_size_t outBufferLen = 0; - char *buffer = Duktape_GetBufferPropertyEx(ctx, -1, "buffer", &bufferLen); - char *outBuffer = Duktape_GetBufferPropertyEx(ctx, -1, "outbuffer", &outBufferLen); - DWORD dwIoControlCode = (DWORD)Duktape_GetIntPropertyValue(ctx, -1, "code", 0); - - DeviceIoControl(descriptor, dwIoControlCode, buffer, (DWORD)bufferLen, outBuffer, (DWORD)outBufferLen, NULL, p); - ILibChain_AddWaitHandleEx(duk_ctx_chain(ctx), p->hEvent, 5000, ILibDuktape_HECI_IoctlHandler, ptrs, "heci.doIoctl()"); -} -#endif - -duk_ret_t ILibDuktape_HECI_doIoctl(duk_context *ctx) -{ - int code = duk_require_int(ctx, 0); - duk_size_t bufferLen = 0; - char *buffer = duk_is_null(ctx, 1) ? NULL : (char*)Duktape_GetBuffer(ctx, 1, &bufferLen); - int nargs = duk_get_top(ctx); - int i; - duk_size_t outBufferLen; - char *outBuffer; - int cbx; - - if (duk_is_buffer(ctx, 2) || duk_is_buffer_data(ctx, 2)) - { - outBuffer = (char*)Duktape_GetBuffer(ctx, 2, &outBufferLen); - cbx = 3; - } - else - { - outBuffer = NULL; - outBufferLen = 0; - cbx = 2; - } - -#ifdef _POSIX - if (outBuffer == NULL) - { - outBuffer = buffer; - outBufferLen = bufferLen; - } - else - { - if (bufferLen < outBufferLen) { return(ILibDuktape_Error(ctx, "HECI.doIoctl(): Output Buffer too small")); } - memcpy_s(outBuffer, outBufferLen, buffer, bufferLen); - } -#endif - - duk_require_function(ctx, cbx); // Make sure a callback function was specified - - duk_push_this(ctx); // [HECI] -#ifdef WIN32 - if (!duk_has_prop_string(ctx, -1, ILibDuktape_HECI_Descriptor)) { return(ILibDuktape_Error(ctx, "Invalid Operation. Call Reset()")); } -#endif - duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [HECI][QUEUE] - duk_push_object(ctx); // [HECI][QUEUE][OBJ] - - duk_dup(ctx, cbx); duk_put_prop_string(ctx, -2, "callback"); - duk_dup(ctx, 1); duk_put_prop_string(ctx, -2, "buffer"); - if (outBufferLen > 0) { duk_dup(ctx, 2); } else { duk_push_null(ctx); } - duk_put_prop_string(ctx, -2, "outbuffer"); - duk_push_int(ctx, code); duk_put_prop_string(ctx, -2, "code"); - void **ptrs = Duktape_PushBuffer(ctx, 2 * sizeof(void*)); duk_put_prop_string(ctx, -2, ILibDuktape_HECI_CTX_PTRS); - ptrs[0] = ctx; - ptrs[1] = duk_get_heapptr(ctx, -3); - - duk_push_array(ctx); // [HECI][QUEUE][OBJ][ARGS] - for (i = cbx + 1; i < nargs; ++i) - { - duk_dup(ctx, i); // [HECI][QUEUE][OBJ][ARGS][arg] - duk_array_push(ctx, -2); // [HECI][QUEUE][OBJ][ARGS] - } - duk_put_prop_string(ctx, -2, "args"); // [HECI][QUEUE][OBJ] - duk_queue_enQueue(ctx, -2); // [HECI][QUEUE] - if (duk_get_length(ctx, -1) == 1) - { -#ifdef WIN32 - ILibDuktape_HECI_NextIoctl(ctx, duk_get_heapptr(ctx, -2)); -#else - ILibForceUnBlockChain(duk_ctx_chain(ctx)); -#endif - } - return(0); -// -// duk_require_function(ctx, cbx); -// duk_push_this(ctx); // [heci] -// duk_get_prop_string(ctx, -1, ILibDuktape_HECI_Q); // [heci][q] -// qptr = duk_get_heapptr(ctx, -1); -// duk_pop(ctx); // [heci] -// -// ILibDuktape_Push_ObjectStash(ctx); // [heci][stash] -// duk_push_array(ctx); // [heci][stash][array] -// ILibDuktape_HECI_ioctl_data *data; -// data = (ILibDuktape_HECI_ioctl_data*)ILibMemory_SmartAllocate(bufferLen + sizeof(ILibDuktape_HECI_ioctl_data)); -// data->ctxnonce = duk_ctx_nonce(ctx); -// if (ILibDuktape_HECI_Debug) { printf("doIoctl() -> Allocate HECI Ioctl Data [%p]\n", (void*)data); } -// data->reserved = Duktape_PushBuffer(ctx, sizeof(void*)); // [heci][stash][array][ptr] -// duk_put_prop_index(ctx, -2, 0); // [heci][stash][array] -// if (outBufferLen > 0) -// { // [heci][stash][array][buffer] -// duk_dup(ctx, 2); -// } -// else -// { -// duk_push_null(ctx); // [heci][stash][array][buffer] -// } -// -// duk_put_prop_index(ctx, -2, 1); // [heci][stash][array] -// data->ctx = ctx; -// -// duk_dup(ctx, cbx); // [heci][stash][array][callback] -// duk_put_prop_index(ctx, -2, 2); // [heci][stash][array] -// -//#ifdef WIN32 -// duk_get_prop_string(ctx, -3, ILibDuktape_HECI_IoctlWaitHandle); // [heci][stash][array][handle] -// data->v.hEvent = (HANDLE)duk_get_pointer(ctx, -1); -// duk_pop(ctx); // [heci][stash][array] -//#endif -// -// duk_get_prop_string(ctx, -3, ILibDuktape_HECI_Descriptor); // [heci][stash][array][descriptor] -//#ifdef WIN32 -// data->device = (HANDLE)duk_get_pointer(ctx, -1); -//#elif defined(_POSIX) -// data->device = duk_get_int(ctx, -1); -//#endif -// duk_pop(ctx); // [heci][stash][array] -// data->chain = Duktape_GetChain(ctx); -// data->Q = Q; -// data->code = code; -// data->outBuffer = outBuffer; -// data->outBufferLen = outBufferLen; -// data->heciObject = duk_get_heapptr(ctx, -3); -// data->bufferLen = bufferLen; -// data->data = duk_get_heapptr(ctx, -1); -// memcpy_s(data->buffer, bufferLen, buffer, bufferLen); -// -// for (i = cbx + 1; i < nargs; ++i) -// { -// duk_dup(ctx, i); // [heci][stash][array][object] -// duk_put_prop_index(ctx, -2, i-1); // [heci][stash][array] -// } -// duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [heci][stash] -// -// -//#ifdef WIN32 -// duk_get_prop_string(ctx, -2, ILibDuktape_HECI_ChildProcess); // [heci][stash][childProcess] -// duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_Manager); // [heci][stash][childProcess][manager] -// data->pipeManager = (ILibProcessPipe_Manager)duk_get_pointer(ctx, -1); -// -// ILibDuktape_HECI_apc_AddIoctl((ULONG_PTR)data); -//#elif defined(_POSIX) -// ILibDuktape_HECI_AddIoctl(data); -//#endif -// -// return(0); -} - -#ifdef WIN32 -void __stdcall ILibDuktape_HECI_Finalizer2(ULONG_PTR obj) -{ - ILibQueue Q = (ILibQueue)obj; - - if (ILibQueue_IsEmpty(Q) != 0) - { - if (ILibDuktape_HECI_Debug) { printf("<== Queue: %p Destroyed in Finalizer ==>\n", (void*)Q); } - ILibQueue_Destroy(Q); - } - else - { - void *node = ILibLinkedList_GetNode_Head((void*)Q); - while (node != NULL) - { - ((ILibDuktape_HECI_ioctl_data*)ILibLinkedList_GetDataFromNode(node))->abort = 1; - node = ILibLinkedList_GetNextNode(node); - } - } -} -#endif - -duk_ret_t ILibDuktape_HECI_Finalizer(duk_context *ctx) -{ - if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_Finalizer()\n"); } -#ifdef WIN32 - HANDLE h = Duktape_GetPointerProperty(ctx, 0, ILibDuktape_HECI_Descriptor); - if (h != NULL) { CloseHandle(h); } - OVERLAPPED *p = (OVERLAPPED*)Duktape_GetBufferProperty(ctx, 0, ILibDuktape_HECI_OVERLAPPED); - if (p->hEvent != NULL) - { - ILibChain_RemoveWaitHandle(duk_ctx_chain(ctx), p->hEvent); - CloseHandle(p->hEvent); - } -#endif - - -#ifdef _POSIX - if (duk_has_prop_string(ctx, 0, ILibDuktape_HECI_ChainLink)) - { - duk_get_prop_string(ctx, 0, ILibDuktape_HECI_ChainLink); - HECI_chainLink *h = (HECI_chainLink*)duk_get_pointer(ctx, -1); - h->ctx = NULL; - h->heciObject = NULL; - if (h->link.ParentChain != NULL) { ILibChain_SafeRemove(h->link.ParentChain, h); } - } -#endif - - return(0); -} -#if !defined(WIN32) && !defined(__APPLE__) -void ILibDuktape_HECI_PreSelect(void* object, fd_set *readset, fd_set *writeset, fd_set *errorset, int* blocktime) -{ - - int result; - HECI_chainLink *h = (HECI_chainLink*)object; - //printf("h = %p, descriptor = %d, paused = %d, session = %p\n", (void*)h, h->descriptor, h->paused, (void*)h->session); - - if (h->descriptor <= 0) { return; } - if (h->paused == 0 && h->session != NULL) { FD_SET(h->descriptor, readset); } - if (h->session != NULL && ILibMemory_CanaryOK(h->session) && ILibQueue_GetCount(h->session->PendingWrites) > 0) { FD_SET(h->descriptor, writeset); } - - while (ILibQueue_GetCount(h->Q) > 0 && h->paused == 0) - { - ILibDuktape_HECI_ioctl_data *data = (ILibDuktape_HECI_ioctl_data*)ILibQueue_DeQueue(h->Q); - switch (data->code) - { - case 0x00: - break; - case 0x01: - case 0x02: - case 0x03: - result = ioctl(h->descriptor, _IOC(_IOC_READ | _IOC_WRITE, 'H', data->code, data->outBufferLen), data->outBuffer); - data->code = result ? errno : 0; - ILibDuktape_HECI_IoctlHandler_Dispatch(NULL, data); - break; - default: - break; - } - } -} -void ILibDuktape_HECI_PostSelect(void* object, int slct, fd_set *readset, fd_set *writeset, fd_set *errorset) -{ - HECI_chainLink *h = (HECI_chainLink*)object; - if (h->descriptor <= 0) { return; } - - if (FD_ISSET(h->descriptor, readset)) - { - //printf("session = %p\n", (void*)h->session); - //printf("Attempting to read: %d bytes from %p\n", h->session->bufferSize, (void*)h->session->buffer); - int bytesRead = read(h->descriptor, h->session->buffer, h->session->bufferSize); - if (bytesRead >= 0) - { - ILibDuktape_DuplexStream_WriteData(h->session->stream, h->session->buffer, bytesRead); - } - else if(h->ctx != NULL && ILibMemory_CanaryOK(h->session)) - { - ILibDuktape_EventEmitter_SetupEmit(h->ctx, h->session->stream->ParentObject, "error"); // [emit][this][error] - duk_push_string(h->ctx, "HECI Read Error"); // [emit][this][error][msg] - duk_pcall_method(h->ctx, 2); duk_pop(h->ctx); // ... - - duk_push_heapptr(h->ctx, h->session->stream->ParentObject); // [heci] - duk_del_prop_string(h->ctx, -1, ILibDuktape_HECI_Descriptor); - duk_pop(h->ctx); // ... - - int td = h->descriptor; - h->descriptor = -1; - close(td); - } - } - if (FD_ISSET(h->descriptor, writeset)) - { - ILibDuktape_HECI_Session_WriteHandler_Process(h->session); - } -} -void ILibDuktape_HECI_Destroy(void *object) -{ - HECI_chainLink *h = (HECI_chainLink*)object; - if (h->ctx != NULL && h->heciObject != NULL) - { - duk_push_heapptr(h->ctx, h->heciObject); // [heci] - duk_del_prop_string(h->ctx, -1, ILibDuktape_HECI_ChainLink); - duk_pop(h->ctx); // ... - } - close(h->descriptor); -} -#endif - -duk_ret_t ILibDuktape_HECI_reset(duk_context *ctx) -{ - duk_push_this(ctx); -#ifdef WIN32 - if (ILibDuktape_HECI_Debug) { printf("ILibDuktape_HECI_reset()\n"); } - - HANDLE h = (HANDLE)Duktape_GetPointerProperty(ctx, -1, ILibDuktape_HECI_Descriptor); - if (h != NULL) - { - CloseHandle(h); - } - h = ILibDuktape_HECI_windowsInit(); - duk_push_pointer(ctx, h); - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Descriptor); -#endif - return(0); -} - -void ILibDuktape_HECI_Push(duk_context *ctx, void *chain) -{ - duk_push_object(ctx); // [HECI] - ILibDuktape_WriteID(ctx, "heci"); - ILibDuktape_CreateFinalizer(ctx, ILibDuktape_HECI_Finalizer); - -#ifdef WIN32 - HANDLE h = ILibDuktape_HECI_windowsInit(); - if (h == NULL) { ILibDuktape_Error(ctx, "Error initializing HECI"); return; } - duk_push_pointer(ctx, h); // [HECI][HANDLE] - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Descriptor); // [HECI] - - if (duk_peval_string(ctx, "require('child_process');") != 0) // [HECI][child_process] - { - ILibDuktape_Error(ctx, "Error instantiating dependency 'child_process'"); - return; - } - - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_ChildProcess); // [HECI] - OVERLAPPED *v = Duktape_PushBuffer(ctx, sizeof(OVERLAPPED)); // [HECI][OVERLAPPED] - v->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_OVERLAPPED); // [HECI] - void **ptrs = (void**)Duktape_PushBuffer(ctx, 2*sizeof(void*)); duk_put_prop_string(ctx, -2, ILibDuktape_HECI_CTX_PTRS); - ptrs[0] = ctx; - ptrs[1] = duk_get_heapptr(ctx, -1); - -#elif defined(_POSIX) && !defined(__APPLE__) - int h = ILibDuktape_HECI_linuxInit(); - if (h < 0) { ILibDuktape_Error(ctx, "error initializing HECI"); return; } - duk_push_int(ctx, h); // [HECI][descriptor] - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Descriptor); // [HECI] - - HECI_chainLink *hlink = ILibMemory_Allocate(sizeof(HECI_chainLink), 0, NULL, NULL); - hlink->link.MetaData = "ILibDuktape_HECI"; - hlink->ctx = ctx; - hlink->descriptor = h; - hlink->link.PreSelectHandler = ILibDuktape_HECI_PreSelect; - hlink->link.PostSelectHandler = ILibDuktape_HECI_PostSelect; - hlink->link.DestroyHandler = ILibDuktape_HECI_Destroy; - duk_push_pointer(ctx, hlink); // [HECI][link] - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_ChainLink); // [HECI] - - ILibChain_SafeAdd(Duktape_GetChain(ctx), hlink); -#endif - if (chain != NULL) { ILibDuktape_CreateInstanceMethod(ctx, "create", ILibDuktape_HECI_create, 0); } - ILibDuktape_CreateInstanceMethod(ctx, "doIoctl", ILibDuktape_HECI_doIoctl, DUK_VARARGS); - ILibDuktape_CreateInstanceMethod(ctx, "disconnect", ILibDuktape_HECI_Session_close, 0); - ILibDuktape_CreateInstanceMethod(ctx, "reset", ILibDuktape_HECI_reset, 0); - - duk_queue_create(ctx); - duk_put_prop_string(ctx, -2, ILibDuktape_HECI_Q); // [HECI] - duk_push_object(ctx); -#ifdef WIN32 - ILibDuktape_CreateReadonlyProperty_int(ctx, "HECI_VERSION", (int)(CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS))); - ILibDuktape_CreateReadonlyProperty_int(ctx, "CLIENT_CONNECT", (int)(CTL_CODE(0x8000, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS))); -#elif defined(_POSIX) - ILibDuktape_CreateReadonlyProperty_int(ctx, "HECI_VERSION", (int)0x00); - ILibDuktape_CreateReadonlyProperty_int(ctx, "CLIENT_CONNECT", (int)0x01); -#endif - - ILibDuktape_CreateReadonlyProperty(ctx, "IOCTL"); - duk_push_object(ctx); - duk_peval_string(ctx, "Buffer.from('DBA4336776047B4EB3AFBCFC29BEE7A7', 'hex');"); - ILibDuktape_CreateReadonlyProperty(ctx, "LME"); - duk_peval_string(ctx, "Buffer.from('2800F812B7B42D4BACA846E0FF65814C', 'hex');"); - ILibDuktape_CreateReadonlyProperty(ctx, "AMT"); - ILibDuktape_CreateReadonlyProperty(ctx, "GUIDS"); - -} // KLOCKWORK: We are not losing reference to created Event... It is freed in the object finalizer 'ILibDuktape_HECI_Finalizer' -void ILibDuktape_HECI_Init(duk_context *ctx) -{ - ILibDuktape_ModSearch_AddHandler(ctx, "heci", ILibDuktape_HECI_Push); -} - -#endif - diff --git a/microscript/ILibDuktape_HECI.h b/microscript/ILibDuktape_HECI.h deleted file mode 100644 index 9a361dc..0000000 --- a/microscript/ILibDuktape_HECI.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright 2006 - 2018 Intel Corporation - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#ifndef __DUKTAPEHECI__ -#define __DUKTAPEHECI__ - -#include "duktape.h" - -void ILibDuktape_HECI_Init(duk_context *ctx); - - -#endif diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index e2ff4f1..e424e80 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -2269,6 +2269,17 @@ void ILibDuktape_Polyfills_JS_Init(duk_context *ctx) duk_pcall_method(ctx, 2); duk_pop(ctx); free(_identifiers); +#ifndef _NOHECI + char *_heci = ILibMemory_Allocate(57652, 0, NULL, NULL); + memcpy_s(_heci + 0, 32944, "LyoNCkNvcHlyaWdodCAyMDIwIEludGVsIENvcnBvcmF0aW9uDQoNCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOw0KeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLg0KWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0DQoNCiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjANCg0KVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQ0KZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywNCldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLg0KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZA0KbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuDQoqLw0KDQp2YXIgR00gPSBudWxsOw0KdmFyIHNldHVwID0gbnVsbDsNCnZhciBrZXJuZWwzMiA9IG51bGw7DQp2YXIgZHVwbGV4ID0gcmVxdWlyZSgnc3RyZWFtJykuRHVwbGV4Ow0KDQoNCmlmIChwcm9jZXNzLnBsYXRmb3JtID09ICd3aW4zMicpDQp7DQogICAgR00gPSByZXF1aXJlKCdfR2VuZXJpY01hcnNoYWwnKTsNCiAgICBzZXR1cCA9IEdNLkNyZWF0ZU5hdGl2ZVByb3h5KCdTZXR1cEFQSS5kbGwnKTsNCiAgICBzZXR1cC5DcmVhdGVNZXRob2QoJ1NldHVwRGlHZXRDbGFzc0RldnNBJyk7DQogICAgc2V0dXAuQ3JlYXRlTWV0aG9kKCdTZXR1cERpRW51bURldmljZUludGVyZmFjZXMnKTsNCiAgICBzZXR1cC5DcmVhdGVNZXRob2QoJ1NldHVwRGlHZXREZXZpY2VJbnRlcmZhY2VEZXRhaWxBJyk7DQogICAgc2V0dXAuQ3JlYXRlTWV0aG9kKCdTZXR1cERpRGVzdHJveURldmljZUluZm9MaXN0Jyk7DQoNCiAgICBrZXJuZWwzMiA9IEdNLkNyZWF0ZU5hdGl2ZVByb3h5KCdLZXJuZWwzMi5kbGwnKTsNCiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0Nsb3NlSGFuZGxlJyk7DQogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdDcmVhdGVFdmVudEEnKTsNCiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0NyZWF0ZUZpbGVBJyk7DQogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdEZXZpY2VJb0NvbnRyb2wnKTsNCiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ0dldE92ZXJsYXBwZWRSZXN1bHQnKTsNCiAgICBrZXJuZWwzMi5DcmVhdGVNZXRob2QoJ1JlYWRGaWxlJyk7DQogICAga2VybmVsMzIuQ3JlYXRlTWV0aG9kKCdXcml0ZUZpbGUnKTsNCn0NCg0KdmFyIERJR0NGX0RFRkFVTFQgICAgICAgICAgICAgICA9IDB4MDAwMDAwMDE7ICANCnZhciBESUdDRl9QUkVTRU5UICAgICAgICAgICAgICAgPSAweDAwMDAwMDAyOw0KdmFyIERJR0NGX0FMTENMQVNTRVMgICAgICAgICAgICA9IDB4MDAwMDAwMDQ7DQp2YXIgRElHQ0ZfUFJPRklMRSAgICAgICAgICAgICAgID0gMHgwMDAwMDAwODsNCnZhciBESUdDRl9ERVZJQ0VJTlRFUkZBQ0UgICAgICAgPSAweDAwMDAwMDEwOw0KdmFyIEVSUk9SX0lOU1VGRklDSUVOVF9CVUZGRVIgICA9IDEyMjsgICAgDQp2YXIgR0VORVJJQ19SRUFEICAgICAgICAgICAgICAgID0gMHg4MDAwMDAwMDsNCnZhciBHRU5FUklDX1dSSVRFICAgICAgICAgICAgICAgPSAweDQwMDAwMDAwOw0KdmFyIEZJTEVfU0hBUkVfUkVBRCAgICAgICAgICAgICA9IDB4MDAwMDAwMDE7ICANCnZhciBGSUxFX1NIQVJFX1dSSVRFICAgICAgICAgICAgPSAweDAwMDAwMDAyOyAgDQp2YXIgT1BFTl9FWElTVElORyAgICAgICAgICAgICAgID0gMzsNCnZhciBGSUxFX0ZMQUdfT1ZFUkxBUFBFRCAgICAgICAgPSAweDQwMDAwMDAwOw0KdmFyIEVSUk9SX0lPX1BFTkRJTkcgICAgICAgICAgICA9IDk5NzsNCg0KZnVuY3Rpb24gaGVjaV9jcmVhdGUoKQ0Kew0KICAgIHZhciByZXQgPSBuZXcgZHVwbGV4KA0KICAgIHsNCiAgICAgICAgJ3dyaXRlJzogZnVuY3Rpb24gKGNodW5rLCBmbHVzaCkNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKGNodW5rLmxlbmd0aCA+IHRoaXMuTWF4QnVmZmVyU2l6ZSkgeyB0aHJvdyAoJ0J1ZmZlciB0b28gbGFyZ2UnKTsgfQ0KICAgICAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ3dpbjMyJykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBpZiAodGhpcy5fd3JpdGVvdmVybGFwcGVkID09IG51bGwpIHsgdGhyb3cgKCdOb3QgQ29ubmVjdGVkJyk7IH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIHRoaXMuX3BlbmRpbmdXcml0ZXMudW5zaGlmdCh7IGJ1ZmZlcjogY2h1bmssIGZsdXNoOiBmbHVzaCB9KTsNCg0KICAgICAgICAgICAgaWYgKHRoaXMuX3BlbmRpbmdXcml0ZXMubGVuZ3RoID09IDEpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgLy8gS2lja3N0YXJ0IHRoZSB3cml0ZQ0KICAgICAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3NXcml0ZSgpOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PSAnd2luMzInKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHJldHVybiAoZmFsc2UpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9LA0KICAgICAgICAnZmluYWwnOiBmdW5jdGlvbiAoZmx1c2gpDQogICAgICAgIHsNCiAgICAgICAgICAgIGZsdXNoKCk7DQogICAgICAgIH0sDQogICAgICAgICdyZWFkJzogZnVuY3Rpb24oc2l6ZSkNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKCF0aGlzLl9yZWFkYnVmZmVyKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRidWZmZXIgPSBwcm9jZXNzLnBsYXRmb3JtID09ICd3aW4zMicgPyBHTS5DcmVhdGVWYXJpYWJsZSh0aGlzLk1heEJ1ZmZlclNpemUpIDogQnVmZmVyLmFsbG9jKHRoaXMuTWF4QnVmZmVyU2l6ZSk7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmIChwcm9jZXNzLnBsYXRmb3JtID09ICdsaW51eCcpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgdGhpcy5fcHJvY2Vzc1JlYWQoKTsNCiAgICAgICAgICAgICAgICByZXR1cm47DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIHZhciByZXN1bHQgPSBrZXJuZWwzMi5SZWFkRmlsZSh0aGlzLl9kZXNjcmlwdG9yLCB0aGlzLl9yZWFkYnVmZmVyLCB0aGlzLl9yZWFkYnVmZmVyLl9zaXplLCAwLCB0aGlzLl9yZWFkb3ZlcmxhcHBlZCk7DQogICAgICAgICAgICBpZihyZXN1bHQuVmFsICE9IDAgfHwgcmVzdWx0Ll9MYXN0RXJyb3IgPT0gRVJST1JfSU9fUEVORElORykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBpZighdGhpcy5fckRlc2NyaXB0b3JFdmVudCkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuX3JEZXNjcmlwdG9yRXZlbnQgPSByZXF1aXJlKCdEZXNjcmlwdG9yRXZlbnRzJykuYWRkRGVzY3JpcHRvcih0aGlzLl9yZWFkb3ZlcmxhcHBlZC5oRXZlbnQsIHsgbWV0YWRhdGE6ICdoZWNpLnNlc3Npb24gW3JlYWRdJyB9KTsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fckRlc2NyaXB0b3JFdmVudC5zZXNzaW9uID0gdGhpczsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fckRlc2NyaXB0b3JFdmVudC5vbignc2lnbmFsZWQnLCBmdW5jdGlvbiAoc3RhdHVzKQ0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICBpZihzdGF0dXMgIT0gJ05PTkUnKQ0KICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzMoJz4+PiBoZWNpLnNlc3Npb24gc2lnbmFsZWQgd2l0aCBzdGF0dXM6ICcgKyBzdGF0dXMpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5wdXNoKG51bGwpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBieXRlc1JlYWQgPSBHTS5DcmVhdGVWYXJpYWJsZSg0KTsNCiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQ7DQogICAgICAgICAgICAgICAgICAgICAgICBpZigocmVzdWx0PWtlcm5lbDMyLkdldE92ZXJsYXBwZWRSZXN1bHQodGhpcy5zZXNzaW9uLl9kZXNjcmlwdG9yLCB0aGlzLnNlc3Npb24uX3JlYWRvdmVybGFwcGVkLCBieXRlc1JlYWQsIDApKS5WYWwgIT0gMCkNCiAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYnVmZmVyID0gdGhpcy5zZXNzaW9uLl9yZWFkYnVmZmVyLnRvQnVmZmVyKCkuc2xpY2UoMCwgYnl0ZXNSZWFkLnRvQnVmZmVyKCkucmVhZFVJbnQzMkxFKCkpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzMoYnVmZmVyLmxlbmd0aCArICcgYnl0ZXMgUkVBRCcpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHB1c2hSZXN1bHQgPSB0aGlzLnNlc3Npb24ucHVzaChidWZmZXIpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlc3Npb24uX29wdGlvbnMubm9QaXBlbGluZSAhPSAwICYmIHRoaXMuc2Vzc2lvbi5fcGVuZGluZ1dyaXRlcy5sZW5ndGg+MCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVubG9jayBhIHdyaXRlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzIoJ3BlbmRpbmdXcml0ZUNvdW50OiAnICsgdGhpcy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLmxlbmd0aCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpdGVtID0gdGhpcy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLnBvcCgpOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlc3Npb24uX3BlbmRpbmdXcml0ZXMubGVuZ3RoID4gMCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLl9wcm9jZXNzV3JpdGUoKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzIoJ1dyaXRlL0ZsdXNoJyk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLmZsdXNoKCk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHVzaFJlc3VsdCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGNhbiByZWFkIG1vcmUsIGJlY2F1c2UgZGF0YSBpcyBzdGlsbCBmbG93aW5nDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBrZXJuZWwzMi5SZWFkRmlsZSh0aGlzLnNlc3Npb24uX2Rlc2NyaXB0b3IsIHRoaXMuc2Vzc2lvbi5fcmVhZGJ1ZmZlciwgdGhpcy5zZXNzaW9uLl9yZWFkYnVmZmVyLl9zaXplLCAwLCB0aGlzLnNlc3Npb24uX3JlYWRvdmVybGFwcGVkKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVzdWx0LlZhbCAhPSAwIHx8IHJlc3VsdC5fTGFzdEVycm9yID09IEVSUk9SX0lPX1BFTkRJTkcpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAodHJ1ZSk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8xKCdTb21ldHlwZSBvZiBlcnJvcjogJyArIHJlc3VsdC5fTGFzdEVycm9yKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5wdXNoKG51bGwpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzEoJ1JFQURfT1ZFUkxBUFBFRF9FUlJPUjogJyArIHJlc3VsdC5fTGFzdEVycm9yICsgJyBvbiAnICsgdGhpcy5zZXNzaW9uLl9oYXNoQ29kZSgpKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnU29tZSBPdGhlciBFcnJvcjogJyArIHJlc3VsdC5fTGFzdEVycm9yKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH0pOw0KICAgIHJldC5fT2JqZWN0SUQgPSAnaGVjaS5zZXNzaW9uJzsNCiAgICByZXQuYnVmZmVyTW9kZSA9IDE7DQogICAgcmV0Ll9pb2N0bHMgPSBbXTsNCiAgICByZXQuX3BlbmRpbmdXcml0ZXMgPSBbXTsNCiAgICByZXQuaGVjaVBhcmVudCA9IHRoaXM7DQoNCiAgICByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXIuY2FsbChyZXQsIHRydWUpDQogICAgICAgIC5jcmVhdGVFdmVudCgnY29ubmVjdCcpDQogICAgICAgIC5jcmVhdGVFdmVudCgnZXJyb3InKQ0KICAgICAgICAuYWRkTWV0aG9kKCdjb25uZWN0JywgZnVuY3Rpb24gX2Nvbm5lY3QoZ3VpZCwgb3B0aW9ucykNCiAgICAgICAgew0KICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnY29ubmVjdCgpJyk7DQogICAgICAgICAgICB0aGlzLmRvSW9jdGwodGhpcy5oZWNpUGFyZW50LklPQ1RMLkNMSUVOVF9DT05ORUNULCBndWlkLCBCdWZmZXIuYWxsb2MoMTYpLCBmdW5jdGlvbiBfb25jb25uZWN0KHN0YXR1cywgYnVmZmVyLCBvcHQpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgaWYoc3RhdHVzIT0wKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnSEVDSSBDb25uZWN0aW9uIEVycm9yIFsnICsgdGhpcy5MYXN0RXJyb3IgKyAnXScpOw0KICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXQoJ2Vycm9yJywgJ0hFQ0kgQ29ubmVjdGlvbiBFcnJvciBbJyArIHRoaXMuTGFzdEVycm9yICsgJ10nKTsNCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBpZihidWZmZXIubGVuZ3RoIDw9NCkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIC8vIEludmFsaWQgUmVzcG9uc2UNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0KCdlcnJvcicsICdIRUNJIENvbm5lY3Rpb24gRXJyb3IgW0lOVkFMSUQgUkVTUE9OU0VdJyk7DQogICAgICAgICAgICAgICAgICAgIHJldHVybjsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICJNYXhCdWZmZXJTaXplIiwgeyB2YWx1ZTogYnVmZmVyLnJlYWRVSW50MzJMRSgpIH0pOw0KICAgICAgICAgICAgICAgIHRoaXMuX29wdGlvbnMgPSBvcHQ7DQoNCiAgICAgICAgICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PSAnd2luMzInKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZG92ZXJsYXBwZWQgPSBHTS5DcmVhdGVWYXJpYWJsZShHTS5Qb2ludGVyU2l6ZSA9PSA4ID8gMzIgOiAyMCk7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuX3dyaXRlb3ZlcmxhcHBlZCA9IEdNLkNyZWF0ZVZhcmlhYmxlKEdNLlBvaW50ZXJTaXplID09IDggPyAzMiA6IDIwKTsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZG92ZXJsYXBwZWQuaEV2ZW50ID0ga2VybmVsMzIuQ3JlYXRlRXZlbnRBKDAsIDEsIDAsIDApOw0KICAgICAgICAgICAgICAgICAgICB0aGlzLl93cml0ZW92ZXJsYXBwZWQuaEV2ZW50ID0ga2VybmVsMzIuQ3JlYXRlRXZlbnRBKDAsIDEsIDAsIDApOw0KICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkb3ZlcmxhcHBlZC5oRXZlbnQucG9pbnRlckJ1ZmZlcigpLmNvcHkodGhpcy5fcmVhZG92ZXJsYXBwZWQuRGVyZWYoR00uUG9pbnRlclNpemUgPT0gOCA/IDI0IDogMTYsIEdNLlBvaW50ZXJTaXplKS50b0J1ZmZlcigpKTsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fd3JpdGVvdmVybGFwcGVkLmhFdmVudC5wb2ludGVyQnVmZmVyKCkuY29weSh0aGlzLl93cml0ZW92ZXJsYXBwZWQuRGVyZWYoR00uUG9pbnRlclNpemUgPT0gOCA/IDI0IDogMTYsIEdNLlBvaW50ZXJTaXplKS50b0J1ZmZlcigpKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnQ29ubmVjdGVkLCBidWZmZXIgc2l6ZTogJyArIHRoaXMuTWF4QnVmZmVyU2l6ZSk7DQogICAgICAgICAgICAgICAgdGhpcy5fcmVhZCh0aGlzLk1heEJ1ZmZlclNpemUpOw0KICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnY29ubmVjdCcpOw0KICAgICAgICAgICAgfSwgb3B0aW9ucyk7DQogICAgICAgIH0pDQogICAgICAgIC5hZGRNZXRob2QoJ2Rlc2NyaXB0b3JQYXRoJywgZnVuY3Rpb24gX2Rlc2NyaXB0b3JQYXRoKCkNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ2xpbnV4JykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBpZiAocmVxdWlyZSgnZnMnKS5leGlzdHNTeW5jKCcvZGV2L21laScpKSB7IHJldHVybiAoJy9kZXYvbWVpJyk7IH0NCiAgICAgICAgICAgICAgICBpZiAocmVxdWlyZSgnZnMnKS5leGlzdHNTeW5jKCcvZGV2L21laTAnKSkgeyByZXR1cm4gKCcvZGV2L21laTAnKTsgfQ0KICAgICAgICAgICAgICAgIHRocm93ICgnSEVDSSBub3Qgc3VwcG9ydGVkJyk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSAhPSAnd2luMzInKSB7IHRocm93ICgnSEVDSSBub3Qgc3VwcG9ydGVkJyk7IH0NCg0KICAgICAgICAgICAgdmFyIHJlc3VsdDsNCiAgICAgICAgICAgIHZhciBpaTsNCiAgICAgICAgICAgIHZhciBkZXZpY2VEZXRhaWw7DQogICAgICAgICAgICB2YXIgYnVmZmVyU2l6ZSA9IEdNLkNyZWF0ZVZhcmlhYmxlKDQpOyAgLy8gRFdPUkQNCiAgICAgICAgICAgIHZhciBoZWNpZ3VpZCA9IEdNLkNyZWF0ZVZhcmlhYmxlKHRoaXMuaGVjaVBhcmVudC5HVUlEUy5IRUNJKTsNCiAgICAgICAgICAgIHZhciBkZXZpY2VJbmZvID0gc2V0dXAuU2V0dXBEaUdldENsYXNzRGV2c0EoaGVjaWd1aWQsIDAsIDAsIERJR0NGX1BSRVNFTlQgfCBESUdDRl9ERVZJQ0VJTlRFUkZBQ0UpOw0KICAgICAgICAgICAgaWYgKGRldmljZUluZm8uVmFsID09IC0xKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzEoJy4uLiBVbmFibGUgdG8gYWNxdWlyZSBbZGV2aWNlSW5mb10nKTsNCiAgICAgICAgICAgICAgICB0aHJvdyAoJ3VuYWJsZSB0byBhY3F1aXJlIFtkZXZpY2VJbmZvXScpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnLi4uIGFjcXVpcmVkIFtkZXZpY2VJbmZvXScpOw0KDQoNCiAgICAgICAgICAgIHZhciBpbnRlcmZhY2VEYXRhID0gR00uQ3JlYXRlVmFyaWFibGUoR00uUG9pbnRlclNpemUgPT0gOCA/IDMyIDogMjgpOw0KICAgICAgICAgICAgaW50ZXJmYWNlRGF0YS50b0J1ZmZlcigpLndyaXRlVUludDMyTEUoaW50ZXJmYWNlRGF0YS5fc2l6ZSwgMCk7DQoNCiAgICAgICAgICAgIGZvciAoaWkgPSAwOyBzZXR1cC5TZXR1cERpRW51bURldmljZUludGVyZmFjZXMoZGV2aWNlSW5mbywgMCwgaGVjaWd1aWQsIGlpLCBpbnRlcmZhY2VEYXRhKS5WYWwgIT0gMDsgKytpaSkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAvLyBGb3VuZCBvdXIgZGV2aWNlIGluc3RhbmNlDQogICAgICAgICAgICAgICAgaWYgKChyZXN1bHQgPSBzZXR1cC5TZXR1cERpR2V0RGV2aWNlSW50ZXJmYWNlRGV0YWlsQShkZXZpY2VJbmZvLCBpbnRlcmZhY2VEYXRhLCAwLCAwLCBidWZmZXJTaXplLCAwKSkuVmFsID09IDApDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0Ll9MYXN0RXJyb3IgIT0gRVJST1JfSU5TVUZGSUNJRU5UX0JVRkZFUikNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7DQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAvLyBBbGxvY2F0ZSBhIGJpZyBlbm91Z2ggYnVmZmVyIHRvIGdldCBkZXRhaWwgZGF0YQ0KICAgICAgICAgICAgICAgIGRldmljZURldGFpbCA9IEdNLkNyZWF0ZVZhcmlhYmxlKGJ1ZmZlclNpemUudG9CdWZmZXIoKS5yZWFkVUludDMyTEUoKSk7DQogICAgICAgICAgICAgICAgZGV2aWNlRGV0YWlsLnRvQnVmZmVyKCkud3JpdGVVSW50MzJMRShHTS5Qb2ludGVyU2l6ZSA9PSA4ID8gOCA6IDUsIDApOw0KDQogICAgICAgICAgICAgICAgLy8gVHJ5IGFnYWluIHRvIGdldCB0aGUgZGV2aWNlIGludGVyZmFjZSBkZXRhaWwgaW5mbw0KICAgICAgICAgICAgICAgIGlmIChzZXR1cC5TZXR1cERpR2V0RGV2aWNlSW50ZXJmYWNlRGV0YWlsQShkZXZpY2VJbmZvLCBpbnRlcmZhY2VEYXRhLCBkZXZpY2VEZXRhaWwsIGJ1ZmZlclNpemUsIDAsIDApLlZhbCA9PSAwKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgZGV2aWNlRGV0YWlsID0gTlVMTDsNCiAgICAgICAgICAgICAgICAgICAgY29udGludWU7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgc2V0dXAuU2V0dXBEaURlc3Ryb3lEZXZpY2VJbmZvTGlzdChkZXZpY2VJbmZvKTsNCiAgICAgICAgICAgIGlmIChkZXZpY2VEZXRhaWwgPT0gbnVsbCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8xKCcuLi4gZmFpbGVkIHRvIGFjcXVpcmUgW2RldmljZURldGFpbF0nKTsNCiAgICAgICAgICAgICAgICB0aHJvdyAoJ3VuYWJsZSB0byBhY3F1aXJlIFtkZXZpY2VEZXRhaWxdJyk7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIHZhciBkZXZQYXRoID0gZGV2aWNlRGV0YWlsLkRlcmVmKDQsIEdNLlBvaW50ZXJTaXplKTsNCiAgICAgICAgICAgIHJldHVybiAoZGV2UGF0aC5TdHJpbmcpOw0KICAgICAgICB9KQ0KICAgICAgICAuYWRkTWV0aG9kKCdjcmVhdGVEZXNjcmlwdG9yJywgZnVuY3Rpb24gX2NyZWF0ZURlc2NyaXB0b3IocGF0aCkNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ2xpbnV4JykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICByZXR1cm4gKHJlcXVpcmUoJ2ZzJykub3BlblN5bmMocGF0aCwgcmVxdWlyZSgnZnMnKS5jb25zdGFudHMuT19SRFdSIHwgcmVxdWlyZSgnZnMnKS5jb25zdGFudHMuT19OT05CTE9DSykpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gIT0gJ3dpbjMyJykgeyB0aHJvdyAoJ0hFQ0kgbm90IHN1cHBvcnRlZCcpOyB9DQoNCiAgICAgICAgICAgIHZhciBkZXZQYXRoID0gR00uQ3JlYXRlVmFyaWFibGUo", 16000); + memcpy_s(_heci + 16000, 16944, "cGF0aCk7DQogICAgICAgICAgICB2YXIgcmV0ID0ga2VybmVsMzIuQ3JlYXRlRmlsZUEoZGV2UGF0aCwgR0VORVJJQ19SRUFEIHwgR0VORVJJQ19XUklURSwgRklMRV9TSEFSRV9SRUFEIHwgRklMRV9TSEFSRV9XUklURSwgMCwgT1BFTl9FWElTVElORywgRklMRV9GTEFHX09WRVJMQVBQRUQsIDApOw0KICAgICAgICAgICAgaWYgKHJldC5WYWwgPT0gLTEpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnLi4uIGZhaWxlZCB0byBhY3F1aXJlIFtkZXNjcmlwdG9yXScpOw0KICAgICAgICAgICAgICAgIHRocm93ICgnZmFpbGVkIHRvIGFjcXVpcmUgZGVzY3JpcHRvcicpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnLi4uIGFjcXVpcmVkIFtERVNDUklQVE9SXScpOw0KICAgICAgICAgICAgcmV0dXJuIChyZXQpOw0KICAgICAgICB9KTsNCiAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PSAnd2luMzInKQ0KICAgIHsNCiAgICAgICAgcmV0Ll9vdmVybGFwcGVkID0gR00uQ3JlYXRlVmFyaWFibGUoR00uUG9pbnRlclNpemUgPT0gOCA/IDMyIDogMjApOw0KICAgICAgICByZXQuX292ZXJsYXBwZWQuaEV2ZW50ID0ga2VybmVsMzIuQ3JlYXRlRXZlbnRBKDAsIDEsIDAsIDApOw0KDQogICAgICAgIHZhciBvdmVybGFwcGVkX2V2ZW50cHRyID0gcmV0Ll9vdmVybGFwcGVkLkRlcmVmKEdNLlBvaW50ZXJTaXplID09IDggPyAyNCA6IDE2LCBHTS5Qb2ludGVyU2l6ZSkudG9CdWZmZXIoKTsNCiAgICAgICAgcmV0Ll9vdmVybGFwcGVkLmhFdmVudC5wb2ludGVyQnVmZmVyKCkuY29weShvdmVybGFwcGVkX2V2ZW50cHRyKTsNCiAgICB9DQogICAgcmV0LmRpc2Nvbm5lY3QgPSBmdW5jdGlvbiBkaXNjb25uZWN0KCkNCiAgICB7DQogICAgICAgIC8vIENsZWFuIHVwIGFsbCBIYW5kbGVzIGFuZCBEZXNjcmlwdG9ycw0KICAgICAgICBjb25zb2xlLmluZm8xKCdESVNDT05ORUNUIG9uICcgKyB0aGlzLl9oYXNoQ29kZSgpKTsNCiAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ2xpbnV4JykNCiAgICAgICAgew0KICAgICAgICAgICAgaWYodGhpcy5fZGVzY3JpcHRvciAhPSBudWxsKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHJlcXVpcmUoJ0Rlc2NyaXB0b3JFdmVudHMnKS5yZW1vdmVEZXNjcmlwdG9yKHRoaXMuX2Rlc2NyaXB0b3IpOw0KICAgICAgICAgICAgICAgIHJlcXVpcmUoJ2ZzJykuY2xvc2VTeW5jKHRoaXMuX2Rlc2NyaXB0b3IpOw0KICAgICAgICAgICAgICAgIHRoaXMuX2Rlc2NyaXB0b3IgPSBudWxsOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ3dpbjMyJykNCiAgICAgICAgew0KICAgICAgICAgICAgLy8NCiAgICAgICAgICAgIC8vIGRvSW9jdGwoKSANCiAgICAgICAgICAgIC8vDQogICAgICAgICAgICBpZiAodGhpcy5fZGVzY3JpcHRvckV2ZW50KQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vdmVybGFwcGVkKSB7IHJlcXVpcmUoJ0Rlc2NyaXB0b3JFdmVudHMnKS5yZW1vdmVEZXNjcmlwdG9yKHRoaXMuX292ZXJsYXBwZWQuaEV2ZW50KTsgfQ0KICAgICAgICAgICAgICAgIHRoaXMuX2Rlc2NyaXB0b3JFdmVudCA9IG51bGw7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBpZiAodGhpcy5fb3ZlcmxhcHBlZCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBrZXJuZWwzMi5DbG9zZUhhbmRsZSh0aGlzLl9vdmVybGFwcGVkLmhFdmVudCk7DQogICAgICAgICAgICAgICAgdGhpcy5fb3ZlcmxhcHBlZCA9IG51bGw7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIC8vDQogICAgICAgICAgICAvLyBSZWFkDQogICAgICAgICAgICAvLw0KICAgICAgICAgICAgaWYgKHRoaXMuX3JEZXNjcmlwdG9yRXZlbnQpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgaWYgKHRoaXMuX3JlYWRvdmVybGFwcGVkKSB7IHJlcXVpcmUoJ0Rlc2NyaXB0b3JFdmVudHMnKS5yZW1vdmVEZXNjcmlwdG9yKHRoaXMuX3JlYWRvdmVybGFwcGVkLmhFdmVudCk7IH0NCiAgICAgICAgICAgICAgICB0aGlzLl9yRGVzY3JpcHRvckV2ZW50ID0gbnVsbDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGlmICh0aGlzLl9yZWFkb3ZlcmxhcHBlZCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBrZXJuZWwzMi5DbG9zZUhhbmRsZSh0aGlzLl9yZWFkb3ZlcmxhcHBlZC5oRXZlbnQpOw0KICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRvdmVybGFwcGVkID0gbnVsbDsNCiAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgLy8NCiAgICAgICAgICAgIC8vIFdyaXRlDQogICAgICAgICAgICAvLw0KICAgICAgICAgICAgaWYgKHRoaXMuX3dEZXNjcmlwdG9yRXZlbnQpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgaWYgKHRoaXMuX3dyaXRlb3ZlcmxhcHBlZCkgeyByZXF1aXJlKCdEZXNjcmlwdG9yRXZlbnRzJykucmVtb3ZlRGVzY3JpcHRvcih0aGlzLl93cml0ZW92ZXJsYXBwZWQuaEV2ZW50KTsgfQ0KICAgICAgICAgICAgICAgIHRoaXMuX3dEZXNjcmlwdG9yRXZlbnQgPSBudWxsOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaWYgKHRoaXMuX3dyaXRlb3ZlcmxhcHBlZCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBrZXJuZWwzMi5DbG9zZUhhbmRsZSh0aGlzLl93cml0ZW92ZXJsYXBwZWQuaEV2ZW50KTsNCiAgICAgICAgICAgICAgICB0aGlzLl93cml0ZW92ZXJsYXBwZWQgPSBudWxsOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAvLw0KICAgICAgICAgICAgLy8gSEVDSQ0KICAgICAgICAgICAgLy8NCiAgICAgICAgICAgIGlmICh0aGlzLl9kZXNjcmlwdG9yKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIGtlcm5lbDMyLkNsb3NlSGFuZGxlKHRoaXMuX2Rlc2NyaXB0b3IpOw0KICAgICAgICAgICAgICAgIHRoaXMuX2Rlc2NyaXB0b3IgPSBudWxsOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfTsNCiAgICByZXQuZG9Jb2N0bCA9IGZ1bmN0aW9uIGRvSW9jdGwoY29kZSwgaW5wdXRCdWZmZXIsIG91dHB1dEJ1ZmZlciwgY2FsbGJhY2spDQogICAgew0KICAgICAgICBpZiAodHlwZW9mIChjYWxsYmFjaykgIT0gJ2Z1bmN0aW9uJykgeyB0aHJvdyAoJ0NhbGxiYWNrIG5vdCBzcGVjaWZpZWQnKTsgfQ0KDQogICAgICAgIHZhciBpOw0KICAgICAgICB2YXIgcGFybXMgPSBbXTsNCiAgICAgICAgZm9yIChpID0gNDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7ICsraSkNCiAgICAgICAgew0KICAgICAgICAgICAgcGFybXMucHVzaChhcmd1bWVudHNbaV0pOw0KICAgICAgICB9DQoNCg0KICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PSAnbGludXgnKQ0KICAgICAgICB7DQogICAgICAgICAgICBpZiAob3V0cHV0QnVmZmVyLmxlbmd0aCA8IGlucHV0QnVmZmVyLmxlbmd0aCkgeyB0aHJvdyAoJ291dHB1dCBidWZmZXIgaXMgdG9vIHNtYWxsJyk7IH0NCiAgICAgICAgICAgIG91dHB1dEJ1ZmZlci5maWxsKDApOw0KICAgICAgICAgICAgaW5wdXRCdWZmZXIuY29weShvdXRwdXRCdWZmZXIpOw0KICAgICAgICAgICAgaWYgKHRoaXMuX2Rlc2NyaXB0b3IgPT0gbnVsbCkgeyB0aGlzLl9kZXNjcmlwdG9yID0gdGhpcy5jcmVhdGVEZXNjcmlwdG9yKHRoaXMuZGVzY3JpcHRvclBhdGgoKSk7IH0NCiAgICAgICAgICAgIHZhciByZXQgPSByZXF1aXJlKCdpb2N0bCcpKHRoaXMuX2Rlc2NyaXB0b3IsIGNvZGUsIG91dHB1dEJ1ZmZlcik7DQogICAgICAgICAgICBwYXJtcy51bnNoaWZ0KG91dHB1dEJ1ZmZlcik7DQogICAgICAgICAgICBwYXJtcy51bnNoaWZ0KHJldCk7DQogICAgICAgICAgICBjYWxsYmFjay5hcHBseSh0aGlzLCBwYXJtcyk7DQogICAgICAgICAgICByZXR1cm47DQogICAgICAgIH0NCg0KICAgICAgICB0aGlzLl9pb2N0bHMudW5zaGlmdCh7IGNvZGU6IGNvZGUsIGlucHV0OiBpbnB1dEJ1ZmZlciwgb3V0cHV0OiBvdXRwdXRCdWZmZXIsIGNhbGxiYWNrOiBjYWxsYmFjaywgcGFybXM6IHBhcm1zIH0pOw0KICAgICAgICBpZih0aGlzLl9pb2N0bHMubGVuZ3RoID09IDEpDQogICAgICAgIHsNCiAgICAgICAgICAgIC8vIEZpcnN0IElPQ1RMLCBzbyB3ZSBuZWVkIHRvIHNlbmQgdGhlIGZpcnN0IG9uZQ0KICAgICAgICAgICAgdGhpcy5fc2VuZCh0aGlzLl9pb2N0bHMucGVlaygpKTsNCiAgICAgICAgfQ0KICAgIH07DQoNCiAgICByZXQuX3NlbmQgPSBmdW5jdGlvbiBfc2VuZChvcHRpb25zKQ0KICAgIHsNCiAgICAgICAgaWYodGhpcy5fZGVzY3JpcHRvciA9PSBudWxsKSANCiAgICAgICAgew0KICAgICAgICAgICAgdGhpcy5fZGVzY3JpcHRvciA9IHRoaXMuY3JlYXRlRGVzY3JpcHRvcih0aGlzLmRlc2NyaXB0b3JQYXRoKCkpOyANCiAgICAgICAgICAgIHRoaXMuX2Rlc2NyaXB0b3JFdmVudCA9IHJlcXVpcmUoJ0Rlc2NyaXB0b3JFdmVudHMnKS5hZGREZXNjcmlwdG9yKHRoaXMuX292ZXJsYXBwZWQuaEV2ZW50LCB7bWV0YWRhdGE6ICdoZWNpJ30pOw0KICAgICAgICAgICAgdGhpcy5fZGVzY3JpcHRvckV2ZW50LnNlc3Npb24gPSB0aGlzOw0KICAgICAgICAgICAgdGhpcy5fZGVzY3JpcHRvckV2ZW50Lm9uKCdzaWduYWxlZCcsIGZ1bmN0aW9uKHN0YXR1cykNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMuc2Vzc2lvbi5faW9jdGxzLnBvcCgpOw0KICAgICAgICAgICAgICAgIGlmKHN0YXR1cyA9PSAnTk9ORScpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICB2YXIgYnl0ZXNSZWFkID0gR00uQ3JlYXRlVmFyaWFibGUoNCk7DQogICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBrZXJuZWwzMi5HZXRPdmVybGFwcGVkUmVzdWx0KHRoaXMuc2Vzc2lvbi5fZGVzY3JpcHRvciwgdGhpcy5zZXNzaW9uLl9vdmVybGFwcGVkLCBieXRlc1JlYWQsIDApOw0KICAgICAgICAgICAgICAgICAgICBpZihyZXN1bHQuVmFsICE9IDApDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvdXQgPSBkYXRhLm91dHB1dDsNCiAgICAgICAgICAgICAgICAgICAgICAgIHRyeQ0KICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dC5zbGljZSgwLGJ5dGVzUmVhZC50b0J1ZmZlcigpLnJlYWRVSW50MzJMRSgpKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIGNhdGNoKGUpDQogICAgICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0ID0gbnVsbDsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEucGFybXMudW5zaGlmdChvdXQpOw0KICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5wYXJtcy51bnNoaWZ0KDApOw0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLkxhc3RFcnJvciA9ICdOT05FJzsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEucGFybXMudW5zaGlmdChudWxsKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEucGFybXMudW5zaGlmdCgxKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5MYXN0RXJyb3IgPSAnT1ZFUkxBUFBFRF9FUlJPUjogJyArIHJlc3VsdC5fTGFzdEVycm9yOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIGRhdGEucGFybXMudW5zaGlmdChudWxsKTsNCiAgICAgICAgICAgICAgICAgICAgZGF0YS5wYXJtcy51bnNoaWZ0KDEpOw0KICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uTGFzdEVycm9yID0gc3RhdHVzOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB0cnkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIGRhdGEuY2FsbGJhY2suYXBwbHkodGhpcy5zZXNzaW9uLCBkYXRhLnBhcm1zKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgY2F0Y2godWUpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLmVtaXQoJ3VuY2F1Z2h0RXhjZXB0aW9uJywgdWUpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBpZih0aGlzLnNlc3Npb24uX2lvY3Rscy5sZW5ndGggPiAwKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgLy8gU3RpbGwgbW9yZSBJT0NUTHMgdG8gc2VuZA0KICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uX3NlbmQodGhpcy5zZXNzaW9uLl9pb2N0bHMucGVlaygpKTsNCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICh0cnVlKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9KTsNCiAgICAgICAgfQ0KICAgICAgICBrZXJuZWwzMi5EZXZpY2VJb0NvbnRyb2wodGhpcy5fZGVzY3JpcHRvciwgb3B0aW9ucy5jb2RlLCBHTS5DcmVhdGVWYXJpYWJsZShvcHRpb25zLmlucHV0KSwgb3B0aW9ucy5pbnB1dC5sZW5ndGgsIEdNLkNyZWF0ZVZhcmlhYmxlKG9wdGlvbnMub3V0cHV0KSwgb3B0aW9ucy5vdXRwdXQubGVuZ3RoLCAwLCB0aGlzLl9vdmVybGFwcGVkKTsNCiAgICB9Ow0KICAgIHJldC5fcHJvY2Vzc1dyaXRlID0gZnVuY3Rpb24gX3Byb2Nlc3NXcml0ZSgpDQogICAgew0KICAgICAgICB2YXIgY2h1bmsgPSB0aGlzLl9wZW5kaW5nV3JpdGVzLnBlZWsoKTsNCiAgICAgICAgY29uc29sZS5pbmZvMygnX1dSSVRJTkc6ICcgKyBjaHVuay5idWZmZXIubGVuZ3RoICsgJyBieXRlcycgKyAnIG9uICcgKyB0aGlzLl9oYXNoQ29kZSgpKTsNCg0KICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PSAnd2luMzInKQ0KICAgICAgICB7DQogICAgICAgICAgICB2YXIgcmVzdWx0ID0ga2VybmVsMzIuV3JpdGVGaWxlKHRoaXMuX2Rlc2NyaXB0b3IsIEdNLkNyZWF0ZVZhcmlhYmxlKGNodW5rLmJ1ZmZlciksIGNodW5rLmJ1ZmZlci5sZW5ndGgsIDAsIHRoaXMuX3dyaXRlb3ZlcmxhcHBlZCk7DQogICAgICAgICAgICBpZiAocmVzdWx0LlZhbCAhPSAwIHx8IHJlc3VsdC5fTGFzdEVycm9yID09IEVSUk9SX0lPX1BFTkRJTkcpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgaWYgKCF0aGlzLl93RGVzY3JpcHRvckV2ZW50KQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgdGhpcy5fd0Rlc2NyaXB0b3JFdmVudCA9IHJlcXVpcmUoJ0Rlc2NyaXB0b3JFdmVudHMnKS5hZGREZXNjcmlwdG9yKHRoaXMuX3dyaXRlb3ZlcmxhcHBlZC5oRXZlbnQsIHsgbWV0YWRhdGE6ICdoZWNpLnNlc3Npb24gW3dyaXRlXScgfSk7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuX3dEZXNjcmlwdG9yRXZlbnQuc2Vzc2lvbiA9IHRoaXM7DQogICAgICAgICAgICAgICAgICAgIHRoaXMuX3dEZXNjcmlwdG9yRXZlbnQub24oJ3NpZ25hbGVkJywgdGhpcy5fcHJvY2Vzc1dyaXRlX3NpZ25hbGVkKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMSgnV3JpdGUgRXJyb3I6ICcgKyByZXN1bHQuX0xhc3RFcnJvcik7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICByZXF1aXJlKCdmcycpLndyaXRlKHRoaXMuX2Rlc2NyaXB0b3IsIGNodW5rLmJ1ZmZlciwgdGhpcy5fcHJvY2Vzc1dyaXRlX2xpbnV4X3NpZ25hbGVkLCB7IG1ldGFkYXRhOiAnaGVjaS5zZXNzaW9uJywgc2Vzc2lvbjogdGhpcyB9KTsNCiAgICB9Ow0KICAgIHJldC5fcHJvY2Vzc1dyaXRlX2xpbnV4X3NpZ25hbGVkID0gZnVuY3Rpb24gX3Byb2Nlc3NXcml0ZV9saW51eF9zaWduYWxlZChzdGF0dXMsIGJ5dGVzV3JpdHRlbiwgYnVmZmVyLCBvcHRpb25zKQ0KICAgIHsNCiAgICAgICAgaWYoc3RhdHVzID09IDApDQogICAgICAgIHsNCiAgICAgICAgICAgIGNvbnNvbGUuaW5mbzMoYnl0ZXNXcml0dGVuICsgJyBieXRlcyB3cml0dGVuJyk7DQogICAgICAgICAgICBjb25zb2xlLmluZm8zKCdub1BpcGVsaW5lID0gJyArIG9wdGlvbnMuc2Vzc2lvbi5fb3B0aW9ucy5ub1BpcGVsaW5lLCBvcHRpb25zLnNlc3Npb24uX3BlbmRpbmdXcml0ZXMubGVuZ3RoKTsNCiAgICAgICAgICAgIGlmIChvcHRpb25zLnNlc3Npb24uX29wdGlvbnMubm9QaXBlbGluZSA9PSBudWxsIHx8IG9wdGlvbnMuc2Vzc2lvbi5fb3B0aW9ucy5ub1BpcGVsaW5lID09IGZhbHNlKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHZhciBpdGVtID0gb3B0aW9ucy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLnBvcCgpOw0KICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNlc3Npb24uX3BlbmRpbmdXcml0ZXMubGVuZ3RoID4gMCkNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuc2Vzc2lvbi5fcHJvY2Vzc1dyaXRlKCk7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbzMoJ1dyaXRlL0ZsdXNoJyk7DQogICAgICAgICAgICAgICAgICAgIGl0ZW0uZmx1c2goKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICB9Ow0KICAgIHJldC5fcHJvY2Vzc1dyaXRlX3NpZ25hbGVkID0gZnVuY3Rpb24gX3Byb2Nlc3NXcml0ZV9zaWduYWxlZChzdGF0dXMpDQogICAgew0KICAgICAgICBjb25zb2xlLmluZm8zKCdXcml0ZSBTaWduYWxlZDogJyArIHN0YXR1cyk7DQogICAgICAgIGlmKHN0YXR1cyA9PSAnTk9ORScpDQogICAgICAgIHsNCiAgICAgICAgICAgIC8vIE5vIEVycm9ycw0KICAgICAgICAgICAgdmFyIGJ5dGVzV3JpdHRlbiA9IEdNLkNyZWF0ZVZhcmlhYmxlKDQpOw0KICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGtlcm5lbDMyLkdldE92ZXJsYXBwZWRSZXN1bHQodGhpcy5zZXNzaW9uLl9kZXNjcmlwdG9yLCB0aGlzLnNlc3Npb24uX3dyaXRlb3ZlcmxhcHBlZCwgYnl0ZXNXcml0dGVuLCAwKTsNCiAgICAgICAgICAgIGlmKHJlc3VsdC5WYWwgIT0gMCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8zKGJ5dGVzV3JpdHRlbi50b0J1ZmZlcigpLnJlYWRVSW50MzJMRSgpICsgJyBieXRlcyB3cml0dGVuJyk7DQogICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMygnbm9QaXBlbGluZSA9ICcgKyB0aGlzLnNlc3Npb24uX29wdGlvbnMubm9QaXBlbGluZSwgdGhpcy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLmxlbmd0aCk7DQogICAgICAgICAgICAgICAgaWYodGhpcy5zZXNzaW9uLl9vcHRpb25zLm5vUGlwZWxpbmU9PW51bGwgfHwgdGhpcy5zZXNzaW9uLl9vcHRpb25zLm5vUGlwZWxpbmUgPT0gZmFsc2UpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IHRoaXMuc2Vzc2lvbi5fcGVuZGluZ1dyaXRlcy5wb3AoKTsNCiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5fcGVuZGluZ1dyaXRlcy5sZW5ndGggPiAwKQ0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uX3Byb2Nlc3NXcml0ZSgpOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvMygnV3JpdGUvRmx1c2gnKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uZmx1c2goKTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gKHRydWUpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH07DQogICAgcmV0Ll9wcm9jZXNzUmVhZF9yZWFkU2V0X3NpbmsgPSBmdW5jdGlvbiBfcHJvY2Vzc1JlYWRfcmVhZFNldF9zaW5rKHN0YXR1cywgYnl0ZXNSZWFkLCBidWZmZXIsIG9wdGlvbnMpDQogICAgew0KICAgICAgICBpZiAoc3RhdHVzICE9IDApIHsgb3B0aW9ucy5zZXNzaW9uLnB1c2gobnVsbCk7IHJldHVybjsgfQ0KICAgICAgICBjb25zb2xlLmluZm8zKGJ5dGVzUmVhZCArICcgYnl0ZXMgcmVhZCcpOw0KDQogICAgICAgIGJ1ZmZlciA9IGJ1ZmZlci5zbGljZSgwLCBieXRlc1JlYWQpOw0KICAgICAgICB2YXIgcHVzaFJlc3VsdCA9IG9wdGlvbnMuc2Vzc2lvbi5wdXNoKGJ1ZmZlcik7DQogICAgICAgIGlmIChvcHRpb25zLnNlc3Npb24uX29wdGlvbnMubm9QaXBlbGluZSAhPSAwICYmIG9wdGlvbnMuc2Vzc2lvbi5fcGVuZGluZ1dyaXRlcy5sZW5ndGggPiAwKQ0KICAgICAgICB7DQogICAgICAgICAgICAvLyBVbmxvY2sgYSB3cml0ZQ0KICAgICAgICAgICAgY29uc29sZS5pbmZvMygncGVuZGluZ1dyaXRlQ291bnQ6ICcgKyBvcHRpb25zLnNlc3Npb24uX3BlbmRpbmdXcml0ZXMubGVuZ3RoKTsNCiAgICAgICAgICAgIHZhciBpdGVtID0gb3B0aW9ucy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLnBvcCgpOw0KDQogICAgICAgICAgICBpZiAob3B0aW9ucy5zZXNzaW9uLl9wZW5kaW5nV3JpdGVzLmxlbmd0aCA+IDApDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgb3B0aW9ucy5zZXNzaW9uLl9wcm9jZXNzV3JpdGUoKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8zKCdXcml0ZS9GbHVzaCcpOw0KICAgICAgICAgICAgICAgIGl0ZW0uZmx1c2goKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGlmIChwdXNoUmVzdWx0KQ0KICAgICAgICB7DQogICAgICAgICAgICAvLyBXZSBjYW4gcmVhZCBtb3JlLCBiZWNhdXNlIGRhdGEgaXMgc3RpbGwgZmxvd2luZw0KICAgICAgICAgICAgb3B0aW9ucy5zZXNzaW9uLl9wcm9jZXNzUmVhZCgpOw0KICAgICAgICB9DQogICAgfTsNCiAgICByZXQuX3Byb2Nlc3NSZWFkID0gZnVuY3Rpb24gX3Byb2Nlc3NSZWFkKCkNCiAgICB7DQogICAgICAgIGlmICh0aGlzLl9kZXNjcmlwdG9yID09IG51bGwpIHsgcmV0dXJuOyB9DQogICAgICAgIHJlcXVpcmUoJ2ZzJykucmVhZCh0aGlzLl9kZXNjcmlwdG9yLCB7IG1ldGFkYXRhOiAnaGVjaS5zZXNzaW9uJywgYnVmZmVyOiB0aGlzLl9yZWFkYnVmZmVyLCBzZXNzaW9uOiB0aGlzIH0sIHRoaXMuX3Byb2Nlc3NSZWFkX3JlYWRTZXRfc2luayk7DQogICAgfTsNCiAgICByZXQub25jZSgnficsIGZ1bmN0aW9uICgpIHsgdGhpcy5kaXNjb25uZWN0KCk7IH0pOw0KICAgIHJldHVybiAocmV0KTsNCn0NCg0KdmFyIGlvY3RsID0ge307DQppZihwcm9jZXNzLnBsYXRmb3JtID09ICd3aW4zMicpDQp7DQogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGlvY3RsLCAnSEVDSV9WRVJTSU9OJywgeyB2YWx1ZTogMHg4MDAwRTAwMCB9KTsNCiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoaW9jdGwsICdDTElFTlRfQ09OTkVDVCcsIHsgdmFsdWU6IDB4ODAwMEUwMDQgfSk7DQp9DQppZihwcm9jZXNzLnBsYXRmb3JtID09ICdsaW51eCcpDQp7DQogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGlvY3RsLCAnSEVDSV9WRVJTSU9OJywgeyB2YWx1ZTogMHgwMCB9KTsNCiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoaW9jdGwsICdDTElFTlRfQ09OTkVDVCcsIHsgdmFsdWU6IDB4MDEgfSk7DQp9DQoNCnZhciBndWlkcyA9IHt9Ow0KT2JqZWN0LmRlZmluZVByb3BlcnR5KGd1aWRzLCAnQU1UJywgeyB2YWx1ZTogQnVmZmVyLmZyb20oJzI4MDBGODEyQjdCNDJENEJBQ0E4NDZF", 16000); + memcpy_s(_heci + 32000, 944, "MEZGNjU4MTRDJywgJ2hleCcpIH0pOw0KT2JqZWN0LmRlZmluZVByb3BlcnR5KGd1aWRzLCAnTE1FJywgeyB2YWx1ZTogQnVmZmVyLmZyb20oJ0RCQTQzMzY3NzYwNDdCNEVCM0FGQkNGQzI5QkVFN0E3JywgJ2hleCcpIH0pOw0KaWYgKHByb2Nlc3MucGxhdGZvcm0gPT0gJ3dpbjMyJykNCnsNCiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZ3VpZHMsICdIRUNJJywgeyB2YWx1ZTogQnVmZmVyLmZyb20oJzM0RkZEMUUyNTgzNEE5NDk4OERBOEU2OTE1Q0U5QkU1JywgJ2hleCcpIH0pOw0KfQ0KDQoNCm1vZHVsZS5leHBvcnRzID0geyBfT2JqZWN0SUQ6ICdoZWNpJywgSU9DVEw6IGlvY3RsLCBHVUlEUzogZ3VpZHMsIGNyZWF0ZTogaGVjaV9jcmVhdGUgfTsNCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGUuZXhwb3J0cywgInN1cHBvcnRlZCIsIHsNCiAgICBnZXQ6IGZ1bmN0aW9uICgpDQogICAgew0KICAgICAgICB0cnkNCiAgICAgICAgew0KICAgICAgICAgICAgdmFyIHAgPSB0aGlzLmNyZWF0ZSgpLmRlc2NyaXB0b3JQYXRoKCk7DQogICAgICAgICAgICB2YXIgZCA9IHRoaXMuY3JlYXRlKCkuY3JlYXRlRGVzY3JpcHRvcihwKTsNCiAgICAgICAgICAgIHJldHVybih0cnVlKTsNCiAgICAgICAgfQ0KICAgICAgICBjYXRjaChlKQ0KICAgICAgICB7DQogICAgICAgICAgICByZXR1cm4gKGZhbHNlKTsNCiAgICAgICAgfQ0KICAgIH0NCn0pOw==", 944); + ILibBase64DecodeEx((unsigned char*)_heci, 32944, (unsigned char*)_heci + 32944); + duk_push_global_object(ctx); duk_get_prop_string(ctx, -1, "addModule"); duk_swap_top(ctx, -2); duk_push_string(ctx, "heci"); duk_push_string(ctx, _heci + 32944); + duk_pcall_method(ctx, 2); duk_pop(ctx); + free(_heci); +#endif + #ifdef __APPLE__ duk_peval_string_noresult(ctx, "addModule('mac-powerutil', Buffer.from('LyoKQ29weXJpZ2h0IDIwMjAgSW50ZWwgQ29ycG9yYXRpb24KCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwp5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQpkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLApXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZApsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KKi8KCmZ1bmN0aW9uIHBvd2VydXRpbCgpCnsKICAgIHRoaXMuX09iamVjdElEID0gJ21hYy1wb3dlcnV0aWwnOwoKICAgIHRoaXMuc2xlZXAgPSBmdW5jdGlvbiBzbGVlcCgpCiAgICB7DQogICAgICAgIHZhciBjaGlsZDsNCiAgICAgICAgc3dpdGNoIChwcm9jZXNzLnBsYXRmb3JtKQ0KICAgICAgICB7DQogICAgICAgICAgICBjYXNlICdkYXJ3aW4nOg0KICAgICAgICAgICAgICAgIGNoaWxkID0gcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWNGaWxlKCcvYmluL3NoJywgWydzaCddKTsKICAgICAgICAgICAgICAgIGNoaWxkLnN0ZG91dC5zdHIgPSAnJzsgY2hpbGQuc3Rkb3V0Lm9uKCdkYXRhJywgZnVuY3Rpb24gKGNodW5rKSB7IHRoaXMuc3RyICs9IGNodW5rLnRvU3RyaW5nKCk7IH0pOwogICAgICAgICAgICAgICAgY2hpbGQuc3RkZXJyLnN0ciA9ICcnOyBjaGlsZC5zdGRlcnIub24oJ2RhdGEnLCBmdW5jdGlvbiAoY2h1bmspIHsgdGhpcy5zdHIgKz0gY2h1bmsudG9TdHJpbmcoKTsgfSk7CiAgICAgICAgICAgICAgICBjaGlsZC5zdGRpbi53cml0ZSgnb3Nhc2NyaXB0IC1lIFwndGVsbCBhcHBsaWNhdGlvbiAiU3lzdGVtIEV2ZW50cyIgdG8gc2xlZXBcJ1xuZXhpdFxuJyk7CiAgICAgICAgICAgICAgICBjaGlsZC53YWl0RXhpdCgpOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgZGVmYXVsdDoNCiAgICAgICAgICAgICAgICB0aHJvdyAoJ3NsZWVwKCkgbm90IGltcGxlbWVudGVkIG9uIHRoaXMgcGxhdGZvcm0nKTsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KICAgIH0KICAgIHRoaXMucmVzdGFydCA9IGZ1bmN0aW9uIHJlc3RhcnQoKQogICAgew0KICAgICAgICB2YXIgY2hpbGQ7DQogICAgICAgIHN3aXRjaChwcm9jZXNzLnBsYXRmb3JtKQ0KICAgICAgICB7DQogICAgICAgICAgICBjYXNlICdkYXJ3aW4nOg0KICAgICAgICAgICAgICAgIGNoaWxkID0gcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWNGaWxlKCcvYmluL3NoJywgWydzaCddKTsKICAgICAgICAgICAgICAgIGNoaWxkLnN0ZG91dC5zdHIgPSAnJzsgY2hpbGQuc3Rkb3V0Lm9uKCdkYXRhJywgZnVuY3Rpb24gKGNodW5rKSB7IHRoaXMuc3RyICs9IGNodW5rLnRvU3RyaW5nKCk7IH0pOwogICAgICAgICAgICAgICAgY2hpbGQuc3RkZXJyLnN0ciA9ICcnOyBjaGlsZC5zdGRlcnIub24oJ2RhdGEnLCBmdW5jdGlvbiAoY2h1bmspIHsgdGhpcy5zdHIgKz0gY2h1bmsudG9TdHJpbmcoKTsgfSk7CiAgICAgICAgICAgICAgICBjaGlsZC5zdGRpbi53cml0ZSgnc2h1dGRvd24gLXIgbm93XG4nKTsKICAgICAgICAgICAgICAgIGNoaWxkLndhaXRFeGl0KCk7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICBkZWZhdWx0Og0KICAgICAgICAgICAgICAgIHRocm93ICgncmVzdGFydCgpIG5vdCBpbXBsZW1lbnRlZCBvbiB0aGlzIHBsYXRmb3JtJyk7DQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCiAgICB9CiAgICB0aGlzLnNodXRkb3duID0gZnVuY3Rpb24gc2h1dGRvd24oKQogICAgew0KICAgICAgICB2YXIgY2hpbGQ7DQogICAgICAgIHN3aXRjaCAocHJvY2Vzcy5wbGF0Zm9ybSkNCiAgICAgICAgew0KICAgICAgICAgICAgY2FzZSAnZGFyd2luJzoNCiAgICAgICAgICAgICAgICBjaGlsZCA9IHJlcXVpcmUoJ2NoaWxkX3Byb2Nlc3MnKS5leGVjRmlsZSgnL2Jpbi9zaCcsIFsnc2gnXSk7CiAgICAgICAgICAgICAgICBjaGlsZC5zdGRvdXQuc3RyID0gJyc7IGNoaWxkLnN0ZG91dC5vbignZGF0YScsIGZ1bmN0aW9uIChjaHVuaykgeyB0aGlzLnN0ciArPSBjaHVuay50b1N0cmluZygpOyB9KTsKICAgICAgICAgICAgICAgIGNoaWxkLnN0ZGVyci5zdHIgPSAnJzsgY2hpbGQuc3RkZXJyLm9uKCdkYXRhJywgZnVuY3Rpb24gKGNodW5rKSB7IHRoaXMuc3RyICs9IGNodW5rLnRvU3RyaW5nKCk7IH0pOwogICAgICAgICAgICAgICAgY2hpbGQuc3RkaW4ud3JpdGUoJ3NodXRkb3duIC1oIG5vd1xuJyk7CiAgICAgICAgICAgICAgICBjaGlsZC53YWl0RXhpdCgpOw0KICAgICAgICAgICAgICAgIGJyZWFrOw0KICAgICAgICAgICAgZGVmYXVsdDoNCiAgICAgICAgICAgICAgICB0aHJvdyAoJ3NodXRkb3duKCkgbm90IGltcGxlbWVudGVkIG9uIHRoaXMgcGxhdGZvcm0nKTsNCiAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KICAgIH0KfQoKbW9kdWxlLmV4cG9ydHMgPSBuZXcgcG93ZXJ1dGlsKCk7', 'base64').toString());"); #endif diff --git a/microscript/ILibDuktape_ScriptContainer.c b/microscript/ILibDuktape_ScriptContainer.c index 8db2749..0db6643 100644 --- a/microscript/ILibDuktape_ScriptContainer.c +++ b/microscript/ILibDuktape_ScriptContainer.c @@ -72,7 +72,6 @@ limitations under the License. #include "ILibDuktape_SHA256.h" #include "ILibDuktape_EncryptionStream.h" #include "ILibDuktape_ChildProcess.h" -#include "ILibDuktape_HECI.h" #include "ILibDuktape_Debugger.h" #include "ILibDuktape_Commit.h" @@ -2377,9 +2376,6 @@ duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx3(duk_conte if ((securityFlags & SCRIPT_ENGINE_NO_PROCESS_SPAWNING) == 0) { ILibDuktape_ChildProcess_Init(ctx); -#ifndef _NOHECI - ILibDuktape_HECI_Init(ctx); -#endif } if ((securityFlags & SCRIPT_ENGINE_NO_FILE_SYSTEM_ACCESS) == 0) { ILibDuktape_fs_init(ctx); } diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c index e5179f5..eaccee7 100644 --- a/microscript/ILibDuktape_fs.c +++ b/microscript/ILibDuktape_fs.c @@ -473,7 +473,6 @@ duk_ret_t ILibDuktape_fs_write_writeset_sink(duk_context *ctx) } duk_ret_t ILibDuktape_fs_write(duk_context *ctx) { - int top = duk_get_top(ctx); int fd = (int)duk_require_int(ctx, 0); duk_size_t bufferLen; char *buffer = Duktape_GetBuffer(ctx, 1, &bufferLen); @@ -1419,7 +1418,6 @@ duk_ret_t ILibDuktape_fs_watcher_finalizer(duk_context *ctx) void ILibDuktape_fs_notifyDispatcher_QueryEx(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user) { ILibDuktape_fs_watcherData *data = (ILibDuktape_fs_watcherData*)Data; - int fd = (int)(uintptr_t)Key1; duk_push_heapptr(data->ctx, user); // [array] duk_push_heapptr(data->ctx, data->object); // [array][watcher] duk_get_prop_string(data->ctx, -1, FS_WATCH_PATH); // [array][watcher][path] diff --git a/modules/heci.js b/modules/heci.js index e870ff3..2ff0590 100644 --- a/modules/heci.js +++ b/modules/heci.js @@ -563,6 +563,7 @@ function heci_create() if (this._descriptor == null) { return; } require('fs').read(this._descriptor, { metadata: 'heci.session', buffer: this._readbuffer, session: this }, this._processRead_readSet_sink); }; + ret.once('~', function () { this.disconnect(); }); return (ret); } From 5fa79bdee0b17675a15c21caca9debda360f5a73 Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Thu, 28 May 2020 01:00:59 -0700 Subject: [PATCH 20/21] Fixed compiler warnings --- microscript/ILibDuktape_fs.c | 9 +++++++-- microstack/ILibProcessPipe.c | 1 - 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/microscript/ILibDuktape_fs.c b/microscript/ILibDuktape_fs.c index eaccee7..1d57be8 100644 --- a/microscript/ILibDuktape_fs.c +++ b/microscript/ILibDuktape_fs.c @@ -478,10 +478,15 @@ duk_ret_t ILibDuktape_fs_write(duk_context *ctx) char *buffer = Duktape_GetBuffer(ctx, 1, &bufferLen); int cbx = 2; int offset = 0, length = (int)bufferLen, e; - int position = -1; + //int position = -1; + if (duk_is_number(ctx, 2)) { offset = (int)duk_require_int(ctx, 2); cbx++; } if (duk_is_number(ctx, 3)) { length = (int)duk_require_int(ctx, 3); cbx++; } - if (duk_is_number(ctx, 4)) { position = (int)duk_require_int(ctx, 4); cbx++; } + if (duk_is_number(ctx, 4)) + { + //position = (int)duk_require_int(ctx, 4); + cbx++; + } if (!duk_is_function(ctx, cbx)) { return(ILibDuktape_Error(ctx, "Invalid Parameters")); } #ifdef WIN32 diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c index c174274..2051a25 100644 --- a/microstack/ILibProcessPipe.c +++ b/microstack/ILibProcessPipe.c @@ -184,7 +184,6 @@ char * ILibProcessPipe_Manager_OnQuery(void *chain, void *object, int fd, size_t { ILibProcessPipe_Manager_Object *man = (ILibProcessPipe_Manager_Object*)object; char *ret = ((ILibChain_Link*)object)->MetaData; - int i; *dataLen = strnlen_s(((ILibChain_Link*)object)->MetaData, 1024); void *node = ILibLinkedList_GetNode_Search(man->ActivePipes, ILibProcessPipe_Manager_OnQuery_comparer, (void*)(uintptr_t)fd); From 9297eca58ca2a58ca895a84f811468ab46cb445c Mon Sep 17 00:00:00 2001 From: Bryan Roe Date: Thu, 28 May 2020 13:20:10 -0700 Subject: [PATCH 21/21] Updated metadata, and fixed end() to remove HANDLE from select() if connection is not paused. --- microscript/ILibDuktape_net.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index b89ca91..0c4313c 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -1013,6 +1013,12 @@ void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void * ILibChain_WaitHandle_DestroySavedState(winIPC->mChain, winIPC->reservedState); winIPC->reservedState = NULL; } + else + { + // We probably aren't paused, so we need to remove our wait handles + if (winIPC->read_overlapped.hEvent != NULL) { ILibChain_RemoveWaitHandle(winIPC->mChain, winIPC->read_overlapped.hEvent); } + if (winIPC->write_overlapped.hEvent != NULL) { ILibChain_RemoveWaitHandle(winIPC->mChain, winIPC->write_overlapped.hEvent); } + } if (winIPC->mPipeHandle != NULL) { if (winIPC->mServer != NULL) { DisconnectNamedPipe(winIPC->mPipeHandle); } @@ -1264,8 +1270,10 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx) return(ILibDuktape_Error(ctx, "Error Creating Named Pipe: %s", ipc)); } //printf("ConnectNamedPipe(%s)\n", ipc); + duk_push_sprintf(ctx, "net.ipcServer [listen: %s]", ipc); ConnectNamedPipe(winIPC->mPipeHandle, &winIPC->overlapped); - ILibChain_AddWaitHandleEx(duk_ctx_chain(ctx), winIPC->overlapped.hEvent, -1, ILibDuktape_net_server_IPC_ConnectSink, winIPC, "net.ipcServer [listen]"); + ILibChain_AddWaitHandleEx(duk_ctx_chain(ctx), winIPC->overlapped.hEvent, -1, ILibDuktape_net_server_IPC_ConnectSink, winIPC, (char*)duk_get_string(ctx, -1)); + duk_pop(ctx); if (pIPC_SA != NULL) { LocalFree(IPC_ACL); } return(1);