1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2026-02-17 18:09:09 +00:00

Merge branch 'Branch_heci_update'

This commit is contained in:
Bryan Roe
2020-05-28 13:22:02 -07:00
18 changed files with 1303 additions and 1362 deletions

View File

@@ -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

View File

@@ -68,7 +68,6 @@
<ClCompile Include="..\microscript\ILibduktape_EventEmitter.c" />
<ClCompile Include="..\microscript\ILibDuktape_fs.c" />
<ClCompile Include="..\microscript\ILibDuktape_GenericMarshal.c" />
<ClCompile Include="..\microscript\ILibDuktape_HECI.c" />
<ClCompile Include="..\microscript\ILibDuktape_Helpers.c" />
<ClCompile Include="..\microscript\ILibDuktape_HttpStream.c" />
<ClCompile Include="..\microscript\ILibDuktape_MemoryStream.c" />
@@ -118,7 +117,6 @@
<ClInclude Include="..\microscript\ILibDuktape_EventEmitter.h" />
<ClInclude Include="..\microscript\ILibDuktape_fs.h" />
<ClInclude Include="..\microscript\ILibDuktape_GenericMarshal.h" />
<ClInclude Include="..\microscript\ILibDuktape_HECI.h" />
<ClInclude Include="..\microscript\ILibDuktape_Helpers.h" />
<ClInclude Include="..\microscript\ILibDuktape_net.h" />
<ClInclude Include="..\microscript\ILibDuktape_NetworkMonitor.h" />

View File

@@ -573,7 +573,6 @@
<ClCompile Include="..\microscript\ILibduktape_EventEmitter.c" />
<ClCompile Include="..\microscript\ILibDuktape_fs.c" />
<ClCompile Include="..\microscript\ILibDuktape_GenericMarshal.c" />
<ClCompile Include="..\microscript\ILibDuktape_HECI.c" />
<ClCompile Include="..\microscript\ILibDuktape_Helpers.c" />
<ClCompile Include="..\microscript\ILibDuktape_HttpStream.c" />
<ClCompile Include="..\microscript\ILibDuktape_MemoryStream.c" />
@@ -625,7 +624,6 @@
<ClInclude Include="..\microscript\ILibDuktape_EventEmitter.h" />
<ClInclude Include="..\microscript\ILibDuktape_fs.h" />
<ClInclude Include="..\microscript\ILibDuktape_GenericMarshal.h" />
<ClInclude Include="..\microscript\ILibDuktape_HECI.h" />
<ClInclude Include="..\microscript\ILibDuktape_Helpers.h" />
<ClInclude Include="..\microscript\ILibDuktape_net.h" />
<ClInclude Include="..\microscript\ILibDuktape_NetworkMonitor.h" />

View File

@@ -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"));

View File

@@ -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);

View File

@@ -33,11 +33,7 @@ limitations under the License.
#include <pthread.h>
#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))
{

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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,16 @@ 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);
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);

File diff suppressed because one or more lines are too long

View File

@@ -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); }

View File

@@ -21,6 +21,8 @@ limitations under the License.
#include <ws2tcpip.h>
#include <direct.h>
#include <wchar.h>
#include <io.h>
#include <fcntl.h>
#endif
#include "microstack/ILibParsers.h"
@@ -66,6 +68,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 +202,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 +279,44 @@ 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
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);
}
duk_ret_t ILibDuktape_fs_readSync(duk_context *ctx)
{
@@ -303,6 +342,329 @@ 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_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_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));
}
duk_pop_2(ctx); // [DescriptorEvents][pending]
if (duk_get_length(ctx, -1) == 0)
{
// 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_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]
duk_del_prop_index(ctx, -1, fd);
}
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_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);
}
duk_ret_t ILibDuktape_fs_write(duk_context *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);
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]
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);
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]
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);
if (top > 2 && (!duk_is_function(ctx, 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_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
if (bytesRead >= 0 || (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR))
{
// Completed
int errStatus = bytesRead >= 0 ? 0 : errno;
duk_dup(ctx, 2); // [func]
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);
}
//
// 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, -2, 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);
@@ -1061,7 +1423,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]
@@ -1644,16 +2005,23 @@ 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);
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);
@@ -1678,6 +2046,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);

