mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-24 04:04:31 +00:00
Much improved, better stability, lots of fixes
This commit is contained in:
@@ -29,7 +29,7 @@ limitations under the License.
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#define ILibDuktape_ModSearch_ModuleFile "0xFF"
|
||||
#define ILibDuktape_ModSearch_ModuleFile (void*)0xFF
|
||||
|
||||
int ILibDuktape_ModSearch_AddModule(duk_context *ctx, char *id, char *module, int moduleLen)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "ILibDuktape_WritableStream.h"
|
||||
#include "ILibDuktape_EventEmitter.h"
|
||||
|
||||
#define ILibDuktape_ChildProcess_Manager "\xFF_ChildProcess_Manager"
|
||||
#define ILibDuktape_ChildProcess_Process "\xFF_ChildProcess_Process"
|
||||
#define ILibDuktape_ChildProcess_MemBuf "\xFF_ChildProcess_MemBuf"
|
||||
|
||||
@@ -122,14 +121,23 @@ ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUS
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "kill", ILibDuktape_ChildProcess_Kill, 0);
|
||||
|
||||
duk_push_object(ctx);
|
||||
ILibDuktape_WriteID(ctx, "childProcess.stdout");
|
||||
duk_dup(ctx, -2);
|
||||
ILibDuktape_CreateReadonlyProperty(ctx, "parent");
|
||||
retVal->stdOut = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdOut_OnPause, ILibDuktape_ChildProcess_SubProcess_StdOut_OnResume, retVal);
|
||||
ILibDuktape_CreateReadonlyProperty(ctx, "stdout");
|
||||
|
||||
duk_push_object(ctx);
|
||||
ILibDuktape_WriteID(ctx, "childProcess.stderr");
|
||||
duk_dup(ctx, -2);
|
||||
ILibDuktape_CreateReadonlyProperty(ctx, "parent");
|
||||
retVal->stdErr = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdErr_OnPause, ILibDuktape_ChildProcess_SubProcess_StdErr_OnResume, retVal);
|
||||
ILibDuktape_CreateReadonlyProperty(ctx, "stderr");
|
||||
|
||||
duk_push_object(ctx);
|
||||
ILibDuktape_WriteID(ctx, "childProcess.stdin");
|
||||
duk_dup(ctx, -2);
|
||||
ILibDuktape_CreateReadonlyProperty(ctx, "parent");
|
||||
retVal->stdIn = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_ChildProcess_SubProcess_StdIn_WriteHandler, ILibDuktape_ChildProcess_SubProcess_StdIn_EndHandler, retVal);
|
||||
ILibDuktape_CreateReadonlyProperty(ctx, "stdin");
|
||||
|
||||
@@ -163,12 +171,13 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
|
||||
int i, x;
|
||||
void *callback = NULL;
|
||||
ILibProcessPipe_Process p = NULL;
|
||||
ILibProcessPipe_SpawnTypes spawnType = ILibProcessPipe_SpawnTypes_DEFAULT;
|
||||
|
||||
for (i = 0; i < nargs; ++i)
|
||||
{
|
||||
if (duk_is_array(ctx, i) != 0)
|
||||
{
|
||||
int arrLen = duk_get_length(ctx, i);
|
||||
int arrLen = (int)duk_get_length(ctx, i);
|
||||
#ifdef WIN32
|
||||
args = (char**)_alloca((arrLen + 1) * sizeof(char*));
|
||||
#else
|
||||
@@ -185,6 +194,11 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
|
||||
{
|
||||
callback = duk_get_heapptr(ctx, i);
|
||||
}
|
||||
else if (duk_is_object(ctx, i))
|
||||
{
|
||||
// Options
|
||||
spawnType = (ILibProcessPipe_SpawnTypes)Duktape_GetIntPropertyValue(ctx, i, "type", (int)ILibProcessPipe_SpawnTypes_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -206,7 +220,7 @@ duk_ret_t ILibDuktape_ChildProcess_execFile(duk_context *ctx)
|
||||
}
|
||||
#endif
|
||||
|
||||
p = ILibProcessPipe_Manager_SpawnProcess(manager, target, args);
|
||||
p = ILibProcessPipe_Manager_SpawnProcessEx2(manager, target, args, spawnType, 0);
|
||||
if (p == NULL)
|
||||
{
|
||||
return(ILibDuktape_Error(ctx, "child_process.execFile(): Could not exec [%s]", target));
|
||||
@@ -222,6 +236,16 @@ void ILibDuktape_ChildProcess_PUSH(duk_context *ctx, void *chain)
|
||||
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_ChildProcess_Manager_Finalizer);
|
||||
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "execFile", ILibDuktape_ChildProcess_execFile, DUK_VARARGS);
|
||||
duk_push_object(ctx);
|
||||
duk_push_int(ctx, 0);
|
||||
duk_put_prop_string(ctx, -2, "DEFAULT");
|
||||
duk_push_int(ctx, 1);
|
||||
duk_put_prop_string(ctx, -2, "USER");
|
||||
duk_push_int(ctx, 2);
|
||||
duk_put_prop_string(ctx, -2, "WINLOGON");
|
||||
duk_push_int(ctx, 3);
|
||||
duk_put_prop_string(ctx, -2, "TERM");
|
||||
duk_put_prop_string(ctx, -2, "SpawnTypes");
|
||||
}
|
||||
void ILibDuktape_ChildProcess_Init(duk_context *ctx)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define __ILIBDUKTAPE_CHILDPROCESS__
|
||||
|
||||
#include "duktape.h"
|
||||
#define ILibDuktape_ChildProcess_Manager "\xFF_ChildProcess_Manager"
|
||||
|
||||
void ILibDuktape_ChildProcess_Init(duk_context *ctx);
|
||||
|
||||
|
||||
@@ -376,6 +376,29 @@ duk_ret_t ILibDuktape_DGram_setTTL(duk_context *ctx)
|
||||
{
|
||||
return ILibDuktape_Error(ctx, "Not implemented");
|
||||
}
|
||||
duk_ret_t ILibDuktape_DGram_setMulticastInterface(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_DGRAM_DATA *ptrs = ILibDuktape_DGram_GetPTR(ctx);
|
||||
struct sockaddr_in addr;
|
||||
char *str = (char*)duk_require_string(ctx, 0);
|
||||
|
||||
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||
ILibInet_pton(AF_INET, str, &(addr.sin_addr));
|
||||
|
||||
ILibAsyncUDPSocket_SetMulticastInterface(ptrs->mSocket, (struct sockaddr*)&addr);
|
||||
return(0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_Dgram_socket_close(duk_context *ctx)
|
||||
{
|
||||
if (duk_get_top(ctx) > 0 && duk_is_function(ctx, 0)) { ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter_GetEmitter_fromThis(ctx), "close", duk_require_heapptr(ctx, 0)); }
|
||||
|
||||
duk_push_this(ctx); // [socket]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_DGRAM_SOCKET_NATIVE); // [socket][ptr]
|
||||
ILibDuktape_DGRAM_DATA *data = (ILibDuktape_DGRAM_DATA*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
ILibAsyncSocket_Disconnect(data->mSocket);
|
||||
|
||||
return(0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_DGRAM_Config config = ILibDuktape_DGRAM_Config_NONE;
|
||||
@@ -397,6 +420,7 @@ duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
|
||||
|
||||
/**************************************************************************************/
|
||||
duk_push_object(ctx); // [socket]
|
||||
ILibDuktape_WriteID(ctx, "dgram.socket");
|
||||
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_Dgram_Finalizer);
|
||||
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_DGRAM_DATA)); // [socket][native]
|
||||
ptrs = (ILibDuktape_DGRAM_DATA*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
@@ -420,10 +444,13 @@ duk_ret_t ILibDuktape_DGram_createSocket(duk_context *ctx)
|
||||
ILibDuktape_CreateInstanceMethodWithStringProperty(ctx, ILibDuktape_DGRAM_MULTICAST_MEMBERSHIP_TYPE, "add", "addMembership", ILibDuktape_DGram_multicastMembership, DUK_VARARGS);
|
||||
ILibDuktape_CreateInstanceMethodWithStringProperty(ctx, ILibDuktape_DGRAM_MULTICAST_MEMBERSHIP_TYPE, "remove", "dropMembership", ILibDuktape_DGram_multicastMembership, DUK_VARARGS);
|
||||
|
||||
|
||||
ILibDuktape_CreateProperty_InstanceMethod(ctx, "close", ILibDuktape_Dgram_socket_close, DUK_VARARGS);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "send", ILibDuktape_DGram_send, DUK_VARARGS);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "setBroadcast", ILibDuktape_DGram_setBroadcast, DUK_VARARGS);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastLoopback", ILibDuktape_DGram_setMulticastLoopback, 1);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastTTL", ILibDuktape_DGram_setMulticastTTL, 1);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "setMulticastInterface", ILibDuktape_DGram_setMulticastInterface, 1);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "setTTL", ILibDuktape_DGram_setTTL, 1);
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -18,6 +18,7 @@ limitations under the License.
|
||||
#include "ILibDuktape_Helpers.h"
|
||||
#include "ILibDuktape_DuplexStream.h"
|
||||
|
||||
#define ILibDuktape_Transform_Data "\xFF_Transform_Data"
|
||||
|
||||
#ifdef __DOXY__
|
||||
/*!
|
||||
@@ -53,7 +54,19 @@ void ILibDuktape_DuplexStream_OnEnd(struct ILibDuktape_WritableStream *stream, v
|
||||
if (ds->OnEnd != NULL) { ((ILibDuktape_DuplexStream_EndHandler)ds->OnEnd)(ds, ds->user); }
|
||||
}
|
||||
|
||||
ILibDuktape_DuplexStream * ILibDuktape_DuplexStream_Init(duk_context * ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, void * user)
|
||||
int ILibDuktape_DuplexStream_OnUnshift(ILibDuktape_readableStream *sender, int unshiftBytes, void *user)
|
||||
{
|
||||
ILibDuktape_DuplexStream *ds = (ILibDuktape_DuplexStream*)user;
|
||||
if (ds->unshiftHandler == NULL)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(((ILibDuktape_DuplexStream_UnshiftHandler)ds->unshiftHandler)(ds, unshiftBytes, ds->user));
|
||||
}
|
||||
}
|
||||
ILibDuktape_DuplexStream * ILibDuktape_DuplexStream_InitEx(duk_context * ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, ILibDuktape_DuplexStream_UnshiftHandler UnshiftHandler, void * user)
|
||||
{
|
||||
ILibDuktape_DuplexStream *retVal;
|
||||
|
||||
@@ -63,12 +76,94 @@ ILibDuktape_DuplexStream * ILibDuktape_DuplexStream_Init(duk_context * ctx, ILib
|
||||
|
||||
memset(retVal, 0, sizeof(ILibDuktape_DuplexStream));
|
||||
retVal->user = user;
|
||||
retVal->readableStream = ILibDuktape_InitReadableStream(ctx, ILibDuktape_DuplexStream_OnPause, ILibDuktape_DuplexStream_OnResume, retVal);
|
||||
retVal->readableStream = ILibDuktape_ReadableStream_InitEx(ctx, ILibDuktape_DuplexStream_OnPause, ILibDuktape_DuplexStream_OnResume, UnshiftHandler != NULL ? ILibDuktape_DuplexStream_OnUnshift : NULL, retVal);
|
||||
retVal->writableStream = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_DuplexStream_OnWrite, ILibDuktape_DuplexStream_OnEnd, retVal);
|
||||
retVal->OnEnd = EndHandler;
|
||||
retVal->OnWrite = WriteHandler;
|
||||
retVal->OnPause = PauseHandler;
|
||||
retVal->OnResume = ResumeHandler;
|
||||
retVal->ParentObject = duk_get_heapptr(ctx, -1);
|
||||
retVal->unshiftHandler = UnshiftHandler;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
ILibTransport_DoneState ILibDuktape_Transform_WriteSink(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user)
|
||||
{
|
||||
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
|
||||
TF->writerEnded = stream->endBytes;
|
||||
TF->On_NativeTransform(TF, TF->source->Reserved, stream->endBytes, buffer, bufferLen, TF->user);
|
||||
return(TF->target->paused == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE);
|
||||
}
|
||||
void ILibDuktape_Transform_EndSink(struct ILibDuktape_WritableStream *stream, void *user)
|
||||
{
|
||||
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
|
||||
if (TF->writerEnded == 0)
|
||||
{
|
||||
TF->writerEnded = -1;
|
||||
TF->On_NativeTransform(TF, 0, -1, NULL, 0, TF->user);
|
||||
}
|
||||
ILibDuktape_readableStream_WriteEnd(TF->target);
|
||||
}
|
||||
void ILibDuktape_Transform_PauseSink(struct ILibDuktape_readableStream *sender, void *user)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(sender);
|
||||
UNREFERENCED_PARAMETER(user);
|
||||
|
||||
// NO-OP, because it is handled in the WriteSink
|
||||
}
|
||||
void ILibDuktape_Transform_ResumeSink(struct ILibDuktape_readableStream *sender, void *user)
|
||||
{
|
||||
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
|
||||
ILibDuktape_WritableStream_Ready(TF->source);
|
||||
}
|
||||
void ILibDuktape_Transform_ReaderPipeHook(struct ILibDuktape_readableStream *sender, void *wstream, void *user)
|
||||
{
|
||||
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
|
||||
TF->readerIsPiped = 1;
|
||||
if (TF->On_NativePipedSink != NULL) { TF->On_NativePipedSink(TF, TF->user); }
|
||||
}
|
||||
int ILibDuktape_Transform_UnshiftSink(struct ILibDuktape_readableStream *sender, int unshiftBytes, void *user)
|
||||
{
|
||||
ILibDuktape_Transform *TF = (ILibDuktape_Transform*)user;
|
||||
return(TF->On_NativeUnshift(TF, unshiftBytes, TF->user));
|
||||
}
|
||||
ILibDuktape_Transform* ILibDuktape_Transform_InitEx(duk_context *ctx, ILibDuktape_TransformStream_TransformHandler transformHandler, ILibDuktape_TransformStream_UnShiftHandler unshiftHandler, ILibDuktape_TransformStream_TargetPipedHandler pipedHandler, void *user)
|
||||
{
|
||||
ILibDuktape_Transform *TF;
|
||||
|
||||
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_Transform)); // [buffer]
|
||||
TF = (ILibDuktape_Transform*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_Transform_Data); // ...
|
||||
|
||||
TF->source = ILibDuktape_WritableStream_Init(ctx, ILibDuktape_Transform_WriteSink, ILibDuktape_Transform_EndSink, TF);
|
||||
if (unshiftHandler != NULL)
|
||||
{
|
||||
TF->target = ILibDuktape_ReadableStream_InitEx(ctx, ILibDuktape_Transform_PauseSink, ILibDuktape_Transform_ResumeSink, ILibDuktape_Transform_UnshiftSink, TF);
|
||||
}
|
||||
else
|
||||
{
|
||||
TF->target = ILibDuktape_ReadableStream_Init(ctx, ILibDuktape_Transform_PauseSink, ILibDuktape_Transform_ResumeSink, TF);
|
||||
}
|
||||
TF->target->PipeHookHandler = ILibDuktape_Transform_ReaderPipeHook;
|
||||
TF->On_NativePipedSink = pipedHandler;
|
||||
TF->On_NativeTransform = transformHandler;
|
||||
TF->On_NativeUnshift = unshiftHandler;
|
||||
TF->user = user;
|
||||
|
||||
return(TF);
|
||||
}
|
||||
|
||||
ILibDuktape_WritableStream *ILibDuktape_DuplexStream_GetNativeWritable(duk_context *ctx, void *stream)
|
||||
{
|
||||
ILibDuktape_WritableStream *retVal = NULL;
|
||||
duk_push_heapptr(ctx, stream); // [stream]
|
||||
if (duk_has_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS))
|
||||
{
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS); // [stream][ws]
|
||||
retVal = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
if (retVal->JSCreated) { retVal = NULL; }
|
||||
duk_pop(ctx); // [stream]
|
||||
}
|
||||
duk_pop(ctx); // ...
|
||||
return(retVal);
|
||||
}
|
||||
@@ -28,6 +28,7 @@ typedef struct ILibDuktape_DuplexStream
|
||||
{
|
||||
ILibDuktape_readableStream *readableStream;
|
||||
ILibDuktape_WritableStream *writableStream;
|
||||
void *unshiftHandler;
|
||||
void *user;
|
||||
void *ParentObject;
|
||||
void *OnWrite;
|
||||
@@ -36,9 +37,34 @@ typedef struct ILibDuktape_DuplexStream
|
||||
void *OnResume;
|
||||
}ILibDuktape_DuplexStream;
|
||||
|
||||
struct ILibDuktape_Transform;
|
||||
typedef void(*ILibDuktape_TransformStream_TransformHandler)(struct ILibDuktape_Transform *sender, int Reserved, int flush, char *buffer, int bufferLen, void *user);
|
||||
typedef void(*ILibDuktape_TransformStream_TargetPipedHandler)(struct ILibDuktape_Transform *sender, void *user);
|
||||
typedef int(*ILibDuktape_TransformStream_UnShiftHandler)(struct ILibDuktape_Transform *sender, int unshiftBytes, void *user);
|
||||
|
||||
typedef struct ILibDuktape_Transform
|
||||
{
|
||||
duk_context *ctx;
|
||||
ILibDuktape_WritableStream *source;
|
||||
ILibDuktape_readableStream *target;
|
||||
int readerIsPiped;
|
||||
int writerEnded;
|
||||
|
||||
ILibDuktape_TransformStream_UnShiftHandler On_NativeUnshift;
|
||||
ILibDuktape_TransformStream_TransformHandler On_NativeTransform;
|
||||
ILibDuktape_TransformStream_TargetPipedHandler On_NativePipedSink;
|
||||
void *user;
|
||||
}ILibDuktape_Transform;
|
||||
|
||||
|
||||
|
||||
ILibDuktape_Transform* ILibDuktape_Transform_InitEx(duk_context *ctx, ILibDuktape_TransformStream_TransformHandler transformHandler, ILibDuktape_TransformStream_UnShiftHandler unshiftHandler, ILibDuktape_TransformStream_TargetPipedHandler pipedHandler, void *user);
|
||||
#define ILibDuktape_Transform_Init(ctx, transformHandler, pipedHandler, user) ILibDuktape_Transform_InitEx(ctx, transformHandler, NULL, pipedHandler, user)
|
||||
|
||||
typedef ILibTransport_DoneState(*ILibDuktape_DuplexStream_WriteHandler)(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user);
|
||||
typedef void(*ILibDuktape_DuplexStream_EndHandler)(ILibDuktape_DuplexStream *stream, void *user);
|
||||
typedef void(*ILibDuktape_DuplexStream_PauseResumeHandler)(ILibDuktape_DuplexStream *sender, void *user);
|
||||
typedef int(*ILibDuktape_DuplexStream_UnshiftHandler)(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user);
|
||||
|
||||
#define ILibDuktape_DuplexStream_Ready(duplexStream) ILibDuktape_WritableStream_Ready((duplexStream)->writableStream)
|
||||
#define ILibDuktape_DuplexStream_WriteData(duplexStream, buffer, bufferLen) ILibDuktape_readableStream_WriteData((duplexStream)->readableStream, buffer, bufferLen)
|
||||
@@ -46,7 +72,7 @@ typedef void(*ILibDuktape_DuplexStream_PauseResumeHandler)(ILibDuktape_DuplexStr
|
||||
#define ILibDuktape_DuplexStream_WriteEnd(duplexStream) ILibDuktape_readableStream_WriteEnd((duplexStream)->readableStream)
|
||||
#define ILibDuktape_DuplexStream_Closed(duplexStream) ILibDuktape_readableStream_Closed((duplexStream)->readableStream)
|
||||
|
||||
ILibDuktape_DuplexStream* ILibDuktape_DuplexStream_Init(duk_context *ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, void *user);
|
||||
|
||||
|
||||
ILibDuktape_DuplexStream* ILibDuktape_DuplexStream_InitEx(duk_context *ctx, ILibDuktape_DuplexStream_WriteHandler WriteHandler, ILibDuktape_DuplexStream_EndHandler EndHandler, ILibDuktape_DuplexStream_PauseResumeHandler PauseHandler, ILibDuktape_DuplexStream_PauseResumeHandler ResumeHandler, ILibDuktape_DuplexStream_UnshiftHandler UnshiftHandler, void *user);
|
||||
#define ILibDuktape_DuplexStream_Init(ctx, WriteHandler, EndHandler, PauseHandler, ResumeHandler, user) ILibDuktape_DuplexStream_InitEx(ctx, WriteHandler, EndHandler, PauseHandler, ResumeHandler, NULL, user)
|
||||
ILibDuktape_WritableStream *ILibDuktape_DuplexStream_GetNativeWritable(duk_context *ctx, void *stream);
|
||||
#endif
|
||||
|
||||
@@ -31,11 +31,13 @@ int ILibDuktape_EventEmitter_AddEventHeapptr(ILibDuktape_EventEmitter *emitter,
|
||||
int ILibDuktape_EventEmitter_AddSink(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_Handler handler); // Add Native Event Handler
|
||||
int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler 'once'
|
||||
int ILibDuktape_EventEmitter_AddOnceEx(ILibDuktape_EventEmitter *emitter, char *eventName, duk_c_function func, duk_idx_t funcArgs);
|
||||
int ILibDuktape_EventEmitter_AddOnceEx2(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func, duk_idx_t funcArgs);
|
||||
int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler
|
||||
int ILibDuktape_EventEmitter_AddOnceEx3(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func);
|
||||
#define ILibDuktape_EventEmitter_AddOnceEx2(ctx, idx, eventName, func, argCount) ILibDuktape_EventEmitter_AddOnceEx3(ctx, idx, eventName, func)
|
||||
|
||||
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);
|
||||
|
||||
void ILibDuktape_EventEmitter_AddHook(ILibDuktape_EventEmitter *emitter, char *eventName, ILibDuktape_EventEmitter_HookHandler handler);
|
||||
|
||||
void ILibDuktape_EventEmitter_ForwardEvent(duk_context *ctx, duk_idx_t eventSourceIndex, char *sourceEventName, duk_idx_t eventTargetIndex, char *targetEventName);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,8 @@ limitations under the License.
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#define ILibDuktape_GenericMarshal_VariableType "\xFF_GenericMarshal_VarType"
|
||||
|
||||
typedef PTRSIZE(APICALLTYPE *R0)();
|
||||
typedef PTRSIZE(APICALLTYPE *R1)(PTRSIZE V1);
|
||||
typedef PTRSIZE(APICALLTYPE *R2)(PTRSIZE V1, PTRSIZE V2);
|
||||
@@ -52,6 +54,17 @@ typedef PTRSIZE(APICALLTYPE *R7)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4,
|
||||
typedef PTRSIZE(APICALLTYPE *R8)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8);
|
||||
typedef PTRSIZE(APICALLTYPE *R9)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9);
|
||||
typedef PTRSIZE(APICALLTYPE *R10)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10);
|
||||
typedef PTRSIZE(APICALLTYPE *R11)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11);
|
||||
typedef PTRSIZE(APICALLTYPE *R12)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12);
|
||||
typedef PTRSIZE(APICALLTYPE *R13)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13);
|
||||
typedef PTRSIZE(APICALLTYPE *R14)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14);
|
||||
typedef PTRSIZE(APICALLTYPE *R15)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15);
|
||||
typedef PTRSIZE(APICALLTYPE *R16)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16);
|
||||
typedef PTRSIZE(APICALLTYPE *R17)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17);
|
||||
typedef PTRSIZE(APICALLTYPE *R18)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17, PTRSIZE V18);
|
||||
typedef PTRSIZE(APICALLTYPE *R19)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17, PTRSIZE V18, PTRSIZE V19);
|
||||
typedef PTRSIZE(APICALLTYPE *R20)(PTRSIZE V1, PTRSIZE V2, PTRSIZE V3, PTRSIZE V4, PTRSIZE V5, PTRSIZE V6, PTRSIZE V7, PTRSIZE V8, PTRSIZE V9, PTRSIZE V10, PTRSIZE V11, PTRSIZE V12, PTRSIZE V13, PTRSIZE V14, PTRSIZE V15, PTRSIZE V16, PTRSIZE V17, PTRSIZE V18, PTRSIZE V19, PTRSIZE V20);
|
||||
|
||||
|
||||
typedef struct Duktape_GenericMarshal_Proxy
|
||||
{
|
||||
@@ -175,7 +188,6 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_SET(duk_context *ctx)
|
||||
{
|
||||
void *ptr;
|
||||
int size;
|
||||
int value = duk_require_int(ctx, 0);
|
||||
|
||||
duk_push_this(ctx); // [var]
|
||||
duk_get_prop_string(ctx, -1, "_ptr"); // [var][ptr]
|
||||
@@ -183,18 +195,32 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_Val_SET(duk_context *ctx)
|
||||
duk_get_prop_string(ctx, -2, "_size"); // [var][ptr][size]
|
||||
size = duk_to_int(ctx, -1);
|
||||
|
||||
switch (size)
|
||||
if (duk_is_number(ctx, 0))
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 2:
|
||||
((unsigned short*)ptr)[0] = (unsigned short)value;
|
||||
((unsigned short*)ptr)[0] = (unsigned short)duk_require_int(ctx, 0);
|
||||
break;
|
||||
case 4:
|
||||
((unsigned int*)ptr)[0] = (unsigned int)value;
|
||||
((unsigned int*)ptr)[0] = (unsigned int)duk_require_int(ctx, 0);
|
||||
break;
|
||||
default:
|
||||
duk_push_string(ctx, "UNSUPPORTED VAL SIZE");
|
||||
duk_push_string(ctx, "UNSUPPORTED VAL SIZE, with integral type");
|
||||
duk_throw(ctx);
|
||||
return(DUK_RET_ERROR);
|
||||
}
|
||||
}
|
||||
else if (duk_is_object(ctx, 0) && duk_has_prop_string(ctx, 0, ILibDuktape_GenericMarshal_VariableType))
|
||||
{
|
||||
((void**)ptr)[0] = Duktape_GetPointerProperty(ctx, 0, "_ptr");
|
||||
duk_push_this(ctx); // [var]
|
||||
duk_dup(ctx, 0); // [var][var]
|
||||
duk_put_prop_string(ctx, -2, "\xFF_ref");
|
||||
}
|
||||
else
|
||||
{
|
||||
return(ILibDuktape_Error(ctx, "Invalid Parameter"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -292,6 +318,18 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_SetEx(duk_context *ctx)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
duk_ret_t ILibDuktape_GenericMarshal_Variable_toBuffer(duk_context *ctx)
|
||||
{
|
||||
duk_push_this(ctx); // [variable]
|
||||
|
||||
void *buffer = Duktape_GetPointerProperty(ctx, -1, "_ptr");
|
||||
int bufferLen = Duktape_GetIntPropertyValue(ctx, -1, "_size", 0);
|
||||
|
||||
duk_push_external_buffer(ctx); // [variable][ext]
|
||||
duk_config_buffer(ctx, -1, buffer, (duk_size_t)bufferLen);
|
||||
duk_push_buffer_object(ctx, -1, 0, (duk_size_t)bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
|
||||
return(1);
|
||||
}
|
||||
void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int size)
|
||||
{
|
||||
duk_push_object(ctx); // [var]
|
||||
@@ -299,7 +337,8 @@ void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int s
|
||||
duk_put_prop_string(ctx, -2, "_ptr"); // [var]
|
||||
duk_push_int(ctx, size); // [var][size]
|
||||
duk_put_prop_string(ctx, -2, "_size"); // [var]
|
||||
|
||||
duk_push_true(ctx);
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_GenericMarshal_VariableType);
|
||||
|
||||
ILibDuktape_CreateEventWithGetterAndSetterEx(ctx, "Val", ILibDuktape_GenericMarshal_Variable_Val_GET, ILibDuktape_GenericMarshal_Variable_Val_SET);
|
||||
ILibDuktape_CreateEventWithGetterAndSetterWithIntMetaData(ctx, "_VarSize", 4, "IntVal", ILibDuktape_GenericMarshal_Variable_GetEx, ILibDuktape_GenericMarshal_Variable_SetEx);
|
||||
@@ -310,6 +349,8 @@ void ILibDuktape_GenericMarshal_Variable_PUSH(duk_context *ctx, void *ptr, int s
|
||||
ILibDuktape_CreateEventWithGetter(ctx, "AnsiString", ILibDuktape_GenericMarshal_Variable_Val_ASTRING);
|
||||
ILibDuktape_CreateEventWithGetter(ctx, "HexString", ILibDuktape_GenericMarshal_Variable_Val_HSTRING);
|
||||
ILibDuktape_CreateEventWithGetter(ctx, "HexString2", ILibDuktape_GenericMarshal_Variable_Val_HSTRING2);
|
||||
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "toBuffer", ILibDuktape_GenericMarshal_Variable_toBuffer, 0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_GenericMarshal_Variable_Finalizer(duk_context *ctx)
|
||||
{
|
||||
@@ -330,9 +371,30 @@ duk_ret_t ILibDuktape_GenericMarshal_Variable_Finalizer(duk_context *ctx)
|
||||
duk_ret_t ILibDuktape_GenericMarshal_CreateVariable(duk_context *ctx)
|
||||
{
|
||||
char* ptr;
|
||||
int size = duk_require_int(ctx, 0);
|
||||
int size;
|
||||
char *str = NULL;
|
||||
duk_size_t strLen;
|
||||
|
||||
if (duk_is_number(ctx, 0))
|
||||
{
|
||||
size = duk_require_int(ctx, 0);
|
||||
}
|
||||
else if(duk_is_string(ctx, 0))
|
||||
{
|
||||
str = Duktape_GetBuffer(ctx, 0, &strLen);
|
||||
size = (int)strLen + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return(ILibDuktape_Error(ctx, "_GenericMarshal.CreateVariable(): Invalid Parameter"));
|
||||
}
|
||||
|
||||
ptr = (char*)ILibMemory_Allocate(size, 0, NULL, NULL);
|
||||
if (str != NULL)
|
||||
{
|
||||
memcpy_s(ptr, size, str, strLen);
|
||||
ptr[strLen] = 0;
|
||||
}
|
||||
ILibDuktape_GenericMarshal_Variable_PUSH(ctx, ptr, size); // [var]
|
||||
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_GenericMarshal_Variable_Finalizer);
|
||||
|
||||
@@ -567,8 +629,9 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx)
|
||||
void *fptr = NULL;
|
||||
int parms = duk_get_top(ctx);
|
||||
int i;
|
||||
PTRSIZE vars[10];
|
||||
int retVal = -1;
|
||||
if (parms > 20) { return(ILibDuktape_Error(ctx, "Too many parameters")); }
|
||||
PTRSIZE *vars = ILibMemory_AllocateA(sizeof(PTRSIZE)*parms);
|
||||
|
||||
duk_push_current_function(ctx); // [func]
|
||||
duk_get_prop_string(ctx, -1, "_address"); // [func][addr]
|
||||
@@ -639,6 +702,36 @@ duk_ret_t ILibDuktape_GenericMarshal_MethodInvoke(duk_context *ctx)
|
||||
case 10:
|
||||
retVal = (int)((R10)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9]);
|
||||
break;
|
||||
case 11:
|
||||
retVal = (int)((R11)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10]);
|
||||
break;
|
||||
case 12:
|
||||
retVal = (int)((R12)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11]);
|
||||
break;
|
||||
case 13:
|
||||
retVal = (int)((R13)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12]);
|
||||
break;
|
||||
case 14:
|
||||
retVal = (int)((R14)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13]);
|
||||
break;
|
||||
case 15:
|
||||
retVal = (int)((R15)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14]);
|
||||
break;
|
||||
case 16:
|
||||
retVal = (int)((R16)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15]);
|
||||
break;
|
||||
case 17:
|
||||
retVal = (int)((R17)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16]);
|
||||
break;
|
||||
case 18:
|
||||
retVal = (int)((R18)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16], vars[17]);
|
||||
break;
|
||||
case 19:
|
||||
retVal = (int)((R19)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16], vars[17], vars[18]);
|
||||
break;
|
||||
case 20:
|
||||
retVal = (int)((R20)fptr)(vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7], vars[8], vars[9], vars[10], vars[11], vars[12], vars[13], vars[14], vars[15], vars[16], vars[17], vars[18], vars[19]);
|
||||
break;
|
||||
default:
|
||||
duk_push_string(ctx, "INVALID NUMBER OF PARAMETERS, MAX of 10");
|
||||
duk_throw(ctx);
|
||||
@@ -726,6 +819,7 @@ duk_ret_t ILibDuktape_GenericMarshal_CreateVariableEx(duk_context *ctx)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ILibDuktape_GenericMarshal_Push(duk_context *ctx, void *chain)
|
||||
{
|
||||
duk_push_object(ctx); // [obj]
|
||||
|
||||
1023
microscript/ILibDuktape_HECI.c
Normal file
1023
microscript/ILibDuktape_HECI.c
Normal file
File diff suppressed because it is too large
Load Diff
9
microscript/ILibDuktape_HECI.h
Normal file
9
microscript/ILibDuktape_HECI.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef __DUKTAPEHECI__
|
||||
#define __DUKTAPEHECI__
|
||||
|
||||
#include "duktape.h"
|
||||
|
||||
void ILibDuktape_HECI_Init(duk_context *ctx);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -245,6 +245,15 @@ void ILibDuktape_CreateEventWithGetter(duk_context *ctx, char *propName, duk_c_f
|
||||
duk_push_c_function(ctx, getterMethod, 1); // [obj][prop][getFunc]
|
||||
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
|
||||
}
|
||||
void ILibDuktape_CreateEventWithGetterAndCustomProperty(duk_context *ctx, char *customPropName, char *propName, duk_c_function getterMethod)
|
||||
{
|
||||
duk_push_string(ctx, propName); // [obj][customProp][prop]
|
||||
duk_push_c_function(ctx, getterMethod, 1); // [obj][customProp][prop][getFunc]
|
||||
duk_dup(ctx, -3); // [obj][customProp][prop][getFunc][customProp]
|
||||
duk_put_prop_string(ctx, -2, customPropName); // [obj][customProp][prop][getFunc]
|
||||
duk_remove(ctx, -3); // [obj][prop][getFunc]
|
||||
duk_def_prop(ctx, -3, DUK_DEFPROP_FORCE | DUK_DEFPROP_HAVE_GETTER); // [obj]
|
||||
}
|
||||
|
||||
void ILibDuktape_CreateEventWithGetterAndSetterEx(duk_context *ctx, char *propName, duk_c_function getterMethod, duk_c_function setterMethod)
|
||||
{
|
||||
@@ -597,3 +606,127 @@ void *ILibDuktape_Memory_Alloc(duk_context *ctx, duk_size_t size)
|
||||
|
||||
return(retVal);
|
||||
}
|
||||
void *ILibDuktape_Memory_AllocEx(duk_context *ctx, duk_idx_t index, duk_size_t size)
|
||||
{
|
||||
char *retVal = NULL;
|
||||
|
||||
duk_dup(ctx, index); // [object]
|
||||
ILibDuktape_Push_ObjectStash(ctx); // [object][stash]
|
||||
duk_push_fixed_buffer(ctx, size); // [object][stash][buffer]
|
||||
retVal = (char*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(retVal)); // [object][stash]
|
||||
duk_pop_2(ctx); // ...
|
||||
return(retVal);
|
||||
}
|
||||
void ILibDuktape_ValidatePointer(void *chain, void *ptr)
|
||||
{
|
||||
ILibHashtable_Put(ILibChain_GetBaseHashtable(chain), ptr, NULL, 0, (void*)0xFFFF);
|
||||
}
|
||||
void ILibDuktape_InValidatePointer(void *chain, void *ptr)
|
||||
{
|
||||
ILibHashtable_Remove(ILibChain_GetBaseHashtable(chain), ptr, NULL, 0);
|
||||
}
|
||||
int ILibDuktape_IsPointerValid(void *chain, void *ptr)
|
||||
{
|
||||
return(ILibHashtable_Get(ILibChain_GetBaseHashtable(chain), ptr, NULL, 0) == NULL ? 0 : 1);
|
||||
}
|
||||
void ILibDuktape_PointerValidation_Finalizer(duk_context *ctx, void *obj)
|
||||
{
|
||||
void *chain = Duktape_GetChain(ctx);
|
||||
ILibDuktape_InValidatePointer(chain, obj);
|
||||
}
|
||||
void ILibDuktape_PointerValidation_Init(duk_context *ctx)
|
||||
{
|
||||
void *chain = Duktape_GetChain(ctx);
|
||||
if (!ILibDuktape_IsPointerValid(chain, duk_get_heapptr(ctx, -1)))
|
||||
{
|
||||
// Not set up yet, so set it up
|
||||
ILibDuktape_ValidatePointer(chain, duk_get_heapptr(ctx, -1));
|
||||
ILibDuktape_CreateIndependentFinalizer(ctx, ILibDuktape_PointerValidation_Finalizer);
|
||||
}
|
||||
}
|
||||
duk_ret_t ILibDuktape_Immediate_Sink(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_ImmediateHandler userCallback = (ILibDuktape_ImmediateHandler)duk_get_pointer(ctx, 0);
|
||||
void **args = NULL;
|
||||
int argsLen, i;
|
||||
|
||||
duk_push_this(ctx); // [immediate]
|
||||
duk_dup(ctx, 1); // [immediate][array]
|
||||
if ((argsLen = (int)duk_get_length(ctx, -1)) > 0)
|
||||
{
|
||||
args = ILibMemory_AllocateA(sizeof(void*)*argsLen);
|
||||
for (i = 0; i < argsLen; ++i)
|
||||
{
|
||||
duk_get_prop_index(ctx, -1, i); // [immediate][array][arg]
|
||||
args[i] = duk_get_pointer(ctx, -1);
|
||||
duk_pop(ctx); // [immediate][array]
|
||||
}
|
||||
}
|
||||
|
||||
duk_push_heap_stash(ctx); // [immediate][array][stash]
|
||||
duk_del_prop_string(ctx, -1, Duktape_GetStashKey(duk_get_heapptr(ctx, -3)));
|
||||
|
||||
if (userCallback != NULL) { userCallback(ctx, args, argsLen); }
|
||||
return(0);
|
||||
}
|
||||
void ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDuktape_ImmediateHandler callback)
|
||||
{
|
||||
int i = 0;
|
||||
duk_push_global_object(ctx); // [g]
|
||||
duk_get_prop_string(ctx, -1, "setImmediate"); // [g][setImmediate]
|
||||
duk_swap_top(ctx, -2); // [setImmediate][this]
|
||||
duk_push_c_function(ctx, ILibDuktape_Immediate_Sink, DUK_VARARGS); // [setImmediate][this][func]
|
||||
duk_push_pointer(ctx, callback); // [setImmediate][this][func][userFunc]
|
||||
duk_push_array(ctx); // [setImmediate][this][func][userFunc][array]
|
||||
|
||||
while (args[i] != NULL && i < argsLen)
|
||||
{
|
||||
duk_get_prop_string(ctx, -1, "push"); // [setImmediate][this][func][userFunc][array][push]
|
||||
duk_dup(ctx, -2); // [setImmediate][this][func][userFunc][array][push][this]
|
||||
duk_push_pointer(ctx, args[i]); // [setImmediate][this][func][userFunc][array][push][this][val]
|
||||
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Immediate => Array.push(): "); }
|
||||
duk_pop(ctx); // [setImmediate][this][func][userFunc][array]
|
||||
++i;
|
||||
}
|
||||
|
||||
if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ILibDuktape_Immediate => immediate(): "); duk_pop(ctx); return; }
|
||||
|
||||
// [immediate]
|
||||
duk_push_heap_stash(ctx); // [immediate][stash]
|
||||
duk_swap_top(ctx, -2); // [stash][immediate]
|
||||
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1)));// [stash]
|
||||
duk_pop(ctx); // ...
|
||||
}
|
||||
void ILibDuktape_CreateInstanceMethodWithProperties(duk_context *ctx, char *funcName, duk_c_function funcImpl, duk_idx_t numArgs, unsigned int propertyCount, ...)
|
||||
{
|
||||
unsigned int i;
|
||||
char *name;
|
||||
duk_idx_t valueIndex;
|
||||
|
||||
duk_push_c_function(ctx, funcImpl, numArgs); // [func]
|
||||
|
||||
va_list vlist;
|
||||
va_start(vlist, propertyCount);
|
||||
for (i = 0; i < propertyCount; ++i)
|
||||
{
|
||||
name = va_arg(vlist, char*);
|
||||
valueIndex = va_arg(vlist, duk_idx_t);
|
||||
|
||||
duk_dup(ctx, valueIndex); // [func][value]
|
||||
duk_put_prop_string(ctx, -2, name); // [func]
|
||||
}
|
||||
va_end(vlist);
|
||||
|
||||
while (propertyCount-- > 0) { duk_remove(ctx, -2); }
|
||||
|
||||
duk_put_prop_string(ctx, -2, funcName);
|
||||
}
|
||||
duk_idx_t duk_push_int_ex(duk_context *ctx, duk_int_t val)
|
||||
{
|
||||
return(duk_push_int(ctx, val), duk_get_top_index(ctx));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,10 @@ typedef void(*ILibDuktape_HelperEvent)(duk_context *ctx, void *user);
|
||||
#define ILibDuktape_MeshAgent_Cert_Server "\xFF_selftlscert"
|
||||
#define CONTEXT_GUID_BUFFER "_CONTEXT_GUID"
|
||||
#define ILibDuktape_Context_Chain "\xFF_chainptr"
|
||||
#define ILibDuktape_OBJID "_ObjectID"
|
||||
|
||||
#define ILibDuktape_CR2HTTP "\xFF_CR2HTTP"
|
||||
#define ILibDuktape_CR2Options "\xFF_CR2Options"
|
||||
|
||||
char* Duktape_GetContextGuidHex(duk_context *ctx);
|
||||
void *Duktape_GetChain(duk_context *ctx);
|
||||
@@ -62,6 +66,7 @@ int ILibDuktape_Process_GetExitCode(duk_context *ctx);
|
||||
|
||||
void ILibDuktape_CreateEventWithGetter(duk_context *ctx, char *propName, duk_c_function getterMethod);
|
||||
void ILibDuktape_CreateEventWithGetterEx(duk_context *ctx, char *propName, void *heapptr);
|
||||
void ILibDuktape_CreateEventWithGetterAndCustomProperty(duk_context *ctx, char *customPropName, char *propName, duk_c_function getterMethod);
|
||||
void ILibDuktape_CreateEventWithSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr);
|
||||
void ILibDuktape_CreateEventWithSetterEx(duk_context *ctx, char *propName, duk_c_function setterMethod);
|
||||
void ILibDuktape_CreateEventWithGetterAndSetter(duk_context *ctx, char *propName, char *propNamePtr, void **hptr, duk_c_function getterMethod);
|
||||
@@ -74,6 +79,9 @@ void ILibDuktape_CreateEventWithGetterAndSetterWithMetaData(duk_context *ctx, ch
|
||||
#define ILibDuktape_CreateInstanceMethodWithBooleanProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_boolean(context, propValue);duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
|
||||
#define ILibDuktape_CreateInstanceMethodWithIntProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_int(context, propValue);duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
|
||||
#define ILibDuktape_CreateInstanceMethodWithNumberProperty(context, propName, propValue, methodName, funcImpl, numArgs) duk_push_c_function(context, funcImpl, numArgs);duk_push_number(context, (propValue));duk_put_prop_string(ctx, -2, propName);duk_put_prop_string(ctx, -2, methodName);
|
||||
void ILibDuktape_CreateInstanceMethodWithProperties(duk_context *ctx, char *funcName, duk_c_function funcImpl, duk_idx_t numArgs, unsigned int propertyCount, ...);
|
||||
duk_idx_t duk_push_int_ex(duk_context *ctx, duk_int_t val);
|
||||
|
||||
void ILibDuktape_CreateProperty_InstanceMethod(duk_context *ctx, char *methodName, duk_c_function impl, duk_idx_t argCount);
|
||||
void ILibDuktape_CreateProperty_InstanceMethodEx(duk_context *ctx, char *methodName, void *funcHeapPtr);
|
||||
void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName);
|
||||
@@ -81,8 +89,21 @@ void ILibDuktape_CreateReadonlyProperty(duk_context *ctx, char *propName);
|
||||
#define ILibDuktape_CreateFinalizer(context, funcImpl) duk_push_c_function(context, funcImpl, 1); duk_set_finalizer(context, -2);
|
||||
|
||||
void *ILibDuktape_Memory_Alloc(duk_context *ctx, duk_size_t size);
|
||||
void *ILibDuktape_Memory_AllocEx(duk_context *ctx, duk_idx_t index, duk_size_t size);
|
||||
void ILibDuktape_Helper_AddHeapFinalizer(duk_context *ctx, ILibDuktape_HelperEvent handler, void *user);
|
||||
|
||||
void ILibDuktape_Push_ObjectStash(duk_context *ctx);
|
||||
|
||||
void ILibDuktape_PointerValidation_Init(duk_context *ctx);
|
||||
void ILibDuktape_ValidatePointer(void *chain, void *ptr);
|
||||
void ILibDuktape_InValidatePointer(void *chain, void *ptr);
|
||||
int ILibDuktape_IsPointerValid(void *chain, void *ptr);
|
||||
#define ILibDuktape_ValidateHeapPointer(ctx, objIdx) ILibDuktape_ValidatePointer(Duktape_GetChain(ctx), duk_get_heapptr(ctx, objIdx))
|
||||
#define ILibDuktape_InValidateHeapPointer(ctx, objIdx) ILibDuktape_InValidatePointer(Duktape_GetChain(ctx), duk_get_heapptr(ctx, objIdx))
|
||||
|
||||
typedef void(*ILibDuktape_ImmediateHandler)(duk_context *ctx, void ** args, int argsLen);
|
||||
void ILibDuktape_Immediate(duk_context *ctx, void ** args, int argsLen, ILibDuktape_ImmediateHandler callback);
|
||||
|
||||
#define ILibDuktape_WriteID(ctx, id) duk_push_string(ctx, id);duk_put_prop_string(ctx, -2, ILibDuktape_OBJID)
|
||||
|
||||
#endif
|
||||
3614
microscript/ILibDuktape_HttpStream.c
Normal file
3614
microscript/ILibDuktape_HttpStream.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -81,6 +81,7 @@ duk_ret_t ILibDuktape_MemoryStream_buffer(duk_context *ctx)
|
||||
|
||||
duk_push_external_buffer(ctx);
|
||||
duk_config_buffer(ctx, -1, ms->buffer, ms->bufferLen);
|
||||
duk_push_buffer_object(ctx, -1, 0, ms->bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
|
||||
|
||||
return(1);
|
||||
}
|
||||
@@ -93,6 +94,43 @@ duk_ret_t ILibDuktape_MemoryStream_Finalizer(duk_context *ctx)
|
||||
return(0);
|
||||
}
|
||||
|
||||
duk_ret_t ILibDuktape_MemoryStream_writeBE(duk_context *ctx)
|
||||
{
|
||||
duk_push_current_function(ctx);
|
||||
int size = Duktape_GetIntPropertyValue(ctx, -1, "size", 0);
|
||||
char buffer[16];
|
||||
int value = duk_require_int(ctx, 0);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
buffer[0] = (char)value;
|
||||
break;
|
||||
case 2:
|
||||
((unsigned short*)buffer)[0] = htons((unsigned short)value);
|
||||
break;
|
||||
case 4:
|
||||
((unsigned int*)buffer)[0] = htonl((unsigned int)value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
duk_push_this(ctx); // [ms]
|
||||
duk_get_prop_string(ctx, -1, "write"); // [ms][write]
|
||||
duk_swap_top(ctx, -2); // [write][this]
|
||||
duk_push_external_buffer(ctx); // [write][this][buffer]
|
||||
duk_config_buffer(ctx, -1, buffer, size);
|
||||
duk_call_method(ctx, 1); // [retVal]
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(ILibDuktape_Error(ctx, "MemoryStream.writeBE() Unknown Error"));
|
||||
}
|
||||
}
|
||||
duk_ret_t ILibDuktape_MemoryStream_new(duk_context *ctx)
|
||||
{
|
||||
int initial = duk_get_top(ctx) > 0 ? duk_require_int(ctx, 0) : 4096;
|
||||
@@ -110,6 +148,11 @@ duk_ret_t ILibDuktape_MemoryStream_new(duk_context *ctx)
|
||||
ms->s = ILibDuktape_DuplexStream_Init(ctx, ILibDuktape_MemoryStream_OnWrite, ILibDuktape_MemoryStream_OnEnd, NULL, NULL, ms);
|
||||
ILibDuktape_CreateEventWithGetter(ctx, "buffer", ILibDuktape_MemoryStream_buffer);
|
||||
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_MemoryStream_Finalizer);
|
||||
|
||||
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "size", 4, "writeUInt32BE", ILibDuktape_MemoryStream_writeBE, 1);
|
||||
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "size", 2, "writeUInt16BE", ILibDuktape_MemoryStream_writeBE, 1);
|
||||
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "size", 1, "writeUInt8", ILibDuktape_MemoryStream_writeBE, 1);
|
||||
|
||||
return(1);
|
||||
}
|
||||
void ILibDuktape_MemoryStream_PUSH(duk_context *ctx, void *chain)
|
||||
|
||||
@@ -108,14 +108,14 @@ void ILibDuktape_NetworkMonitor_EventSink(ILibIPAddressMonitor sender, void *use
|
||||
}
|
||||
duk_ret_t ILibDuktape_NetworkMonitor_Finalizer(duk_context *ctx)
|
||||
{
|
||||
if (ILibIsChainBeingDestroyed(Duktape_GetChain(ctx)) != 0) { return(0); }
|
||||
duk_get_prop_string(ctx, 0, ILibDuktape_NetworkMonitor_PTR);
|
||||
|
||||
ILibDuktape_NetworkMonitor *nm = (ILibDuktape_NetworkMonitor*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
ILibChain_SafeRemoveEx(Duktape_GetChain(ctx), nm->addressMonitor);
|
||||
|
||||
if (nm->addressTable != NULL) { ILibHashtable_Destroy(nm->addressTable); }
|
||||
|
||||
if (ILibIsChainBeingDestroyed(Duktape_GetChain(ctx)) != 0) { return(0); }
|
||||
ILibChain_SafeRemoveEx(Duktape_GetChain(ctx), nm->addressMonitor);
|
||||
|
||||
return(0);
|
||||
}
|
||||
void ILibDuktape_NetworkMonitor_PUSH(duk_context *ctx, void *chain)
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
#include "duktape.h"
|
||||
#include "ILibDuktape_Helpers.h"
|
||||
#include "ILibDuktapeModSearch.h"
|
||||
#include "ILibDuktape_DuplexStream.h"
|
||||
#include "ILibDuktape_EventEmitter.h"
|
||||
#include "../microstack/ILibParsers.h"
|
||||
#include "../microstack/ILibCrypto.h"
|
||||
|
||||
|
||||
#define ILibDuktape_Timer_Ptrs "\xFF_DuktapeTimer_PTRS"
|
||||
#define ILibDuktape_Queue_Ptr "\xFF_Queue"
|
||||
|
||||
|
||||
duk_ret_t ILibDuktape_Pollyfills_Buffer_slice(duk_context *ctx)
|
||||
{
|
||||
@@ -63,6 +67,13 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_toString(duk_context *ctx)
|
||||
util_tohex(buffer, (int)bufferLen, tmpBuffer);
|
||||
duk_push_string(ctx, tmpBuffer);
|
||||
}
|
||||
else if (strcmp(cType, "hex:") == 0)
|
||||
{
|
||||
duk_push_fixed_buffer(ctx, 1 + (bufferLen * 3));
|
||||
tmpBuffer = Duktape_GetBuffer(ctx, -1, NULL);
|
||||
util_tohex2(buffer, (int)bufferLen, tmpBuffer);
|
||||
duk_push_string(ctx, tmpBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_push_string(ctx, "buffer.toString(): Unrecognized parameter");
|
||||
@@ -84,11 +95,10 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_from(duk_context *ctx)
|
||||
if (nargs == 1)
|
||||
{
|
||||
str = (char*)duk_get_lstring(ctx, 0, &strlength);
|
||||
duk_push_fixed_buffer(ctx, strlength + 1);
|
||||
duk_push_fixed_buffer(ctx, strlength);
|
||||
buffer = Duktape_GetBuffer(ctx, -1, NULL);
|
||||
memcpy_s(buffer, strlength + 1, str, strlength);
|
||||
buffer[strlength] = 0;
|
||||
duk_push_buffer_object(ctx, -1, 0, strlength+1, DUK_BUFOBJ_ARRAYBUFFER);
|
||||
memcpy_s(buffer, strlength, str, strlength);
|
||||
duk_push_buffer_object(ctx, -1, 0, strlength, DUK_BUFOBJ_NODEJS_BUFFER);
|
||||
return(1);
|
||||
}
|
||||
else if(!(nargs == 2 && duk_is_string(ctx, 0) && duk_is_string(ctx, 1)))
|
||||
@@ -107,14 +117,14 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_from(duk_context *ctx)
|
||||
duk_push_fixed_buffer(ctx, ILibBase64DecodeLength((int)strlength));
|
||||
buffer = Duktape_GetBuffer(ctx, -1, NULL);
|
||||
bufferLen = ILibBase64Decode((unsigned char*)str, (int)strlength, (unsigned char**)&buffer);
|
||||
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_ARRAYBUFFER);
|
||||
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
|
||||
}
|
||||
else if (strcmp(encoding, "hex") == 0)
|
||||
{
|
||||
duk_push_fixed_buffer(ctx, strlength / 2);
|
||||
buffer = Duktape_GetBuffer(ctx, -1, NULL);
|
||||
bufferLen = util_hexToBuf(str, (int)strlength, buffer);
|
||||
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_ARRAYBUFFER);
|
||||
duk_push_buffer_object(ctx, -1, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -136,31 +146,55 @@ duk_ret_t ILibDuktape_Polyfills_Buffer_readInt32BE(duk_context *ctx)
|
||||
duk_push_int(ctx, ntohl(((int*)(buffer + offset))[0]));
|
||||
return(1);
|
||||
}
|
||||
duk_ret_t ILibDuktape_Polyfills_Buffer_alloc(duk_context *ctx)
|
||||
{
|
||||
int sz = duk_require_int(ctx, 0);
|
||||
duk_push_fixed_buffer(ctx, sz);
|
||||
char *buffer = Duktape_GetBuffer(ctx, -1, NULL);
|
||||
memset(buffer, 0, sz);
|
||||
duk_push_buffer_object(ctx, -1, 0, sz, DUK_BUFOBJ_NODEJS_BUFFER);
|
||||
return(1);
|
||||
}
|
||||
void ILibDuktape_Polyfills_Buffer(duk_context *ctx)
|
||||
{
|
||||
// Polyfill 'Buffer.slice'
|
||||
duk_get_prop_string(ctx, -1, "Duktape"); // [g][Duktape]
|
||||
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Duktape][Buffer]
|
||||
duk_get_prop_string(ctx, -1, "prototype"); // [g][Duktape][Buffer][prototype]
|
||||
duk_push_c_function(ctx, ILibDuktape_Pollyfills_Buffer_slice, DUK_VARARGS); // [g][Duktape][Buffer][prototype][func]
|
||||
duk_put_prop_string(ctx, -2, "slice"); // [g][Duktape][Buffer][prototype]
|
||||
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_readInt32BE, DUK_VARARGS);
|
||||
duk_put_prop_string(ctx, -2, "readInt32BE");
|
||||
duk_pop_3(ctx); // [g]
|
||||
duk_get_prop_string(ctx, -1, "Duktape"); // [g][Duktape]
|
||||
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Duktape][Buffer]
|
||||
duk_get_prop_string(ctx, -1, "prototype"); // [g][Duktape][Buffer][prototype]
|
||||
duk_push_c_function(ctx, ILibDuktape_Pollyfills_Buffer_slice, DUK_VARARGS); // [g][Duktape][Buffer][prototype][func]
|
||||
duk_put_prop_string(ctx, -2, "slice"); // [g][Duktape][Buffer][prototype]
|
||||
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_readInt32BE, DUK_VARARGS);// [g][Duktape][Buffer][prototype][func]
|
||||
duk_put_prop_string(ctx, -2, "readInt32BE"); // [g][Duktape][Buffer][prototype]
|
||||
duk_pop_3(ctx); // [g]
|
||||
|
||||
// Polyfill 'Buffer.toString()
|
||||
duk_get_prop_string(ctx, -1, "Duktape"); // [g][Duktape]
|
||||
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Duktape][Buffer]
|
||||
duk_get_prop_string(ctx, -1, "prototype"); // [g][Duktape][Buffer][prototype]
|
||||
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_toString, DUK_VARARGS);// [g][Duktape][Buffer][prototype][func]
|
||||
duk_put_prop_string(ctx, -2, "toString"); // [g][Duktape][Buffer][prototype]
|
||||
duk_pop_3(ctx); // [g]
|
||||
|
||||
duk_get_prop_string(ctx, -1, "Duktape"); // [g][Duktape]
|
||||
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Duktape][Buffer]
|
||||
duk_get_prop_string(ctx, -1, "prototype"); // [g][Duktape][Buffer][prototype]
|
||||
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_toString, DUK_VARARGS); // [g][Duktape][Buffer][prototype][func]
|
||||
duk_put_prop_string(ctx, -2, "toString"); // [g][Duktape][Buffer][prototype]
|
||||
duk_pop_3(ctx); // [g]
|
||||
|
||||
// Polyfill Buffer.from()
|
||||
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
|
||||
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_from, DUK_VARARGS); // [g][Buffer][func]
|
||||
duk_put_prop_string(ctx, -2, "from"); // [g][Buffer]
|
||||
duk_pop(ctx);
|
||||
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
|
||||
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_from, DUK_VARARGS); // [g][Buffer][func]
|
||||
duk_put_prop_string(ctx, -2, "from"); // [g][Buffer]
|
||||
duk_pop(ctx); // [g]
|
||||
|
||||
// Polyfill Buffer.alloc() for Node Buffers)
|
||||
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
|
||||
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_alloc, DUK_VARARGS); // [g][Buffer][func]
|
||||
duk_put_prop_string(ctx, -2, "alloc"); // [g][Buffer]
|
||||
duk_pop(ctx); // [g]
|
||||
|
||||
|
||||
// Polyfill Buffer.toString() for Node Buffers
|
||||
duk_get_prop_string(ctx, -1, "Buffer"); // [g][Buffer]
|
||||
duk_get_prop_string(ctx, -1, "prototype"); // [g][Buffer][prototype]
|
||||
duk_push_c_function(ctx, ILibDuktape_Polyfills_Buffer_toString, DUK_VARARGS); // [g][Buffer][prototype][func]
|
||||
duk_put_prop_string(ctx, -2, "toString"); // [g][Buffer][prototype]
|
||||
duk_pop_2(ctx); // [g]
|
||||
|
||||
}
|
||||
duk_ret_t ILibDuktape_Polyfills_String_startsWith(duk_context *ctx)
|
||||
{
|
||||
@@ -379,6 +413,7 @@ void ILibDuktape_Polyfills_timer_elapsed(void *obj)
|
||||
{
|
||||
ILibDuktape_Timer *ptrs = (ILibDuktape_Timer*)obj;
|
||||
int argCount, i;
|
||||
duk_context *ctx = ptrs->ctx;
|
||||
|
||||
if (ptrs->timerType == ILibDuktape_Timer_Type_INTERVAL)
|
||||
{
|
||||
@@ -397,7 +432,7 @@ void ILibDuktape_Polyfills_timer_elapsed(void *obj)
|
||||
}
|
||||
duk_pop(ptrs->ctx); // [func][this][...arg...]
|
||||
if (duk_pcall_method(ptrs->ctx, argCount) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ptrs->ctx, "timers.onElapsed() callback handler"); }
|
||||
duk_pop(ptrs->ctx); // ...
|
||||
duk_pop(ctx); // ...
|
||||
}
|
||||
duk_ret_t ILibDuktape_Polyfills_timer_set(duk_context *ctx)
|
||||
{
|
||||
@@ -490,8 +525,245 @@ duk_ret_t ILibDuktape_Polyfills_addModule(duk_context *ctx)
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_Queue_Finalizer(duk_context *ctx)
|
||||
{
|
||||
duk_get_prop_string(ctx, 0, ILibDuktape_Queue_Ptr);
|
||||
ILibQueue_Destroy((ILibQueue)duk_get_pointer(ctx, -1));
|
||||
return(0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_Queue_EnQueue(duk_context *ctx)
|
||||
{
|
||||
ILibQueue Q;
|
||||
int i;
|
||||
int nargs = duk_get_top(ctx);
|
||||
duk_push_this(ctx); // [queue]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_Queue_Ptr); // [queue][ptr]
|
||||
Q = (ILibQueue)duk_get_pointer(ctx, -1);
|
||||
duk_pop(ctx); // [queue]
|
||||
|
||||
ILibDuktape_Push_ObjectStash(ctx); // [queue][stash]
|
||||
duk_push_array(ctx); // [queue][stash][array]
|
||||
for (i = 0; i < nargs; ++i)
|
||||
{
|
||||
duk_dup(ctx, i); // [queue][stash][array][arg]
|
||||
duk_put_prop_index(ctx, -2, i); // [queue][stash][array]
|
||||
}
|
||||
ILibQueue_EnQueue(Q, duk_get_heapptr(ctx, -1));
|
||||
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [queue][stash]
|
||||
return(0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_Queue_DeQueue(duk_context *ctx)
|
||||
{
|
||||
duk_push_current_function(ctx);
|
||||
duk_get_prop_string(ctx, -1, "peek");
|
||||
int peek = duk_get_int(ctx, -1);
|
||||
|
||||
duk_push_this(ctx); // [Q]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_Queue_Ptr); // [Q][ptr]
|
||||
ILibQueue Q = (ILibQueue)duk_get_pointer(ctx, -1);
|
||||
void *h = peek == 0 ? ILibQueue_DeQueue(Q) : ILibQueue_PeekQueue(Q);
|
||||
if (h == NULL) { return(ILibDuktape_Error(ctx, "Queue is empty")); }
|
||||
duk_pop(ctx); // [Q]
|
||||
ILibDuktape_Push_ObjectStash(ctx); // [Q][stash]
|
||||
duk_push_heapptr(ctx, h); // [Q][stash][array]
|
||||
int length = (int)duk_get_length(ctx, -1);
|
||||
int i;
|
||||
for (i = 0; i < length; ++i)
|
||||
{
|
||||
duk_get_prop_index(ctx, -i - 1, i); // [Q][stash][array][args]
|
||||
}
|
||||
if (peek == 0) { duk_del_prop_string(ctx, -length - 2, Duktape_GetStashKey(h)); }
|
||||
return(length);
|
||||
}
|
||||
|
||||
duk_ret_t ILibDuktape_Queue_new(duk_context *ctx)
|
||||
{
|
||||
duk_push_object(ctx); // [queue]
|
||||
duk_push_pointer(ctx, ILibQueue_Create()); // [queue][ptr]
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_Queue_Ptr); // [queue]
|
||||
|
||||
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_Queue_Finalizer);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "enQueue", ILibDuktape_Queue_EnQueue, DUK_VARARGS);
|
||||
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "peek", 0, "deQueue", ILibDuktape_Queue_DeQueue, DUK_VARARGS);
|
||||
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "peek", 1, "peekQueue", ILibDuktape_Queue_DeQueue, DUK_VARARGS);
|
||||
|
||||
return(1);
|
||||
}
|
||||
void ILibDuktape_Queue_Push(duk_context *ctx, void* chain)
|
||||
{
|
||||
duk_push_c_function(ctx, ILibDuktape_Queue_new, 0);
|
||||
}
|
||||
|
||||
typedef struct ILibDuktape_DynamicBuffer_data
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
int unshiftBytes;
|
||||
char *buffer;
|
||||
int bufferLen;
|
||||
}ILibDuktape_DynamicBuffer_data;
|
||||
|
||||
typedef struct ILibDuktape_DynamicBuffer_ContextSwitchData
|
||||
{
|
||||
void *chain;
|
||||
void *heapptr;
|
||||
ILibDuktape_DuplexStream *stream;
|
||||
ILibDuktape_DynamicBuffer_data *data;
|
||||
int bufferLen;
|
||||
char buffer[];
|
||||
}ILibDuktape_DynamicBuffer_ContextSwitchData;
|
||||
|
||||
ILibTransport_DoneState ILibDuktape_DynamicBuffer_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user);
|
||||
void ILibDuktape_DynamicBuffer_WriteSink_ChainThread(void *chain, void *user)
|
||||
{
|
||||
ILibDuktape_DynamicBuffer_ContextSwitchData *data = (ILibDuktape_DynamicBuffer_ContextSwitchData*)user;
|
||||
if (ILibDuktape_IsPointerValid(chain, data->heapptr) != 0)
|
||||
{
|
||||
ILibDuktape_DynamicBuffer_WriteSink(data->stream, data->buffer, data->bufferLen, data->data);
|
||||
ILibDuktape_DuplexStream_Ready(data->stream);
|
||||
}
|
||||
free(user);
|
||||
}
|
||||
ILibTransport_DoneState ILibDuktape_DynamicBuffer_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
|
||||
{
|
||||
ILibDuktape_DynamicBuffer_data *data = (ILibDuktape_DynamicBuffer_data*)user;
|
||||
if (ILibIsRunningOnChainThread(stream->readableStream->chain) == 0)
|
||||
{
|
||||
ILibDuktape_DynamicBuffer_ContextSwitchData *tmp = (ILibDuktape_DynamicBuffer_ContextSwitchData*)ILibMemory_Allocate(sizeof(ILibDuktape_DynamicBuffer_ContextSwitchData) + bufferLen, 0, NULL, NULL);
|
||||
tmp->chain = stream->readableStream->chain;
|
||||
tmp->heapptr = stream->ParentObject;
|
||||
tmp->stream = stream;
|
||||
tmp->data = data;
|
||||
tmp->bufferLen = bufferLen;
|
||||
memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen);
|
||||
ILibChain_RunOnMicrostackThread(tmp->chain, ILibDuktape_DynamicBuffer_WriteSink_ChainThread, tmp);
|
||||
return(ILibTransport_DoneState_INCOMPLETE);
|
||||
}
|
||||
|
||||
|
||||
if ((data->bufferLen - data->start - data->end) < bufferLen)
|
||||
{
|
||||
if (data->end > 0)
|
||||
{
|
||||
// Move the buffer first
|
||||
memmove_s(data->buffer, data->bufferLen, data->buffer + data->start, data->end);
|
||||
data->start = 0;
|
||||
}
|
||||
if ((data->bufferLen - data->end) < bufferLen)
|
||||
{
|
||||
// Need to resize buffer first
|
||||
int tmpSize = data->bufferLen;
|
||||
while ((tmpSize - data->end) < bufferLen)
|
||||
{
|
||||
tmpSize += 4096;
|
||||
}
|
||||
data->buffer = (char*)realloc(data->buffer, tmpSize);
|
||||
data->bufferLen = tmpSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
memcpy_s(data->buffer + data->start + data->end, data->bufferLen - data->start - data->end, buffer, bufferLen);
|
||||
data->end += bufferLen;
|
||||
|
||||
int unshifted = 0;
|
||||
do
|
||||
{
|
||||
duk_push_heapptr(stream->readableStream->ctx, stream->ParentObject); // [ds]
|
||||
duk_get_prop_string(stream->readableStream->ctx, -1, "emit"); // [ds][emit]
|
||||
duk_swap_top(stream->readableStream->ctx, -2); // [emit][this]
|
||||
duk_push_string(stream->readableStream->ctx, "readable"); // [emit][this][readable]
|
||||
if (duk_pcall_method(stream->readableStream->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(stream->readableStream->ctx, "DynamicBuffer.WriteSink => readable(): "); }
|
||||
duk_pop(stream->readableStream->ctx); // ...
|
||||
|
||||
ILibDuktape_DuplexStream_WriteData(stream, data->buffer + data->start, data->end);
|
||||
if (data->unshiftBytes == 0)
|
||||
{
|
||||
// All the data was consumed
|
||||
data->start = data->end = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unshifted = (data->end - data->unshiftBytes);
|
||||
if (unshifted > 0)
|
||||
{
|
||||
data->start += unshifted;
|
||||
data->end = data->unshiftBytes;
|
||||
data->unshiftBytes = 0;
|
||||
}
|
||||
}
|
||||
} while (unshifted != 0);
|
||||
|
||||
return(ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
void ILibDuktape_DynamicBuffer_EndSink(ILibDuktape_DuplexStream *stream, void *user)
|
||||
{
|
||||
ILibDuktape_DuplexStream_WriteEnd(stream);
|
||||
}
|
||||
duk_ret_t ILibDuktape_DynamicBuffer_Finalizer(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_InValidateHeapPointer(ctx, 0);
|
||||
duk_get_prop_string(ctx, 0, "\xFF_buffer");
|
||||
ILibDuktape_DynamicBuffer_data *data = (ILibDuktape_DynamicBuffer_data*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
free(data->buffer);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int ILibDuktape_DynamicBuffer_unshift(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
|
||||
{
|
||||
ILibDuktape_DynamicBuffer_data *data = (ILibDuktape_DynamicBuffer_data*)user;
|
||||
data->unshiftBytes = unshiftBytes;
|
||||
return(unshiftBytes);
|
||||
}
|
||||
duk_ret_t ILibDuktape_DynamicBuffer_read(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_DynamicBuffer_data *data;
|
||||
duk_push_this(ctx); // [DynamicBuffer]
|
||||
duk_get_prop_string(ctx, -1, "\xFF_buffer"); // [DynamicBuffer][buffer]
|
||||
data = (ILibDuktape_DynamicBuffer_data*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_push_external_buffer(ctx); // [DynamicBuffer][buffer][extBuffer]
|
||||
duk_config_buffer(ctx, -1, data->buffer + data->start, data->bufferLen - (data->start + data->end));
|
||||
duk_push_buffer_object(ctx, -1, 0, data->bufferLen - (data->start + data->end), DUK_BUFOBJ_NODEJS_BUFFER);
|
||||
return(1);
|
||||
}
|
||||
duk_ret_t ILibDuktape_DynamicBuffer_new(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_DynamicBuffer_data *data;
|
||||
int initSize = 4096;
|
||||
if (duk_get_top(ctx) != 0)
|
||||
{
|
||||
initSize = duk_require_int(ctx, 0);
|
||||
}
|
||||
|
||||
duk_push_object(ctx); // [stream]
|
||||
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_DynamicBuffer_data));
|
||||
data = (ILibDuktape_DynamicBuffer_data*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
memset(data, 0, sizeof(ILibDuktape_DynamicBuffer_data));
|
||||
duk_put_prop_string(ctx, -2, "\xFF_buffer");
|
||||
|
||||
data->bufferLen = initSize;
|
||||
data->buffer = (char*)malloc(initSize);
|
||||
|
||||
ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_DynamicBuffer_WriteSink, ILibDuktape_DynamicBuffer_EndSink, NULL, NULL, ILibDuktape_DynamicBuffer_unshift, data);
|
||||
ILibDuktape_EventEmitter_CreateEventEx(ILibDuktape_EventEmitter_GetEmitter(ctx, -1), "readable");
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "read", ILibDuktape_DynamicBuffer_read, DUK_VARARGS);
|
||||
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_DynamicBuffer_Finalizer);
|
||||
ILibDuktape_ValidateHeapPointer(ctx, -1);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
void ILibDuktape_DynamicBuffer_Push(duk_context *ctx, void *chain)
|
||||
{
|
||||
duk_push_c_function(ctx, ILibDuktape_DynamicBuffer_new, DUK_VARARGS);
|
||||
}
|
||||
|
||||
|
||||
void ILibDuktape_Polyfills_Init(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_ModSearch_AddHandler(ctx, "queue", ILibDuktape_Queue_Push);
|
||||
ILibDuktape_ModSearch_AddHandler(ctx, "DynamicBuffer", ILibDuktape_DynamicBuffer_Push);
|
||||
|
||||
// Global Polyfills
|
||||
duk_push_global_object(ctx); // [g]
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ limitations under the License.
|
||||
#define ILibDuktape_readableStream_WritePipes "\xFF_WritePipes"
|
||||
#define ILibDuktape_readableStream_WritePipes_PTRBUFFER "\xFF_WritePipesPtrBuffer"
|
||||
#define ILibDuktape_readableStream_WritePipes_Stream "\xFF_WritePipes_Stream"
|
||||
#define ILibDuktape_readableStream_PipeArray "\xFF_RS_PipeArray"
|
||||
|
||||
#ifdef __DOXY__
|
||||
/*!
|
||||
@@ -124,40 +125,48 @@ void ILibDuktape_readableStream_WriteData_buffer(ILibDuktape_readableStream *str
|
||||
}
|
||||
tmp->Next = buffered;
|
||||
}
|
||||
|
||||
if (stream->paused == 0)
|
||||
{
|
||||
stream->paused = 1;
|
||||
stream->PauseHandler(stream, stream->user);
|
||||
}
|
||||
}
|
||||
void ILibDuktape_readableStream_WriteData_OnData_ChainThread(void *chain, void *user)
|
||||
{
|
||||
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
|
||||
ILibDuktape_readableStream_bufferedData *data = (ILibDuktape_readableStream_bufferedData*)user;
|
||||
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)data->Next;
|
||||
|
||||
stream->paused = 0;
|
||||
duk_push_heapptr(stream->ctx, stream->OnData); // [func]
|
||||
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
|
||||
if (stream->extBuffer_Reserved == 0)
|
||||
if (data->Reserved == 0)
|
||||
{
|
||||
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][buffer]
|
||||
duk_config_buffer(stream->ctx, -1, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
|
||||
duk_push_external_buffer(stream->ctx); // [ext]
|
||||
duk_config_buffer(stream->ctx, -1, data->buffer, data->bufferLen);
|
||||
}
|
||||
duk_push_heapptr(stream->ctx, stream->OnData); // [ext][func]
|
||||
duk_push_heapptr(stream->ctx, stream->object); // [ext][func][this]
|
||||
if (data->Reserved == 0)
|
||||
{
|
||||
duk_push_buffer_object(stream->ctx, -3, 0, data->bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [ext][func][this][buffer]
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_push_lstring(stream->ctx, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
|
||||
duk_push_lstring(stream->ctx, data->buffer, data->bufferLen); // [ext][func][this][buffer/string]
|
||||
}
|
||||
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
|
||||
if (duk_pcall_method(stream->ctx, 1) != 0) // [...][retVal]
|
||||
{
|
||||
ILibDuktape_Process_UncaughtException(stream->ctx);
|
||||
}
|
||||
duk_pop(stream->ctx); // ...
|
||||
if (data->Reserved == 0)
|
||||
{
|
||||
duk_pop_2(stream->ctx); // ...
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_pop(stream->ctx); // ...
|
||||
}
|
||||
free(data);
|
||||
if (stream->paused == 0 && stream->ResumeHandler != NULL) { stream->ResumeHandler(stream, stream->user); }
|
||||
}
|
||||
void ILibDuktape_readableStream_WriteData_Flush(struct ILibDuktape_WritableStream *ws, void *user)
|
||||
int ILibDuktape_readableStream_WriteData_Flush(struct ILibDuktape_WritableStream *ws, void *user)
|
||||
{
|
||||
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
|
||||
|
||||
int unpipeInProgress = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
if(InterlockedDecrement(&(stream->pipe_pendingCount)) == 0)
|
||||
#elif defined(__ATOMIC_SEQ_CST)
|
||||
@@ -169,243 +178,220 @@ void ILibDuktape_readableStream_WriteData_Flush(struct ILibDuktape_WritableStrea
|
||||
if(stream->pipe_pendingCount == 0)
|
||||
#endif
|
||||
{
|
||||
if (stream->ResumeHandler != NULL) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
|
||||
sem_wait(&(stream->pipeLock));
|
||||
stream->pipeInProgress = 0;
|
||||
unpipeInProgress = stream->unpipeInProgress;
|
||||
sem_post(&(stream->pipeLock));
|
||||
if (unpipeInProgress == 0 && stream->ResumeHandler != NULL && stream->paused != 0) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_readableStream_WriteData_Flush_JS(duk_context *ctx)
|
||||
|
||||
duk_ret_t ILibDuktape_readableStream_WriteDataEx_Flush(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_readableStream *stream;
|
||||
|
||||
duk_push_current_function(ctx);
|
||||
duk_get_prop_string(ctx, -1, "readable");
|
||||
stream = (ILibDuktape_readableStream*)duk_get_pointer(ctx, -1);
|
||||
duk_get_prop_string(ctx, -1, "\xFF_STREAM");
|
||||
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)duk_to_pointer(ctx, -1);
|
||||
|
||||
ILibDuktape_readableStream_WriteData_Flush(NULL, stream);
|
||||
|
||||
return 0;
|
||||
return(0);
|
||||
}
|
||||
void ILibDuktape_readableStream_WriteData_ChainThread(void *chain, void *user)
|
||||
|
||||
int ILibDuktape_readableStream_WriteDataEx_Chain_Dispatch(ILibDuktape_readableStream *stream, void *ws, char *buffer, int bufferLen)
|
||||
{
|
||||
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)user;
|
||||
ILibDuktape_readableStream_nextWriteablePipe *w;
|
||||
int jsCount = 0;
|
||||
int retVal = 0;
|
||||
duk_push_external_buffer(stream->ctx); // [ext]
|
||||
duk_config_buffer(stream->ctx, -1, buffer, bufferLen);
|
||||
duk_push_heapptr(stream->ctx, ws); // [ext][ws]
|
||||
duk_get_prop_string(stream->ctx, -1, "write"); // [ext][ws][write]
|
||||
duk_swap_top(stream->ctx, -2); // [ext][write][this]
|
||||
duk_push_buffer_object(stream->ctx, -3, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [ext][write][this][buffer]
|
||||
duk_push_c_function(stream->ctx, ILibDuktape_readableStream_WriteDataEx_Flush, DUK_VARARGS);// [ext][write][this][buffer][flush]
|
||||
duk_push_pointer(stream->ctx, stream); // [ext][write][this][buffer][flush][ptr]
|
||||
duk_put_prop_string(stream->ctx, -2, "\xFF_STREAM"); // [ext][write][this][buffer][flush]
|
||||
if (duk_pcall_method(stream->ctx, 2) != 0) // [ext][...]
|
||||
{
|
||||
ILibDuktape_Process_UncaughtExceptionEx(stream->ctx, "readable.write(): Error Piping ");
|
||||
if (ILibDuktape_readableStream_WriteData_Flush(NULL, stream)) { retVal = 2; }
|
||||
}
|
||||
retVal = duk_to_boolean(stream->ctx, -1) ? 1 : 0;
|
||||
duk_pop_2(stream->ctx);
|
||||
|
||||
sem_wait(&(stream->pipeLock));
|
||||
w = stream->nextWriteable;
|
||||
stream->pipe_pendingCount = 0;
|
||||
return(retVal);
|
||||
}
|
||||
void ILibDuktape_readableStream_WriteDataEx_Chain(void *chain, void *user)
|
||||
{
|
||||
ILibDuktape_readableStream_bufferedData *data = (ILibDuktape_readableStream_bufferedData*)user;
|
||||
ILibDuktape_readableStream *stream = (ILibDuktape_readableStream*)data->Next;
|
||||
ILibDuktape_readableStream_nextWriteablePipe *w = stream->nextWriteable;
|
||||
|
||||
while (w != NULL)
|
||||
{
|
||||
if (w->nativeWritable != NULL || w->writableStream != NULL) { stream->pipe_pendingCount++; }
|
||||
w = w->next;
|
||||
}
|
||||
|
||||
w = stream->nextWriteable;
|
||||
while (w != NULL)
|
||||
{
|
||||
if (w->nativeWritable != NULL)
|
||||
if (w->writableStream != NULL && w->nativeWritable == NULL)
|
||||
{
|
||||
ILibDuktape_WritableStream *ws = (ILibDuktape_WritableStream*)w->nativeWritable;
|
||||
switch (ws->WriteSink(ws, stream->extBuffer_buffer, stream->extBuffer_bufferLen, ws->WriteSink_User))
|
||||
{
|
||||
case ILibTransport_DoneState_INCOMPLETE:
|
||||
ws->OnWriteFlushEx = ILibDuktape_readableStream_WriteData_Flush;
|
||||
ws->OnWriteFlushEx_User = stream;
|
||||
break;
|
||||
case ILibTransport_DoneState_COMPLETE:
|
||||
ws->OnWriteFlushEx = NULL;
|
||||
ws->OnWriteFlushEx_User = NULL;
|
||||
#ifdef WIN32
|
||||
InterlockedDecrement(&(stream->pipe_pendingCount));
|
||||
#elif defined(__ATOMIC_SEQ_CST)
|
||||
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
|
||||
#else
|
||||
--stream->pipe_pendingCount;
|
||||
#endif
|
||||
break;
|
||||
case ILibTransport_DoneState_ERROR:
|
||||
#ifdef WIN32
|
||||
InterlockedDecrement(&(stream->pipe_pendingCount));
|
||||
#elif defined(__ATOMIC_SEQ_CST)
|
||||
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
|
||||
#else
|
||||
--stream->pipe_pendingCount;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(w->writableStream != NULL)
|
||||
{
|
||||
duk_push_heapptr(stream->ctx, w->writableStream); // [stream]
|
||||
duk_get_prop_string(stream->ctx, -1, "write"); // [stream][func]
|
||||
duk_swap_top(stream->ctx, -2); // [func][this]
|
||||
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][chunk]
|
||||
duk_config_buffer(stream->ctx, -1, stream->extBuffer_buffer, stream->extBuffer_bufferLen);
|
||||
duk_push_c_function(stream->ctx, ILibDuktape_readableStream_WriteData_Flush_JS, DUK_VARARGS); // [func][this][chunk][callback]
|
||||
duk_push_pointer(stream->ctx, stream); // [func][this][chunk][callback][user]
|
||||
duk_put_prop_string(stream->ctx, -2, "readable"); // [func][this][chunk][callback]
|
||||
if (duk_pcall_method(stream->ctx, 2) != 0) // [retVal]
|
||||
{
|
||||
ILibDuktape_Process_UncaughtException(stream->ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
jsCount += duk_get_int(stream->ctx, -1);
|
||||
}
|
||||
duk_pop(stream->ctx);
|
||||
if (ILibDuktape_readableStream_WriteDataEx_Chain_Dispatch(stream, w->writableStream, data->buffer, data->bufferLen) == 2) { break; }
|
||||
}
|
||||
w = w->next;
|
||||
}
|
||||
if (stream->paused != 0 && stream->pipe_pendingCount == 0)
|
||||
{
|
||||
sem_post(&(stream->pipeLock));
|
||||
if (stream->ResumeHandler != NULL) { stream->paused = 0; stream->ResumeHandler(stream, stream->user); }
|
||||
}
|
||||
else
|
||||
{
|
||||
sem_post(&(stream->pipeLock));
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, int streamReserved, char* buffer, int bufferLen)
|
||||
{
|
||||
ILibDuktape_readableStream_nextWriteablePipe *w;
|
||||
int nonNativeCount = 0;
|
||||
int nativeCount = 0;
|
||||
int dispatchedNonNative = 0;
|
||||
int noContinue = 0;
|
||||
int dispatched = 0;
|
||||
int needPause = 0;
|
||||
|
||||
if (stream == NULL) { return(1); }
|
||||
|
||||
if (stream->paused != 0)
|
||||
{
|
||||
ILibDuktape_readableStream_WriteData_buffer(stream, streamReserved, buffer, bufferLen);
|
||||
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
|
||||
return(stream->paused);
|
||||
}
|
||||
|
||||
if (stream->bypassValue == 0 || stream->bypassValue != streamReserved)
|
||||
{
|
||||
sem_wait(&(stream->pipeLock));
|
||||
stream->pipeInProgress = 1;
|
||||
sem_post(&(stream->pipeLock));
|
||||
|
||||
w = stream->nextWriteable;
|
||||
stream->pipe_pendingCount = 0;
|
||||
while (w != NULL)
|
||||
{
|
||||
++stream->pipe_pendingCount;
|
||||
w = w->next;
|
||||
}
|
||||
dispatched = stream->pipe_pendingCount;
|
||||
w = stream->nextWriteable;
|
||||
while (w != NULL)
|
||||
{
|
||||
if (w->nativeWritable == 0) { ++nonNativeCount; }
|
||||
else { ++nativeCount; }
|
||||
w = w->next;
|
||||
}
|
||||
w = stream->nextWriteable;
|
||||
if (w != NULL)
|
||||
{
|
||||
if (nonNativeCount > 0)
|
||||
if (w->nativeWritable != NULL)
|
||||
{
|
||||
// There are piped Pure JavaScript objects... We must context switch to Microstack Thread
|
||||
stream->extBuffer_Reserved = streamReserved;
|
||||
stream->extBuffer_buffer = buffer;
|
||||
stream->extBuffer_bufferLen = bufferLen;
|
||||
sem_post(&(stream->pipeLock));
|
||||
if (stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
|
||||
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_ChainThread, stream);
|
||||
return(stream->paused);
|
||||
}
|
||||
else
|
||||
{
|
||||
// All piped objects are native, so we can blast out a send
|
||||
stream->pipe_pendingCount = nativeCount;
|
||||
while (w != NULL)
|
||||
ILibDuktape_WritableStream *ws = (ILibDuktape_WritableStream*)w->nativeWritable;
|
||||
ws->Reserved = streamReserved;
|
||||
switch (ws->WriteSink(ws, buffer, bufferLen, ws->WriteSink_User))
|
||||
{
|
||||
if (w->nativeWritable != NULL)
|
||||
{
|
||||
ILibDuktape_WritableStream *ws = (ILibDuktape_WritableStream*)w->nativeWritable;
|
||||
ws->Reserved = streamReserved;
|
||||
switch (ws->WriteSink(ws, buffer, bufferLen, ws->WriteSink_User))
|
||||
{
|
||||
case ILibTransport_DoneState_INCOMPLETE:
|
||||
ws->OnWriteFlushEx = ILibDuktape_readableStream_WriteData_Flush;
|
||||
ws->OnWriteFlushEx_User = stream;
|
||||
break;
|
||||
case ILibTransport_DoneState_COMPLETE:
|
||||
ws->OnWriteFlushEx = NULL;
|
||||
ws->OnWriteFlushEx_User = NULL;
|
||||
#ifdef WIN32
|
||||
InterlockedDecrement(&(stream->pipe_pendingCount));
|
||||
#elif defined(__ATOMIC_SEQ_CST)
|
||||
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
|
||||
#else
|
||||
--stream->pipe_pendingCount;
|
||||
#endif
|
||||
break;
|
||||
case ILibTransport_DoneState_ERROR:
|
||||
#ifdef WIN32
|
||||
InterlockedDecrement(&(stream->pipe_pendingCount));
|
||||
#elif defined(__ATOMIC_SEQ_CST)
|
||||
__atomic_sub_fetch(&(stream->pipe_pendingCount), 1, __ATOMIC_SEQ_CST);
|
||||
#else
|
||||
--stream->pipe_pendingCount;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
w = w->next;
|
||||
case ILibTransport_DoneState_INCOMPLETE:
|
||||
ws->OnWriteFlushEx = ILibDuktape_readableStream_WriteData_Flush;
|
||||
ws->OnWriteFlushEx_User = stream;
|
||||
needPause = 1;
|
||||
break;
|
||||
case ILibTransport_DoneState_COMPLETE:
|
||||
ws->OnWriteFlushEx = NULL;
|
||||
ws->OnWriteFlushEx_User = NULL;
|
||||
if (ILibDuktape_readableStream_WriteData_Flush(ws, stream)) { noContinue = 1; }
|
||||
break;
|
||||
case ILibTransport_DoneState_ERROR:
|
||||
if (ILibDuktape_readableStream_WriteData_Flush(ws, stream)) { noContinue = 1; }
|
||||
break;
|
||||
}
|
||||
if (stream->pipe_pendingCount == 0)
|
||||
if (noContinue != 0) { break; }
|
||||
}
|
||||
else if (w->writableStream != NULL && dispatchedNonNative == 0)
|
||||
{
|
||||
if (ILibIsRunningOnChainThread(stream->chain) == 0)
|
||||
{
|
||||
sem_post(&(stream->pipeLock));
|
||||
return(stream->paused);
|
||||
ILibDuktape_readableStream_bufferedData *tmp = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen, 0, NULL, NULL);
|
||||
tmp->Next = (ILibDuktape_readableStream_bufferedData*)stream;
|
||||
tmp->Reserved = streamReserved;
|
||||
tmp->bufferLen = bufferLen;
|
||||
memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen);
|
||||
dispatchedNonNative = 1;
|
||||
needPause = 1;
|
||||
ILibChain_RunOnMicrostackThreadEx(stream->chain, ILibDuktape_readableStream_WriteDataEx_Chain, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
sem_post(&(stream->pipeLock));
|
||||
if (stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
|
||||
return(stream->paused);
|
||||
// We're running on the Chain Thread, so we can directly dispatch into JS
|
||||
switch (ILibDuktape_readableStream_WriteDataEx_Chain_Dispatch(stream, w->writableStream, buffer, bufferLen))
|
||||
{
|
||||
case 1: // Need to Pause
|
||||
needPause = 1;
|
||||
break;
|
||||
case 2: // Complete
|
||||
noContinue = 1;
|
||||
break;
|
||||
default: // NOP
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sem_post(&(stream->pipeLock));
|
||||
if (noContinue != 0) { break; }
|
||||
w = w->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (stream->OnData != NULL)
|
||||
|
||||
if (dispatched == 0)
|
||||
{
|
||||
if (ILibIsRunningOnChainThread(stream->chain))
|
||||
sem_wait(&(stream->pipeLock));
|
||||
stream->pipeInProgress = 0;
|
||||
sem_post(&(stream->pipeLock));
|
||||
|
||||
if (stream->OnData != NULL)
|
||||
{
|
||||
duk_push_heapptr(stream->ctx, stream->OnData); // [func]
|
||||
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
|
||||
if (streamReserved == 0)
|
||||
if (ILibIsRunningOnChainThread(stream->chain))
|
||||
{
|
||||
duk_push_heapptr(stream->ctx, stream->extBuffer); // [func][this][buffer]
|
||||
duk_config_buffer(stream->ctx, -1, buffer, bufferLen);
|
||||
if (streamReserved == 0)
|
||||
{
|
||||
duk_push_external_buffer(stream->ctx); // [extBuffer]
|
||||
duk_config_buffer(stream->ctx, -1, buffer, bufferLen);
|
||||
}
|
||||
duk_push_heapptr(stream->ctx, stream->OnData); // [func]
|
||||
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
|
||||
if (streamReserved == 0)
|
||||
{
|
||||
duk_push_buffer_object(stream->ctx, -3, 0, bufferLen, DUK_BUFOBJ_NODEJS_BUFFER); // [extBuffer][func][this][nodeBuffer]
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_push_lstring(stream->ctx, buffer, bufferLen); // [func][this][string]
|
||||
}
|
||||
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
|
||||
{
|
||||
ILibDuktape_Process_UncaughtException(stream->ctx);
|
||||
}
|
||||
if (streamReserved == 0)
|
||||
{
|
||||
duk_pop_2(stream->ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_pop(stream->ctx); // ...
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_push_lstring(stream->ctx, buffer, bufferLen); // [func][this][string]
|
||||
// Need to PAUSE, and context switch to Chain Thread, so we can dispatch into JavaScript
|
||||
ILibDuktape_readableStream_bufferedData *tmp = (ILibDuktape_readableStream_bufferedData*)ILibMemory_Allocate(sizeof(ILibDuktape_readableStream_bufferedData) + bufferLen, 0, NULL, NULL);
|
||||
tmp->bufferLen = bufferLen;
|
||||
tmp->Reserved = streamReserved;
|
||||
tmp->Next = (ILibDuktape_readableStream_bufferedData*)stream;
|
||||
memcpy_s(tmp->buffer, bufferLen, buffer, bufferLen);
|
||||
needPause = 1;
|
||||
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, tmp);
|
||||
}
|
||||
if (duk_pcall_method(stream->ctx, 1) != 0) // [retVal]
|
||||
{
|
||||
ILibDuktape_Process_UncaughtException(stream->ctx);
|
||||
}
|
||||
duk_pop(stream->ctx); // ...
|
||||
}
|
||||
else
|
||||
else if (stream->PauseHandler != NULL && stream->OnEnd == NULL)
|
||||
{
|
||||
// Need to PAUSE, and context switch to Chain Thread, so we can dispatch into JavaScript
|
||||
sem_wait(&(stream->pipeLock));
|
||||
stream->extBuffer_Reserved = streamReserved;
|
||||
stream->extBuffer_buffer = buffer;
|
||||
stream->extBuffer_bufferLen = bufferLen;
|
||||
sem_post(&(stream->pipeLock));
|
||||
|
||||
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
|
||||
ILibChain_RunOnMicrostackThread(stream->chain, ILibDuktape_readableStream_WriteData_OnData_ChainThread, stream);
|
||||
// If we get here, it means we are writing data, but nobody is going to be receiving it...
|
||||
// So we need to buffer the data, so when we are resumed later, we can retry
|
||||
needPause = 1;
|
||||
ILibDuktape_readableStream_WriteData_buffer(stream, streamReserved, buffer, bufferLen);
|
||||
}
|
||||
else if (stream->OnEnd != NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if(stream->PauseHandler != NULL && stream->OnEnd == NULL)
|
||||
if (needPause)
|
||||
{
|
||||
// If we get here, it means we are writing data, but nobody is going to be receiving it...
|
||||
// So we need to buffer the data, so when we are resumed later, we can retry
|
||||
|
||||
ILibDuktape_readableStream_WriteData_buffer(stream, streamReserved, buffer, bufferLen);
|
||||
}
|
||||
else if (stream->OnEnd != NULL)
|
||||
{
|
||||
return 0;
|
||||
if (stream->paused == 0 && stream->PauseHandler != NULL) { stream->paused = 1; stream->PauseHandler(stream, stream->user); }
|
||||
}
|
||||
return(stream->paused);
|
||||
}
|
||||
@@ -426,7 +412,24 @@ int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream)
|
||||
{
|
||||
ILibDuktape_readableStream_nextWriteablePipe *next;
|
||||
|
||||
if (stream->OnEnd != NULL)
|
||||
if (stream->noPropagateEnd == 0 && stream->nextWriteable != NULL)
|
||||
{
|
||||
next = stream->nextWriteable;
|
||||
while (next != NULL)
|
||||
{
|
||||
duk_push_heapptr(stream->ctx, next->writableStream); // [stream]
|
||||
duk_get_prop_string(stream->ctx, -1, "end"); // [stream][func]
|
||||
duk_swap_top(stream->ctx, -2); // [func][this]
|
||||
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
|
||||
{
|
||||
ILibDuktape_Process_UncaughtException(stream->ctx);
|
||||
}
|
||||
duk_pop(stream->ctx); // ...
|
||||
next = next->next;
|
||||
retVal = 0;
|
||||
}
|
||||
}
|
||||
else if (stream->OnEnd != NULL)
|
||||
{
|
||||
duk_context *x = stream->ctx;
|
||||
duk_push_heapptr(stream->ctx, stream->OnEnd); // [func]
|
||||
@@ -438,29 +441,15 @@ int ILibDuktape_readableStream_WriteEnd(ILibDuktape_readableStream *stream)
|
||||
duk_pop(x); // ...
|
||||
retVal = 0;
|
||||
}
|
||||
next = stream->nextWriteable;
|
||||
while (next != NULL)
|
||||
{
|
||||
duk_push_heapptr(stream->ctx, next->writableStream); // [stream]
|
||||
duk_get_prop_string(stream->ctx, -1, "end"); // [stream][func]
|
||||
duk_swap_top(stream->ctx, -2); // [func][this]
|
||||
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
|
||||
{
|
||||
ILibDuktape_Process_UncaughtException(stream->ctx);
|
||||
}
|
||||
duk_pop(stream->ctx); // ...
|
||||
next = next->next;
|
||||
retVal = 0;
|
||||
}
|
||||
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
void ILibDuktape_readableStream_Closed(ILibDuktape_readableStream *stream)
|
||||
{
|
||||
ILibDuktape_readableStream_WriteEnd(stream);
|
||||
if (stream->OnClose != NULL)
|
||||
{
|
||||
duk_push_heapptr(stream->ctx, stream->OnEnd); // [func]
|
||||
duk_push_heapptr(stream->ctx, stream->OnClose); // [func]
|
||||
duk_push_heapptr(stream->ctx, stream->object); // [func][this]
|
||||
if (duk_pcall_method(stream->ctx, 0) != 0) // [retVal]
|
||||
{
|
||||
@@ -479,7 +468,14 @@ duk_ret_t ILibDuktape_readableStream_pause(duk_context *ctx)
|
||||
ptr = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_pop(ctx); // [stream]
|
||||
|
||||
if (ptr->PauseHandler != NULL) { ptr->paused = 1; ptr->PauseHandler(ptr, ptr->user); }
|
||||
if (ptr->PauseHandler != NULL)
|
||||
{
|
||||
ptr->paused = 1; ptr->PauseHandler(ptr, ptr->user);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(ILibDuktape_Error(ctx, "Pause Not Supported"));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -523,151 +519,240 @@ duk_ret_t ILibDuktape_readableStream_resume(duk_context *ctx)
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
|
||||
ptr = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_pop(ctx); // [stream]
|
||||
if (ptr->ResumeHandler == NULL) { return(ILibDuktape_Error(ctx, "Resume not supported")); }
|
||||
|
||||
if (ILibDuktape_readableStream_resume_flush(ptr) == 0 && ptr->ResumeHandler != NULL) { ptr->paused = 0; ptr->ResumeHandler(ptr, ptr->user); }
|
||||
return 1;
|
||||
}
|
||||
void ILibDuktape_readableStream_pipe_resumeFromTimer(void *obj)
|
||||
|
||||
void ILibDuktape_ReadableStream_pipe_ResumeLater(duk_context *ctx, void **args, int argsLen)
|
||||
{
|
||||
ILibDuktape_readableStream* ptr = (ILibDuktape_readableStream*)((void**)obj)[0];
|
||||
if (ILibDuktape_readableStream_resume_flush(ptr) == 0 && ptr->ResumeHandler != NULL) { ptr->paused = 0; ptr->ResumeHandler(ptr, ptr->user); }
|
||||
free(obj);
|
||||
ILibDuktape_readableStream *rs = (ILibDuktape_readableStream*)args[0];
|
||||
if (ILibDuktape_readableStream_resume_flush(rs) == 0 && rs->ResumeHandler != NULL) { rs->paused = 0; rs->ResumeHandler(rs, rs->user); }
|
||||
if (rs->PipeHookHandler != NULL) { rs->PipeHookHandler(rs, args[1], rs->user); }
|
||||
}
|
||||
void ILibDuktape_readableStream_pipe_resumeFromTimer2(void *obj)
|
||||
void ILibDuktape_readableStream_pipe_later(duk_context *ctx, void **args, int argsLen)
|
||||
{
|
||||
free(obj);
|
||||
duk_push_heapptr(ctx, args[0]); // [readable]
|
||||
duk_get_prop_string(ctx, -1, "pipe"); // [readable][pipe]
|
||||
duk_swap_top(ctx, -2); // [pipe][this]
|
||||
duk_push_heapptr(ctx, args[1]); // [pipe][this][writable]
|
||||
if (argsLen > 2) { duk_push_heapptr(ctx, args[2]); } // [pipe][this][writable][options]
|
||||
if (duk_pcall_method(ctx, argsLen - 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "readableStream.pipeLater(): "); }
|
||||
duk_pop(ctx); // ...
|
||||
}
|
||||
duk_ret_t ILibDuktape_readableStream_pipe(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_readableStream *rstream;
|
||||
ILibDuktape_readableStream_nextWriteablePipe *w;
|
||||
ILibDuktape_readableStream_nextWriteablePipe *w, *tmp;
|
||||
int nargs = duk_get_top(ctx);
|
||||
|
||||
duk_push_this(ctx); // [readable]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [readable][ptrs]
|
||||
rstream = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_pop(ctx); // [readable]
|
||||
duk_pop_2(ctx); // ...
|
||||
|
||||
if (nargs > 1 && duk_is_object(ctx, 1))
|
||||
sem_wait(&(rstream->pipeLock));
|
||||
if (rstream->pipeInProgress != 0)
|
||||
{
|
||||
rstream->bypassValue = Duktape_GetIntPropertyValue(ctx, 1, "dataTypeSkip", 0);
|
||||
}
|
||||
// We must YIELD and try again later, becuase there is an active dispatch going on
|
||||
duk_push_this(ctx);
|
||||
ILibDuktape_Immediate(ctx, (void*[]) { duk_get_heapptr(ctx, -1), duk_get_heapptr(ctx, 0), nargs > 1 ? duk_get_heapptr(ctx, 1) : NULL }, 1 + nargs, ILibDuktape_readableStream_pipe_later);
|
||||
|
||||
duk_push_object(ctx); // [readable][nextWriteable]
|
||||
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream_nextWriteablePipe)); // [readable][nextWriteable][ptrBuffer]
|
||||
w = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
memset(w, 0, sizeof(ILibDuktape_readableStream_nextWriteablePipe));
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes_PTRBUFFER); // [readable][nextWriteable]
|
||||
|
||||
|
||||
if (duk_has_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes))
|
||||
{
|
||||
// There are already associated pipes
|
||||
duk_get_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable][nextWriteable][prevWriteable]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_WritePipes_PTRBUFFER); // [readable][nextWriteable][prevWriteable][ptr]
|
||||
w->next = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_pop(ctx); // [readable][nextWriteable][prevWriteable]
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable][nextWriteable]
|
||||
}
|
||||
|
||||
duk_dup(ctx, 0); // [readable][nextWriteable][stream]
|
||||
if (duk_has_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS))
|
||||
{
|
||||
// This is one of our writable stream implementation... So we can keep everything native
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS); // [readable][nextWriteable][stream][buffer]
|
||||
w->nativeWritable = Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_pop(ctx); // [readable][nextWriteable][stream]
|
||||
}
|
||||
w->writableStream = duk_get_heapptr(ctx, -1);
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes_Stream); // [readable][nextWriteable]
|
||||
|
||||
rstream->nextWriteable = w;
|
||||
|
||||
// Save to the readableStream
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes); // [readable]
|
||||
|
||||
duk_dup(ctx, 0); // [readable][writable]
|
||||
if (duk_has_prop_string(ctx, -1, "emit"))
|
||||
{
|
||||
duk_push_string(ctx, "emit"); // [readable][writable][key]
|
||||
duk_push_string(ctx, "pipe"); // [readable][writable][key][eventName]
|
||||
duk_dup(ctx, -4); // [readable][writable][key][eventName][readable]
|
||||
if (duk_pcall_prop(ctx, -4, 2) != 0) // [readable][writable][retVal/err]
|
||||
{
|
||||
ILibDuktape_Process_UncaughtException(ctx);
|
||||
}
|
||||
duk_pop_2(ctx); // [readable]
|
||||
duk_dup(ctx, 0);
|
||||
sem_post(&(rstream->pipeLock));
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_pop(ctx);
|
||||
}
|
||||
|
||||
if (rstream->paused != 0)
|
||||
{
|
||||
void *chain = Duktape_GetChain(ctx);
|
||||
if (chain != NULL)
|
||||
// No Active Dispatch, so while we hold this lock, we can setup/add the pipe
|
||||
duk_push_heapptr(ctx, rstream->pipeArray); // [pipeArray]
|
||||
duk_get_prop_string(ctx, -1, "push"); // [pipeArray][push]
|
||||
duk_swap_top(ctx, -2); // [push][this]
|
||||
duk_dup(ctx, 0); // [push][this][dest]
|
||||
ILibDuktape_Push_ObjectStash(ctx); // [push][this][dest][stash]
|
||||
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream_nextWriteablePipe)); // [push][this][dest][stash][buffer]
|
||||
w = (ILibDuktape_readableStream_nextWriteablePipe*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_put_prop_string(ctx, -2, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [push][this][dest][stash]
|
||||
duk_pop(ctx); // [push][this][dest]
|
||||
duk_call_method(ctx, 1); duk_pop(ctx); // ...
|
||||
memset(w, 0, sizeof(ILibDuktape_readableStream_nextWriteablePipe));
|
||||
w->writableStream = duk_get_heapptr(ctx, 0);
|
||||
if (duk_has_prop_string(ctx, 0, ILibDuktape_WritableStream_WSPTRS))
|
||||
{
|
||||
// We are paused, so we should yield and resume... We yield, so in case the user tries to chain multiple pipes, it will chain first
|
||||
void **tmp = (void**)ILibMemory_Allocate(sizeof(void*), 0, NULL, NULL);
|
||||
tmp[0] = rstream;
|
||||
ILibLifeTime_AddEx(ILibGetBaseTimer(chain), tmp, 0, ILibDuktape_readableStream_pipe_resumeFromTimer, ILibDuktape_readableStream_pipe_resumeFromTimer2);
|
||||
// This is one of our writable stream implementation... So we can keep everything native
|
||||
duk_get_prop_string(ctx, 0, ILibDuktape_WritableStream_WSPTRS); // [wrsPTR]
|
||||
w->nativeWritable = Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_pop(ctx); // ...
|
||||
// If JSCreate is non-zero, it means this is actually a JS Stream, not a native one
|
||||
if (((int*)w->nativeWritable)[0] != 0) { w->nativeWritable = NULL; }
|
||||
}
|
||||
|
||||
// Now lets lets add this entry to the end of the list, so it can be dispatched without invoking into JS to access the array
|
||||
if (rstream->nextWriteable == NULL)
|
||||
{
|
||||
rstream->nextWriteable = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Oops
|
||||
duk_push_string(ctx, "ILibParsers_Duktape *MISSING*");
|
||||
duk_throw(ctx);
|
||||
return(DUK_RET_ERROR);
|
||||
tmp = rstream->nextWriteable;
|
||||
while (tmp->next != NULL) { tmp = tmp->next; }
|
||||
tmp->next = w;
|
||||
w->previous = tmp;
|
||||
}
|
||||
}
|
||||
if (nargs > 1 && duk_is_object(ctx, 1))
|
||||
{
|
||||
rstream->bypassValue = Duktape_GetIntPropertyValue(ctx, 1, "dataTypeSkip", 0);
|
||||
rstream->noPropagateEnd = Duktape_GetBooleanProperty(ctx, 1, "end", 1) == 0 ? 1 : 0;
|
||||
}
|
||||
sem_post(&(rstream->pipeLock));
|
||||
|
||||
if (rstream->PipeHookHandler != NULL) { rstream->PipeHookHandler(rstream, rstream->user); }
|
||||
// Now we need to emit a 'pipe' event on the writable that we just attached
|
||||
duk_push_heapptr(ctx, w->writableStream); // [dest]
|
||||
duk_get_prop_string(ctx, -1, "emit"); // [dest][emit]
|
||||
duk_swap_top(ctx, -2); // [emit][this]
|
||||
duk_push_string(ctx, "pipe"); // [emit][this][pipe]
|
||||
duk_push_this(ctx); // [emit][this][pipe][readable]
|
||||
duk_call_method(ctx, 2); duk_pop(ctx); // ...
|
||||
|
||||
|
||||
if (rstream->paused != 0)
|
||||
{
|
||||
// We are paused, so we should yield and resume... We yield, so in case the user tries to chain multiple pipes, it will chain first
|
||||
ILibDuktape_Immediate(ctx, (void*[]) { rstream, duk_get_heapptr(ctx, 0) }, 1, ILibDuktape_ReadableStream_pipe_ResumeLater);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rstream->PipeHookHandler != NULL) { rstream->PipeHookHandler(rstream, duk_get_heapptr(ctx, 0), rstream->user); }
|
||||
}
|
||||
|
||||
duk_dup(ctx, 0);
|
||||
return 1;
|
||||
}
|
||||
void ILibDuktape_readableStream_unpipe_later(duk_context *ctx, void ** args, int argsLen)
|
||||
{
|
||||
ILibDuktape_readableStream *data;
|
||||
ILibDuktape_readableStream_nextWriteablePipe *w;
|
||||
int i;
|
||||
duk_size_t arrayLen;
|
||||
|
||||
duk_push_heapptr(ctx, args[0]); // [readable]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [readable][ptrs]
|
||||
data = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_pop_2(ctx); // ...
|
||||
|
||||
sem_wait(&(data->pipeLock));
|
||||
if (data->pipeInProgress != 0)
|
||||
{
|
||||
// We must yield, and try again, because there's an active dispatch going on
|
||||
ILibDuktape_Immediate(ctx, (void*[]) { args[0], args[1] }, argsLen, ILibDuktape_readableStream_unpipe_later);
|
||||
sem_post(&(data->pipeLock));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
w = data->nextWriteable;
|
||||
if (argsLen > 1)
|
||||
{
|
||||
// Specific stream was specified in 'unpipe'
|
||||
while (w != NULL)
|
||||
{
|
||||
if (w->writableStream == args[1])
|
||||
{
|
||||
// Emit the 'unpipe' event
|
||||
duk_push_heapptr(ctx, args[1]); // [ws]
|
||||
duk_get_prop_string(ctx, -1, "emit"); // [ws][emit]
|
||||
duk_swap_top(ctx, -2); // [emit][this]
|
||||
duk_push_string(ctx, "unpipe"); // [emit][this][unpipe]
|
||||
duk_push_heapptr(ctx, args[0]); // [emit][this][unpipe][readable]
|
||||
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "readable.unpipe(): "); }
|
||||
duk_pop(ctx); // ...
|
||||
|
||||
if (w->previous != NULL)
|
||||
{
|
||||
w->previous->next = w->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
data->nextWriteable = w->next;
|
||||
}
|
||||
duk_push_heapptr(ctx, data->pipeArray); // [array]
|
||||
arrayLen = duk_get_length(ctx, -1);
|
||||
for (i = 0; i < (int)arrayLen; ++i)
|
||||
{
|
||||
duk_get_prop_index(ctx, -1, i); // [array][ws]
|
||||
ILibDuktape_Push_ObjectStash(ctx); // [array][ws][stash]
|
||||
if (duk_has_prop_string(ctx, -1, Duktape_GetStashKey(args[1])))
|
||||
{
|
||||
// Removing the entry from the Array
|
||||
duk_pop_2(ctx); // [array]
|
||||
duk_get_prop_string(ctx, -1, "splice"); // [array][splice]
|
||||
duk_swap_top(ctx, -2); // [splice][this]
|
||||
duk_push_int(ctx, i); // [splice][this][i]
|
||||
duk_push_int(ctx, 1); // [splice][this][i][1]
|
||||
duk_call_method(ctx, 2); // [undefined]
|
||||
duk_pop(ctx); // ...
|
||||
break;
|
||||
}
|
||||
duk_pop_2(ctx); // [array]
|
||||
}
|
||||
duk_pop(ctx); // ...
|
||||
break;
|
||||
}
|
||||
w = w->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 'unpipe' all pipes
|
||||
w = data->nextWriteable;
|
||||
while (w != NULL)
|
||||
{
|
||||
duk_push_heapptr(ctx, w->writableStream); // [ws]
|
||||
duk_get_prop_string(ctx, -1, "emit"); // [ws][emit]
|
||||
duk_swap_top(ctx, -2); // [emit][this]
|
||||
duk_push_string(ctx, "unpipe"); // [emit][this][unpipe]
|
||||
duk_push_heapptr(ctx, args[0]); // [emit][this][unpipe][readable]
|
||||
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "readable.unpipe(): "); }
|
||||
duk_pop(ctx); // ...
|
||||
w = w->next;
|
||||
}
|
||||
data->nextWriteable = NULL;
|
||||
duk_push_heapptr(ctx, args[0]); // [readable]
|
||||
duk_del_prop_string(ctx, -1, ILibDuktape_readableStream_PipeArray);
|
||||
duk_push_array(ctx); // [readable][array]
|
||||
data->pipeArray = duk_get_heapptr(ctx, -1);
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_PipeArray); // [readable]
|
||||
duk_pop(ctx); // ...
|
||||
}
|
||||
}
|
||||
data->unpipeInProgress = 0;
|
||||
sem_post(&(data->pipeLock));
|
||||
}
|
||||
duk_ret_t ILibDuktape_readableStream_unpipe(duk_context *ctx)
|
||||
{
|
||||
int nargs = duk_get_top(ctx);
|
||||
ILibDuktape_readableStream *data;
|
||||
ILibDuktape_readableStream_nextWriteablePipe *w, *prev;
|
||||
|
||||
duk_push_this(ctx); // [stream]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
|
||||
duk_push_this(ctx); // [readable]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [readable][ptrs]
|
||||
data = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_pop(ctx); // [readable]
|
||||
|
||||
if (nargs == 0)
|
||||
{
|
||||
duk_del_prop_string(ctx, -2, ILibDuktape_readableStream_WritePipes);
|
||||
data->nextWriteable = NULL;
|
||||
}
|
||||
else if (data->nextWriteable != NULL)
|
||||
{
|
||||
w = data->nextWriteable;
|
||||
prev = NULL;
|
||||
while (w != NULL)
|
||||
{
|
||||
if (w->writableStream == duk_get_heapptr(ctx, 0))
|
||||
{
|
||||
memset(w, 0, 2 * sizeof(void*));
|
||||
if (data->nextWriteable == w)
|
||||
{
|
||||
//printf("Unpiping object: %p\n", (void*)w);
|
||||
data->nextWriteable = w->next;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev->next = w->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = w;
|
||||
w = w->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sem_wait(&(data->pipeLock));
|
||||
data->unpipeInProgress = 1;
|
||||
sem_post(&(data->pipeLock));
|
||||
|
||||
// We need to pause first
|
||||
duk_push_this(ctx); // [readable]
|
||||
duk_get_prop_string(ctx, -1, "pause"); // [readable][pause]
|
||||
duk_dup(ctx, -2); // [readable][pause][this]
|
||||
duk_call_method(ctx, 0); duk_pop(ctx); // [readable]
|
||||
|
||||
// We must yield, and do this on the next event loop, because we can't unpipe if we're called from a pipe'ed call
|
||||
ILibDuktape_Immediate(ctx, (void*[]) { duk_get_heapptr(ctx, -1), nargs == 1 ? duk_get_heapptr(ctx, 0) : NULL }, nargs + 1, ILibDuktape_readableStream_unpipe_later);
|
||||
return 0;
|
||||
}
|
||||
duk_ret_t ILibDuktape_readableStream_isPaused(duk_context *ctx)
|
||||
@@ -710,11 +795,31 @@ void ILibDuktape_ReadableStream_PipeLockFinalizer(duk_context *ctx, void *stream
|
||||
sem_destroy(&(ptrs->pipeLock));
|
||||
duk_pop_2(ctx);
|
||||
}
|
||||
ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, void *user)
|
||||
duk_ret_t ILibDuktape_ReadableStream_unshift(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_readableStream *rs;
|
||||
duk_push_this(ctx); // [stream]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_readableStream_RSPTRS); // [stream][ptrs]
|
||||
rs = (ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
|
||||
if (rs->UnshiftHandler == NULL)
|
||||
{
|
||||
return(ILibDuktape_Error(ctx, "readable.unshift(): Not Implemented"));
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_size_t bufferLen;
|
||||
Duktape_GetBuffer(ctx, 0, &bufferLen);
|
||||
duk_push_int(ctx, rs->UnshiftHandler(rs, (int)bufferLen, rs->user));
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, ILibDuktape_readableStream_UnShiftHandler OnUnshift, void *user)
|
||||
{
|
||||
ILibDuktape_readableStream *retVal;
|
||||
ILibDuktape_EventEmitter *emitter;
|
||||
|
||||
ILibDuktape_PointerValidation_Init(ctx);
|
||||
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_readableStream)); // [obj][buffer]
|
||||
duk_dup(ctx, -1); // [obj][buffer][buffer]
|
||||
duk_put_prop_string(ctx, -3, ILibDuktape_readableStream_RSPTRS); // [obj][buffer]
|
||||
@@ -722,9 +827,10 @@ ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILi
|
||||
memset(retVal, 0, sizeof(ILibDuktape_readableStream));
|
||||
|
||||
duk_pop(ctx); // [obj]
|
||||
duk_push_external_buffer(ctx); // [obj][extBuffer]
|
||||
retVal->extBuffer = duk_get_heapptr(ctx, -1);
|
||||
duk_put_prop_string(ctx, -2, "_extBuffer"); // [obj]
|
||||
duk_push_array(ctx); // [obj][array]
|
||||
retVal->pipeArray = duk_get_heapptr(ctx, -1);
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_readableStream_PipeArray); // [obj]
|
||||
|
||||
|
||||
retVal->ctx = ctx;
|
||||
retVal->chain = Duktape_GetChain(ctx);
|
||||
@@ -732,6 +838,7 @@ ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILi
|
||||
retVal->user = user;
|
||||
retVal->PauseHandler = OnPause;
|
||||
retVal->ResumeHandler = OnResume;
|
||||
retVal->UnshiftHandler = OnUnshift;
|
||||
sem_init(&(retVal->pipeLock), 0, 1);
|
||||
ILibDuktape_CreateIndependentFinalizer(ctx, ILibDuktape_ReadableStream_PipeLockFinalizer);
|
||||
|
||||
@@ -743,7 +850,8 @@ ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILi
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "pause", ILibDuktape_readableStream_pause, 0);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "resume", ILibDuktape_readableStream_resume, 0);
|
||||
ILibDuktape_CreateEventWithGetter(ctx, "pipe", ILibDuktape_readableStream_pipe_getter);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "unpipe", ILibDuktape_readableStream_unpipe, DUK_VARARGS);
|
||||
ILibDuktape_CreateProperty_InstanceMethod(ctx, "unpipe", ILibDuktape_readableStream_unpipe, DUK_VARARGS);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "isPaused", ILibDuktape_readableStream_isPaused, 0);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "unshift", ILibDuktape_ReadableStream_unshift, 1);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@@ -24,12 +24,14 @@ limitations under the License.
|
||||
|
||||
struct ILibDuktape_readableStream;
|
||||
typedef void(*ILibDuktape_readableStream_PauseResumeHandler)(struct ILibDuktape_readableStream *sender, void *user);
|
||||
typedef void(*ILibDuktape_readableStream_MethodHookHandler)(struct ILibDuktape_readableStream *sender, void *user);
|
||||
typedef void(*ILibDuktape_readableStream_MethodHookHandler)(struct ILibDuktape_readableStream *sender, void *writableStream, void *user);
|
||||
typedef int(*ILibDuktape_readableStream_UnShiftHandler)(struct ILibDuktape_readableStream *sender, int unshiftBytes, void *user);
|
||||
|
||||
typedef struct ILibDuktape_readableStream_nextWriteablePipe
|
||||
{
|
||||
void *writableStream;
|
||||
void *nativeWritable;
|
||||
struct ILibDuktape_readableStream_nextWriteablePipe *next;
|
||||
struct ILibDuktape_readableStream_nextWriteablePipe *previous, *next;
|
||||
}ILibDuktape_readableStream_nextWriteablePipe;
|
||||
|
||||
typedef struct ILibDuktape_readableStream
|
||||
@@ -40,11 +42,9 @@ typedef struct ILibDuktape_readableStream
|
||||
void *OnClose;
|
||||
void *OnData;
|
||||
void *OnEnd;
|
||||
void *extBuffer;
|
||||
char *extBuffer_buffer;
|
||||
int extBuffer_bufferLen, extBuffer_Reserved;
|
||||
|
||||
void *user;
|
||||
void *pipeArray;
|
||||
ILibDuktape_readableStream_nextWriteablePipe *nextWriteable;
|
||||
sem_t pipeLock;
|
||||
#if defined(WIN32)
|
||||
@@ -54,16 +54,21 @@ typedef struct ILibDuktape_readableStream
|
||||
#else
|
||||
int pipe_pendingCount; // No Atomic Built-ins... Use a Mutex
|
||||
#endif
|
||||
int pipeInProgress;
|
||||
int unpipeInProgress;
|
||||
int bypassValue;
|
||||
int noPropagateEnd;
|
||||
int paused;
|
||||
void *paused_data;
|
||||
ILibDuktape_readableStream_PauseResumeHandler PauseHandler;
|
||||
ILibDuktape_readableStream_PauseResumeHandler ResumeHandler;
|
||||
ILibDuktape_readableStream_MethodHookHandler PipeHookHandler;
|
||||
ILibDuktape_readableStream_UnShiftHandler UnshiftHandler;
|
||||
}ILibDuktape_readableStream;
|
||||
|
||||
ILibDuktape_readableStream* ILibDuktape_InitReadableStream(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, void *user);
|
||||
#define ILibDuktape_ReadableStream_Init(ctx, OnPause, OnResume, user) ILibDuktape_InitReadableStream(ctx, OnPause, OnResume, user)
|
||||
ILibDuktape_readableStream* ILibDuktape_ReadableStream_InitEx(duk_context *ctx, ILibDuktape_readableStream_PauseResumeHandler OnPause, ILibDuktape_readableStream_PauseResumeHandler OnResume, ILibDuktape_readableStream_UnShiftHandler OnUnshift, void *user);
|
||||
#define ILibDuktape_InitReadableStream(ctx, OnPause, OnResume, user) ILibDuktape_ReadableStream_InitEx(ctx, OnPause, OnResume, NULL, user)
|
||||
#define ILibDuktape_ReadableStream_Init(ctx, OnPause, OnResume, user) ILibDuktape_ReadableStream_InitEx(ctx, OnPause, OnResume, NULL, user)
|
||||
#define ILibDuktape_readableStream_SetPauseResumeHandlers(stream, PauseFunc, ResumeFunc, userObj) ((ILibDuktape_readableStream*)stream)->PauseHandler = PauseFunc; ((ILibDuktape_readableStream*)stream)->ResumeHandler = ResumeFunc; ((ILibDuktape_readableStream*)stream)->user = userObj;
|
||||
|
||||
int ILibDuktape_readableStream_WriteDataEx(ILibDuktape_readableStream *stream, int streamReserved, char* buffer, int bufferLen);
|
||||
|
||||
@@ -40,7 +40,6 @@ limitations under the License.
|
||||
#include "ILibDuktape_EventEmitter.h"
|
||||
#include "ILibDuktape_Helpers.h"
|
||||
#include "../microstack/ILibParsers.h"
|
||||
#include "../microstack/ILibProcessPipe.h"
|
||||
#include "../microstack/ILibRemoteLogging.h"
|
||||
#include "../microstack/ILibCrypto.h"
|
||||
|
||||
@@ -49,7 +48,6 @@ limitations under the License.
|
||||
#include "ILibDuktape_WebRTC.h"
|
||||
#include "ILibDuktape_Dgram.h"
|
||||
#include "ILibDuktape_GenericMarshal.h"
|
||||
#include "ILibDuktape_ProcessPipe.h"
|
||||
#include "ILibDuktape_fs.h"
|
||||
#include "ILibDuktape_Polyfills.h"
|
||||
#include "ILibDuktape_SimpleDataStore.h"
|
||||
@@ -58,6 +56,7 @@ limitations under the License.
|
||||
#include "ILibDuktape_SHA256.h"
|
||||
#include "ILibDuktape_EncryptionStream.h"
|
||||
#include "ILibDuktape_ChildProcess.h"
|
||||
#include "ILibDuktape_HECI.h"
|
||||
|
||||
#ifdef _POSIX
|
||||
extern char **environ;
|
||||
@@ -198,11 +197,11 @@ void ILibDuktape_ScriptContainer_CheckEmbedded(char **argv, char **script, int *
|
||||
if (ILibString_EndsWith(argv[0], -1, ".exe", 4) == 0)
|
||||
{
|
||||
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s.exe", argv[0]);
|
||||
tmpFile = fopen(ILibScratchPad, "rb");
|
||||
fopen_s(&tmpFile, ILibScratchPad, "rb");
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFile = fopen(argv[0], "rb");
|
||||
fopen_s(&tmpFile, argv[0], "rb");
|
||||
}
|
||||
#else
|
||||
tmpFile = fopen(argv[0], "rb");
|
||||
@@ -290,15 +289,23 @@ duk_ret_t ILibDuktape_ScriptContainer_Process_Argv0(duk_context *ctx)
|
||||
// Polyfill process object:
|
||||
duk_ret_t ILibDuktape_ScriptContainer_Process_Argv(duk_context *ctx)
|
||||
{
|
||||
duk_push_current_function(ctx);
|
||||
int readOnly = Duktape_GetIntPropertyValue(ctx, -1, "readOnly", 0);
|
||||
|
||||
duk_push_this(ctx); // [process]
|
||||
if (duk_has_prop_string(ctx, -1, ILibDuktape_ScriptContainer_Process_ArgArray))
|
||||
{
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_ScriptContainer_Process_ArgArray); // [process][array]
|
||||
duk_dup(ctx, -1); // [process][array][array]
|
||||
if (readOnly != 0) { duk_dup(ctx, -1); } // [process][array][array]
|
||||
}
|
||||
else
|
||||
{
|
||||
duk_push_array(ctx); // [process][array]
|
||||
if (readOnly == 0)
|
||||
{
|
||||
duk_dup(ctx, -1); // [process][array][array]
|
||||
duk_put_prop_string(ctx, -3, ILibDuktape_ScriptContainer_Process_ArgArray); // [process][array]
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -404,7 +411,10 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
|
||||
ILibDuktape_EventEmitter_CreateEventEx(emitter, "uncaughtException");
|
||||
|
||||
ILibDuktape_CreateEventWithGetter(ctx, "argv0", ILibDuktape_ScriptContainer_Process_Argv0);
|
||||
ILibDuktape_CreateEventWithGetter(ctx, "argv", ILibDuktape_ScriptContainer_Process_Argv);
|
||||
duk_push_int(ctx, 1);
|
||||
ILibDuktape_CreateEventWithGetterAndCustomProperty(ctx, "readOnly", "argv", ILibDuktape_ScriptContainer_Process_Argv);
|
||||
duk_push_int(ctx, 0);
|
||||
ILibDuktape_CreateEventWithGetterAndCustomProperty(ctx, "readOnly", "_argv", ILibDuktape_ScriptContainer_Process_Argv);
|
||||
|
||||
duk_put_prop_string(ctx, -2, "process"); // [g]
|
||||
duk_pop(ctx); // ...
|
||||
@@ -762,7 +772,7 @@ void ILibDuktape_ScriptContainer_OS_Init(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_ModSearch_AddHandler(ctx, "os", ILibDuktape_ScriptContainer_OS_Push);
|
||||
}
|
||||
|
||||
extern void ILibDuktape_HttpStream_Init(duk_context *ctx);
|
||||
duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(SCRIPT_ENGINE_SECURITY_FLAGS securityFlags, unsigned int executionTimeout, void *chain, char **argList, ILibSimpleDataStore *db, char *exePath, ILibProcessPipe_Manager pipeManager, ILibDuktape_HelperEvent exitHandler, void *exitUser)
|
||||
{
|
||||
duk_context *ctx = duk_create_heap(ILibDuktape_ScriptContainer_Engine_malloc, ILibDuktape_ScriptContainer_Engine_realloc, ILibDuktape_ScriptContainer_Engine_free, NULL, ILibDuktape_ScriptContainer_Engine_fatal);
|
||||
@@ -800,12 +810,19 @@ duk_context *ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(SCRIPT_ENG
|
||||
if ((securityFlags & SCRIPT_ENGINE_NO_NETWORK_ACCESS) == 0)
|
||||
{
|
||||
ILibDuktape_WebRTC_Init(ctx); // WebRTC library (browser api)
|
||||
ILibDuktape_http_init(ctx, chain); // HTTP library (node api)
|
||||
ILibDuktape_http_init(ctx, chain); // HTTP-Digest library (node api)
|
||||
ILibDuktape_net_init(ctx, chain); // Network library (node api)
|
||||
ILibDuktape_DGram_Init(ctx); // Datagram Sockets
|
||||
ILibDuktape_HttpStream_Init(ctx); // HTTP Library (node api)
|
||||
}
|
||||
if ((securityFlags & SCRIPT_ENGINE_NO_GENERIC_MARSHAL_ACCESS) == 0) { ILibDuktape_GenericMarshal_init(ctx); }
|
||||
if ((securityFlags & SCRIPT_ENGINE_NO_PROCESS_SPAWNING) == 0) { ILibDuktape_ProcessPipe_Init(ctx, chain); ILibDuktape_ChildProcess_Init(ctx); }
|
||||
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); }
|
||||
|
||||
|
||||
|
||||
561
microscript/ILibDuktape_TlsStream.c
Normal file
561
microscript/ILibDuktape_TlsStream.c
Normal file
@@ -0,0 +1,561 @@
|
||||
#include "duktape.h"
|
||||
#include "ILibDuktape_Helpers.h"
|
||||
#include "ILibDuktapeModSearch.h"
|
||||
#include "ILibDuktape_DuplexStream.h"
|
||||
#include "ILibDuktape_EventEmitter.h"
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
#include "../microstack/ILibCrypto.h"
|
||||
|
||||
#define ILibDuktape_TlsStream_Ptr "\xFF_ILibDuktape_TLSSTREAM_PTR"
|
||||
#define ILibDuktape_TlsStream2Cert "\xFF_TLS_CERT"
|
||||
|
||||
#define MEMORYCHUNKSIZE 4096
|
||||
int ILibDuktape_TlsStream_ctx2stream = -1;
|
||||
|
||||
typedef struct ILibDuktape_TlsStream_Data
|
||||
{
|
||||
duk_context *ctx;
|
||||
void *tlsObject;
|
||||
void *chain;
|
||||
int isClient;
|
||||
ILibDuktape_EventEmitter *emitter;
|
||||
char *decryptedBuffer;
|
||||
int decryptedBuffer_mallocSize;
|
||||
int decryptedBuffer_beginPointer;
|
||||
int decryptedBuffer_endPointer;
|
||||
int decryptedBuffer_unshiftedBytes;
|
||||
int decryptedBuffer_maxSize;
|
||||
|
||||
int rejectUnauthorized;
|
||||
void *OnVerify;
|
||||
void *OnServerSNI;
|
||||
|
||||
int ProcessEncryptedBuffer_Active;
|
||||
|
||||
SSL* ssl;
|
||||
SSL_CTX *ssl_ctx;
|
||||
BIO *readBio, *writeBio;
|
||||
BUF_MEM *readBioBuffer, *writeBioBuffer;
|
||||
int TLSHandshakeCompleted;
|
||||
ILibDuktape_DuplexStream *clear;
|
||||
ILibDuktape_DuplexStream *encrypted;
|
||||
int encrypted_unshiftBytes;
|
||||
}ILibDuktape_TlsStream_Data;
|
||||
|
||||
|
||||
void ILibDuktape_TlsStream_X509_PUSH(duk_context *ctx, X509* cert)
|
||||
{
|
||||
char hash[UTIL_SHA384_HASHSIZE];
|
||||
char fingerprint[150];
|
||||
|
||||
util_keyhash2(cert, hash);
|
||||
util_tohex2(hash, UTIL_SHA384_HASHSIZE, fingerprint);
|
||||
|
||||
duk_push_object(ctx); // [cert]
|
||||
duk_push_string(ctx, fingerprint); // [cert][fingerprint]
|
||||
duk_put_prop_string(ctx, -2, "fingerprint"); // [cert]
|
||||
}
|
||||
ILibTransport_DoneState ILibDuktape_TlsStream_ProcessEncryptedBuffer(ILibDuktape_TlsStream_Data *tlsdata)
|
||||
{
|
||||
int j, first = 1;
|
||||
|
||||
if (tlsdata->ProcessEncryptedBuffer_Active == 0)
|
||||
{
|
||||
tlsdata->ProcessEncryptedBuffer_Active = 1;
|
||||
tlsdata->encrypted_unshiftBytes = 0;
|
||||
BIO_clear_retry_flags(tlsdata->writeBio);
|
||||
|
||||
while ((j = (int)tlsdata->writeBioBuffer->length) > 0 && tlsdata->encrypted->readableStream->paused == 0)
|
||||
{
|
||||
if (first == 1)
|
||||
{
|
||||
first = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tlsdata->encrypted_unshiftBytes = 0;
|
||||
BIO_clear_retry_flags(tlsdata->writeBio);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ILibDuktape_DuplexStream_WriteData(tlsdata->encrypted, tlsdata->writeBioBuffer->data, (int)tlsdata->writeBioBuffer->length);
|
||||
} while (tlsdata->encrypted_unshiftBytes > 0);
|
||||
if (tlsdata->encrypted_unshiftBytes == 0)
|
||||
{
|
||||
tlsdata->writeBioBuffer->data += (int)tlsdata->writeBioBuffer->length;
|
||||
tlsdata->writeBioBuffer->length = 0;
|
||||
}
|
||||
}
|
||||
tlsdata->ProcessEncryptedBuffer_Active = 0;
|
||||
return(tlsdata->writeBioBuffer->length > 0 ? ILibTransport_DoneState_INCOMPLETE : ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(ILibTransport_DoneState_ERROR);
|
||||
}
|
||||
}
|
||||
ILibTransport_DoneState ILibDuktape_TlsStream_Clear_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
|
||||
{
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
|
||||
|
||||
SSL_write(data->ssl, buffer, bufferLen);
|
||||
return(ILibDuktape_TlsStream_ProcessEncryptedBuffer(data));
|
||||
}
|
||||
void ILibDuktape_TlsStream_Clear_EndSink(ILibDuktape_DuplexStream *stream, void *user)
|
||||
{
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
|
||||
if (ILibIsRunningOnChainThread(data->chain) != 0 && data->encrypted->writableStream->pipedReadable != NULL)
|
||||
{
|
||||
duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [stream]
|
||||
duk_get_prop_string(data->ctx, -1, "end"); // [stream][end]
|
||||
duk_swap_top(data->ctx, -2); // [end][this]
|
||||
if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.unencrypted.end(): Error dispatching 'end' upstream "); }
|
||||
duk_pop(data->ctx); // ...
|
||||
}
|
||||
}
|
||||
void ILibDuktape_TlsStream_Clear_PauseSink_Chain(void *chain, void *user)
|
||||
{
|
||||
if (chain != NULL && !ILibDuktape_IsPointerValid(chain, user)) { return; }
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
|
||||
|
||||
duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [readable]
|
||||
duk_get_prop_string(data->ctx, -1, "pause"); // [readable][pause]
|
||||
duk_swap_top(data->ctx, -2); // [pause][this]
|
||||
if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.Decrypted.pause(): Error pausing upstream object "); };
|
||||
duk_pop(data->ctx); // ...
|
||||
}
|
||||
void ILibDuktape_TlsStream_Clear_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
|
||||
{
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
|
||||
if (data->encrypted->writableStream->pipedReadable_native != NULL && data->encrypted->writableStream->pipedReadable_native->PauseHandler != NULL)
|
||||
{
|
||||
data->encrypted->writableStream->pipedReadable_native->paused = 1;
|
||||
data->encrypted->writableStream->pipedReadable_native->PauseHandler(data->encrypted->writableStream->pipedReadable_native, data->encrypted->writableStream->pipedReadable_native->user);
|
||||
}
|
||||
else if (data->encrypted->writableStream->pipedReadable != NULL)
|
||||
{
|
||||
if (ILibIsRunningOnChainThread(data->chain) != 0)
|
||||
{
|
||||
ILibDuktape_TlsStream_Clear_PauseSink_Chain(NULL, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're on the wrong thread to resume the upstream object
|
||||
ILibChain_RunOnMicrostackThreadEx(data->chain, ILibDuktape_TlsStream_Clear_PauseSink_Chain, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ILibDuktape_TlsStream_Clear_ResumeSink_Chain(void *chain, void *user)
|
||||
{
|
||||
if (chain != NULL && !ILibDuktape_IsPointerValid(chain, user)) { return; }
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
|
||||
|
||||
duk_push_heapptr(data->ctx, data->encrypted->writableStream->pipedReadable); // [readable]
|
||||
duk_get_prop_string(data->ctx, -1, "resume"); // [readable][resume]
|
||||
duk_swap_top(data->ctx, -2); // [resume][this]
|
||||
if (duk_pcall_method(data->ctx, 0) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.Decrypted.resume(): Error resuming upstream object "); };
|
||||
duk_pop(data->ctx); // ...
|
||||
}
|
||||
void ILibDuktape_TlsStream_Clear_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
|
||||
{
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
|
||||
if (data->encrypted->writableStream->pipedReadable_native != NULL && data->encrypted->writableStream->pipedReadable_native->ResumeHandler != NULL)
|
||||
{
|
||||
data->encrypted->writableStream->pipedReadable_native->paused = 0;
|
||||
data->encrypted->writableStream->pipedReadable_native->ResumeHandler(data->encrypted->writableStream->pipedReadable_native, data->encrypted->writableStream->pipedReadable_native->user);
|
||||
}
|
||||
else if (data->encrypted->writableStream->pipedReadable != NULL)
|
||||
{
|
||||
if (ILibIsRunningOnChainThread(data->chain) != 0)
|
||||
{
|
||||
ILibDuktape_TlsStream_Clear_ResumeSink_Chain(NULL, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're on the wrong thread to resume the upstream object
|
||||
ILibChain_RunOnMicrostackThreadEx(data->chain, ILibDuktape_TlsStream_Clear_ResumeSink_Chain, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
int ILibDuktape_TlsStream_Clear_UnshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
|
||||
{
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
|
||||
|
||||
if (unshiftBytes == data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer)
|
||||
{
|
||||
data->decryptedBuffer_unshiftedBytes = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
data->decryptedBuffer_beginPointer = data->decryptedBuffer_endPointer - unshiftBytes;
|
||||
data->decryptedBuffer_unshiftedBytes = unshiftBytes;
|
||||
}
|
||||
return(unshiftBytes);
|
||||
}
|
||||
|
||||
ILibTransport_DoneState ILibDuktape_TlsStream_Encrypted_WriteSink(ILibDuktape_DuplexStream *stream, char *buffer, int bufferLen, void *user)
|
||||
{
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
|
||||
int j;
|
||||
|
||||
//int len = BIO_write(data->writeBio, buffer, bufferLen);
|
||||
BIO_write(SSL_get_rbio(data->ssl), buffer, bufferLen);
|
||||
int sslerror;
|
||||
|
||||
if (data->TLSHandshakeCompleted == 0)
|
||||
{
|
||||
switch ((sslerror = SSL_do_handshake(data->ssl)))
|
||||
{
|
||||
case 0:
|
||||
// Handshake Failed!
|
||||
while ((sslerror = ERR_get_error()) != 0)
|
||||
{
|
||||
ERR_error_string_n(sslerror, ILibScratchPad, sizeof(ILibScratchPad));
|
||||
}
|
||||
// TODO: We should probably do something
|
||||
break;
|
||||
case 1:
|
||||
data->TLSHandshakeCompleted = 1;
|
||||
if (ILibIsRunningOnChainThread(data->chain) != 0)
|
||||
{
|
||||
// We're on the Duktape Thread
|
||||
duk_push_heapptr(data->ctx, data->tlsObject); // [TLS]
|
||||
duk_get_prop_string(data->ctx, -1, "emit"); // [TLS][emit]
|
||||
duk_swap_top(data->ctx, -2); // [emit][this]
|
||||
duk_push_string(data->ctx, "connect"); // [emit][this][connect]
|
||||
if (duk_pcall_method(data->ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.connect(): "); }
|
||||
duk_pop(data->ctx); // ...
|
||||
}
|
||||
else
|
||||
{
|
||||
// Need to context switch to the Duktape Thread
|
||||
}
|
||||
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
|
||||
break;
|
||||
default:
|
||||
// SSL_WANT_READ most likely
|
||||
sslerror = SSL_get_error(data->ssl, sslerror);
|
||||
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
|
||||
break;
|
||||
}
|
||||
return(ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((j = SSL_read(data->ssl, data->decryptedBuffer + data->decryptedBuffer_endPointer, data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer)) > 0)
|
||||
{
|
||||
// We got new TLS Data
|
||||
if (j > 0)
|
||||
{
|
||||
data->decryptedBuffer_endPointer += j;
|
||||
if (data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer == 0)
|
||||
{
|
||||
data->decryptedBuffer_mallocSize = (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE < data->decryptedBuffer_maxSize) ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : (data->decryptedBuffer_maxSize == 0 ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : data->decryptedBuffer_maxSize);
|
||||
if((data->decryptedBuffer = (char*)realloc(data->decryptedBuffer, data->decryptedBuffer_mallocSize)) == NULL) ILIBCRITICALEXIT(254);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j < 0)
|
||||
{
|
||||
sslerror = SSL_get_error(data->ssl, j);
|
||||
if (data->writeBioBuffer->length > 0)
|
||||
{
|
||||
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Event data up the stack, to process any data that is available
|
||||
//
|
||||
do
|
||||
{
|
||||
data->decryptedBuffer_unshiftedBytes = 0;
|
||||
ILibDuktape_DuplexStream_WriteData(data->clear, data->decryptedBuffer + data->decryptedBuffer_beginPointer, data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer);
|
||||
} while (data->decryptedBuffer_unshiftedBytes > 0);
|
||||
if (data->decryptedBuffer_unshiftedBytes == 0) { data->decryptedBuffer_beginPointer = data->decryptedBuffer_endPointer = 0; }
|
||||
|
||||
|
||||
//
|
||||
// Check to see if we need to move any data, to maximize buffer space
|
||||
//
|
||||
if (data->decryptedBuffer_beginPointer != 0)
|
||||
{
|
||||
//
|
||||
// We can save some cycles by moving the data back to the top
|
||||
// of the buffer, instead of just allocating more memory.
|
||||
//
|
||||
char *temp = data->decryptedBuffer + data->decryptedBuffer_beginPointer;
|
||||
|
||||
memmove_s(data->decryptedBuffer, data->decryptedBuffer_mallocSize, temp, data->decryptedBuffer_endPointer - data->decryptedBuffer_beginPointer);
|
||||
data->decryptedBuffer_endPointer -= data->decryptedBuffer_beginPointer;
|
||||
data->decryptedBuffer_beginPointer = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Check to see if we should grow the buffer
|
||||
//
|
||||
if (data->decryptedBuffer_mallocSize - data->decryptedBuffer_endPointer < 1024 && (data->decryptedBuffer_maxSize == 0 || data->decryptedBuffer_mallocSize < data->decryptedBuffer_maxSize))
|
||||
{
|
||||
data->decryptedBuffer_mallocSize = (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE < data->decryptedBuffer_maxSize) ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : (data->decryptedBuffer_maxSize == 0 ? (data->decryptedBuffer_mallocSize + MEMORYCHUNKSIZE) : data->decryptedBuffer_maxSize);
|
||||
if ((data->decryptedBuffer = (char*)realloc(data->decryptedBuffer, data->decryptedBuffer_mallocSize)) == NULL) ILIBCRITICALEXIT(254);
|
||||
}
|
||||
|
||||
return(data->clear->readableStream->paused == 0 ? ILibTransport_DoneState_COMPLETE : ILibTransport_DoneState_INCOMPLETE);
|
||||
}
|
||||
void ILibDuktape_TlsStream_Encrypted_EndSink(ILibDuktape_DuplexStream *stream, void *user)
|
||||
{
|
||||
}
|
||||
void ILibDuktape_TlsStream_Encrypted_PauseSink(ILibDuktape_DuplexStream *sender, void *user)
|
||||
{
|
||||
// Don't need to do anythign, becuase the 'ILibDuktape_TlsStream_ProcessEncryptedBuffer' will exit the processing loop when paused
|
||||
}
|
||||
void ILibDuktape_TlsStream_Encrypted_ResumeSink(ILibDuktape_DuplexStream *sender, void *user)
|
||||
{
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
|
||||
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
|
||||
}
|
||||
int ILibDuktape_TlsStream_Encrypted_UnshiftSink(ILibDuktape_DuplexStream *sender, int unshiftBytes, void *user)
|
||||
{
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)user;
|
||||
|
||||
if (unshiftBytes == data->writeBioBuffer->length)
|
||||
{
|
||||
data->encrypted_unshiftBytes = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
data->writeBioBuffer->data += ((int)data->writeBioBuffer->length - unshiftBytes);
|
||||
data->writeBioBuffer->length = unshiftBytes;
|
||||
}
|
||||
return(unshiftBytes);
|
||||
}
|
||||
int ILibDuktape_TlsStream_verify(int preverify_ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
STACK_OF(X509) *certChain = X509_STORE_CTX_get_chain(ctx);
|
||||
SSL *ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)SSL_get_ex_data(ssl, ILibDuktape_TlsStream_ctx2stream);
|
||||
|
||||
int i;
|
||||
int retVal = 0;
|
||||
|
||||
if (data->rejectUnauthorized != 0) { return(preverify_ok); }
|
||||
if (data->OnVerify == NULL) { return 1; }
|
||||
|
||||
duk_push_heapptr(data->ctx, data->OnVerify); // [func]
|
||||
duk_push_heapptr(data->ctx, data->emitter->object); // [func][this]
|
||||
duk_push_array(data->ctx); // [func][this][certs]
|
||||
for (i = 0; i < sk_X509_num(certChain); ++i)
|
||||
{
|
||||
ILibDuktape_TlsStream_X509_PUSH(data->ctx, sk_X509_value(certChain, i)); // [func][this][certs][cert]
|
||||
duk_put_prop_index(data->ctx, -2, i); // [func][this][certs]
|
||||
}
|
||||
retVal = duk_pcall_method(data->ctx, 1) == 0 ? 1 : 0; // [undefined]
|
||||
duk_pop(data->ctx); // ...
|
||||
return retVal;
|
||||
}
|
||||
duk_ret_t ILibDuktape_TlsStream_Finalizer(duk_context *ctx)
|
||||
{
|
||||
void *chain = Duktape_GetChain(ctx);
|
||||
duk_get_prop_string(ctx, 0, ILibDuktape_TlsStream_Ptr);
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
struct util_cert *cert = NULL;
|
||||
|
||||
if (data->ssl != NULL) { SSL_free(data->ssl); }
|
||||
if (data->ssl_ctx != NULL) { SSL_CTX_free(data->ssl_ctx); }
|
||||
if (data->decryptedBuffer != NULL) { free(data->decryptedBuffer); }
|
||||
|
||||
if (duk_has_prop_string(ctx, 0, ILibDuktape_TlsStream2Cert))
|
||||
{
|
||||
duk_get_prop_string(ctx, 0, ILibDuktape_TlsStream2Cert);
|
||||
cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
util_freecert(cert);
|
||||
}
|
||||
ILibDuktape_InValidatePointer(chain, data);
|
||||
return(0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_TlsStream_serverSNI_cb(duk_context *ctx)
|
||||
{
|
||||
duk_push_current_function(ctx);
|
||||
duk_get_prop_string(ctx, -1, "\xFF_ptr");
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)duk_get_pointer(ctx, -1);
|
||||
|
||||
if (duk_has_prop_string(ctx, 1, "pfx") && duk_has_prop_string(ctx, 1, "passphrase"))
|
||||
{
|
||||
char *passphrase = Duktape_GetStringPropertyValue(ctx, 1, "passphrase", "");
|
||||
char *pfx;
|
||||
duk_size_t pfxLen;
|
||||
duk_get_prop_string(ctx, 1, "pfx");
|
||||
pfx = (char*)Duktape_GetBuffer(ctx, -1, &pfxLen);
|
||||
duk_push_heapptr(ctx, data->tlsObject); // [TLS]
|
||||
duk_push_fixed_buffer(ctx, sizeof(struct util_cert)); // [TLS][cert]
|
||||
struct util_cert *cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
|
||||
if (util_from_p12(pfx, (int)pfxLen, passphrase, cert) == 0) { return(ILibDuktape_Error(ctx, "Error Reading Certificate")); }
|
||||
SSL_CTX *newCTX = SSL_CTX_new(SSLv23_server_method());
|
||||
SSL_CTX_set_options(newCTX, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
|
||||
SSL_CTX_set_verify(newCTX, SSL_VERIFY_CLIENT_ONCE, ILibDuktape_TlsStream_verify); /* Ask for authentication */
|
||||
SSL_CTX_use_certificate(newCTX, cert->x509);
|
||||
SSL_CTX_use_PrivateKey(newCTX, cert->pkey);
|
||||
|
||||
SSL_set_SSL_CTX(data->ssl, newCTX);
|
||||
|
||||
duk_get_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS][cert][oldCert]
|
||||
util_freecert((struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL));
|
||||
duk_pop(ctx); // [TLS][cert]
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS]
|
||||
SSL_CTX_free(data->ssl_ctx);
|
||||
data->ssl_ctx = newCTX;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
static int ILibDuktape_TlsStream_serverSNI_callback(SSL *s, int *ad, void *arg)
|
||||
{
|
||||
const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
|
||||
ILibDuktape_TlsStream_Data *data = (ILibDuktape_TlsStream_Data*)SSL_get_ex_data(s, ILibDuktape_TlsStream_ctx2stream);
|
||||
int retVal = SSL_TLSEXT_ERR_OK;
|
||||
|
||||
duk_push_heapptr(data->ctx, data->OnServerSNI); // [func]
|
||||
duk_push_heapptr(data->ctx, data->tlsObject); // [func][this]
|
||||
duk_push_string(data->ctx, servername); // [func][this][servername]
|
||||
duk_push_c_function(data->ctx, ILibDuktape_TlsStream_serverSNI_cb, 2); // [func][this][servername][cb]
|
||||
duk_push_pointer(data->ctx, data); // [func][this][servername][cb][ptr]
|
||||
duk_put_prop_string(data->ctx, -2, "\xFF_ptr"); // [func][this][servername][cb]
|
||||
if (duk_pcall_method(data->ctx, 2) != 0)
|
||||
{
|
||||
ILibDuktape_Process_UncaughtExceptionEx(data->ctx, "TlsStream.serverSNI(): Error dispatching callback ");
|
||||
retVal = SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
duk_pop(data->ctx); // ...
|
||||
|
||||
return(retVal);
|
||||
}
|
||||
duk_ret_t ILibDuktape_TlsStream_create(duk_context *ctx)
|
||||
{
|
||||
int nargs = duk_get_top(ctx);
|
||||
char *sniHost = NULL;
|
||||
void *chain = Duktape_GetChain(ctx);
|
||||
int status, requestCert;
|
||||
duk_push_current_function(ctx);
|
||||
int isClient = Duktape_GetIntPropertyValue(ctx, -1, "isClient", 0);
|
||||
ILibDuktape_TlsStream_Data *data;
|
||||
duk_push_object(ctx); // [TLS]
|
||||
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_TlsStream_Finalizer);
|
||||
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_TlsStream_Data)); // [TLS][struct]
|
||||
data = (ILibDuktape_TlsStream_Data*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream_Ptr); // [TLS]
|
||||
memset(data, 0, sizeof(ILibDuktape_TlsStream_Data));
|
||||
ILibDuktape_ValidatePointer(chain, data);
|
||||
data->emitter = ILibDuktape_EventEmitter_Create(ctx);
|
||||
ILibDuktape_EventEmitter_CreateEventEx(data->emitter, "connect");
|
||||
data->tlsObject = duk_get_heapptr(ctx, -1);
|
||||
data->decryptedBuffer_mallocSize = MEMORYCHUNKSIZE;
|
||||
data->decryptedBuffer = (char*)ILibMemory_Allocate(data->decryptedBuffer_mallocSize, 0, NULL, NULL);
|
||||
|
||||
data->rejectUnauthorized = Duktape_GetIntPropertyValue(ctx, 0, "rejectUnauthorized", 1);
|
||||
requestCert = Duktape_GetIntPropertyValue(ctx, 0, "requestCert", 0);
|
||||
data->OnVerify = Duktape_GetHeapptrProperty(ctx, 0, isClient != 0 ? "checkServerIdentity" : "checkClientIdentity");
|
||||
|
||||
duk_push_object(ctx); // [TLS][clear]
|
||||
ILibDuktape_WriteID(ctx, "TlsStream.decrypted");
|
||||
data->clear = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_TlsStream_Clear_WriteSink, ILibDuktape_TlsStream_Clear_EndSink,
|
||||
ILibDuktape_TlsStream_Clear_PauseSink, ILibDuktape_TlsStream_Clear_ResumeSink, ILibDuktape_TlsStream_Clear_UnshiftSink, data);
|
||||
ILibDuktape_CreateReadonlyProperty(ctx, "clear"); // [TLS]
|
||||
|
||||
duk_push_object(ctx); // [TLS][encrypted]
|
||||
ILibDuktape_WriteID(ctx, "TlsStream.encrypted");
|
||||
data->encrypted = ILibDuktape_DuplexStream_InitEx(ctx, ILibDuktape_TlsStream_Encrypted_WriteSink, ILibDuktape_TlsStream_Encrypted_EndSink,
|
||||
ILibDuktape_TlsStream_Encrypted_PauseSink, ILibDuktape_TlsStream_Encrypted_ResumeSink, ILibDuktape_TlsStream_Encrypted_UnshiftSink, data);
|
||||
ILibDuktape_CreateReadonlyProperty(ctx, "encrypted"); // [TLS]
|
||||
|
||||
|
||||
data->ctx = ctx;
|
||||
data->chain = Duktape_GetChain(ctx);
|
||||
data->ssl_ctx = isClient != 0 ? SSL_CTX_new(SSLv23_client_method()) : SSL_CTX_new(SSLv23_server_method());
|
||||
SSL_CTX_set_options(data->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
|
||||
if (isClient != 0 || requestCert != 0) { SSL_CTX_set_verify(data->ssl_ctx, isClient != 0 ? SSL_VERIFY_PEER : SSL_VERIFY_CLIENT_ONCE, ILibDuktape_TlsStream_verify); /* Ask for authentication */ }
|
||||
|
||||
if (nargs > 0 && duk_is_object(ctx, 0))
|
||||
{
|
||||
sniHost = Duktape_GetStringPropertyValue(ctx, 0, "host", NULL);
|
||||
data->OnServerSNI = Duktape_GetHeapptrProperty(ctx, 0, "SNICallback");
|
||||
if (duk_has_prop_string(ctx, 0, "pfx") && duk_has_prop_string(ctx, 0, "passphrase"))
|
||||
{
|
||||
// PFX certificate was passed in thru Options
|
||||
char *pfx, *passphrase;
|
||||
duk_size_t pfxLen, passphraseLen;
|
||||
duk_push_fixed_buffer(ctx, sizeof(struct util_cert)); // [TLS][buff]
|
||||
struct util_cert *cert = (struct util_cert*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
duk_put_prop_string(ctx, -2, ILibDuktape_TlsStream2Cert); // [TLS]
|
||||
|
||||
duk_get_prop_string(ctx, 0, "pfx"); // [pfx]
|
||||
duk_get_prop_string(ctx, 0, "passphrase"); // [pfx][passphrase]
|
||||
pfx = (char*)Duktape_GetBuffer(ctx, -2, &pfxLen);
|
||||
passphrase = (char*)Duktape_GetBuffer(ctx, -1, &passphraseLen);
|
||||
|
||||
if (util_from_p12(pfx, (int)pfxLen, passphrase, cert) == 0) { return(ILibDuktape_Error(ctx, "Error Reading Certificate")); }
|
||||
SSL_CTX_use_certificate(data->ssl_ctx, cert->x509);
|
||||
SSL_CTX_use_PrivateKey(data->ssl_ctx, cert->pkey);
|
||||
duk_pop_2(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
data->ssl = SSL_new(data->ssl_ctx);
|
||||
data->TLSHandshakeCompleted = 0;
|
||||
data->readBio = BIO_new(BIO_s_mem());
|
||||
data->writeBio = BIO_new(BIO_s_mem());
|
||||
BIO_get_mem_ptr(data->readBio, &(data->readBioBuffer));
|
||||
BIO_get_mem_ptr(data->writeBio, &(data->writeBioBuffer));
|
||||
BIO_set_mem_eof_return(data->readBio, -1);
|
||||
BIO_set_mem_eof_return(data->writeBio, -1);
|
||||
data->readBioBuffer->length = 0;
|
||||
SSL_set_bio(data->ssl, data->readBio, data->writeBio);
|
||||
|
||||
if (ILibDuktape_TlsStream_ctx2stream < 0)
|
||||
{
|
||||
ILibDuktape_TlsStream_ctx2stream = SSL_get_ex_new_index(0, "ILibDuktape_TlsStream index", NULL, NULL, NULL);
|
||||
}
|
||||
SSL_set_ex_data(data->ssl, ILibDuktape_TlsStream_ctx2stream, data);
|
||||
|
||||
if (isClient != 0)
|
||||
{
|
||||
if (sniHost != NULL) { SSL_set_tlsext_host_name(data->ssl, sniHost); }
|
||||
SSL_set_connect_state(data->ssl);
|
||||
status = SSL_do_handshake(data->ssl);
|
||||
if (status <= 0) { status = SSL_get_error(data->ssl, status); }
|
||||
if (status == SSL_ERROR_WANT_READ)
|
||||
{
|
||||
ILibDuktape_TlsStream_ProcessEncryptedBuffer(data);
|
||||
// We're going to drop out now, becuase we need to check for received data
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data->OnServerSNI != NULL)
|
||||
{
|
||||
SSL_CTX_set_tlsext_servername_callback(data->ssl_ctx, ILibDuktape_TlsStream_serverSNI_callback);
|
||||
}
|
||||
SSL_set_accept_state(data->ssl); // Setup server SSL state
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
void ILibDuktape_TlsStream_PUSH(duk_context *ctx, void *chain)
|
||||
{
|
||||
duk_push_object(ctx);
|
||||
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "isClient", 1, "createClient", ILibDuktape_TlsStream_create, DUK_VARARGS);
|
||||
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "isClient", 0, "createServer", ILibDuktape_TlsStream_create, DUK_VARARGS);
|
||||
}
|
||||
void ILibDuktape_TlsStream_Init(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_ModSearch_AddHandler(ctx, "TlsStream", ILibDuktape_TlsStream_PUSH);
|
||||
}
|
||||
|
||||
@@ -235,6 +235,7 @@ duk_ret_t ILibDuktape_WritableStream_End(duk_context *ctx)
|
||||
duk_dup(ctx, 2); // [stream][flush]
|
||||
duk_put_prop_string(ctx, -2, "_Finish"); // [stream]
|
||||
}
|
||||
stream->endBytes = (int)bufferLen;
|
||||
if (stream->WriteSink(stream, buffer, (int)bufferLen, stream->WriteSink_User) == ILibTransport_DoneState_INCOMPLETE)
|
||||
{
|
||||
// Incomplete, wait for SendOK
|
||||
@@ -265,11 +266,40 @@ duk_ret_t ILibDuktape_WritableStream_End_Getter(duk_context *ctx)
|
||||
duk_push_c_function(ctx, ILibDuktape_WritableStream_End, DUK_VARARGS);
|
||||
return 1;
|
||||
}
|
||||
duk_ret_t ILibDuktape_WritableStream_UnPipeSink(duk_context *ctx)
|
||||
{
|
||||
duk_dup(ctx, 0);
|
||||
duk_push_this(ctx);
|
||||
//printf("UNPIPE: [%s] => X => [%s]\n", Duktape_GetStringPropertyValue(ctx, -2, ILibDuktape_OBJID, "unknown"), Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "unknown"));
|
||||
return(0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_WritableStream_PipeSink(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_WritableStream *ws;
|
||||
duk_push_this(ctx); // [writable]
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_WritableStream_WSPTRS);
|
||||
ws = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
|
||||
if (duk_has_prop_string(ctx, 0, "\xFF_ReadableStream_PTRS"))
|
||||
{
|
||||
duk_get_prop_string(ctx, 0, "\xFF_ReadableStream_PTRS"); // [writable][rs]
|
||||
ws->pipedReadable_native = (struct ILibDuktape_readableStream*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
}
|
||||
ws->pipedReadable = duk_get_heapptr(ctx, 0);
|
||||
|
||||
duk_dup(ctx, 0);
|
||||
duk_push_this(ctx);
|
||||
//printf("PIPE: [%s] => [%s]\n", Duktape_GetStringPropertyValue(ctx, -2, ILibDuktape_OBJID, "unknown"), Duktape_GetStringPropertyValue(ctx, -1, ILibDuktape_OBJID, "unknown"));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, ILibDuktape_WritableStream_WriteHandler WriteHandler, ILibDuktape_WritableStream_EndHandler EndHandler, void *user)
|
||||
{
|
||||
ILibDuktape_WritableStream *retVal;
|
||||
ILibDuktape_EventEmitter *emitter;
|
||||
|
||||
ILibDuktape_PointerValidation_Init(ctx);
|
||||
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_WritableStream)); // [obj][buffer]
|
||||
retVal = (ILibDuktape_WritableStream*)Duktape_GetBuffer(ctx, -1, NULL); // [obj][buffer]
|
||||
memset(retVal, 0, sizeof(ILibDuktape_WritableStream));
|
||||
@@ -283,7 +313,8 @@ ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, IL
|
||||
retVal->WriteSink_User = user;
|
||||
|
||||
emitter = ILibDuktape_EventEmitter_Create(ctx);
|
||||
ILibDuktape_EventEmitter_CreateEvent(emitter, "pipe", &(retVal->OnPipe));
|
||||
ILibDuktape_EventEmitter_CreateEventEx(emitter, "pipe");
|
||||
ILibDuktape_EventEmitter_CreateEventEx(emitter, "unpipe");
|
||||
ILibDuktape_EventEmitter_CreateEvent(emitter, "drain", &(retVal->OnDrain));
|
||||
ILibDuktape_EventEmitter_CreateEvent(emitter, "finish", &(retVal->OnFinish));
|
||||
ILibDuktape_EventEmitter_CreateEvent(emitter, "error", &(retVal->OnError));
|
||||
@@ -291,5 +322,7 @@ ILibDuktape_WritableStream* ILibDuktape_WritableStream_Init(duk_context *ctx, IL
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "write", ILibDuktape_WritableStream_Write, DUK_VARARGS);
|
||||
ILibDuktape_CreateEventWithGetter(ctx, "end", ILibDuktape_WritableStream_End_Getter);
|
||||
|
||||
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "pipe", ILibDuktape_WritableStream_PipeSink);
|
||||
ILibDuktape_EventEmitter_AddOnEx(ctx, -1, "unpipe", ILibDuktape_WritableStream_UnPipeSink);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@@ -23,16 +23,19 @@ limitations under the License.
|
||||
struct ILibDuktape_WritableStream;
|
||||
typedef ILibTransport_DoneState(*ILibDuktape_WritableStream_WriteHandler)(struct ILibDuktape_WritableStream *stream, char *buffer, int bufferLen, void *user);
|
||||
typedef void(*ILibDuktape_WritableStream_EndHandler)(struct ILibDuktape_WritableStream *stream, void *user);
|
||||
typedef void(*ILibDuktape_WriteableStream_WriteFlushNative)(struct ILibDuktape_WritableStream *stream, void *user);
|
||||
typedef int(*ILibDuktape_WriteableStream_WriteFlushNative)(struct ILibDuktape_WritableStream *stream, void *user);
|
||||
typedef void(*ILibDuktape_WritableStream_PipeHandler)(struct ILibDuktape_WritableStream *stream, void *readableSource, void *user);
|
||||
|
||||
struct ILibDuktape_readableStream;
|
||||
|
||||
typedef struct ILibDuktape_WritableStream
|
||||
{
|
||||
int JSCreated;
|
||||
duk_context *ctx;
|
||||
void *obj;
|
||||
void *OnDrain;
|
||||
void *OnWriteFlush;
|
||||
void *OnPipe;
|
||||
|
||||
ILibDuktape_WriteableStream_WriteFlushNative OnWriteFlushEx;
|
||||
void *OnWriteFlushEx_User;
|
||||
|
||||
@@ -42,8 +45,12 @@ typedef struct ILibDuktape_WritableStream
|
||||
|
||||
ILibDuktape_WritableStream_WriteHandler WriteSink;
|
||||
ILibDuktape_WritableStream_EndHandler EndSink;
|
||||
ILibDuktape_WritableStream_PipeHandler PipeSink;
|
||||
|
||||
void *pipedReadable;
|
||||
struct ILibDuktape_readableStream* pipedReadable_native;
|
||||
|
||||
void *WriteSink_User;
|
||||
int endBytes;
|
||||
int Reserved;
|
||||
} ILibDuktape_WritableStream;
|
||||
|
||||
|
||||
@@ -1229,6 +1229,7 @@ duk_ret_t ILibDuktape_fs_readFileSync(duk_context *ctx)
|
||||
duk_push_fixed_buffer(ctx, (duk_size_t)fileLen);
|
||||
ignore_result(fread(Duktape_GetBuffer(ctx, -1, NULL), 1, (size_t)fileLen, f));
|
||||
fclose(f);
|
||||
duk_push_buffer_object(ctx, -1, 0, (duk_size_t)fileLen, DUK_BUFOBJ_NODEJS_BUFFER);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@ limitations under the License.
|
||||
|
||||
#include "microstack/ILibParsers.h"
|
||||
|
||||
#define ILibDuktape_SOCKET2OPTIONS "\xFF_NET_SOCKET2OPTIONS"
|
||||
void ILibDuktape_net_init(duk_context *ctx, void *chain);
|
||||
|
||||
typedef struct ILibDuktape_globalTunnel_data
|
||||
|
||||
@@ -182,7 +182,7 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
|
||||
duk_pop_2(ctx); // [this]
|
||||
self = duk_get_heapptr(ctx, -1);
|
||||
|
||||
if (data->eventTable == NULL) { return 0; } // This probably means the finalizer was already run on the eventEmitter
|
||||
if (data->eventTable == NULL) { duk_push_false(ctx); return(1); } // This probably means the finalizer was already run on the eventEmitter
|
||||
|
||||
eventList = ILibHashtable_Get(data->eventTable, NULL, name, (int)nameLen);
|
||||
if (eventList == NULL) { return ILibDuktape_Error(ctx, "EventEmitter.emit(): Event '%s' not found", name); }
|
||||
@@ -245,8 +245,8 @@ duk_ret_t ILibDuktape_EventEmitter_emit(duk_context *ctx)
|
||||
}
|
||||
duk_pop(ctx); // ...
|
||||
}
|
||||
|
||||
return 0;
|
||||
duk_push_boolean(ctx, i > 1 ? 1 : 0);
|
||||
return(1);
|
||||
}
|
||||
int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr)
|
||||
{
|
||||
@@ -261,13 +261,13 @@ int ILibDuktape_EventEmitter_AddOnce(ILibDuktape_EventEmitter *emitter, char *ev
|
||||
|
||||
return retVal;
|
||||
}
|
||||
int ILibDuktape_EventEmitter_AddOnceEx2(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func, duk_idx_t funcArgs)
|
||||
int ILibDuktape_EventEmitter_AddOnceEx3(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func)
|
||||
{
|
||||
int retVal = 1;
|
||||
|
||||
duk_dup(ctx, idx); // [obj]
|
||||
ILibDuktape_Push_ObjectStash(ctx); // [obj][stash]
|
||||
duk_push_c_function(ctx, func, funcArgs); // [obj][stash][func]
|
||||
duk_push_c_function(ctx, func, DUK_VARARGS); // [obj][stash][func]
|
||||
duk_dup(ctx, -1); // [obj][stash][func][func]
|
||||
duk_put_prop_string(ctx, -3, Duktape_GetStashKey(duk_get_heapptr(ctx, -1))); // [obj][stash][func]
|
||||
duk_get_prop_string(ctx, -3, "once"); // [obj][stash][func][once]
|
||||
@@ -316,10 +316,12 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
|
||||
ILibDuktape_EventEmitter *data;
|
||||
int once;
|
||||
void *eventList, *node, *dispatcher, **hptr;
|
||||
int i, count;
|
||||
int i, count, prepend;
|
||||
|
||||
duk_push_current_function(ctx);
|
||||
once = Duktape_GetIntPropertyValue(ctx, -1, "once", 0);
|
||||
prepend = Duktape_GetIntPropertyValue(ctx, -1, "prepend", 0);
|
||||
|
||||
|
||||
duk_push_this(ctx);
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_EventEmitter_TempObject);
|
||||
@@ -334,7 +336,7 @@ duk_ret_t ILibDuktape_EventEmitter_on(duk_context *ctx)
|
||||
dispatcher = ILibHashtable_Get(data->eventTable, ILibDuktape_EventEmitter_SetterFunc, propName, (int)propNameLen);
|
||||
if (dispatcher == NULL) { return(ILibDuktape_Error(ctx, "EventEmitter.on(): Internal error with Event '%s'", propName)); }
|
||||
|
||||
node = ILibLinkedList_AddTail(eventList, callback);
|
||||
node = prepend ? ILibLinkedList_AddHead(eventList, callback) : ILibLinkedList_AddTail(eventList, callback);
|
||||
((int*)ILibLinkedList_GetExtendedMemory(node))[0] = once;
|
||||
data->totalListeners[0]++;
|
||||
|
||||
@@ -462,8 +464,11 @@ ILibDuktape_EventEmitter* ILibDuktape_EventEmitter_Create(duk_context *ctx)
|
||||
retVal->object = duk_get_heapptr(ctx, -1);
|
||||
retVal->eventTable = ILibHashtable_Create();
|
||||
|
||||
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "once", 1, "once", ILibDuktape_EventEmitter_on, 2);
|
||||
ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "once", 0, "on", ILibDuktape_EventEmitter_on, 2);
|
||||
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "once", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 1), "prepend", duk_push_int_ex(ctx, 0));
|
||||
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "on", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 0), "prepend", duk_push_int_ex(ctx, 0));
|
||||
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "prependOnceListener", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 1), "prepend", duk_push_int_ex(ctx, 1));
|
||||
ILibDuktape_CreateInstanceMethodWithProperties(ctx, "prependListener", ILibDuktape_EventEmitter_on, 2, 2, "once", duk_push_int_ex(ctx, 0), "prepend", duk_push_int_ex(ctx, 1));
|
||||
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "removeListener", ILibDuktape_EventEmitter_removeListener, 2);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "removeAllListeners", ILibDuktape_EventEmitter_removeAllListeners, DUK_VARARGS);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "emit", ILibDuktape_EventEmitter_emit, DUK_VARARGS);
|
||||
@@ -816,6 +821,15 @@ duk_ret_t ILibDuktape_EventEmitter_Inherits_addMethod(duk_context *ctx)
|
||||
ILibDuktape_CreateProperty_InstanceMethodEx(ctx, (char*)duk_require_string(ctx, 0), duk_require_heapptr(ctx, 1));
|
||||
return(0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_EventEmitter_EmitterUtils_Finalizer(duk_context *ctx)
|
||||
{
|
||||
duk_get_prop_string(ctx, 0, "\xFF_MainObject"); // [obj]
|
||||
duk_get_prop_string(ctx, -1, "emit"); // [obj][emit]
|
||||
duk_swap_top(ctx, -2); // [emit][this]
|
||||
duk_push_string(ctx, "~"); // [emit][this][~]
|
||||
duk_call_method(ctx, 1);
|
||||
return(0);
|
||||
}
|
||||
duk_ret_t ILibDuktape_EventEmitter_Inherits(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_EventEmitter *emitter;
|
||||
@@ -823,12 +837,16 @@ duk_ret_t ILibDuktape_EventEmitter_Inherits(duk_context *ctx)
|
||||
duk_dup(ctx, 0); // [target]
|
||||
emitter = ILibDuktape_EventEmitter_Create(ctx);
|
||||
duk_push_object(ctx); // [target][emitterUtils]
|
||||
duk_dup(ctx, -2); // [target][emitterUtils][target]
|
||||
duk_put_prop_string(ctx, -2, "\xFF_MainObject"); // [target][emitterUtils]
|
||||
duk_dup(ctx, -1); // [target][emitterUtils][dup]
|
||||
duk_put_prop_string(ctx, -3, "\xFF_emitterUtils"); // [target][emitterUtils]
|
||||
duk_push_pointer(ctx, emitter); // [target][emitterUtils][ptr]
|
||||
duk_put_prop_string(ctx, -2, "emitter"); // [target][emitterUtils]
|
||||
ILibDuktape_CreateFinalizer(ctx, ILibDuktape_EventEmitter_EmitterUtils_Finalizer);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "createEvent", ILibDuktape_EventEmitter_Inherits_createEvent, 1);
|
||||
ILibDuktape_CreateInstanceMethod(ctx, "addMethod", ILibDuktape_EventEmitter_Inherits_addMethod, 2);
|
||||
ILibDuktape_EventEmitter_CreateEventEx(emitter, "~");
|
||||
return 1;
|
||||
}
|
||||
void ILibDuktape_EventEmitter_PUSH(duk_context *ctx, void *chain)
|
||||
@@ -840,3 +858,54 @@ void ILibDuktape_EventEmitter_Init(duk_context *ctx)
|
||||
{
|
||||
ILibDuktape_ModSearch_AddHandler(ctx, "events", ILibDuktape_EventEmitter_PUSH);
|
||||
}
|
||||
duk_ret_t ILibDuktape_EventEmitter_ForwardEvent_Sink(duk_context *ctx)
|
||||
{
|
||||
int nargs = duk_get_top(ctx);
|
||||
int i;
|
||||
char *name;
|
||||
duk_push_current_function(ctx); // [func]
|
||||
duk_get_prop_string(ctx, -1, "targetObject"); // [func][obj]
|
||||
duk_get_prop_string(ctx, -1, "emit"); // [func][obj][emit]
|
||||
duk_swap_top(ctx, -2); // [func][emit][this]
|
||||
duk_get_prop_string(ctx, -3, "targetName"); // [func][emit][this][name]
|
||||
name = (char*)duk_get_string(ctx, -1);
|
||||
|
||||
for (i = 0; i < nargs; ++i)
|
||||
{
|
||||
duk_dup(ctx, i); // [func][emit][this][name][...args...]
|
||||
}
|
||||
|
||||
if (duk_pcall_method(ctx, 1 + nargs) != 0) { return(ILibDuktape_Error(ctx, "EventEmitter.ForwardEvent() [%s]: %s", name, duk_safe_to_string(ctx, -1))); }
|
||||
return(0);
|
||||
}
|
||||
void ILibDuktape_EventEmitter_ForwardEvent(duk_context *ctx, duk_idx_t eventSourceIndex, char *sourceEventName, duk_idx_t eventTargetIndex, char *targetEventName)
|
||||
{
|
||||
void *target;
|
||||
duk_dup(ctx, eventTargetIndex); // [targetObject]
|
||||
target = duk_get_heapptr(ctx, -1);
|
||||
duk_pop(ctx); // ...
|
||||
duk_dup(ctx, eventSourceIndex); // [sourceObject]
|
||||
duk_get_prop_string(ctx, -1, "on"); // [sourceObject][on]
|
||||
duk_swap_top(ctx, -2); // [on][this]
|
||||
duk_push_string(ctx, sourceEventName); // [on][this][name]
|
||||
duk_push_c_function(ctx, ILibDuktape_EventEmitter_ForwardEvent_Sink, DUK_VARARGS); // [on][this][name][sink]
|
||||
duk_push_heapptr(ctx, target); // [on][this][name][sink][targetObject]
|
||||
duk_put_prop_string(ctx, -2, "targetObject"); // [on][this][name][sink]
|
||||
duk_push_string(ctx, targetEventName); // [on][this][name][sink][targetName]
|
||||
duk_put_prop_string(ctx, -2, "targetName"); // [on][this][name][sink]
|
||||
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "EventEmitter_ForwardEvent(): "); }
|
||||
duk_pop(ctx); // ...
|
||||
}
|
||||
int ILibDuktape_EventEmitter_AddOnEx(duk_context *ctx, duk_idx_t idx, char *eventName, duk_c_function func)
|
||||
{
|
||||
int retVal = 1;
|
||||
duk_dup(ctx, idx); // [object]
|
||||
duk_get_prop_string(ctx, -1, "on"); // [object][on]
|
||||
duk_swap_top(ctx, -2); // [on][this]
|
||||
duk_push_string(ctx, eventName); // [on][this][name]
|
||||
duk_push_c_function(ctx, func, DUK_VARARGS); // [on][this][name][func]
|
||||
if (duk_pcall_method(ctx, 2) != 0) { retVal = 0; }
|
||||
|
||||
duk_pop(ctx); // ...
|
||||
return(retVal);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user