mirror of
https://github.com/Ylianst/MeshAgent
synced 2026-02-17 09:59:06 +00:00
Merge branch 'Branch_heci_update'
This commit is contained in:
2
makefile
2
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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
@@ -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); }
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
606
modules/heci.js
Normal 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user