View File

@@ -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);
@@ -1012,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); }
@@ -1263,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);
@@ -1326,7 +1335,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 +1489,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);
}

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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,10 +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);
@@ -173,6 +178,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

View File

@@ -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;
@@ -397,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);
}
}

606
modules/heci.js Normal file
View File

@@ -0,0 +1,606 @@
/*
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)
{
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();
}
if (process.platform == 'win32')
{
return (false);
}
},
'final': function (flush)
{
flush();
},
'read': function(size)
{
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)
{
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)
{
if(status != 'NONE')
{
console.info3('>>> heci.session signaled with status: ' + 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.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.info2('pendingWriteCount: ' + this.session._pendingWrites.length);
var item = this.session._pendingWrites.pop();
if (this.session._pendingWrites.length > 0)
{
this.session._processWrite();
}
else
{
console.info2('Write/Flush');
item.flush();
}
}
if (pushResult)
{
// We can read more, because data is still flowing
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.info1('Sometype of error: ' + result._LastError);
this.session.push(null);
}
}
}
else
{
console.info1('READ_OVERLAPPED_ERROR: ' + result._LastError + ' on ' + this.session._hashCode());
}
});
}
}
else
{
console.info1('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.info1('connect()');
this.doIoctl(this.heciParent.IOCTL.CLIENT_CONNECT, guid, Buffer.alloc(16), function _onconnect(status, buffer, opt)
{
if(status!=0)
{
console.info1('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;
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.info1('Connected, buffer size: ' + this.MaxBufferSize);
this._read(this.MaxBufferSize);
this.emit('connect');
}, options);
})
.addMethod('descriptorPath', function _descriptorPath()
{
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;
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.info1('... Unable to acquire [deviceInfo]');
throw ('unable to acquire [deviceInfo]');
}
console.info1('... 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.info1('... failed to acquire [deviceDetail]');
throw ('unable to acquire [deviceDetail]');
}
var devPath = deviceDetail.Deref(4, GM.PointerSize);
return (devPath.String);
})
.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)
{
console.info1('... failed to acquire [descriptor]');
throw ('failed to acquire descriptor');
}
console.info1('... 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.info1('DISCONNECT on ' + this._hashCode());
if (process.platform == 'linux')
{
if(this._descriptor != null)
{
require('DescriptorEvents').removeDescriptor(this._descriptor);
require('fs').closeSync(this._descriptor);
this._descriptor = null;
}
}
if (process.platform == 'win32')
{
//
// 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)
{
if (typeof (callback) != 'function') { throw ('Callback not specified'); }
var i;
var parms = [];
for (i = 4; i < arguments.length; ++i)
{
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)
{
// 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.info3('_WRITING: ' + chunk.buffer.length + ' bytes' + ' on ' + this._hashCode());
if (process.platform == 'win32')
{
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.info1('Write Error: ' + result._LastError);
}
}
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)
{
if(status == 0)
{
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();
if (options.session._pendingWrites.length > 0)
{
options.session._processWrite();
}
else
{
console.info3('Write/Flush');
item.flush();
}
}
}
};
ret._processWrite_signaled = function _processWrite_signaled(status)
{
console.info3('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.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();
if (this.session._pendingWrites.length > 0)
{
this.session._processWrite();
}
else
{
console.info3('Write/Flush');
item.flush();
}
return (true);
}
}
}
};
ret._processRead_readSet_sink = function _processRead_readSet_sink(status, bytesRead, buffer, options)
{
if (status != 0) { options.session.push(null); return; }
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.info3('pendingWriteCount: ' + options.session._pendingWrites.length);
var item = options.session._pendingWrites.pop();
if (options.session._pendingWrites.length > 0)
{
options.session._processWrite();
}
else
{
console.info3('Write/Flush');
item.flush();
}
}
if (pushResult)
{
// We can read more, because data is still flowing
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);
};
ret.once('~', function () { this.disconnect(); });
return (ret);
}
var ioctl = {};
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') });
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();
var d = this.create().createDescriptor(p);
return(true);
}
catch(e)
{
return (false);
}
}
});